Aleksander Machniak
2013-12-31 f5d2eef55c89b7f1a5549704705c25fd7f0c0185
More CS fixes, replace global $CONFIG usage with $RCMAIL->config->get()
19 files modified
1791 ■■■■ changed files
program/include/rcmail.php 13 ●●●●● patch | view | raw | blame | history
program/steps/addressbook/copy.inc 5 ●●●●● patch | view | raw | blame | history
program/steps/addressbook/delete.inc 5 ●●●●● patch | view | raw | blame | history
program/steps/addressbook/edit.inc 35 ●●●● patch | view | raw | blame | history
program/steps/addressbook/export.inc 84 ●●●● patch | view | raw | blame | history
program/steps/addressbook/func.inc 49 ●●●● patch | view | raw | blame | history
program/steps/addressbook/import.inc 314 ●●●● patch | view | raw | blame | history
program/steps/addressbook/mailto.inc 17 ●●●●● patch | view | raw | blame | history
program/steps/addressbook/show.inc 20 ●●●● patch | view | raw | blame | history
program/steps/addressbook/undo.inc 8 ●●●● patch | view | raw | blame | history
program/steps/mail/compose.inc 31 ●●●●● patch | view | raw | blame | history
program/steps/mail/func.inc 394 ●●●●● patch | view | raw | blame | history
program/steps/mail/mark.inc 39 ●●●●● patch | view | raw | blame | history
program/steps/mail/pagenav.inc 10 ●●●● patch | view | raw | blame | history
program/steps/mail/search.inc 42 ●●●● patch | view | raw | blame | history
program/steps/mail/sendmail.inc 460 ●●●● patch | view | raw | blame | history
program/steps/mail/show.inc 171 ●●●●● patch | view | raw | blame | history
program/steps/mail/viewsource.inc 18 ●●●● patch | view | raw | blame | history
program/steps/settings/folders.inc 76 ●●●●● patch | view | raw | blame | history
program/include/rcmail.php
@@ -980,6 +980,19 @@
    /**
     * Set environment variables for specified config options
     */
    public function set_env_config($options)
    {
        foreach ((array) $options as $option) {
            if ($this->config->get($option)) {
                $this->output->set_env($option, true);
            }
        }
    }
    /**
     * Returns RFC2822 formatted current date in user's timezone
     *
     * @return string Date
program/steps/addressbook/copy.inc
@@ -5,7 +5,7 @@
 | program/steps/addressbook/copy.inc                                    |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2007, The Roundcube Dev Team                            |
 | 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.                |
@@ -32,8 +32,7 @@
$errormsg = 'copyerror';
$maxnum   = $RCMAIL->config->get('max_group_members', 0);
foreach ($cids as $source => $cid)
{
foreach ($cids as $source => $cid) {
    // Something wrong, target not specified
    if (!strlen($target)) {
        break;
program/steps/addressbook/delete.inc
@@ -5,7 +5,7 @@
 | program/steps/addressbook/delete.inc                                  |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2005-2009, The Roundcube Dev Team                       |
 | 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.                |
@@ -30,8 +30,7 @@
$undo_time = $RCMAIL->config->get('undo_timeout', 0);
$RCMAIL->session->remove('contact_undo');
foreach ($cids as $source => $cid)
{
foreach ($cids as $source => $cid) {
    $CONTACTS = rcmail_contact_source($source);
    if ($CONTACTS->readonly) {
program/steps/addressbook/edit.inc
@@ -59,6 +59,25 @@
$SOURCE_ID = $source;
rcmail_set_sourcename($CONTACTS);
$OUTPUT->add_handlers(array(
    'contactedithead' => 'rcmail_contact_edithead',
    'contacteditform' => 'rcmail_contact_editform',
    'contactphoto'    => 'rcmail_contact_photo',
    'photouploadform' => 'rcmail_upload_photo_form',
    'sourceselector'  => 'rcmail_source_selector',
    'filedroparea'    => 'rcmail_photo_drop_area',
));
if ($RCMAIL->action == 'add' && $OUTPUT->template_exists('contactadd')) {
    $OUTPUT->send('contactadd');
}
// this will be executed if no template for addcontact exists
$OUTPUT->send('contactedit');
function rcmail_get_edit_record()
{
    global $RCMAIL, $CONTACTS;
@@ -289,19 +308,3 @@
        $OUTPUT->set_env('filedrop', array('action' => 'upload-photo', 'fieldname' => '_photo', 'single' => 1, 'filter' => '^image/.+'));
    }
}
$OUTPUT->add_handlers(array(
    'contactedithead' => 'rcmail_contact_edithead',
    'contacteditform' => 'rcmail_contact_editform',
    'contactphoto'    => 'rcmail_contact_photo',
    'photouploadform' => 'rcmail_upload_photo_form',
    'sourceselector'  => 'rcmail_source_selector',
    'filedroparea'    => 'rcmail_photo_drop_area',
));
if ($RCMAIL->action == 'add' && $OUTPUT->template_exists('contactadd'))
    $OUTPUT->send('contactadd');
// this will be executed if no template for addcontact exists
$OUTPUT->send('contactedit');
program/steps/addressbook/export.inc
@@ -6,7 +6,7 @@
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2008-2013, The Roundcube Dev Team                       |
 | Copyright (C) 2011, Kolab Systems AG                                  |
 | Copyright (C) 2011-2013, Kolab Systems AG                             |
 |                                                                       |
 | Licensed under the GNU General Public License version 3 or            |
 | any later version with exceptions for skins & plugins.                |
@@ -21,49 +21,8 @@
 +-----------------------------------------------------------------------+
*/
/**
 * Copy contact record properties into a vcard object
 */
function prepare_for_export(&$record, $source = null)
{
    $groups = $source && $source->groups && $source->export_groups ? $source->get_record_groups($record['ID']) : null;
    if (empty($record['vcard'])) {
        $vcard = new rcube_vcard();
        if ($source) {
            $vcard->extend_fieldmap($source->vcard_map);
        }
        $vcard->load($record['vcard']);
        $vcard->reset();
        foreach ($record as $key => $values) {
            list($field, $section) = explode(':', $key);
            foreach ((array)$values as $value) {
                if (is_array($value) || @strlen($value)) {
                    $vcard->set($field, $value, strtoupper($section));
                }
            }
        }
        // append group names
        if ($groups) {
            $vcard->set('groups', join(',', $groups), null);
        }
        $record['vcard'] = $vcard->export(true);
    }
    // patch categories to alread existing vcard block
    else if ($record['vcard'] && !empty($groups) && !strpos($record['vcard'], 'CATEGORIES:')) {
        $vgroups = 'CATEGORIES:' . rcube_vcard::vcard_quote(join(',', $groups));
        $record['vcard'] = str_replace('END:VCARD', $vgroups . rcube_vcard::$eol . 'END:VCARD', $record['vcard']);
    }
}
// Use search result
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']]))
{
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']])) {
    $sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
    $search  = (array)$_SESSION['search'][$_REQUEST['_search']];
    $records = array();
@@ -153,3 +112,42 @@
}
exit;
/**
 * Copy contact record properties into a vcard object
 */
function prepare_for_export(&$record, $source = null)
{
    $groups = $source && $source->groups && $source->export_groups ? $source->get_record_groups($record['ID']) : null;
    if (empty($record['vcard'])) {
        $vcard = new rcube_vcard();
        if ($source) {
            $vcard->extend_fieldmap($source->vcard_map);
        }
        $vcard->load($record['vcard']);
        $vcard->reset();
        foreach ($record as $key => $values) {
            list($field, $section) = explode(':', $key);
            foreach ((array)$values as $value) {
                if (is_array($value) || @strlen($value)) {
                    $vcard->set($field, $value, strtoupper($section));
                }
            }
        }
        // append group names
        if ($groups) {
            $vcard->set('groups', join(',', $groups), null);
        }
        $record['vcard'] = $vcard->export(true);
    }
    // patch categories to alread existing vcard block
    else if ($record['vcard'] && !empty($groups) && !strpos($record['vcard'], 'CATEGORIES:')) {
        $vgroups = 'CATEGORIES:' . rcube_vcard::vcard_quote(join(',', $groups));
        $record['vcard'] = str_replace('END:VCARD', $vgroups . rcube_vcard::$eol . 'END:VCARD', $record['vcard']);
    }
}
program/steps/addressbook/func.inc
@@ -109,6 +109,31 @@
        $RCMAIL->session->remove('contact_undo');
}
// register UI objects
$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')
));
// register action aliases
$RCMAIL->register_action_map(array(
    'add'              => 'edit.inc',
    'group-create'     => 'groups.inc',
    'group-rename'     => 'groups.inc',
    'group-delete'     => 'groups.inc',
    'group-addmembers' => 'groups.inc',
    'group-delmembers' => 'groups.inc',
    'search-create'    => 'search.inc',
    'search-delete'    => 'search.inc',
));
// instantiate a contacts object according to the given source
function rcmail_contact_source($source=null, $init_env=false, $writable=false)
{
@@ -895,27 +920,3 @@
    return $filter !== null ? $result[$filter] : $result;
}
// register UI objects
$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')
));
// register action aliases
$RCMAIL->register_action_map(array(
    'add' => 'edit.inc',
    'group-create' => 'groups.inc',
    'group-rename' => 'groups.inc',
    'group-delete' => 'groups.inc',
    'group-addmembers' => 'groups.inc',
    'group-delmembers' => 'groups.inc',
    'search-create' => 'search.inc',
    'search-delete' => 'search.inc',
));
program/steps/addressbook/import.inc
@@ -20,164 +20,6 @@
 +-----------------------------------------------------------------------+
*/
/**
 * Handler function to display the import/upload form
 */
function rcmail_import_form($attrib)
{
    global $RCMAIL, $OUTPUT;
    $target = rcube_utils::get_input_value('_target', rcube_utils::INPUT_GPC);
    $attrib += array('id' => "rcmImportForm");
    $writable_books = $RCMAIL->get_address_sources(true, true);
    $upload = new html_inputfield(array(
        'type'     => 'file',
        'name'     => '_file[]',
        'id'       => 'rcmimportfile',
        'size'     => 40,
        'multiple' => 'multiple',
    ));
    $form  = html::p(null, html::label('rcmimportfile', $RCMAIL->gettext('importfromfile')) . $upload->show());
    $table = new html_table(array('cols' => 2));
    // addressbook selector
    if (count($writable_books) > 1) {
        $select = new html_select(array('name' => '_target', 'id' => 'rcmimporttarget', 'is_escaped' => true));
        foreach ($writable_books as $book) {
            $select->add($book['name'], $book['id']);
        }
        $table->add('title', html::label('rcmimporttarget', $RCMAIL->gettext('importtarget')));
        $table->add(null, $select->show($target));
    }
    else {
        $abook = new html_hiddenfield(array('name' => '_target', 'value' => key($writable_books)));
        $form .= $abook->show();
    }
    // selector for group import options
    if (count($writable_books) >= 1 || $writable_books[0]->groups) {
        $select = new html_select(array('name' => '_groups', 'id' => 'rcmimportgroups', 'is_escaped' => true));
        $select->add($RCMAIL->gettext('none'), '0');
        $select->add($RCMAIL->gettext('importgroupsall'), '1');
        $select->add($RCMAIL->gettext('importgroupsexisting'), '2');
        $table->add('title', html::label('rcmimportgroups', $RCMAIL->gettext('importgroups')));
        $table->add(null, $select->show(rcube_utils::get_input_value('_groups', rcube_utils::INPUT_GPC)));
    }
    // checkbox to replace the entire address book
    $check_replace = new html_checkbox(array('name' => '_replace', 'value' => 1, 'id' => 'rcmimportreplace'));
    $table->add('title', html::label('rcmimportreplace', $RCMAIL->gettext('importreplace')));
    $table->add(null, $check_replace->show(rcube_utils::get_input_value('_replace', rcube_utils::INPUT_GPC)));
    $form .= $table->show(array('id' => null) + $attrib);
    $OUTPUT->set_env('writable_source', !empty($writable_books));
    $OUTPUT->add_label('selectimportfile','importwait');
    $OUTPUT->add_gui_object('importform', $attrib['id']);
    $out = html::p(null, rcube::Q($RCMAIL->gettext('importdesc'), 'show'))
        . $OUTPUT->form_tag(array(
            'action'  => $RCMAIL->url('import'),
            'method'  => 'post',
            'enctype' => 'multipart/form-data') + $attrib,
            $form);
    return $out;
}
/**
 * Render the confirmation page for the import process
 */
function rcmail_import_confirm($attrib)
{
    global $IMPORT_STATS, $RCMAIL;
    $vars = get_object_vars($IMPORT_STATS);
    $vars['names'] = $vars['skipped_names'] = '';
    $content = html::p(null, $RCMAIL->gettext(array(
        'name' => 'importconfirm',
        'nr'   => $IMPORT_STATS->inserted,
        'vars' => $vars,
        )) . ($IMPORT_STATS->names ? ':' : '.'));
    if ($IMPORT_STATS->names) {
        $content .= html::p('em', join(', ', array_map('Q', $IMPORT_STATS->names)));
    }
    if ($IMPORT_STATS->skipped) {
        $content .= html::p(null, $RCMAIL->gettext(array(
                'name' => 'importconfirmskipped',
                'nr'   => $IMPORT_STATS->skipped,
                'vars' => $vars,
            )) . ':')
            . html::p('em', join(', ', array_map('Q', $IMPORT_STATS->skipped_names)));
    }
    return html::div($attrib, $content);
}
/**
 * Create navigation buttons for the current import step
 */
function rcmail_import_buttons($attrib)
{
    global $IMPORT_STATS, $OUTPUT;
    $target = rcube_utils::get_input_value('_target', rcube_utils::INPUT_GPC);
    $attrib += array('type' => 'input');
    unset($attrib['name']);
    if (is_object($IMPORT_STATS)) {
        $attrib['class'] = trim($attrib['class'] . ' mainaction');
        $out = $OUTPUT->button(array('command' => 'list', 'prop' => $target, 'label' => 'done') + $attrib);
    }
    else {
        $out = $OUTPUT->button(array('command' => 'list', 'label' => 'cancel') + $attrib);
        $out .= ' ';
        $attrib['class'] = trim($attrib['class'] . ' mainaction');
        $out .= $OUTPUT->button(array('command' => 'import', 'label' => 'import') + $attrib);
    }
    return $out;
}
/**
 * Returns the matching group id. If group doesn't exist, it'll be created if allowed.
 */
function rcmail_import_group_id($group_name, $CONTACTS, $create, &$import_groups)
{
    $group_id = 0;
    foreach ($import_groups as $key => $group) {
        if (strtolower($group['name']) == strtolower($group_name)) {
            $group_id = $group['ID'];
            break;
        }
    }
    // create a new group
    if (!$group_id && $create) {
        $new_group = $CONTACTS->create_group($group_name);
        if (!$new_group['ID'])
            $new_group['ID'] = $new_group['id'];
        $import_groups[] = $new_group;
        $group_id = $new_group['ID'];
    }
    return $group_id;
}
/** The import process **/
$importstep = 'rcmail_import_form';
@@ -343,3 +185,159 @@
// render page
$OUTPUT->send('importcontacts');
/**
 * Handler function to display the import/upload form
 */
function rcmail_import_form($attrib)
{
    global $RCMAIL, $OUTPUT;
    $target = rcube_utils::get_input_value('_target', rcube_utils::INPUT_GPC);
    $attrib += array('id' => "rcmImportForm");
    $writable_books = $RCMAIL->get_address_sources(true, true);
    $upload = new html_inputfield(array(
        'type'     => 'file',
        'name'     => '_file[]',
        'id'       => 'rcmimportfile',
        'size'     => 40,
        'multiple' => 'multiple',
    ));
    $form  = html::p(null, html::label('rcmimportfile', $RCMAIL->gettext('importfromfile')) . $upload->show());
    $table = new html_table(array('cols' => 2));
    // addressbook selector
    if (count($writable_books) > 1) {
        $select = new html_select(array('name' => '_target', 'id' => 'rcmimporttarget', 'is_escaped' => true));
        foreach ($writable_books as $book) {
            $select->add($book['name'], $book['id']);
        }
        $table->add('title', html::label('rcmimporttarget', $RCMAIL->gettext('importtarget')));
        $table->add(null, $select->show($target));
    }
    else {
        $abook = new html_hiddenfield(array('name' => '_target', 'value' => key($writable_books)));
        $form .= $abook->show();
    }
    // selector for group import options
    if (count($writable_books) >= 1 || $writable_books[0]->groups) {
        $select = new html_select(array('name' => '_groups', 'id' => 'rcmimportgroups', 'is_escaped' => true));
        $select->add($RCMAIL->gettext('none'), '0');
        $select->add($RCMAIL->gettext('importgroupsall'), '1');
        $select->add($RCMAIL->gettext('importgroupsexisting'), '2');
        $table->add('title', html::label('rcmimportgroups', $RCMAIL->gettext('importgroups')));
        $table->add(null, $select->show(rcube_utils::get_input_value('_groups', rcube_utils::INPUT_GPC)));
    }
    // checkbox to replace the entire address book
    $check_replace = new html_checkbox(array('name' => '_replace', 'value' => 1, 'id' => 'rcmimportreplace'));
    $table->add('title', html::label('rcmimportreplace', $RCMAIL->gettext('importreplace')));
    $table->add(null, $check_replace->show(rcube_utils::get_input_value('_replace', rcube_utils::INPUT_GPC)));
    $form .= $table->show(array('id' => null) + $attrib);
    $OUTPUT->set_env('writable_source', !empty($writable_books));
    $OUTPUT->add_label('selectimportfile','importwait');
    $OUTPUT->add_gui_object('importform', $attrib['id']);
    $out = html::p(null, rcube::Q($RCMAIL->gettext('importdesc'), 'show'))
        . $OUTPUT->form_tag(array(
            'action'  => $RCMAIL->url('import'),
            'method'  => 'post',
            'enctype' => 'multipart/form-data') + $attrib,
            $form);
    return $out;
}
/**
 * Render the confirmation page for the import process
 */
function rcmail_import_confirm($attrib)
{
    global $IMPORT_STATS, $RCMAIL;
    $vars = get_object_vars($IMPORT_STATS);
    $vars['names'] = $vars['skipped_names'] = '';
    $content = html::p(null, $RCMAIL->gettext(array(
        'name' => 'importconfirm',
        'nr'   => $IMPORT_STATS->inserted,
        'vars' => $vars,
        )) . ($IMPORT_STATS->names ? ':' : '.'));
    if ($IMPORT_STATS->names) {
        $content .= html::p('em', join(', ', array_map('Q', $IMPORT_STATS->names)));
    }
    if ($IMPORT_STATS->skipped) {
        $content .= html::p(null, $RCMAIL->gettext(array(
                'name' => 'importconfirmskipped',
                'nr'   => $IMPORT_STATS->skipped,
                'vars' => $vars,
            )) . ':')
            . html::p('em', join(', ', array_map('Q', $IMPORT_STATS->skipped_names)));
    }
    return html::div($attrib, $content);
}
/**
 * Create navigation buttons for the current import step
 */
function rcmail_import_buttons($attrib)
{
    global $IMPORT_STATS, $OUTPUT;
    $target = rcube_utils::get_input_value('_target', rcube_utils::INPUT_GPC);
    $attrib += array('type' => 'input');
    unset($attrib['name']);
    if (is_object($IMPORT_STATS)) {
        $attrib['class'] = trim($attrib['class'] . ' mainaction');
        $out = $OUTPUT->button(array('command' => 'list', 'prop' => $target, 'label' => 'done') + $attrib);
    }
    else {
        $out = $OUTPUT->button(array('command' => 'list', 'label' => 'cancel') + $attrib);
        $out .= ' ';
        $attrib['class'] = trim($attrib['class'] . ' mainaction');
        $out .= $OUTPUT->button(array('command' => 'import', 'label' => 'import') + $attrib);
    }
    return $out;
}
/**
 * Returns the matching group id. If group doesn't exist, it'll be created if allowed.
 */
function rcmail_import_group_id($group_name, $CONTACTS, $create, &$import_groups)
{
    $group_id = 0;
    foreach ($import_groups as $key => $group) {
        if (strtolower($group['name']) == strtolower($group_name)) {
            $group_id = $group['ID'];
            break;
        }
    }
    // create a new group
    if (!$group_id && $create) {
        $new_group = $CONTACTS->create_group($group_name);
        if (!$new_group['ID'])
            $new_group['ID'] = $new_group['id'];
        $import_groups[] = $new_group;
        $group_id = $new_group['ID'];
    }
    return $group_id;
}
program/steps/addressbook/mailto.inc
@@ -5,7 +5,7 @@
 | program/steps/addressbook/mailto.inc                                  |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2007, The Roundcube Dev Team                            |
 | 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.                |
@@ -23,20 +23,17 @@
$mailto = array();
$recipients = null;
foreach ($cids as $source => $cid)
{
foreach ($cids as $source => $cid) {
    $CONTACTS = $RCMAIL->get_address_book($source);
    if ($CONTACTS->ready)
    {
    if ($CONTACTS->ready) {
        $CONTACTS->set_page(1);
        $CONTACTS->set_pagesize(count($cid) + 2); // +2 to skip counting query
        $recipients = $CONTACTS->search($CONTACTS->primary_key, $cid, 0, true, true, 'email');
    }
}
if (!empty($_REQUEST['_gid']) && isset($_REQUEST['_source']))
{
if (!empty($_REQUEST['_gid']) && isset($_REQUEST['_source'])) {
    $source = rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC);
    $CONTACTS = $RCMAIL->get_address_book($source);
@@ -55,16 +52,14 @@
    }
}
if ($recipients)
{
if ($recipients) {
    while (is_object($recipients) && ($rec = $recipients->iterate())) {
        $emails = $CONTACTS->get_col_values('email', $rec, true);
        $mailto[] = format_email_recipient($emails[0], $rec['name']);
    }
}
if (!empty($mailto))
{
if (!empty($mailto)) {
    $mailto_str = join(', ', $mailto);
    $mailto_id = substr(md5($mailto_str), 0, 16);
    $_SESSION['mailto'][$mailto_id] = urlencode($mailto_str);
program/steps/addressbook/show.inc
@@ -5,7 +5,7 @@
 | program/steps/addressbook/show.inc                                    |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2005-2012, The Roundcube Dev Team                       |
 | 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.                |
@@ -37,6 +37,15 @@
// get address book name (for display)
rcmail_set_sourcename($CONTACTS);
$OUTPUT->add_handlers(array(
    'contacthead'    => 'rcmail_contact_head',
    'contactdetails' => 'rcmail_contact_details',
    'contactphoto'   => 'rcmail_contact_photo',
));
$OUTPUT->send('contact');
function rcmail_contact_head($attrib)
@@ -183,12 +192,3 @@
    return $form_start . html::tag('fieldset', 'contactfieldgroup contactgroups', $table->show()) . $form_end;
}
$OUTPUT->add_handlers(array(
    'contacthead'    => 'rcmail_contact_head',
    'contactdetails' => 'rcmail_contact_details',
    'contactphoto'   => 'rcmail_contact_photo',
));
$OUTPUT->send('contact');
program/steps/addressbook/undo.inc
@@ -5,7 +5,7 @@
 | program/steps/addressbook/undo.inc                                    |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2011, Kolab Systems AG                                  |
 | Copyright (C) 2011-2013, Kolab Systems AG                             |
 |                                                                       |
 | Licensed under the GNU General Public License version 3 or            |
 | any later version with exceptions for skins & plugins.                |
@@ -20,14 +20,14 @@
*/
// process ajax requests only
if (!$OUTPUT->ajax_call)
if (!$OUTPUT->ajax_call) {
    return;
}
$undo   = $_SESSION['contact_undo'];
$delcnt = 0;
foreach ((array)$undo['data'] as $source => $cid)
{
foreach ((array)$undo['data'] as $source => $cid) {
    $CONTACTS = rcmail_contact_source($source);
    $plugin = $RCMAIL->plugins->exec_hook('contact_undelete', array(
program/steps/mail/compose.inc
@@ -121,10 +121,13 @@
$OUTPUT->set_env('top_posting', intval($RCMAIL->config->get('reply_mode')) > 0);
$OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ',')));
$drafts_mbox     = $RCMAIL->config->get('drafts_mbox');
$config_show_sig = $RCMAIL->config->get('show_sig', 1);
// add config parameters to client script
if (!empty($CONFIG['drafts_mbox'])) {
    $OUTPUT->set_env('drafts_mailbox', $CONFIG['drafts_mbox']);
    $OUTPUT->set_env('draft_autosave', $CONFIG['draft_autosave']);
if (strlen($drafts_mbox)) {
    $OUTPUT->set_env('drafts_mailbox', $drafts_mbox);
    $OUTPUT->set_env('draft_autosave', $RCMAIL->config->get('draft_autosave'));
}
// default font for HTML editor
@@ -142,7 +145,7 @@
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']);
    $RCMAIL->storage->set_folder($drafts_mbox);
}
else if ($msg_uid = $COMPOSE['param']['reply_uid']) {
    $compose_mode = RCUBE_COMPOSE_REPLY;
@@ -159,7 +162,6 @@
$COMPOSE['mode'] = $compose_mode;
$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)
@@ -186,7 +188,9 @@
        $RCMAIL->config->set('prefer_html', $_SESSION['msg_formats'][$mbox_name.':'.$msg_uid]);
    }
    else {
        $prefer_html = $CONFIG['prefer_html'] || $CONFIG['htmleditor'] || $compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT;
        $prefer_html = $RCMAIL->config->get('prefer_html') || $RCMAIL->config->get('htmleditor')
            || $compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT;
        $RCMAIL->config->set('prefer_html', $prefer_html);
    }
@@ -849,7 +853,7 @@
function rcmail_compose_body($attrib)
{
    global $RCMAIL, $CONFIG, $OUTPUT, $HTML_MODE, $MESSAGE_BODY;
    global $RCMAIL, $OUTPUT, $HTML_MODE, $MESSAGE_BODY;
    list($form_start, $form_end) = get_form_tags($attrib);
    unset($attrib['form']);
@@ -901,7 +905,7 @@
    $RCMAIL->html_editor();
    // Set language list
    if (!empty($CONFIG['enable_spellcheck'])) {
    if ($RCMAIL->config->get('enable_spellcheck')) {
        $engine           = new rcube_spellchecker();
        $dictionary       = (bool) $RCMAIL->config->get('spellcheck_dictionary');
        $spellcheck_langs = $engine->languages();
@@ -1453,7 +1457,7 @@
function rcmail_compose_attachment_list($attrib)
{
    global $RCMAIL, $OUTPUT, $CONFIG, $COMPOSE;
    global $RCMAIL, $OUTPUT, $COMPOSE;
    // add ID if not given
    if (!$attrib['id'])
@@ -1462,11 +1466,12 @@
    $out    = "\n";
    $jslist = array();
    $button = '';
    $skin_path = $RCMAIL->config->get('skin_path');
    if (is_array($COMPOSE['attachments'])) {
        if ($attrib['deleteicon']) {
            $button = html::img(array(
                'src' => $CONFIG['skin_path'] . $attrib['deleteicon'],
                'src' => $skin_path . $attrib['deleteicon'],
                'alt' => $RCMAIL->gettext('delete')
            ));
        }
@@ -1503,13 +1508,13 @@
    }
    if ($attrib['deleteicon'])
        $COMPOSE['deleteicon'] = $CONFIG['skin_path'] . $attrib['deleteicon'];
        $COMPOSE['deleteicon'] = $skin_path . $attrib['deleteicon'];
    else if (rcube_utils::get_boolean($attrib['textbuttons']))
        $COMPOSE['textbuttons'] = true;
    if ($attrib['cancelicon'])
        $OUTPUT->set_env('cancelicon', $CONFIG['skin_path'] . $attrib['cancelicon']);
        $OUTPUT->set_env('cancelicon', $skin_path . $attrib['cancelicon']);
    if ($attrib['loadingicon'])
        $OUTPUT->set_env('loadingicon', $CONFIG['skin_path'] . $attrib['loadingicon']);
        $OUTPUT->set_env('loadingicon', $skin_path . $attrib['loadingicon']);
    $OUTPUT->set_env('attachments', $jslist);
    $OUTPUT->add_gui_object('attachmentlist', $attrib['id']);
program/steps/mail/func.inc
@@ -5,7 +5,7 @@
 | program/steps/mail/func.inc                                           |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2005-2012, The Roundcube Dev Team                       |
 | 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.                |
@@ -16,43 +16,44 @@
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 | Author: Aleksander Machniak <alec@alec.pl>                            |
 +-----------------------------------------------------------------------+
*/
// setup some global vars used by mail steps
$SENT_MBOX = $RCMAIL->config->get('sent_mbox');
$DRAFTS_MBOX = $RCMAIL->config->get('drafts_mbox');
$SEARCH_MODS_DEFAULT = array(
    '*'         => array('subject'=>1, 'from'=>1),
    $SENT_MBOX  => array('subject'=>1, 'to'=>1),
    $DRAFTS_MBOX => array('subject'=>1, 'to'=>1)
);
// always instantiate storage object (but not connect to server yet)
$RCMAIL->storage_init();
// set imap properties and session vars
if (strlen(trim($mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true))))
if (strlen(trim($mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true)))) {
  $RCMAIL->storage->set_folder(($_SESSION['mbox'] = $mbox));
else if ($RCMAIL->storage)
}
else if ($RCMAIL->storage) {
  $_SESSION['mbox'] = $RCMAIL->storage->get_folder();
}
if (!empty($_GET['_page']))
if (!empty($_GET['_page'])) {
  $RCMAIL->storage->set_page(($_SESSION['page'] = intval($_GET['_page'])));
}
$a_threading        = $RCMAIL->config->get('message_threading', array());
$message_sort_col   = $RCMAIL->config->get('message_sort_col');
$message_sort_order = $RCMAIL->config->get('message_sort_col');
// set default sort col/order to session
if (!isset($_SESSION['sort_col']))
  $_SESSION['sort_col'] = !empty($CONFIG['message_sort_col']) ? $CONFIG['message_sort_col'] : '';
if (!isset($_SESSION['sort_order']))
  $_SESSION['sort_order'] = strtoupper($CONFIG['message_sort_order']) == 'ASC' ? 'ASC' : 'DESC';
if (!isset($_SESSION['sort_col'])) {
    $_SESSION['sort_col'] = $message_sort_col ? $message_sort_col : '';
}
if (!isset($_SESSION['sort_order'])) {
  $_SESSION['sort_order'] = strtoupper($message_sort_order) == 'ASC' ? 'ASC' : 'DESC';
}
// set threads mode
$a_threading = $RCMAIL->config->get('message_threading', array());
if (isset($_GET['_threads'])) {
  if ($_GET['_threads'])
    $a_threading[$_SESSION['mbox']] = true;
  else
    unset($a_threading[$_SESSION['mbox']]);
  $RCMAIL->user->save_prefs(array('message_threading' => $a_threading));
}
$RCMAIL->storage->set_threading($a_threading[$_SESSION['mbox']]);
@@ -62,6 +63,7 @@
    && $_SESSION['search_request'] == $_REQUEST['_search']
) {
  $RCMAIL->storage->set_search_set($_SESSION['search']);
  $OUTPUT->set_env('search_request', $_REQUEST['_search']);
  $OUTPUT->set_env('search_text', $_SESSION['last_text_search']);
}
@@ -76,16 +78,16 @@
  if (empty($RCMAIL->action)) {
    // initialize searching result if search_filter is used
    if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL') {
      $search_request = md5($mbox_name.$_SESSION['search_filter']);
      $RCMAIL->storage->search($mbox_name, $_SESSION['search_filter'], RCUBE_CHARSET, rcmail_sort_column());
            $search_request             = md5($mbox_name.$_SESSION['search_filter']);
      $_SESSION['search'] = $RCMAIL->storage->get_search_set();
      $_SESSION['search_request'] = $search_request;
      $OUTPUT->set_env('search_request', $search_request);
    }
    $search_mods = $RCMAIL->config->get('search_mods', $SEARCH_MODS_DEFAULT);
    $OUTPUT->set_env('search_mods', $search_mods);
        $OUTPUT->set_env('search_mods', rcmail_search_mods());
  }
  $threading = (bool) $RCMAIL->storage->get_threading();
@@ -99,29 +101,31 @@
  $OUTPUT->set_env('threads', $threading || $RCMAIL->storage->get_capability('THREAD'));
  $OUTPUT->set_env('reply_all_mode', (int) $RCMAIL->config->get('reply_all_mode'));
  $OUTPUT->set_env('preview_pane_mark_read', $RCMAIL->config->get('preview_pane_mark_read', 0));
  if ($RCMAIL->storage->get_capability('QUOTA')) {
    $OUTPUT->set_env('quota', true);
  }
  foreach (array('delete_junk','flag_for_deletion','read_when_deleted','skip_deleted','display_next','message_extwin','compose_extwin','forward_attachment') as $prop) {
    if ($CONFIG[$prop])
      $OUTPUT->set_env($prop, true);
    // set special folders
    foreach (array('drafts', 'trash', 'junk') as $mbox) {
        if ($folder = $RCMAIL->config->get($mbox . '_mbox')) {
            $OUTPUT->set_env($mbox . '_mailbox', $folder);
        }
  }
  if ($CONFIG['trash_mbox'])
    $OUTPUT->set_env('trash_mailbox', $CONFIG['trash_mbox']);
  if ($CONFIG['drafts_mbox'])
    $OUTPUT->set_env('drafts_mailbox', $CONFIG['drafts_mbox']);
  if ($CONFIG['junk_mbox'])
    $OUTPUT->set_env('junk_mailbox', $CONFIG['junk_mbox']);
    // set configuration
    $RCMAIL->set_env_config(array('delete_junk', 'flag_for_deletion', 'read_when_deleted',
        'skip_deleted', 'display_next', 'message_extwin', 'compose_extwin', 'forward_attachment'));
  if (!empty($_SESSION['browser_caps']))
    if (!empty($_SESSION['browser_caps'])) {
    $OUTPUT->set_env('browser_capabilities', $_SESSION['browser_caps']);
    }
  if (!$OUTPUT->ajax_call)
    if (!$OUTPUT->ajax_call) {
    $OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash',
      'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage',
      'copy', 'move', 'quota', 'replyall', 'replylist', 'importwait');
    }
  $pagetitle = $RCMAIL->localize_foldername($RCMAIL->storage->mod_folder($mbox_name), true);
  $pagetitle = str_replace($delimiter, " \xC2\xBB ", $pagetitle);
@@ -132,9 +136,9 @@
// register UI objects
$OUTPUT->add_handlers(array(
  'mailboxlist'         => array($RCMAIL, 'folder_list'),
    'quotadisplay'        => array($RCMAIL, 'quota_display'),
  'messages'            => 'rcmail_message_list',
  'messagecountdisplay' => 'rcmail_messagecount_display',
  'quotadisplay'        => array($RCMAIL, 'quota_display'),
  'mailboxname'         => 'rcmail_mailbox_name_display',
  'messageheaders'      => 'rcmail_message_headers',
  'messagefullheaders'  => 'rcmail_message_full_headers',
@@ -162,6 +166,28 @@
));
/**
 * Returns default search mods
 */
function rcmail_search_mods()
{
    global $RCMAIL;
    $mods = $RCMAIL->config->get('search_mods');
    if (empty($mods)) {
        $mods = array('*' => array('subject' => 1, 'from' => 1));
        foreach (array('sent', 'drafts') as $mbox) {
            if ($mbox = $RCMAIL->config->get($mbox . '_mbox')) {
                $mods[$mbox] = array('subject' => 1, 'to' => 1);
            }
        }
    }
    return $mods;
}
/**
 * Returns 'to' if current folder is configured Sent or Drafts
@@ -234,7 +260,7 @@
 */
function rcmail_message_list($attrib)
{
  global $CONFIG, $OUTPUT;
    global $RCMAIL, $OUTPUT;
  // add some labels to client
  $OUTPUT->add_label('from', 'to');
@@ -245,8 +271,10 @@
  // define list of cols to be displayed based on parameter or config
  if (empty($attrib['columns'])) {
    $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
    $OUTPUT->set_env('col_movable', !in_array('list_cols', (array)$CONFIG['dont_override']));
        $list_cols   = $RCMAIL->config->get('list_cols');
        $a_show_cols = !empty($list_cols) && is_array($list_cols) ? $list_cols : array('subject');
        $OUTPUT->set_env('col_movable', !in_array('list_cols', (array)$RCMAIL->config->get('dont_override')));
  }
  else {
    $a_show_cols = preg_split('/[\s,;]+/', str_replace(array("'", '"'), '', $attrib['columns']));
@@ -255,17 +283,18 @@
  // save some variables for use in ajax list
  $_SESSION['list_attrib'] = $attrib;
  // make sure 'threads' and 'subject' columns are present
  if (!in_array('subject', $a_show_cols))
    array_unshift($a_show_cols, 'subject');
  if (!in_array('threads', $a_show_cols))
    array_unshift($a_show_cols, 'threads');
  $_SESSION['skin_path'] = $CONFIG['skin_path'];
    $_SESSION['skin_path'] = $RCMAIL->config->get('skin_path');
  // set client env
  $OUTPUT->add_gui_object('messagelist', $attrib['id']);
  $OUTPUT->set_env('autoexpand_threads', intval($CONFIG['autoexpand_threads']));
    $OUTPUT->set_env('autoexpand_threads', intval($RCMAIL->config->get('autoexpand_threads')));
  $OUTPUT->set_env('sort_col', $_SESSION['sort_col']);
  $OUTPUT->set_env('sort_order', $_SESSION['sort_order']);
  $OUTPUT->set_env('messages', array());
@@ -274,6 +303,7 @@
  $OUTPUT->include_script('list.js');
  $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']);
@@ -282,23 +312,25 @@
  return $table->show();
}
/**
 * return javascript commands to add rows to the message list
 */
function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null)
{
  global $CONFIG, $RCMAIL, $OUTPUT;
    global $RCMAIL, $OUTPUT;
  if (empty($a_show_cols)) {
    if (!empty($_SESSION['list_attrib']['columns']))
      $a_show_cols = $_SESSION['list_attrib']['columns'];
    else
      $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
        else {
            $list_cols   = $RCMAIL->config->get('list_cols');
            $a_show_cols = !empty($list_cols) && is_array($list_cols) ? $list_cols : array('subject');
        }
  }
  else {
    if (!is_array($a_show_cols))
        if (!is_array($a_show_cols)) {
      $a_show_cols = preg_split('/[\s,;]+/', str_replace(array("'", '"'), '', $a_show_cols));
        }
    $head_replace = true;
  }
@@ -332,13 +364,15 @@
  $OUTPUT->command('set_message_coltypes', $a_show_cols, $thead, $smart_col);
  if (empty($a_headers))
    if (empty($a_headers)) {
    return;
    }
  // remove 'threads', 'attachment', 'flag', 'status' columns, we don't need them here
  foreach (array('threads', 'attachment', 'flag', 'status', 'priority') as $col) {
    if (($key = array_search($col, $a_show_cols)) !== FALSE)
        if (($key = array_search($col, $a_show_cols)) !== FALSE) {
      unset($a_show_cols[$key]);
        }
  }
  // loop through message headers
@@ -407,7 +441,6 @@
  }
}
/*
 * Creates <THEAD> for message list table
 */
@@ -442,11 +475,11 @@
    else
      $list_menu = html::a(array('href' => '#', 'onclick' => $onclick),
        html::img(array('src' => $skin_path . $attrib['optionsmenuicon'],
          'id' => 'listmenulink', 'title' => $RCMAIL->gettext('listoptions')))
      );
                    'id' => 'listmenulink', 'title' => $RCMAIL->gettext('listoptions'))));
  }
  else
    else {
    $list_menu = '';
    }
  $cells = array();
@@ -477,10 +510,16 @@
    }
    // make sort links
    if (in_array($col, $a_sort_cols))
      $col_name = html::a(array('href'=>"./#sort", 'onclick' => 'return '.rcmail_output::JS_OBJECT_NAME.".command('sort','".$col."',this)", 'title' => $RCMAIL->gettext('sortby')), $col_name);
    else if ($col_name[0] != '<')
        if (in_array($col, $a_sort_cols)) {
            $col_name = html::a(array(
                    'href'    => "./#sort",
                    'onclick' => 'return '.rcmail_output::JS_OBJECT_NAME.".command('sort','".$col."',this)",
                    'title'   => $RCMAIL->gettext('sortby')
                ), $col_name);
        }
        else if ($col_name[0] != '<') {
      $col_name = '<span class="' . $col .'">' . $col_name . '</span>';
        }
    $sort_class = $col == $sort_col && !$disabled_order ? " sorted$sort_order" : '';
    $class_name = $col.$sort_class;
@@ -491,7 +530,6 @@
  return $cells;
}
/**
 * return an HTML iframe for loading mail content
@@ -505,13 +543,14 @@
  $attrib['name'] = $attrib['id'];
  if ($RCMAIL->config->get('preview_pane'))
    if ($RCMAIL->config->get('preview_pane')) {
    $OUTPUT->set_env('contentframe', $attrib['id']);
    }
  $OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/resources/blank.gif');
  return $OUTPUT->frame($attrib, true);
}
function rcmail_messagecount_display($attrib)
{
@@ -527,19 +566,18 @@
  return html::span($attrib, $content);
}
function rcmail_get_messagecount_text($count=NULL, $page=NULL)
function rcmail_get_messagecount_text($count = null, $page = null)
{
  global $RCMAIL;
  if ($page === NULL) {
    if ($page === null) {
    $page = $RCMAIL->storage->get_page();
  }
  $page_size = $RCMAIL->storage->get_pagesize();
  $start_msg = ($page-1) * $page_size + 1;
  if ($count!==NULL)
    if ($count !== null)
    $max = $count;
  else if ($RCMAIL->action)
    $max = $RCMAIL->storage->count(NULL, $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL');
@@ -555,7 +593,6 @@
  return rcube::Q($out);
}
function rcmail_mailbox_name_display($attrib)
{
  global $RCMAIL;
@@ -568,13 +605,11 @@
  return html::span($attrib, rcmail_get_mailbox_name_text());
}
function rcmail_get_mailbox_name_text()
{
  global $RCMAIL;
  return $RCMAIL->localize_foldername($RCMAIL->storage->get_folder());
}
function rcmail_send_unread_count($mbox_name, $force=false, $count=null, $mark='')
{
@@ -596,27 +631,24 @@
  return $unseen;
}
function rcmail_set_unseen_count($mbox_name, $count)
{
  // @TODO: this data is doubled (session and cache tables) if caching is enabled
  // Make sure we have an array here (#1487066)
  if (!is_array($_SESSION['unseen_count']))
    if (!is_array($_SESSION['unseen_count'])) {
    $_SESSION['unseen_count'] = array();
    }
  $_SESSION['unseen_count'][$mbox_name] = $count;
}
function rcmail_get_unseen_count($mbox_name)
{
  if (is_array($_SESSION['unseen_count']) && array_key_exists($mbox_name, $_SESSION['unseen_count']))
    if (is_array($_SESSION['unseen_count']) && array_key_exists($mbox_name, $_SESSION['unseen_count'])) {
    return $_SESSION['unseen_count'][$mbox_name];
  else
    return null;
}
}
/**
 * Sets message is_safe flag according to 'show_images' option value
@@ -652,7 +684,6 @@
    }
  }
}
/**
 * Cleans up the given message HTML Body (for displaying)
@@ -708,12 +739,14 @@
  // initialize HTML washer
  $washer = new rcube_washtml($wash_opts);
  if (!$p['skip_washer_form_callback'])
    if (!$p['skip_washer_form_callback']) {
    $washer->add_callback('form', 'rcmail_washtml_callback');
    }
  // allow CSS styles, will be sanitized by rcmail_washtml_callback()
  if (!$p['skip_washer_style_callback'])
    if (!$p['skip_washer_style_callback']) {
    $washer->add_callback('style', 'rcmail_washtml_callback');
    }
  // Remove non-UTF8 characters (#1487813)
  $html = rcube_charset::clean($html);
@@ -723,7 +756,6 @@
  return $html;
}
/**
 * Convert the given message part to proper HTML
@@ -747,6 +779,7 @@
    if ($data['type'] == 'enriched') {
      $data['body'] = rcube_enriched::to_html($data['body']);
    }
    $txt = new rcube_html2text($data['body'], false, true);
    $body = $txt->get_text();
    $part->ctype_secondary = 'plain';
@@ -786,7 +819,6 @@
  return $data['type'] == 'html' ? $data['body'] : html::tag('pre', array(), $data['body']);
}
/**
 * Handle links and citation marks in plain text message
@@ -848,12 +880,15 @@
  // colorize signature (up to <sig_max_lines> lines)
  $len = strlen($body);
  $sig_max_lines = $RCMAIL->config->get('sig_max_lines', 15);
  while (($sp = strrpos($body, "-- \n", $sp ? -$len+$sp-1 : 0)) !== false) {
    if ($sp == 0 || $body[$sp-1] == "\n") {
      // do not touch blocks with more that X lines
      if (substr_count($body, "\n", $sp) < $sig_max_lines)
            if (substr_count($body, "\n", $sp) < $sig_max_lines) {
        $body = substr($body, 0, max(0, $sp))
          .'<span class="sig">'.substr($body, $sp).'</span>';
            }
      break;
    }
  }
@@ -863,7 +898,6 @@
  return $body;
}
/**
 * Callback function for washtml cleaning class
@@ -895,7 +929,6 @@
  return $out;
}
/**
 * return table with message headers
 */
@@ -910,8 +943,9 @@
  else if (!is_array($attrib) && is_array($sa_attrib))
    $attrib = $sa_attrib;
  if (!isset($MESSAGE))
    return FALSE;
    if (!isset($MESSAGE)) {
        return false;
    }
  // get associative array of headers object
  if (!$headers) {
@@ -962,7 +996,8 @@
    }
    else if ($hkey == 'replyto') {
      if ($headers['replyto'] != $headers['from']) {
        $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title);
                $header_value = rcmail_address_string($value, $attrib['max'], true,
                    $attrib['addicon'], $headers['charset'], $header_title);
        $ishtml = true;
      }
      else
@@ -972,7 +1007,8 @@
      if ($headers['mail-replyto'] != $headers['reply-to']
        && $headers['reply-to'] != $headers['from']
      ) {
        $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title);
                $header_value = rcmail_address_string($value, $attrib['max'], true,
                    $attrib['addicon'], $headers['charset'], $header_title);
        $ishtml = true;
      }
      else
@@ -980,18 +1016,21 @@
    }
    else if ($hkey == 'sender') {
      if ($headers['sender'] != $headers['from']) {
        $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title);
                $header_value = rcmail_address_string($value, $attrib['max'], true,
                    $attrib['addicon'], $headers['charset'], $header_title);
        $ishtml = true;
      }
      else
        continue;
    }
    else if ($hkey == 'mail-followup-to') {
      $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title);
            $header_value = rcmail_address_string($value, $attrib['max'], true,
                $attrib['addicon'], $headers['charset'], $header_title);
      $ishtml = true;
    }
    else if (in_array($hkey, array('from', 'to', 'cc', 'bcc'))) {
      $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title);
            $header_value = rcmail_address_string($value, $attrib['max'], true,
                $attrib['addicon'], $headers['charset'], $header_title);
      $ishtml = true;
    }
    else if ($hkey == 'subject' && empty($value))
@@ -1007,19 +1046,25 @@
    );
  }
  $plugin = $RCMAIL->plugins->exec_hook('message_headers_output',
    array('output' => $output_headers, 'headers' => $headers_obj, 'exclude' => $exclude_headers));
    $plugin = $RCMAIL->plugins->exec_hook('message_headers_output', array(
        'output'  => $output_headers,
        'headers' => $headers_obj,
        'exclude' => $exclude_headers
    ));
  // single header value is requested
  if (!empty($attrib['valueof']))
    if (!empty($attrib['valueof'])) {
    return rcube::Q($plugin['output'][$attrib['valueof']]['value'], ($attrib['valueof'] == 'subject' ? 'strict' : 'show'));
    }
  // compose html table
  $table = new html_table(array('cols' => 2));
  foreach ($plugin['output'] as $hkey => $row) {
        $val = $row['html'] ? $row['value'] : rcube::Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show'));
    $table->add(array('class' => 'header-title'), rcube::Q($row['title']));
    $table->add(array('class' => 'header '.$hkey), $row['html'] ? $row['value'] : rcube::Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show')));
        $table->add(array('class' => 'header '.$hkey), $val);
  }
  return $table->show($attrib);
@@ -1040,8 +1085,9 @@
    '5' => 'lowest',
  );
  if ($value && $labels_map[$value])
    if ($value && $labels_map[$value]) {
    return $RCMAIL->gettext($labels_map[$value]);
    }
  return '';
}
@@ -1054,14 +1100,17 @@
  global $OUTPUT, $RCMAIL;
  $html = html::div(array('id' => "all-headers", 'class' => "all", 'style' => 'display:none'), html::div(array('id' => 'headers-source'), ''));
  $html .= html::div(array('class' => "more-headers show-headers", 'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".command('show-headers','',this)", 'title' => $RCMAIL->gettext('togglefullheaders')), '');
    $html .= html::div(array(
            'class'   => "more-headers show-headers",
            'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".command('show-headers','',this)",
            'title'   => $RCMAIL->gettext('togglefullheaders')
        ), '');
  $OUTPUT->add_gui_object('all_headers_row', 'all-headers');
  $OUTPUT->add_gui_object('all_headers_box', 'headers-source');
  return html::div($attrib, $html);
}
/**
 * Handler for the 'messagebody' GUI object
@@ -1071,10 +1120,11 @@
 */
function rcmail_message_body($attrib)
{
  global $CONFIG, $OUTPUT, $MESSAGE, $RCMAIL, $REMOTE_OBJECTS;
    global $OUTPUT, $MESSAGE, $RCMAIL, $REMOTE_OBJECTS;
  if (!is_array($MESSAGE->parts) && empty($MESSAGE->body))
    if (!is_array($MESSAGE->parts) && empty($MESSAGE->body)) {
    return '';
    }
  if (!$attrib['id'])
    $attrib['id'] = 'rcmailMsgBody';
@@ -1083,9 +1133,11 @@
  $out = '';
  $header_attrib = array();
  foreach ($attrib as $attr => $value)
    if (preg_match('/^headertable([a-z]+)$/i', $attr, $regs))
    foreach ($attrib as $attr => $value) {
        if (preg_match('/^headertable([a-z]+)$/i', $attr, $regs)) {
      $header_attrib[$regs[1]] = $value;
        }
    }
  if (!empty($MESSAGE->parts)) {
    foreach ($MESSAGE->parts as $part) {
@@ -1103,6 +1155,7 @@
        else if (!$part->size) {
          continue;
        }
        // Check if we have enough memory to handle the message in it
        // #1487424: we need up to 10x more memory than the body
        else if (!rcube_utils::mem_check($part->size * 10)) {
@@ -1112,12 +1165,14 @@
          continue;
        }
        if (empty($part->ctype_parameters) || empty($part->ctype_parameters['charset']))
                if (empty($part->ctype_parameters) || empty($part->ctype_parameters['charset'])) {
          $part->ctype_parameters['charset'] = $MESSAGE->headers->charset;
                }
        // fetch part if not available
        if (!isset($part->body))
                if (!isset($part->body)) {
          $part->body = $MESSAGE->get_part_content($part->mime_id);
                }
        // extract headers from message/rfc822 parts
        if ($part->mimetype == 'message/rfc822') {
@@ -1133,10 +1188,10 @@
          rcmail_message_error($MESSAGE->uid);
        }
        $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', array(
          'part' => $part, 'prefix' => ''));
                $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix',
                    array('part' => $part, 'prefix' => ''));
        $body = rcmail_print_body($part, array('safe' => $safe_mode, 'plain' => !$CONFIG['prefer_html']));
                $body = rcmail_print_body($part, array('safe' => $safe_mode, 'plain' => !$RCMAIL->config->get('prefer_html')));
        if ($part->ctype_secondary == 'html') {
          $body = rcmail_html4inline($body, $attrib['id'], 'rcmBody', $attrs, $safe_mode);
@@ -1166,8 +1221,8 @@
          .'&_mbox='. urlencode($RCMAIL->storage->get_folder()), $RCMAIL->gettext('download')));
    }
    else {
      $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', array(
        'part' => $MESSAGE, 'prefix' => ''));
            $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix',
                array('part' => $MESSAGE, 'prefix' => ''));
      $out .= html::div('message-part', $plugin['prefix'] . html::tag('pre', array(),
        rcmail_plain_body(rcube::Q($MESSAGE->body, 'strict', false))));
@@ -1218,7 +1273,7 @@
        else {
          $out .= html::tag('fieldset', 'image-attachment',
            html::tag('legend', 'image-filename', rcube::Q($attach_prop->filename)) .
            html::p(array('align' => "center"),
                        html::p(array('align' => 'center'),
              html::img(array(
                'src'   => $MESSAGE->get_part_url($attach_prop->mime_id, 'image'),
                'title' => $attach_prop->filename,
@@ -1231,8 +1286,9 @@
  }
  // tell client that there are blocked remote objects
  if ($REMOTE_OBJECTS && !$safe_mode)
    if ($REMOTE_OBJECTS && !$safe_mode) {
    $OUTPUT->set_env('blockedobjects', true);
    }
  return html::div($attrib, $out);
}
@@ -1280,7 +1336,6 @@
  }
}
/**
 * modify a HTML message that it can be displayed inside a HTML page
 */
@@ -1290,8 +1345,7 @@
  $cont_id = $container_id.($body_id ? ' div.'.$body_id : '');
  // find STYLE tags
  while (($pos = stripos($body, '<style', $last_style_pos)) && ($pos2 = stripos($body, '</style>', $pos)))
  {
    while (($pos = stripos($body, '<style', $last_style_pos)) && ($pos2 = stripos($body, '</style>', $pos))) {
    $pos = strpos($body, '>', $pos) + 1;
    $len = $pos2 - $pos;
@@ -1343,16 +1397,19 @@
  $regexp = '/<div class="' . preg_quote($body_id, '/') . '"([^>]*)/';
  if (preg_match($regexp, $body, $m)) {
    $attrs = $m[0];
    // Get bgcolor, we'll set it as background-color of the message container
    if ($m[1] && preg_match('/bgcolor=["\']*([a-z0-9#]+)["\']*/i', $attrs, $mb)) {
      $attributes['background-color'] = $mb[1];
      $attrs = preg_replace('/bgcolor=["\']*[a-z0-9#]+["\']*/i', '', $attrs);
    }
    // Get background, we'll set it as background-image of the message container
    if ($m[1] && preg_match('/background=["\']*([^"\'>\s]+)["\']*/', $attrs, $mb)) {
      $attributes['background-image'] = 'url('.$mb[1].')';
      $attrs = preg_replace('/background=["\']*([^"\'>\s]+)["\']*/', '', $attrs);
    }
    if (!empty($attributes)) {
      $body = preg_replace($regexp, rtrim($attrs), $body, 1);
    }
@@ -1362,9 +1419,11 @@
      // get body style
      if (preg_match('/#'.preg_quote($cont_id, '/').'\s+\{([^}]+)}/i', $body, $m)) {
        // get background related style
        if (preg_match_all('/(background-position|background-repeat)\s*:\s*([^;]+);/i', $m[1], $ma, PREG_SET_ORDER)) {
          foreach ($ma as $style)
                $regexp = '/(background-position|background-repeat)\s*:\s*([^;]+);/i';
                if (preg_match_all($regexp, $m[1], $ma, PREG_SET_ORDER)) {
                    foreach ($ma as $style) {
            $attributes[$style[1]] = $style[2];
                    }
        }
      }
    }
@@ -1377,7 +1436,6 @@
  return $body;
}
/**
 * parse link (a, link, area) attributes and set correct target
@@ -1451,18 +1509,18 @@
  return "<$tag" . html::attrib_string($attrib, $allow) . $end;
}
/**
 * decode address string and re-format it as HTML links
 */
function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, $default_charset=null, $title=null)
{
  global $RCMAIL, $PRINT_MODE, $CONFIG;
    global $RCMAIL, $PRINT_MODE;
  $a_parts = rcube_mime::decode_address_list($input, null, true, $default_charset);
  if (!sizeof($a_parts))
    if (!sizeof($a_parts)) {
    return $input;
    }
  $c = count($a_parts);
  $j = 0;
@@ -1476,6 +1534,7 @@
  foreach ($a_parts as $part) {
    $j++;
    $name   = $part['name'];
    $mailto = $part['mailto'];
    $string = $part['string'];
@@ -1500,8 +1559,9 @@
      if ($linked) {
        $attrs = array(
           'href' => 'mailto:' . $mailto,
           'onclick' => sprintf("return %s.command('compose','%s',this)", rcmail_output::JS_OBJECT_NAME, rcube::JQ(format_email_recipient($mailto, $name))),
           'class' => "rcmContactAddress",
                    'class'   => 'rcmContactAddress',
                    'onclick' => sprintf("return %s.command('compose','%s',this)",
                        rcmail_output::JS_OBJECT_NAME, rcube::JQ(format_email_recipient($mailto, $name))),
        );
        if ($show_email && $name && $mailto) {
@@ -1522,12 +1582,13 @@
      if ($addicon && $_SESSION['writeable_abook']) {
        $address .= html::a(array(
            'href' => "#add",
            'onclick' => sprintf("return %s.command('add-contact','%s',this)", rcmail_output::JS_OBJECT_NAME, rcube::JQ($string)),
            'title' => $RCMAIL->gettext('addtoaddressbook'),
            'class' => 'rcmaddcontact',
                        'onclick' => sprintf("return %s.command('add-contact','%s',this)",
                            rcmail_output::JS_OBJECT_NAME, rcube::JQ($string)),
          ),
          html::img(array(
            'src' => $CONFIG['skin_path'] . $addicon,
                        'src' => $RCMAIL->config->get('skin_path') . $addicon,
            'alt' => "Add contact",
          )));
      }
@@ -1563,8 +1624,9 @@
        'href' => '#more',
        'class' => 'morelink',
        'onclick' => '$(this).hide().next().show()',
      ), rcube::Q($RCMAIL->gettext(array('name' => 'andnmore', 'vars' => array('nr' => $moreadrs))))) .
      html::span(array('style' => 'display:none'), join(', ', $allvalues));
                ),
                rcube::Q($RCMAIL->gettext(array('name' => 'andnmore', 'vars' => array('nr' => $moreadrs)))))
                . html::span(array('style' => 'display:none'), join(', ', $allvalues));
    }
    else {
      $out .= ' ' . html::a(array(
@@ -1581,7 +1643,6 @@
  return $out;
}
/**
 * Wrap text to a given number of characters per line
@@ -1602,20 +1663,24 @@
  foreach ($lines as $line) {
    // don't wrap already quoted lines
    if ($line[0] == '>')
        if ($line[0] == '>') {
      $line = '>' . rtrim($line);
        }
    else if (mb_strlen($line) > $max) {
      $newline = '';
      foreach (explode("\n", rcube_mime::wordwrap($line, $length - 2)) as $l) {
        if (strlen($l))
          $newline .= '> ' . $l . "\n";
        else
          $newline .= ">\n";
      }
      $line = rtrim($newline);
    }
    else
        else {
      $line = '> ' . $line;
        }
    // Append the line
    $out .= $line . "\n";
@@ -1624,44 +1689,45 @@
  return rtrim($out, "\n");
}
function rcmail_draftinfo_encode($p)
{
  $parts = array();
  foreach ($p as $key => $val)
    foreach ($p as $key => $val) {
    $parts[] = $key . '=' . ($key == 'folder' ? base64_encode($val) : $val);
    }
  return join('; ', $parts);
}
function rcmail_draftinfo_decode($str)
{
  $info = array();
  foreach (preg_split('/;\s+/', $str) as $part) {
    list($key, $val) = explode('=', $part, 2);
    if ($key == 'folder')
        if ($key == 'folder') {
      $val = base64_decode($val);
        }
    $info[$key] = $val;
  }
  return $info;
}
/**
 * clear message composing settings
 */
function rcmail_compose_cleanup($id)
{
  if (!isset($_SESSION['compose_data_'.$id]))
    if (!isset($_SESSION['compose_data_'.$id])) {
    return;
    }
  $rcmail = rcmail::get_instance();
  $rcmail->plugins->exec_hook('attachments_cleanup', array('group' => $id));
  $rcmail->session->remove('compose_data_'.$id);
}
/**
 * Send the MDN response
@@ -1675,12 +1741,13 @@
{
  global $RCMAIL;
  if (!is_object($message) || !is_a($message, 'rcube_message'))
    if (!is_object($message) || !is_a($message, 'rcube_message')) {
    $message = new rcube_message($message);
    }
  if ($message->headers->mdn_to && empty($message->headers->flags['MDNSENT']) &&
    ($RCMAIL->storage->check_permflag('MDNSENT') || $RCMAIL->storage->check_permflag('*')))
  {
        ($RCMAIL->storage->check_permflag('MDNSENT') || $RCMAIL->storage->check_permflag('*'))
    ) {
    $identity  = rcmail_identity_select($message);
    $sender    = format_email_recipient($identity['email'], $identity['name']);
    $recipient = array_shift(rcube_mime::decode_address_list(
@@ -1707,9 +1774,9 @@
      'References' => trim($message->headers->references . ' ' . $message->headers->messageID),
    );
    $report = "Final-Recipient: rfc822; {$identity['email']}\r\n" .
               "Original-Message-ID: {$message->headers->messageID}\r\n" .
               "Disposition: manual-action/MDN-sent-manually; displayed\r\n";
        $report = "Final-Recipient: rfc822; {$identity['email']}\r\n"
            . "Original-Message-ID: {$message->headers->messageID}\r\n"
            . "Disposition: manual-action/MDN-sent-manually; displayed\r\n";
    if ($message->headers->to) {
        $report .= "Original-Recipient: {$message->headers->to}\r\n";
@@ -1731,8 +1798,9 @@
    $compose->setTXTBody(rcube_mime::wordwrap($body, 75, "\r\n"));
    $compose->addAttachment($report, 'message/disposition-notification', 'MDNPart2.txt', false, '7bit', 'inline');
    if ($RCMAIL->config->get('mdn_use_from'))
        if ($RCMAIL->config->get('mdn_use_from')) {
      $options['mdn_use_from'] = true;
        }
    $sent = $RCMAIL->deliver_message($compose, $identity['email'], $mailto, $smtp_error, $body_file, $options);
@@ -1858,11 +1926,13 @@
{
  // Some versions of Outlook create garbage Content-Type:
  // application/pdf.A520491B_3BF7_494D_8855_7FAC2C6C0608
  if (preg_match('/^application\/pdf.+/', $name))
    if (preg_match('/^application\/pdf.+/', $name)) {
    $name = 'application/pdf';
    }
  // treat image/pjpeg (image/pjpg, image/jpg) as image/jpeg (#1489097)
  else if (preg_match('/^image\/p?jpe?g$/', $name))
    else if (preg_match('/^image\/p?jpe?g$/', $name)) {
    $name = 'image/jpeg';
    }
  return $name;
}
@@ -1902,7 +1972,7 @@
function rcmail_search_filter($attrib)
{
  global $RCMAIL, $OUTPUT, $CONFIG;
    global $RCMAIL;
  if (!strlen($attrib['id']))
    $attrib['id'] = 'rcmlistfilter';
@@ -1924,7 +1994,7 @@
  $select_filter->add($RCMAIL->gettext('unread'), 'UNSEEN');
  $select_filter->add($RCMAIL->gettext('flagged'), 'FLAGGED');
  $select_filter->add($RCMAIL->gettext('unanswered'), 'UNANSWERED');
  if (!$CONFIG['skip_deleted']) {
    if (!$RCMAIL->config->get('skip_deleted')) {
    $select_filter->add($RCMAIL->gettext('deleted'), 'DELETED');
    $select_filter->add($RCMAIL->gettext('undeleted'), 'UNDELETED');
  }
@@ -1937,7 +2007,7 @@
  $out = $select_filter->show($_SESSION['search_filter']);
  $OUTPUT->add_gui_object('search_filter', $attrib['id']);
    $RCMAIL->output->add_gui_object('search_filter', $attrib['id']);
  return $out;
}
@@ -1949,9 +2019,11 @@
  // Set env variables for messageerror.html template
  if ($RCMAIL->action == 'show') {
    $mbox_name = $RCMAIL->storage->get_folder();
    $RCMAIL->output->set_env('mailbox', $mbox_name);
    $RCMAIL->output->set_env('uid', null);
  }
  // display error message
  $RCMAIL->output->show_message('messageopenerror', 'error');
  // ... display message error page
@@ -1960,7 +2032,7 @@
function rcmail_message_import_form($attrib = array())
{
  global $OUTPUT, $RCMAIL;
    global $RCMAIL;
  // set defaults
  $attrib += array('id' => 'rcmImportform', 'buttons' => 'yes');
@@ -1976,18 +2048,28 @@
      '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', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))) .
      (rcube_utils::get_boolean($attrib['buttons']) ? html::div('buttons',
        $button->show($RCMAIL->gettext('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()")) . ' ' .
        $button->show($RCMAIL->gettext('upload'), array('class' => 'button mainaction', 'onclick' => rcmail_output::JS_OBJECT_NAME . ".command('import-messages', this.form)"))
      ) : '')
    )
  );
    $content = html::tag('input', array('type' => 'hidden', 'name' => '_unlock', 'value' => ''))
        . html::div(null, $fileinput->show())
        . html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize))));
  $OUTPUT->add_gui_object('importform', $attrib['id'].'Frm');
  return $out;
    if (rcube_utils::get_boolean($attrib['buttons'])) {
        $content .= html::div('buttons',
            $button->show($RCMAIL->gettext('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()"))
            . ' ' .
            $button->show($RCMAIL->gettext('upload'), array(
                'class'   => 'button mainaction',
                'onclick' => rcmail_output::JS_OBJECT_NAME . ".command('import-messages', this.form)"
            )));
    }
    $out = $RCMAIL->output->form_tag(array(
            'id'      => $attrib['id'].'Frm',
            'method'  => 'post',
            'enctype' => 'multipart/form-data'
        ),
        $content);
    $RCMAIL->output->add_gui_object('importform', $attrib['id'].'Frm');
    return html::div($attrib, $out);
}
program/steps/mail/mark.inc
@@ -4,7 +4,7 @@
 | program/steps/mail/mark.inc                                           |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2005-2009, The Roundcube Dev Team                       |
 | 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.                |
@@ -19,8 +19,13 @@
*/
// only process ajax requests
if (!$OUTPUT->ajax_call)
if (!$OUTPUT->ajax_call) {
  return;
}
$threading    = (bool) $RCMAIL->storage->get_threading();
$skip_deleted = (bool) $RCMAIL->config->get('skip_deleted');
$read_deleted = (bool) $RCMAIL->config->get('read_when_deleted');
$a_flags_map = array(
  'undelete' => 'UNDELETED',
@@ -28,15 +33,15 @@
  'read' => 'SEEN',
  'unread' => 'UNSEEN',
  'flagged' => 'FLAGGED',
  'unflagged' => 'UNFLAGGED');
    'unflagged' => 'UNFLAGGED',
);
$threading = (bool) $RCMAIL->storage->get_threading();
if (($uids = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST)) && ($flag = rcube_utils::get_input_value('_flag', rcube_utils::INPUT_POST)))
{
if (($uids = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST))
    && ($flag = rcube_utils::get_input_value('_flag', rcube_utils::INPUT_POST))
) {
  $flag = $a_flags_map[$flag] ? $a_flags_map[$flag] : strtoupper($flag);
  if ($flag == 'DELETED' && $CONFIG['skip_deleted'] && $_POST['_from'] != 'show') {
    if ($flag == 'DELETED' && $skip_deleted && $_POST['_from'] != 'show') {
    // count messages before changing anything
    $old_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL');
    $old_pages = ceil($old_count / $RCMAIL->storage->get_pagesize());
@@ -47,8 +52,10 @@
  if (!$marked) {
    // send error message
    if ($_POST['_from'] != 'show')
        if ($_POST['_from'] != 'show') {
      $OUTPUT->command('list_mailbox');
        }
    $RCMAIL->display_server_error('errormarking');
    $OUTPUT->send();
    exit;
@@ -57,25 +64,28 @@
    $OUTPUT->show_message('messagemarked', 'confirmation');
  }
  if ($flag == 'DELETED' && $CONFIG['read_when_deleted'] && !empty($_POST['_ruid'])) {
    if ($flag == 'DELETED' && $read_deleted && !empty($_POST['_ruid'])) {
    $ruids = rcube_utils::get_input_value('_ruid', rcube_utils::INPUT_POST);
    $read = $RCMAIL->storage->set_flag($ruids, 'SEEN');
    if ($read && !$CONFIG['skip_deleted'])
        if ($read && !$skip_deleted) {
      $OUTPUT->command('flag_deleted_as_read', $ruids);
  }
    }
  if ($flag == 'SEEN' || $flag == 'UNSEEN' || ($flag == 'DELETED' && !$CONFIG['skip_deleted'])) {
    if ($flag == 'SEEN' || $flag == 'UNSEEN' || ($flag == 'DELETED' && !$skip_deleted)) {
    rcmail_send_unread_count($RCMAIL->storage->get_folder());
  }
  else if ($flag == 'DELETED' && $CONFIG['skip_deleted']) {
    else if ($flag == 'DELETED' && $skip_deleted) {
    if ($_POST['_from'] == 'show') {
      if ($next = rcube_utils::get_input_value('_next_uid', rcube_utils::INPUT_GPC))
        $OUTPUT->command('show_message', $next);
      else
        $OUTPUT->command('command', 'list');
    } else {
        }
        else {
      $search_request = rcube_utils::get_input_value('_search', rcube_utils::INPUT_GPC);
      // refresh saved search set after moving some messages
      if ($search_request && $RCMAIL->storage->get_search_set()) {
        $_SESSION['search'] = $RCMAIL->storage->refresh_search();
@@ -110,6 +120,7 @@
        $OUTPUT->command('set_unread_count', $mbox, $unseen_count, ($mbox == 'INBOX'));
        rcmail_set_unseen_count($mbox, $unseen_count);
      }
      $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count), $mbox);
      if ($threading) {
program/steps/mail/pagenav.inc
@@ -35,14 +35,19 @@
    $OUTPUT->set_env('prev_uid', $prev);
    $OUTPUT->command('enable_command', 'previousmessage', 'firstmessage', true);
}
if ($next) {
    $OUTPUT->set_env('next_uid', $next);
    $OUTPUT->command('enable_command', 'nextmessage', 'lastmessage', true);
}
if ($first)
if ($first) {
    $OUTPUT->set_env('first_uid', $first);
if ($last)
}
if ($last) {
    $OUTPUT->set_env('last_uid', $last);
}
// Don't need a real messages count value
$OUTPUT->set_env('messagecount', 1);
@@ -54,4 +59,3 @@
)));
$OUTPUT->send();
program/steps/mail/search.inc
@@ -1,14 +1,18 @@
<?php
/*
 +-----------------------------------------------------------------------+
 | steps/mail/search.inc                                                 |
 |                                                                       |
 | Search functions for rc webmail                                       |
 | 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:                                                              |
 |   Mail messages search action                                         |
 +-----------------------------------------------------------------------+
 | Author: Benjamin Smith <defitro@gmail.com>                            |
 |         Thomas Bruederli <roundcube@gmail.com>                        |
@@ -41,38 +45,31 @@
$_SESSION['search_filter'] = $filter;
// Check the search string for type of search
if (preg_match("/^from:.*/i", $str))
{
if (preg_match("/^from:.*/i", $str)) {
  list(,$srch) = explode(":", $str);
  $subject['from'] = "HEADER FROM";
}
else if (preg_match("/^to:.*/i", $str))
{
else if (preg_match("/^to:.*/i", $str)) {
  list(,$srch) = explode(":", $str);
  $subject['to'] = "HEADER TO";
}
else if (preg_match("/^cc:.*/i", $str))
{
else if (preg_match("/^cc:.*/i", $str)) {
  list(,$srch) = explode(":", $str);
  $subject['cc'] = "HEADER CC";
}
else if (preg_match("/^bcc:.*/i", $str))
{
else if (preg_match("/^bcc:.*/i", $str)) {
  list(,$srch) = explode(":", $str);
  $subject['bcc'] = "HEADER BCC";
}
else if (preg_match("/^subject:.*/i", $str))
{
else if (preg_match("/^subject:.*/i", $str)) {
  list(,$srch) = explode(":", $str);
  $subject['subject'] = "HEADER SUBJECT";
}
else if (preg_match("/^body:.*/i", $str))
{
else if (preg_match("/^body:.*/i", $str)) {
  list(,$srch) = explode(":", $str);
  $subject['body'] = "BODY";
}
else if (strlen(trim($str)))
{
else if (strlen(trim($str))) {
  if ($headers) {
    foreach (explode(',', $headers) as $header) {
      if ($header == 'text') {
@@ -86,8 +83,9 @@
    }
    // save search modifiers for the current folder to user prefs
    $search_mods = $RCMAIL->config->get('search_mods', $SEARCH_MODS_DEFAULT);
        $search_mods        = rcmail_search_mods();
    $search_mods[$mbox] = array_fill_keys(array_keys($subject), 1);
    $RCMAIL->user->save_prefs(array('search_mods' => $search_mods));
  }
  else {
@@ -100,20 +98,23 @@
if (!empty($subject)) {
  $search_str .= str_repeat(' OR', count($subject)-1);
  foreach ($subject as $sub)
    foreach ($subject as $sub) {
    $search_str .= ' ' . $sub . ' ' . rcube_imap_generic::escape($search);
    }
}
$search_str  = trim($search_str);
$sort_column = rcmail_sort_column();
// execute IMAP search
if ($search_str)
if ($search_str) {
  $RCMAIL->storage->search($mbox, $search_str, $imap_charset, $sort_column);
}
// save search results in session
if (!is_array($_SESSION['search']))
if (!is_array($_SESSION['search'])) {
  $_SESSION['search'] = array();
}
if ($search_str) {
  $_SESSION['search'] = $RCMAIL->storage->get_search_set();
@@ -129,8 +130,9 @@
// Make sure we got the headers
if (!empty($result_h)) {
  rcmail_js_message_list($result_h);
  if ($search_str)
    if ($search_str) {
    $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $RCMAIL->storage->count(NULL, 'ALL')));
    }
  // remember last HIGHESTMODSEQ value (if supported)
  // we need it for flag updates in check-recent
program/steps/mail/sendmail.inc
@@ -60,236 +60,6 @@
}
/****** message sending functions ********/
// encrypt parts of the header
function rcmail_encrypt_header($what)
{
    global $RCMAIL;
    if (!$RCMAIL->config->get('http_received_header_encrypt')) {
        return $what;
    }
    return $RCMAIL->encrypt($what);
}
// get identity record
function rcmail_get_identity($id)
{
    global $RCMAIL, $message_charset;
    if ($sql_arr = $RCMAIL->user->get_identity($id)) {
        $out = $sql_arr;
        if ($message_charset != RCUBE_CHARSET) {
            foreach ($out as $k => $v) {
                $out[$k] = rcube_charset::convert($v, RCUBE_CHARSET, $message_charset);
            }
        }
        $out['mailto'] = $sql_arr['email'];
        $out['string'] = format_email_recipient($sql_arr['email'], $sql_arr['name']);
        return $out;
    }
    return false;
}
/**
 * go from this:
 * <img src="http[s]://.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
 *
 * to this:
 *
 * <img src="/path/on/server/.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
 */
function rcmail_fix_emoticon_paths($mime_message)
{
    global $RCMAIL;
    $body = $mime_message->getHTMLBody();
    // remove any null-byte characters before parsing
    $body = preg_replace('/\x00/', '', $body);
    $searchstr = 'program/js/tiny_mce/plugins/emotions/img/';
    $offset = 0;
    // keep track of added images, so they're only added once
    $included_images = array();
    if (preg_match_all('# src=[\'"]([^\'"]+)#', $body, $matches, PREG_OFFSET_CAPTURE)) {
        foreach ($matches[1] as $m) {
            // find emoticon image tags
            if (preg_match('#'.$searchstr.'(.*)$#', $m[0], $imatches)) {
                $image_name = $imatches[1];
                // sanitize image name so resulting attachment doesn't leave images dir
                $image_name = preg_replace('/[^a-zA-Z0-9_\.\-]/i', '', $image_name);
                $img_file   = INSTALL_PATH . '/' . $searchstr . $image_name;
                if (! in_array($image_name, $included_images)) {
                    // add the image to the MIME message
                    if (!$mime_message->addHTMLImage($img_file, 'image/gif', '', true, $image_name)) {
                        $RCMAIL->output->show_message("emoticonerror", 'error');
                    }
                    array_push($included_images, $image_name);
                }
                $body    = substr_replace($body, $img_file, $m[1] + $offset, strlen($m[0]));
                $offset += strlen($img_file) - strlen($m[0]);
            }
        }
    }
    $mime_message->setHTMLBody($body);
}
/**
 * Extract image attachments from HTML content (data URIs)
 */
function rcmail_extract_inline_images($mime_message, $from)
{
    $body   = $mime_message->getHTMLBody();
    $offset = 0;
    $list   = array();
    $regexp = '# src=[\'"](data:(image/[a-z]+);base64,([a-z0-9+/=\r\n]+))([\'"])#i';
    // get domain for the Content-ID, must be the same as in Mail_Mime::get()
    if (preg_match('#@([0-9a-zA-Z\-\.]+)#', $from, $matches)) {
        $domain = $matches[1];
    } else {
        $domain = 'localhost';
    }
    if (preg_match_all($regexp, $body, $matches, PREG_OFFSET_CAPTURE)) {
        foreach ($matches[1] as $idx => $m) {
            $data = preg_replace('/\r\n/', '', $matches[3][$idx][0]);
            $data = base64_decode($data);
            if (empty($data)) {
                continue;
            }
            $hash      = md5($data) . '@' . $domain;
            $mime_type = $matches[2][$idx][0];
            $name      = $list[$hash];
            // add the image to the MIME message
            if (!$name) {
                $ext         = preg_replace('#^[^/]+/#', '', $mime_type);
                $name        = substr($hash, 0, 8) . '.' . $ext;
                $list[$hash] = $name;
                $mime_message->addHTMLImage($data, $mime_type, $name, false, $hash);
            }
            $body = substr_replace($body, $name, $m[1] + $offset, strlen($m[0]));
            $offset += strlen($name) - strlen($m[0]);
        }
    }
    $mime_message->setHTMLBody($body);
}
/**
 * Parse and cleanup email address input (and count addresses)
 *
 * @param string  Address input
 * @param boolean Do count recipients (saved in global $RECIPIENT_COUNT)
 * @param boolean Validate addresses (errors saved in global $EMAIL_FORMAT_ERROR)
 * @return string Canonical recipients string separated by comma
 */
function rcmail_email_input_format($mailto, $count=false, $check=true)
{
    global $RCMAIL, $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT;
    // simplified email regexp, supporting quoted local part
    $email_regexp = '(\S+|("[^"]+"))@\S+';
    $delim   = trim($RCMAIL->config->get('recipients_separator', ','));
    $regexp  = array("/[,;$delim]\s*[\r\n]+/", '/[\r\n]+/', "/[,;$delim]\s*\$/m", '/;/', '/(\S{1})(<'.$email_regexp.'>)/U');
    $replace = array($delim.' ', ', ', '', $delim, '\\1 \\2');
    // replace new lines and strip ending ', ', make address input more valid
    $mailto = trim(preg_replace($regexp, $replace, $mailto));
    $items  = rcube_utils::explode_quoted_string($delim, $mailto);
    $result = array();
    foreach ($items as $item) {
        $item = trim($item);
        // address in brackets without name (do nothing)
        if (preg_match('/^<'.$email_regexp.'>$/', $item)) {
            $item     = rcube_utils::idn_to_ascii(trim($item, '<>'));
            $result[] = $item;
        }
        // address without brackets and without name (add brackets)
        else if (preg_match('/^'.$email_regexp.'$/', $item)) {
            $item     = rcube_utils::idn_to_ascii($item);
            $result[] = $item;
        }
        // address with name (handle name)
        else if (preg_match('/<*'.$email_regexp.'>*$/', $item, $matches)) {
            $address = $matches[0];
            $name    = trim(str_replace($address, '', $item));
            if ($name[0] == '"' && $name[count($name)-1] == '"') {
                $name = substr($name, 1, -1);
            }
            $name     = stripcslashes($name);
            $address  = rcube_utils::idn_to_ascii(trim($address, '<>'));
            $result[] = format_email_recipient($address, $name);
            $item     = $address;
        }
        else if (trim($item)) {
            continue;
        }
        // check address format
        $item = trim($item, '<>');
        if ($item && $check && !rcube_utils::check_email($item)) {
            $EMAIL_FORMAT_ERROR = $item;
            return;
        }
    }
    if ($count) {
        $RECIPIENT_COUNT += count($result);
    }
    return implode(', ', $result);
}
function rcmail_generic_message_footer($isHtml)
{
    global $RCMAIL;
    if ($isHtml && ($file = $RCMAIL->config->get('generic_message_footer_html'))) {
        $html_footer = true;
    }
    else {
        $file = $RCMAIL->config->get('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 (empty($COMPOSE['param']['message-id'])) {
@@ -911,3 +681,233 @@
}
$OUTPUT->send('iframe');
/****** message sending functions ********/
// encrypt parts of the header
function rcmail_encrypt_header($what)
{
    global $RCMAIL;
    if (!$RCMAIL->config->get('http_received_header_encrypt')) {
        return $what;
    }
    return $RCMAIL->encrypt($what);
}
// get identity record
function rcmail_get_identity($id)
{
    global $RCMAIL, $message_charset;
    if ($sql_arr = $RCMAIL->user->get_identity($id)) {
        $out = $sql_arr;
        if ($message_charset != RCUBE_CHARSET) {
            foreach ($out as $k => $v) {
                $out[$k] = rcube_charset::convert($v, RCUBE_CHARSET, $message_charset);
            }
        }
        $out['mailto'] = $sql_arr['email'];
        $out['string'] = format_email_recipient($sql_arr['email'], $sql_arr['name']);
        return $out;
    }
    return false;
}
/**
 * go from this:
 * <img src="http[s]://.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
 *
 * to this:
 *
 * <img src="/path/on/server/.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
 */
function rcmail_fix_emoticon_paths($mime_message)
{
    global $RCMAIL;
    $body = $mime_message->getHTMLBody();
    // remove any null-byte characters before parsing
    $body = preg_replace('/\x00/', '', $body);
    $searchstr = 'program/js/tiny_mce/plugins/emotions/img/';
    $offset = 0;
    // keep track of added images, so they're only added once
    $included_images = array();
    if (preg_match_all('# src=[\'"]([^\'"]+)#', $body, $matches, PREG_OFFSET_CAPTURE)) {
        foreach ($matches[1] as $m) {
            // find emoticon image tags
            if (preg_match('#'.$searchstr.'(.*)$#', $m[0], $imatches)) {
                $image_name = $imatches[1];
                // sanitize image name so resulting attachment doesn't leave images dir
                $image_name = preg_replace('/[^a-zA-Z0-9_\.\-]/i', '', $image_name);
                $img_file   = INSTALL_PATH . '/' . $searchstr . $image_name;
                if (! in_array($image_name, $included_images)) {
                    // add the image to the MIME message
                    if (!$mime_message->addHTMLImage($img_file, 'image/gif', '', true, $image_name)) {
                        $RCMAIL->output->show_message("emoticonerror", 'error');
                    }
                    array_push($included_images, $image_name);
                }
                $body    = substr_replace($body, $img_file, $m[1] + $offset, strlen($m[0]));
                $offset += strlen($img_file) - strlen($m[0]);
            }
        }
    }
    $mime_message->setHTMLBody($body);
}
/**
 * Extract image attachments from HTML content (data URIs)
 */
function rcmail_extract_inline_images($mime_message, $from)
{
    $body   = $mime_message->getHTMLBody();
    $offset = 0;
    $list   = array();
    $regexp = '# src=[\'"](data:(image/[a-z]+);base64,([a-z0-9+/=\r\n]+))([\'"])#i';
    // get domain for the Content-ID, must be the same as in Mail_Mime::get()
    if (preg_match('#@([0-9a-zA-Z\-\.]+)#', $from, $matches)) {
        $domain = $matches[1];
    } else {
        $domain = 'localhost';
    }
    if (preg_match_all($regexp, $body, $matches, PREG_OFFSET_CAPTURE)) {
        foreach ($matches[1] as $idx => $m) {
            $data = preg_replace('/\r\n/', '', $matches[3][$idx][0]);
            $data = base64_decode($data);
            if (empty($data)) {
                continue;
            }
            $hash      = md5($data) . '@' . $domain;
            $mime_type = $matches[2][$idx][0];
            $name      = $list[$hash];
            // add the image to the MIME message
            if (!$name) {
                $ext         = preg_replace('#^[^/]+/#', '', $mime_type);
                $name        = substr($hash, 0, 8) . '.' . $ext;
                $list[$hash] = $name;
                $mime_message->addHTMLImage($data, $mime_type, $name, false, $hash);
            }
            $body = substr_replace($body, $name, $m[1] + $offset, strlen($m[0]));
            $offset += strlen($name) - strlen($m[0]);
        }
    }
    $mime_message->setHTMLBody($body);
}
/**
 * Parse and cleanup email address input (and count addresses)
 *
 * @param string  Address input
 * @param boolean Do count recipients (saved in global $RECIPIENT_COUNT)
 * @param boolean Validate addresses (errors saved in global $EMAIL_FORMAT_ERROR)
 * @return string Canonical recipients string separated by comma
 */
function rcmail_email_input_format($mailto, $count=false, $check=true)
{
    global $RCMAIL, $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT;
    // simplified email regexp, supporting quoted local part
    $email_regexp = '(\S+|("[^"]+"))@\S+';
    $delim   = trim($RCMAIL->config->get('recipients_separator', ','));
    $regexp  = array("/[,;$delim]\s*[\r\n]+/", '/[\r\n]+/', "/[,;$delim]\s*\$/m", '/;/', '/(\S{1})(<'.$email_regexp.'>)/U');
    $replace = array($delim.' ', ', ', '', $delim, '\\1 \\2');
    // replace new lines and strip ending ', ', make address input more valid
    $mailto = trim(preg_replace($regexp, $replace, $mailto));
    $items  = rcube_utils::explode_quoted_string($delim, $mailto);
    $result = array();
    foreach ($items as $item) {
        $item = trim($item);
        // address in brackets without name (do nothing)
        if (preg_match('/^<'.$email_regexp.'>$/', $item)) {
            $item     = rcube_utils::idn_to_ascii(trim($item, '<>'));
            $result[] = $item;
        }
        // address without brackets and without name (add brackets)
        else if (preg_match('/^'.$email_regexp.'$/', $item)) {
            $item     = rcube_utils::idn_to_ascii($item);
            $result[] = $item;
        }
        // address with name (handle name)
        else if (preg_match('/<*'.$email_regexp.'>*$/', $item, $matches)) {
            $address = $matches[0];
            $name    = trim(str_replace($address, '', $item));
            if ($name[0] == '"' && $name[count($name)-1] == '"') {
                $name = substr($name, 1, -1);
            }
            $name     = stripcslashes($name);
            $address  = rcube_utils::idn_to_ascii(trim($address, '<>'));
            $result[] = format_email_recipient($address, $name);
            $item     = $address;
        }
        else if (trim($item)) {
            continue;
        }
        // check address format
        $item = trim($item, '<>');
        if ($item && $check && !rcube_utils::check_email($item)) {
            $EMAIL_FORMAT_ERROR = $item;
            return;
        }
    }
    if ($count) {
        $RECIPIENT_COUNT += count($result);
    }
    return implode(', ', $result);
}
function rcmail_generic_message_footer($isHtml)
{
    global $RCMAIL;
    if ($isHtml && ($file = $RCMAIL->config->get('generic_message_footer_html'))) {
        $html_footer = true;
    }
    else {
        $file = $RCMAIL->config->get('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;
}
program/steps/mail/show.inc
@@ -5,7 +5,7 @@
 | program/steps/mail/show.inc                                           |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2005-2009, The Roundcube Dev Team                       |
 | 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.                |
@@ -58,20 +58,36 @@
  rcmail_check_safe($MESSAGE);
  // set message charset as default
  if (!empty($MESSAGE->headers->charset))
    if (!empty($MESSAGE->headers->charset)) {
    $RCMAIL->storage->set_charset($MESSAGE->headers->charset);
    }
  $OUTPUT->set_pagetitle(abbreviate_string($MESSAGE->subject, 128, '...', true));
  // give message uid to the client
    // set message environment
  $OUTPUT->set_env('uid', $MESSAGE->uid);
  // set environement
  $OUTPUT->set_env('safemode', $MESSAGE->is_safe);
  $OUTPUT->set_env('sender', $MESSAGE->sender['string']);
  $OUTPUT->set_env('permaurl', $RCMAIL->url(array('_action' => 'show', '_uid' => $MESSAGE->uid, '_mbox' => $mbox_name)));
  $OUTPUT->set_env('delimiter', $RCMAIL->storage->get_hierarchy_delimiter());
  $OUTPUT->set_env('mailbox', $mbox_name);
  $OUTPUT->set_env('compose_extwin', $RCMAIL->config->get('compose_extwin',false));
    $OUTPUT->set_env('permaurl', $RCMAIL->url(array('_action' => 'show', '_uid' => $MESSAGE->uid, '_mbox' => $mbox_name)));
    if ($MESSAGE->headers->get('list-post', false)) {
        $OUTPUT->set_env('list_post', true);
    }
    // set environment
    $OUTPUT->set_env('delimiter', $RCMAIL->storage->get_hierarchy_delimiter());
    // set configuration
    $RCMAIL->set_env_config(array('delete_junk', 'flag_for_deletion', 'read_when_deleted',
        'skip_deleted', 'display_next', 'compose_extwin', 'forward_attachment'));
    // set special folders
    foreach (array('drafts', 'trash', 'junk') as $mbox) {
        if ($folder = $RCMAIL->config->get($mbox . '_mbox')) {
            $OUTPUT->set_env($mbox . '_mailbox', $folder);
        }
    }
  // mimetypes supported by the browser (default settings)
  $mimetypes = (array)$RCMAIL->config->get('client_mimetypes');
@@ -93,34 +109,14 @@
  $OUTPUT->set_env('mimetypes', array_values($mimetypes));
  if ($CONFIG['drafts_mbox'])
    $OUTPUT->set_env('drafts_mailbox', $CONFIG['drafts_mbox']);
  if ($CONFIG['trash_mbox'])
    $OUTPUT->set_env('trash_mailbox', $CONFIG['trash_mbox']);
  if ($CONFIG['junk_mbox'])
    $OUTPUT->set_env('junk_mailbox', $CONFIG['junk_mbox']);
  if ($CONFIG['delete_junk'])
    $OUTPUT->set_env('delete_junk', true);
  if ($CONFIG['flag_for_deletion'])
    $OUTPUT->set_env('flag_for_deletion', true);
  if ($CONFIG['read_when_deleted'])
    $OUTPUT->set_env('read_when_deleted', true);
  if ($CONFIG['skip_deleted'])
    $OUTPUT->set_env('skip_deleted', true);
  if ($CONFIG['display_next'])
    $OUTPUT->set_env('display_next', true);
  if ($MESSAGE->headers->get('list-post', false))
    $OUTPUT->set_env('list_post', true);
  if ($CONFIG['forward_attachment'])
    $OUTPUT->set_env('forward_attachment', true);
    if ($MESSAGE->has_html_part()) {
        $prefer_html = $RCMAIL->config->get('prefer_html');
        $OUTPUT->set_env('optional_format', $prefer_html ? 'text' : 'html');
    }
  if (!$OUTPUT->ajax_call)
    if (!$OUTPUT->ajax_call) {
    $OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash',
      'movingmessage', 'deletingmessage', 'markingmessage', 'replyall', 'replylist');
  $prefer_html = $RCMAIL->config->get('prefer_html');
  if ($MESSAGE->has_html_part()) {
    $OUTPUT->set_env('optional_format', $prefer_html ? 'text' : 'html');
  }
  // check for unset disposition notification
@@ -128,10 +124,10 @@
      && empty($MESSAGE->headers->flags['MDNSENT'])
      && empty($MESSAGE->headers->flags['SEEN'])
      && ($RCMAIL->storage->check_permflag('MDNSENT') || $RCMAIL->storage->check_permflag('*'))
      && $mbox_name != $CONFIG['drafts_mbox']
      && $mbox_name != $CONFIG['sent_mbox']
        && $mbox_name != $RCMAIL->config->get('drafts_mbox')
        && $mbox_name != $RCMAIL->config->get('sent_mbox')
  ) {
    $mdn_cfg = intval($CONFIG['mdn_requests']);
        $mdn_cfg = intval($RCMAIL->config->get('mdn_requests'));
    if ($mdn_cfg == 1 || (($mdn_cfg == 3 || $mdn_cfg ==  4) && rcmail_contact_exists($MESSAGE->sender['mailto']))) {
      // Send MDN
@@ -150,12 +146,45 @@
  }
  if (empty($MESSAGE->headers->flags['SEEN'])
    && ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($CONFIG['preview_pane_mark_read']) == 0))
        && ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($RCMAIL->config->get('preview_pane_mark_read')) == 0))
  ) {
    $RCMAIL->plugins->exec_hook('message_read', array('uid' => $MESSAGE->uid,
      'mailbox' => $mbox_name, 'message' => $MESSAGE));
        $RCMAIL->plugins->exec_hook('message_read', array(
            'uid'     => $MESSAGE->uid,
            'mailbox' => $mbox_name,
            'message' => $MESSAGE,
        ));
  }
}
$OUTPUT->add_handlers(array(
    'messageattachments' => 'rcmail_message_attachments',
    'mailboxname'        => 'rcmail_mailbox_name_display',
    'messageobjects'     => 'rcmail_message_objects',
    'contactphoto'       => 'rcmail_message_contactphoto',
));
if ($RCMAIL->action == 'print' && $OUTPUT->template_exists('messageprint'))
    $OUTPUT->send('messageprint', false);
else if ($RCMAIL->action == 'preview' && $OUTPUT->template_exists('messagepreview'))
    $OUTPUT->send('messagepreview', false);
else
    $OUTPUT->send('message', false);
// mark message as read
if ($MESSAGE && $MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN']) &&
    ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($RCMAIL->config->get('preview_pane_mark_read')) == 0))
) {
    if ($RCMAIL->storage->set_flag($MESSAGE->uid, 'SEEN')) {
        if ($count = rcmail_get_unseen_count($mbox_name)) {
            rcmail_set_unseen_count($mbox_name, $count - 1);
        }
    }
}
exit;
@@ -193,6 +222,7 @@
            'onmouseover' => $title ? '' : 'rcube_webmail.long_subject_title_ex(this, 0)',
            'title' => rcube::Q($title),
            ), rcube::Q($filename));
        $ol .= html::tag('li', array('class' => $class, 'id' => $id), $link);
        $attachments[$attach_prop->mime_id] = $mimetype;
@@ -200,6 +230,7 @@
    }
    $out = html::tag('ul', $attrib, $ol, html::$common_attrib);
    $RCMAIL->output->set_env('attachments', $attachments);
  }
@@ -215,15 +246,24 @@
  $attrib['style'] = 'display: none';
  $msg = rcube::Q($RCMAIL->gettext('blockedimages')) . '&nbsp;';
  $msg .= html::a(array('href' => "#loadimages", 'onclick' => rcmail_output::JS_OBJECT_NAME.".command('load-images')"), rcube::Q($RCMAIL->gettext('showimages')));
    $msg .= html::a(array(
            'href'    => "#loadimages",
            'onclick' => rcmail_output::JS_OBJECT_NAME.".command('load-images')"
        ),
        rcube::Q($RCMAIL->gettext('showimages')));
  // add link to save sender in addressbook and reload message
  if ($MESSAGE->sender['mailto'] && $RCMAIL->config->get('show_images') == 1) {
    $msg .= ' ' . html::a(array('href' => "#alwaysload", 'onclick' => rcmail_output::JS_OBJECT_NAME.".command('always-load')", 'style' => "white-space:nowrap"),
        $msg .= ' ' . html::a(array(
                'href'    => "#alwaysload",
                'onclick' => rcmail_output::JS_OBJECT_NAME.".command('always-load')",
                'style'   => "white-space:nowrap"
            ),
      rcube::Q($RCMAIL->gettext(array('name' => 'alwaysshow', 'vars' => array('sender' => $MESSAGE->sender['mailto'])))));
  }
  $RCMAIL->output->add_gui_object('remoteobjectsmsg', $attrib['id']);
  return html::div($attrib, $msg);
}
@@ -244,7 +284,11 @@
  $attrib['class'] = 'notice';
  $msg = rcube::Q($RCMAIL->gettext('isdraft')) . '&nbsp;';
  $msg .= html::a(array('href' => "#edit", 'onclick' => rcmail_output::JS_OBJECT_NAME.".command('edit')"), rcube::Q($RCMAIL->gettext('edit')));
    $msg .= html::a(array(
            'href'    => "#edit",
            'onclick' => rcmail_output::JS_OBJECT_NAME.".command('edit')"
        ),
        rcube::Q($RCMAIL->gettext('edit')));
  return html::div($attrib, $msg);
}
@@ -293,41 +337,18 @@
  global $RCMAIL, $MESSAGE;
  $placeholder = $attrib['placeholder'] ? $RCMAIL->config->get('skin_path') . $attrib['placeholder'] : null;
  if ($MESSAGE->sender)
    $photo_img = $RCMAIL->url(array('_task' => 'addressbook', '_action' => 'photo', '_email' => $MESSAGE->sender['mailto'], '_alt' => $placeholder));
  else
    if ($MESSAGE->sender) {
        $photo_img = $RCMAIL->url(array(
            '_task'   => 'addressbook',
            '_action' => 'photo',
            '_email'  => $MESSAGE->sender['mailto'],
            '_alt'    => $placeholder
        ));
    }
    else {
    $photo_img = $placeholder ? $placeholder : 'program/resources/blank.gif';
    }
  return html::img(array('src' => $photo_img) + $attrib);
}
$OUTPUT->add_handlers(array(
  'messageattachments' => 'rcmail_message_attachments',
  'mailboxname' => 'rcmail_mailbox_name_display',
  'messageobjects' => 'rcmail_message_objects',
  'contactphoto' => 'rcmail_message_contactphoto',
));
if ($RCMAIL->action == 'print' && $OUTPUT->template_exists('messageprint'))
  $OUTPUT->send('messageprint', false);
else if ($RCMAIL->action == 'preview' && $OUTPUT->template_exists('messagepreview'))
  $OUTPUT->send('messagepreview', false);
else
  $OUTPUT->send('message', false);
// mark message as read
if ($MESSAGE && $MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN']) &&
  ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($CONFIG['preview_pane_mark_read']) == 0)))
{
  if ($RCMAIL->storage->set_flag($MESSAGE->uid, 'SEEN')) {
    if ($count = rcmail_get_unseen_count($mbox_name)) {
      rcmail_set_unseen_count($mbox_name, $count - 1);
    }
  }
}
exit;
program/steps/mail/viewsource.inc
@@ -5,7 +5,7 @@
 | program/steps/mail/viewsource.inc                                     |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2005-2009, The Roundcube Dev Team                       |
 | 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.                |
@@ -22,10 +22,10 @@
ob_end_clean();
// similar code as in program/steps/mail/get.inc
if ($uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_GET))
{
if ($uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_GET)) {
  $headers = $RCMAIL->storage->get_message_headers($uid);
  $charset = $headers->charset ? $headers->charset : $CONFIG['default_charset'];
    $charset = $headers->charset ? $headers->charset : $RCMAIL->config->get('default_charset');
  header("Content-Type: text/plain; charset={$charset}");
  if (!empty($_GET['_save'])) {
@@ -46,15 +46,15 @@
  $RCMAIL->storage->print_raw_body($uid, empty($_GET['_save']));
}
else
{
else {
  rcube::raise_error(array(
      'code' => 500,
      'type' => 'php',
      'file' => __FILE__, 'line' => __LINE__,
      'message' => 'Message UID '.$uid.' not found'),
            'file'    => __FILE__,
            'line'    => __LINE__,
            'message' => "Message UID $uid not found"
        ),
    true, true);
}
exit;
program/steps/settings/folders.inc
@@ -5,7 +5,7 @@
 | program/steps/settings/folders.inc                                    |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2005-2009, The Roundcube Dev Team                       |
 | 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.                |
@@ -26,9 +26,9 @@
$STORAGE = $RCMAIL->get_storage();
// subscribe mailbox
if ($RCMAIL->action == 'subscribe')
{
if ($RCMAIL->action == 'subscribe') {
    $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true, 'UTF7-IMAP');
    if (strlen($mbox)) {
        $result = $STORAGE->subscribe(array($mbox));
@@ -56,10 +56,8 @@
            $RCMAIL->display_server_error('errorsaving');
    }
}
// unsubscribe mailbox
else if ($RCMAIL->action == 'unsubscribe')
{
else if ($RCMAIL->action == 'unsubscribe') {
    $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true, 'UTF7-IMAP');
    if (strlen($mbox)) {
        $result = $STORAGE->unsubscribe(array($mbox));
@@ -69,10 +67,8 @@
            $RCMAIL->display_server_error('errorsaving');
    }
}
// delete an existing mailbox
else if ($RCMAIL->action == 'delete-folder')
{
else if ($RCMAIL->action == 'delete-folder') {
    $mbox_utf8 = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
    $mbox      = rcube_charset::convert($mbox_utf8, RCUBE_CHARSET, 'UTF7-IMAP');
@@ -104,10 +100,8 @@
        $RCMAIL->display_server_error('errorsaving');
    }
}
// rename an existing mailbox
else if ($RCMAIL->action == 'rename-folder')
{
else if ($RCMAIL->action == 'rename-folder') {
    $name_utf8    = trim(rcube_utils::get_input_value('_folder_newname', rcube_utils::INPUT_POST, true));
    $oldname_utf8 = rcube_utils::get_input_value('_folder_oldname', rcube_utils::INPUT_POST, true);
@@ -125,17 +119,16 @@
        $RCMAIL->display_server_error('errorsaving');
    }
}
// clear mailbox
else if ($RCMAIL->action == 'purge')
{
else if ($RCMAIL->action == 'purge') {
    $mbox_utf8 = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
    $mbox      = rcube_charset::convert($mbox_utf8, RCUBE_CHARSET, 'UTF7-IMAP');
    $delimiter = $STORAGE->get_hierarchy_delimiter();
    $trash_regexp = '/^' . preg_quote($CONFIG['trash_mbox'] . $delimiter, '/') . '/';
    $trash_mbox   = $RCMAIL->config->get('trash_mbox');
    $trash_regexp = '/^' . preg_quote($trash . $delimiter, '/') . '/';
    // we should only be purging trash (or their subfolders)
    if (!strlen($CONFIG['trash_mbox']) || $mbox == $CONFIG['trash_mbox']
    if (!strlen($trash_mbox) || $mbox === $trash_mbox
        || preg_match($trash_regexp, $mbox)
    ) {
        $success = $STORAGE->delete_message('*', $mbox);
@@ -143,7 +136,7 @@
    }
    // copy to Trash
    else {
        $success = $STORAGE->move_message('1:*', $CONFIG['trash_mbox'], $mbox);
        $success = $STORAGE->move_message('1:*', $trash_mbox, $mbox);
        $delete = false;
    }
@@ -163,10 +156,8 @@
        $RCMAIL->display_server_error('errorsaving');
    }
}
// get mailbox size
else if ($RCMAIL->action == 'folder-size')
{
else if ($RCMAIL->action == 'folder-size') {
    $name = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
    $size = $STORAGE->folder_size($name);
@@ -181,8 +172,29 @@
    }
}
if ($OUTPUT->ajax_call)
if ($OUTPUT->ajax_call) {
    $OUTPUT->send();
}
$OUTPUT->set_pagetitle($RCMAIL->gettext('folders'));
$OUTPUT->include_script('list.js');
$OUTPUT->set_env('prefix_ns', $STORAGE->get_namespace('prefix'));
if ($STORAGE->get_capability('QUOTA')) {
    $OUTPUT->set_env('quota', true);
}
// add some labels to client
$OUTPUT->add_label('deletefolderconfirm', 'purgefolderconfirm', 'folderdeleting',
    'foldermoving', 'foldersubscribing', 'folderunsubscribing', 'quota');
// register UI objects
$OUTPUT->add_handlers(array(
    'foldersubscription' => 'rcube_subscription_form',
    'folderframe'        => 'rcmail_folder_frame',
    'quotadisplay'       => array($RCMAIL, 'quota_display'),
));
$OUTPUT->send('folders');
// build table with all folders listed by server
@@ -417,23 +429,3 @@
    return false;
}
$OUTPUT->set_pagetitle($RCMAIL->gettext('folders'));
$OUTPUT->include_script('list.js');
$OUTPUT->set_env('prefix_ns', $STORAGE->get_namespace('prefix'));
if ($STORAGE->get_capability('QUOTA')) {
    $OUTPUT->set_env('quota', true);
}
// add some labels to client
$OUTPUT->add_label('deletefolderconfirm', 'purgefolderconfirm', 'folderdeleting',
    'foldermoving', 'foldersubscribing', 'folderunsubscribing', 'quota');
// register UI objects
$OUTPUT->add_handlers(array(
    'foldersubscription' => 'rcube_subscription_form',
    'folderframe'        => 'rcmail_folder_frame',
    'quotadisplay'       => array($RCMAIL, 'quota_display'),
));
$OUTPUT->send('folders');