Show spam aliases #
This commit is contained in:
128
data/web/rc/program/steps/addressbook/copy.inc
Normal file
128
data/web/rc/program/steps/addressbook/copy.inc
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/copy.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2007-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Copy a contact record from one direcotry to another |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// only process ajax requests
|
||||
if (!$OUTPUT->ajax_call)
|
||||
return;
|
||||
|
||||
|
||||
$cids = rcmail_get_cids();
|
||||
$target = rcube_utils::get_input_value('_to', rcube_utils::INPUT_POST);
|
||||
$target_group = rcube_utils::get_input_value('_togid', rcube_utils::INPUT_POST);
|
||||
|
||||
$success = 0;
|
||||
$errormsg = 'copyerror';
|
||||
$maxnum = $RCMAIL->config->get('max_group_members', 0);
|
||||
|
||||
foreach ($cids as $source => $cid) {
|
||||
// Something wrong, target not specified
|
||||
if (!strlen($target)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// It maight happen when copying records from search result
|
||||
// Do nothing, go to next source
|
||||
if ((string)$target == (string)$source) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$CONTACTS = $RCMAIL->get_address_book($source);
|
||||
$TARGET = $RCMAIL->get_address_book($target);
|
||||
|
||||
if (!$TARGET || !$TARGET->ready || $TARGET->readonly) {
|
||||
break;
|
||||
}
|
||||
|
||||
$ids = array();
|
||||
|
||||
foreach ($cid as $cid) {
|
||||
$a_record = $CONTACTS->get_record($cid, true);
|
||||
|
||||
// avoid copying groups
|
||||
if ($a_record['_type'] == 'group')
|
||||
continue;
|
||||
|
||||
// Check if contact exists, if so, we'll need it's ID
|
||||
// Note: Some addressbooks allows empty email address field
|
||||
// @TODO: should we check all email addresses?
|
||||
$email = $CONTACTS->get_col_values('email', $a_record, true);
|
||||
if (!empty($email))
|
||||
$result = $TARGET->search('email', $email[0], 1, true, true);
|
||||
else if (!empty($a_record['name']))
|
||||
$result = $TARGET->search('name', $a_record['name'], 1, true, true);
|
||||
else
|
||||
$result = new rcube_result_set();
|
||||
|
||||
// insert contact record
|
||||
if (!$result->count) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('contact_create', array(
|
||||
'record' => $a_record, 'source' => $target, 'group' => $target_group));
|
||||
|
||||
if (!$plugin['abort']) {
|
||||
if ($insert_id = $TARGET->insert($plugin['record'], false)) {
|
||||
$ids[] = $insert_id;
|
||||
$success++;
|
||||
}
|
||||
}
|
||||
else if ($plugin['result']) {
|
||||
$ids = array_merge($ids, $plugin['result']);
|
||||
$success++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$record = $result->first();
|
||||
$ids[] = $record['ID'];
|
||||
$errormsg = empty($email) ? 'contactnameexists' : 'contactexists';
|
||||
}
|
||||
}
|
||||
|
||||
// assign to group
|
||||
if ($target_group && $TARGET->groups && !empty($ids)) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('group_addmembers', array(
|
||||
'group_id' => $target_group, 'ids' => $ids, 'source' => $target));
|
||||
|
||||
if (!$plugin['abort']) {
|
||||
$TARGET->reset();
|
||||
$TARGET->set_group($target_group);
|
||||
|
||||
if ($maxnum && ($TARGET->count()->count + count($plugin['ids']) > $maxnum)) {
|
||||
$OUTPUT->show_message('maxgroupmembersreached', 'warning', array('max' => $maxnum));
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
if (($cnt = $TARGET->add_to_group($target_group, $plugin['ids'])) && $cnt > $success)
|
||||
$success = $cnt;
|
||||
}
|
||||
else if ($plugin['result']) {
|
||||
$success = $plugin['result'];
|
||||
}
|
||||
|
||||
$errormsg = $plugin['message'] ?: 'copyerror';
|
||||
}
|
||||
}
|
||||
|
||||
if (!$success)
|
||||
$OUTPUT->show_message($errormsg, 'error');
|
||||
else
|
||||
$OUTPUT->show_message('copysuccess', 'notice', array('nr' => $success));
|
||||
|
||||
// send response
|
||||
$OUTPUT->send();
|
154
data/web/rc/program/steps/addressbook/delete.inc
Normal file
154
data/web/rc/program/steps/addressbook/delete.inc
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/delete.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Delete the submitted contacts (CIDs) from the users address book |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// process ajax requests only
|
||||
if (!$OUTPUT->ajax_call) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cids = rcmail_get_cids(null, rcube_utils::INPUT_POST);
|
||||
$delcnt = 0;
|
||||
|
||||
// remove previous deletes
|
||||
$undo_time = $RCMAIL->config->get('undo_timeout', 0);
|
||||
$RCMAIL->session->remove('contact_undo');
|
||||
|
||||
foreach ($cids as $source => $cid) {
|
||||
$CONTACTS = rcmail_contact_source($source);
|
||||
|
||||
if ($CONTACTS->readonly) {
|
||||
// more sources? do nothing, probably we have search results from
|
||||
// more than one source, some of these sources can be readonly
|
||||
if (count($cids) == 1) {
|
||||
$OUTPUT->show_message('contactdelerror', 'error');
|
||||
$OUTPUT->command('list_contacts');
|
||||
$OUTPUT->send();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('contact_delete', array(
|
||||
'id' => $cid, 'source' => $source));
|
||||
|
||||
$deleted = !$plugin['abort'] ? $CONTACTS->delete($cid, $undo_time < 1) : $plugin['result'];
|
||||
|
||||
if (!$deleted) {
|
||||
if ($plugin['message']) {
|
||||
$error = $plugin['message'];
|
||||
}
|
||||
else if (($error = $CONTACTS->get_error()) && $error['message']) {
|
||||
$error = $error['message'];
|
||||
}
|
||||
else {
|
||||
$error = 'contactdelerror';
|
||||
}
|
||||
|
||||
$source = rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC);
|
||||
$group = rcube_utils::get_input_value('_gid', rcube_utils::INPUT_GPC);
|
||||
|
||||
$OUTPUT->show_message($error, 'error');
|
||||
$OUTPUT->command('list_contacts', $source, $group);
|
||||
$OUTPUT->send();
|
||||
}
|
||||
else {
|
||||
$delcnt += $deleted;
|
||||
|
||||
// store deleted contacts IDs in session for undo action
|
||||
if ($undo_time > 0 && $CONTACTS->undelete) {
|
||||
$_SESSION['contact_undo']['data'][$source] = $cid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($_SESSION['contact_undo'])) {
|
||||
$_SESSION['contact_undo']['ts'] = time();
|
||||
$msg = html::span(null, $RCMAIL->gettext('contactdeleted'))
|
||||
. ' ' . html::a(array('onclick' => rcmail_output::JS_OBJECT_NAME.".command('undo', '', this)"), $RCMAIL->gettext('undo'));
|
||||
|
||||
$OUTPUT->show_message($msg, 'confirmation', null, true, $undo_time);
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message('contactdeleted', 'confirmation');
|
||||
}
|
||||
|
||||
$page = isset($_SESSION['page']) ? $_SESSION['page'] : 1;
|
||||
|
||||
// update saved search after data changed
|
||||
if (($records = rcmail_search_update(true)) !== false) {
|
||||
// create resultset object
|
||||
$count = count($records);
|
||||
$first = ($page-1) * $PAGE_SIZE;
|
||||
$result = new rcube_result_set($count, $first);
|
||||
$pages = ceil((count($records) + $delcnt) / $PAGE_SIZE);
|
||||
|
||||
// last page and it's empty, display previous one
|
||||
if ($result->count && $result->count <= ($PAGE_SIZE * ($page - 1))) {
|
||||
$OUTPUT->command('list_page', 'prev');
|
||||
$rowcount = $RCMAIL->gettext('loading');
|
||||
}
|
||||
// get records from the next page to add to the list
|
||||
else if ($pages > 1 && $page < $pages) {
|
||||
// sort the records
|
||||
ksort($records, SORT_LOCALE_STRING);
|
||||
|
||||
$first += $PAGE_SIZE;
|
||||
// create resultset object
|
||||
$res = new rcube_result_set($count, $first - $delcnt);
|
||||
|
||||
if ($PAGE_SIZE < $count) {
|
||||
$records = array_slice($records, $first - $delcnt, $delcnt);
|
||||
}
|
||||
|
||||
$res->records = array_values($records);
|
||||
$records = $res;
|
||||
}
|
||||
else {
|
||||
unset($records);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// count contacts for this user
|
||||
$result = $CONTACTS->count();
|
||||
$pages = ceil(($result->count + $delcnt) / $PAGE_SIZE);
|
||||
|
||||
// last page and it's empty, display previous one
|
||||
if ($result->count && $result->count <= ($PAGE_SIZE * ($page - 1))) {
|
||||
$OUTPUT->command('list_page', 'prev');
|
||||
$rowcount = $RCMAIL->gettext('loading');
|
||||
}
|
||||
// get records from the next page to add to the list
|
||||
else if ($pages > 1 && $page < $pages) {
|
||||
$CONTACTS->set_page($page);
|
||||
$records = $CONTACTS->list_records(null, -$delcnt);
|
||||
}
|
||||
}
|
||||
|
||||
// update message count display
|
||||
$OUTPUT->set_env('pagecount', ceil($result->count / $PAGE_SIZE));
|
||||
$OUTPUT->command('set_rowcount', $rowcount ?: rcmail_get_rowcount_text($result));
|
||||
|
||||
// add new rows from next page (if any)
|
||||
if (!empty($records)) {
|
||||
rcmail_js_contacts_list($records);
|
||||
}
|
||||
|
||||
// send response
|
||||
$OUTPUT->send();
|
275
data/web/rc/program/steps/addressbook/edit.inc
Normal file
275
data/web/rc/program/steps/addressbook/edit.inc
Normal file
@@ -0,0 +1,275 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/edit.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Show edit form for a contact entry or to add a new one |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
if ($RCMAIL->action == 'edit') {
|
||||
// Get contact ID and source ID from request
|
||||
$cids = rcmail_get_cids();
|
||||
$source = key($cids);
|
||||
$cid = array_shift($cids[$source]);
|
||||
|
||||
// Initialize addressbook
|
||||
$CONTACTS = rcmail_contact_source($source, true);
|
||||
|
||||
// Contact edit
|
||||
if ($cid && ($record = $CONTACTS->get_record($cid, true))) {
|
||||
$OUTPUT->set_env('cid', $record['ID']);
|
||||
}
|
||||
|
||||
// editing not allowed here
|
||||
if ($CONTACTS->readonly || $record['readonly']) {
|
||||
$OUTPUT->show_message('sourceisreadonly');
|
||||
$RCMAIL->overwrite_action('show');
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$source = rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC);
|
||||
|
||||
if (strlen($source)) {
|
||||
$CONTACTS = $RCMAIL->get_address_book($source, true);
|
||||
}
|
||||
|
||||
if (!$CONTACTS || $CONTACTS->readonly) {
|
||||
$CONTACTS = $RCMAIL->get_address_book(-1, true);
|
||||
$source = $RCMAIL->get_address_book_id($CONTACTS);
|
||||
}
|
||||
|
||||
// Initialize addressbook
|
||||
$CONTACTS = rcmail_contact_source($source, true);
|
||||
}
|
||||
|
||||
$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',
|
||||
));
|
||||
|
||||
$OUTPUT->set_pagetitle($RCMAIL->gettext(($RCMAIL->action == 'add' ? 'addcontact' : 'editcontact')));
|
||||
|
||||
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;
|
||||
|
||||
// check if we have a valid result
|
||||
if ($GLOBALS['EDIT_RECORD']) {
|
||||
$record = $GLOBALS['EDIT_RECORD'];
|
||||
}
|
||||
else if ($RCMAIL->action != 'add'
|
||||
&& !(($result = $CONTACTS->get_result()) && ($record = $result->first()))
|
||||
) {
|
||||
$RCMAIL->output->show_message('contactnotfound', 'error');
|
||||
return false;
|
||||
}
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
function rcmail_contact_edithead($attrib)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
// check if we have a valid result
|
||||
$record = rcmail_get_edit_record();
|
||||
$i_size = $attrib['size'] ?: 20;
|
||||
|
||||
$form = array(
|
||||
'head' => array(
|
||||
'name' => $RCMAIL->gettext('contactnameandorg'),
|
||||
'content' => array(
|
||||
'prefix' => array('size' => $i_size),
|
||||
'firstname' => array('size' => $i_size, 'visible' => true),
|
||||
'middlename' => array('size' => $i_size),
|
||||
'surname' => array('size' => $i_size, 'visible' => true),
|
||||
'suffix' => array('size' => $i_size),
|
||||
'name' => array('size' => 2*$i_size),
|
||||
'nickname' => array('size' => 2*$i_size),
|
||||
'organization' => array('size' => 2*$i_size),
|
||||
'department' => array('size' => 2*$i_size),
|
||||
'jobtitle' => array('size' => 2*$i_size),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
list($form_start, $form_end) = get_form_tags($attrib);
|
||||
unset($attrib['form'], $attrib['name'], $attrib['size']);
|
||||
|
||||
// return the address edit form
|
||||
$out = rcmail_contact_form($form, $record, $attrib);
|
||||
|
||||
return $form_start . $out . $form_end;
|
||||
}
|
||||
|
||||
function rcmail_contact_editform($attrib)
|
||||
{
|
||||
global $RCMAIL, $CONTACT_COLTYPES;
|
||||
|
||||
$record = rcmail_get_edit_record();
|
||||
|
||||
// copy (parsed) address template to client
|
||||
if (preg_match_all('/\{([a-z0-9]+)\}([^{]*)/i', $RCMAIL->config->get('address_template', ''), $templ, PREG_SET_ORDER))
|
||||
$RCMAIL->output->set_env('address_template', $templ);
|
||||
|
||||
$i_size = $attrib['size'] ?: 40;
|
||||
$t_rows = $attrib['textarearows'] ?: 10;
|
||||
$t_cols = $attrib['textareacols'] ?: 40;
|
||||
|
||||
$form = array(
|
||||
'contact' => array(
|
||||
'name' => $RCMAIL->gettext('properties'),
|
||||
'content' => array(
|
||||
'email' => array('size' => $i_size, 'maxlength' => 254, 'visible' => true),
|
||||
'phone' => array('size' => $i_size, 'visible' => true),
|
||||
'address' => array('visible' => true),
|
||||
'website' => array('size' => $i_size),
|
||||
'im' => array('size' => $i_size),
|
||||
),
|
||||
),
|
||||
'personal' => array(
|
||||
'name' => $RCMAIL->gettext('personalinfo'),
|
||||
'content' => array(
|
||||
'gender' => array('visible' => true),
|
||||
'maidenname' => array('size' => $i_size),
|
||||
'birthday' => array('visible' => true),
|
||||
'anniversary' => array(),
|
||||
'manager' => array('size' => $i_size),
|
||||
'assistant' => array('size' => $i_size),
|
||||
'spouse' => array('size' => $i_size),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (isset($CONTACT_COLTYPES['notes'])) {
|
||||
$form['notes'] = array(
|
||||
'name' => $RCMAIL->gettext('notes'),
|
||||
'content' => array(
|
||||
'notes' => array('size' => $t_cols, 'rows' => $t_rows, 'label' => false, 'visible' => true, 'limit' => 1),
|
||||
),
|
||||
'single' => true,
|
||||
);
|
||||
}
|
||||
|
||||
list($form_start, $form_end) = get_form_tags($attrib);
|
||||
unset($attrib['form']);
|
||||
|
||||
// return the complete address edit form as table
|
||||
$out = rcmail_contact_form($form, $record, $attrib);
|
||||
|
||||
return $form_start . $out . $form_end;
|
||||
}
|
||||
|
||||
function rcmail_upload_photo_form($attrib)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
$hidden = new html_hiddenfield(array('name' => '_cid', 'value' => $GLOBALS['cid']));
|
||||
$attrib['prefix'] = $hidden->show();
|
||||
$input_attr = array('name' => '_photo', 'accept' => 'image/*');
|
||||
|
||||
$RCMAIL->output->add_label('addphoto','replacephoto');
|
||||
|
||||
return $RCMAIL->upload_form($attrib, 'uploadform', 'upload-photo', $input_attr);
|
||||
}
|
||||
|
||||
// similar function as in /steps/settings/edit_identity.inc
|
||||
function get_form_tags($attrib)
|
||||
{
|
||||
global $CONTACTS, $EDIT_FORM, $RCMAIL, $SOURCE_ID;
|
||||
|
||||
$form_start = $form_end = '';
|
||||
|
||||
if (empty($EDIT_FORM)) {
|
||||
$hiddenfields = new html_hiddenfield();
|
||||
|
||||
if ($RCMAIL->action == 'edit')
|
||||
$hiddenfields->add(array('name' => '_source', 'value' => $SOURCE_ID));
|
||||
$hiddenfields->add(array('name' => '_gid', 'value' => $CONTACTS->group_id));
|
||||
$hiddenfields->add(array('name' => '_search', 'value' => rcube_utils::get_input_value('_search', rcube_utils::INPUT_GPC)));
|
||||
|
||||
if (($result = $CONTACTS->get_result()) && ($record = $result->first()))
|
||||
$hiddenfields->add(array('name' => '_cid', 'value' => $record['ID']));
|
||||
|
||||
$form_start = $RCMAIL->output->request_form(array(
|
||||
'name' => "form", 'method' => "post",
|
||||
'task' => $RCMAIL->task, 'action' => 'save',
|
||||
'request' => 'save.'.intval($record['ID']),
|
||||
'noclose' => true) + $attrib, $hiddenfields->show());
|
||||
$form_end = !strlen($attrib['form']) ? '</form>' : '';
|
||||
|
||||
$EDIT_FORM = $attrib['form'] ?: 'form';
|
||||
$RCMAIL->output->add_gui_object('editform', $EDIT_FORM);
|
||||
}
|
||||
|
||||
return array($form_start, $form_end);
|
||||
}
|
||||
|
||||
function rcmail_source_selector($attrib)
|
||||
{
|
||||
global $RCMAIL, $SOURCE_ID;
|
||||
|
||||
$sources_list = $RCMAIL->get_address_sources(true, true);
|
||||
|
||||
if (count($sources_list) < 2) {
|
||||
$source = $sources_list[$SOURCE_ID];
|
||||
$hiddenfield = new html_hiddenfield(array('name' => '_source', 'value' => $SOURCE_ID));
|
||||
return html::span($attrib, $source['name'] . $hiddenfield->show());
|
||||
}
|
||||
|
||||
$attrib['name'] = '_source';
|
||||
$attrib['is_escaped'] = true;
|
||||
$attrib['onchange'] = rcmail_output::JS_OBJECT_NAME . ".command('save', 'reload', this.form)";
|
||||
|
||||
$select = new html_select($attrib);
|
||||
|
||||
foreach ($sources_list as $source)
|
||||
$select->add($source['name'], $source['id']);
|
||||
|
||||
return $select->show($SOURCE_ID);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register container as active area to drop photos onto
|
||||
*/
|
||||
function rcmail_photo_drop_area($attrib)
|
||||
{
|
||||
global $OUTPUT;
|
||||
|
||||
if ($attrib['id']) {
|
||||
$OUTPUT->add_gui_object('filedrop', $attrib['id']);
|
||||
$OUTPUT->set_env('filedrop', array('action' => 'upload-photo', 'fieldname' => '_photo', 'single' => 1, 'filter' => '^image/.+'));
|
||||
}
|
||||
}
|
176
data/web/rc/program/steps/addressbook/export.inc
Normal file
176
data/web/rc/program/steps/addressbook/export.inc
Normal file
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/export.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2008-2013, The Roundcube Dev Team |
|
||||
| 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. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Export the selected address book as vCard file |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
| Author: Aleksander Machniak <machniak@kolabsys.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$RCMAIL->request_security_check(rcube_utils::INPUT_GET);
|
||||
|
||||
// Use search result
|
||||
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();
|
||||
|
||||
// Get records from all sources
|
||||
foreach ($search as $s => $set) {
|
||||
$source = $RCMAIL->get_address_book($s);
|
||||
|
||||
// reset page
|
||||
$source->set_page(1);
|
||||
$source->set_pagesize(99999);
|
||||
$source->set_search_set($set);
|
||||
|
||||
// get records
|
||||
$result = $source->list_records();
|
||||
|
||||
while ($record = $result->next()) {
|
||||
// because vcard_map is per-source we need to create vcard here
|
||||
prepare_for_export($record, $source);
|
||||
|
||||
$record['sourceid'] = $s;
|
||||
$key = rcube_addressbook::compose_contact_key($record, $sort_col);
|
||||
$records[$key] = $record;
|
||||
}
|
||||
|
||||
unset($result);
|
||||
}
|
||||
|
||||
// sort the records
|
||||
ksort($records, SORT_LOCALE_STRING);
|
||||
|
||||
// create resultset object
|
||||
$count = count($records);
|
||||
$result = new rcube_result_set($count);
|
||||
$result->records = array_values($records);
|
||||
}
|
||||
// selected contacts
|
||||
else if (!empty($_REQUEST['_cid'])) {
|
||||
$sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
|
||||
$records = array();
|
||||
|
||||
// Selected contact IDs (with multi-source support)
|
||||
$cids = rcmail_get_cids();
|
||||
|
||||
foreach ($cids as $s => $ids) {
|
||||
$source = $RCMAIL->get_address_book($s);
|
||||
$result = $source->search('ID', $ids, 1, true, true);
|
||||
|
||||
while ($record = $result->next()) {
|
||||
// because vcard_map is per-source we need to create vcard here
|
||||
prepare_for_export($record, $source);
|
||||
|
||||
$record['sourceid'] = $s;
|
||||
$key = rcube_addressbook::compose_contact_key($record, $sort_col);
|
||||
$records[$key] = $record;
|
||||
}
|
||||
}
|
||||
|
||||
ksort($records, SORT_LOCALE_STRING);
|
||||
|
||||
// create resultset object
|
||||
$count = count($records);
|
||||
$result = new rcube_result_set($count);
|
||||
$result->records = array_values($records);
|
||||
}
|
||||
// selected directory/group
|
||||
else {
|
||||
$CONTACTS = rcmail_contact_source(null, true);
|
||||
|
||||
// get contacts for this user
|
||||
$CONTACTS->set_page(1);
|
||||
$CONTACTS->set_pagesize(99999);
|
||||
$result = $CONTACTS->list_records(null, 0, true);
|
||||
}
|
||||
|
||||
// Give plugins a possibility to implement other output formats or modify the result
|
||||
$plugin = $RCMAIL->plugins->exec_hook('addressbook_export', array('result' => $result));
|
||||
$result = $plugin['result'];
|
||||
|
||||
if ($plugin['abort']) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// send downlaod headers
|
||||
header('Content-Type: text/vcard; charset=' . RCUBE_CHARSET);
|
||||
header('Content-Disposition: attachment; filename="contacts.vcf"');
|
||||
|
||||
while ($result && ($row = $result->next())) {
|
||||
if ($CONTACTS) {
|
||||
prepare_for_export($row, $CONTACTS);
|
||||
}
|
||||
|
||||
// fix folding and end-of-line chars
|
||||
$row['vcard'] = preg_replace('/\r|\n\s+/', '', $row['vcard']);
|
||||
$row['vcard'] = preg_replace('/\n/', rcube_vcard::$eol, $row['vcard']);
|
||||
echo rcube_vcard::rfc2425_fold($row['vcard']) . rcube_vcard::$eol;
|
||||
}
|
||||
|
||||
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;
|
||||
$fieldmap = $source ? $source->vcard_map : null;
|
||||
|
||||
if (empty($record['vcard'])) {
|
||||
$vcard = new rcube_vcard($record['vcard'], RCUBE_CHARSET, false, $fieldmap);
|
||||
$vcard->reset();
|
||||
|
||||
foreach ($record as $key => $values) {
|
||||
list($field, $section) = explode(':', $key);
|
||||
// avoid unwanted casting of DateTime objects to an array
|
||||
// (same as in rcube_contacts::convert_save_data())
|
||||
if (is_object($values) && is_a($values, 'DateTime')) {
|
||||
$values = array($values);
|
||||
}
|
||||
|
||||
foreach ((array) $values as $value) {
|
||||
if (is_array($value) || is_a($value, 'DateTime') || @strlen($value)) {
|
||||
$vcard->set($field, $value, strtoupper($section));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// append group names
|
||||
if ($groups) {
|
||||
$vcard->set('groups', join(',', $groups), null);
|
||||
}
|
||||
|
||||
$record['vcard'] = $vcard->export();
|
||||
}
|
||||
// patch categories to alread existing vcard block
|
||||
else if ($record['vcard']) {
|
||||
$vcard = new rcube_vcard($record['vcard'], RCUBE_CHARSET, false, $fieldmap);
|
||||
|
||||
// unset CATEGORIES entry, it might be not up-to-date (#1490277)
|
||||
$vcard->set('groups', null);
|
||||
$record['vcard'] = $vcard->export();
|
||||
|
||||
if (!empty($groups)) {
|
||||
$vgroups = 'CATEGORIES:' . rcube_vcard::vcard_quote($groups, ',');
|
||||
$record['vcard'] = str_replace('END:VCARD', $vgroups . rcube_vcard::$eol . 'END:VCARD', $record['vcard']);
|
||||
}
|
||||
}
|
||||
}
|
977
data/web/rc/program/steps/addressbook/func.inc
Normal file
977
data/web/rc/program/steps/addressbook/func.inc
Normal file
@@ -0,0 +1,977 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/func.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Provide addressbook functionality and GUI objects |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$SEARCH_MODS_DEFAULT = array('name'=>1, 'firstname'=>1, 'surname'=>1, 'email'=>1, '*'=>1);
|
||||
|
||||
// general definition of contact coltypes
|
||||
$CONTACT_COLTYPES = array(
|
||||
'name' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'limit' => 1, 'label' => $RCMAIL->gettext('name'), 'category' => 'main'),
|
||||
'firstname' => array('type' => 'text', 'size' => 19, 'maxlength' => 50, 'limit' => 1, 'label' => $RCMAIL->gettext('firstname'), 'category' => 'main'),
|
||||
'surname' => array('type' => 'text', 'size' => 19, 'maxlength' => 50, 'limit' => 1, 'label' => $RCMAIL->gettext('surname'), 'category' => 'main'),
|
||||
'email' => array('type' => 'text', 'size' => 40, 'maxlength' => 254, 'label' => $RCMAIL->gettext('email'), 'subtypes' => array('home','work','other'), 'category' => 'main'),
|
||||
'middlename' => array('type' => 'text', 'size' => 19, 'maxlength' => 50, 'limit' => 1, 'label' => $RCMAIL->gettext('middlename'), 'category' => 'main'),
|
||||
'prefix' => array('type' => 'text', 'size' => 8, 'maxlength' => 20, 'limit' => 1, 'label' => $RCMAIL->gettext('nameprefix'), 'category' => 'main'),
|
||||
'suffix' => array('type' => 'text', 'size' => 8, 'maxlength' => 20, 'limit' => 1, 'label' => $RCMAIL->gettext('namesuffix'), 'category' => 'main'),
|
||||
'nickname' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'limit' => 1, 'label' => $RCMAIL->gettext('nickname'), 'category' => 'main'),
|
||||
'jobtitle' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'limit' => 1, 'label' => $RCMAIL->gettext('jobtitle'), 'category' => 'main'),
|
||||
'organization' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'limit' => 1, 'label' => $RCMAIL->gettext('organization'), 'category' => 'main'),
|
||||
'department' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'limit' => 1, 'label' => $RCMAIL->gettext('department'), 'category' => 'main'),
|
||||
'gender' => array('type' => 'select', 'limit' => 1, 'label' => $RCMAIL->gettext('gender'), 'options' => array('male' => $RCMAIL->gettext('male'), 'female' => $RCMAIL->gettext('female')), 'category' => 'personal'),
|
||||
'maidenname' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'limit' => 1, 'label' => $RCMAIL->gettext('maidenname'), 'category' => 'personal'),
|
||||
'phone' => array('type' => 'text', 'size' => 40, 'maxlength' => 20, 'label' => $RCMAIL->gettext('phone'), 'subtypes' => array('home','home2','work','work2','mobile','main','homefax','workfax','car','pager','video','assistant','other'), 'category' => 'main'),
|
||||
'address' => array('type' => 'composite', 'label' => $RCMAIL->gettext('address'), 'subtypes' => array('home','work','other'), 'childs' => array(
|
||||
'street' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'label' => $RCMAIL->gettext('street'), 'category' => 'main'),
|
||||
'locality' => array('type' => 'text', 'size' => 28, 'maxlength' => 50, 'label' => $RCMAIL->gettext('locality'), 'category' => 'main'),
|
||||
'zipcode' => array('type' => 'text', 'size' => 8, 'maxlength' => 15, 'label' => $RCMAIL->gettext('zipcode'), 'category' => 'main'),
|
||||
'region' => array('type' => 'text', 'size' => 12, 'maxlength' => 50, 'label' => $RCMAIL->gettext('region'), 'category' => 'main'),
|
||||
'country' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'label' => $RCMAIL->gettext('country'), 'category' => 'main'),
|
||||
), 'category' => 'main'),
|
||||
'birthday' => array('type' => 'date', 'size' => 12, 'maxlength' => 16, 'label' => $RCMAIL->gettext('birthday'), 'limit' => 1, 'render_func' => 'rcmail_format_date_col', 'category' => 'personal'),
|
||||
'anniversary' => array('type' => 'date', 'size' => 12, 'maxlength' => 16, 'label' => $RCMAIL->gettext('anniversary'), 'limit' => 1, 'render_func' => 'rcmail_format_date_col', 'category' => 'personal'),
|
||||
'website' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'label' => $RCMAIL->gettext('website'), 'subtypes' => array('homepage','work','blog','profile','other'), 'category' => 'main'),
|
||||
'im' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'label' => $RCMAIL->gettext('instantmessenger'), 'subtypes' => array('aim','icq','msn','yahoo','jabber','skype','other'), 'category' => 'main'),
|
||||
'notes' => array('type' => 'textarea', 'size' => 40, 'rows' => 15, 'maxlength' => 500, 'label' => $RCMAIL->gettext('notes'), 'limit' => 1),
|
||||
'photo' => array('type' => 'image', 'limit' => 1, 'category' => 'main'),
|
||||
'assistant' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'limit' => 1, 'label' => $RCMAIL->gettext('assistant'), 'category' => 'personal'),
|
||||
'manager' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'limit' => 1, 'label' => $RCMAIL->gettext('manager'), 'category' => 'personal'),
|
||||
'spouse' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'limit' => 1, 'label' => $RCMAIL->gettext('spouse'), 'category' => 'personal'),
|
||||
// TODO: define fields for vcards like GEO, KEY
|
||||
);
|
||||
|
||||
$PAGE_SIZE = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50));
|
||||
|
||||
// Addressbook UI
|
||||
if (!$RCMAIL->action && !$OUTPUT->ajax_call) {
|
||||
// add list of address sources to client env
|
||||
$js_list = $RCMAIL->get_address_sources();
|
||||
|
||||
// count all/writeable sources
|
||||
$writeable = 0;
|
||||
$count = 0;
|
||||
foreach ($js_list as $sid => $s) {
|
||||
$count++;
|
||||
if (!$s['readonly']) {
|
||||
$writeable++;
|
||||
}
|
||||
// unset hidden sources
|
||||
if ($s['hidden']) {
|
||||
unset($js_list[$sid]);
|
||||
}
|
||||
}
|
||||
|
||||
$search_mods = $RCMAIL->config->get('addressbook_search_mods', $SEARCH_MODS_DEFAULT);
|
||||
$OUTPUT->set_env('search_mods', $search_mods);
|
||||
$OUTPUT->set_env('address_sources', $js_list);
|
||||
$OUTPUT->set_env('writable_source', $writeable);
|
||||
|
||||
$OUTPUT->set_pagetitle($RCMAIL->gettext('contacts'));
|
||||
$_SESSION['addressbooks_count'] = $count;
|
||||
$_SESSION['addressbooks_count_writeable'] = $writeable;
|
||||
|
||||
// select address book
|
||||
$source = rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC);
|
||||
|
||||
// use first directory by default
|
||||
if (!strlen($source) || !isset($js_list[$source])) {
|
||||
$source = $RCMAIL->config->get('default_addressbook');
|
||||
if (!strlen($source) || !isset($js_list[$source])) {
|
||||
$source = strval(key($js_list));
|
||||
}
|
||||
}
|
||||
|
||||
$CONTACTS = rcmail_contact_source($source, true);
|
||||
}
|
||||
|
||||
// remove undo information...
|
||||
if ($undo = $_SESSION['contact_undo']) {
|
||||
// ...after timeout
|
||||
$undo_time = $RCMAIL->config->get('undo_timeout', 0);
|
||||
if ($undo['ts'] < time() - $undo_time)
|
||||
$RCMAIL->session->remove('contact_undo');
|
||||
}
|
||||
|
||||
// register UI objects
|
||||
$OUTPUT->add_handlers(array(
|
||||
'directorylist' => 'rcmail_directory_list',
|
||||
'savedsearchlist' => 'rcmail_savedsearch_list',
|
||||
'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)
|
||||
{
|
||||
global $RCMAIL, $OUTPUT, $CONTACT_COLTYPES, $PAGE_SIZE;
|
||||
|
||||
if (!strlen($source)) {
|
||||
$source = rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC);
|
||||
}
|
||||
|
||||
// Get object
|
||||
$CONTACTS = $RCMAIL->get_address_book($source, $writable);
|
||||
$CONTACTS->set_pagesize($PAGE_SIZE);
|
||||
|
||||
// set list properties and session vars
|
||||
if (!empty($_GET['_page']))
|
||||
$CONTACTS->set_page(($_SESSION['page'] = intval($_GET['_page'])));
|
||||
else
|
||||
$CONTACTS->set_page(isset($_SESSION['page']) ? $_SESSION['page'] : 1);
|
||||
|
||||
if (!empty($_REQUEST['_gid'])) {
|
||||
$group = rcube_utils::get_input_value('_gid', rcube_utils::INPUT_GPC);
|
||||
$CONTACTS->set_group($group);
|
||||
}
|
||||
|
||||
if (!$init_env) {
|
||||
return $CONTACTS;
|
||||
}
|
||||
|
||||
$OUTPUT->set_env('readonly', $CONTACTS->readonly);
|
||||
$OUTPUT->set_env('source', (string) $source);
|
||||
$OUTPUT->set_env('group', $group);
|
||||
|
||||
// reduce/extend $CONTACT_COLTYPES with specification from the current $CONTACT object
|
||||
if (is_array($CONTACTS->coltypes)) {
|
||||
// remove cols not listed by the backend class
|
||||
$contact_cols = $CONTACTS->coltypes[0] ? array_flip($CONTACTS->coltypes) : $CONTACTS->coltypes;
|
||||
$CONTACT_COLTYPES = array_intersect_key($CONTACT_COLTYPES, $contact_cols);
|
||||
// add associative coltypes definition
|
||||
if (!$CONTACTS->coltypes[0]) {
|
||||
foreach ($CONTACTS->coltypes as $col => $colprop) {
|
||||
if (is_array($colprop['childs'])) {
|
||||
foreach ($colprop['childs'] as $childcol => $childprop)
|
||||
$colprop['childs'][$childcol] = array_merge((array)$CONTACT_COLTYPES[$col]['childs'][$childcol], $childprop);
|
||||
}
|
||||
$CONTACT_COLTYPES[$col] = $CONTACT_COLTYPES[$col] ? array_merge($CONTACT_COLTYPES[$col], $colprop) : $colprop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$OUTPUT->set_env('photocol', is_array($CONTACT_COLTYPES['photo']));
|
||||
|
||||
return $CONTACTS;
|
||||
}
|
||||
|
||||
|
||||
function rcmail_set_sourcename($abook)
|
||||
{
|
||||
global $OUTPUT, $RCMAIL;
|
||||
|
||||
// get address book name (for display)
|
||||
if ($abook && $_SESSION['addressbooks_count'] > 1) {
|
||||
$name = $abook->get_name();
|
||||
if (!$name) {
|
||||
$name = $RCMAIL->gettext('personaladrbook');
|
||||
}
|
||||
$OUTPUT->set_env('sourcename', html_entity_decode($name, ENT_COMPAT, 'UTF-8'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function rcmail_directory_list($attrib)
|
||||
{
|
||||
global $RCMAIL, $OUTPUT;
|
||||
|
||||
if (!$attrib['id'])
|
||||
$attrib['id'] = 'rcmdirectorylist';
|
||||
|
||||
$out = '';
|
||||
$jsdata = array();
|
||||
|
||||
$line_templ = html::tag('li', array(
|
||||
'id' => 'rcmli%s', 'class' => '%s', 'noclose' => true),
|
||||
html::a(array('href' => '%s',
|
||||
'rel' => '%s',
|
||||
'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".command('list','%s',this)"), '%s'));
|
||||
|
||||
$sources = (array) $OUTPUT->get_env('address_sources');
|
||||
reset($sources);
|
||||
|
||||
// currently selected source
|
||||
$current = rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC);
|
||||
|
||||
foreach ($sources as $j => $source) {
|
||||
$id = strval(strlen($source['id']) ? $source['id'] : $j);
|
||||
$js_id = rcube::JQ($id);
|
||||
|
||||
// set class name(s)
|
||||
$class_name = 'addressbook';
|
||||
if ($current === $id)
|
||||
$class_name .= ' selected';
|
||||
if ($source['readonly'])
|
||||
$class_name .= ' readonly';
|
||||
if ($source['class_name'])
|
||||
$class_name .= ' ' . $source['class_name'];
|
||||
|
||||
$name = $source['name'] ?: $id;
|
||||
$out .= sprintf($line_templ,
|
||||
rcube_utils::html_identifier($id, true),
|
||||
$class_name,
|
||||
rcube::Q($RCMAIL->url(array('_source' => $id))),
|
||||
$source['id'],
|
||||
$js_id, $name);
|
||||
|
||||
$groupdata = array('out' => $out, 'jsdata' => $jsdata, 'source' => $id);
|
||||
if ($source['groups'])
|
||||
$groupdata = rcmail_contact_groups($groupdata);
|
||||
$jsdata = $groupdata['jsdata'];
|
||||
$out = $groupdata['out'];
|
||||
$out .= '</li>';
|
||||
}
|
||||
|
||||
$OUTPUT->set_env('contactgroups', $jsdata);
|
||||
$OUTPUT->set_env('collapsed_abooks', (string)$RCMAIL->config->get('collapsed_abooks',''));
|
||||
$OUTPUT->add_gui_object('folderlist', $attrib['id']);
|
||||
$OUTPUT->include_script('treelist.js');
|
||||
|
||||
// add some labels to client
|
||||
$OUTPUT->add_label('deletegroupconfirm', 'groupdeleting', 'addingmember', 'removingmember',
|
||||
'newgroup', 'grouprename', 'searchsave', 'namex', 'save'
|
||||
);
|
||||
|
||||
return html::tag('ul', $attrib, $out, html::$common_attrib);
|
||||
}
|
||||
|
||||
|
||||
function rcmail_savedsearch_list($attrib)
|
||||
{
|
||||
global $RCMAIL, $OUTPUT;
|
||||
|
||||
if (!$attrib['id'])
|
||||
$attrib['id'] = 'rcmsavedsearchlist';
|
||||
|
||||
$out = '';
|
||||
$line_templ = html::tag('li', array(
|
||||
'id' => 'rcmli%s', 'class' => '%s'),
|
||||
html::a(array('href' => '#', 'rel' => 'S%s',
|
||||
'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".command('listsearch', '%s', this)"), '%s'));
|
||||
|
||||
// Saved searches
|
||||
$sources = $RCMAIL->user->list_searches(rcube_user::SEARCH_ADDRESSBOOK);
|
||||
foreach ($sources as $source) {
|
||||
$id = $source['id'];
|
||||
$js_id = rcube::JQ($id);
|
||||
|
||||
// set class name(s)
|
||||
$classes = array('contactsearch');
|
||||
if (!empty($source['class_name']))
|
||||
$classes[] = $source['class_name'];
|
||||
|
||||
$out .= sprintf($line_templ,
|
||||
rcube_utils::html_identifier('S'.$id, true),
|
||||
join(' ', $classes),
|
||||
$id,
|
||||
$js_id, rcube::Q($source['name'] ?: $id)
|
||||
);
|
||||
}
|
||||
|
||||
$OUTPUT->add_gui_object('savedsearchlist', $attrib['id']);
|
||||
|
||||
return html::tag('ul', $attrib, $out, html::$common_attrib);
|
||||
}
|
||||
|
||||
|
||||
function rcmail_contact_groups($args)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
$groups_html = '';
|
||||
$groups = $RCMAIL->get_address_book($args['source'])->list_groups();
|
||||
|
||||
if (!empty($groups)) {
|
||||
$line_templ = html::tag('li', array(
|
||||
'id' => 'rcmli%s', 'class' => 'contactgroup'),
|
||||
html::a(array('href' => '#',
|
||||
'rel' => '%s:%s',
|
||||
'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".command('listgroup',{'source':'%s','id':'%s'},this)"), '%s'));
|
||||
|
||||
// append collapse/expand toggle and open a new <ul>
|
||||
$is_collapsed = strpos($RCMAIL->config->get('collapsed_abooks',''), '&'.rawurlencode($args['source']).'&') !== false;
|
||||
$args['out'] .= html::div('treetoggle ' . ($is_collapsed ? 'collapsed' : 'expanded'), ' ');
|
||||
|
||||
foreach ($groups as $group) {
|
||||
$groups_html .= sprintf($line_templ,
|
||||
rcube_utils::html_identifier('G' . $args['source'] . $group['ID'], true),
|
||||
$args['source'], $group['ID'],
|
||||
$args['source'], $group['ID'], rcube::Q($group['name'])
|
||||
);
|
||||
$args['jsdata']['G'.$args['source'].$group['ID']] = array(
|
||||
'source' => $args['source'], 'id' => $group['ID'],
|
||||
'name' => $group['name'], 'type' => 'group');
|
||||
}
|
||||
}
|
||||
|
||||
$args['out'] .= html::tag('ul',
|
||||
array('class' => 'groups', 'style' => ($is_collapsed || empty($groups) ? "display:none;" : null)),
|
||||
$groups_html);
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
|
||||
// return the contacts list as HTML table
|
||||
function rcmail_contacts_list($attrib)
|
||||
{
|
||||
global $RCMAIL, $CONTACTS, $OUTPUT;
|
||||
|
||||
// define list of cols to be displayed
|
||||
$a_show_cols = array('name','action');
|
||||
|
||||
// add id to message list table if not specified
|
||||
if (!strlen($attrib['id']))
|
||||
$attrib['id'] = 'rcmAddressList';
|
||||
|
||||
// create XHTML table
|
||||
$out = $RCMAIL->table_output($attrib, array(), $a_show_cols, $CONTACTS->primary_key);
|
||||
|
||||
// set client env
|
||||
$OUTPUT->add_gui_object('contactslist', $attrib['id']);
|
||||
$OUTPUT->set_env('current_page', (int)$CONTACTS->list_page);
|
||||
$OUTPUT->include_script('list.js');
|
||||
|
||||
// add some labels to client
|
||||
$OUTPUT->add_label('deletecontactconfirm', 'copyingcontact', 'movingcontact', 'contactdeleting');
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
function rcmail_js_contacts_list($result, $prefix='')
|
||||
{
|
||||
global $OUTPUT, $RCMAIL;
|
||||
|
||||
if (empty($result) || $result->count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// define list of cols to be displayed
|
||||
$a_show_cols = array('name','action');
|
||||
|
||||
while ($row = $result->next()) {
|
||||
$emails = rcube_addressbook::get_col_values('email', $row, true);
|
||||
$row['CID'] = $row['ID'];
|
||||
$row['email'] = reset($emails);
|
||||
|
||||
$source_id = $OUTPUT->get_env('source');
|
||||
$a_row_cols = array();
|
||||
$classes = array($row['_type'] ?: 'person');
|
||||
|
||||
// build contact ID with source ID
|
||||
if (isset($row['sourceid'])) {
|
||||
$row['ID'] = $row['ID'].'-'.$row['sourceid'];
|
||||
$source_id = $row['sourceid'];
|
||||
}
|
||||
|
||||
// format each col
|
||||
foreach ($a_show_cols as $col) {
|
||||
$val = '';
|
||||
switch ($col) {
|
||||
case 'name':
|
||||
$val = rcube::Q(rcube_addressbook::compose_list_name($row));
|
||||
break;
|
||||
|
||||
case 'action':
|
||||
if ($row['_type'] == 'group') {
|
||||
$val = html::a(array(
|
||||
'href' => '#list',
|
||||
'rel' => $row['ID'],
|
||||
'title' => $RCMAIL->gettext('listgroup'),
|
||||
'onclick' => sprintf("return %s.command('pushgroup',{'source':'%s','id':'%s'},this,event)", rcmail_output::JS_OBJECT_NAME, $source_id, $row['CID']),
|
||||
), '»');
|
||||
}
|
||||
else
|
||||
$val = '';
|
||||
break;
|
||||
|
||||
default:
|
||||
$val = rcube::Q($row[$col]);
|
||||
break;
|
||||
}
|
||||
|
||||
$a_row_cols[$col] = $val;
|
||||
}
|
||||
|
||||
if ($row['readonly'])
|
||||
$classes[] = 'readonly';
|
||||
|
||||
$OUTPUT->command($prefix.'add_contact_row', $row['ID'], $a_row_cols, join(' ', $classes), array_intersect_key($row, array('ID'=>1,'readonly'=>1,'_type'=>1,'email'=>1,'name'=>1)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function rcmail_contacts_list_title($attrib)
|
||||
{
|
||||
global $OUTPUT, $RCMAIL;
|
||||
|
||||
$attrib += array('label' => 'contacts', 'id' => 'rcmabooklisttitle', 'tag' => 'span');
|
||||
unset($attrib['name']);
|
||||
|
||||
$OUTPUT->add_gui_object('addresslist_title', $attrib['id']);
|
||||
$OUTPUT->add_label('contacts','uponelevel');
|
||||
|
||||
return html::tag($attrib['tag'], $attrib, $RCMAIL->gettext($attrib['label']), html::$common_attrib);
|
||||
}
|
||||
|
||||
|
||||
// similar function as /steps/settings/identities.inc::rcmail_identity_frame()
|
||||
function rcmail_contact_frame($attrib)
|
||||
{
|
||||
global $OUTPUT;
|
||||
|
||||
if (!$attrib['id'])
|
||||
$attrib['id'] = 'rcmcontactframe';
|
||||
|
||||
return $OUTPUT->frame($attrib, true);
|
||||
}
|
||||
|
||||
|
||||
function rcmail_rowcount_display($attrib)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
if (!$attrib['id'])
|
||||
$attrib['id'] = 'rcmcountdisplay';
|
||||
|
||||
$RCMAIL->output->add_gui_object('countdisplay', $attrib['id']);
|
||||
|
||||
if ($attrib['label'])
|
||||
$_SESSION['contactcountdisplay'] = $attrib['label'];
|
||||
|
||||
return html::span($attrib, $RCMAIL->gettext('loading'));
|
||||
}
|
||||
|
||||
|
||||
function rcmail_get_rowcount_text($result=null)
|
||||
{
|
||||
global $RCMAIL, $CONTACTS, $PAGE_SIZE;
|
||||
|
||||
// read nr of contacts
|
||||
if (!$result) {
|
||||
$result = $CONTACTS->get_result();
|
||||
}
|
||||
|
||||
if ($result->count == 0)
|
||||
$out = $RCMAIL->gettext('nocontactsfound');
|
||||
else
|
||||
$out = $RCMAIL->gettext(array(
|
||||
'name' => $_SESSION['contactcountdisplay'] ?: 'contactsfromto',
|
||||
'vars' => array(
|
||||
'from' => $result->first + 1,
|
||||
'to' => min($result->count, $result->first + $PAGE_SIZE),
|
||||
'count' => $result->count)
|
||||
));
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
function rcmail_get_type_label($type)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
$label = 'type'.$type;
|
||||
if ($RCMAIL->text_exists($label, '*', $domain))
|
||||
return $RCMAIL->gettext($label, $domain);
|
||||
else if (preg_match('/\w+(\d+)$/', $label, $m)
|
||||
&& ($label = preg_replace('/(\d+)$/', '', $label))
|
||||
&& $RCMAIL->text_exists($label, '*', $domain))
|
||||
return $RCMAIL->gettext($label, $domain) . ' ' . $m[1];
|
||||
|
||||
return ucfirst($type);
|
||||
}
|
||||
|
||||
|
||||
function rcmail_contact_form($form, $record, $attrib = null)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
// group fields
|
||||
$head_fields = array(
|
||||
'names' => array('prefix','firstname','middlename','surname','suffix'),
|
||||
'displayname' => array('name'),
|
||||
'nickname' => array('nickname'),
|
||||
'organization' => array('organization'),
|
||||
'department' => array('department'),
|
||||
'jobtitle' => array('jobtitle'),
|
||||
);
|
||||
|
||||
// Allow plugins to modify contact form content
|
||||
$plugin = $RCMAIL->plugins->exec_hook('contact_form', array(
|
||||
'form' => $form, 'record' => $record, 'head_fields' => $head_fields));
|
||||
|
||||
$form = $plugin['form'];
|
||||
$record = $plugin['record'];
|
||||
$head_fields = $plugin['head_fields'];
|
||||
$edit_mode = $RCMAIL->action != 'show' && $RCMAIL->action != 'print';
|
||||
$del_button = $attrib['deleteicon'] ? html::img(array('src' => $RCMAIL->output->get_skin_file($attrib['deleteicon']), 'alt' => $RCMAIL->gettext('delete'))) : $RCMAIL->gettext('delete');
|
||||
$out = '';
|
||||
|
||||
unset($attrib['deleteicon']);
|
||||
|
||||
// get default coltypes
|
||||
$coltypes = $GLOBALS['CONTACT_COLTYPES'];
|
||||
$coltype_labels = array();
|
||||
|
||||
foreach ($coltypes as $col => $prop) {
|
||||
if ($prop['subtypes']) {
|
||||
$subtype_names = array_map('rcmail_get_type_label', $prop['subtypes']);
|
||||
$select_subtype = new html_select(array('name' => '_subtype_'.$col.'[]', 'class' => 'contactselectsubtype', 'title' => $prop['label'] . ' ' . $RCMAIL->gettext('type')));
|
||||
$select_subtype->add($subtype_names, $prop['subtypes']);
|
||||
$coltypes[$col]['subtypes_select'] = $select_subtype->show();
|
||||
}
|
||||
if ($prop['childs']) {
|
||||
foreach ($prop['childs'] as $childcol => $cp)
|
||||
$coltype_labels[$childcol] = array('label' => $cp['label']);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($form as $section => $fieldset) {
|
||||
// skip empty sections
|
||||
if (empty($fieldset['content'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$select_add = new html_select(array('class' => 'addfieldmenu', 'rel' => $section));
|
||||
$select_add->add($RCMAIL->gettext('addfield'), '');
|
||||
|
||||
// render head section with name fields (not a regular list of rows)
|
||||
if ($section == 'head') {
|
||||
$content = '';
|
||||
|
||||
// unset display name if it is composed from name parts
|
||||
if ($record['name'] == rcube_addressbook::compose_display_name(array('name' => '') + (array)$record)) {
|
||||
unset($record['name']);
|
||||
}
|
||||
|
||||
foreach ($head_fields as $blockname => $colnames) {
|
||||
$fields = '';
|
||||
foreach ($colnames as $col) {
|
||||
// skip cols unknown to the backend
|
||||
if (!$coltypes[$col])
|
||||
continue;
|
||||
|
||||
// skip cols not listed in the form definition
|
||||
if (is_array($fieldset['content']) && !in_array($col, array_keys($fieldset['content']))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// only string values are expected here
|
||||
if (is_array($record[$col]))
|
||||
$record[$col] = join(' ', $record[$col]);
|
||||
|
||||
if (!$edit_mode) {
|
||||
if (!empty($record[$col]))
|
||||
$fields .= html::span('namefield ' . $col, rcube::Q($record[$col])) . " ";
|
||||
}
|
||||
else {
|
||||
$colprop = (array)$fieldset['content'][$col] + (array)$coltypes[$col];
|
||||
$colprop['id'] = 'ff_'.$col;
|
||||
if (empty($record[$col]) && !$colprop['visible']) {
|
||||
$colprop['style'] = 'display:none';
|
||||
$select_add->add($colprop['label'], $col);
|
||||
}
|
||||
$fields .= rcube_output::get_edit_field($col, $record[$col], $colprop, $colprop['type']);
|
||||
}
|
||||
}
|
||||
$content .= html::div($blockname, $fields);
|
||||
}
|
||||
|
||||
if ($edit_mode)
|
||||
$content .= html::p('addfield', $select_add->show(null));
|
||||
|
||||
$out .= html::tag('fieldset', $attrib, (!empty($fieldset['name']) ? html::tag('legend', null, rcube::Q($fieldset['name'])) : '') . $content) ."\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$content = '';
|
||||
if (is_array($fieldset['content'])) {
|
||||
foreach ($fieldset['content'] as $col => $colprop) {
|
||||
// remove subtype part of col name
|
||||
list($field, $subtype) = explode(':', $col);
|
||||
if (!$subtype) $subtype = 'home';
|
||||
$fullkey = $col.':'.$subtype;
|
||||
|
||||
// skip cols unknown to the backend
|
||||
if (!$coltypes[$field] && empty($colprop['value'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// merge colprop with global coltype configuration
|
||||
if ($coltypes[$field]) {
|
||||
$colprop += $coltypes[$field];
|
||||
}
|
||||
|
||||
$label = isset($colprop['label']) ? $colprop['label'] : $RCMAIL->gettext($col);
|
||||
|
||||
// prepare subtype selector in edit mode
|
||||
if ($edit_mode && is_array($colprop['subtypes'])) {
|
||||
$subtype_names = array_map('rcmail_get_type_label', $colprop['subtypes']);
|
||||
$select_subtype = new html_select(array('name' => '_subtype_'.$col.'[]', 'class' => 'contactselectsubtype', 'title' => $colprop['label'] . ' ' . $RCMAIL->gettext('type')));
|
||||
$select_subtype->add($subtype_names, $colprop['subtypes']);
|
||||
}
|
||||
else {
|
||||
$select_subtype = null;
|
||||
}
|
||||
|
||||
if (!empty($colprop['value'])) {
|
||||
$values = (array)$colprop['value'];
|
||||
}
|
||||
else {
|
||||
// iterate over possible subtypes and collect values with their subtype
|
||||
if (is_array($colprop['subtypes'])) {
|
||||
$values = $subtypes = array();
|
||||
foreach (rcube_addressbook::get_col_values($field, $record) as $st => $vals) {
|
||||
foreach((array)$vals as $value) {
|
||||
$i = count($values);
|
||||
$subtypes[$i] = $st;
|
||||
$values[$i] = $value;
|
||||
}
|
||||
// TODO: add $st to $select_subtype if missing ?
|
||||
}
|
||||
}
|
||||
else {
|
||||
$values = $record[$fullkey] ?: $record[$field];
|
||||
$subtypes = null;
|
||||
}
|
||||
}
|
||||
|
||||
// hack: create empty values array to force this field to be displayed
|
||||
if (empty($values) && $colprop['visible'])
|
||||
$values[] = '';
|
||||
|
||||
if (!is_array($values)) {
|
||||
// $values can be an object, don't use (array)$values syntax
|
||||
$values = !empty($values) ? array($values) : array();
|
||||
}
|
||||
|
||||
$rows = '';
|
||||
foreach ($values as $i => $val) {
|
||||
if ($subtypes[$i])
|
||||
$subtype = $subtypes[$i];
|
||||
|
||||
$colprop['id'] = 'ff_' . $col . intval($coltypes[$field]['count']);
|
||||
|
||||
// render composite field
|
||||
if ($colprop['type'] == 'composite') {
|
||||
$composite = array(); $j = 0;
|
||||
$template = $RCMAIL->config->get($col . '_template', '{'.join('} {', array_keys($colprop['childs'])).'}');
|
||||
foreach ($colprop['childs'] as $childcol => $cp) {
|
||||
if (!empty($val) && is_array($val)) {
|
||||
$childvalue = $val[$childcol] ?: $val[$j];
|
||||
}
|
||||
else {
|
||||
$childvalue = '';
|
||||
}
|
||||
|
||||
if ($edit_mode) {
|
||||
if ($colprop['subtypes'] || $colprop['limit'] != 1) $cp['array'] = true;
|
||||
$composite['{'.$childcol.'}'] = rcube_output::get_edit_field($childcol, $childvalue, $cp, $cp['type']) . " ";
|
||||
}
|
||||
else {
|
||||
$childval = $cp['render_func'] ? call_user_func($cp['render_func'], $childvalue, $childcol) : rcube::Q($childvalue);
|
||||
$composite['{'.$childcol.'}'] = html::span('data ' . $childcol, $childval) . " ";
|
||||
}
|
||||
$j++;
|
||||
}
|
||||
|
||||
$coltypes[$field] += (array)$colprop;
|
||||
$coltypes[$field]['count']++;
|
||||
$val = preg_replace('/\{\w+\}/', '', strtr($template, $composite));
|
||||
}
|
||||
else if ($edit_mode) {
|
||||
// call callback to render/format value
|
||||
if ($colprop['render_func'])
|
||||
$val = call_user_func($colprop['render_func'], $val, $col);
|
||||
|
||||
$coltypes[$field] = (array)$colprop + $coltypes[$field];
|
||||
|
||||
if ($colprop['subtypes'] || $colprop['limit'] != 1)
|
||||
$colprop['array'] = true;
|
||||
|
||||
// load jquery UI datepicker for date fields
|
||||
if ($colprop['type'] == 'date') {
|
||||
$colprop['class'] .= ($colprop['class'] ? ' ' : '') . 'datepicker';
|
||||
if (!$colprop['render_func'])
|
||||
$val = rcmail_format_date_col($val);
|
||||
}
|
||||
|
||||
$val = rcube_output::get_edit_field($col, $val, $colprop, $colprop['type']);
|
||||
$coltypes[$field]['count']++;
|
||||
}
|
||||
else if ($colprop['render_func'])
|
||||
$val = call_user_func($colprop['render_func'], $val, $col);
|
||||
else if (is_array($colprop['options']) && isset($colprop['options'][$val]))
|
||||
$val = $colprop['options'][$val];
|
||||
else
|
||||
$val = rcube::Q($val);
|
||||
|
||||
// use subtype as label
|
||||
if ($colprop['subtypes'])
|
||||
$label = rcmail_get_type_label($subtype);
|
||||
|
||||
// add delete button/link
|
||||
if ($edit_mode && !($colprop['visible'] && $colprop['limit'] == 1))
|
||||
$val .= html::a(array('href' => '#del', 'class' => 'contactfieldbutton deletebutton', 'title' => $RCMAIL->gettext('delete'), 'rel' => $col), $del_button);
|
||||
|
||||
// display row with label
|
||||
if ($label) {
|
||||
if ($RCMAIL->action == 'print') {
|
||||
$_label = rcube::Q($colprop['label'] . ($label != $colprop['label'] ? ' (' . $label . ')' : ''));
|
||||
}
|
||||
else {
|
||||
$_label = $select_subtype ? $select_subtype->show($subtype) : html::label($colprop['id'], rcube::Q($label));
|
||||
}
|
||||
|
||||
$rows .= html::div('row',
|
||||
html::div('contactfieldlabel label', $_label) .
|
||||
html::div('contactfieldcontent '.$colprop['type'], $val));
|
||||
}
|
||||
// row without label
|
||||
else {
|
||||
$rows .= html::div('row', html::div('contactfield', $val));
|
||||
}
|
||||
}
|
||||
|
||||
// add option to the add-field menu
|
||||
if (!$colprop['limit'] || $coltypes[$field]['count'] < $colprop['limit']) {
|
||||
$select_add->add($colprop['label'], $col);
|
||||
$select_add->_count++;
|
||||
}
|
||||
|
||||
// wrap rows in fieldgroup container
|
||||
if ($rows) {
|
||||
$c_class = 'contactfieldgroup ' . ($colprop['subtypes'] ? 'contactfieldgroupmulti ' : '') . 'contactcontroller' . $col;
|
||||
$with_label = $colprop['subtypes'] && $RCMAIL->action != 'print';
|
||||
$content .= html::tag(
|
||||
'fieldset',
|
||||
array('class' => $c_class, 'style' => ($rows ? null : 'display:none')),
|
||||
($with_label ? html::tag('legend', null, rcube::Q($colprop['label'])) : ' ') . $rows
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$content && (!$edit_mode || !$select_add->_count))
|
||||
continue;
|
||||
|
||||
// also render add-field selector
|
||||
if ($edit_mode)
|
||||
$content .= html::p('addfield', $select_add->show(null, array('style' => $select_add->_count ? null : 'display:none')));
|
||||
|
||||
$content = html::div(array('id' => 'contactsection' . $section), $content);
|
||||
}
|
||||
else {
|
||||
$content = $fieldset['content'];
|
||||
}
|
||||
|
||||
if ($content)
|
||||
$out .= html::tag('fieldset', null, html::tag('legend', null, rcube::Q($fieldset['name'])) . $content) ."\n";
|
||||
}
|
||||
|
||||
if ($edit_mode) {
|
||||
$RCMAIL->output->set_env('coltypes', $coltypes + $coltype_labels);
|
||||
$RCMAIL->output->set_env('delbutton', $del_button);
|
||||
$RCMAIL->output->add_label('delete');
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
function rcmail_contact_photo($attrib)
|
||||
{
|
||||
global $SOURCE_ID, $CONTACTS, $CONTACT_COLTYPES, $RCMAIL;
|
||||
|
||||
if ($result = $CONTACTS->get_result())
|
||||
$record = $result->first();
|
||||
|
||||
$photo_img = $attrib['placeholder'] ? $RCMAIL->output->abs_url($attrib['placeholder'], true) : 'program/resources/blank.gif';
|
||||
if ($record['_type'] == 'group' && $attrib['placeholdergroup'])
|
||||
$photo_img = $RCMAIL->output->abs_url($attrib['placeholdergroup'], true);
|
||||
|
||||
$RCMAIL->output->set_env('photo_placeholder', $RCMAIL->output->asset_url($photo_img));
|
||||
|
||||
unset($attrib['placeholder']);
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('contact_photo', array('record' => $record, 'data' => $record['photo']));
|
||||
|
||||
// check if we have photo data from contact form
|
||||
if ($GLOBALS['EDIT_RECORD']) {
|
||||
$rec = $GLOBALS['EDIT_RECORD'];
|
||||
if ($rec['photo'] == '-del-') {
|
||||
$record['photo'] = '';
|
||||
}
|
||||
else if ($_SESSION['contacts']['files'][$rec['photo']]) {
|
||||
$record['photo'] = $file_id = $rec['photo'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($plugin['url'])
|
||||
$photo_img = $plugin['url'];
|
||||
else if (preg_match('!^https?://!i', $record['photo']))
|
||||
$photo_img = $record['photo'];
|
||||
else if ($record['photo']) {
|
||||
$url = array('_action' => 'photo', '_cid' => $record['ID'], '_source' => $SOURCE_ID);
|
||||
if ($file_id) {
|
||||
$url['_photo'] = $ff_value = $file_id;
|
||||
}
|
||||
$photo_img = $RCMAIL->url($url);
|
||||
}
|
||||
else {
|
||||
$ff_value = '-del-'; // will disable delete-photo action
|
||||
}
|
||||
|
||||
$content = html::div($attrib, html::img(array(
|
||||
'src' => $photo_img,
|
||||
'alt' => $RCMAIL->gettext('contactphoto'),
|
||||
'onerror' => 'this.src = rcmail.env.photo_placeholder',
|
||||
)));
|
||||
|
||||
if ($CONTACT_COLTYPES['photo'] && ($RCMAIL->action == 'edit' || $RCMAIL->action == 'add')) {
|
||||
$RCMAIL->output->add_gui_object('contactphoto', $attrib['id']);
|
||||
$hidden = new html_hiddenfield(array('name' => '_photo', 'id' => 'ff_photo', 'value' => $ff_value));
|
||||
$content .= $hidden->show();
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
|
||||
function rcmail_format_date_col($val)
|
||||
{
|
||||
global $RCMAIL;
|
||||
return $RCMAIL->format_date($val, $RCMAIL->config->get('date_format', 'Y-m-d'), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates saved search after data changed
|
||||
*/
|
||||
function rcmail_search_update($return = false)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
if (($search_request = $_REQUEST['_search']) && isset($_SESSION['search'][$search_request])) {
|
||||
$search = (array)$_SESSION['search'][$search_request];
|
||||
$sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
|
||||
$afields = $return ? $RCMAIL->config->get('contactlist_fields') : array('name', 'email');
|
||||
$records = array();
|
||||
|
||||
foreach ($search as $s => $set) {
|
||||
$source = $RCMAIL->get_address_book($s);
|
||||
|
||||
// reset page
|
||||
$source->set_page(1);
|
||||
$source->set_pagesize(9999);
|
||||
$source->set_search_set($set);
|
||||
|
||||
// get records
|
||||
$result = $source->list_records($afields);
|
||||
|
||||
if (!$result->count) {
|
||||
unset($search[$s]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($return) {
|
||||
while ($row = $result->next()) {
|
||||
$row['sourceid'] = $s;
|
||||
$key = rcube_addressbook::compose_contact_key($row, $sort_col);
|
||||
$records[$key] = $row;
|
||||
}
|
||||
unset($result);
|
||||
}
|
||||
|
||||
$search[$s] = $source->get_search_set();
|
||||
}
|
||||
|
||||
$_SESSION['search'][$search_request] = $search;
|
||||
|
||||
return $records;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns contact ID(s) and source(s) from GET/POST data
|
||||
*
|
||||
* @return array List of contact IDs per-source
|
||||
*/
|
||||
function rcmail_get_cids($filter = null, $request_type = rcube_utils::INPUT_GPC)
|
||||
{
|
||||
// contact ID (or comma-separated list of IDs) is provided in two
|
||||
// forms. If _source is an empty string then the ID is a string
|
||||
// containing contact ID and source name in form: <ID>-<SOURCE>
|
||||
|
||||
$cid = rcube_utils::get_input_value('_cid', $request_type);
|
||||
$source = (string) rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC);
|
||||
|
||||
if (is_array($cid)) {
|
||||
return $cid;
|
||||
}
|
||||
|
||||
if (!preg_match('/^[a-zA-Z0-9\+\/=_-]+(,[a-zA-Z0-9\+\/=_-]+)*$/', $cid)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$cid = explode(',', $cid);
|
||||
$got_source = strlen($source);
|
||||
$result = array();
|
||||
|
||||
// create per-source contact IDs array
|
||||
foreach ($cid as $id) {
|
||||
// extract source ID from contact ID (it's there in search mode)
|
||||
// see #1488959 and #1488862 for reference
|
||||
if (!$got_source) {
|
||||
if ($sep = strrpos($id, '-')) {
|
||||
$contact_id = substr($id, 0, $sep);
|
||||
$source_id = (string) substr($id, $sep+1);
|
||||
if (strlen($source_id)) {
|
||||
$result[$source_id][] = $contact_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (substr($id, -($got_source+1)) === "-$source") {
|
||||
$id = substr($id, 0, -($got_source+1));
|
||||
}
|
||||
$result[$source][] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
return $filter !== null ? $result[$filter] : $result;
|
||||
}
|
154
data/web/rc/program/steps/addressbook/groups.inc
Normal file
154
data/web/rc/program/steps/addressbook/groups.inc
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/groups.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2010-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: |
|
||||
| Create/delete/rename contact groups and assign/remove contacts |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$source = rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC);
|
||||
$CONTACTS = rcmail_contact_source($source);
|
||||
|
||||
if ($CONTACTS->readonly || !$CONTACTS->groups) {
|
||||
$OUTPUT->show_message('sourceisreadonly', 'warning');
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
if ($RCMAIL->action == 'group-addmembers') {
|
||||
if (($gid = rcube_utils::get_input_value('_gid', rcube_utils::INPUT_POST)) && ($ids = rcmail_get_cids($source))) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('group_addmembers', array(
|
||||
'group_id' => $gid,
|
||||
'ids' => $ids,
|
||||
'source' => $source,
|
||||
));
|
||||
|
||||
$CONTACTS->set_group($gid);
|
||||
$num2add = count($plugin['ids']);
|
||||
|
||||
if (!$plugin['abort']) {
|
||||
if (($maxnum = $RCMAIL->config->get('max_group_members', 0)) && ($CONTACTS->count()->count + $num2add > $maxnum)) {
|
||||
$OUTPUT->show_message('maxgroupmembersreached', 'warning', array('max' => $maxnum));
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
$result = $CONTACTS->add_to_group($gid, $plugin['ids']);
|
||||
}
|
||||
else {
|
||||
$result = $plugin['result'];
|
||||
}
|
||||
|
||||
if ($result)
|
||||
$OUTPUT->show_message('contactaddedtogroup');
|
||||
else if ($plugin['abort'] || $CONTACTS->get_error())
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'errorsaving', 'error');
|
||||
else
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'nogroupassignmentschanged');
|
||||
}
|
||||
}
|
||||
else if ($RCMAIL->action == 'group-delmembers') {
|
||||
if (($gid = rcube_utils::get_input_value('_gid', rcube_utils::INPUT_POST)) && ($ids = rcmail_get_cids($source))) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('group_delmembers', array(
|
||||
'group_id' => $gid,
|
||||
'ids' => $ids,
|
||||
'source' => $source,
|
||||
));
|
||||
|
||||
if (!$plugin['abort'])
|
||||
$result = $CONTACTS->remove_from_group($gid, $plugin['ids']);
|
||||
else
|
||||
$result = $plugin['result'];
|
||||
|
||||
if ($result) {
|
||||
$OUTPUT->show_message('contactremovedfromgroup');
|
||||
$OUTPUT->command('remove_group_contacts',array('source' => $source, 'gid' => $gid));
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'errorsaving', 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($RCMAIL->action == 'group-create') {
|
||||
if ($name = trim(rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true))) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('group_create', array(
|
||||
'name' => $name,
|
||||
'source' => $source,
|
||||
));
|
||||
|
||||
if (!$plugin['abort'])
|
||||
$created = $CONTACTS->create_group($plugin['name']);
|
||||
else
|
||||
$created = $plugin['result'];
|
||||
}
|
||||
|
||||
if ($created && $OUTPUT->ajax_call) {
|
||||
$created['name'] = rcube::Q($created['name']);
|
||||
|
||||
$OUTPUT->show_message('groupcreated', 'confirmation');
|
||||
$OUTPUT->command('insert_contact_group', array('source' => $source) + $created);
|
||||
}
|
||||
else if (!$created) {
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'errorsaving', 'error');
|
||||
}
|
||||
}
|
||||
else if ($RCMAIL->action == 'group-rename') {
|
||||
if (($gid = rcube_utils::get_input_value('_gid', rcube_utils::INPUT_POST))
|
||||
&& ($name = trim(rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true)))
|
||||
) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('group_rename', array(
|
||||
'group_id' => $gid,
|
||||
'name' => $name,
|
||||
'source' => $source,
|
||||
));
|
||||
|
||||
if (!$plugin['abort'])
|
||||
$newname = $CONTACTS->rename_group($gid, $plugin['name'], $newgid);
|
||||
else
|
||||
$newname = $plugin['result'];
|
||||
}
|
||||
|
||||
if ($newname && $OUTPUT->ajax_call) {
|
||||
$OUTPUT->show_message('grouprenamed', 'confirmation');
|
||||
$OUTPUT->command('update_contact_group', array(
|
||||
'source' => $source, 'id' => $gid, 'name' => rcube::Q($newname), 'newid' => $newgid));
|
||||
}
|
||||
else if (!$newname) {
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'errorsaving', 'error');
|
||||
}
|
||||
}
|
||||
else if ($RCMAIL->action == 'group-delete') {
|
||||
if ($gid = rcube_utils::get_input_value('_gid', rcube_utils::INPUT_POST)) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('group_delete', array(
|
||||
'group_id' => $gid,
|
||||
'source' => $source,
|
||||
));
|
||||
|
||||
if (!$plugin['abort'])
|
||||
$deleted = $CONTACTS->delete_group($gid);
|
||||
else
|
||||
$deleted = $plugin['result'];
|
||||
}
|
||||
|
||||
if ($deleted) {
|
||||
$OUTPUT->show_message('groupdeleted', 'confirmation');
|
||||
$OUTPUT->command('remove_group_item', array('source' => $source, 'id' => $gid));
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'errorsaving', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// send response
|
||||
$OUTPUT->send();
|
344
data/web/rc/program/steps/addressbook/import.inc
Normal file
344
data/web/rc/program/steps/addressbook/import.inc
Normal file
@@ -0,0 +1,344 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/import.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2008-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: |
|
||||
| Import contacts from a vCard or CSV file |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
| Author: Aleksander Machniak <machniak@kolabsys.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/** The import process **/
|
||||
|
||||
$importstep = 'rcmail_import_form';
|
||||
|
||||
if (is_array($_FILES['_file'])) {
|
||||
$replace = (bool)rcube_utils::get_input_value('_replace', rcube_utils::INPUT_GPC);
|
||||
$target = rcube_utils::get_input_value('_target', rcube_utils::INPUT_GPC);
|
||||
$with_groups = intval(rcube_utils::get_input_value('_groups', rcube_utils::INPUT_GPC));
|
||||
|
||||
$vcards = array();
|
||||
$upload_error = null;
|
||||
|
||||
$CONTACTS = $RCMAIL->get_address_book($target, true);
|
||||
|
||||
if (!$CONTACTS->groups) {
|
||||
$with_groups = false;
|
||||
}
|
||||
|
||||
if ($CONTACTS->readonly) {
|
||||
$OUTPUT->show_message('addresswriterror', 'error');
|
||||
}
|
||||
else {
|
||||
foreach ((array)$_FILES['_file']['tmp_name'] as $i => $filepath) {
|
||||
// Process uploaded file if there is no error
|
||||
$err = $_FILES['_file']['error'][$i];
|
||||
|
||||
if ($err) {
|
||||
$upload_error = $err;
|
||||
}
|
||||
else {
|
||||
$file_content = file_get_contents($filepath);
|
||||
|
||||
// let rcube_vcard do the hard work :-)
|
||||
$vcard_o = new rcube_vcard();
|
||||
$vcard_o->extend_fieldmap($CONTACTS->vcard_map);
|
||||
$v_list = $vcard_o->import($file_content);
|
||||
|
||||
if (!empty($v_list)) {
|
||||
$vcards = array_merge($vcards, $v_list);
|
||||
continue;
|
||||
}
|
||||
|
||||
// no vCards found, try CSV
|
||||
$csv = new rcube_csv2vcard($_SESSION['language']);
|
||||
$csv->import($file_content);
|
||||
$v_list = $csv->export();
|
||||
|
||||
if (!empty($v_list)) {
|
||||
$vcards = array_merge($vcards, $v_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no vcards detected
|
||||
if (!count($vcards)) {
|
||||
if ($upload_error == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
|
||||
$size = $RCMAIL->show_bytes(rcube_utils::max_upload_size());
|
||||
$OUTPUT->show_message('filesizeerror', 'error', array('size' => $size));
|
||||
}
|
||||
else if ($upload_error) {
|
||||
$OUTPUT->show_message('fileuploaderror', 'error');
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message('importformaterror', 'error');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$IMPORT_STATS = new stdClass;
|
||||
$IMPORT_STATS->names = array();
|
||||
$IMPORT_STATS->skipped_names = array();
|
||||
$IMPORT_STATS->count = count($vcards);
|
||||
$IMPORT_STATS->inserted = $IMPORT_STATS->skipped = $IMPORT_STATS->invalid = $IMPORT_STATS->errors = 0;
|
||||
|
||||
if ($replace) {
|
||||
$CONTACTS->delete_all($CONTACTS->groups && $with_groups < 2);
|
||||
}
|
||||
|
||||
if ($with_groups) {
|
||||
$import_groups = $CONTACTS->list_groups();
|
||||
}
|
||||
|
||||
foreach ($vcards as $vcard) {
|
||||
$a_record = $vcard->get_assoc();
|
||||
|
||||
// Generate contact's display name (must be before validation), the same we do in save.inc
|
||||
if (empty($a_record['name'])) {
|
||||
$a_record['name'] = rcube_addressbook::compose_display_name($a_record, true);
|
||||
// Reset it if equals to email address (from compose_display_name())
|
||||
if ($a_record['name'] == $a_record['email'][0]) {
|
||||
$a_record['name'] = '';
|
||||
}
|
||||
}
|
||||
|
||||
// skip invalid (incomplete) entries
|
||||
if (!$CONTACTS->validate($a_record, true)) {
|
||||
$IMPORT_STATS->invalid++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// We're using UTF8 internally
|
||||
$email = $vcard->email[0];
|
||||
$email = rcube_utils::idn_to_utf8($email);
|
||||
|
||||
if (!$replace) {
|
||||
$existing = null;
|
||||
// compare e-mail address
|
||||
if ($email) {
|
||||
$existing = $CONTACTS->search('email', $email, 1, false);
|
||||
}
|
||||
// compare display name if email not found
|
||||
if ((!$existing || !$existing->count) && $vcard->displayname) {
|
||||
$existing = $CONTACTS->search('name', $vcard->displayname, 1, false);
|
||||
}
|
||||
if ($existing && $existing->count) {
|
||||
$IMPORT_STATS->skipped++;
|
||||
$IMPORT_STATS->skipped_names[] = $vcard->displayname ?: $email;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$a_record['vcard'] = $vcard->export();
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('contact_create',
|
||||
array('record' => $a_record, 'source' => null));
|
||||
$a_record = $plugin['record'];
|
||||
|
||||
// insert record and send response
|
||||
if (!$plugin['abort'])
|
||||
$success = $CONTACTS->insert($a_record);
|
||||
else
|
||||
$success = $plugin['result'];
|
||||
|
||||
if ($success) {
|
||||
// assign groups for this contact (if enabled)
|
||||
if ($with_groups && !empty($a_record['groups'])) {
|
||||
foreach (explode(',', $a_record['groups'][0]) as $group_name) {
|
||||
if ($group_id = rcmail_import_group_id($group_name, $CONTACTS, $with_groups == 1, $import_groups)) {
|
||||
$CONTACTS->add_to_group($group_id, $success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$IMPORT_STATS->inserted++;
|
||||
$IMPORT_STATS->names[] = $a_record['name'] ?: $email;
|
||||
}
|
||||
else {
|
||||
$IMPORT_STATS->errors++;
|
||||
}
|
||||
}
|
||||
|
||||
$importstep = 'rcmail_import_confirm';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$OUTPUT->set_pagetitle($RCMAIL->gettext('importcontacts'));
|
||||
|
||||
$OUTPUT->add_handlers(array(
|
||||
'importstep' => $importstep,
|
||||
'importnav' => 'rcmail_import_buttons',
|
||||
));
|
||||
|
||||
// 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(array('rcube', '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(array('rcube', '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 {
|
||||
$cancel = $OUTPUT->button(array('command' => 'list', 'label' => 'cancel') + $attrib);
|
||||
$attrib['class'] = trim($attrib['class'] . ' mainaction');
|
||||
$out = $OUTPUT->button(array('command' => 'import', 'label' => 'import') + $attrib);
|
||||
$out .= ' ';
|
||||
$out .= $cancel;
|
||||
}
|
||||
|
||||
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 $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;
|
||||
}
|
75
data/web/rc/program/steps/addressbook/list.inc
Normal file
75
data/web/rc/program/steps/addressbook/list.inc
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/list.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2012, 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: |
|
||||
| Send contacts list to client (as remote response) |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
if (!empty($_GET['_page']))
|
||||
$page = intval($_GET['_page']);
|
||||
else
|
||||
$page = $_SESSION['page'] ?: 1;
|
||||
|
||||
$_SESSION['page'] = $page;
|
||||
|
||||
// Use search result
|
||||
if (($records = rcmail_search_update(true)) !== false) {
|
||||
// sort the records
|
||||
ksort($records, SORT_LOCALE_STRING);
|
||||
|
||||
// create resultset object
|
||||
$count = count($records);
|
||||
$first = ($page-1) * $PAGE_SIZE;
|
||||
$result = new rcube_result_set($count, $first);
|
||||
|
||||
// we need only records for current page
|
||||
if ($PAGE_SIZE < $count) {
|
||||
$records = array_slice($records, $first, $PAGE_SIZE);
|
||||
}
|
||||
|
||||
$result->records = array_values($records);
|
||||
}
|
||||
// List selected directory
|
||||
else {
|
||||
$afields = $RCMAIL->config->get('contactlist_fields');
|
||||
$CONTACTS = rcmail_contact_source(null, true);
|
||||
|
||||
// get contacts for this user
|
||||
$result = $CONTACTS->list_records($afields);
|
||||
|
||||
if (!$result->count && $result->searchonly) {
|
||||
$OUTPUT->show_message('contactsearchonly', 'notice');
|
||||
$OUTPUT->command('command', 'advanced-search');
|
||||
}
|
||||
|
||||
if ($CONTACTS->group_id) {
|
||||
$group_data = array('ID' => $CONTACTS->group_id)
|
||||
+ array_intersect_key((array)$CONTACTS->get_group($CONTACTS->group_id), array('name'=>1,'email'=>1));
|
||||
}
|
||||
}
|
||||
|
||||
$OUTPUT->command('set_group_prop', $group_data);
|
||||
|
||||
// update message count display
|
||||
$OUTPUT->set_env('pagecount', ceil($result->count / $PAGE_SIZE));
|
||||
$OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result));
|
||||
|
||||
// create javascript list
|
||||
rcmail_js_contacts_list($result);
|
||||
|
||||
// send response
|
||||
$OUTPUT->send();
|
76
data/web/rc/program/steps/addressbook/mailto.inc
Normal file
76
data/web/rc/program/steps/addressbook/mailto.inc
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/mailto.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2007-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Compose a recipient list with all selected contacts |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$cids = rcmail_get_cids();
|
||||
$mailto = array();
|
||||
$sources = array();
|
||||
|
||||
foreach ($cids as $source => $cid) {
|
||||
$CONTACTS = $RCMAIL->get_address_book($source);
|
||||
|
||||
if ($CONTACTS->ready) {
|
||||
$CONTACTS->set_page(1);
|
||||
$CONTACTS->set_pagesize(count($cid) + 2); // +2 to skip counting query
|
||||
$sources[] = $CONTACTS->search($CONTACTS->primary_key, $cid, 0, true, true, 'email');
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($_REQUEST['_gid']) && isset($_REQUEST['_source'])) {
|
||||
$source = rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC);
|
||||
$CONTACTS = $RCMAIL->get_address_book($source);
|
||||
|
||||
$group_id = rcube_utils::get_input_value('_gid', rcube_utils::INPUT_GPC);
|
||||
$group_data = $CONTACTS->get_group($group_id);
|
||||
|
||||
// group has an email address assigned: use that
|
||||
if ($group_data['email']) {
|
||||
$mailto[] = format_email_recipient($group_data['email'][0], $group_data['name']);
|
||||
}
|
||||
else if ($CONTACTS->ready) {
|
||||
$CONTACTS->set_group($group_id);
|
||||
$CONTACTS->set_page(1);
|
||||
$CONTACTS->set_pagesize(200); // limit somehow
|
||||
$sources[] = $CONTACTS->list_records();
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($sources as $source) {
|
||||
while (is_object($source) && ($rec = $source->iterate())) {
|
||||
$emails = $CONTACTS->get_col_values('email', $rec, true);
|
||||
|
||||
if (!empty($emails)) {
|
||||
$mailto[] = format_email_recipient($emails[0], $rec['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($mailto)) {
|
||||
$mailto_str = join(', ', $mailto);
|
||||
$mailto_id = substr(md5($mailto_str), 0, 16);
|
||||
$_SESSION['mailto'][$mailto_id] = urlencode($mailto_str);
|
||||
$OUTPUT->command('open_compose_step', array('_mailto' => $mailto_id));
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message('nocontactsfound', 'warning');
|
||||
}
|
||||
|
||||
// send response
|
||||
$OUTPUT->send();
|
214
data/web/rc/program/steps/addressbook/move.inc
Normal file
214
data/web/rc/program/steps/addressbook/move.inc
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/move.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2007-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Move a contact record from one direcotry to another |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// only process ajax requests
|
||||
if (!$OUTPUT->ajax_call) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cids = rcmail_get_cids();
|
||||
$target = rcube_utils::get_input_value('_to', rcube_utils::INPUT_POST);
|
||||
$target_group = rcube_utils::get_input_value('_togid', rcube_utils::INPUT_POST);
|
||||
|
||||
$all = 0;
|
||||
$deleted = 0;
|
||||
$success = 0;
|
||||
$errormsg = 'moveerror';
|
||||
$maxnum = $RCMAIL->config->get('max_group_members', 0);
|
||||
$page = $_SESSION['page'] ?: 1;
|
||||
|
||||
foreach ($cids as $source => $source_cids) {
|
||||
// Something wrong, target not specified
|
||||
if (!strlen($target)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// It maight happen when moving records from search result
|
||||
// Do nothing, go to next source
|
||||
if ((string)$target === (string)$source) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$CONTACTS = $RCMAIL->get_address_book($source);
|
||||
$TARGET = $RCMAIL->get_address_book($target);
|
||||
|
||||
if (!$TARGET || !$TARGET->ready || $TARGET->readonly) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!$CONTACTS || !$CONTACTS->ready || $CONTACTS->readonly) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ids = array();
|
||||
|
||||
foreach ($source_cids as $idx => $cid) {
|
||||
$a_record = $CONTACTS->get_record($cid, true);
|
||||
|
||||
// avoid moving groups
|
||||
if ($a_record['_type'] == 'group') {
|
||||
unset($source_cids[$idx]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if contact exists, if so, we'll need it's ID
|
||||
// Note: Some addressbooks allows empty email address field
|
||||
// @TODO: should we check all email addresses?
|
||||
$email = $CONTACTS->get_col_values('email', $a_record, true);
|
||||
if (!empty($email))
|
||||
$result = $TARGET->search('email', $email[0], 1, true, true);
|
||||
else if (!empty($a_record['name']))
|
||||
$result = $TARGET->search('name', $a_record['name'], 1, true, true);
|
||||
else
|
||||
$result = new rcube_result_set();
|
||||
|
||||
// insert contact record
|
||||
if (!$result->count) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('contact_create', array(
|
||||
'record' => $a_record, 'source' => $target, 'group' => $target_group));
|
||||
|
||||
if (!$plugin['abort']) {
|
||||
if ($insert_id = $TARGET->insert($plugin['record'], false)) {
|
||||
$ids[] = $insert_id;
|
||||
$success++;
|
||||
}
|
||||
}
|
||||
else if ($plugin['result']) {
|
||||
$ids = array_merge($ids, $plugin['result']);
|
||||
$success++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$record = $result->first();
|
||||
$ids[] = $record['ID'];
|
||||
$errormsg = empty($email) ? 'contactnameexists' : 'contactexists';
|
||||
}
|
||||
}
|
||||
|
||||
// remove source contacts
|
||||
if ($success && !empty($source_cids)) {
|
||||
$all += count($source_cids);
|
||||
$plugin = $RCMAIL->plugins->exec_hook('contact_delete', array(
|
||||
'id' => $source_cids, 'source' => $source));
|
||||
|
||||
$del_status = !$plugin['abort'] ? $CONTACTS->delete($source_cids) : $plugin['result'];
|
||||
|
||||
if ($del_status) {
|
||||
$deleted += $del_status;
|
||||
}
|
||||
}
|
||||
|
||||
// assign to group
|
||||
if ($target_group && $TARGET->groups && !empty($ids)) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('group_addmembers', array(
|
||||
'group_id' => $target_group, 'ids' => $ids, 'source' => $target));
|
||||
|
||||
if (!$plugin['abort']) {
|
||||
$TARGET->reset();
|
||||
$TARGET->set_group($target_group);
|
||||
|
||||
if ($maxnum && ($TARGET->count()->count + count($plugin['ids']) > $maxnum)) {
|
||||
$OUTPUT->show_message('maxgroupmembersreached', 'warning', array('max' => $maxnum));
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
if (($cnt = $TARGET->add_to_group($target_group, $plugin['ids'])) && $cnt > $success)
|
||||
$success = $cnt;
|
||||
}
|
||||
else if ($plugin['result']) {
|
||||
$success = $plugin['result'];
|
||||
}
|
||||
|
||||
$errormsg = $plugin['message'] ?: 'moveerror';
|
||||
}
|
||||
}
|
||||
|
||||
if (!$deleted || $deleted != $all) {
|
||||
$OUTPUT->command('list_contacts');
|
||||
}
|
||||
else {
|
||||
// update saved search after data changed
|
||||
if (($records = rcmail_search_update(true)) !== false) {
|
||||
// create resultset object
|
||||
$count = count($records);
|
||||
$first = ($page-1) * $PAGE_SIZE;
|
||||
$result = new rcube_result_set($count, $first);
|
||||
$pages = ceil((count($records) + $delcnt) / $PAGE_SIZE);
|
||||
|
||||
// last page and it's empty, display previous one
|
||||
if ($result->count && $result->count <= ($PAGE_SIZE * ($page - 1))) {
|
||||
$OUTPUT->command('list_page', 'prev');
|
||||
$rowcount = $RCMAIL->gettext('loading');
|
||||
}
|
||||
// get records from the next page to add to the list
|
||||
else if ($pages > 1 && $page < $pages) {
|
||||
// sort the records
|
||||
ksort($records, SORT_LOCALE_STRING);
|
||||
|
||||
$first += $PAGE_SIZE;
|
||||
// create resultset object
|
||||
$res = new rcube_result_set($count, $first - $deleted);
|
||||
|
||||
if ($PAGE_SIZE < $count) {
|
||||
$records = array_slice($records, $first - $deleted, $deleted);
|
||||
}
|
||||
|
||||
$res->records = array_values($records);
|
||||
$records = $res;
|
||||
}
|
||||
else {
|
||||
unset($records);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// count contacts for this user
|
||||
$result = $CONTACTS->count();
|
||||
$pages = ceil(($result->count + $deleted) / $PAGE_SIZE);
|
||||
|
||||
// last page and it's empty, display previous one
|
||||
if ($result->count && $result->count <= ($PAGE_SIZE * ($page - 1))) {
|
||||
$OUTPUT->command('list_page', 'prev');
|
||||
$rowcount = $RCMAIL->gettext('loading');
|
||||
}
|
||||
// get records from the next page to add to the list
|
||||
else if ($pages > 1 && $page < $pages) {
|
||||
$CONTACTS->set_page($page);
|
||||
$records = $CONTACTS->list_records(null, -$deleted);
|
||||
}
|
||||
}
|
||||
|
||||
// update message count display
|
||||
$OUTPUT->set_env('pagecount', ceil($result->count / $PAGE_SIZE));
|
||||
$OUTPUT->command('set_rowcount', $rowcount ?: rcmail_get_rowcount_text($result));
|
||||
|
||||
// add new rows from next page (if any)
|
||||
if (!empty($records)) {
|
||||
rcmail_js_contacts_list($records);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$success)
|
||||
$OUTPUT->show_message($errormsg, 'error');
|
||||
else
|
||||
$OUTPUT->show_message('movesuccess', 'notice', array('nr' => $success));
|
||||
|
||||
// send response
|
||||
$OUTPUT->send();
|
99
data/web/rc/program/steps/addressbook/photo.inc
Normal file
99
data/web/rc/program/steps/addressbook/photo.inc
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/photo.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Show contact photo |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// Get contact ID and source ID from request
|
||||
$cids = rcmail_get_cids();
|
||||
$source = key($cids);
|
||||
$cid = $cids ? array_shift($cids[$source]) : null;
|
||||
|
||||
// read the referenced file
|
||||
if (($file_id = rcube_utils::get_input_value('_photo', rcube_utils::INPUT_GPC)) && ($tempfile = $_SESSION['contacts']['files'][$file_id])) {
|
||||
$tempfile = $RCMAIL->plugins->exec_hook('attachment_display', $tempfile);
|
||||
if ($tempfile['status']) {
|
||||
if ($tempfile['data'])
|
||||
$data = $tempfile['data'];
|
||||
else if ($tempfile['path'])
|
||||
$data = file_get_contents($tempfile['path']);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// by email, search for contact first
|
||||
if ($email = rcube_utils::get_input_value('_email', rcube_utils::INPUT_GPC)) {
|
||||
foreach ($RCMAIL->get_address_sources() as $s) {
|
||||
$abook = $RCMAIL->get_address_book($s['id']);
|
||||
$result = $abook->search(array('email'), $email, 1, true, true, 'photo');
|
||||
while ($result && ($record = $result->iterate())) {
|
||||
if ($record['photo'])
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// by contact id
|
||||
if (!$record && $cid) {
|
||||
// Initialize addressbook source
|
||||
$CONTACTS = rcmail_contact_source($source, true);
|
||||
$SOURCE_ID = $source;
|
||||
// read contact record
|
||||
$record = $CONTACTS->get_record($cid, true);
|
||||
}
|
||||
|
||||
if ($record['photo']) {
|
||||
$data = is_array($record['photo']) ? $record['photo'][0] : $record['photo'];
|
||||
if (!preg_match('![^a-z0-9/=+-]!i', $data))
|
||||
$data = base64_decode($data, true);
|
||||
}
|
||||
}
|
||||
|
||||
// let plugins do fancy things with contact photos
|
||||
$plugin = $RCMAIL->plugins->exec_hook('contact_photo',
|
||||
array('record' => $record, 'email' => $email, 'data' => $data));
|
||||
|
||||
// redirect to url provided by a plugin
|
||||
if ($plugin['url']) {
|
||||
$RCMAIL->output->redirect($plugin['url']);
|
||||
}
|
||||
|
||||
$data = $plugin['data'];
|
||||
|
||||
// detect if photo data is an URL
|
||||
if (strlen($data) < 1024 && filter_var($data, FILTER_VALIDATE_URL)) {
|
||||
$RCMAIL->output->redirect($data);
|
||||
}
|
||||
|
||||
// cache for one day if requested by email
|
||||
if (!$cid && $email) {
|
||||
$RCMAIL->output->future_expire_header(86400);
|
||||
}
|
||||
|
||||
if ($data) {
|
||||
header('Content-Type: ' . rcube_mime::image_content_type($data));
|
||||
echo $data;
|
||||
}
|
||||
else if (!empty($_GET['_error'])) {
|
||||
header('HTTP/1.0 404 Photo not found');
|
||||
}
|
||||
else {
|
||||
header('Content-Type: image/gif');
|
||||
echo base64_decode(rcmail_output::BLANK_GIF);
|
||||
}
|
||||
exit;
|
138
data/web/rc/program/steps/addressbook/print.inc
Normal file
138
data/web/rc/program/steps/addressbook/print.inc
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/print.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2015, The Roundcube Dev Team |
|
||||
| Copyright (C) 2011-2015, Kolab Systems AG |
|
||||
| |
|
||||
| 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: |
|
||||
| Print contact details |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
| Author: Aleksander Machniak <machniak@kolabsys.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// Get contact ID and source ID from request
|
||||
$cids = rcmail_get_cids();
|
||||
$source = key($cids);
|
||||
$cid = $cids ? array_shift($cids[$source]) : null;
|
||||
|
||||
// Initialize addressbook source
|
||||
$CONTACTS = rcmail_contact_source($source, true);
|
||||
$SOURCE_ID = $source;
|
||||
|
||||
// read contact record
|
||||
if ($cid && $CONTACTS) {
|
||||
$record = $CONTACTS->get_record($cid, true);
|
||||
}
|
||||
|
||||
$OUTPUT->add_handlers(array(
|
||||
'contacthead' => 'rcmail_contact_head',
|
||||
'contactdetails' => 'rcmail_contact_details',
|
||||
'contactphoto' => 'rcmail_contact_photo',
|
||||
));
|
||||
|
||||
$OUTPUT->send('contactprint');
|
||||
|
||||
|
||||
|
||||
function rcmail_contact_head($attrib)
|
||||
{
|
||||
global $CONTACTS, $RCMAIL;
|
||||
|
||||
// check if we have a valid result
|
||||
if (!(($result = $CONTACTS->get_result()) && ($record = $result->first()))) {
|
||||
$RCMAIL->output->show_message('contactnotfound', 'error');
|
||||
return false;
|
||||
}
|
||||
|
||||
$form = array(
|
||||
'head' => array( // section 'head' is magic!
|
||||
'name' => $RCMAIL->gettext('contactnameandorg'),
|
||||
'content' => array(
|
||||
'prefix' => array(),
|
||||
'name' => array(),
|
||||
'firstname' => array(),
|
||||
'middlename' => array(),
|
||||
'surname' => array(),
|
||||
'suffix' => array(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
unset($attrib['name']);
|
||||
return rcmail_contact_form($form, $record, $attrib);
|
||||
}
|
||||
|
||||
|
||||
function rcmail_contact_details($attrib)
|
||||
{
|
||||
global $CONTACTS, $RCMAIL, $CONTACT_COLTYPES;
|
||||
|
||||
// check if we have a valid result
|
||||
if (!(($result = $CONTACTS->get_result()) && ($record = $result->first()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$i_size = $attrib['size'] ?: 40;
|
||||
|
||||
$form = array(
|
||||
'contact' => array(
|
||||
'name' => $RCMAIL->gettext('properties'),
|
||||
'content' => array(
|
||||
'organization' => array(),
|
||||
'department' => array(),
|
||||
'jobtitle' => array(),
|
||||
'email' => array(),
|
||||
'phone' => array(),
|
||||
'address' => array(),
|
||||
'website' => array(),
|
||||
'im' => array(),
|
||||
'groups' => array(),
|
||||
),
|
||||
),
|
||||
'personal' => array(
|
||||
'name' => $RCMAIL->gettext('personalinfo'),
|
||||
'content' => array(
|
||||
'nickname' => array(),
|
||||
'gender' => array(),
|
||||
'maidenname' => array(),
|
||||
'birthday' => array(),
|
||||
'anniversary' => array(),
|
||||
'manager' => array(),
|
||||
'assistant' => array(),
|
||||
'spouse' => array(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (isset($CONTACT_COLTYPES['notes'])) {
|
||||
$form['notes'] = array(
|
||||
'name' => $RCMAIL->gettext('notes'),
|
||||
'content' => array(
|
||||
'notes' => array('type' => 'textarea', 'label' => false),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if ($CONTACTS->groups) {
|
||||
$groups = $CONTACTS->get_record_groups($record['ID']);
|
||||
if (!empty($groups)) {
|
||||
$form['contact']['content']['groups'] = array(
|
||||
'value' => rcube::Q(implode(', ', $groups)),
|
||||
'label' => $RCMAIL->gettext('groups')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return rcmail_contact_form($form, $record);
|
||||
}
|
75
data/web/rc/program/steps/addressbook/qrcode.inc
Normal file
75
data/web/rc/program/steps/addressbook/qrcode.inc
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/qrcode.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2016, 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: |
|
||||
| Show contact data as QR code |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// Get contact ID and source ID from request
|
||||
$cids = rcmail_get_cids();
|
||||
$source = key($cids);
|
||||
$cid = $cids ? array_shift($cids[$source]) : null;
|
||||
|
||||
// read contact record
|
||||
$abook = rcmail_contact_source($source, true);
|
||||
$contact = $abook->get_record($cid, true);
|
||||
|
||||
// generate QR code image
|
||||
if ($data = rcmail_contact_qrcode($contact)) {
|
||||
header('Content-Type: image/png');
|
||||
header('Content-Length: ' . strlen($data));
|
||||
echo $data;
|
||||
}
|
||||
else {
|
||||
header('HTTP/1.0 404 Contact not found');
|
||||
}
|
||||
|
||||
exit;
|
||||
|
||||
|
||||
function rcmail_contact_qrcode($contact)
|
||||
{
|
||||
$vcard = new rcube_vcard();
|
||||
|
||||
// QR code input is limited, use only common fields
|
||||
$fields = array('firstname', 'surname', 'middlename', 'nickname', 'organization',
|
||||
'prefix', 'suffix', 'phone', 'email', 'jobtitle');
|
||||
|
||||
foreach ($contact as $field => $value) {
|
||||
list($field, $section) = explode(':', $field, 2);
|
||||
if (in_array($field, $fields)) {
|
||||
foreach ((array) $value as $v) {
|
||||
$vcard->set($field, $v, $section);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data = $vcard->export();
|
||||
|
||||
$qrCode = new Endroid\QrCode\QrCode();
|
||||
$qrCode
|
||||
->setText($data)
|
||||
->setSize(300)
|
||||
->setPadding(0)
|
||||
->setErrorCorrection('high')
|
||||
// ->setLabel('Scan the code')
|
||||
// ->setLabelFontSize(16)
|
||||
->setForegroundColor(array('r' => 0, 'g' => 0, 'b' => 0, 'a' => 0))
|
||||
->setBackgroundColor(array('r' => 255, 'g' => 255, 'b' => 255, 'a' => 0));
|
||||
|
||||
return $qrCode->get('png');
|
||||
}
|
265
data/web/rc/program/steps/addressbook/save.inc
Normal file
265
data/web/rc/program/steps/addressbook/save.inc
Normal file
@@ -0,0 +1,265 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/save.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Save a contact entry or to add a new one |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$CONTACTS = rcmail_contact_source(null, true, true);
|
||||
$cid = rcube_utils::get_input_value('_cid', rcube_utils::INPUT_POST);
|
||||
$return_action = empty($cid) ? 'add' : 'edit';
|
||||
|
||||
// Source changed, display the form again
|
||||
if (!empty($_GET['_reload'])) {
|
||||
$RCMAIL->overwrite_action($return_action);
|
||||
return;
|
||||
}
|
||||
|
||||
// cannot edit record
|
||||
if ($CONTACTS->readonly) {
|
||||
$OUTPUT->show_message('contactreadonly', 'error');
|
||||
$RCMAIL->overwrite_action($return_action);
|
||||
return;
|
||||
}
|
||||
|
||||
// read POST values into hash array
|
||||
$a_record = array();
|
||||
foreach ($GLOBALS['CONTACT_COLTYPES'] as $col => $colprop) {
|
||||
if ($colprop['composite']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fname = '_'.$col;
|
||||
|
||||
// gather form data of composite fields
|
||||
if ($colprop['childs']) {
|
||||
$values = array();
|
||||
foreach ($colprop['childs'] as $childcol => $cp) {
|
||||
$vals = rcube_utils::get_input_value('_'.$childcol, rcube_utils::INPUT_POST, true);
|
||||
foreach ((array)$vals as $i => $val) {
|
||||
$values[$i][$childcol] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
$subtypes = isset($_REQUEST['_subtype_' . $col]) ? (array)rcube_utils::get_input_value('_subtype_' . $col, rcube_utils::INPUT_POST) : array('');
|
||||
foreach ($subtypes as $i => $subtype) {
|
||||
$suffix = $subtype ? ':'.$subtype : '';
|
||||
if ($values[$i]) {
|
||||
$a_record[$col.$suffix][] = $values[$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
// assign values and subtypes
|
||||
else if (is_array($_POST[$fname])) {
|
||||
$values = rcube_utils::get_input_value($fname, rcube_utils::INPUT_POST, true);
|
||||
$subtypes = rcube_utils::get_input_value('_subtype_' . $col, rcube_utils::INPUT_POST);
|
||||
|
||||
foreach ($values as $i => $val) {
|
||||
if ($col == 'email') {
|
||||
// extract email from full address specification, e.g. "Name" <addr@domain.tld>
|
||||
$addr = rcube_mime::decode_address_list($val, 1, false);
|
||||
if (!empty($addr) && ($addr = array_pop($addr)) && $addr['mailto']) {
|
||||
$val = $addr['mailto'];
|
||||
}
|
||||
}
|
||||
|
||||
$subtype = $subtypes[$i] ? ':'.$subtypes[$i] : '';
|
||||
$a_record[$col.$subtype][] = $val;
|
||||
}
|
||||
}
|
||||
else if (isset($_POST[$fname])) {
|
||||
$a_record[$col] = rcube_utils::get_input_value($fname, rcube_utils::INPUT_POST, true);
|
||||
|
||||
// normalize the submitted date strings
|
||||
if ($colprop['type'] == 'date') {
|
||||
if ($a_record[$col] && ($dt = rcube_utils::anytodatetime($a_record[$col]))) {
|
||||
$a_record[$col] = $dt->format('Y-m-d');
|
||||
}
|
||||
else {
|
||||
unset($a_record[$col]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate contact's display name (must be before validation)
|
||||
if (empty($a_record['name'])) {
|
||||
$a_record['name'] = rcube_addressbook::compose_display_name($a_record, true);
|
||||
|
||||
// Reset it if equals to email address (from compose_display_name())
|
||||
$email = rcube_addressbook::get_col_values('email', $a_record, true);
|
||||
if ($a_record['name'] == $email[0]) {
|
||||
$a_record['name'] = '';
|
||||
}
|
||||
}
|
||||
|
||||
// do input checks (delegated to $CONTACTS instance)
|
||||
if (!$CONTACTS->validate($a_record)) {
|
||||
$err = (array)$CONTACTS->get_error();
|
||||
$OUTPUT->show_message($err['message'] ? rcube::Q($err['message']) : 'formincomplete', 'warning');
|
||||
$GLOBALS['EDIT_RECORD'] = $a_record; // store submitted data to be used in edit form
|
||||
$RCMAIL->overwrite_action($return_action);
|
||||
return;
|
||||
}
|
||||
|
||||
// get raw photo data if changed
|
||||
if (isset($a_record['photo'])) {
|
||||
if ($a_record['photo'] == '-del-') {
|
||||
$a_record['photo'] = '';
|
||||
}
|
||||
else if ($tempfile = $_SESSION['contacts']['files'][$a_record['photo']]) {
|
||||
$tempfile = $RCMAIL->plugins->exec_hook('attachment_get', $tempfile);
|
||||
if ($tempfile['status'])
|
||||
$a_record['photo'] = $tempfile['data'] ?: @file_get_contents($tempfile['path']);
|
||||
}
|
||||
else
|
||||
unset($a_record['photo']);
|
||||
|
||||
// cleanup session data
|
||||
$RCMAIL->plugins->exec_hook('attachments_cleanup', array('group' => 'contact'));
|
||||
$RCMAIL->session->remove('contacts');
|
||||
}
|
||||
|
||||
$source = rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC);
|
||||
|
||||
// update an existing contact
|
||||
if (!empty($cid)) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('contact_update',
|
||||
array('id' => $cid, 'record' => $a_record, 'source' => $source));
|
||||
$a_record = $plugin['record'];
|
||||
|
||||
if (!$plugin['abort'])
|
||||
$result = $CONTACTS->update($cid, $a_record);
|
||||
else
|
||||
$result = $plugin['result'];
|
||||
|
||||
if ($result) {
|
||||
// show confirmation
|
||||
$OUTPUT->show_message('successfullysaved', 'confirmation', null, false);
|
||||
|
||||
// in search mode, just reload the list (#1490015)
|
||||
if ($_REQUEST['_search']) {
|
||||
$OUTPUT->command('parent.command', 'list');
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
|
||||
// LDAP DN change
|
||||
if (is_string($result) && strlen($result) > 1) {
|
||||
$newcid = $result;
|
||||
// change cid in POST for 'show' action
|
||||
$_POST['_cid'] = $newcid;
|
||||
}
|
||||
|
||||
// refresh contact data for list update and 'show' action
|
||||
$CONTACT_RECORD = $CONTACTS->get_record($newcid ?: $cid, true);
|
||||
|
||||
// Plugins can decide to remove the contact on edit, e.g. automatic_addressbook
|
||||
// Best we can do is to refresh the list (#5522)
|
||||
if (empty($CONTACT_RECORD)) {
|
||||
$OUTPUT->command('parent.command', 'list');
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
|
||||
// Update contacts list
|
||||
$a_js_cols = array();
|
||||
$record = $CONTACT_RECORD;
|
||||
$record['email'] = reset($CONTACTS->get_col_values('email', $record, true));
|
||||
$record['name'] = rcube_addressbook::compose_list_name($record);
|
||||
|
||||
foreach (array('name') as $col) {
|
||||
$a_js_cols[] = rcube::Q((string)$record[$col]);
|
||||
}
|
||||
|
||||
// performance: unset some big data items we don't need here
|
||||
$record = array_intersect_key($record, array('ID' => 1,'email' => 1,'name' => 1));
|
||||
$record['_type'] = 'person';
|
||||
|
||||
// update the changed col in list
|
||||
$OUTPUT->command('parent.update_contact_row', $cid, $a_js_cols, $newcid, $source, $record);
|
||||
|
||||
$RCMAIL->overwrite_action('show');
|
||||
}
|
||||
else {
|
||||
// show error message
|
||||
$err = $CONTACTS->get_error();
|
||||
$OUTPUT->show_message($plugin['message'] ?: ($err['message'] ?: 'errorsaving'), 'error', null, false);
|
||||
$RCMAIL->overwrite_action('show');
|
||||
}
|
||||
}
|
||||
|
||||
// insert a new contact
|
||||
else {
|
||||
// Name of the addressbook already selected on the list
|
||||
$orig_source = rcube_utils::get_input_value('_orig_source', rcube_utils::INPUT_GPC);
|
||||
|
||||
if (!strlen($source)) {
|
||||
$source = $orig_source;
|
||||
}
|
||||
|
||||
// show notice if existing contacts with same e-mail are found
|
||||
foreach ($CONTACTS->get_col_values('email', $a_record, true) as $email) {
|
||||
if ($email && ($res = $CONTACTS->search('email', $email, 1, false, true)) && $res->count) {
|
||||
$OUTPUT->show_message('contactexists', 'notice', null, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('contact_create', array(
|
||||
'record' => $a_record, 'source' => $source));
|
||||
$a_record = $plugin['record'];
|
||||
|
||||
// insert record and send response
|
||||
if (!$plugin['abort'])
|
||||
$insert_id = $CONTACTS->insert($a_record);
|
||||
else
|
||||
$insert_id = $plugin['result'];
|
||||
|
||||
if ($insert_id) {
|
||||
$CONTACTS->reset();
|
||||
|
||||
// add new contact to the specified group
|
||||
if ($CONTACTS->groups && $CONTACTS->group_id) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('group_addmembers', array(
|
||||
'group_id' => $CONTACTS->group_id, 'ids' => $insert_id, 'source' => $source));
|
||||
|
||||
if (!$plugin['abort']) {
|
||||
if (($maxnum = $RCMAIL->config->get('max_group_members', 0)) && ($CONTACTS->count()->count + 1 > $maxnum)) {
|
||||
// @FIXME: should we remove the contact?
|
||||
$msgtext = $RCMAIL->gettext(array('name' => 'maxgroupmembersreached', 'vars' => array('max' => $maxnum)));
|
||||
$OUTPUT->command('parent.display_message', $msgtext, 'warning');
|
||||
}
|
||||
else {
|
||||
$CONTACTS->add_to_group($plugin['group_id'], $plugin['ids']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// show confirmation
|
||||
$OUTPUT->show_message('successfullysaved', 'confirmation', null, false);
|
||||
|
||||
$OUTPUT->command('parent.set_rowcount', $RCMAIL->gettext('loading'));
|
||||
$OUTPUT->command('parent.list_contacts');
|
||||
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
else {
|
||||
// show error message
|
||||
$err = $CONTACTS->get_error();
|
||||
$OUTPUT->show_message($plugin['message'] ?: ($err['message'] ?: 'errorsaving'), 'error', null, false);
|
||||
$RCMAIL->overwrite_action('add');
|
||||
}
|
||||
}
|
354
data/web/rc/program/steps/addressbook/search.inc
Normal file
354
data/web/rc/program/steps/addressbook/search.inc
Normal file
@@ -0,0 +1,354 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/search.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2011, The Roundcube Dev Team |
|
||||
| Copyright (C) 2011, Kolab Systems AG |
|
||||
| |
|
||||
| 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: |
|
||||
| Search action (and form) for address book contacts |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
| Author: Aleksander Machniak <machniak@kolabsys.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
if ($RCMAIL->action == 'search-create') {
|
||||
$id = rcube_utils::get_input_value('_search', rcube_utils::INPUT_POST);
|
||||
$name = rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true);
|
||||
|
||||
if (($params = $_SESSION['search_params']) && $params['id'] == $id) {
|
||||
|
||||
$data = array(
|
||||
'type' => rcube_user::SEARCH_ADDRESSBOOK,
|
||||
'name' => $name,
|
||||
'data' => array(
|
||||
'fields' => $params['data'][0],
|
||||
'search' => $params['data'][1],
|
||||
),
|
||||
);
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('saved_search_create', array('data' => $data));
|
||||
|
||||
if (!$plugin['abort'])
|
||||
$result = $RCMAIL->user->insert_search($plugin['data']);
|
||||
else
|
||||
$result = $plugin['result'];
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
$OUTPUT->show_message('savedsearchcreated', 'confirmation');
|
||||
$OUTPUT->command('insert_saved_search', rcube::Q($name), rcube::Q($result));
|
||||
}
|
||||
else
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'savedsearchcreateerror', 'error');
|
||||
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
if ($RCMAIL->action == 'search-delete') {
|
||||
$id = rcube_utils::get_input_value('_sid', rcube_utils::INPUT_POST);
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('saved_search_delete', array('id' => $id));
|
||||
|
||||
if (!$plugin['abort'])
|
||||
$result = $RCMAIL->user->delete_search($id);
|
||||
else
|
||||
$result = $plugin['result'];
|
||||
|
||||
if ($result) {
|
||||
$OUTPUT->show_message('savedsearchdeleted', 'confirmation');
|
||||
$OUTPUT->command('remove_search_item', rcube::Q($id));
|
||||
// contact list will be cleared, clear also page counter
|
||||
$OUTPUT->command('set_rowcount', $RCMAIL->gettext('nocontactsfound'));
|
||||
$OUTPUT->set_env('pagecount', 0);
|
||||
}
|
||||
else
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'savedsearchdeleteerror', 'error');
|
||||
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
|
||||
if (!isset($_GET['_form'])) {
|
||||
rcmail_contact_search();
|
||||
}
|
||||
|
||||
$OUTPUT->add_handler('searchform', 'rcmail_contact_search_form');
|
||||
$OUTPUT->send('contactsearch');
|
||||
|
||||
|
||||
function rcmail_contact_search()
|
||||
{
|
||||
global $RCMAIL, $OUTPUT, $SEARCH_MODS_DEFAULT, $PAGE_SIZE;
|
||||
|
||||
$adv = isset($_POST['_adv']);
|
||||
$sid = rcube_utils::get_input_value('_sid', rcube_utils::INPUT_GET);
|
||||
|
||||
// get search criteria from saved search
|
||||
if ($sid && ($search = $RCMAIL->user->get_search($sid))) {
|
||||
$fields = $search['data']['fields'];
|
||||
$search = $search['data']['search'];
|
||||
}
|
||||
// get fields/values from advanced search form
|
||||
else if ($adv) {
|
||||
foreach (array_keys($_POST) as $key) {
|
||||
$s = trim(rcube_utils::get_input_value($key, rcube_utils::INPUT_POST, true));
|
||||
if (strlen($s) && preg_match('/^_search_([a-zA-Z0-9_-]+)$/', $key, $m)) {
|
||||
$search[] = $s;
|
||||
$fields[] = $m[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($fields)) {
|
||||
// do nothing, show the form again
|
||||
return;
|
||||
}
|
||||
}
|
||||
// quick-search
|
||||
else {
|
||||
$search = trim(rcube_utils::get_input_value('_q', rcube_utils::INPUT_GET, true));
|
||||
$fields = explode(',', rcube_utils::get_input_value('_headers', rcube_utils::INPUT_GET));
|
||||
|
||||
if (empty($fields)) {
|
||||
$fields = array_keys($SEARCH_MODS_DEFAULT);
|
||||
}
|
||||
else {
|
||||
$fields = array_filter($fields);
|
||||
}
|
||||
|
||||
// update search_mods setting
|
||||
$old_mods = $RCMAIL->config->get('addressbook_search_mods');
|
||||
$search_mods = array_fill_keys($fields, 1);
|
||||
if ($old_mods != $search_mods) {
|
||||
$RCMAIL->user->save_prefs(array('addressbook_search_mods' => $search_mods));
|
||||
}
|
||||
|
||||
if (in_array('*', $fields)) {
|
||||
$fields = '*';
|
||||
}
|
||||
}
|
||||
|
||||
// Values matching mode
|
||||
$mode = (int) $RCMAIL->config->get('addressbook_search_mode');
|
||||
$mode |= rcube_addressbook::SEARCH_GROUPS;
|
||||
|
||||
// get sources list
|
||||
$sources = $RCMAIL->get_address_sources();
|
||||
$search_set = array();
|
||||
$records = array();
|
||||
$sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
|
||||
$afields = $RCMAIL->config->get('contactlist_fields');
|
||||
|
||||
foreach ($sources as $s) {
|
||||
$source = $RCMAIL->get_address_book($s['id']);
|
||||
|
||||
// check if search fields are supported....
|
||||
if (is_array($fields)) {
|
||||
$cols = $source->coltypes[0] ? array_flip($source->coltypes) : $source->coltypes;
|
||||
$supported = 0;
|
||||
|
||||
foreach ($fields as $f) {
|
||||
if (array_key_exists($f, $cols)) {
|
||||
$supported ++;
|
||||
}
|
||||
}
|
||||
|
||||
// in advanced search we require all fields (AND operator)
|
||||
// in quick search we require at least one field (OR operator)
|
||||
if (($adv && $supported < count($fields)) || (!$adv && !$supported)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// reset page
|
||||
$source->set_page(1);
|
||||
$source->set_pagesize(9999);
|
||||
|
||||
// get contacts count
|
||||
$result = $source->search($fields, $search, $mode, false);
|
||||
|
||||
if (!$result->count) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// get records
|
||||
$result = $source->list_records($afields);
|
||||
|
||||
while ($row = $result->next()) {
|
||||
$row['sourceid'] = $s['id'];
|
||||
$key = rcube_addressbook::compose_contact_key($row, $sort_col);
|
||||
$records[$key] = $row;
|
||||
}
|
||||
|
||||
unset($result);
|
||||
$search_set[$s['id']] = $source->get_search_set();
|
||||
}
|
||||
|
||||
// sort the records
|
||||
ksort($records, SORT_LOCALE_STRING);
|
||||
|
||||
// create resultset object
|
||||
$count = count($records);
|
||||
$result = new rcube_result_set($count);
|
||||
|
||||
// cut first-page records
|
||||
if ($PAGE_SIZE < $count) {
|
||||
$records = array_slice($records, 0, $PAGE_SIZE);
|
||||
}
|
||||
|
||||
$result->records = array_values($records);
|
||||
|
||||
// search request ID
|
||||
$search_request = md5('addr'
|
||||
.(is_array($fields) ? implode($fields, ',') : $fields)
|
||||
.(is_array($search) ? implode($search, ',') : $search));
|
||||
|
||||
// save search settings in session
|
||||
$_SESSION['search'][$search_request] = $search_set;
|
||||
$_SESSION['search_params'] = array('id' => $search_request, 'data' => array($fields, $search));
|
||||
$_SESSION['page'] = 1;
|
||||
|
||||
if ($adv)
|
||||
$OUTPUT->command('list_contacts_clear');
|
||||
|
||||
if ($result->count > 0) {
|
||||
// create javascript list
|
||||
rcmail_js_contacts_list($result);
|
||||
$OUTPUT->show_message('contactsearchsuccessful', 'confirmation', array('nr' => $result->count));
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message('nocontactsfound', 'notice');
|
||||
}
|
||||
|
||||
// update message count display
|
||||
$OUTPUT->set_env('search_request', $search_request);
|
||||
$OUTPUT->set_env('pagecount', ceil($result->count / $PAGE_SIZE));
|
||||
$OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result));
|
||||
// Re-set current source
|
||||
$OUTPUT->set_env('search_id', $sid);
|
||||
$OUTPUT->set_env('source', '');
|
||||
$OUTPUT->set_env('group', '');
|
||||
// Re-set list header
|
||||
$OUTPUT->command('set_group_prop', null);
|
||||
|
||||
if ($adv) {
|
||||
$OUTPUT->command('parent.set_env', array(
|
||||
'search_request' => $search_request,
|
||||
'pagecount' => ceil($result->count / $PAGE_SIZE),
|
||||
'search_id' => $sid,
|
||||
'source' => '',
|
||||
'group' => '',
|
||||
));
|
||||
}
|
||||
|
||||
if (!$sid) {
|
||||
// unselect currently selected directory/group
|
||||
$OUTPUT->command('unselect_directory');
|
||||
// enable "Save search" command
|
||||
$OUTPUT->command('enable_command', 'search-create', true);
|
||||
}
|
||||
$OUTPUT->command('update_group_commands');
|
||||
|
||||
// send response
|
||||
$OUTPUT->send($adv ? 'iframe' : null);
|
||||
}
|
||||
|
||||
function rcmail_contact_search_form($attrib)
|
||||
{
|
||||
global $RCMAIL, $CONTACT_COLTYPES;
|
||||
|
||||
$i_size = $attrib['size'] ?: 30;
|
||||
|
||||
$form = array(
|
||||
'main' => array(
|
||||
'name' => $RCMAIL->gettext('properties'),
|
||||
'content' => array(
|
||||
),
|
||||
),
|
||||
'personal' => array(
|
||||
'name' => $RCMAIL->gettext('personalinfo'),
|
||||
'content' => array(
|
||||
),
|
||||
),
|
||||
'other' => array(
|
||||
'name' => $RCMAIL->gettext('other'),
|
||||
'content' => array(
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// get supported coltypes from all address sources
|
||||
$sources = $RCMAIL->get_address_sources();
|
||||
$coltypes = array();
|
||||
|
||||
foreach ($sources as $s) {
|
||||
$CONTACTS = $RCMAIL->get_address_book($s['id']);
|
||||
|
||||
if (is_array($CONTACTS->coltypes)) {
|
||||
$contact_cols = $CONTACTS->coltypes[0] ? array_flip($CONTACTS->coltypes) : $CONTACTS->coltypes;
|
||||
$coltypes = array_merge($coltypes, $contact_cols);
|
||||
}
|
||||
}
|
||||
|
||||
// merge supported coltypes with $CONTACT_COLTYPES
|
||||
foreach ($coltypes as $col => $colprop) {
|
||||
$coltypes[$col] = $CONTACT_COLTYPES[$col] ? array_merge($CONTACT_COLTYPES[$col], (array)$colprop) : (array)$colprop;
|
||||
}
|
||||
|
||||
// build form fields list
|
||||
foreach ($coltypes as $col => $colprop)
|
||||
{
|
||||
if ($colprop['type'] != 'image' && !$colprop['nosearch'])
|
||||
{
|
||||
$ftype = $colprop['type'] == 'select' ? 'select' : 'text';
|
||||
$label = isset($colprop['label']) ? $colprop['label'] : $RCMAIL->gettext($col);
|
||||
$category = $colprop['category'] ?: 'other';
|
||||
|
||||
// load jquery UI datepicker for date fields
|
||||
if ($colprop['type'] == 'date')
|
||||
$colprop['class'] .= ($colprop['class'] ? ' ' : '') . 'datepicker';
|
||||
else if ($ftype == 'text')
|
||||
$colprop['size'] = $i_size;
|
||||
|
||||
|
||||
$content = html::div('row', html::div('contactfieldlabel label', rcube::Q($label))
|
||||
. html::div('contactfieldcontent', rcube_output::get_edit_field('search_'.$col, '', $colprop, $ftype)));
|
||||
|
||||
$form[$category]['content'][] = $content;
|
||||
}
|
||||
}
|
||||
|
||||
$hiddenfields = new html_hiddenfield();
|
||||
$hiddenfields->add(array('name' => '_adv', 'value' => 1));
|
||||
|
||||
$out = $RCMAIL->output->request_form(array(
|
||||
'name' => 'form', 'method' => 'post',
|
||||
'task' => $RCMAIL->task, 'action' => 'search',
|
||||
'noclose' => true) + $attrib, $hiddenfields->show());
|
||||
|
||||
$RCMAIL->output->add_gui_object('editform', $attrib['id']);
|
||||
|
||||
unset($attrib['name']);
|
||||
unset($attrib['id']);
|
||||
|
||||
foreach ($form as $f) {
|
||||
if (!empty($f['content'])) {
|
||||
$content = html::div('contactfieldgroup', join("\n", $f['content']));
|
||||
|
||||
$out .= html::tag('fieldset', $attrib,
|
||||
html::tag('legend', null, rcube::Q($f['name']))
|
||||
. $content) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $out . '</form>';
|
||||
}
|
208
data/web/rc/program/steps/addressbook/show.inc
Normal file
208
data/web/rc/program/steps/addressbook/show.inc
Normal file
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/show.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Show contact details |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// Get contact ID and source ID from request
|
||||
$cids = rcmail_get_cids();
|
||||
$source = key($cids);
|
||||
$cid = $cids ? array_shift($cids[$source]) : null;
|
||||
|
||||
// Initialize addressbook source
|
||||
$CONTACTS = rcmail_contact_source($source, true);
|
||||
$SOURCE_ID = $source;
|
||||
|
||||
// read contact record (or get the one defined in 'save' action)
|
||||
if ($cid && ($record = ($CONTACT_RECORD ?: $CONTACTS->get_record($cid, true)))) {
|
||||
$OUTPUT->set_env('readonly', $CONTACTS->readonly || $record['readonly']);
|
||||
$OUTPUT->set_env('cid', $record['ID']);
|
||||
|
||||
// remember current search request ID (if in search mode)
|
||||
if ($search = rcube_utils::get_input_value('_search', rcube_utils::INPUT_GET)) {
|
||||
$OUTPUT->set_env('search_request', $search);
|
||||
}
|
||||
}
|
||||
|
||||
// get address book name (for display)
|
||||
rcmail_set_sourcename($CONTACTS);
|
||||
|
||||
// Disable qr-code if php-gd is not installed
|
||||
$OUTPUT->set_env('qrcode', function_exists('imagecreate'));
|
||||
$OUTPUT->add_label('qrcode');
|
||||
|
||||
$OUTPUT->add_handlers(array(
|
||||
'contacthead' => 'rcmail_contact_head',
|
||||
'contactdetails' => 'rcmail_contact_details',
|
||||
'contactphoto' => 'rcmail_contact_photo',
|
||||
));
|
||||
|
||||
$OUTPUT->send('contact');
|
||||
|
||||
|
||||
|
||||
function rcmail_contact_head($attrib)
|
||||
{
|
||||
global $CONTACTS, $RCMAIL;
|
||||
|
||||
// check if we have a valid result
|
||||
if (!(($result = $CONTACTS->get_result()) && ($record = $result->first()))) {
|
||||
$RCMAIL->output->show_message('contactnotfound', 'error');
|
||||
return false;
|
||||
}
|
||||
|
||||
$form = array(
|
||||
'head' => array( // section 'head' is magic!
|
||||
'name' => $RCMAIL->gettext('contactnameandorg'),
|
||||
'content' => array(
|
||||
'prefix' => array('type' => 'text'),
|
||||
'firstname' => array('type' => 'text'),
|
||||
'middlename' => array('type' => 'text'),
|
||||
'surname' => array('type' => 'text'),
|
||||
'suffix' => array('type' => 'text'),
|
||||
'name' => array('type' => 'text'),
|
||||
'nickname' => array('type' => 'text'),
|
||||
'organization' => array('type' => 'text'),
|
||||
'department' => array('type' => 'text'),
|
||||
'jobtitle' => array('type' => 'text'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
unset($attrib['name']);
|
||||
return rcmail_contact_form($form, $record, $attrib);
|
||||
}
|
||||
|
||||
|
||||
function rcmail_contact_details($attrib)
|
||||
{
|
||||
global $CONTACTS, $RCMAIL, $CONTACT_COLTYPES;
|
||||
|
||||
// check if we have a valid result
|
||||
if (!(($result = $CONTACTS->get_result()) && ($record = $result->first()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$i_size = $attrib['size'] ?: 40;
|
||||
|
||||
$form = array(
|
||||
'contact' => array(
|
||||
'name' => $RCMAIL->gettext('properties'),
|
||||
'content' => array(
|
||||
'email' => array('size' => $i_size, 'render_func' => 'rcmail_render_email_value'),
|
||||
'phone' => array('size' => $i_size),
|
||||
'address' => array(),
|
||||
'website' => array('size' => $i_size, 'render_func' => 'rcmail_render_url_value'),
|
||||
'im' => array('size' => $i_size),
|
||||
),
|
||||
),
|
||||
'personal' => array(
|
||||
'name' => $RCMAIL->gettext('personalinfo'),
|
||||
'content' => array(
|
||||
'gender' => array('size' => $i_size),
|
||||
'maidenname' => array('size' => $i_size),
|
||||
'birthday' => array('size' => $i_size),
|
||||
'anniversary' => array('size' => $i_size),
|
||||
'manager' => array('size' => $i_size),
|
||||
'assistant' => array('size' => $i_size),
|
||||
'spouse' => array('size' => $i_size),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (isset($CONTACT_COLTYPES['notes'])) {
|
||||
$form['notes'] = array(
|
||||
'name' => $RCMAIL->gettext('notes'),
|
||||
'content' => array(
|
||||
'notes' => array('type' => 'textarea', 'label' => false),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if ($CONTACTS->groups) {
|
||||
$form['groups'] = array(
|
||||
'name' => $RCMAIL->gettext('groups'),
|
||||
'content' => rcmail_contact_record_groups($record['ID']),
|
||||
);
|
||||
}
|
||||
|
||||
return rcmail_contact_form($form, $record);
|
||||
}
|
||||
|
||||
|
||||
function rcmail_render_email_value($email)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
return html::a(array(
|
||||
'href' => 'mailto:' . $email,
|
||||
'onclick' => sprintf("return %s.command('compose','%s',this)", rcmail_output::JS_OBJECT_NAME, rcube::JQ($email)),
|
||||
'title' => $RCMAIL->gettext('composeto'),
|
||||
'class' => 'email',
|
||||
), rcube::Q($email));
|
||||
}
|
||||
|
||||
|
||||
function rcmail_render_url_value($url)
|
||||
{
|
||||
$prefix = preg_match('!^(http|ftp)s?://!', $url) ? '' : 'http://';
|
||||
return html::a(array(
|
||||
'href' => $prefix . $url,
|
||||
'target' => '_blank',
|
||||
'class' => 'url',
|
||||
), rcube::Q($url));
|
||||
}
|
||||
|
||||
|
||||
function rcmail_contact_record_groups($contact_id)
|
||||
{
|
||||
global $RCMAIL, $CONTACTS, $GROUPS;
|
||||
|
||||
$GROUPS = $CONTACTS->list_groups();
|
||||
|
||||
if (empty($GROUPS)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$members = $CONTACTS->get_record_groups($contact_id);
|
||||
$table = new html_table(array('cols' => 2, 'cellspacing' => 0, 'border' => 0));
|
||||
$checkbox = new html_checkbox(array('name' => '_gid[]',
|
||||
'class' => 'groupmember', 'disabled' => $CONTACTS->readonly));
|
||||
|
||||
foreach ($GROUPS as $group) {
|
||||
$gid = $group['ID'];
|
||||
$table->add(null, $checkbox->show($members[$gid] ? $gid : null,
|
||||
array('value' => $gid, 'id' => 'ff_gid' . $gid)));
|
||||
$table->add(null, html::label('ff_gid' . $gid, rcube::Q($group['name'])));
|
||||
}
|
||||
|
||||
$hiddenfields = new html_hiddenfield(array('name' => '_source', 'value' => rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC)));
|
||||
$hiddenfields->add(array('name' => '_cid', 'value' => $contact_id));
|
||||
|
||||
$form_start = $RCMAIL->output->request_form(array(
|
||||
'name' => "form", 'method' => "post",
|
||||
'task' => $RCMAIL->task, 'action' => 'save',
|
||||
'request' => 'save.'.intval($contact_id),
|
||||
'noclose' => true), $hiddenfields->show());
|
||||
$form_end = '</form>';
|
||||
|
||||
$RCMAIL->output->add_gui_object('editform', 'form');
|
||||
$RCMAIL->output->add_label('addingmember', 'removingmember');
|
||||
|
||||
return $form_start . html::tag('fieldset', 'contactfieldgroup contactgroups', $table->show()) . $form_end;
|
||||
}
|
54
data/web/rc/program/steps/addressbook/undo.inc
Normal file
54
data/web/rc/program/steps/addressbook/undo.inc
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/undo.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| 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. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Undelete contacts (CIDs) from last delete action |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Aleksander Machniak <machniak@kolabsys.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// process ajax requests only
|
||||
if (!$OUTPUT->ajax_call) {
|
||||
return;
|
||||
}
|
||||
|
||||
$undo = $_SESSION['contact_undo'];
|
||||
$delcnt = 0;
|
||||
|
||||
foreach ((array)$undo['data'] as $source => $cid) {
|
||||
$CONTACTS = rcmail_contact_source($source);
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('contact_undelete', array(
|
||||
'id' => $cid, 'source' => $source));
|
||||
|
||||
$restored = !$plugin['abort'] ? $CONTACTS->undelete($cid) : $plugin['result'];
|
||||
|
||||
if (!$restored) {
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'contactrestoreerror', 'error');
|
||||
$OUTPUT->command('list_contacts');
|
||||
$OUTPUT->send();
|
||||
}
|
||||
else {
|
||||
$delcnt += $restored;
|
||||
}
|
||||
}
|
||||
|
||||
$RCMAIL->session->remove('contact_undo');
|
||||
|
||||
$OUTPUT->show_message('contactrestored', 'confirmation');
|
||||
$OUTPUT->command('list_contacts');
|
||||
|
||||
// send response
|
||||
$OUTPUT->send();
|
91
data/web/rc/program/steps/addressbook/upload_photo.inc
Normal file
91
data/web/rc/program/steps/addressbook/upload_photo.inc
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/addressbook/upload_photo.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2011, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Handles contact photo uploads |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// Supported image format types
|
||||
// ImageMagick works with other non-image types (e.g.pdf) we don't want here
|
||||
$IMAGE_TYPES = explode(',', 'jpeg,jpg,jp2,tiff,tif,bmp,eps,gif,png,png8,png24,png32,svg,ico');
|
||||
|
||||
// clear all stored output properties (like scripts and env vars)
|
||||
$OUTPUT->reset();
|
||||
|
||||
if ($filepath = $_FILES['_photo']['tmp_name']) {
|
||||
// check file type and resize image
|
||||
$image = new rcube_image($_FILES['_photo']['tmp_name']);
|
||||
$imageprop = $image->props();
|
||||
|
||||
if (in_array(strtolower($imageprop['type']), $IMAGE_TYPES)
|
||||
&& $imageprop['width'] && $imageprop['height']
|
||||
) {
|
||||
$maxsize = intval($RCMAIL->config->get('contact_photo_size', 160));
|
||||
$tmpfname = tempnam($RCMAIL->config->get('temp_dir'), 'rcmImgConvert');
|
||||
$save_hook = 'attachment_upload';
|
||||
|
||||
// scale image to a maximum size
|
||||
if (($imageprop['width'] > $maxsize || $imageprop['height'] > $maxsize) && $image->resize($maxsize, $tmpfname)) {
|
||||
$filepath = $tmpfname;
|
||||
$save_hook = 'attachment_save';
|
||||
}
|
||||
|
||||
// save uploaded file in storage backend
|
||||
$attachment = $RCMAIL->plugins->exec_hook($save_hook, array(
|
||||
'path' => $filepath,
|
||||
'size' => $_FILES['_photo']['size'],
|
||||
'name' => $_FILES['_photo']['name'],
|
||||
'mimetype' => 'image/' . $imageprop['type'],
|
||||
'group' => 'contact',
|
||||
));
|
||||
}
|
||||
else {
|
||||
$attachment['error'] = $RCMAIL->gettext('invalidimageformat');
|
||||
}
|
||||
|
||||
if ($attachment['status'] && !$attachment['abort']) {
|
||||
$file_id = $attachment['id'];
|
||||
$_SESSION['contacts']['files'][$file_id] = $attachment;
|
||||
$OUTPUT->command('replace_contact_photo', $file_id);
|
||||
}
|
||||
else { // upload failed
|
||||
$err = $_FILES['_photo']['error'];
|
||||
$size = $RCMAIL->show_bytes(rcube_utils::max_upload_size());
|
||||
|
||||
if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE)
|
||||
$msg = $RCMAIL->gettext(array('name' => 'filesizeerror', 'vars' => array('size' => $size)));
|
||||
else if ($attachment['error'])
|
||||
$msg = $attachment['error'];
|
||||
else
|
||||
$msg = $RCMAIL->gettext('fileuploaderror');
|
||||
|
||||
$OUTPUT->command('display_message', $msg, 'error');
|
||||
}
|
||||
}
|
||||
else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
// if filesize exceeds post_max_size then $_FILES array is empty,
|
||||
// show filesizeerror instead of fileuploaderror
|
||||
if ($maxsize = ini_get('post_max_size'))
|
||||
$msg = $RCMAIL->gettext(array('name' => 'filesizeerror', 'vars' => array('size' => $RCMAIL->show_bytes(parse_bytes($maxsize)))));
|
||||
else
|
||||
$msg = $RCMAIL->gettext('fileuploaderror');
|
||||
|
||||
$OUTPUT->command('display_message', $msg, 'error');
|
||||
}
|
||||
|
||||
$OUTPUT->command('photo_upload_end');
|
||||
$OUTPUT->send('iframe');
|
93
data/web/rc/program/steps/mail/addcontact.inc
Normal file
93
data/web/rc/program/steps/mail/addcontact.inc
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/addcontact.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Add the submitted contact to the users address book |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// only process ajax requests
|
||||
if (!$OUTPUT->ajax_call) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get default addressbook
|
||||
$CONTACTS = $RCMAIL->get_address_book(-1, true);
|
||||
|
||||
if (!empty($_POST['_address']) && is_object($CONTACTS)) {
|
||||
$address = rcube_utils::get_input_value('_address', rcube_utils::INPUT_POST, true);
|
||||
$contact_arr = rcube_mime::decode_address_list($address, 1, false);
|
||||
|
||||
if (!empty($contact_arr[1]['mailto'])) {
|
||||
$contact = array(
|
||||
'email' => $contact_arr[1]['mailto'],
|
||||
'name' => $contact_arr[1]['name'],
|
||||
);
|
||||
|
||||
// Validity checks
|
||||
if (empty($contact['email'])) {
|
||||
$OUTPUT->show_message('errorsavingcontact', 'error');
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
$email = rcube_utils::idn_to_ascii($contact['email']);
|
||||
if (!rcube_utils::check_email($email, false)) {
|
||||
$OUTPUT->show_message('emailformaterror', 'error', array('email' => $contact['email']));
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
$contact['email'] = rcube_utils::idn_to_utf8($contact['email']);
|
||||
|
||||
$contact = $RCMAIL->plugins->exec_hook('contact_displayname', $contact);
|
||||
|
||||
if (empty($contact['firstname']) || empty($contact['surname'])) {
|
||||
$contact['name'] = rcube_addressbook::compose_display_name($contact);
|
||||
}
|
||||
|
||||
// validate contact record
|
||||
if (!$CONTACTS->validate($contact, true)) {
|
||||
$error = $CONTACTS->get_error();
|
||||
// TODO: show dialog to complete record
|
||||
// if ($error['type'] == rcube_addressbook::ERROR_VALIDATE) { }
|
||||
|
||||
$OUTPUT->show_message($error['message'] ?: 'errorsavingcontact', 'error');
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
// check for existing contacts
|
||||
$existing = $CONTACTS->search('email', $contact['email'], 1, false);
|
||||
|
||||
if ($done = $existing->count) {
|
||||
$OUTPUT->show_message('contactexists', 'warning');
|
||||
}
|
||||
else {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('contact_create', array('record' => $contact, 'source' => null));
|
||||
$contact = $plugin['record'];
|
||||
|
||||
$done = !$plugin['abort'] ? $CONTACTS->insert($contact) : $plugin['result'];
|
||||
|
||||
if ($done) {
|
||||
$OUTPUT->show_message('addedsuccessfully', 'confirmation');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$done) {
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'errorsavingcontact', 'error');
|
||||
}
|
||||
|
||||
$OUTPUT->send();
|
291
data/web/rc/program/steps/mail/attachments.inc
Normal file
291
data/web/rc/program/steps/mail/attachments.inc
Normal file
@@ -0,0 +1,291 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/attachments.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Upload, remove, display attachments in compose form |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// Upload progress update
|
||||
if (!empty($_GET['_progress'])) {
|
||||
$RCMAIL->upload_progress();
|
||||
}
|
||||
|
||||
$COMPOSE_ID = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC);
|
||||
$COMPOSE = null;
|
||||
|
||||
if ($COMPOSE_ID && $_SESSION['compose_data_' . $COMPOSE_ID]) {
|
||||
$SESSION_KEY = 'compose_data_' . $COMPOSE_ID;
|
||||
$COMPOSE =& $_SESSION[$SESSION_KEY];
|
||||
}
|
||||
|
||||
if (!$COMPOSE) {
|
||||
die("Invalid session var!");
|
||||
}
|
||||
|
||||
$file_id = rcube_utils::get_input_value('_file', rcube_utils::INPUT_GPC);
|
||||
$file_id = preg_replace('/^rcmfile/', '', $file_id) ?: 'unknown';
|
||||
|
||||
// remove an attachment
|
||||
if ($RCMAIL->action == 'remove-attachment') {
|
||||
if ($attachment = $COMPOSE['attachments'][$file_id]) {
|
||||
$attachment = $RCMAIL->plugins->exec_hook('attachment_delete', $attachment);
|
||||
}
|
||||
|
||||
if ($attachment['status']) {
|
||||
if (is_array($COMPOSE['attachments'][$file_id])) {
|
||||
$RCMAIL->session->remove($SESSION_KEY . '.attachments.' . $file_id);
|
||||
$OUTPUT->command('remove_from_attachment_list', "rcmfile$file_id");
|
||||
}
|
||||
}
|
||||
|
||||
$OUTPUT->send();
|
||||
exit;
|
||||
}
|
||||
|
||||
// rename an attachment
|
||||
if ($RCMAIL->action == 'rename-attachment') {
|
||||
$filename = rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST);
|
||||
$filename = trim($filename);
|
||||
|
||||
if (strlen($filename)
|
||||
&& ($attachment = $COMPOSE['attachments'][$file_id])
|
||||
&& is_array($attachment)
|
||||
) {
|
||||
$attachment['name'] = $filename;
|
||||
$RCMAIL->session->remove($SESSION_KEY . '.attachments. ' . $file_id);
|
||||
$RCMAIL->session->append($SESSION_KEY . '.attachments', $attachment['id'], $attachment);
|
||||
$OUTPUT->command('rename_attachment_handler', "rcmfile$file_id", $filename);
|
||||
}
|
||||
|
||||
$OUTPUT->send();
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($RCMAIL->action == 'display-attachment') {
|
||||
$RCMAIL->display_uploaded_file($COMPOSE['attachments'][$file_id]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/***** attachment upload action *****/
|
||||
|
||||
// clear all stored output properties (like scripts and env vars)
|
||||
$OUTPUT->reset();
|
||||
|
||||
$uploadid = rcube_utils::get_input_value('_uploadid', rcube_utils::INPUT_GPC);
|
||||
$uri = rcube_utils::get_input_value('_uri', rcube_utils::INPUT_POST);
|
||||
|
||||
// handle dropping a reference to an attachment part of some message
|
||||
if ($uri) {
|
||||
$url = parse_url($uri);
|
||||
parse_str($url['query'], $params);
|
||||
|
||||
if (strlen($params['_mbox']) && $params['_uid'] && $params['_part']) {
|
||||
// @TODO: at some point we might support drag-n-drop between
|
||||
// two different accounts on the same server, for now make sure
|
||||
// this is the same server and the same user
|
||||
list($host, $port) = explode(':', $_SERVER['HTTP_HOST']);
|
||||
if ($host == $url['host'] && $port == $url['port']
|
||||
&& $RCMAIL->get_user_name() == rawurldecode($url['user'])
|
||||
) {
|
||||
$message = new rcube_message($params['_uid'], $params['_mbox']);
|
||||
|
||||
if ($message && !empty($message->headers)) {
|
||||
$attachment = rcmail_save_attachment($message, $params['_part'], $COMPOSE_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('attachment_from_uri', array(
|
||||
'attachment' => $attachment, 'uri' => $uri, 'compose_id' => $COMPOSE_ID));
|
||||
|
||||
if ($plugin['attachment']) {
|
||||
rcmail_attachment_success($plugin['attachment'], $uploadid);
|
||||
}
|
||||
else {
|
||||
$OUTPUT->command('display_message', $RCMAIL->gettext('filelinkerror'), 'error');
|
||||
$OUTPUT->command('remove_from_attachment_list', $uploadid);
|
||||
}
|
||||
|
||||
$OUTPUT->send();
|
||||
return;
|
||||
}
|
||||
|
||||
// handle file(s) upload
|
||||
if (is_array($_FILES['_attachments']['tmp_name'])) {
|
||||
$multiple = count($_FILES['_attachments']['tmp_name']) > 1;
|
||||
$errors = array();
|
||||
|
||||
foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) {
|
||||
// Process uploaded attachment if there is no error
|
||||
$err = $_FILES['_attachments']['error'][$i];
|
||||
|
||||
if (!$err) {
|
||||
$filename = $_FILES['_attachments']['name'][$i];
|
||||
$filesize = $_FILES['_attachments']['size'][$i];
|
||||
$filetype = rcube_mime::file_content_type($filepath, $filename, $_FILES['_attachments']['type'][$i]);
|
||||
|
||||
if ($err = rcmail_check_message_size($filesize, $filetype)) {
|
||||
if (!in_array($err, $errors)) {
|
||||
$OUTPUT->command('display_message', $err, 'error');
|
||||
$OUTPUT->command('remove_from_attachment_list', $uploadid);
|
||||
$errors[] = $err;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$attachment = $RCMAIL->plugins->exec_hook('attachment_upload', array(
|
||||
'path' => $filepath,
|
||||
'name' => $filename,
|
||||
'size' => $filesize,
|
||||
'mimetype' => $filetype,
|
||||
'group' => $COMPOSE_ID,
|
||||
));
|
||||
}
|
||||
|
||||
if (!$err && $attachment['status'] && !$attachment['abort']) {
|
||||
// store new attachment in session
|
||||
unset($attachment['status'], $attachment['abort']);
|
||||
$RCMAIL->session->append($SESSION_KEY . '.attachments', $attachment['id'], $attachment);
|
||||
|
||||
rcmail_attachment_success($attachment, $uploadid);
|
||||
}
|
||||
else { // upload failed
|
||||
if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
|
||||
$size = $RCMAIL->show_bytes(rcube_utils::max_upload_size());
|
||||
$msg = $RCMAIL->gettext(array('name' => 'filesizeerror', 'vars' => array('size' => $size)));
|
||||
}
|
||||
else if ($attachment['error']) {
|
||||
$msg = $attachment['error'];
|
||||
}
|
||||
else {
|
||||
$msg = $RCMAIL->gettext('fileuploaderror');
|
||||
}
|
||||
|
||||
if ($attachment['error'] || $err != UPLOAD_ERR_NO_FILE) {
|
||||
if (!in_array($msg, $errors)) {
|
||||
$OUTPUT->command('display_message', $msg, 'error');
|
||||
$OUTPUT->command('remove_from_attachment_list', $uploadid);
|
||||
$errors[] = $msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
// if filesize exceeds post_max_size then $_FILES array is empty,
|
||||
// show filesizeerror instead of fileuploaderror
|
||||
if ($maxsize = ini_get('post_max_size')) {
|
||||
$msg = $RCMAIL->gettext(array(
|
||||
'name' => 'filesizeerror',
|
||||
'vars' => array('size' => $RCMAIL->show_bytes(parse_bytes($maxsize)))
|
||||
));
|
||||
}
|
||||
else {
|
||||
$msg = $RCMAIL->gettext('fileuploaderror');
|
||||
}
|
||||
|
||||
$OUTPUT->command('display_message', $msg, 'error');
|
||||
$OUTPUT->command('remove_from_attachment_list', $uploadid);
|
||||
}
|
||||
|
||||
// send html page with JS calls as response
|
||||
$OUTPUT->command('auto_save_start', false);
|
||||
$OUTPUT->send('iframe');
|
||||
|
||||
|
||||
function rcmail_attachment_success($attachment, $uploadid)
|
||||
{
|
||||
global $RCMAIL, $COMPOSE;
|
||||
|
||||
$id = $attachment['id'];
|
||||
|
||||
if (($icon = $COMPOSE['deleteicon']) && is_file($icon)) {
|
||||
$button = html::img(array(
|
||||
'src' => $icon,
|
||||
'alt' => $RCMAIL->gettext('delete')
|
||||
));
|
||||
}
|
||||
else if ($COMPOSE['textbuttons']) {
|
||||
$button = rcube::Q($RCMAIL->gettext('delete'));
|
||||
}
|
||||
else {
|
||||
$button = '';
|
||||
}
|
||||
|
||||
$link_content = sprintf('%s <span class="attachment-size"> (%s)</span>',
|
||||
rcube::Q($attachment['name']), $RCMAIL->show_bytes($attachment['size']));
|
||||
|
||||
$content_link = html::a(array(
|
||||
'href' => "#load",
|
||||
'class' => 'filename',
|
||||
'onclick' => sprintf("return %s.command('load-attachment','rcmfile%s', this, event)", rcmail_output::JS_OBJECT_NAME, $id),
|
||||
), $link_content);
|
||||
|
||||
$delete_link = html::a(array(
|
||||
'href' => "#delete",
|
||||
'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this, event)", rcmail_output::JS_OBJECT_NAME, $id),
|
||||
'title' => $RCMAIL->gettext('delete'),
|
||||
'class' => 'delete',
|
||||
'aria-label' => $RCMAIL->gettext('delete') . ' ' . $attachment['name'],
|
||||
), $button);
|
||||
|
||||
$content = $COMPOSE['icon_pos'] == 'left' ? $delete_link.$content_link : $content_link.$delete_link;
|
||||
|
||||
$RCMAIL->output->command('add2attachment_list', "rcmfile$id", array(
|
||||
'html' => $content,
|
||||
'name' => $attachment['name'],
|
||||
'mimetype' => $attachment['mimetype'],
|
||||
'classname' => rcube_utils::file2class($attachment['mimetype'], $attachment['name']),
|
||||
'complete' => true), $uploadid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the attached file will fit in message size limit.
|
||||
* Calculates size of all attachments and compares with the limit.
|
||||
*
|
||||
* @param int $filesize File size
|
||||
* @param string $filetype File mimetype
|
||||
*
|
||||
* @return string Error message if the limit is exceeded
|
||||
*/
|
||||
function rcmail_check_message_size($filesize, $filetype)
|
||||
{
|
||||
global $RCMAIL, $COMPOSE;
|
||||
|
||||
$limit = parse_bytes($RCMAIL->config->get('max_message_size'));
|
||||
$size = 10 * 1024; // size of message body
|
||||
|
||||
if (!$limit) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add size of already attached files
|
||||
foreach ((array) $COMPOSE['attachments'] as $att) {
|
||||
// All attachments are base64-encoded except message/rfc822 (see sendmail.inc)
|
||||
$multip = $att['mimetype'] == 'message/rfc822' ? 1 : 1.33;
|
||||
$size += $att['size'] * $multip;
|
||||
}
|
||||
|
||||
// add size of the new attachment
|
||||
$multip = $filetype == 'message/rfc822' ? 1 : 1.33;
|
||||
$size += $filesize * $multip;
|
||||
|
||||
if ($size > $limit) {
|
||||
$limit = $RCMAIL->show_bytes($limit);
|
||||
return $RCMAIL->gettext(array('name' => 'msgsizeerror', 'vars' => array('size' => $limit)));
|
||||
}
|
||||
}
|
194
data/web/rc/program/steps/mail/autocomplete.inc
Normal file
194
data/web/rc/program/steps/mail/autocomplete.inc
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/autocomplete.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2008-2013, Roundcube Dev Team |
|
||||
| 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. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Perform a search on configured address books for the address |
|
||||
| autocompletion of the message compose screen |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
if ($RCMAIL->action == 'group-expand') {
|
||||
$abook = $RCMAIL->get_address_book(rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC));
|
||||
if ($gid = rcube_utils::get_input_value('_gid', rcube_utils::INPUT_GPC)) {
|
||||
$abook->set_group($gid);
|
||||
$abook->set_pagesize(1000); // TODO: limit number of group members by config
|
||||
|
||||
$separator = trim($RCMAIL->config->get('recipients_separator', ',')) . ' ';
|
||||
$result = $abook->list_records($RCMAIL->config->get('contactlist_fields'));
|
||||
$members = array();
|
||||
|
||||
while ($result && ($sql_arr = $result->iterate())) {
|
||||
$emails = (array) $abook->get_col_values('email', $sql_arr, true);
|
||||
if (!empty($emails) && ($email = array_shift($emails))) {
|
||||
$members[] = format_email_recipient($email, rcube_addressbook::compose_list_name($sql_arr));
|
||||
}
|
||||
}
|
||||
|
||||
$OUTPUT->command('replace_group_recipients', $gid, join($separator, array_unique($members)));
|
||||
}
|
||||
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
|
||||
$MAXNUM = (int) $RCMAIL->config->get('autocomplete_max', 15);
|
||||
$mode = (int) $RCMAIL->config->get('addressbook_search_mode');
|
||||
$single = (bool) $RCMAIL->config->get('autocomplete_single');
|
||||
$search = rcube_utils::get_input_value('_search', rcube_utils::INPUT_GPC, true);
|
||||
$source = rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC);
|
||||
$reqid = rcube_utils::get_input_value('_reqid', rcube_utils::INPUT_GPC);
|
||||
|
||||
if (strlen($source)) {
|
||||
$book_types = array($source);
|
||||
}
|
||||
else {
|
||||
$book_types = (array) $RCMAIL->config->get('autocomplete_addressbooks', 'sql');
|
||||
}
|
||||
|
||||
$contacts = array();
|
||||
if (!empty($book_types) && strlen($search)) {
|
||||
$sort_keys = array();
|
||||
$books_num = count($book_types);
|
||||
$search_lc = mb_strtolower($search);
|
||||
$mode |= rcube_addressbook::SEARCH_GROUPS;
|
||||
|
||||
foreach ($book_types as $abook_id) {
|
||||
$abook = $RCMAIL->get_address_book($abook_id);
|
||||
$abook->set_pagesize($MAXNUM);
|
||||
|
||||
if ($result = $abook->search($RCMAIL->config->get('contactlist_fields'), $search, $mode, true, true, 'email')) {
|
||||
while ($sql_arr = $result->iterate()) {
|
||||
// Contact can have more than one e-mail address
|
||||
$email_arr = (array)$abook->get_col_values('email', $sql_arr, true);
|
||||
$email_cnt = count($email_arr);
|
||||
$idx = 0;
|
||||
|
||||
foreach ($email_arr as $email) {
|
||||
if (empty($email)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = rcube_addressbook::compose_list_name($sql_arr);
|
||||
$contact = format_email_recipient($email, $name);
|
||||
|
||||
// skip entries that don't match
|
||||
if ($email_cnt > 1 && strpos(mb_strtolower($contact), $search_lc) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$index = $contact;
|
||||
|
||||
// skip duplicates
|
||||
if (empty($contacts[$index])) {
|
||||
$contact = array(
|
||||
'name' => $contact,
|
||||
'type' => $sql_arr['_type'],
|
||||
'id' => $sql_arr['ID'],
|
||||
'source' => $abook_id,
|
||||
);
|
||||
|
||||
if (($display = rcube_addressbook::compose_search_name($sql_arr, $email, $name)) && $display != $contact['name']) {
|
||||
$contact['display'] = $display;
|
||||
}
|
||||
|
||||
$contacts[$index] = $contact;
|
||||
$sort_keys[$index] = sprintf('%s %03d', $contact['display'] ?: $name, $idx++);
|
||||
|
||||
if (count($contacts) >= $MAXNUM) {
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
|
||||
// skip redundant entries (show only first email address)
|
||||
if ($single) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// also list matching contact groups
|
||||
if ($abook->groups && count($contacts) < $MAXNUM) {
|
||||
foreach ($abook->list_groups($search, $mode) as $group) {
|
||||
$abook->reset();
|
||||
$abook->set_group($group['ID']);
|
||||
|
||||
$group_prop = $abook->get_group($group['ID']);
|
||||
|
||||
// group (distribution list) with email address(es)
|
||||
if ($group_prop['email']) {
|
||||
$idx = 0;
|
||||
foreach ((array)$group_prop['email'] as $email) {
|
||||
$index = format_email_recipient($email, $group['name']);
|
||||
|
||||
if (empty($contacts[$index])) {
|
||||
$sort_keys[$index] = sprintf('%s %03d', $group['name'] , $idx++);
|
||||
$contacts[$index] = array(
|
||||
'name' => $index,
|
||||
'email' => $email,
|
||||
'type' => 'group',
|
||||
'id' => $group['ID'],
|
||||
'source' => $abook_id,
|
||||
);
|
||||
|
||||
if (count($contacts) >= $MAXNUM) {
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// show group with count
|
||||
else if (($result = $abook->count()) && $result->count) {
|
||||
if (empty($contacts[$group['name']])) {
|
||||
$sort_keys[$group['name']] = $group['name'];
|
||||
$contacts[$group['name']] = array(
|
||||
'name' => $group['name'] . ' (' . intval($result->count) . ')',
|
||||
'type' => 'group',
|
||||
'id' => $group['ID'],
|
||||
'source' => $abook_id,
|
||||
);
|
||||
|
||||
if (count($contacts) >= $MAXNUM) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($contacts)) {
|
||||
// sort contacts index
|
||||
asort($sort_keys, SORT_LOCALE_STRING);
|
||||
// re-sort contacts according to index
|
||||
foreach ($sort_keys as $idx => $val) {
|
||||
$sort_keys[$idx] = $contacts[$idx];
|
||||
}
|
||||
$contacts = array_values($sort_keys);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Allow autocomplete result optimization via plugin
|
||||
$pluginResult = $RCMAIL->plugins->exec_hook('contacts_autocomplete_after', array(
|
||||
'search' => $search,
|
||||
'contacts' => $contacts, // Provide already-found contacts to plugin if they are required
|
||||
));
|
||||
$contacts = $pluginResult['contacts'];
|
||||
|
||||
|
||||
$OUTPUT->command('ksearch_query_results', $contacts, $search, $reqid);
|
||||
$OUTPUT->send();
|
157
data/web/rc/program/steps/mail/check_recent.inc
Normal file
157
data/web/rc/program/steps/mail/check_recent.inc
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/check_recent.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2014, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Check for recent messages, in all mailboxes |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// If there's no folder or messages list, there's nothing to update
|
||||
// This can happen on 'refresh' request
|
||||
if (empty($_POST['_folderlist']) && empty($_POST['_list'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$trash = $RCMAIL->config->get('trash_mbox');
|
||||
$current = $RCMAIL->storage->get_folder();
|
||||
$check_all = $RCMAIL->action != 'refresh' || (bool)$RCMAIL->config->get('check_all_folders');
|
||||
$page = $RCMAIL->storage->get_page();
|
||||
$page_size = $RCMAIL->storage->get_pagesize();
|
||||
|
||||
$search_request = rcube_utils::get_input_value('_search', rcube_utils::INPUT_GPC);
|
||||
if ($search_request && $_SESSION['search_request'] != $search_request) {
|
||||
$search_request = null;
|
||||
}
|
||||
|
||||
// list of folders to check
|
||||
if ($check_all) {
|
||||
$a_mailboxes = $RCMAIL->storage->list_folders_subscribed('', '*', 'mail');
|
||||
}
|
||||
else if ($search_request && is_object($_SESSION['search'][1])) {
|
||||
$a_mailboxes = (array) $_SESSION['search'][1]->get_parameters('MAILBOX');
|
||||
}
|
||||
else {
|
||||
$a_mailboxes = (array) $current;
|
||||
if ($current != 'INBOX') {
|
||||
$a_mailboxes[] = 'INBOX';
|
||||
}
|
||||
}
|
||||
|
||||
// Control folders list from a plugin
|
||||
$plugin = $RCMAIL->plugins->exec_hook('check_recent', array('folders' => $a_mailboxes, 'all' => $check_all));
|
||||
$a_mailboxes = $plugin['folders'];
|
||||
|
||||
// check recent/unseen counts
|
||||
foreach ($a_mailboxes as $mbox_name) {
|
||||
$is_current = $mbox_name == $current || ($search_request && is_object($_SESSION['search'][1]) && in_array($mbox_name, (array)$_SESSION['search'][1]->get_parameters('MAILBOX')));
|
||||
if ($is_current) {
|
||||
// Synchronize mailbox cache, handle flag changes
|
||||
$RCMAIL->storage->folder_sync($mbox_name);
|
||||
}
|
||||
|
||||
// Get mailbox status
|
||||
$status = $RCMAIL->storage->folder_status($mbox_name, $diff);
|
||||
|
||||
if ($status & 1) {
|
||||
// trigger plugin hook
|
||||
$RCMAIL->plugins->exec_hook('new_messages',
|
||||
array('mailbox' => $mbox_name, 'is_current' => $is_current, 'diff' => $diff));
|
||||
}
|
||||
|
||||
rcmail_send_unread_count($mbox_name, true, null,
|
||||
(!$is_current && ($status & 1)) ? 'recent' : '');
|
||||
|
||||
if ($status && $is_current) {
|
||||
// refresh saved search set
|
||||
if ($search_request && isset($_SESSION['search'])) {
|
||||
unset($search_request); // only do this once
|
||||
$_SESSION['search'] = $RCMAIL->storage->refresh_search();
|
||||
if ($_SESSION['search'][1]->multi) {
|
||||
$mbox_name = '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($_POST['_quota'])) {
|
||||
$OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $mbox_name));
|
||||
}
|
||||
|
||||
$OUTPUT->set_env('exists', $RCMAIL->storage->count($mbox_name, 'EXISTS', true));
|
||||
|
||||
// "No-list" mode, don't get messages
|
||||
if (empty($_POST['_list'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// get overall message count; allow caching because rcube_storage::folder_status()
|
||||
// did a refresh but only in list mode
|
||||
$list_mode = $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL';
|
||||
$all_count = $RCMAIL->storage->count($mbox_name, $list_mode, $list_mode == 'THREADS', false);
|
||||
|
||||
// check current page if we're not on the first page
|
||||
if ($all_count && $page > 1) {
|
||||
$remaining = $all_count - $page_size * ($page - 1);
|
||||
if ($remaining <= 0) {
|
||||
$page -= 1;
|
||||
$RCMAIL->storage->set_page($page);
|
||||
$_SESSION['page'] = $page;
|
||||
}
|
||||
}
|
||||
|
||||
$OUTPUT->set_env('messagecount', $all_count);
|
||||
$OUTPUT->set_env('pagecount', ceil($all_count/$page_size));
|
||||
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($all_count), $mbox_name);
|
||||
$OUTPUT->set_env('current_page', $all_count ? $page : 1);
|
||||
|
||||
// remove old rows (and clear selection if new list is empty)
|
||||
$OUTPUT->command('message_list.clear', $all_count ? false : true);
|
||||
|
||||
if ($all_count) {
|
||||
$a_headers = $RCMAIL->storage->list_messages($mbox_name, null, rcmail_sort_column(), rcmail_sort_order());
|
||||
// add message rows
|
||||
rcmail_js_message_list($a_headers, false);
|
||||
// remove messages that don't exists from list selection array
|
||||
$OUTPUT->command('update_selection');
|
||||
}
|
||||
}
|
||||
// handle flag updates
|
||||
else if ($is_current && ($uids = rcube_utils::get_input_value('_uids', rcube_utils::INPUT_GPC)) && empty($search_request)) {
|
||||
$data = $RCMAIL->storage->folder_data($mbox_name);
|
||||
|
||||
if (empty($_SESSION['list_mod_seq']) || $_SESSION['list_mod_seq'] != $data['HIGHESTMODSEQ']) {
|
||||
$flags = $RCMAIL->storage->list_flags($mbox_name, explode(',', $uids), $_SESSION['list_mod_seq']);
|
||||
foreach ($flags as $idx => $row) {
|
||||
$flags[$idx] = array_change_key_case(array_map('intval', $row));
|
||||
}
|
||||
|
||||
// remember last HIGHESTMODSEQ value (if supported)
|
||||
if (!empty($data['HIGHESTMODSEQ'])) {
|
||||
$_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ'];
|
||||
}
|
||||
|
||||
$RCMAIL->output->set_env('recent_flags', $flags);
|
||||
}
|
||||
}
|
||||
|
||||
// set trash folder state
|
||||
if ($mbox_name === $trash) {
|
||||
$OUTPUT->command('set_trash_count', $RCMAIL->storage->count($mbox_name, 'EXISTS', true));
|
||||
}
|
||||
}
|
||||
|
||||
// trigger refresh hook
|
||||
$RCMAIL->plugins->exec_hook('refresh', array());
|
||||
|
||||
$OUTPUT->send();
|
1896
data/web/rc/program/steps/mail/compose.inc
Normal file
1896
data/web/rc/program/steps/mail/compose.inc
Normal file
File diff suppressed because it is too large
Load Diff
62
data/web/rc/program/steps/mail/copy.inc
Normal file
62
data/web/rc/program/steps/mail/copy.inc
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/copy.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2014, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Copy the submitted messages to a specific mailbox |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// only process ajax requests
|
||||
if (!$OUTPUT->ajax_call) {
|
||||
return;
|
||||
}
|
||||
|
||||
// copy messages
|
||||
if (!empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) {
|
||||
$target = rcube_utils::get_input_value('_target_mbox', rcube_utils::INPUT_POST, true);
|
||||
$sources = array();
|
||||
|
||||
foreach (rcmail::get_uids(null, null, $multifolder) as $mbox => $uids) {
|
||||
if ($mbox === $target) {
|
||||
$copied++;
|
||||
}
|
||||
else {
|
||||
$copied += (int)$RCMAIL->storage->copy_message($uids, $target, $mbox);
|
||||
$sources[] = $mbox;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$copied) {
|
||||
// send error message
|
||||
$RCMAIL->display_server_error('errorcopying');
|
||||
$OUTPUT->send();
|
||||
exit;
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message('messagecopied', 'confirmation');
|
||||
}
|
||||
|
||||
rcmail_send_unread_count($target, true);
|
||||
|
||||
$OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $multifolder ? $sources[0] : 'INBOX'));
|
||||
}
|
||||
// unknown action or missing query param
|
||||
else {
|
||||
$OUTPUT->show_message('internalerror', 'error');
|
||||
}
|
||||
|
||||
// send response
|
||||
$OUTPUT->send();
|
87
data/web/rc/program/steps/mail/folders.inc
Normal file
87
data/web/rc/program/steps/mail/folders.inc
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/folders.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Implement folder operations line EXPUNGE and Clear |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// only process ajax requests
|
||||
if (!$OUTPUT->ajax_call) {
|
||||
return;
|
||||
}
|
||||
|
||||
$mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
|
||||
|
||||
// send EXPUNGE command
|
||||
if ($RCMAIL->action == 'expunge') {
|
||||
$success = $RCMAIL->storage->expunge_folder($mbox);
|
||||
|
||||
// reload message list if current mailbox
|
||||
if ($success) {
|
||||
$OUTPUT->show_message('folderexpunged', 'confirmation');
|
||||
|
||||
if (!empty($_REQUEST['_reload'])) {
|
||||
$OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $mbox));
|
||||
$OUTPUT->command('message_list.clear');
|
||||
$RCMAIL->action = 'list';
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$RCMAIL->display_server_error();
|
||||
}
|
||||
}
|
||||
// clear mailbox
|
||||
else if ($RCMAIL->action == 'purge') {
|
||||
$delimiter = $RCMAIL->storage->get_hierarchy_delimiter();
|
||||
$trash_mbox = $RCMAIL->config->get('trash_mbox');
|
||||
$junk_mbox = $RCMAIL->config->get('junk_mbox');
|
||||
$trash_regexp = '/^' . preg_quote($trash_mbox . $delimiter, '/') . '/';
|
||||
$junk_regexp = '/^' . preg_quote($junk_mbox . $delimiter, '/') . '/';
|
||||
|
||||
// we should only be purging trash and junk (or their subfolders)
|
||||
if ($mbox == $trash_mbox || $mbox == $junk_mbox
|
||||
|| preg_match($trash_regexp, $mbox) || preg_match($junk_regexp, $mbox)
|
||||
) {
|
||||
$success = $RCMAIL->storage->clear_folder($mbox);
|
||||
|
||||
if ($success) {
|
||||
$OUTPUT->show_message('folderpurged', 'confirmation');
|
||||
|
||||
if (!empty($_REQUEST['_reload'])) {
|
||||
$OUTPUT->set_env('messagecount', 0);
|
||||
$OUTPUT->set_env('pagecount', 0);
|
||||
$OUTPUT->set_env('exists', 0);
|
||||
$OUTPUT->command('message_list.clear');
|
||||
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text(), $mbox);
|
||||
$OUTPUT->command('set_unread_count', $mbox, 0);
|
||||
$OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $mbox));
|
||||
rcmail_set_unseen_count($mbox, 0);
|
||||
|
||||
// set trash folder state
|
||||
if ($mbox === $trash_mbox) {
|
||||
$OUTPUT->command('set_trash_count', 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$RCMAIL->display_server_error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$OUTPUT->send();
|
2369
data/web/rc/program/steps/mail/func.inc
Normal file
2369
data/web/rc/program/steps/mail/func.inc
Normal file
File diff suppressed because it is too large
Load Diff
730
data/web/rc/program/steps/mail/get.inc
Normal file
730
data/web/rc/program/steps/mail/get.inc
Normal file
@@ -0,0 +1,730 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/get.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2016, 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: |
|
||||
| Delivering a specific uploaded file or mail message attachment |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
|
||||
// show loading page
|
||||
if (!empty($_GET['_preload'])) {
|
||||
unset($_GET['_preload']);
|
||||
unset($_GET['_safe']);
|
||||
|
||||
$url = $RCMAIL->url($_GET + array('_mimewarning' => 1, '_embed' => 1));
|
||||
$message = $RCMAIL->gettext('loadingdata');
|
||||
|
||||
header('Content-Type: text/html; charset=' . RCUBE_CHARSET);
|
||||
print "<html>\n<head>\n"
|
||||
. '<meta http-equiv="refresh" content="0; url='.rcube::Q($url).'">' . "\n"
|
||||
. '<meta http-equiv="content-type" content="text/html; charset='.RCUBE_CHARSET.'">' . "\n"
|
||||
. "</head>\n<body>\n$message\n</body>\n</html>";
|
||||
exit;
|
||||
}
|
||||
|
||||
$attachment = new rcmail_attachment_handler;
|
||||
$mimetype = $attachment->mimetype;
|
||||
$filename = $attachment->filename;
|
||||
|
||||
// show part page
|
||||
if (!empty($_GET['_frame'])) {
|
||||
$OUTPUT->set_pagetitle($filename);
|
||||
|
||||
// register UI objects
|
||||
$OUTPUT->add_handlers(array(
|
||||
'messagepartframe' => 'rcmail_message_part_frame',
|
||||
'messagepartcontrols' => 'rcmail_message_part_controls',
|
||||
));
|
||||
|
||||
$part_id = rcube_utils::get_input_value('_part', rcube_utils::INPUT_GET);
|
||||
$uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_GET);
|
||||
|
||||
// message/rfc822 preview (Note: handle also multipart/ parts, they can
|
||||
// come from Enigma, which replaces message/rfc822 with real mimetype)
|
||||
if ($part_id && ($mimetype == 'message/rfc822' || strpos($mimetype, 'multipart/') === 0)) {
|
||||
$uid = preg_replace('/\.[0-9.]+/', '', $uid);
|
||||
$uid .= '.' . $part_id;
|
||||
|
||||
$OUTPUT->set_env('is_message', true);
|
||||
}
|
||||
|
||||
$OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder());
|
||||
$OUTPUT->set_env('uid', $uid);
|
||||
$OUTPUT->set_env('part', $part_id);
|
||||
$OUTPUT->set_env('filename', $filename);
|
||||
$OUTPUT->set_env('mimetype', $mimetype);
|
||||
|
||||
$OUTPUT->send('messagepart');
|
||||
exit;
|
||||
}
|
||||
|
||||
// render thumbnail of an image attachment
|
||||
if (!empty($_GET['_thumb']) && $attachment->is_valid()) {
|
||||
$thumbnail_size = $RCMAIL->config->get('image_thumbnail_size', 240);
|
||||
$temp_dir = $RCMAIL->config->get('temp_dir');
|
||||
$file_ident = $attachment->ident;
|
||||
$cache_basename = $temp_dir . '/' . md5($file_ident . ':' . $RCMAIL->user->ID . ':' . $thumbnail_size);
|
||||
$cache_file = $cache_basename . '.thumb';
|
||||
|
||||
// render thumbnail image if not done yet
|
||||
if (!is_file($cache_file) && $attachment->body_to_file($orig_name = $cache_basename . '.tmp')) {
|
||||
$image = new rcube_image($orig_name);
|
||||
|
||||
if ($imgtype = $image->resize($thumbnail_size, $cache_file, true)) {
|
||||
$mimetype = 'image/' . $imgtype;
|
||||
unlink($orig_name);
|
||||
}
|
||||
else {
|
||||
// Resize failed, we need to check the file mimetype
|
||||
// So, we do not exit here, but goto generic file body handler below
|
||||
$_GET['_thumb'] = 0;
|
||||
$_REQUEST['_embed'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($_GET['_thumb'])) {
|
||||
if (is_file($cache_file)) {
|
||||
$RCMAIL->output->future_expire_header(3600);
|
||||
header('Content-Type: ' . $mimetype);
|
||||
header('Content-Length: ' . filesize($cache_file));
|
||||
readfile($cache_file);
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle attachment body (display or download)
|
||||
if (empty($_GET['_thumb']) && $attachment->is_valid()) {
|
||||
// require CSRF protected url for downloads
|
||||
if (!empty($_GET['_download'])) {
|
||||
$RCMAIL->request_security_check(rcube_utils::INPUT_GET);
|
||||
}
|
||||
|
||||
$extensions = rcube_mime::get_mime_extensions($mimetype);
|
||||
|
||||
// compare file mimetype with the stated content-type headers and file extension to avoid malicious operations
|
||||
if (!empty($_REQUEST['_embed']) && empty($_REQUEST['_nocheck'])) {
|
||||
$file_extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
||||
|
||||
// 1. compare filename suffix with expected suffix derived from mimetype
|
||||
$valid = $file_extension && in_array($file_extension, (array)$extensions) || empty($extensions) || !empty($_REQUEST['_mimeclass']);
|
||||
|
||||
// 2. detect the real mimetype of the attachment part and compare it with the stated mimetype and filename extension
|
||||
if ($valid || !$file_extension || $mimetype == 'application/octet-stream' || stripos($mimetype, 'text/') === 0) {
|
||||
$tmp_body = $attachment->body(2048);
|
||||
|
||||
// detect message part mimetype
|
||||
$real_mimetype = rcube_mime::file_content_type($tmp_body, $filename, $mimetype, true, true);
|
||||
list($real_ctype_primary, $real_ctype_secondary) = explode('/', $real_mimetype);
|
||||
|
||||
// accept text/plain with any extension
|
||||
if ($real_mimetype == 'text/plain' && $real_mimetype == $mimetype) {
|
||||
$valid_extension = true;
|
||||
}
|
||||
// ignore differences in text/* mimetypes. Filetype detection isn't very reliable here
|
||||
else if ($real_ctype_primary == 'text' && strpos($mimetype, $real_ctype_primary) === 0) {
|
||||
$real_mimetype = $mimetype;
|
||||
$valid_extension = true;
|
||||
}
|
||||
// ignore filename extension if mimeclass matches (#1489029)
|
||||
else if (!empty($_REQUEST['_mimeclass']) && $real_ctype_primary == $_REQUEST['_mimeclass']) {
|
||||
$valid_extension = true;
|
||||
}
|
||||
else {
|
||||
// get valid file extensions
|
||||
$extensions = rcube_mime::get_mime_extensions($real_mimetype);
|
||||
$valid_extension = !$file_extension || empty($extensions) || in_array($file_extension, (array)$extensions);
|
||||
}
|
||||
|
||||
// fix mimetype for images wrongly declared as octet-stream
|
||||
if ($mimetype == 'application/octet-stream' && strpos($real_mimetype, 'image/') === 0 && $valid_extension) {
|
||||
$mimetype = $real_mimetype;
|
||||
}
|
||||
// fix mimetype for images with wrong mimetype
|
||||
else if (strpos($real_mimetype, 'image/') === 0 && strpos($mimetype, 'image/') === 0) {
|
||||
$mimetype = $real_mimetype;
|
||||
}
|
||||
|
||||
// "fix" real mimetype the same way the original is before comparison
|
||||
$real_mimetype = rcmail_fix_mimetype($real_mimetype);
|
||||
|
||||
$valid = $real_mimetype == $mimetype && $valid_extension;
|
||||
}
|
||||
else {
|
||||
$real_mimetype = $mimetype;
|
||||
}
|
||||
|
||||
// show warning if validity checks failed
|
||||
if (!$valid) {
|
||||
// send blocked.gif for expected images
|
||||
if (empty($_REQUEST['_mimewarning']) && strpos($mimetype, 'image/') === 0) {
|
||||
// Do not cache. Failure might be the result of a misconfiguration, thus real content should be returned once fixed.
|
||||
$content = $RCMAIL->get_resource_content('blocked.gif');
|
||||
$OUTPUT->nocacheing_headers();
|
||||
header("Content-Type: image/gif");
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
header("Content-Length: " . strlen($content));
|
||||
echo $content;
|
||||
}
|
||||
else { // html warning with a button to load the file anyway
|
||||
$OUTPUT = new rcmail_html_page();
|
||||
$OUTPUT->write(html::tag('html', null, html::tag('body', 'embed',
|
||||
html::div(array('class' => 'rcmail-inline-message rcmail-inline-warning'),
|
||||
$RCMAIL->gettext(array(
|
||||
'name' => 'attachmentvalidationerror',
|
||||
'vars' => array(
|
||||
'expected' => $mimetype . ($file_extension ? " (.$file_extension)" : ''),
|
||||
'detected' => $real_mimetype . ($extensions[0] ? " (.$extensions[0])" : ''),
|
||||
)
|
||||
))
|
||||
. html::p(array('class' => 'rcmail-inline-buttons'),
|
||||
html::tag('button', array(
|
||||
'onclick' => "location.href='" . $RCMAIL->url(array_merge($_GET, array('_nocheck' => 1))) . "'"
|
||||
),
|
||||
$RCMAIL->gettext('showanyway'))
|
||||
)
|
||||
))));
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// TIFF/WEBP to JPEG conversion, if needed
|
||||
foreach (array('tiff', 'webp') as $type) {
|
||||
$img_support = !empty($_SESSION['browser_caps']) && !empty($_SESSION['browser_caps'][$type]);
|
||||
if (!empty($_REQUEST['_embed']) && !$img_support
|
||||
&& $attachment->image_type() == 'image/' . $type
|
||||
&& rcube_image::is_convertable('image/' . $type)
|
||||
) {
|
||||
$convert2jpeg = true;
|
||||
$mimetype = 'image/jpeg';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$browser = $RCMAIL->output->browser;
|
||||
list($ctype_primary, $ctype_secondary) = explode('/', $mimetype);
|
||||
|
||||
if (!empty($_GET['_download']) && $ctype_primary == 'text') {
|
||||
header("Content-Type: text/$ctype_secondary; charset=" . $attachment->charset);
|
||||
}
|
||||
else {
|
||||
header("Content-Type: $mimetype");
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
}
|
||||
|
||||
// deliver part content
|
||||
if ($mimetype == 'text/html' && empty($_GET['_download'])) {
|
||||
// Check if we have enough memory to handle the message in it
|
||||
// #1487424: we need up to 10x more memory than the body
|
||||
if (!rcube_utils::mem_check($attachment->size * 10)) {
|
||||
$out = '<html><body>'
|
||||
. $RCMAIL->gettext('messagetoobig'). ' '
|
||||
. html::a($RCMAIL->url(array_merge($_GET, array('download' => 1))), $RCMAIL->gettext('download'))
|
||||
. '</body></html>';
|
||||
}
|
||||
else {
|
||||
// render HTML body
|
||||
$out = $attachment->html();
|
||||
|
||||
// insert remote objects warning into HTML body
|
||||
if ($REMOTE_OBJECTS) {
|
||||
$body_start = 0;
|
||||
if ($body_pos = strpos($out, '<body')) {
|
||||
$body_start = strpos($out, '>', $body_pos) + 1;
|
||||
}
|
||||
|
||||
$out = substr($out, 0, $body_start)
|
||||
. html::div(array('class' => 'rcmail-inline-message rcmail-inline-warning'),
|
||||
rcube::Q($RCMAIL->gettext('blockedimages')) . ' ' .
|
||||
html::tag('button',
|
||||
array('onclick' => "location.href='" . $RCMAIL->url(array_merge($_GET, array('_safe' => 1))) . "'"),
|
||||
rcube::Q($RCMAIL->gettext('showimages')))
|
||||
)
|
||||
. substr($out, $body_start);
|
||||
}
|
||||
}
|
||||
|
||||
$OUTPUT = new rcmail_html_page();
|
||||
$OUTPUT->write($out);
|
||||
exit;
|
||||
}
|
||||
|
||||
// don't kill the connection if download takes some more time
|
||||
@set_time_limit(3600);
|
||||
|
||||
$filename = $browser->ie ? rawurlencode($filename) : addcslashes($filename, '"');
|
||||
$disposition = !empty($_GET['_download']) ? 'attachment' : 'inline';
|
||||
|
||||
// add filename extension if missing
|
||||
if (!pathinfo($filename, PATHINFO_EXTENSION) && ($extensions = rcube_mime::get_mime_extensions($mimetype))) {
|
||||
$filename .= '.' . $extensions[0];
|
||||
}
|
||||
|
||||
header("Content-Disposition: $disposition; filename=\"$filename\"");
|
||||
|
||||
// handle tiff to jpeg conversion
|
||||
if (!empty($convert2jpeg)) {
|
||||
$temp_dir = unslashify($RCMAIL->config->get('temp_dir'));
|
||||
$file_path = tempnam($temp_dir, 'rcmAttmnt');
|
||||
|
||||
// convert image to jpeg and send it to the browser
|
||||
if ($attachment->body_to_file($file_path)) {
|
||||
$image = new rcube_image($file_path);
|
||||
if ($image->convert(rcube_image::TYPE_JPG, $file_path)) {
|
||||
header("Content-Length: " . filesize($file_path));
|
||||
readfile($file_path);
|
||||
}
|
||||
unlink($file_path);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$attachment->output($mimetype);
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
// if we arrive here, the requested part was not found
|
||||
header('HTTP/1.1 404 Not Found');
|
||||
exit;
|
||||
|
||||
|
||||
/**
|
||||
* Attachment properties table
|
||||
*/
|
||||
function rcmail_message_part_controls($attrib)
|
||||
{
|
||||
global $attachment, $RCMAIL;
|
||||
|
||||
if (!$attachment->is_valid()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$table = new html_table(array('cols' => 2));
|
||||
|
||||
$table->add('title', rcube::Q($RCMAIL->gettext('namex')).':');
|
||||
$table->add('header', rcube::Q($attachment->filename));
|
||||
|
||||
$table->add('title', rcube::Q($RCMAIL->gettext('type')).':');
|
||||
$table->add('header', rcube::Q($attachment->mimetype));
|
||||
|
||||
$table->add('title', rcube::Q($RCMAIL->gettext('size')).':');
|
||||
$table->add('header', rcube::Q($attachment->size()));
|
||||
|
||||
return $table->show($attrib);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attachment preview frame
|
||||
*/
|
||||
function rcmail_message_part_frame($attrib)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
if ($RCMAIL->output->get_env('is_message')) {
|
||||
$attrib['src'] = $RCMAIL->url(array(
|
||||
'task' => 'mail',
|
||||
'action' => 'preview',
|
||||
'uid' => $RCMAIL->output->get_env('uid'),
|
||||
'mbox' => $RCMAIL->output->get_env('mailbox'),
|
||||
'framed' => 1,
|
||||
));
|
||||
}
|
||||
else {
|
||||
$mimetype = $RCMAIL->output->get_env('mimetype');
|
||||
$frame_replace = strpos($mimetype, 'text/') === 0 ? '_embed=' : '_preload=';
|
||||
$attrib['src'] = './?' . str_replace('_frame=', $frame_replace, $_SERVER['QUERY_STRING']);
|
||||
}
|
||||
|
||||
$RCMAIL->output->add_gui_object('messagepartframe', $attrib['id']);
|
||||
|
||||
return html::iframe($attrib);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper class with unified access to attachment properties and body
|
||||
*
|
||||
* Unified for message parts as well as uploaded attachments
|
||||
*/
|
||||
class rcmail_attachment_handler
|
||||
{
|
||||
public $filename;
|
||||
public $size;
|
||||
public $mimetype;
|
||||
public $ident;
|
||||
public $charset = RCUBE_CHARSET;
|
||||
|
||||
private $message;
|
||||
private $part;
|
||||
private $upload;
|
||||
private $body;
|
||||
private $body_file;
|
||||
private $download = false;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
* Reads request parameters and initializes attachment/part props.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
ob_end_clean();
|
||||
|
||||
$part_id = rcube_utils::get_input_value('_part', rcube_utils::INPUT_GET);
|
||||
$file_id = rcube_utils::get_input_value('_file', rcube_utils::INPUT_GET);
|
||||
$compose_id = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GET);
|
||||
$uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_GET);
|
||||
$rcube = rcube::get_instance();
|
||||
|
||||
$this->download = !empty($_GET['_download']);
|
||||
|
||||
// similar code as in program/steps/mail/show.inc
|
||||
if (!empty($uid)) {
|
||||
$rcube->config->set('prefer_html', true);
|
||||
$this->message = new rcube_message($uid, null, intval($_GET['_safe']));
|
||||
|
||||
if ($this->part = $this->message->mime_parts[$part_id]) {
|
||||
$this->filename = rcmail_attachment_name($this->part);
|
||||
$this->mimetype = $this->part->mimetype;
|
||||
$this->size = $this->part->size;
|
||||
$this->ident = $this->message->headers->messageID . ':' . $this->part->mime_id . ':' . $this->size . ':' . $this->mimetype;
|
||||
$this->charset = $this->part->charset ?: RCUBE_CHARSET;
|
||||
|
||||
if (empty($_GET['_frame'])) {
|
||||
// allow post-processing of the attachment body
|
||||
$plugin = $rcube->plugins->exec_hook('message_part_get', array(
|
||||
'uid' => $uid,
|
||||
'id' => $this->part->mime_id,
|
||||
'mimetype' => $this->mimetype,
|
||||
'part' => $this->part,
|
||||
'download' => $this->download,
|
||||
));
|
||||
|
||||
if ($plugin['abort']) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// overwrite modified vars from plugin
|
||||
$this->mimetype = $plugin['mimetype'];
|
||||
|
||||
if ($plugin['body']) {
|
||||
$this->body = $plugin['body'];
|
||||
$this->size = strlen($this->body);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($file_id && $compose_id) {
|
||||
$file_id = preg_replace('/^rcmfile/', '', $file_id);
|
||||
|
||||
if (($compose = $_SESSION['compose_data_' . $compose_id])
|
||||
&& ($this->upload = $compose['attachments'][$file_id])
|
||||
) {
|
||||
$this->filename = $this->upload['name'];
|
||||
$this->mimetype = $this->upload['mimetype'];
|
||||
$this->size = $this->upload['size'];
|
||||
$this->ident = sprintf('%s:%s%s', $compose_id, $file_id, $this->size);
|
||||
$this->charset = $this->upload['charset'] ?: RCUBE_CHARSET;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($this->part) && empty($this->upload)) {
|
||||
header('HTTP/1.1 404 Not Found');
|
||||
exit;
|
||||
}
|
||||
|
||||
// check connection status
|
||||
self::check_storage_status();
|
||||
|
||||
$this->mimetype = rcmail_fix_mimetype($this->mimetype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove temp files, etc.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->body_file) {
|
||||
@unlink($this->body_file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the object is a message part not uploaded file
|
||||
*
|
||||
* @return bool True if the object is a meesage part
|
||||
*/
|
||||
public function is_message_part()
|
||||
{
|
||||
return !empty($this->message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Object/request status
|
||||
*
|
||||
* @return bool Status
|
||||
*/
|
||||
public function is_valid()
|
||||
{
|
||||
return !empty($this->part) || !empty($this->upload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return attachment/part mimetype if this is an image
|
||||
* of supported type.
|
||||
*
|
||||
* @return string Image mimetype
|
||||
*/
|
||||
public function image_type()
|
||||
{
|
||||
$part = (object) array(
|
||||
'filename' => $this->filename,
|
||||
'mimetype' => $this->mimetype,
|
||||
);
|
||||
|
||||
return rcmail_part_image_type($part);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formatted attachment/part size (with units)
|
||||
*
|
||||
* @return string Attachment/part size (with units)
|
||||
*/
|
||||
public function size()
|
||||
{
|
||||
$part = $this->part ?: ((object) array('size' => $this->size, 'exact_size' => true));
|
||||
return rcube::get_instance()->message_part_size($part);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns, prints or saves the attachment/part body
|
||||
*/
|
||||
public function body($size = null, $fp = null)
|
||||
{
|
||||
// we may have the body in memory or file already
|
||||
if ($this->body !== null) {
|
||||
if ($fp == -1) {
|
||||
echo $size ? substr($this->body, 0, $size) : $this->body;
|
||||
}
|
||||
else if ($fp) {
|
||||
$result = fwrite($fp, $size ? substr($this->body, $size) : $this->body) !== false;
|
||||
}
|
||||
else {
|
||||
$result = $size ? substr($this->body, 0, $size) : $this->body;
|
||||
}
|
||||
}
|
||||
else if ($this->body_file) {
|
||||
if ($size) {
|
||||
$result = file_get_contents($this->body_file, false, null, 0, $size);
|
||||
}
|
||||
else {
|
||||
$result = file_get_contents($this->body_file);
|
||||
}
|
||||
|
||||
if ($fp == -1) {
|
||||
echo $result;
|
||||
}
|
||||
else if ($fp) {
|
||||
$result = fwrite($fp, $result) !== false;
|
||||
}
|
||||
}
|
||||
else if ($this->message) {
|
||||
$result = $this->message->get_part_body($this->part->mime_id, false, 0, $fp);
|
||||
|
||||
// check connection status
|
||||
if (!$fp && $this->size && empty($result)) {
|
||||
self::check_storage_status();
|
||||
}
|
||||
}
|
||||
else if ($this->upload) {
|
||||
// This hook retrieves the attachment contents from the file storage backend
|
||||
$attachment = rcube::get_instance()->plugins->exec_hook('attachment_get', $this->upload);
|
||||
|
||||
if ($fp && $fp != -1) {
|
||||
if ($attachment['data']) {
|
||||
$result = fwrite($fp, $size ? substr($attachment['data'], 0, $size) : $attachment['data']) !== false;
|
||||
}
|
||||
else if ($attachment['path']) {
|
||||
if ($fh = fopen($attachment['path'], 'rb')) {
|
||||
$result = stream_copy_to_stream($fh, $fp, $size ? $size : -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$data = $attachment['data'];
|
||||
if (!$data && $attachment['path']) {
|
||||
$data = file_get_contents($attachment['path']);
|
||||
}
|
||||
|
||||
if ($fp == -1) {
|
||||
echo $size ? substr($data, 0, $size) : $data;
|
||||
}
|
||||
else {
|
||||
$result = $size ? substr($data, 0, $size) : $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the body to a file
|
||||
*
|
||||
* @param string $filename File name with path
|
||||
*
|
||||
* @return bool True on success, False on failure
|
||||
*/
|
||||
public function body_to_file($filename)
|
||||
{
|
||||
if ($filename && $this->size && ($fp = fopen($filename, 'w'))) {
|
||||
$this->body(0, $fp);
|
||||
$this->body_file = $filename;
|
||||
fclose($fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output attachment body with content filtering
|
||||
*/
|
||||
public function output($mimetype)
|
||||
{
|
||||
if (!$this->size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$secure = stripos($mimetype, 'image/') === false || $this->download;
|
||||
|
||||
// Remove <script> in SVG images
|
||||
if (!$secure && stripos($mimetype, 'image/svg') === 0) {
|
||||
if (!$this->body) {
|
||||
$this->body = $this->body();
|
||||
if (empty($this->body)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
echo self::svg_filter($this->body);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->body !== null && !$this->download) {
|
||||
header("Content-Length: " . strlen($this->body));
|
||||
echo $this->body;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Don't be tempted to set Content-Length to $part->d_parameters['size'] (#1490482)
|
||||
// RFC2183 says "The size parameter indicates an approximate size"
|
||||
|
||||
return $this->body(0, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns formatted HTML if the attachment is HTML
|
||||
*/
|
||||
public function html()
|
||||
{
|
||||
list($type, $subtype) = explode($this->mimetype, '/');
|
||||
$part = (object) array(
|
||||
'charset' => $this->charset,
|
||||
'ctype_secondary' => $subtype,
|
||||
);
|
||||
|
||||
// get part body if not available
|
||||
// fix formatting and charset
|
||||
$body = rcube_message::format_part_body($this->body(), $part);
|
||||
|
||||
// show images?
|
||||
$is_safe = $this->is_safe();
|
||||
|
||||
return rcmail_wash_html($body, array('safe' => $is_safe, 'inline_html' => false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove <script> in SVG images
|
||||
*/
|
||||
public static function svg_filter($body)
|
||||
{
|
||||
// clean SVG with washtml
|
||||
$wash_opts = array(
|
||||
'show_washed' => false,
|
||||
'allow_remote' => false,
|
||||
'charset' => RCUBE_CHARSET,
|
||||
'html_elements' => array('title'),
|
||||
// 'blocked_src' => 'program/resources/blocked.gif',
|
||||
);
|
||||
|
||||
// initialize HTML washer
|
||||
$washer = new rcube_washtml($wash_opts);
|
||||
|
||||
// allow CSS styles, will be sanitized by rcmail_washtml_callback()
|
||||
$washer->add_callback('style', 'rcmail_washtml_callback');
|
||||
|
||||
return $washer->wash($body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles nicely storage connection errors
|
||||
*/
|
||||
public static function check_storage_status()
|
||||
{
|
||||
$error = rcmail::get_instance()->storage->get_error_code();
|
||||
|
||||
// Check if we have a connection error
|
||||
if ($error == rcube_imap_generic::ERROR_BAD) {
|
||||
ob_end_clean();
|
||||
|
||||
// Get action is often executed simultanously.
|
||||
// Some servers have MAXPERIP or other limits.
|
||||
// To workaround this we'll wait for some time
|
||||
// and try again (once).
|
||||
// Note: Random sleep interval is used to minimize concurency
|
||||
// in getting message parts
|
||||
|
||||
if (!isset($_GET['_redirected'])) {
|
||||
usleep(rand(10,30)*100000); // 1-3 sec.
|
||||
header('Location: ' . $_SERVER['REQUEST_URI'] . '&_redirected=1');
|
||||
}
|
||||
else {
|
||||
rcube::raise_error(array(
|
||||
'code' => 500, 'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => 'Unable to get/display message part. IMAP connection error'),
|
||||
true, true);
|
||||
}
|
||||
|
||||
// Don't kill session, just quit (#1486995)
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
public function is_safe()
|
||||
{
|
||||
if ($this->message) {
|
||||
return rcmail_check_safe($this->message);
|
||||
}
|
||||
|
||||
return !empty($_GET['_safe']);
|
||||
}
|
||||
}
|
56
data/web/rc/program/steps/mail/getunread.inc
Normal file
56
data/web/rc/program/steps/mail/getunread.inc
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/getunread.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Check all mailboxes for unread messages and update GUI |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$a_folders = $RCMAIL->storage->list_folders_subscribed('', '*', 'mail');
|
||||
|
||||
if (!empty($a_folders)) {
|
||||
$current = $RCMAIL->storage->get_folder();
|
||||
$inbox = ($current == 'INBOX');
|
||||
$trash = $RCMAIL->config->get('trash_mbox');
|
||||
$check_all = (bool)$RCMAIL->config->get('check_all_folders');
|
||||
|
||||
foreach ($a_folders as $mbox) {
|
||||
$unseen_old = rcmail_get_unseen_count($mbox);
|
||||
|
||||
if (!$check_all && $unseen_old !== null && $mbox != $current) {
|
||||
$unseen = $unseen_old;
|
||||
}
|
||||
else {
|
||||
$unseen = $RCMAIL->storage->count($mbox, 'UNSEEN', $unseen_old === null);
|
||||
}
|
||||
|
||||
// call it always for current folder, so it can update counter
|
||||
// after possible message status change when opening a message
|
||||
// not in preview frame
|
||||
if ($unseen || $unseen_old === null || $mbox == $current) {
|
||||
$OUTPUT->command('set_unread_count', $mbox, $unseen, $inbox && $mbox_row == 'INBOX');
|
||||
}
|
||||
|
||||
rcmail_set_unseen_count($mbox, $unseen);
|
||||
|
||||
// set trash folder state
|
||||
if ($mbox === $trash) {
|
||||
$OUTPUT->command('set_trash_count', $RCMAIL->storage->count($mbox, 'EXISTS'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$OUTPUT->send();
|
56
data/web/rc/program/steps/mail/headers.inc
Normal file
56
data/web/rc/program/steps/mail/headers.inc
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/headers.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2016, 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: |
|
||||
| Fetch message headers in raw format for display |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
if ($uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST)) {
|
||||
if ($pos = strpos($uid, '.')) {
|
||||
$message = new rcube_message($uid);
|
||||
$source = $message->get_part_body(substr($uid, $pos + 1));
|
||||
$source = substr($source, 0, strpos($source, "\r\n\r\n"));
|
||||
}
|
||||
else {
|
||||
$source = $RCMAIL->storage->get_raw_headers($uid);
|
||||
}
|
||||
|
||||
if ($source !== false) {
|
||||
$source = trim(rcube_charset::clean($source));
|
||||
$source = htmlspecialchars($source);
|
||||
$source = preg_replace(
|
||||
array(
|
||||
'/\n[\t\s]+/',
|
||||
'/^([a-z0-9_:-]+)/im',
|
||||
'/\r?\n/'
|
||||
),
|
||||
array(
|
||||
"\n ",
|
||||
'<font class="bold">\1</font>',
|
||||
'<br />'
|
||||
), $source);
|
||||
|
||||
$OUTPUT->command('set_headers', $source);
|
||||
}
|
||||
else {
|
||||
$RCMAIL->output->show_message('messageopenerror', 'error');
|
||||
}
|
||||
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
exit;
|
197
data/web/rc/program/steps/mail/import.inc
Normal file
197
data/web/rc/program/steps/mail/import.inc
Normal file
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/import.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2014, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Save the uploaded file(s) as messages to the current IMAP folder |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// clear all stored output properties (like scripts and env vars)
|
||||
$OUTPUT->reset();
|
||||
|
||||
if (is_array($_FILES['_file'])) {
|
||||
$imported = 0;
|
||||
$folder = $RCMAIL->storage->get_folder();
|
||||
|
||||
foreach ((array)$_FILES['_file']['tmp_name'] as $i => $filepath) {
|
||||
// Process uploaded file if there is no error
|
||||
$err = $_FILES['_file']['error'][$i];
|
||||
|
||||
if (!$err) {
|
||||
// check file content type first
|
||||
$ctype = rcube_mime::file_content_type($filepath, $_FILES['_file']['name'][$i], $_FILES['_file']['type'][$i]);
|
||||
list($mtype_primary, $mtype_secondary) = explode('/', $ctype);
|
||||
|
||||
if (in_array($ctype, array('application/zip', 'application/x-zip'))) {
|
||||
$filepath = rcmail_zip_extract($filepath);
|
||||
if (empty($filepath)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (!in_array($mtype_primary, array('text', 'message'))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ((array) $filepath as $file) {
|
||||
// read the first few lines to detect header-like structure
|
||||
$fp = fopen($file, 'r');
|
||||
do {
|
||||
$line = fgets($fp);
|
||||
}
|
||||
while ($line !== false && trim($line) == '');
|
||||
|
||||
if (!preg_match('/^From .+/', $line) && !preg_match('/^[a-z-_]+:\s+.+/i', $line)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$message = $lastline = '';
|
||||
fseek($fp, 0);
|
||||
|
||||
while (($line = fgets($fp)) !== false) {
|
||||
// importing mbox file, split by From - lines
|
||||
if ($lastline === '' && strncmp($line, 'From ', 5) === 0 && strlen($line) > 5) {
|
||||
if (!empty($message)) {
|
||||
$imported += (int) rcmail_save_message($folder, $message);
|
||||
}
|
||||
|
||||
$message = $line;
|
||||
$lastline = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
$message .= $line;
|
||||
$lastline = rtrim($line);
|
||||
}
|
||||
|
||||
if (!empty($message)) {
|
||||
$imported += (int) rcmail_save_message($folder, $message);
|
||||
}
|
||||
|
||||
// remove temp files extracted from zip
|
||||
if (is_array($filepath)) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
|
||||
$size = $RCMAIL->show_bytes(rcube_utils::max_upload_size());
|
||||
$msg = $RCMAIL->gettext(array('name' => 'filesizeerror', 'vars' => array('size' => $size)));
|
||||
|
||||
$OUTPUT->command('display_message', $msg, 'error');
|
||||
}
|
||||
else if ($err) {
|
||||
$OUTPUT->show_message('fileuploaderror', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
if ($imported) {
|
||||
$OUTPUT->show_message($RCMAIL->gettext(array('name' => 'importmessagesuccess', 'nr' => $imported, 'vars' => array('nr' => $imported))), 'confirmation');
|
||||
$OUTPUT->command('command', 'list');
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message('importmessageerror', 'error');
|
||||
}
|
||||
}
|
||||
else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
// if filesize exceeds post_max_size then $_FILES array is empty,
|
||||
// show filesizeerror instead of fileuploaderror
|
||||
if ($maxsize = ini_get('post_max_size'))
|
||||
$msg = $RCMAIL->gettext(array('name' => 'filesizeerror', 'vars' => array('size' => $RCMAIL->show_bytes(parse_bytes($maxsize)))));
|
||||
else
|
||||
$msg = $RCMAIL->gettext('fileuploaderror');
|
||||
|
||||
$OUTPUT->command('display_message', $msg, 'error');
|
||||
}
|
||||
|
||||
// send html page with JS calls as response
|
||||
$OUTPUT->send('iframe');
|
||||
|
||||
|
||||
function rcmail_zip_extract($path)
|
||||
{
|
||||
if (!class_exists('ZipArchive', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$rcmail = rcmail::get_instance();
|
||||
$temp_dir = $rcmail->config->get('temp_dir');
|
||||
$zip = new ZipArchive;
|
||||
$files = array();
|
||||
|
||||
if ($zip->open($path)) {
|
||||
for ($i = 0; $i < $zip->numFiles; $i++) {
|
||||
$entry = $zip->getNameIndex($i);
|
||||
$tmpfname = tempnam($temp_dir, 'zipimport');
|
||||
|
||||
if (copy("zip://$path#$entry", $tmpfname)) {
|
||||
$ctype = rcube_mime::file_content_type($tmpfname, $entry);
|
||||
list($mtype_primary, $mtype_secondary) = explode('/', $ctype);
|
||||
|
||||
if (in_array($mtype_primary, array('text', 'message'))) {
|
||||
$files[] = $tmpfname;
|
||||
}
|
||||
else {
|
||||
unlink($tmpfname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
function rcmail_save_message($folder, &$message)
|
||||
{
|
||||
if (strncmp($message, 'From ', 5) === 0) {
|
||||
// Extract the mbox from_line
|
||||
$pos = strpos($message, "\n");
|
||||
$from = substr($message, 0, $pos);
|
||||
$message = substr($message, $pos + 1);
|
||||
|
||||
// Read the received date, support only known date formats
|
||||
|
||||
// RFC4155: "Sat Jan 3 01:05:34 1996"
|
||||
$mboxdate_rx = '/^([a-z]{3} [a-z]{3} [0-9 ][0-9] [0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{4})/i';
|
||||
// Roundcube/Zipdownload: "12-Dec-2016 10:56:33 +0100"
|
||||
$imapdate_rx = '/^([0-9]{1,2}-[a-z]{3}-[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2} [0-9+-]{5})/i';
|
||||
|
||||
if (($pos = strpos($from, ' ', 6)) && ($dt_str = substr($from, $pos + 1))
|
||||
&& (preg_match($mboxdate_rx, $dt_str, $m) || preg_match($imapdate_rx, $dt_str, $m))
|
||||
) {
|
||||
try {
|
||||
$date = new DateTime($m[0], new DateTimeZone('UTC'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unquote ">From " lines in message body
|
||||
$message = preg_replace('/\n>([>]*)From /', "\n\\1From ", $message);
|
||||
$message = rtrim($message);
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
if ($rcmail->storage->save_message($folder, $message, '', false, array(), $date)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
rcube::raise_error("Failed to import message to $folder", true, false);
|
||||
return false;
|
||||
}
|
147
data/web/rc/program/steps/mail/list.inc
Normal file
147
data/web/rc/program/steps/mail/list.inc
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/list.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2014, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Send message list to client (as remote response) |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
if (!$OUTPUT->ajax_call) {
|
||||
return;
|
||||
}
|
||||
|
||||
$save_arr = array();
|
||||
$dont_override = (array) $RCMAIL->config->get('dont_override');
|
||||
|
||||
// is there a sort type for this request?
|
||||
if ($sort = rcube_utils::get_input_value('_sort', rcube_utils::INPUT_GET)) {
|
||||
// yes, so set the sort vars
|
||||
list($sort_col, $sort_order) = explode('_', $sort);
|
||||
|
||||
// set session vars for sort (so next page and task switch know how to sort)
|
||||
if (!in_array('message_sort_col', $dont_override)) {
|
||||
$_SESSION['sort_col'] = $save_arr['message_sort_col'] = $sort_col;
|
||||
}
|
||||
if (!in_array('message_sort_order', $dont_override)) {
|
||||
$_SESSION['sort_order'] = $save_arr['message_sort_order'] = $sort_order;
|
||||
}
|
||||
}
|
||||
|
||||
// register layout change
|
||||
if ($layout = rcube_utils::get_input_value('_layout', rcube_utils::INPUT_GET)) {
|
||||
$OUTPUT->set_env('layout', $layout);
|
||||
$save_arr['layout'] = $layout;
|
||||
// force header replace on layout change
|
||||
$cols = $_SESSION['list_attrib']['columns'];
|
||||
}
|
||||
// is there a set of columns for this request?
|
||||
else if ($cols = rcube_utils::get_input_value('_cols', rcube_utils::INPUT_GET)) {
|
||||
$_SESSION['list_attrib']['columns'] = explode(',', $cols);
|
||||
if (!in_array('list_cols', $dont_override)) {
|
||||
$save_arr['list_cols'] = explode(',', $cols);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($save_arr)) {
|
||||
$RCMAIL->user->save_prefs($save_arr);
|
||||
}
|
||||
|
||||
$mbox_name = $RCMAIL->storage->get_folder();
|
||||
$threading = (bool) $RCMAIL->storage->get_threading();
|
||||
|
||||
// Synchronize mailbox cache, handle flag changes
|
||||
$RCMAIL->storage->folder_sync($mbox_name);
|
||||
|
||||
// fetch message headers
|
||||
if ($count = $RCMAIL->storage->count($mbox_name, $threading ? 'THREADS' : 'ALL', !empty($_REQUEST['_refresh']))) {
|
||||
$a_headers = $RCMAIL->storage->list_messages($mbox_name, NULL, rcmail_sort_column(), rcmail_sort_order());
|
||||
}
|
||||
|
||||
// update search set (possible change of threading mode)
|
||||
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'])
|
||||
&& $_SESSION['search_request'] == $_REQUEST['_search']
|
||||
) {
|
||||
$search_request = $_REQUEST['_search'];
|
||||
$_SESSION['search'] = $RCMAIL->storage->get_search_set();
|
||||
}
|
||||
// remove old search data
|
||||
else if (empty($_REQUEST['_search']) && isset($_SESSION['search'])) {
|
||||
$RCMAIL->session->remove('search');
|
||||
}
|
||||
|
||||
rcmail_list_pagetitle();
|
||||
|
||||
// update mailboxlist
|
||||
if (empty($search_request)) {
|
||||
rcmail_send_unread_count($mbox_name, !empty($_REQUEST['_refresh']), empty($a_headers) ? 0 : null);
|
||||
}
|
||||
|
||||
// update message count display
|
||||
$pages = ceil($count/$RCMAIL->storage->get_pagesize());
|
||||
$page = $count ? $RCMAIL->storage->get_page() : 1;
|
||||
$exists = $RCMAIL->storage->count($mbox_name, 'EXISTS', true);
|
||||
|
||||
$OUTPUT->set_env('messagecount', $count);
|
||||
$OUTPUT->set_env('pagecount', $pages);
|
||||
$OUTPUT->set_env('threading', $threading);
|
||||
$OUTPUT->set_env('current_page', $page);
|
||||
$OUTPUT->set_env('exists', $exists);
|
||||
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count), $mbox_name);
|
||||
|
||||
// remove old message rows if commanded by the client
|
||||
if (!empty($_REQUEST['_clear'])) {
|
||||
$OUTPUT->command('clear_message_list');
|
||||
}
|
||||
|
||||
// add message rows
|
||||
rcmail_js_message_list($a_headers, false, $cols);
|
||||
|
||||
if (isset($a_headers) && count($a_headers)) {
|
||||
if ($search_request) {
|
||||
$OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count));
|
||||
}
|
||||
|
||||
// remember last HIGHESTMODSEQ value (if supported)
|
||||
// we need it for flag updates in check-recent
|
||||
$data = $RCMAIL->storage->folder_data($mbox_name);
|
||||
if (!empty($data['HIGHESTMODSEQ'])) {
|
||||
$_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
// handle IMAP errors (e.g. #1486905)
|
||||
if ($err_code = $RCMAIL->storage->get_error_code()) {
|
||||
$RCMAIL->display_server_error();
|
||||
}
|
||||
else if ($search_request) {
|
||||
$OUTPUT->show_message('searchnomatch', 'notice');
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message('nomessagesfound', 'notice');
|
||||
}
|
||||
}
|
||||
|
||||
// set trash folder state
|
||||
if ($mbox_name === $RCMAIL->config->get('trash_mbox')) {
|
||||
$OUTPUT->command('set_trash_count', $exists);
|
||||
}
|
||||
|
||||
if ($page == 1) {
|
||||
$OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $multifolder ? 'INBOX' : $mbox_name));
|
||||
}
|
||||
|
||||
// send response
|
||||
$OUTPUT->send();
|
126
data/web/rc/program/steps/mail/list_contacts.inc
Normal file
126
data/web/rc/program/steps/mail/list_contacts.inc
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/list_contacts.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2012-2014, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Send contacts list to client (as remote response) |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$afields = $RCMAIL->config->get('contactlist_fields');
|
||||
$addr_sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
|
||||
$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50));
|
||||
$list_page = max(1, intval($_GET['_page']));
|
||||
$jsresult = array();
|
||||
|
||||
// Use search result
|
||||
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']])) {
|
||||
$search = (array)$_SESSION['search'][$_REQUEST['_search']];
|
||||
$sparam = $_SESSION['search_params']['id'] == $_REQUEST['_search'] ? $_SESSION['search_params']['data'] : array();
|
||||
|
||||
// get records from all sources
|
||||
foreach ($search as $s => $set) {
|
||||
$CONTACTS = $RCMAIL->get_address_book($s);
|
||||
|
||||
// list matching groups of this source (on page one)
|
||||
if ($sparam[1] && $CONTACTS->groups && $list_page == 1) {
|
||||
$jsresult += rcmail_compose_contact_groups($CONTACTS, $s, $sparam[1], (int)$RCMAIL->config->get('addressbook_search_mode'));
|
||||
}
|
||||
|
||||
// reset page
|
||||
$CONTACTS->set_page(1);
|
||||
$CONTACTS->set_pagesize(9999);
|
||||
$CONTACTS->set_search_set($set);
|
||||
|
||||
// get records
|
||||
$result = $CONTACTS->list_records($afields);
|
||||
|
||||
while ($row = $result->next()) {
|
||||
$row['sourceid'] = $s;
|
||||
$key = rcube_addressbook::compose_contact_key($row, $addr_sort_col);
|
||||
$records[$key] = $row;
|
||||
}
|
||||
unset($result);
|
||||
}
|
||||
|
||||
// sort the records
|
||||
ksort($records, SORT_LOCALE_STRING);
|
||||
|
||||
// create resultset object
|
||||
$count = count($records);
|
||||
$first = ($list_page-1) * $page_size;
|
||||
$result = new rcube_result_set($count, $first);
|
||||
|
||||
// we need only records for current page
|
||||
if ($page_size < $count) {
|
||||
$records = array_slice($records, $first, $page_size);
|
||||
}
|
||||
|
||||
$result->records = array_values($records);
|
||||
}
|
||||
// list contacts from selected source
|
||||
else {
|
||||
$source = rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC);
|
||||
$CONTACTS = $RCMAIL->get_address_book($source);
|
||||
|
||||
if ($CONTACTS && $CONTACTS->ready) {
|
||||
// set list properties
|
||||
$CONTACTS->set_pagesize($page_size);
|
||||
$CONTACTS->set_page($list_page);
|
||||
|
||||
if ($group_id = rcube_utils::get_input_value('_gid', rcube_utils::INPUT_GPC)) {
|
||||
$CONTACTS->set_group($group_id);
|
||||
}
|
||||
// list groups of this source (on page one)
|
||||
else if ($CONTACTS->groups && $CONTACTS->list_page == 1) {
|
||||
$jsresult = rcmail_compose_contact_groups($CONTACTS, $source);
|
||||
}
|
||||
|
||||
// get contacts for this user
|
||||
$result = $CONTACTS->list_records($afields);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($result) && !$result->count && $result->searchonly) {
|
||||
$OUTPUT->show_message('contactsearchonly', 'notice');
|
||||
}
|
||||
else if (!empty($result) && $result->count > 0) {
|
||||
// create javascript list
|
||||
while ($row = $result->next()) {
|
||||
$name = rcube_addressbook::compose_list_name($row);
|
||||
|
||||
// add record for every email address of the contact
|
||||
$emails = $CONTACTS->get_col_values('email', $row, true);
|
||||
foreach ($emails as $i => $email) {
|
||||
$row_id = $row['ID'].'-'.$i;
|
||||
$jsresult[$row_id] = format_email_recipient($email, $name);
|
||||
$classname = $row['_type'] == 'group' ? 'group' : 'person';
|
||||
$keyname = $row['_type'] == 'group' ? 'contactgroup' : 'contact';
|
||||
|
||||
$OUTPUT->command('add_contact_row', $row_id, array(
|
||||
$keyname => html::a(array('title' => $email), rcube::Q($name ?: $email) .
|
||||
($name && count($emails) > 1 ? ' ' . html::span('email', rcube::Q($email)) : '')
|
||||
)), $classname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update env
|
||||
$OUTPUT->set_env('contactdata', $jsresult);
|
||||
$OUTPUT->set_env('pagecount', ceil($result->count / $page_size));
|
||||
$OUTPUT->command('set_page_buttons');
|
||||
|
||||
// send response
|
||||
$OUTPUT->send();
|
173
data/web/rc/program/steps/mail/mark.inc
Normal file
173
data/web/rc/program/steps/mail/mark.inc
Normal file
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/mark.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2014, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Mark the submitted messages with the specified flag |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// only process ajax requests
|
||||
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',
|
||||
'delete' => 'DELETED',
|
||||
'read' => 'SEEN',
|
||||
'unread' => 'UNSEEN',
|
||||
'flagged' => 'FLAGGED',
|
||||
'unflagged' => 'UNFLAGGED',
|
||||
);
|
||||
|
||||
$_uids = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST);
|
||||
$flag = rcube_utils::get_input_value('_flag', rcube_utils::INPUT_POST);
|
||||
$folders = rcube_utils::get_input_value('_folders', rcube_utils::INPUT_POST);
|
||||
$mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST);
|
||||
|
||||
if ($_uids && $flag) {
|
||||
$flag = $a_flags_map[$flag] ?: strtoupper($flag);
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
if ($folders == 'all') {
|
||||
$mboxes = $RCMAIL->storage->list_folders_subscribed('', '*', 'mail');
|
||||
$input = array_combine($mboxes, array_fill(0, count($mboxes), '*'));
|
||||
}
|
||||
else if ($folders == 'sub') {
|
||||
$delim = $RCMAIL->storage->get_hierarchy_delimiter();
|
||||
$mboxes = $RCMAIL->storage->list_folders_subscribed($mbox . $delim, '*', 'mail');
|
||||
array_unshift($mboxes, $mbox);
|
||||
$input = array_combine($mboxes, array_fill(0, count($mboxes), '*'));
|
||||
}
|
||||
else if ($folders == 'cur') {
|
||||
$input = array($mbox => '*');
|
||||
}
|
||||
else {
|
||||
$input = rcmail::get_uids();
|
||||
}
|
||||
|
||||
foreach ($input as $mbox => $uids) {
|
||||
$marked += (int)$RCMAIL->storage->set_flag($uids, $flag, $mbox);
|
||||
$count += count($uids);
|
||||
}
|
||||
|
||||
if (!$marked) {
|
||||
// send error message
|
||||
if ($_POST['_from'] != 'show') {
|
||||
$OUTPUT->command('list_mailbox');
|
||||
}
|
||||
|
||||
$RCMAIL->display_server_error('errormarking');
|
||||
$OUTPUT->send();
|
||||
exit;
|
||||
}
|
||||
else if (empty($_POST['_quiet'])) {
|
||||
$OUTPUT->show_message('messagemarked', 'confirmation');
|
||||
}
|
||||
|
||||
if ($flag == 'DELETED' && $read_deleted && !empty($_POST['_ruid'])) {
|
||||
$ruids = rcube_utils::get_input_value('_ruid', rcube_utils::INPUT_POST);
|
||||
foreach (rcmail::get_uids($ruids) as $mbox => $uids) {
|
||||
$read += (int)$RCMAIL->storage->set_flag($uids, 'SEEN', $mbox);
|
||||
}
|
||||
|
||||
if ($read && !$skip_deleted) {
|
||||
$OUTPUT->command('flag_deleted_as_read', $ruids);
|
||||
}
|
||||
}
|
||||
|
||||
if ($flag == 'SEEN' || $flag == 'UNSEEN' || ($flag == 'DELETED' && !$skip_deleted)) {
|
||||
foreach ($input as $mbox => $uids) {
|
||||
rcmail_send_unread_count($mbox);
|
||||
}
|
||||
|
||||
$OUTPUT->set_env('last_flag', $flag);
|
||||
}
|
||||
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 {
|
||||
$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();
|
||||
}
|
||||
|
||||
$msg_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL');
|
||||
$page_size = $RCMAIL->storage->get_pagesize();
|
||||
$page = $RCMAIL->storage->get_page();
|
||||
$pages = ceil($msg_count / $page_size);
|
||||
$nextpage_count = $old_count - $page_size * $page;
|
||||
$remaining = $msg_count - $page_size * ($page - 1);
|
||||
|
||||
// jump back one page (user removed the whole last page)
|
||||
if ($page > 1 && $remaining == 0) {
|
||||
$page -= 1;
|
||||
$RCMAIL->storage->set_page($page);
|
||||
$_SESSION['page'] = $page;
|
||||
$jump_back = true;
|
||||
}
|
||||
|
||||
// update message count display
|
||||
$OUTPUT->set_env('messagecount', $msg_count);
|
||||
$OUTPUT->set_env('current_page', $page);
|
||||
$OUTPUT->set_env('pagecount', $pages);
|
||||
|
||||
// update mailboxlist
|
||||
$mbox = $RCMAIL->storage->get_folder();
|
||||
$unseen_count = $msg_count ? $RCMAIL->storage->count($mbox, 'UNSEEN') : 0;
|
||||
$old_unseen = rcmail_get_unseen_count($mbox);
|
||||
|
||||
if ($old_unseen != $unseen_count) {
|
||||
$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) {
|
||||
$count = rcube_utils::get_input_value('_count', rcube_utils::INPUT_POST);
|
||||
}
|
||||
|
||||
// add new rows from next page (if any)
|
||||
if ($old_count && $_uids != '*' && ($jump_back || $nextpage_count > 0)) {
|
||||
$a_headers = $RCMAIL->storage->list_messages($mbox, NULL,
|
||||
rcmail_sort_column(), rcmail_sort_order(), $jump_back ? NULL : $count);
|
||||
|
||||
rcmail_js_message_list($a_headers, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message('internalerror', 'error');
|
||||
}
|
||||
|
||||
$OUTPUT->send();
|
179
data/web/rc/program/steps/mail/move_del.inc
Normal file
179
data/web/rc/program/steps/mail/move_del.inc
Normal file
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/move_del.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2014, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Move the submitted messages to a specific mailbox or delete them |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// only process ajax requests
|
||||
if (!$OUTPUT->ajax_call) {
|
||||
return;
|
||||
}
|
||||
|
||||
// count messages before changing anything
|
||||
$threading = (bool) $RCMAIL->storage->get_threading();
|
||||
$trash = $RCMAIL->config->get('trash_mbox');
|
||||
$sources = array();
|
||||
|
||||
if ($_POST['_from'] != 'show') {
|
||||
$old_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL');
|
||||
$old_pages = ceil($old_count / $RCMAIL->storage->get_pagesize());
|
||||
}
|
||||
|
||||
// move messages
|
||||
if ($RCMAIL->action == 'move' && !empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) {
|
||||
$target = rcube_utils::get_input_value('_target_mbox', rcube_utils::INPUT_POST, true);
|
||||
$success = true;
|
||||
|
||||
foreach (rcmail::get_uids(null, null, $multifolder) as $mbox => $uids) {
|
||||
if ($mbox === $target) {
|
||||
$count += count($uids);
|
||||
}
|
||||
else if ($RCMAIL->storage->move_message($uids, $target, $mbox)) {
|
||||
$count += count($uids);
|
||||
$sources[] = $mbox;
|
||||
}
|
||||
else {
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$success) {
|
||||
// send error message
|
||||
if ($_POST['_from'] != 'show')
|
||||
$OUTPUT->command('list_mailbox');
|
||||
$RCMAIL->display_server_error('errormoving', null, $target == $trash ? 'delete' : '');
|
||||
$OUTPUT->send();
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message($target == $trash ? 'messagemovedtotrash' : 'messagemoved', 'confirmation');
|
||||
}
|
||||
|
||||
if (!empty($_POST['_refresh'])) {
|
||||
// FIXME: send updated message rows instead of reloading the entire list
|
||||
$OUTPUT->command('refresh_list');
|
||||
}
|
||||
else {
|
||||
$addrows = true;
|
||||
}
|
||||
}
|
||||
// delete messages
|
||||
else if ($RCMAIL->action == 'delete' && !empty($_POST['_uid'])) {
|
||||
foreach (rcmail::get_uids(null, null, $multifolder) as $mbox => $uids) {
|
||||
$del += (int)$RCMAIL->storage->delete_message($uids, $mbox);
|
||||
$count += count($uids);
|
||||
$sources[] = $mbox;
|
||||
}
|
||||
|
||||
if (!$del) {
|
||||
// send error message
|
||||
if ($_POST['_from'] != 'show')
|
||||
$OUTPUT->command('list_mailbox');
|
||||
$RCMAIL->display_server_error('errordeleting');
|
||||
$OUTPUT->send();
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message('messagedeleted', 'confirmation');
|
||||
}
|
||||
|
||||
$addrows = true;
|
||||
}
|
||||
// unknown action or missing query param
|
||||
else {
|
||||
$OUTPUT->show_message('internalerror', 'error');
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
$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();
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
$mbox = $RCMAIL->storage->get_folder();
|
||||
$msg_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL');
|
||||
$exists = $RCMAIL->storage->count($mbox, 'EXISTS', true);
|
||||
$page_size = $RCMAIL->storage->get_pagesize();
|
||||
$page = $RCMAIL->storage->get_page();
|
||||
$pages = ceil($msg_count / $page_size);
|
||||
$nextpage_count = $old_count - $page_size * $page;
|
||||
$remaining = $msg_count - $page_size * ($page - 1);
|
||||
|
||||
// jump back one page (user removed the whole last page)
|
||||
if ($page > 1 && $remaining == 0) {
|
||||
$page -= 1;
|
||||
$RCMAIL->storage->set_page($page);
|
||||
$_SESSION['page'] = $page;
|
||||
$jump_back = true;
|
||||
}
|
||||
|
||||
// update message count display
|
||||
$OUTPUT->set_env('messagecount', $msg_count);
|
||||
$OUTPUT->set_env('current_page', $page);
|
||||
$OUTPUT->set_env('pagecount', $pages);
|
||||
$OUTPUT->set_env('exists', $exists);
|
||||
|
||||
// update mailboxlist
|
||||
$unseen_count = $msg_count ? $RCMAIL->storage->count($mbox, 'UNSEEN') : 0;
|
||||
$old_unseen = rcmail_get_unseen_count($mbox);
|
||||
|
||||
if ($old_unseen != $unseen_count) {
|
||||
$OUTPUT->command('set_unread_count', $mbox, $unseen_count, ($mbox == 'INBOX'));
|
||||
rcmail_set_unseen_count($mbox, $unseen_count);
|
||||
}
|
||||
|
||||
if ($RCMAIL->action == 'move' && strlen($target)) {
|
||||
rcmail_send_unread_count($target, true);
|
||||
}
|
||||
|
||||
$OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $multifolder ? $sources[0] : 'INBOX'));
|
||||
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count), $mbox);
|
||||
|
||||
if ($threading) {
|
||||
$count = rcube_utils::get_input_value('_count', rcube_utils::INPUT_POST);
|
||||
}
|
||||
|
||||
// add new rows from next page (if any)
|
||||
if ($addrows && $count && $uids != '*' && ($jump_back || $nextpage_count > 0)) {
|
||||
$a_headers = $RCMAIL->storage->list_messages($mbox, NULL,
|
||||
rcmail_sort_column(), rcmail_sort_order(), $jump_back ? NULL : $count);
|
||||
|
||||
rcmail_js_message_list($a_headers, false);
|
||||
}
|
||||
|
||||
// set trash folder state
|
||||
if ($mbox === $trash) {
|
||||
$OUTPUT->command('set_trash_count', $exists);
|
||||
}
|
||||
else if ($target !== null && $target === $trash) {
|
||||
$OUTPUT->command('set_trash_count', $RCMAIL->storage->count($trash, 'EXISTS', true));
|
||||
}
|
||||
|
||||
// send response
|
||||
$OUTPUT->send();
|
66
data/web/rc/program/steps/mail/pagenav.inc
Normal file
66
data/web/rc/program/steps/mail/pagenav.inc
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/pagenav.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2016, 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: |
|
||||
| Updates message page navigation controls |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_GET);
|
||||
$index = $RCMAIL->storage->index(null, rcmail_sort_column(), rcmail_sort_order());
|
||||
$cnt = $index->count_messages();
|
||||
|
||||
if ($cnt && ($pos = $index->exists($uid, true)) !== false) {
|
||||
$prev = $pos ? $index->get_element($pos-1) : 0;
|
||||
$first = $pos ? $index->get_element('FIRST') : 0;
|
||||
$next = $pos < $cnt-1 ? $index->get_element($pos+1) : 0;
|
||||
$last = $pos < $cnt-1 ? $index->get_element('LAST') : 0;
|
||||
}
|
||||
else {
|
||||
// error, this will at least disable page navigation
|
||||
$OUTPUT->command('set_rowcount', '');
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
// Set UIDs and activate navigation buttons
|
||||
if ($prev) {
|
||||
$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) {
|
||||
$OUTPUT->set_env('first_uid', $first);
|
||||
}
|
||||
|
||||
if ($last) {
|
||||
$OUTPUT->set_env('last_uid', $last);
|
||||
}
|
||||
|
||||
// Don't need a real messages count value
|
||||
$OUTPUT->set_env('messagecount', 1);
|
||||
|
||||
// Set rowcount text
|
||||
$OUTPUT->command('set_rowcount', $RCMAIL->gettext(array(
|
||||
'name' => 'messagenrof',
|
||||
'vars' => array('nr' => $pos+1, 'count' => $cnt)
|
||||
)));
|
||||
|
||||
$OUTPUT->send();
|
248
data/web/rc/program/steps/mail/search.inc
Normal file
248
data/web/rc/program/steps/mail/search.inc
Normal file
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| steps/mail/search.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Mail messages search action |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Benjamin Smith <defitro@gmail.com> |
|
||||
| Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$REMOTE_REQUEST = TRUE;
|
||||
|
||||
@set_time_limit(170); // extend default max_execution_time to ~3 minutes
|
||||
|
||||
// reset list_page and old search results
|
||||
$RCMAIL->storage->set_page(1);
|
||||
$RCMAIL->storage->set_search_set(NULL);
|
||||
$_SESSION['page'] = 1;
|
||||
|
||||
// using encodeURI with javascript "should" give us
|
||||
// a correctly encoded query string
|
||||
$imap_charset = RCUBE_CHARSET;
|
||||
|
||||
// get search string
|
||||
$str = rcube_utils::get_input_value('_q', rcube_utils::INPUT_GET, true);
|
||||
$mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GET, true);
|
||||
$filter = rcube_utils::get_input_value('_filter', rcube_utils::INPUT_GET);
|
||||
$headers = rcube_utils::get_input_value('_headers', rcube_utils::INPUT_GET);
|
||||
$scope = rcube_utils::get_input_value('_scope', rcube_utils::INPUT_GET);
|
||||
$interval = rcube_utils::get_input_value('_interval', rcube_utils::INPUT_GET);
|
||||
$continue = rcube_utils::get_input_value('_continue', rcube_utils::INPUT_GET);
|
||||
$subject = array();
|
||||
|
||||
$filter = trim($filter);
|
||||
$search_request = md5($mbox.$scope.$interval.$filter.$str);
|
||||
|
||||
// add list filter string
|
||||
$search_str = $filter && $filter != 'ALL' ? $filter : '';
|
||||
|
||||
// Check the search string for type of search
|
||||
if (preg_match("/^from:.*/i", $str)) {
|
||||
list(,$srch) = explode(":", $str);
|
||||
$subject['from'] = "HEADER FROM";
|
||||
}
|
||||
else if (preg_match("/^to:.*/i", $str)) {
|
||||
list(,$srch) = explode(":", $str);
|
||||
$subject['to'] = "HEADER TO";
|
||||
}
|
||||
else if (preg_match("/^cc:.*/i", $str)) {
|
||||
list(,$srch) = explode(":", $str);
|
||||
$subject['cc'] = "HEADER CC";
|
||||
}
|
||||
else if (preg_match("/^bcc:.*/i", $str)) {
|
||||
list(,$srch) = explode(":", $str);
|
||||
$subject['bcc'] = "HEADER BCC";
|
||||
}
|
||||
else if (preg_match("/^subject:.*/i", $str)) {
|
||||
list(,$srch) = explode(":", $str);
|
||||
$subject['subject'] = "HEADER SUBJECT";
|
||||
}
|
||||
else if (preg_match("/^body:.*/i", $str)) {
|
||||
list(,$srch) = explode(":", $str);
|
||||
$subject['body'] = "BODY";
|
||||
}
|
||||
else if (strlen(trim($str))) {
|
||||
if ($headers) {
|
||||
foreach (explode(',', $headers) as $header) {
|
||||
if ($header == 'text') {
|
||||
// #1488208: get rid of other headers when searching by "TEXT"
|
||||
$subject = array('text' => 'TEXT');
|
||||
break;
|
||||
}
|
||||
else {
|
||||
$subject[$header] = ($header != 'body' ? 'HEADER ' : '') . strtoupper($header);
|
||||
}
|
||||
}
|
||||
|
||||
// save search modifiers for the current folder to user prefs
|
||||
$mkey = $scope == 'all' ? '*' : $mbox;
|
||||
$search_mods = rcmail_search_mods();
|
||||
$search_mods[$mkey] = array_fill_keys(array_keys($subject), 1);
|
||||
|
||||
$RCMAIL->user->save_prefs(array('search_mods' => $search_mods));
|
||||
}
|
||||
else {
|
||||
// search in subject by default
|
||||
$subject['subject'] = 'HEADER SUBJECT';
|
||||
}
|
||||
}
|
||||
|
||||
$search = isset($srch) ? trim($srch) : trim($str);
|
||||
|
||||
if ($search_interval = rcmail_search_interval_criteria($interval)) {
|
||||
$search_str .= ' ' . $search_interval;
|
||||
}
|
||||
|
||||
if (!empty($subject)) {
|
||||
$search_str .= str_repeat(' OR', count($subject)-1);
|
||||
foreach ($subject as $sub) {
|
||||
$search_str .= ' ' . $sub . ' ' . rcube_imap_generic::escape($search);
|
||||
}
|
||||
}
|
||||
|
||||
$search_str = trim($search_str);
|
||||
$sort_column = rcmail_sort_column();
|
||||
|
||||
// set message set for already stored (but incomplete) search request
|
||||
if (!empty($continue) && isset($_SESSION['search']) && $_SESSION['search_request'] == $continue) {
|
||||
$RCMAIL->storage->set_search_set($_SESSION['search']);
|
||||
$search_str = $_SESSION['search'][0];
|
||||
}
|
||||
|
||||
// execute IMAP search
|
||||
if ($search_str) {
|
||||
// search all, current or subfolders folders
|
||||
if ($scope == 'all') {
|
||||
$mboxes = $RCMAIL->storage->list_folders_subscribed('', '*', 'mail', null, true);
|
||||
natcasesort($mboxes); // we want natural alphabetic sorting of folders in the result set
|
||||
}
|
||||
else if ($scope == 'sub') {
|
||||
$delim = $RCMAIL->storage->get_hierarchy_delimiter();
|
||||
$mboxes = $RCMAIL->storage->list_folders_subscribed($mbox . $delim, '*', 'mail');
|
||||
array_unshift($mboxes, $mbox);
|
||||
}
|
||||
|
||||
if ($scope != 'all') {
|
||||
// Remember current folder, it can change in meantime (plugins)
|
||||
// but we need it to e.g. recognize Sent folder to handle From/To column later
|
||||
$RCMAIL->output->set_env('mailbox', $mbox);
|
||||
}
|
||||
|
||||
$result = $RCMAIL->storage->search($mboxes, $search_str, $imap_charset, $sort_column);
|
||||
}
|
||||
|
||||
// save search results in session
|
||||
if (!is_array($_SESSION['search'])) {
|
||||
$_SESSION['search'] = array();
|
||||
}
|
||||
|
||||
if ($search_str) {
|
||||
$_SESSION['search'] = $RCMAIL->storage->get_search_set();
|
||||
$_SESSION['last_text_search'] = $str;
|
||||
}
|
||||
$_SESSION['search_request'] = $search_request;
|
||||
$_SESSION['search_scope'] = $scope;
|
||||
$_SESSION['search_interval'] = $interval;
|
||||
$_SESSION['search_filter'] = $filter;
|
||||
|
||||
// Get the headers
|
||||
if (!$result->incomplete) {
|
||||
$result_h = $RCMAIL->storage->list_messages($mbox, 1, $sort_column, rcmail_sort_order());
|
||||
}
|
||||
|
||||
// Make sure we got the headers
|
||||
if (!empty($result_h)) {
|
||||
$count = $RCMAIL->storage->count($mbox, $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL');
|
||||
|
||||
rcmail_js_message_list($result_h, false);
|
||||
|
||||
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
|
||||
if ($mbox !== null) {
|
||||
$data = $RCMAIL->storage->folder_data($mbox);
|
||||
if (!empty($data['HIGHESTMODSEQ'])) {
|
||||
$_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ'];
|
||||
}
|
||||
}
|
||||
}
|
||||
// handle IMAP errors (e.g. #1486905)
|
||||
else if ($err_code = $RCMAIL->storage->get_error_code()) {
|
||||
$count = 0;
|
||||
$RCMAIL->display_server_error();
|
||||
}
|
||||
// advice the client to re-send the (cross-folder) search request
|
||||
else if ($result->incomplete) {
|
||||
$count = 0; // keep UI locked
|
||||
$OUTPUT->command('continue_search', $search_request);
|
||||
}
|
||||
else {
|
||||
$count = 0;
|
||||
$OUTPUT->show_message('searchnomatch', 'notice');
|
||||
$OUTPUT->set_env('multifolder_listing', (bool)$result->multi);
|
||||
if ($result->multi && $scope == 'all') {
|
||||
$OUTPUT->command('select_folder', '');
|
||||
}
|
||||
}
|
||||
|
||||
// update message count display
|
||||
$OUTPUT->set_env('search_request', $search_str ? $search_request : '');
|
||||
$OUTPUT->set_env('search_filter', $_SESSION['search_filter']);
|
||||
$OUTPUT->set_env('threading', $RCMAIL->storage->get_threading());
|
||||
$OUTPUT->set_env('messagecount', $count);
|
||||
$OUTPUT->set_env('pagecount', ceil($count/$RCMAIL->storage->get_pagesize()));
|
||||
$OUTPUT->set_env('exists', $mbox === null ? 0 : $RCMAIL->storage->count($mbox, 'EXISTS'));
|
||||
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count, 1), $mbox);
|
||||
|
||||
rcmail_list_pagetitle();
|
||||
|
||||
// update unseen messages count
|
||||
if (empty($search_str)) {
|
||||
rcmail_send_unread_count($mbox, false, empty($result_h) ? 0 : null);
|
||||
}
|
||||
|
||||
if (!$result->incomplete) {
|
||||
$OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $result->multi ? 'INBOX' : $mbox));
|
||||
}
|
||||
|
||||
$OUTPUT->send();
|
||||
|
||||
|
||||
// Creates BEFORE/SINCE search criteria from the specified interval
|
||||
// Interval can be: 1W, 1M, 1Y, -1W, -1M, -1Y
|
||||
function rcmail_search_interval_criteria($interval)
|
||||
{
|
||||
if (empty($interval)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($interval[0] == '-') {
|
||||
$search = 'BEFORE';
|
||||
$interval = substr($interval, 1);
|
||||
}
|
||||
else {
|
||||
$search = 'SINCE';
|
||||
}
|
||||
|
||||
$date = new DateTime('now');
|
||||
$interval = new DateInterval('P' . $interval);
|
||||
|
||||
$date->sub($interval);
|
||||
|
||||
return $search . ' ' . $date->format('j-M-Y');
|
||||
}
|
121
data/web/rc/program/steps/mail/search_contacts.inc
Normal file
121
data/web/rc/program/steps/mail/search_contacts.inc
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/search_contacts.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2013-2014, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Search contacts from the adress book widget |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$search = rcube_utils::get_input_value('_q', rcube_utils::INPUT_GPC, true);
|
||||
$sources = $RCMAIL->get_address_sources();
|
||||
$search_mode = (int) $RCMAIL->config->get('addressbook_search_mode');
|
||||
$addr_sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
|
||||
$afields = $RCMAIL->config->get('contactlist_fields');
|
||||
$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50));
|
||||
$records = array();
|
||||
$search_set = array();
|
||||
$jsresult = array();
|
||||
$search_mode |= rcube_addressbook::SEARCH_GROUPS;
|
||||
|
||||
foreach ($sources as $s) {
|
||||
$source = $RCMAIL->get_address_book($s['id']);
|
||||
$source->set_page(1);
|
||||
$source->set_pagesize(9999);
|
||||
|
||||
// list matching groups of this source
|
||||
if ($source->groups) {
|
||||
$jsresult += rcmail_compose_contact_groups($source, $s['id'], $search, $search_mode);
|
||||
}
|
||||
|
||||
// get contacts count
|
||||
$result = $source->search($afields, $search, $search_mode, true, true, 'email');
|
||||
|
||||
if (!$result->count) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while ($row = $result->next()) {
|
||||
$row['sourceid'] = $s['id'];
|
||||
$key = rcube_addressbook::compose_contact_key($row, $addr_sort_col);
|
||||
$records[$key] = $row;
|
||||
}
|
||||
|
||||
$search_set[$s['id']] = $source->get_search_set();
|
||||
unset($result);
|
||||
}
|
||||
|
||||
$group_count = count($jsresult);
|
||||
|
||||
// sort the records
|
||||
ksort($records, SORT_LOCALE_STRING);
|
||||
|
||||
// create resultset object
|
||||
$count = count($records);
|
||||
$result = new rcube_result_set($count);
|
||||
|
||||
// select the requested page
|
||||
if ($page_size < $count) {
|
||||
$records = array_slice($records, $result->first, $page_size);
|
||||
}
|
||||
|
||||
$result->records = array_values($records);
|
||||
|
||||
if (!empty($result) && $result->count > 0) {
|
||||
// create javascript list
|
||||
while ($row = $result->next()) {
|
||||
$name = rcube_addressbook::compose_list_name($row);
|
||||
$classname = $row['_type'] == 'group' ? 'group' : 'person';
|
||||
$keyname = $row['_type'] == 'group' ? 'contactgroup' : 'contact';
|
||||
|
||||
// add record for every email address of the contact
|
||||
// (same as in list_contacts.inc)
|
||||
$emails = $source->get_col_values('email', $row, true);
|
||||
foreach ($emails as $i => $email) {
|
||||
$row_id = $row['ID'].'-'.$i;
|
||||
$jsresult[$row_id] = format_email_recipient($email, $name);
|
||||
$title = rcube_addressbook::compose_search_name($row, $email, $name);
|
||||
|
||||
$OUTPUT->command('add_contact_row', $row_id, array(
|
||||
$keyname => html::a(array('title' => $title), rcube::Q($name ?: $email) .
|
||||
($name && count($emails) > 1 ? ' ' . html::span('email', rcube::Q($email)) : '')
|
||||
)), $classname);
|
||||
}
|
||||
}
|
||||
|
||||
// search request ID
|
||||
$search_request = md5('composeaddr' . $search);
|
||||
|
||||
// save search settings in session
|
||||
$_SESSION['search'][$search_request] = $search_set;
|
||||
$_SESSION['search_params'] = array('id' => $search_request, 'data' => array($afields, $search));
|
||||
|
||||
$OUTPUT->show_message('contactsearchsuccessful', 'confirmation', array('nr' => $result->count));
|
||||
|
||||
$OUTPUT->set_env('search_request', $search_request);
|
||||
$OUTPUT->set_env('source', '');
|
||||
$OUTPUT->command('unselect_directory');
|
||||
}
|
||||
else if (!$group_count) {
|
||||
$OUTPUT->show_message('nocontactsfound', 'notice');
|
||||
}
|
||||
|
||||
// update env
|
||||
$OUTPUT->set_env('contactdata', $jsresult);
|
||||
$OUTPUT->set_env('pagecount', ceil($result->count / $page_size));
|
||||
$OUTPUT->command('set_page_buttons');
|
||||
|
||||
// send response
|
||||
$OUTPUT->send();
|
963
data/web/rc/program/steps/mail/sendmail.inc
Normal file
963
data/web/rc/program/steps/mail/sendmail.inc
Normal file
@@ -0,0 +1,963 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/sendmail.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Compose a new mail message with all headers and attachments |
|
||||
| and send it using the PEAR::Net_SMTP class or with PHP mail() |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// remove all scripts and act as called in frame
|
||||
$OUTPUT->reset();
|
||||
$OUTPUT->framed = TRUE;
|
||||
|
||||
$saveonly = !empty($_GET['_saveonly']);
|
||||
$savedraft = !empty($_POST['_draft']) && !$saveonly;
|
||||
$sendmail_delay = (int) $RCMAIL->config->get('sendmail_delay');
|
||||
$drafts_mbox = $RCMAIL->config->get('drafts_mbox');
|
||||
|
||||
$COMPOSE_ID = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC);
|
||||
$COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
|
||||
|
||||
/****** checks ********/
|
||||
|
||||
if (!isset($COMPOSE['id'])) {
|
||||
rcube::raise_error(array('code' => 500, 'type' => 'php',
|
||||
'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Invalid compose ID"), true, false);
|
||||
|
||||
$OUTPUT->show_message('internalerror', 'error');
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
|
||||
if (!$savedraft) {
|
||||
if (empty($_POST['_to']) && empty($_POST['_cc']) && empty($_POST['_bcc']) && $_POST['_message']) {
|
||||
$OUTPUT->show_message('sendingfailed', 'error');
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
|
||||
if ($sendmail_delay) {
|
||||
$wait_sec = time() - $sendmail_delay - intval($RCMAIL->config->get('last_message_time'));
|
||||
if ($wait_sec < 0) {
|
||||
$OUTPUT->show_message('senttooquickly', 'error', array('sec' => $wait_sec * -1));
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****** compose message ********/
|
||||
|
||||
// set default charset
|
||||
$message_charset = isset($_POST['_charset']) ? $_POST['_charset'] : $OUTPUT->get_charset();
|
||||
|
||||
$EMAIL_FORMAT_ERROR = NULL;
|
||||
$RECIPIENT_COUNT = 0;
|
||||
|
||||
$mailto = rcmail_email_input_format(rcube_utils::get_input_value('_to', rcube_utils::INPUT_POST, TRUE, $message_charset), true);
|
||||
$mailcc = rcmail_email_input_format(rcube_utils::get_input_value('_cc', rcube_utils::INPUT_POST, TRUE, $message_charset), true);
|
||||
$mailbcc = rcmail_email_input_format(rcube_utils::get_input_value('_bcc', rcube_utils::INPUT_POST, TRUE, $message_charset), true);
|
||||
|
||||
if ($EMAIL_FORMAT_ERROR && !$savedraft) {
|
||||
$OUTPUT->show_message('emailformaterror', 'error', array('email' => $EMAIL_FORMAT_ERROR));
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
|
||||
if (empty($mailto) && !empty($mailcc)) {
|
||||
$mailto = $mailcc;
|
||||
$mailcc = null;
|
||||
}
|
||||
else if (empty($mailto)) {
|
||||
$mailto = 'undisclosed-recipients:;';
|
||||
}
|
||||
|
||||
// Get sender name and address...
|
||||
$from = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST, true, $message_charset);
|
||||
// ... from identity...
|
||||
if (is_numeric($from)) {
|
||||
if (is_array($identity_arr = rcmail_get_identity($from))) {
|
||||
if ($identity_arr['mailto'])
|
||||
$from = $identity_arr['mailto'];
|
||||
if ($identity_arr['string'])
|
||||
$from_string = $identity_arr['string'];
|
||||
}
|
||||
else {
|
||||
$from = null;
|
||||
}
|
||||
}
|
||||
// ... if there is no identity record, this might be a custom from
|
||||
else if (($from_string = rcmail_email_input_format($from))
|
||||
&& preg_match('/(\S+@\S+)/', $from_string, $m)
|
||||
) {
|
||||
$from = trim($m[1], '<>');
|
||||
}
|
||||
// ... otherwise it's empty or invalid
|
||||
else {
|
||||
$from = null;
|
||||
}
|
||||
|
||||
// check 'From' address (identity may be incomplete)
|
||||
if (!$savedraft && !$saveonly && empty($from)) {
|
||||
$OUTPUT->show_message('nofromaddress', 'error');
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
|
||||
if (!$from_string && $from) {
|
||||
$from_string = $from;
|
||||
}
|
||||
|
||||
if (empty($COMPOSE['param']['message-id'])) {
|
||||
$COMPOSE['param']['message-id'] = $RCMAIL->gen_message_id($from);
|
||||
}
|
||||
$message_id = $COMPOSE['param']['message-id'];
|
||||
|
||||
// compose headers array
|
||||
$headers = array();
|
||||
|
||||
// if configured, the Received headers goes to top, for good measure
|
||||
if ($RCMAIL->config->get('http_received_header')) {
|
||||
$nldlm = "\r\n\t";
|
||||
$http_header = 'from ';
|
||||
|
||||
// FROM/VIA
|
||||
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$hosts = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'], 2);
|
||||
$http_header .= rcmail_received_host($hosts[0]) . $nldlm . ' via ';
|
||||
}
|
||||
|
||||
$http_header .= rcmail_received_host($_SERVER['REMOTE_ADDR']);
|
||||
|
||||
// BY
|
||||
$http_header .= $nldlm . 'by ' . $_SERVER['HTTP_HOST'];
|
||||
|
||||
// WITH
|
||||
$http_header .= $nldlm . 'with HTTP (' . $_SERVER['SERVER_PROTOCOL']
|
||||
. ' ' . $_SERVER['REQUEST_METHOD'] . '); ' . date('r');
|
||||
|
||||
$headers['Received'] = wordwrap($http_header, 69, $nldlm);
|
||||
}
|
||||
|
||||
$headers['Date'] = $RCMAIL->user_date();
|
||||
$headers['From'] = rcube_charset::convert($from_string, RCUBE_CHARSET, $message_charset);
|
||||
$headers['To'] = $mailto;
|
||||
|
||||
// additional recipients
|
||||
if (!empty($mailcc)) {
|
||||
$headers['Cc'] = $mailcc;
|
||||
}
|
||||
if (!empty($mailbcc)) {
|
||||
$headers['Bcc'] = $mailbcc;
|
||||
}
|
||||
|
||||
if (($max_recipients = (int) $RCMAIL->config->get('max_recipients')) > 0) {
|
||||
if ($RECIPIENT_COUNT > $max_recipients) {
|
||||
$OUTPUT->show_message('toomanyrecipients', 'error', array('max' => $max_recipients));
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
}
|
||||
|
||||
$dont_override = (array) $RCMAIL->config->get('dont_override');
|
||||
$mdn_enabled = in_array('mdn_default', $dont_override) ? $RCMAIL->config->get('mdn_default') : !empty($_POST['_mdn']);
|
||||
$dsn_enabled = in_array('dsn_default', $dont_override) ? $RCMAIL->config->get('dsn_default') : !empty($_POST['_dsn']);
|
||||
$subject = trim(rcube_utils::get_input_value('_subject', rcube_utils::INPUT_POST, TRUE, $message_charset));
|
||||
|
||||
if (strlen($subject)) {
|
||||
$headers['Subject'] = $subject;
|
||||
}
|
||||
if (!empty($identity_arr['organization'])) {
|
||||
$headers['Organization'] = $identity_arr['organization'];
|
||||
}
|
||||
if ($hdr = rcube_utils::get_input_value('_replyto', rcube_utils::INPUT_POST, TRUE, $message_charset)) {
|
||||
$headers['Reply-To'] = rcmail_email_input_format($hdr);
|
||||
}
|
||||
if (!empty($headers['Reply-To'])) {
|
||||
$headers['Mail-Reply-To'] = $headers['Reply-To'];
|
||||
}
|
||||
if ($hdr = rcube_utils::get_input_value('_followupto', rcube_utils::INPUT_POST, TRUE, $message_charset)) {
|
||||
$headers['Mail-Followup-To'] = rcmail_email_input_format($hdr);
|
||||
}
|
||||
|
||||
// remember reply/forward UIDs in special headers
|
||||
if ($savedraft) {
|
||||
// Note: We ignore <UID>.<PART> forwards/replies here
|
||||
if (($uid = $COMPOSE['reply_uid']) && !preg_match('/^\d+\.[0-9.]+$/', $uid)) {
|
||||
$headers['X-Draft-Info'] = array('type' => 'reply', 'uid' => $uid);
|
||||
}
|
||||
else if (!empty($COMPOSE['forward_uid'])
|
||||
&& ($uid = rcube_imap_generic::compressMessageSet($COMPOSE['forward_uid']))
|
||||
&& !preg_match('/^\d+[0-9.]+$/', $uid)
|
||||
) {
|
||||
$headers['X-Draft-Info'] = array('type' => 'forward', 'uid' => $uid);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($COMPOSE['reply_msgid'])) {
|
||||
$headers['In-Reply-To'] = $COMPOSE['reply_msgid'];
|
||||
}
|
||||
if (!empty($COMPOSE['references'])) {
|
||||
$headers['References'] = $COMPOSE['references'];
|
||||
}
|
||||
|
||||
if (!empty($_POST['_priority'])) {
|
||||
$priority = intval($_POST['_priority']);
|
||||
$a_priorities = array(1 => 'highest', 2 => 'high', 4 => 'low', 5 => 'lowest');
|
||||
|
||||
if ($str_priority = $a_priorities[$priority]) {
|
||||
$headers['X-Priority'] = sprintf("%d (%s)", $priority, ucfirst($str_priority));
|
||||
}
|
||||
}
|
||||
|
||||
if ($mdn_enabled) {
|
||||
$headers['Return-Receipt-To'] = $from_string;
|
||||
$headers['Disposition-Notification-To'] = $from_string;
|
||||
}
|
||||
|
||||
// additional headers
|
||||
$headers['Message-ID'] = $message_id;
|
||||
$headers['X-Sender'] = $from;
|
||||
|
||||
if (is_array($headers['X-Draft-Info'])) {
|
||||
$headers['X-Draft-Info'] = rcmail_draftinfo_encode($headers['X-Draft-Info'] + array('folder' => $COMPOSE['mailbox']));
|
||||
}
|
||||
if ($hdr = $RCMAIL->config->get('useragent')) {
|
||||
$headers['User-Agent'] = $hdr;
|
||||
}
|
||||
|
||||
// exec hook for header checking and manipulation
|
||||
// Depracated: use message_before_send hook instead
|
||||
$data = $RCMAIL->plugins->exec_hook('message_outgoing_headers', array('headers' => $headers));
|
||||
|
||||
// sending aborted by plugin
|
||||
if ($data['abort'] && !$savedraft) {
|
||||
$OUTPUT->show_message($data['message'] ?: 'sendingfailed');
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
else {
|
||||
$headers = $data['headers'];
|
||||
}
|
||||
|
||||
$isHtml = (bool) rcube_utils::get_input_value('_is_html', rcube_utils::INPUT_POST);
|
||||
|
||||
// fetch message body
|
||||
$message_body = rcube_utils::get_input_value('_message', rcube_utils::INPUT_POST, TRUE, $message_charset);
|
||||
|
||||
if (isset($_POST['_pgpmime'])) {
|
||||
$pgp_mime = rcube_utils::get_input_value('_pgpmime', rcube_utils::INPUT_POST);
|
||||
$isHtml = false;
|
||||
$message_body = '';
|
||||
|
||||
// clear unencrypted attachments
|
||||
foreach ((array) $COMPOSE['attachments'] as $attach) {
|
||||
$RCMAIL->plugins->exec_hook('attachment_delete', $attach);
|
||||
}
|
||||
|
||||
$COMPOSE['attachments'] = array();
|
||||
}
|
||||
|
||||
if ($isHtml) {
|
||||
$bstyle = array();
|
||||
|
||||
if ($font_size = $RCMAIL->config->get('default_font_size')) {
|
||||
$bstyle[] = 'font-size: ' . $font_size;
|
||||
}
|
||||
if ($font_family = $RCMAIL->config->get('default_font')) {
|
||||
$bstyle[] = 'font-family: ' . rcmail::font_defs($font_family);
|
||||
}
|
||||
|
||||
// append doctype and html/body wrappers
|
||||
$bstyle = !empty($bstyle) ? (" style='" . implode($bstyle, '; ') . "'") : '';
|
||||
$message_body = '<html><head>'
|
||||
. '<meta http-equiv="Content-Type" content="text/html; charset=' . $message_charset . '" /></head>'
|
||||
. "<body" . $bstyle . ">\r\n" . $message_body;
|
||||
}
|
||||
|
||||
if (!$savedraft) {
|
||||
if ($isHtml) {
|
||||
$b_style = 'padding: 0 0.4em; border-left: #1010ff 2px solid; margin: 0';
|
||||
$pre_style = 'margin: 0; padding: 0; font-family: monospace';
|
||||
|
||||
$message_body = preg_replace(
|
||||
array(
|
||||
// remove empty signature div
|
||||
'/<div id="_rc_sig">( )?<\/div>[\s\r\n]*$/',
|
||||
// remove signature's div ID
|
||||
'/\s*id="_rc_sig"/',
|
||||
// add inline css for blockquotes and container
|
||||
'/<blockquote>/',
|
||||
'/<div class="pre">/',
|
||||
// convert TinyMCE's new-line sequences (#1490463)
|
||||
'/<p> <\/p>/',
|
||||
),
|
||||
array(
|
||||
'',
|
||||
'',
|
||||
'<blockquote type="cite" style="'.$b_style.'">',
|
||||
'<div class="pre" style="'.$pre_style.'">',
|
||||
'<p><br /></p>',
|
||||
),
|
||||
$message_body);
|
||||
}
|
||||
|
||||
// Check spelling before send
|
||||
if ($RCMAIL->config->get('spellcheck_before_send') && $RCMAIL->config->get('enable_spellcheck')
|
||||
&& empty($COMPOSE['spell_checked']) && !empty($message_body)
|
||||
) {
|
||||
$message_body = str_replace("\r\n", "\n", $message_body);
|
||||
$spellchecker = new rcube_spellchecker(rcube_utils::get_input_value('_lang', rcube_utils::INPUT_GPC));
|
||||
$spell_result = $spellchecker->check($message_body, $isHtml);
|
||||
|
||||
$COMPOSE['spell_checked'] = true;
|
||||
|
||||
if (!$spell_result) {
|
||||
if ($isHtml) {
|
||||
$result['words'] = $spellchecker->get();
|
||||
$result['dictionary'] = (bool) $RCMAIL->config->get('spellcheck_dictionary');
|
||||
}
|
||||
else {
|
||||
$result = $spellchecker->get_xml();
|
||||
}
|
||||
|
||||
$OUTPUT->show_message('mispellingsfound', 'error');
|
||||
$OUTPUT->command('spellcheck_resume', $result);
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
}
|
||||
|
||||
// generic footer for all messages
|
||||
if ($footer = rcmail_generic_message_footer($isHtml)) {
|
||||
$footer = rcube_charset::convert($footer, RCUBE_CHARSET, $message_charset);
|
||||
$message_body .= "\r\n" . $footer;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isHtml) {
|
||||
$message_body .= "\r\n</body></html>\r\n";
|
||||
}
|
||||
|
||||
// sort attachments to make sure the order is the same as in the UI (#1488423)
|
||||
if ($files = rcube_utils::get_input_value('_attachments', rcube_utils::INPUT_POST)) {
|
||||
$files = explode(',', $files);
|
||||
$files = array_flip($files);
|
||||
foreach ($files as $idx => $val) {
|
||||
$files[$idx] = $COMPOSE['attachments'][$idx];
|
||||
unset($COMPOSE['attachments'][$idx]);
|
||||
}
|
||||
|
||||
$COMPOSE['attachments'] = array_merge(array_filter($files), $COMPOSE['attachments']);
|
||||
}
|
||||
|
||||
// set line length for body wrapping
|
||||
$LINE_LENGTH = $RCMAIL->config->get('line_length', 72);
|
||||
|
||||
// Since we can handle big messages with disk usage, we need more time to work
|
||||
@set_time_limit(0);
|
||||
|
||||
// create PEAR::Mail_mime instance
|
||||
$MAIL_MIME = new Mail_mime("\r\n");
|
||||
|
||||
// Check if we have enough memory to handle the message in it
|
||||
// It's faster than using files, so we'll do this if we only can
|
||||
if (is_array($COMPOSE['attachments']) && ($mem_limit = parse_bytes(ini_get('memory_limit')))) {
|
||||
$memory = 0;
|
||||
foreach ($COMPOSE['attachments'] as $id => $attachment) {
|
||||
$memory += $attachment['size'];
|
||||
}
|
||||
|
||||
// Yeah, Net_SMTP needs up to 12x more memory, 1.33 is for base64
|
||||
if (!rcube_utils::mem_check($memory * 1.33 * 12)) {
|
||||
$MAIL_MIME->setParam('delay_file_io', true);
|
||||
}
|
||||
}
|
||||
|
||||
// For HTML-formatted messages, construct the MIME message with both
|
||||
// the HTML part and the plain-text part
|
||||
if ($isHtml) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('message_outgoing_body',
|
||||
array('body' => $message_body, 'type' => 'html', 'message' => $MAIL_MIME));
|
||||
|
||||
$MAIL_MIME->setHTMLBody($plugin['body']);
|
||||
|
||||
$plainTextPart = $RCMAIL->html2text($plugin['body'], array('width' => 0, 'charset' => $message_charset));
|
||||
$plainTextPart = rcube_mime::wordwrap($plainTextPart, $LINE_LENGTH, "\r\n", false, $message_charset);
|
||||
$plainTextPart = wordwrap($plainTextPart, 998, "\r\n", true);
|
||||
|
||||
// There's no sense to use multipart/alternative if the text/plain
|
||||
// part would be blank. Completely blank text/plain part may confuse
|
||||
// some mail clients (#5283)
|
||||
if (strlen(trim($plainTextPart)) > 0) {
|
||||
// make sure all line endings are CRLF (#1486712)
|
||||
$plainTextPart = preg_replace('/\r?\n/', "\r\n", $plainTextPart);
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('message_outgoing_body',
|
||||
array('body' => $plainTextPart, 'type' => 'alternative', 'message' => $MAIL_MIME));
|
||||
|
||||
// add a plain text version of the e-mail as an alternative part.
|
||||
$MAIL_MIME->setTXTBody($plugin['body']);
|
||||
}
|
||||
|
||||
// Extract image Data URIs into message attachments (#1488502)
|
||||
rcmail_extract_inline_images($MAIL_MIME, $from);
|
||||
}
|
||||
else {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('message_outgoing_body',
|
||||
array('body' => $message_body, 'type' => 'plain', 'message' => $MAIL_MIME));
|
||||
|
||||
$message_body = $plugin['body'];
|
||||
|
||||
// compose format=flowed content if enabled
|
||||
if ($flowed = ($savedraft || $RCMAIL->config->get('send_format_flowed', true)))
|
||||
$message_body = rcube_mime::format_flowed($message_body, min($LINE_LENGTH+2, 79), $message_charset);
|
||||
else
|
||||
$message_body = rcube_mime::wordwrap($message_body, $LINE_LENGTH, "\r\n", false, $message_charset);
|
||||
|
||||
$message_body = wordwrap($message_body, 998, "\r\n", true);
|
||||
|
||||
$MAIL_MIME->setTXTBody($message_body, false, true);
|
||||
}
|
||||
|
||||
// add stored attachments, if any
|
||||
if (is_array($COMPOSE['attachments'])) {
|
||||
foreach ($COMPOSE['attachments'] as $id => $attachment) {
|
||||
// This hook retrieves the attachment contents from the file storage backend
|
||||
$attachment = $RCMAIL->plugins->exec_hook('attachment_get', $attachment);
|
||||
|
||||
if ($isHtml) {
|
||||
$dispurl = '/[\'"]\S+display-attachment\S+file=rcmfile' . preg_quote($attachment['id']) . '[\'"]/';
|
||||
$message_body = $MAIL_MIME->getHTMLBody();
|
||||
$is_inline = preg_match($dispurl, $message_body);
|
||||
}
|
||||
else {
|
||||
$is_inline = false;
|
||||
}
|
||||
|
||||
// inline image
|
||||
if ($is_inline) {
|
||||
// Mail_Mime does not support many inline attachments with the same name (#1489406)
|
||||
// we'll generate cid: urls here to workaround this
|
||||
$cid = preg_replace('/[^0-9a-zA-Z]/', '', uniqid(time(), true));
|
||||
if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $from, $matches)) {
|
||||
$cid .= $matches[1];
|
||||
}
|
||||
else {
|
||||
$cid .= '@localhost';
|
||||
}
|
||||
|
||||
$message_body = preg_replace($dispurl, '"cid:' . $cid . '"', $message_body);
|
||||
|
||||
$MAIL_MIME->setHTMLBody($message_body);
|
||||
|
||||
if ($attachment['data'])
|
||||
$MAIL_MIME->addHTMLImage($attachment['data'], $attachment['mimetype'], $attachment['name'], false, $cid);
|
||||
else
|
||||
$MAIL_MIME->addHTMLImage($attachment['path'], $attachment['mimetype'], $attachment['name'], true, $cid);
|
||||
}
|
||||
else {
|
||||
$ctype = str_replace('image/pjpeg', 'image/jpeg', $attachment['mimetype']); // #1484914
|
||||
$file = $attachment['data'] ?: $attachment['path'];
|
||||
$folding = (int) $RCMAIL->config->get('mime_param_folding');
|
||||
|
||||
$MAIL_MIME->addAttachment($file,
|
||||
$ctype,
|
||||
$attachment['name'],
|
||||
$attachment['data'] ? false : true,
|
||||
$ctype == 'message/rfc822' ? '8bit' : 'base64',
|
||||
'attachment',
|
||||
$attachment['charset'],
|
||||
'', '',
|
||||
$folding ? 'quoted-printable' : NULL,
|
||||
$folding == 2 ? 'quoted-printable' : NULL,
|
||||
'', RCUBE_CHARSET
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// choose transfer encoding for plain/text body
|
||||
if (preg_match('/[^\x00-\x7F]/', $MAIL_MIME->getTXTBody())) {
|
||||
$text_charset = $message_charset;
|
||||
$transfer_encoding = $RCMAIL->config->get('force_7bit') ? 'quoted-printable' : '8bit';
|
||||
}
|
||||
else {
|
||||
$text_charset = 'US-ASCII';
|
||||
$transfer_encoding = '7bit';
|
||||
}
|
||||
|
||||
if ($flowed) {
|
||||
$text_charset .= ";\r\n format=flowed";
|
||||
}
|
||||
|
||||
// compose PGP/Mime message
|
||||
if ($pgp_mime) {
|
||||
$MAIL_MIME->addAttachment(new Mail_mimePart('Version: 1', array(
|
||||
'content_type' => 'application/pgp-encrypted',
|
||||
'description' => 'PGP/MIME version identification',
|
||||
)));
|
||||
|
||||
$MAIL_MIME->addAttachment(new Mail_mimePart($pgp_mime, array(
|
||||
'content_type' => 'application/octet-stream',
|
||||
'filename' => 'encrypted.asc',
|
||||
'disposition' => 'inline',
|
||||
)));
|
||||
|
||||
$MAIL_MIME->setContentType('multipart/encrypted', array('protocol' => 'application/pgp-encrypted'));
|
||||
$MAIL_MIME->setParam('preamble', 'This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)');
|
||||
}
|
||||
|
||||
// encoding settings for mail composing
|
||||
$MAIL_MIME->setParam('text_encoding', $transfer_encoding);
|
||||
$MAIL_MIME->setParam('html_encoding', 'quoted-printable');
|
||||
$MAIL_MIME->setParam('head_encoding', 'quoted-printable');
|
||||
$MAIL_MIME->setParam('head_charset', $message_charset);
|
||||
$MAIL_MIME->setParam('html_charset', $message_charset);
|
||||
$MAIL_MIME->setParam('text_charset', $text_charset);
|
||||
|
||||
// pass headers to message object
|
||||
$MAIL_MIME->headers($headers);
|
||||
|
||||
// This hook allows to modify the message before send or save action
|
||||
$plugin = $RCMAIL->plugins->exec_hook('message_ready', array('message' => $MAIL_MIME));
|
||||
$MAIL_MIME = $plugin['message'];
|
||||
|
||||
// Begin SMTP Delivery Block
|
||||
if (!$savedraft && !$saveonly) {
|
||||
// Handle Delivery Status Notification request
|
||||
$smtp_opts['dsn'] = $dsn_enabled;
|
||||
|
||||
$sent = $RCMAIL->deliver_message($MAIL_MIME, $from, $mailto,
|
||||
$smtp_error, $mailbody_file, $smtp_opts, true);
|
||||
|
||||
// return to compose page if sending failed
|
||||
if (!$sent) {
|
||||
// remove temp file
|
||||
if ($mailbody_file) {
|
||||
unlink($mailbody_file);
|
||||
}
|
||||
|
||||
if ($smtp_error && is_string($smtp_error)) {
|
||||
$OUTPUT->show_message($smtp_error, 'error');
|
||||
}
|
||||
else if ($smtp_error && !empty($smtp_error['label'])) {
|
||||
$OUTPUT->show_message($smtp_error['label'], 'error', $smtp_error['vars']);
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message('sendingfailed', 'error');
|
||||
}
|
||||
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
|
||||
// save message sent time
|
||||
if ($sendmail_delay) {
|
||||
$RCMAIL->user->save_prefs(array('last_message_time' => time()));
|
||||
}
|
||||
|
||||
// set replied/forwarded flag
|
||||
if ($COMPOSE['reply_uid']) {
|
||||
foreach (rcmail::get_uids($COMPOSE['reply_uid'], $COMPOSE['mailbox']) as $mbox => $uids) {
|
||||
// skip <UID>.<PART> replies
|
||||
if (!preg_match('/^\d+\.[0-9.]+$/', implode(',', (array) $uids))) {
|
||||
$RCMAIL->storage->set_flag($uids, 'ANSWERED', $mbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($COMPOSE['forward_uid']) {
|
||||
foreach (rcmail::get_uids($COMPOSE['forward_uid'], $COMPOSE['mailbox']) as $mbox => $uids) {
|
||||
// skip <UID>.<PART> forwards
|
||||
if (!preg_match('/^\d+\.[0-9.]+$/', implode(',', (array) $uids))) {
|
||||
$RCMAIL->storage->set_flag($uids, 'FORWARDED', $mbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine which folder to save message
|
||||
if ($savedraft) {
|
||||
$store_target = $drafts_mbox;
|
||||
}
|
||||
else if (!$RCMAIL->config->get('no_save_sent_messages')) {
|
||||
if (isset($_POST['_store_target'])) {
|
||||
$store_target = rcube_utils::get_input_value('_store_target', rcube_utils::INPUT_POST);
|
||||
}
|
||||
else {
|
||||
$store_target = $RCMAIL->config->get('sent_mbox');
|
||||
}
|
||||
}
|
||||
|
||||
if ($store_target) {
|
||||
// check if folder is subscribed
|
||||
if ($RCMAIL->storage->folder_exists($store_target, true)) {
|
||||
$store_folder = true;
|
||||
}
|
||||
// folder may be existing but not subscribed (#1485241)
|
||||
else if (!$RCMAIL->storage->folder_exists($store_target)) {
|
||||
$store_folder = $RCMAIL->storage->create_folder($store_target, true);
|
||||
}
|
||||
else if ($RCMAIL->storage->subscribe($store_target)) {
|
||||
$store_folder = true;
|
||||
}
|
||||
|
||||
// append message to sent box
|
||||
if ($store_folder) {
|
||||
// message body in file
|
||||
if ($mailbody_file || $MAIL_MIME->getParam('delay_file_io')) {
|
||||
$headers = $MAIL_MIME->txtHeaders();
|
||||
|
||||
// file already created
|
||||
if ($mailbody_file) {
|
||||
$msg = $mailbody_file;
|
||||
}
|
||||
else {
|
||||
$temp_dir = $RCMAIL->config->get('temp_dir');
|
||||
$mailbody_file = tempnam($temp_dir, 'rcmMsg');
|
||||
$msg = $MAIL_MIME->saveMessageBody($mailbody_file);
|
||||
|
||||
if (!is_a($msg, 'PEAR_Error')) {
|
||||
$msg = $mailbody_file;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$msg = $MAIL_MIME->getMessage();
|
||||
$headers = '';
|
||||
}
|
||||
|
||||
if (is_a($msg, 'PEAR_Error')) {
|
||||
rcube::raise_error(array('code' => 650, 'type' => 'php',
|
||||
'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Could not create message: ".$msg->getMessage()),
|
||||
true, false);
|
||||
}
|
||||
else {
|
||||
$saved = $RCMAIL->storage->save_message($store_target, $msg, $headers,
|
||||
$mailbody_file ? true : false, array('SEEN'));
|
||||
}
|
||||
|
||||
if ($mailbody_file) {
|
||||
unlink($mailbody_file);
|
||||
$mailbody_file = null;
|
||||
}
|
||||
}
|
||||
|
||||
// raise error if saving failed
|
||||
if (!$saved) {
|
||||
rcube::raise_error(array('code' => 800, 'type' => 'imap',
|
||||
'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Could not save message in $store_target"), true, false);
|
||||
|
||||
if ($savedraft) {
|
||||
$RCMAIL->display_server_error('errorsaving');
|
||||
|
||||
// start the auto-save timer again
|
||||
$OUTPUT->command('auto_save_start');
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove temp file
|
||||
else if ($mailbody_file) {
|
||||
unlink($mailbody_file);
|
||||
}
|
||||
|
||||
// delete previous saved draft
|
||||
$old_id = rcube_utils::get_input_value('_draft_saveid', rcube_utils::INPUT_POST);
|
||||
if ($old_id && ($sent || $saved)) {
|
||||
$deleted = $RCMAIL->storage->delete_message($old_id, $drafts_mbox);
|
||||
|
||||
// raise error if deletion of old draft failed
|
||||
if (!$deleted) {
|
||||
rcube::raise_error(array('code' => 800, 'type' => 'imap',
|
||||
'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Could not delete message from $drafts_mbox"), true, false);
|
||||
}
|
||||
}
|
||||
|
||||
if ($savedraft) {
|
||||
// remember new draft-uid ($saved could be an UID or true/false here)
|
||||
if ($saved && is_bool($saved)) {
|
||||
$index = $RCMAIL->storage->search_once($drafts_mbox, 'HEADER Message-ID ' . $message_id);
|
||||
$saved = @max($index->get());
|
||||
}
|
||||
|
||||
if ($saved) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('message_draftsaved',
|
||||
array('msgid' => $message_id, 'uid' => $saved, 'folder' => $store_target));
|
||||
|
||||
// display success
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'messagesaved', 'confirmation');
|
||||
|
||||
// update "_draft_saveid" and the "cmp_hash" to prevent "Unsaved changes" warning
|
||||
$COMPOSE['param']['draft_uid'] = $plugin['uid'];
|
||||
$OUTPUT->command('set_draft_id', $plugin['uid']);
|
||||
$OUTPUT->command('compose_field_hash', true);
|
||||
}
|
||||
|
||||
// start the auto-save timer again
|
||||
$OUTPUT->command('auto_save_start');
|
||||
}
|
||||
else {
|
||||
// Collect folders which could contain the composed message,
|
||||
// we'll refresh the list if currently opened folder is one of them (#1490238)
|
||||
$folders = array();
|
||||
|
||||
if (!$saveonly) {
|
||||
if (in_array($COMPOSE['mode'], array('reply', 'forward', 'draft'))) {
|
||||
$folders[] = $COMPOSE['mailbox'];
|
||||
}
|
||||
if (!empty($COMPOSE['param']['draft_uid']) && $drafts_mbox) {
|
||||
$folders[] = $drafts_mbox;
|
||||
}
|
||||
}
|
||||
|
||||
if ($store_folder && !$saved) {
|
||||
$params = $saveonly ? null : array('prefix' => true);
|
||||
$RCMAIL->display_server_error('errorsavingsent', null, null, $params);
|
||||
if ($saveonly) {
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
|
||||
$save_error = true;
|
||||
}
|
||||
else {
|
||||
rcmail_compose_cleanup($COMPOSE_ID);
|
||||
$OUTPUT->command('remove_compose_data', $COMPOSE_ID);
|
||||
|
||||
if ($store_folder) {
|
||||
$folders[] = $store_target;
|
||||
}
|
||||
}
|
||||
|
||||
$msg = $RCMAIL->gettext($saveonly ? 'successfullysaved' : 'messagesent');
|
||||
|
||||
$OUTPUT->command('sent_successfully', 'confirmation', $msg, $folders, $save_error);
|
||||
}
|
||||
|
||||
$OUTPUT->send('iframe');
|
||||
|
||||
|
||||
/****** message sending functions ********/
|
||||
|
||||
function rcmail_received_host($host)
|
||||
{
|
||||
$hostname = gethostbyaddr($host);
|
||||
|
||||
$result = rcmail_encrypt_host($hostname);
|
||||
|
||||
if ($host != $hostname) {
|
||||
$result .= ' (' . rcmail_encrypt_host($host) . ')';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
// encrypt host IP or hostname for Received header
|
||||
function rcmail_encrypt_host($host)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
if ($RCMAIL->config->get('http_received_header_encrypt')) {
|
||||
return $RCMAIL->encrypt($host);
|
||||
}
|
||||
|
||||
if (!preg_match('/[^0-9:.]/', $host)) {
|
||||
return "[$host]";
|
||||
}
|
||||
|
||||
return $host;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract image attachments from HTML content (data URIs)
|
||||
*/
|
||||
function rcmail_extract_inline_images($mime_message, $from)
|
||||
{
|
||||
$body = $mime_message->getHTMLBody();
|
||||
$offset = 0;
|
||||
$list = array();
|
||||
$domain = 'localhost';
|
||||
$regexp = '#img[^>]+src=[\'"](data:([^;]*);base64,([a-z0-9+/=\r\n]+))([\'"])#i';
|
||||
|
||||
if (preg_match_all($regexp, $body, $matches, PREG_OFFSET_CAPTURE)) {
|
||||
// get domain for the Content-ID, must be the same as in Mail_Mime::get()
|
||||
if (preg_match('#@([0-9a-zA-Z\-\.]+)#', $from, $m)) {
|
||||
$domain = $m[1];
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
if (empty($mime_type)) {
|
||||
$mime_type = rcube_mime::image_content_type($data);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
$t2h = new rcube_text2html($footer, false);
|
||||
$footer = $t2h->get_html();
|
||||
}
|
||||
return $footer;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* clear message composing settings
|
||||
*/
|
||||
function rcmail_compose_cleanup($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);
|
||||
|
||||
$_SESSION['last_compose_session'] = $id;
|
||||
}
|
43
data/web/rc/program/steps/mail/sendmdn.inc
Normal file
43
data/web/rc/program/steps/mail/sendmdn.inc
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/sendmdn.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2008-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: |
|
||||
| Send a message disposition notification for a specific mail |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// only process ajax requests
|
||||
if (!$OUTPUT->ajax_call) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($_POST['_uid'])) {
|
||||
$sent = rcmail_send_mdn(rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST), $smtp_error);
|
||||
}
|
||||
|
||||
// show either confirm or error message
|
||||
if ($sent) {
|
||||
$OUTPUT->set_env('mdn_request', false);
|
||||
$OUTPUT->show_message('receiptsent', 'confirmation');
|
||||
}
|
||||
else if ($smtp_error) {
|
||||
$OUTPUT->show_message($smtp_error['label'], 'error', $smtp_error['vars']);
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message('errorsendingreceipt', 'error');
|
||||
}
|
||||
|
||||
$OUTPUT->send();
|
346
data/web/rc/program/steps/mail/show.inc
Normal file
346
data/web/rc/program/steps/mail/show.inc
Normal file
@@ -0,0 +1,346 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/show.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Display a mail message similar as a usual mail application does |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$PRINT_MODE = $RCMAIL->action == 'print';
|
||||
|
||||
// Read browser capabilities and store them in session
|
||||
if ($caps = rcube_utils::get_input_value('_caps', rcube_utils::INPUT_GET)) {
|
||||
$browser_caps = array();
|
||||
foreach (explode(',', $caps) as $cap) {
|
||||
$cap = explode('=', $cap);
|
||||
$browser_caps[$cap[0]] = $cap[1];
|
||||
}
|
||||
$_SESSION['browser_caps'] = $browser_caps;
|
||||
}
|
||||
|
||||
$msg_id = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_GET);
|
||||
$uid = preg_replace('/\.[0-9.]+$/', '', $msg_id);
|
||||
$mbox_name = $RCMAIL->storage->get_folder();
|
||||
|
||||
// similar code as in program/steps/mail/get.inc
|
||||
if ($uid) {
|
||||
// set message format (need to be done before rcube_message construction)
|
||||
if (!empty($_GET['_format'])) {
|
||||
$prefer_html = $_GET['_format'] == 'html';
|
||||
$RCMAIL->config->set('prefer_html', $prefer_html);
|
||||
$_SESSION['msg_formats'][$mbox_name.':'.$uid] = $prefer_html;
|
||||
}
|
||||
else if (isset($_SESSION['msg_formats'][$mbox_name.':'.$uid])) {
|
||||
$RCMAIL->config->set('prefer_html', $_SESSION['msg_formats'][$mbox_name.':'.$uid]);
|
||||
}
|
||||
|
||||
$MESSAGE = new rcube_message($msg_id, $mbox_name, intval($_GET['_safe']));
|
||||
|
||||
// if message not found (wrong UID)...
|
||||
if (empty($MESSAGE->headers)) {
|
||||
rcmail_message_error($uid);
|
||||
}
|
||||
|
||||
// show images?
|
||||
rcmail_check_safe($MESSAGE);
|
||||
|
||||
// set message charset as default
|
||||
if (!empty($MESSAGE->headers->charset)) {
|
||||
$RCMAIL->storage->set_charset($MESSAGE->headers->charset);
|
||||
}
|
||||
|
||||
$OUTPUT->set_pagetitle(abbreviate_string($MESSAGE->subject, 128, '...', true));
|
||||
|
||||
// set message environment
|
||||
$OUTPUT->set_env('uid', $msg_id);
|
||||
$OUTPUT->set_env('safemode', $MESSAGE->is_safe);
|
||||
$OUTPUT->set_env('message_context', $MESSAGE->context);
|
||||
$OUTPUT->set_env('sender', $MESSAGE->sender['string']);
|
||||
$OUTPUT->set_env('mailbox', $mbox_name);
|
||||
$OUTPUT->set_env('username', $RCMAIL->get_user_name());
|
||||
$OUTPUT->set_env('permaurl', $RCMAIL->url(array('_action' => 'show', '_uid' => $msg_id, '_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());
|
||||
$OUTPUT->set_env('mimetypes', rcmail_supported_mimetypes());
|
||||
|
||||
// set configuration
|
||||
$RCMAIL->set_env_config(array('delete_junk', 'flag_for_deletion', 'read_when_deleted',
|
||||
'skip_deleted', 'display_next', '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);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
$OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash',
|
||||
'movingmessage', 'deletingmessage', 'markingmessage', 'replyall', 'replylist');
|
||||
}
|
||||
|
||||
// check for unset disposition notification
|
||||
if ($MESSAGE->headers->mdn_to
|
||||
&& $MESSAGE->context === null
|
||||
&& empty($MESSAGE->headers->flags['MDNSENT'])
|
||||
&& empty($MESSAGE->headers->flags['SEEN'])
|
||||
&& ($RCMAIL->storage->check_permflag('MDNSENT') || $RCMAIL->storage->check_permflag('*'))
|
||||
&& $mbox_name != $RCMAIL->config->get('drafts_mbox')
|
||||
&& $mbox_name != $RCMAIL->config->get('sent_mbox')
|
||||
) {
|
||||
$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
|
||||
if (rcmail_send_mdn($MESSAGE, $smtp_error))
|
||||
$OUTPUT->show_message('receiptsent', 'confirmation');
|
||||
else if ($smtp_error)
|
||||
$OUTPUT->show_message($smtp_error['label'], 'error', $smtp_error['vars']);
|
||||
else
|
||||
$OUTPUT->show_message('errorsendingreceipt', 'error');
|
||||
}
|
||||
else if ($mdn_cfg != 2 && $mdn_cfg != 4) {
|
||||
// Ask user
|
||||
$OUTPUT->add_label('mdnrequest');
|
||||
$OUTPUT->set_env('mdn_request', true);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($MESSAGE->headers->flags['SEEN']) && $MESSAGE->context === null) {
|
||||
$v = intval($RCMAIL->config->get('mail_read_time'));
|
||||
if ($v > 0) {
|
||||
$OUTPUT->set_env('mail_read_time', $v);
|
||||
}
|
||||
else if ($v == 0) {
|
||||
$RCMAIL->output->command('set_unread_message', $MESSAGE->uid, $mbox_name);
|
||||
$RCMAIL->plugins->exec_hook('message_read', array(
|
||||
'uid' => $MESSAGE->uid,
|
||||
'mailbox' => $mbox_name,
|
||||
'message' => $MESSAGE,
|
||||
));
|
||||
|
||||
$set_seen_flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$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 (!empty($set_seen_flag)) {
|
||||
if ($RCMAIL->storage->set_flag($MESSAGE->uid, 'SEEN', $mbox_name)) {
|
||||
if ($count = rcmail_get_unseen_count($mbox_name)) {
|
||||
rcmail_set_unseen_count($mbox_name, $count - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit;
|
||||
|
||||
|
||||
function rcmail_message_attachments($attrib)
|
||||
{
|
||||
global $PRINT_MODE, $MESSAGE, $RCMAIL;
|
||||
|
||||
$out = $ol = '';
|
||||
$attachments = array();
|
||||
|
||||
if (sizeof($MESSAGE->attachments)) {
|
||||
foreach ($MESSAGE->attachments as $attach_prop) {
|
||||
$filename = rcmail_attachment_name($attach_prop, true);
|
||||
$filesize = $RCMAIL->message_part_size($attach_prop);
|
||||
|
||||
if ($PRINT_MODE) {
|
||||
$ol .= html::tag('li', array('id' => 'attach' . $attach_prop->mime_id),
|
||||
rcube::Q(sprintf("%s (%s)", $filename, $filesize)));
|
||||
}
|
||||
else {
|
||||
if ($attrib['maxlength'] && mb_strlen($filename) > $attrib['maxlength']) {
|
||||
$title = $filename;
|
||||
$filename = abbreviate_string($filename, $attrib['maxlength']);
|
||||
}
|
||||
else {
|
||||
$title = '';
|
||||
}
|
||||
|
||||
$size = ' ' . html::span('attachment-size', '(' . rcube::Q($filesize) . ')');
|
||||
$mimetype = rcmail_fix_mimetype($attach_prop->mimetype);
|
||||
$class = rcube_utils::file2class($mimetype, $filename);
|
||||
$id = 'attach' . $attach_prop->mime_id;
|
||||
$link = html::a(array(
|
||||
'href' => $MESSAGE->get_part_url($attach_prop->mime_id, false),
|
||||
'onclick' => sprintf('return %s.command(\'load-attachment\',\'%s\',this)',
|
||||
rcmail_output::JS_OBJECT_NAME, $attach_prop->mime_id),
|
||||
'onmouseover' => $title ? '' : 'rcube_webmail.long_subject_title_ex(this, 0)',
|
||||
'title' => $title,
|
||||
), rcube::Q($filename) . $size);
|
||||
|
||||
$ol .= html::tag('li', array('class' => $class, 'id' => $id), $link);
|
||||
|
||||
$attachments[$attach_prop->mime_id] = $mimetype;
|
||||
}
|
||||
}
|
||||
|
||||
$out = html::tag('ul', $attrib, $ol, html::$common_attrib);
|
||||
|
||||
$RCMAIL->output->set_env('attachments', $attachments);
|
||||
$RCMAIL->output->add_gui_object('attachments', $attrib['id']);
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
function rcmail_remote_objects_msg()
|
||||
{
|
||||
global $MESSAGE, $RCMAIL;
|
||||
|
||||
$attrib['id'] = 'remote-objects-message';
|
||||
$attrib['class'] = 'notice';
|
||||
$attrib['style'] = 'display: none';
|
||||
|
||||
$msg = rcube::Q($RCMAIL->gettext('blockedimages')) . ' ';
|
||||
$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"
|
||||
),
|
||||
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);
|
||||
}
|
||||
|
||||
function rcmail_message_buttons()
|
||||
{
|
||||
global $RCMAIL, $MESSAGE;
|
||||
|
||||
$delim = $RCMAIL->storage->get_hierarchy_delimiter();
|
||||
$dbox = $RCMAIL->config->get('drafts_mbox');
|
||||
|
||||
// the message is not a draft
|
||||
if ($MESSAGE->folder != $dbox && strpos($MESSAGE->folder, $dbox.$delim) !== 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$attrib['id'] = 'message-buttons';
|
||||
$attrib['class'] = 'notice';
|
||||
|
||||
$msg = rcube::Q($RCMAIL->gettext('isdraft')) . ' ';
|
||||
$msg .= html::a(array(
|
||||
'href' => "#edit",
|
||||
'onclick' => rcmail_output::JS_OBJECT_NAME.".command('edit')"
|
||||
),
|
||||
rcube::Q($RCMAIL->gettext('edit')));
|
||||
|
||||
return html::div($attrib, $msg);
|
||||
}
|
||||
|
||||
function rcmail_message_objects($attrib)
|
||||
{
|
||||
global $RCMAIL, $MESSAGE;
|
||||
|
||||
if (!$attrib['id'])
|
||||
$attrib['id'] = 'message-objects';
|
||||
|
||||
$content = array(
|
||||
rcmail_message_buttons(),
|
||||
rcmail_remote_objects_msg(),
|
||||
);
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('message_objects',
|
||||
array('content' => $content, 'message' => $MESSAGE));
|
||||
|
||||
$content = implode("\n", $plugin['content']);
|
||||
|
||||
return html::div($attrib, $content);
|
||||
}
|
||||
|
||||
function rcmail_contact_exists($email)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
if ($email) {
|
||||
// @TODO: search in all address books?
|
||||
$CONTACTS = $RCMAIL->get_address_book(-1, true);
|
||||
|
||||
if (is_object($CONTACTS)) {
|
||||
$existing = $CONTACTS->search('email', $email, 1, false);
|
||||
if ($existing->count) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function rcmail_message_contactphoto($attrib)
|
||||
{
|
||||
global $RCMAIL, $MESSAGE;
|
||||
|
||||
$placeholder = $attrib['placeholder'] ? $RCMAIL->output->abs_url($attrib['placeholder'], true) : null;
|
||||
$placeholder = $RCMAIL->output->asset_url($placeholder ?: 'program/resources/blank.gif');
|
||||
|
||||
if ($MESSAGE->sender) {
|
||||
$photo_img = $RCMAIL->url(array(
|
||||
'_task' => 'addressbook',
|
||||
'_action' => 'photo',
|
||||
'_email' => $MESSAGE->sender['mailto'],
|
||||
));
|
||||
|
||||
$attrib['onerror'] = "this.src = '$placeholder'";
|
||||
}
|
||||
else {
|
||||
$photo_img = $placeholder;
|
||||
}
|
||||
|
||||
return html::img(array('src' => $photo_img, 'alt' => $RCMAIL->gettext('contactphoto')) + $attrib);
|
||||
}
|
83
data/web/rc/program/steps/mail/viewsource.inc
Normal file
83
data/web/rc/program/steps/mail/viewsource.inc
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/mail/viewsource.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2016, 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: |
|
||||
| Display a mail message similar as a usual mail application does |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
if (!empty($_GET['_save'])) {
|
||||
$RCMAIL->request_security_check(rcube_utils::INPUT_GET);
|
||||
}
|
||||
|
||||
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 ($pos = strpos($uid, '.')) {
|
||||
$message = new rcube_message($uid);
|
||||
$headers = $message->headers;
|
||||
$part_id = substr($uid, $pos + 1);
|
||||
}
|
||||
else {
|
||||
$headers = $RCMAIL->storage->get_message_headers($uid);
|
||||
}
|
||||
|
||||
$charset = $headers->charset ?: $RCMAIL->config->get('default_charset');
|
||||
|
||||
header("Content-Type: text/plain; charset={$charset}");
|
||||
|
||||
if (!empty($_GET['_save'])) {
|
||||
$browser = $RCMAIL->output->browser;
|
||||
$subject = rcube_mime::decode_header($headers->subject, $headers->charset);
|
||||
$filename = rcmail_filename_from_subject(mb_substr($subject, 0, 128));
|
||||
$filename = ($filename ?: $uid) . '.eml';
|
||||
$filename = $browser->ie ? rawurlencode($filename) : addcslashes($filename, '"');
|
||||
|
||||
header("Content-Length: {$headers->size}");
|
||||
header("Content-Disposition: attachment; filename=\"$filename\"");
|
||||
}
|
||||
|
||||
if (isset($message)) {
|
||||
$message->get_part_body($part_id, empty($_GET['_save']), 0, -1);
|
||||
}
|
||||
else {
|
||||
$RCMAIL->storage->print_raw_body($uid, empty($_GET['_save']));
|
||||
}
|
||||
}
|
||||
else {
|
||||
rcube::raise_error(array(
|
||||
'code' => 500,
|
||||
'type' => 'php',
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Message UID $uid not found"
|
||||
),
|
||||
true, true);
|
||||
}
|
||||
|
||||
exit;
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to convert message subject into filename
|
||||
*/
|
||||
function rcmail_filename_from_subject($str)
|
||||
{
|
||||
$str = preg_replace('/[:\t\n\r\0\x0B\/]+\s*/', ' ', $str);
|
||||
|
||||
return trim($str, " \t\n\r\0\x0B./_");
|
||||
}
|
103
data/web/rc/program/steps/settings/about.inc
Normal file
103
data/web/rc/program/steps/settings/about.inc
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/settings/about.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| 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. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Display license information about program and enabled plugins |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
|
||||
$OUTPUT->set_pagetitle($RCMAIL->gettext('about'));
|
||||
|
||||
$OUTPUT->add_handler('supportlink', 'rcmail_supportlink');
|
||||
$OUTPUT->add_handler('pluginlist', 'rcmail_plugins_list');
|
||||
|
||||
$OUTPUT->send('about');
|
||||
|
||||
|
||||
|
||||
function rcmail_supportlink($attrib)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
if ($url = $RCMAIL->config->get('support_url')) {
|
||||
$label = $attrib['label'] ?: 'support';
|
||||
$attrib['href'] = $url;
|
||||
|
||||
return html::a($attrib, $RCMAIL->gettext($label));
|
||||
}
|
||||
}
|
||||
|
||||
function rcmail_plugins_list($attrib)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
if (!$attrib['id']) {
|
||||
$attrib['id'] = 'rcmpluginlist';
|
||||
}
|
||||
|
||||
$plugins = array_filter($RCMAIL->plugins->active_plugins);
|
||||
$plugin_info = array();
|
||||
|
||||
foreach ($plugins as $name) {
|
||||
if ($info = $RCMAIL->plugins->get_info($name)) {
|
||||
$plugin_info[$name] = $info;
|
||||
}
|
||||
}
|
||||
|
||||
// load info from required plugins, too
|
||||
foreach ($plugin_info as $name => $info) {
|
||||
if (is_array($info['require']) && !empty($info['require'])) {
|
||||
foreach ($info['require'] as $req_name) {
|
||||
if (!isset($plugin_info[$req_name]) && ($req_info = $RCMAIL->plugins->get_info($req_name))) {
|
||||
$plugin_info[$req_name] = $req_info;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($plugin_info)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
ksort($plugin_info, SORT_LOCALE_STRING);
|
||||
|
||||
$table = new html_table($attrib);
|
||||
|
||||
// add table header
|
||||
$table->add_header('name', $RCMAIL->gettext('plugin'));
|
||||
$table->add_header('version', $RCMAIL->gettext('version'));
|
||||
$table->add_header('license', $RCMAIL->gettext('license'));
|
||||
$table->add_header('source', $RCMAIL->gettext('source'));
|
||||
|
||||
foreach ($plugin_info as $name => $data) {
|
||||
$uri = $data['src_uri'] ?: $data['uri'];
|
||||
if ($uri && stripos($uri, 'http') !== 0) {
|
||||
$uri = 'http://' . $uri;
|
||||
}
|
||||
|
||||
$table->add_row();
|
||||
$table->add('name', rcube::Q($data['name'] ?: $name));
|
||||
$table->add('version', rcube::Q($data['version']));
|
||||
$table->add('license', $data['license_uri'] ? html::a(array('target' => '_blank', href=> rcube::Q($data['license_uri'])),
|
||||
rcube::Q($data['license'])) : $data['license']);
|
||||
$table->add('source', $uri ? html::a(array('target' => '_blank', href=> rcube::Q($uri)),
|
||||
rcube::Q($RCMAIL->gettext('download'))) : '');
|
||||
}
|
||||
|
||||
return $table->show();
|
||||
}
|
321
data/web/rc/program/steps/settings/edit_folder.inc
Normal file
321
data/web/rc/program/steps/settings/edit_folder.inc
Normal file
@@ -0,0 +1,321 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/settings/edit_folder.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Provide functionality to create/edit a folder |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// register UI objects
|
||||
$OUTPUT->add_handlers(array(
|
||||
'folderdetails' => 'rcmail_folder_form',
|
||||
));
|
||||
|
||||
$OUTPUT->add_label('nonamewarning');
|
||||
|
||||
$OUTPUT->send('folderedit');
|
||||
|
||||
|
||||
// WARNING: folder names in UI are encoded with RCUBE_CHARSET
|
||||
|
||||
function rcmail_folder_form($attrib)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
$storage = $RCMAIL->get_storage();
|
||||
|
||||
// edited folder name (empty in create-folder mode)
|
||||
$mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true);
|
||||
|
||||
// predefined path for new folder
|
||||
$parent = rcube_utils::get_input_value('_path', rcube_utils::INPUT_GPC, true);
|
||||
|
||||
$threading_supported = $storage->get_capability('THREAD');
|
||||
$delimiter = $storage->get_hierarchy_delimiter();
|
||||
|
||||
// Get mailbox parameters
|
||||
if (strlen($mbox)) {
|
||||
$options = rcmail_folder_options($mbox);
|
||||
$namespace = $storage->get_namespace();
|
||||
|
||||
$path = explode($delimiter, $mbox);
|
||||
$folder = array_pop($path);
|
||||
$path = implode($delimiter, $path);
|
||||
$folder = rcube_charset::convert($folder, 'UTF7-IMAP');
|
||||
|
||||
$hidden_fields = array('name' => '_mbox', 'value' => $mbox);
|
||||
}
|
||||
else {
|
||||
$options = array();
|
||||
$path = $parent;
|
||||
|
||||
// allow creating subfolders of INBOX folder
|
||||
if ($path == 'INBOX') {
|
||||
$path = $storage->mod_folder($path, 'in');
|
||||
}
|
||||
}
|
||||
|
||||
// remove personal namespace prefix
|
||||
if (strlen($path)) {
|
||||
$path_id = $path;
|
||||
$path = $storage->mod_folder($path.$delimiter);
|
||||
if ($path[strlen($path)-1] == $delimiter) {
|
||||
$path = substr($path, 0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
$form = array();
|
||||
|
||||
// General tab
|
||||
$form['props'] = array(
|
||||
'name' => $RCMAIL->gettext('properties'),
|
||||
);
|
||||
|
||||
// Location (name)
|
||||
if ($options['protected']) {
|
||||
$foldername = str_replace($delimiter, ' » ', rcube::Q($RCMAIL->localize_folderpath($mbox)));
|
||||
}
|
||||
else if ($options['norename']) {
|
||||
$foldername = rcube::Q($folder);
|
||||
}
|
||||
else {
|
||||
if (isset($_POST['_name']))
|
||||
$folder = trim(rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true));
|
||||
|
||||
$foldername = new html_inputfield(array('name' => '_name', 'id' => '_name', 'size' => 30));
|
||||
$foldername = $foldername->show($folder);
|
||||
|
||||
if ($options['special']) {
|
||||
$foldername .= ' (' . rcube::Q($RCMAIL->localize_foldername($mbox)) .')';
|
||||
}
|
||||
}
|
||||
|
||||
$form['props']['fieldsets']['location'] = array(
|
||||
'name' => $RCMAIL->gettext('location'),
|
||||
'content' => array(
|
||||
'name' => array(
|
||||
'label' => $RCMAIL->gettext('foldername'),
|
||||
'value' => $foldername,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (!empty($options) && ($options['norename'] || $options['protected'])) {
|
||||
// prevent user from moving folder
|
||||
$hidden_path = new html_hiddenfield(array('name' => '_parent', 'value' => $path));
|
||||
$form['props']['fieldsets']['location']['content']['name']['value'] .= $hidden_path->show();
|
||||
}
|
||||
else {
|
||||
$selected = isset($_POST['_parent']) ? $_POST['_parent'] : $path_id;
|
||||
$exceptions = array($mbox);
|
||||
|
||||
// Exclude 'prefix' namespace from parent folders list (#1488349)
|
||||
// If INBOX. namespace exists, folders created as INBOX subfolders
|
||||
// will be listed at the same level - selecting INBOX as a parent does nothing
|
||||
if ($prefix = $storage->get_namespace('prefix')) {
|
||||
$exceptions[] = substr($prefix, 0, -1);
|
||||
}
|
||||
|
||||
$select = $RCMAIL->folder_selector(array(
|
||||
'id' => '_parent',
|
||||
'name' => '_parent',
|
||||
'noselection' => '---',
|
||||
'maxlength' => 150,
|
||||
'unsubscribed' => true,
|
||||
'skip_noinferiors' => true,
|
||||
'exceptions' => $exceptions,
|
||||
'additional' => strlen($selected) ? array($selected) : null,
|
||||
));
|
||||
|
||||
$form['props']['fieldsets']['location']['content']['path'] = array(
|
||||
'label' => $RCMAIL->gettext('parentfolder'),
|
||||
'value' => $select->show($selected),
|
||||
);
|
||||
}
|
||||
|
||||
// Settings
|
||||
$form['props']['fieldsets']['settings'] = array(
|
||||
'name' => $RCMAIL->gettext('settings'),
|
||||
);
|
||||
|
||||
// Settings: threading
|
||||
if ($threading_supported && ($mbox == 'INBOX' || (!$options['noselect'] && !$options['is_root']))) {
|
||||
$select = new html_select(array('name' => '_viewmode', 'id' => '_viewmode'));
|
||||
$select->add($RCMAIL->gettext('list'), 0);
|
||||
$select->add($RCMAIL->gettext('threads'), 1);
|
||||
|
||||
if (isset($_POST['_viewmode'])) {
|
||||
$value = (int) $_POST['_viewmode'];
|
||||
}
|
||||
else if (strlen($mbox)) {
|
||||
$a_threaded = $RCMAIL->config->get('message_threading', array());
|
||||
$default_mode = $RCMAIL->config->get('default_list_mode', 'list');
|
||||
|
||||
$value = (int) (isset($a_threaded[$mbox]) ? $a_threaded[$mbox] : $default_mode == 'threads');
|
||||
}
|
||||
|
||||
$form['props']['fieldsets']['settings']['content']['viewmode'] = array(
|
||||
'label' => $RCMAIL->gettext('listmode'),
|
||||
'value' => $select->show($value),
|
||||
);
|
||||
}
|
||||
/*
|
||||
// Settings: sorting column
|
||||
$select = new html_select(array('name' => '_sortcol', 'id' => '_sortcol'));
|
||||
$select->add($RCMAIL->gettext('nonesort'), '');
|
||||
$select->add($RCMAIL->gettext('arrival'), 'arrival');
|
||||
$select->add($RCMAIL->gettext('sentdate'), 'date');
|
||||
$select->add($RCMAIL->gettext('subject'), 'subject');
|
||||
$select->add($RCMAIL->gettext('fromto'), 'from');
|
||||
$select->add($RCMAIL->gettext('replyto'), 'replyto');
|
||||
$select->add($RCMAIL->gettext('cc'), 'cc');
|
||||
$select->add($RCMAIL->gettext('size'), 'size');
|
||||
|
||||
$value = isset($_POST['_sortcol']) ? $_POST['_sortcol'] : '';
|
||||
|
||||
$form['props']['fieldsets']['settings']['content']['sortcol'] = array(
|
||||
'label' => $RCMAIL->gettext('listsorting'),
|
||||
'value' => $select->show($value),
|
||||
);
|
||||
|
||||
// Settings: sorting order
|
||||
$select = new html_select(array('name' => '_sortord', 'id' => '_sortord'));
|
||||
$select->add($RCMAIL->gettext('asc'), 'ASC');
|
||||
$select->add($RCMAIL->gettext('desc'), 'DESC');
|
||||
|
||||
$value = isset($_POST['_sortord']) ? $_POST['_sortord'] : '';
|
||||
|
||||
$form['props']['fieldsets']['settings']['content']['sortord'] = array(
|
||||
'label' => $RCMAIL->gettext('listorder'),
|
||||
'value' => $select->show(),
|
||||
);
|
||||
*/
|
||||
// Information (count, size) - Edit mode
|
||||
if (strlen($mbox)) {
|
||||
// Number of messages
|
||||
$form['props']['fieldsets']['info'] = array(
|
||||
'name' => $RCMAIL->gettext('info'),
|
||||
'content' => array()
|
||||
);
|
||||
|
||||
if ((!$options['noselect'] && !$options['is_root']) || $mbox == 'INBOX') {
|
||||
$msgcount = $storage->count($mbox, 'ALL', true, false);
|
||||
|
||||
// Size
|
||||
if ($msgcount) {
|
||||
// create link with folder-size command
|
||||
$onclick = sprintf("return %s.command('folder-size', '%s', this)",
|
||||
rcmail_output::JS_OBJECT_NAME, rcube::JQ($mbox));
|
||||
$size = html::a(array('href' => '#', 'onclick' => $onclick,
|
||||
'id' => 'folder-size'), $RCMAIL->gettext('getfoldersize'));
|
||||
}
|
||||
else {
|
||||
// no messages -> zero size
|
||||
$size = 0;
|
||||
}
|
||||
|
||||
$form['props']['fieldsets']['info']['content']['count'] = array(
|
||||
'label' => $RCMAIL->gettext('messagecount'),
|
||||
'value' => (int) $msgcount
|
||||
);
|
||||
$form['props']['fieldsets']['info']['content']['size'] = array(
|
||||
'label' => $RCMAIL->gettext('size'),
|
||||
'value' => $size,
|
||||
);
|
||||
}
|
||||
|
||||
// show folder type only if we have non-private namespaces
|
||||
if (!empty($namespace['shared']) || !empty($namespace['others'])) {
|
||||
$form['props']['fieldsets']['info']['content']['foldertype'] = array(
|
||||
'label' => $RCMAIL->gettext('foldertype'),
|
||||
'value' => $RCMAIL->gettext($options['namespace'] . 'folder'));
|
||||
}
|
||||
}
|
||||
|
||||
// Allow plugins to modify folder form content
|
||||
$plugin = $RCMAIL->plugins->exec_hook('folder_form',
|
||||
array('form' => $form, 'options' => $options,
|
||||
'name' => $mbox, 'parent_name' => $parent));
|
||||
|
||||
$form = $plugin['form'];
|
||||
|
||||
// Set form tags and hidden fields
|
||||
list($form_start, $form_end) = get_form_tags($attrib, 'save-folder', null, $hidden_fields);
|
||||
|
||||
unset($attrib['form'], $attrib['id']);
|
||||
|
||||
// return the complete edit form as table
|
||||
$out = "$form_start\n";
|
||||
|
||||
// Create form output
|
||||
foreach ($form as $idx => $tab) {
|
||||
if (!empty($tab['fieldsets']) && is_array($tab['fieldsets'])) {
|
||||
$content = '';
|
||||
foreach ($tab['fieldsets'] as $fieldset) {
|
||||
$subcontent = rcmail_get_form_part($fieldset, $attrib);
|
||||
if ($subcontent) {
|
||||
$subcontent = html::tag('legend', null, rcube::Q($fieldset['name'])) . $subcontent;
|
||||
$content .= html::tag('fieldset', null, $subcontent) ."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$content = rcmail_get_form_part($tab, $attrib);
|
||||
}
|
||||
|
||||
if ($idx != 'props') {
|
||||
$out .= html::tag('fieldset', null, html::tag('legend', null, rcube::Q($tab['name'])) . $content) ."\n";
|
||||
}
|
||||
else {
|
||||
$out .= $content ."\n";
|
||||
}
|
||||
}
|
||||
|
||||
$out .= "\n$form_end";
|
||||
|
||||
$RCMAIL->output->set_env('messagecount', (int) $msgcount);
|
||||
$RCMAIL->output->set_env('folder', $mbox);
|
||||
|
||||
if ($mbox !== null && empty($_POST)) {
|
||||
$RCMAIL->output->command('parent.set_quota', $RCMAIL->quota_content(null, $mbox));
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
function rcmail_get_form_part($form, $attrib = array())
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
$content = '';
|
||||
|
||||
if (is_array($form['content']) && !empty($form['content'])) {
|
||||
$table = new html_table(array('cols' => 2));
|
||||
foreach ($form['content'] as $col => $colprop) {
|
||||
$colprop['id'] = '_'.$col;
|
||||
$label = $colprop['label'] ?: $RCMAIL->gettext($col);
|
||||
|
||||
$table->add('title', html::label($colprop['id'], rcube::Q($label)));
|
||||
$table->add(null, $colprop['value']);
|
||||
}
|
||||
$content = $table->show($attrib);
|
||||
}
|
||||
else {
|
||||
$content = $form['content'];
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
192
data/web/rc/program/steps/settings/edit_identity.inc
Normal file
192
data/web/rc/program/steps/settings/edit_identity.inc
Normal file
@@ -0,0 +1,192 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/settings/edit_identity.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Show edit form for a identity record or to add a new one |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
define('IDENTITIES_LEVEL', intval($RCMAIL->config->get('identities_level', 0)));
|
||||
|
||||
// edit-identity
|
||||
if (($_GET['_iid'] || $_POST['_iid']) && $RCMAIL->action=='edit-identity') {
|
||||
$id = rcube_utils::get_input_value('_iid', rcube_utils::INPUT_GPC);
|
||||
$IDENTITY_RECORD = $RCMAIL->user->get_identity($id);
|
||||
|
||||
if (is_array($IDENTITY_RECORD)) {
|
||||
$OUTPUT->set_env('iid', $IDENTITY_RECORD['identity_id']);
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message('dberror', 'error');
|
||||
// go to identities page
|
||||
$RCMAIL->overwrite_action('identities');
|
||||
return;
|
||||
}
|
||||
}
|
||||
// add-identity
|
||||
else {
|
||||
if (IDENTITIES_LEVEL > 1) {
|
||||
$OUTPUT->show_message('opnotpermitted', 'error');
|
||||
// go to identities page
|
||||
$RCMAIL->overwrite_action('identities');
|
||||
return;
|
||||
}
|
||||
else if (IDENTITIES_LEVEL == 1) {
|
||||
$IDENTITY_RECORD['email'] = $RCMAIL->get_user_email();
|
||||
}
|
||||
}
|
||||
|
||||
$OUTPUT->include_script('list.js');
|
||||
$OUTPUT->add_handler('identityform', 'rcube_identity_form');
|
||||
$OUTPUT->set_env('identities_level', IDENTITIES_LEVEL);
|
||||
$OUTPUT->add_label('deleteidentityconfirm', 'uploading');
|
||||
|
||||
$OUTPUT->set_pagetitle($RCMAIL->gettext(($RCMAIL->action == 'add-identity' ? 'addidentity' : 'editidentity')));
|
||||
|
||||
if ($RCMAIL->action == 'add-identity' && $OUTPUT->template_exists('identityadd')) {
|
||||
$OUTPUT->send('identityadd');
|
||||
}
|
||||
|
||||
$OUTPUT->send('identityedit');
|
||||
|
||||
|
||||
function rcube_identity_form($attrib)
|
||||
{
|
||||
global $IDENTITY_RECORD, $RCMAIL, $OUTPUT;
|
||||
|
||||
// Add HTML editor script(s)
|
||||
$RCMAIL->html_editor('identity');
|
||||
|
||||
// add some labels to client
|
||||
$OUTPUT->add_label('noemailwarning', 'converting', 'editorwarning');
|
||||
|
||||
$i_size = $attrib['size'] ?: 40;
|
||||
$t_rows = $attrib['textarearows'] ?: 6;
|
||||
$t_cols = $attrib['textareacols'] ?: 40;
|
||||
|
||||
// list of available cols
|
||||
$form = array(
|
||||
'addressing' => array(
|
||||
'name' => $RCMAIL->gettext('settings'),
|
||||
'content' => array(
|
||||
'name' => array('type' => 'text', 'size' => $i_size),
|
||||
'email' => array('type' => 'text', 'size' => $i_size),
|
||||
'organization' => array('type' => 'text', 'size' => $i_size),
|
||||
'reply-to' => array('type' => 'text', 'size' => $i_size),
|
||||
'bcc' => array('type' => 'text', 'size' => $i_size),
|
||||
'standard' => array('type' => 'checkbox', 'label' => $RCMAIL->gettext('setdefault')),
|
||||
)),
|
||||
'signature' => array(
|
||||
'name' => $RCMAIL->gettext('signature'),
|
||||
'content' => array(
|
||||
'signature' => array('type' => 'textarea', 'size' => $t_cols, 'rows' => $t_rows,
|
||||
'spellcheck' => true),
|
||||
'html_signature' => array('type' => 'checkbox',
|
||||
'label' => $RCMAIL->gettext('htmlsignature'),
|
||||
'onclick' => 'return rcmail.command(\'toggle-editor\', {id: \'rcmfd_signature\', html: this.checked}, \'\', event)'),
|
||||
))
|
||||
);
|
||||
|
||||
// Enable TinyMCE editor
|
||||
if ($IDENTITY_RECORD['html_signature']) {
|
||||
$form['signature']['content']['signature']['class'] = 'mce_editor';
|
||||
$form['signature']['content']['signature']['is_escaped'] = true;
|
||||
|
||||
// Correctly handle HTML entities in HTML editor (#1488483)
|
||||
$IDENTITY_RECORD['signature'] = htmlspecialchars($IDENTITY_RECORD['signature'], ENT_NOQUOTES, RCUBE_CHARSET);
|
||||
}
|
||||
|
||||
// hide "default" checkbox if only one identity is allowed
|
||||
if (IDENTITIES_LEVEL > 1) {
|
||||
unset($form['addressing']['content']['standard']);
|
||||
}
|
||||
|
||||
// disable some field according to access level
|
||||
if (IDENTITIES_LEVEL == 1 || IDENTITIES_LEVEL == 3) {
|
||||
$form['addressing']['content']['email']['disabled'] = true;
|
||||
$form['addressing']['content']['email']['class'] = 'disabled';
|
||||
}
|
||||
|
||||
if (IDENTITIES_LEVEL == 4) {
|
||||
foreach($form['addressing']['content'] as $formfield => $value){
|
||||
$form['addressing']['content'][$formfield]['disabled'] = true;
|
||||
$form['addressing']['content'][$formfield]['class'] = 'disabled';
|
||||
}
|
||||
}
|
||||
|
||||
$IDENTITY_RECORD['email'] = rcube_utils::idn_to_utf8($IDENTITY_RECORD['email']);
|
||||
|
||||
// Allow plugins to modify identity form content
|
||||
$plugin = $RCMAIL->plugins->exec_hook('identity_form', array(
|
||||
'form' => $form, 'record' => $IDENTITY_RECORD));
|
||||
|
||||
$form = $plugin['form'];
|
||||
$IDENTITY_RECORD = $plugin['record'];
|
||||
|
||||
// Set form tags and hidden fields
|
||||
list($form_start, $form_end) = get_form_tags($attrib, 'save-identity',
|
||||
intval($IDENTITY_RECORD['identity_id']),
|
||||
array('name' => '_iid', 'value' => $IDENTITY_RECORD['identity_id']));
|
||||
|
||||
unset($plugin);
|
||||
unset($attrib['form'], $attrib['id']);
|
||||
|
||||
// return the complete edit form as table
|
||||
$out = "$form_start\n";
|
||||
|
||||
foreach ($form as $fieldset) {
|
||||
if (empty($fieldset['content'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$content = '';
|
||||
if (is_array($fieldset['content'])) {
|
||||
$table = new html_table(array('cols' => 2));
|
||||
|
||||
foreach ($fieldset['content'] as $col => $colprop) {
|
||||
$colprop['id'] = 'rcmfd_'.$col;
|
||||
|
||||
$label = $colprop['label'] ?: $RCMAIL->gettext(str_replace('-', '', $col));
|
||||
$value = $colprop['value'] ?: rcube_output::get_edit_field($col, $IDENTITY_RECORD[$col], $colprop, $colprop['type']);
|
||||
|
||||
$table->add('title', html::label($colprop['id'], rcube::Q($label)));
|
||||
$table->add(null, $value);
|
||||
}
|
||||
|
||||
$content = $table->show($attrib);
|
||||
}
|
||||
else {
|
||||
$content = $fieldset['content'];
|
||||
}
|
||||
|
||||
$content = html::tag('legend', null, rcube::Q($fieldset['name'])) . $content;
|
||||
$out .= html::tag('fieldset', null, $content) . "\n";
|
||||
}
|
||||
|
||||
$out .= $form_end;
|
||||
|
||||
// add image upload form
|
||||
$max_filesize = $RCMAIL->upload_init($RCMAIL->config->get('identity_image_size', 64) * 1024);
|
||||
$upload_form_id = 'identityImageUpload';
|
||||
|
||||
$out .= '<form id="' . $upload_form_id . '" style="display: none">'
|
||||
. html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize))))
|
||||
. '</form>';
|
||||
|
||||
$RCMAIL->output->add_gui_object('uploadform', $upload_form_id);
|
||||
|
||||
return $out;
|
||||
}
|
87
data/web/rc/program/steps/settings/edit_prefs.inc
Normal file
87
data/web/rc/program/steps/settings/edit_prefs.inc
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/settings/edit_prefs.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Provide functionality for user's settings & preferences |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
|
||||
if (!$OUTPUT->ajax_call) {
|
||||
$OUTPUT->set_pagetitle($RCMAIL->gettext('preferences'));
|
||||
}
|
||||
|
||||
$CURR_SECTION = rcube_utils::get_input_value('_section', rcube_utils::INPUT_GPC);
|
||||
list($SECTIONS,) = rcmail_user_prefs($CURR_SECTION);
|
||||
|
||||
// register UI objects
|
||||
$OUTPUT->add_handlers(array(
|
||||
'userprefs' => 'rcmail_user_prefs_form',
|
||||
'sectionname' => 'rcmail_prefs_section_name',
|
||||
));
|
||||
|
||||
$OUTPUT->send('settingsedit');
|
||||
|
||||
|
||||
|
||||
function rcmail_user_prefs_form($attrib)
|
||||
{
|
||||
global $RCMAIL, $CURR_SECTION, $SECTIONS;
|
||||
|
||||
// add some labels to client
|
||||
$RCMAIL->output->add_label('nopagesizewarning');
|
||||
|
||||
unset($attrib['form']);
|
||||
|
||||
list($form_start, $form_end) = get_form_tags($attrib, 'save-prefs', null,
|
||||
array('name' => '_section', 'value' => $CURR_SECTION));
|
||||
|
||||
$out = $form_start;
|
||||
|
||||
if(!empty($SECTIONS[$CURR_SECTION]['header'])) {
|
||||
$out .= html::div(array('id' => 'preferences-header', 'class' =>'boxcontent'), $SECTIONS[$CURR_SECTION]['header']);
|
||||
}
|
||||
|
||||
foreach ($SECTIONS[$CURR_SECTION]['blocks'] as $class => $block) {
|
||||
if (!empty($block['options'])) {
|
||||
$table = new html_table(array('cols' => 2));
|
||||
|
||||
foreach ($block['options'] as $option) {
|
||||
if (isset($option['title'])) {
|
||||
$table->add('title', $option['title']);
|
||||
$table->add(null, $option['content']);
|
||||
}
|
||||
else {
|
||||
$table->add(array('colspan' => 2), $option['content']);
|
||||
}
|
||||
}
|
||||
|
||||
$out .= html::tag('fieldset', $class, html::tag('legend', null, $block['name']) . $table->show($attrib));
|
||||
}
|
||||
else if (!empty($block['content'])) {
|
||||
$out .= html::tag('fieldset', null, html::tag('legend', null, $block['name']) . $block['content']);
|
||||
}
|
||||
}
|
||||
|
||||
return $out . $form_end;
|
||||
}
|
||||
|
||||
function rcmail_prefs_section_name()
|
||||
{
|
||||
global $SECTIONS, $CURR_SECTION;
|
||||
|
||||
return $SECTIONS[$CURR_SECTION]['section'];
|
||||
}
|
107
data/web/rc/program/steps/settings/edit_response.inc
Normal file
107
data/web/rc/program/steps/settings/edit_response.inc
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/settings/edit_response.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 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: |
|
||||
| Show edit form for a canned response record or to add a new one |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$responses = $RCMAIL->get_compose_responses();
|
||||
|
||||
// edit-response
|
||||
if (($key = rcube_utils::get_input_value('_key', rcube_utils::INPUT_GPC))) {
|
||||
foreach ($responses as $i => $response) {
|
||||
if ($response['key'] == $key) {
|
||||
$RESPONSE_RECORD = $response;
|
||||
$RESPONSE_RECORD['index'] = $i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// save response
|
||||
if ($RCMAIL->action == 'save-response' && isset($_POST['_name']) && !$RESPONSE_RECORD['static']) {
|
||||
$name = trim(rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST));
|
||||
$text = trim(rcube_utils::get_input_value('_text', rcube_utils::INPUT_POST, true));
|
||||
|
||||
if (!empty($name) && !empty($text)) {
|
||||
$dupes = 0;
|
||||
foreach ($responses as $i => $resp) {
|
||||
if ($RESPONSE_RECORD && $RESPONSE_RECORD['index'] === $i)
|
||||
continue;
|
||||
if (strcasecmp($name, preg_replace('/\s\(\d+\)$/', '', $resp['name'])) == 0)
|
||||
$dupes++;
|
||||
}
|
||||
if ($dupes) { // require a unique name
|
||||
$name .= ' (' . ++$dupes . ')';
|
||||
}
|
||||
|
||||
$response = array('name' => $name, 'text' => $text, 'format' => 'text', 'key' => substr(md5($name), 0, 16));
|
||||
if ($RESPONSE_RECORD && $responses[$RESPONSE_RECORD['index']]) {
|
||||
$responses[$RESPONSE_RECORD['index']] = $response;
|
||||
}
|
||||
else {
|
||||
$responses[] = $response;
|
||||
}
|
||||
|
||||
$responses = array_filter($responses, function($item){ return empty($item['static']); });
|
||||
if ($RCMAIL->user->save_prefs(array('compose_responses' => array_values($responses)))) {
|
||||
$RCMAIL->output->show_message('successfullysaved', 'confirmation');
|
||||
$RCMAIL->output->command('parent.update_response_row', $response, $key);
|
||||
$RCMAIL->overwrite_action('edit-response');
|
||||
$RESPONSE_RECORD = $response;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$RCMAIL->output->show_message('formincomplete', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
$OUTPUT->set_env('readonly', !empty($RESPONSE_RECORD['static']));
|
||||
$OUTPUT->add_handler('responseform', 'rcube_response_form');
|
||||
$OUTPUT->set_pagetitle($RCMAIL->gettext($RCMAIL->action == 'add-response' ? 'addresponse' : 'editresponse'));
|
||||
|
||||
$OUTPUT->send('responseedit');
|
||||
|
||||
|
||||
function rcube_response_form($attrib)
|
||||
{
|
||||
global $RCMAIL, $RESPONSE_RECORD;
|
||||
|
||||
// Set form tags and hidden fields
|
||||
$disabled = !empty($RESPONSE_RECORD['static']);
|
||||
$key = $RESPONSE_RECORD['key'];
|
||||
list($form_start, $form_end) = get_form_tags($attrib, 'save-response', $key, array('name' => '_key', 'value' => $key));
|
||||
unset($attrib['form'], $attrib['id']);
|
||||
|
||||
// return the complete edit form as table
|
||||
$out = "$form_start\n";
|
||||
|
||||
$table = new html_table(array('cols' => 2));
|
||||
|
||||
$table->add('title', html::label('ffname', rcube::Q($RCMAIL->gettext('responsename'))));
|
||||
$table->add(null, rcube_output::get_edit_field('name', $RESPONSE_RECORD['name'],
|
||||
array('id' => 'ffname', 'size' => $attrib['size'], 'disabled' => $disabled), 'text'));
|
||||
|
||||
$table->add('title', html::label('fftext', rcube::Q($RCMAIL->gettext('responsetext'))));
|
||||
$table->add(null, rcube_output::get_edit_field('text', $RESPONSE_RECORD['text'],
|
||||
array('id' => 'fftext', 'size' => $attrib['textareacols'], 'rows' => $attrib['textarearows'], 'disabled' => $disabled), 'textarea'));
|
||||
|
||||
$out .= $table->show($attrib);
|
||||
$out .= $form_end;
|
||||
|
||||
return $out;
|
||||
}
|
521
data/web/rc/program/steps/settings/folders.inc
Normal file
521
data/web/rc/program/steps/settings/folders.inc
Normal file
@@ -0,0 +1,521 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/settings/folders.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Provide functionality of folders management |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// init IMAP connection
|
||||
$STORAGE = $RCMAIL->get_storage();
|
||||
|
||||
// subscribe mailbox
|
||||
if ($RCMAIL->action == 'subscribe') {
|
||||
$mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
|
||||
|
||||
if (strlen($mbox)) {
|
||||
$result = $STORAGE->subscribe(array($mbox));
|
||||
|
||||
// Handle virtual (non-existing) folders
|
||||
if (!$result && $STORAGE->get_error_code() == -1 &&
|
||||
$STORAGE->get_response_code() == rcube_storage::TRYCREATE
|
||||
) {
|
||||
$result = $STORAGE->create_folder($mbox, true);
|
||||
if ($result) {
|
||||
// @TODO: remove 'virtual' class of folder's row
|
||||
}
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
// Handle subscription of protected folder (#1487656)
|
||||
if ($RCMAIL->config->get('protect_default_folders')
|
||||
&& $STORAGE->is_special_folder($mbox)
|
||||
) {
|
||||
$OUTPUT->command('disable_subscription', $mbox);
|
||||
}
|
||||
|
||||
$OUTPUT->show_message('foldersubscribed', 'confirmation');
|
||||
}
|
||||
else {
|
||||
$RCMAIL->display_server_error('errorsaving');
|
||||
$OUTPUT->command('reset_subscription', $mbox, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
// unsubscribe mailbox
|
||||
else if ($RCMAIL->action == 'unsubscribe') {
|
||||
$mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
|
||||
|
||||
if (strlen($mbox)) {
|
||||
$result = $STORAGE->unsubscribe(array($mbox));
|
||||
|
||||
if ($result) {
|
||||
$OUTPUT->show_message('folderunsubscribed', 'confirmation');
|
||||
}
|
||||
else {
|
||||
$RCMAIL->display_server_error('errorsaving');
|
||||
$OUTPUT->command('reset_subscription', $mbox, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// delete an existing mailbox
|
||||
else if ($RCMAIL->action == 'delete-folder') {
|
||||
$mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
|
||||
|
||||
if (strlen($mbox)) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('folder_delete', array('name' => $mbox));
|
||||
|
||||
if (!$plugin['abort']) {
|
||||
$deleted = $STORAGE->delete_folder($plugin['name']);
|
||||
}
|
||||
else {
|
||||
$deleted = $plugin['result'];
|
||||
}
|
||||
|
||||
// #1488692: update session
|
||||
if ($deleted && $_SESSION['mbox'] === $mbox) {
|
||||
$RCMAIL->session->remove('mbox');
|
||||
}
|
||||
}
|
||||
|
||||
if ($OUTPUT->ajax_call && $deleted) {
|
||||
// Remove folder and subfolders rows
|
||||
$OUTPUT->command('remove_folder_row', $mbox);
|
||||
$OUTPUT->show_message('folderdeleted', 'confirmation');
|
||||
// Clear content frame
|
||||
$OUTPUT->command('subscription_select');
|
||||
$OUTPUT->command('set_quota', $RCMAIL->quota_content());
|
||||
}
|
||||
else if (!$deleted) {
|
||||
$RCMAIL->display_server_error('errorsaving');
|
||||
}
|
||||
}
|
||||
// rename an existing mailbox
|
||||
else if ($RCMAIL->action == 'rename-folder') {
|
||||
$name = trim(rcube_utils::get_input_value('_folder_newname', rcube_utils::INPUT_POST, true));
|
||||
$oldname = rcube_utils::get_input_value('_folder_oldname', rcube_utils::INPUT_POST, true);
|
||||
|
||||
if (strlen($name) && strlen($oldname)) {
|
||||
$rename = rcmail_rename_folder($oldname, $name);
|
||||
}
|
||||
|
||||
if ($rename && $OUTPUT->ajax_call) {
|
||||
rcmail_update_folder_row($name, $oldname);
|
||||
}
|
||||
else if (!$rename) {
|
||||
$RCMAIL->display_server_error('errorsaving');
|
||||
}
|
||||
}
|
||||
// clear mailbox
|
||||
else if ($RCMAIL->action == 'purge') {
|
||||
$mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
|
||||
$delimiter = $STORAGE->get_hierarchy_delimiter();
|
||||
$trash_mbox = $RCMAIL->config->get('trash_mbox');
|
||||
$trash_regexp = '/^' . preg_quote($trash . $delimiter, '/') . '/';
|
||||
|
||||
// we should only be purging trash (or their subfolders)
|
||||
if (!strlen($trash_mbox) || $mbox === $trash_mbox
|
||||
|| preg_match($trash_regexp, $mbox)
|
||||
) {
|
||||
$success = $STORAGE->delete_message('*', $mbox);
|
||||
$delete = true;
|
||||
}
|
||||
// move to Trash
|
||||
else {
|
||||
$success = $STORAGE->move_message('1:*', $trash_mbox, $mbox);
|
||||
$delete = false;
|
||||
}
|
||||
|
||||
if ($success) {
|
||||
$OUTPUT->set_env('messagecount', 0);
|
||||
if ($delete) {
|
||||
$OUTPUT->show_message('folderpurged', 'confirmation');
|
||||
$OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $mbox));
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message('messagemoved', 'confirmation');
|
||||
}
|
||||
$_SESSION['unseen_count'][$mbox] = 0;
|
||||
$OUTPUT->command('show_folder', $mbox, null, true);
|
||||
}
|
||||
else {
|
||||
$RCMAIL->display_server_error('errorsaving');
|
||||
}
|
||||
}
|
||||
// get mailbox size
|
||||
else if ($RCMAIL->action == 'folder-size') {
|
||||
$name = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
|
||||
|
||||
$size = $STORAGE->folder_size($name);
|
||||
|
||||
// @TODO: check quota and show percentage usage of specified mailbox?
|
||||
|
||||
if ($size !== false) {
|
||||
$OUTPUT->command('folder_size_update', $RCMAIL->show_bytes($size));
|
||||
}
|
||||
else {
|
||||
$RCMAIL->display_server_error();
|
||||
}
|
||||
}
|
||||
|
||||
if ($OUTPUT->ajax_call) {
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
$OUTPUT->set_pagetitle($RCMAIL->gettext('folders'));
|
||||
$OUTPUT->set_env('prefix_ns', $STORAGE->get_namespace('prefix'));
|
||||
$OUTPUT->set_env('quota', (bool) $STORAGE->get_capability('QUOTA'));
|
||||
$OUTPUT->include_script('treelist.js');
|
||||
|
||||
// add some labels to client
|
||||
$OUTPUT->add_label('deletefolderconfirm', 'purgefolderconfirm', 'folderdeleting',
|
||||
'foldermoving', 'foldersubscribing', 'folderunsubscribing', 'quota');
|
||||
|
||||
// register UI objects
|
||||
$OUTPUT->add_handlers(array(
|
||||
'foldersubscription' => 'rcmail_subscription_form',
|
||||
'folderframe' => 'rcmail_folder_frame',
|
||||
'folderfilter' => 'rcmail_folder_filter',
|
||||
'quotadisplay' => array($RCMAIL, 'quota_display'),
|
||||
));
|
||||
|
||||
$OUTPUT->send('folders');
|
||||
|
||||
|
||||
// build table with all folders listed by server
|
||||
function rcmail_subscription_form($attrib)
|
||||
{
|
||||
global $RCMAIL, $OUTPUT;
|
||||
|
||||
list($form_start, $form_end) = get_form_tags($attrib, 'folders');
|
||||
unset($attrib['form']);
|
||||
|
||||
if (!$attrib['id']) {
|
||||
$attrib['id'] = 'rcmSubscriptionlist';
|
||||
}
|
||||
|
||||
$STORAGE = $RCMAIL->get_storage();
|
||||
|
||||
// get folders from server
|
||||
$STORAGE->clear_cache('mailboxes', true);
|
||||
|
||||
$a_unsubscribed = $STORAGE->list_folders();
|
||||
$a_subscribed = $STORAGE->list_folders_subscribed('', '*', null, null, true); // unsorted
|
||||
$delimiter = $STORAGE->get_hierarchy_delimiter();
|
||||
$namespace = $STORAGE->get_namespace();
|
||||
$special_folders = array_flip(array_merge(array('inbox' => 'INBOX'), $STORAGE->get_special_folders()));
|
||||
$protect_default = $RCMAIL->config->get('protect_default_folders');
|
||||
$seen = array();
|
||||
$list_folders = array();
|
||||
|
||||
// pre-process folders list
|
||||
foreach ($a_unsubscribed as $i => $folder) {
|
||||
$folder_id = $folder;
|
||||
$folder = $STORAGE->mod_folder($folder);
|
||||
$foldersplit = explode($delimiter, $folder);
|
||||
$name = rcube_charset::convert(array_pop($foldersplit), 'UTF7-IMAP');
|
||||
$parent_folder = join($delimiter, $foldersplit);
|
||||
$level = count($foldersplit);
|
||||
|
||||
// add any necessary "virtual" parent folders
|
||||
if ($parent_folder && !isset($seen[$parent_folder])) {
|
||||
for ($i=1; $i<=$level; $i++) {
|
||||
$ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i));
|
||||
if ($ancestor_folder && !$seen[$ancestor_folder]++) {
|
||||
$ancestor_name = rcube_charset::convert($foldersplit[$i-1], 'UTF7-IMAP');
|
||||
$list_folders[] = array(
|
||||
'id' => $ancestor_folder,
|
||||
'name' => $ancestor_name,
|
||||
'level' => $i-1,
|
||||
'virtual' => true,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle properly INBOX.INBOX situation
|
||||
if (isset($seen[$folder])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$seen[$folder]++;
|
||||
|
||||
$list_folders[] = array(
|
||||
'id' => $folder_id,
|
||||
'name' => $name,
|
||||
'level' => $level,
|
||||
);
|
||||
}
|
||||
|
||||
unset($seen);
|
||||
|
||||
$checkbox_subscribe = new html_checkbox(array(
|
||||
'name' => '_subscribed[]',
|
||||
'title' => $RCMAIL->gettext('changesubscription'),
|
||||
'onclick' => rcmail_output::JS_OBJECT_NAME.".command(this.checked?'subscribe':'unsubscribe',this.value)",
|
||||
));
|
||||
|
||||
$js_folders = array();
|
||||
$folders = array();
|
||||
$collapsed = (string) $RCMAIL->config->get('collapsed_folders');
|
||||
|
||||
// create list of available folders
|
||||
foreach ($list_folders as $i => $folder) {
|
||||
$sub_key = array_search($folder['id'], $a_subscribed);
|
||||
$subscribed = $sub_key !== false;
|
||||
$protected = $folder['id'] == 'INBOX' || ($protect_default && isset($special_folders[$folder['id']]));
|
||||
$noselect = false;
|
||||
$classes = array();
|
||||
|
||||
$folder_utf8 = rcube_charset::convert($folder['id'], 'UTF7-IMAP');
|
||||
$display_folder = rcube::Q($protected ? $RCMAIL->localize_foldername($folder['id']) : $folder['name']);
|
||||
|
||||
if ($folder['virtual']) {
|
||||
$classes[] = 'virtual';
|
||||
}
|
||||
|
||||
// Check \Noselect flag (of existing folder)
|
||||
if (!$protected && in_array($folder['id'], $a_unsubscribed)) {
|
||||
$attrs = $STORAGE->folder_attributes($folder['id']);
|
||||
$noselect = in_array_nocase('\\Noselect', $attrs);
|
||||
}
|
||||
|
||||
$disabled = (($protected && $subscribed) || $noselect);
|
||||
|
||||
// Below we will disable subscription option for "virtual" folders
|
||||
// according to namespaces, but only if they aren't already subscribed.
|
||||
// User should be able to unsubscribe from the folder
|
||||
// even if it doesn't exists or is not accessible (OTRS:1000059)
|
||||
if (!$subscribed && !$disabled && !empty($namespace) && $folder['virtual']) {
|
||||
// check if the folder is a namespace prefix, then disable subscription option on it
|
||||
if (!$disabled && $folder['level'] == 0) {
|
||||
$fname = $folder['id'] . $delimiter;
|
||||
foreach ($namespace as $ns) {
|
||||
if (is_array($ns)) {
|
||||
foreach ($ns as $item) {
|
||||
if ($item[0] === $fname) {
|
||||
$disabled = true;
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// check if the folder is an other users virtual-root folder, then disable subscription option on it
|
||||
if (!$disabled && $folder['level'] == 1 && !empty($namespace['other'])) {
|
||||
$parts = explode($delimiter, $folder['id']);
|
||||
$fname = $parts[0] . $delimiter;
|
||||
foreach ($namespace['other'] as $item) {
|
||||
if ($item[0] === $fname) {
|
||||
$disabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// check if the folder is shared, then disable subscription option on it (if not subscribed already)
|
||||
if (!$disabled) {
|
||||
$tmp_ns = array_merge((array)$namespace['other'], (array)$namespace['shared']);
|
||||
foreach ($tmp_ns as $item) {
|
||||
if (strlen($item[0]) && strpos($folder['id'], $item[0]) === 0) {
|
||||
$disabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$is_collapsed = strpos($collapsed, '&'.rawurlencode($folder['id']).'&') !== false;
|
||||
$folder_id = rcube_utils::html_identifier($folder['id'], true);
|
||||
|
||||
if ($folder_class = $RCMAIL->folder_classname($folder['id'])) {
|
||||
$classes[] = $folder_class;
|
||||
}
|
||||
|
||||
$folders[$folder['id']] = array(
|
||||
'idx' => $folder_id,
|
||||
'folder_imap' => $folder['id'],
|
||||
'folder' => $folder_utf8,
|
||||
'display' => $display_folder,
|
||||
'protected' => $protected || $folder['virtual'],
|
||||
'class' => join(' ', $classes),
|
||||
'subscribed' => $subscribed,
|
||||
'level' => $folder['level'],
|
||||
'collapsed' => $is_collapsed,
|
||||
'content' => html::a(array('href' => '#'), $display_folder)
|
||||
. $checkbox_subscribe->show(($subscribed ? $folder['id'] : ''),
|
||||
array('value' => $folder['id'], 'disabled' => $disabled ? 'disabled' : ''))
|
||||
);
|
||||
}
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('folders_list', array('list' => $folders));
|
||||
|
||||
// add drop-target representing 'root'
|
||||
$root = array(
|
||||
'idx' => rcube_utils::html_identifier('*', true),
|
||||
'folder_imap' => '*',
|
||||
'folder' => '',
|
||||
'display' => '',
|
||||
'protected' => true,
|
||||
'class' => 'root',
|
||||
'content' => '<span> </span>',
|
||||
);
|
||||
|
||||
$folders = array();
|
||||
$plugin['list'] = array_values($plugin['list']);
|
||||
|
||||
array_unshift($plugin['list'], $root);
|
||||
|
||||
for ($i = 0, $length = count($plugin['list']); $i<$length; $i++) {
|
||||
$folders[] = rcmail_folder_tree_element($plugin['list'], $i, $js_folders);
|
||||
}
|
||||
|
||||
$OUTPUT->add_gui_object('subscriptionlist', $attrib['id']);
|
||||
$OUTPUT->set_env('subscriptionrows', $js_folders);
|
||||
$OUTPUT->set_env('defaultfolders', array_keys($special_folders));
|
||||
$OUTPUT->set_env('collapsed_folders', $collapsed);
|
||||
$OUTPUT->set_env('delimiter', $delimiter);
|
||||
|
||||
return $form_start . html::tag('ul', $attrib, implode('', $folders), html::$common_attrib) . $form_end;
|
||||
}
|
||||
|
||||
function rcmail_folder_tree_element($folders, &$key, &$js_folders)
|
||||
{
|
||||
$data = $folders[$key];
|
||||
$idx = 'rcmli' . $data['idx'];
|
||||
|
||||
$js_folders[$data['folder_imap']] = array($data['folder'], $data['display'], $data['protected']);
|
||||
$content = $data['content'];
|
||||
$attribs = array(
|
||||
'id' => $idx,
|
||||
'class' => trim($data['class'] . ' mailbox')
|
||||
);
|
||||
|
||||
$children = array();
|
||||
while ($folders[$key+1] && $folders[$key+1]['level'] > $data['level']) {
|
||||
$key++;
|
||||
$children[] = rcmail_folder_tree_element($folders, $key, $js_folders);
|
||||
}
|
||||
|
||||
if (!empty($children)) {
|
||||
$content .= html::div('treetoggle ' . ($data['collapsed'] ? 'collapsed' : 'expanded'), ' ')
|
||||
. html::tag('ul', array('style' => ($data['collapsed'] ? "display:none" : null)),
|
||||
implode("\n", $children));
|
||||
}
|
||||
|
||||
return html::tag('li', $attribs, $content);
|
||||
}
|
||||
|
||||
function rcmail_folder_frame($attrib)
|
||||
{
|
||||
global $OUTPUT;
|
||||
|
||||
if (!$attrib['id']) {
|
||||
$attrib['id'] = 'rcmfolderframe';
|
||||
}
|
||||
|
||||
return $OUTPUT->frame($attrib, true);
|
||||
}
|
||||
|
||||
function rcmail_folder_filter($attrib)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
$storage = $RCMAIL->get_storage();
|
||||
$namespace = $storage->get_namespace();
|
||||
|
||||
if (empty($namespace['personal']) && empty($namespace['shared']) && empty($namespace['other'])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$attrib['id']) {
|
||||
$attrib['id'] = 'rcmfolderfilter';
|
||||
}
|
||||
|
||||
$attrib['onchange'] = rcmail_output::JS_OBJECT_NAME . '.folder_filter(this.value)';
|
||||
|
||||
$roots = array();
|
||||
$select = new html_select($attrib);
|
||||
$select->add($RCMAIL->gettext('all'), '---');
|
||||
|
||||
foreach (array_keys($namespace) as $type) {
|
||||
foreach ((array)$namespace[$type] as $ns) {
|
||||
$root = rtrim($ns[0], $ns[1]);
|
||||
$label = $RCMAIL->gettext('namespace.' . $type);
|
||||
|
||||
if (count($namespace[$type]) > 1) {
|
||||
$label .= ' (' . rcube_charset::convert($root, 'UTF7-IMAP', RCUBE_CHARSET) . ')';
|
||||
}
|
||||
|
||||
$select->add($label, $root);
|
||||
|
||||
if (strlen($root)) {
|
||||
$roots[] = $root;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$RCMAIL->output->add_gui_object('foldersfilter', $attrib['id']);
|
||||
$RCMAIL->output->set_env('ns_roots', $roots);
|
||||
|
||||
return $select->show();
|
||||
}
|
||||
|
||||
function rcmail_rename_folder($oldname, $newname)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
$storage = $RCMAIL->get_storage();
|
||||
$delimiter = $storage->get_hierarchy_delimiter();
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('folder_rename', array(
|
||||
'oldname' => $oldname, 'newname' => $newname));
|
||||
|
||||
if (!$plugin['abort']) {
|
||||
$renamed = $storage->rename_folder($oldname, $newname);
|
||||
}
|
||||
else {
|
||||
$renamed = $plugin['result'];
|
||||
}
|
||||
|
||||
// update per-folder options for modified folder and its subfolders
|
||||
if ($renamed) {
|
||||
$a_threaded = (array) $RCMAIL->config->get('message_threading', array());
|
||||
$oldprefix = '/^' . preg_quote($oldname . $delimiter, '/') . '/';
|
||||
|
||||
foreach ($a_threaded as $key => $val) {
|
||||
if ($key == $oldname) {
|
||||
unset($a_threaded[$key]);
|
||||
$a_threaded[$newname] = $val;
|
||||
}
|
||||
else if (preg_match($oldprefix, $key)) {
|
||||
unset($a_threaded[$key]);
|
||||
$a_threaded[preg_replace($oldprefix, $newname.$delimiter, $key)] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
$RCMAIL->user->save_prefs(array('message_threading' => $a_threaded));
|
||||
|
||||
// #1488692: update session
|
||||
if ($_SESSION['mbox'] === $oldname) {
|
||||
$_SESSION['mbox'] = $newname;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
1422
data/web/rc/program/steps/settings/func.inc
Normal file
1422
data/web/rc/program/steps/settings/func.inc
Normal file
File diff suppressed because it is too large
Load Diff
66
data/web/rc/program/steps/settings/identities.inc
Normal file
66
data/web/rc/program/steps/settings/identities.inc
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/settings/identities.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Manage identities of a user account |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
if ($RCMAIL->action == 'delete-identity' && $OUTPUT->ajax_call) {
|
||||
$iid = rcube_utils::get_input_value('_iid', rcube_utils::INPUT_POST);
|
||||
|
||||
if ($iid && preg_match('/^[0-9]+(,[0-9]+)*$/', $iid)) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('identity_delete', array('id' => $iid));
|
||||
|
||||
$deleted = !$plugin['abort'] ? $RCMAIL->user->delete_identity($iid) : $plugin['result'];
|
||||
|
||||
if ($deleted > 0 && $deleted !== false) {
|
||||
$OUTPUT->show_message('deletedsuccessfully', 'confirmation', null, false);
|
||||
$OUTPUT->command('remove_identity', $iid);
|
||||
}
|
||||
else {
|
||||
$msg = $plugin['message'] ?: ($deleted < 0 ? 'nodeletelastidentity' : 'errorsaving');
|
||||
$OUTPUT->show_message($msg, 'error', null, false);
|
||||
}
|
||||
}
|
||||
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
|
||||
define('IDENTITIES_LEVEL', intval($RCMAIL->config->get('identities_level', 0)));
|
||||
|
||||
$OUTPUT->set_pagetitle($RCMAIL->gettext('identities'));
|
||||
$OUTPUT->include_script('list.js');
|
||||
|
||||
$OUTPUT->add_handler('identityframe', 'rcmail_identity_frame');
|
||||
$OUTPUT->set_env('identities_level', IDENTITIES_LEVEL);
|
||||
$OUTPUT->add_label('deleteidentityconfirm');
|
||||
|
||||
$OUTPUT->send('identities');
|
||||
|
||||
|
||||
// similar function as /steps/addressbook/func.inc::rcmail_contact_frame()
|
||||
function rcmail_identity_frame($attrib)
|
||||
{
|
||||
global $OUTPUT;
|
||||
|
||||
if (!$attrib['id']) {
|
||||
$attrib['id'] = 'rcmIdentityFrame';
|
||||
}
|
||||
|
||||
return $OUTPUT->frame($attrib, true);
|
||||
}
|
131
data/web/rc/program/steps/settings/responses.inc
Normal file
131
data/web/rc/program/steps/settings/responses.inc
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/settings/responses.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 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: |
|
||||
| Manage and save canned response texts |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
|
||||
if (!empty($_POST['_insert'])) {
|
||||
$name = trim(rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST));
|
||||
$text = trim(rcube_utils::get_input_value('_text', rcube_utils::INPUT_POST, true));
|
||||
|
||||
if (!empty($name) && !empty($text)) {
|
||||
$dupes = 0;
|
||||
$responses = $RCMAIL->get_compose_responses(false, true);
|
||||
foreach ($responses as $resp) {
|
||||
if (strcasecmp($name, preg_replace('/\s\(\d+\)$/', '', $resp['name'])) == 0)
|
||||
$dupes++;
|
||||
}
|
||||
if ($dupes) { // require a unique name
|
||||
$name .= ' (' . ++$dupes . ')';
|
||||
}
|
||||
|
||||
$response = array('name' => $name, 'text' => $text, 'format' => 'text', 'key' => substr(md5($name), 0, 16));
|
||||
$responses[] = $response;
|
||||
|
||||
if ($RCMAIL->user->save_prefs(array('compose_responses' => $responses))) {
|
||||
$RCMAIL->output->command('add_response_item', $response);
|
||||
$RCMAIL->output->command('display_message', $RCMAIL->gettext('successfullysaved'), 'confirmation');
|
||||
}
|
||||
else {
|
||||
$RCMAIL->output->command('display_message', $RCMAIL->gettext('errorsaving'), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// send response
|
||||
$RCMAIL->output->send();
|
||||
}
|
||||
|
||||
if ($RCMAIL->action == 'delete-response' && $RCMAIL->output->ajax_call) {
|
||||
if ($key = rcube_utils::get_input_value('_key', rcube_utils::INPUT_POST)) {
|
||||
$responses = $RCMAIL->get_compose_responses(false, true);
|
||||
foreach ($responses as $i => $response) {
|
||||
if (empty($response['key']))
|
||||
$response['key'] = substr(md5($response['name']), 0, 16);
|
||||
if ($response['key'] == $key) {
|
||||
unset($responses[$i]);
|
||||
$deleted = $RCMAIL->user->save_prefs(array('compose_responses' => $responses));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($deleted) {
|
||||
$RCMAIL->output->command('display_message', $RCMAIL->gettext('deletedsuccessfully'), 'confirmation');
|
||||
$RCMAIL->output->command('remove_response', $key);
|
||||
}
|
||||
|
||||
$RCMAIL->output->send();
|
||||
}
|
||||
|
||||
|
||||
$OUTPUT->set_pagetitle($RCMAIL->gettext('responses'));
|
||||
$OUTPUT->include_script('list.js');
|
||||
|
||||
$OUTPUT->add_handlers(array(
|
||||
'responseframe' => 'rcmail_response_frame',
|
||||
'responseslist' => 'rcmail_responses_list',
|
||||
));
|
||||
$OUTPUT->add_label('deleteresponseconfirm');
|
||||
|
||||
$OUTPUT->send('responses');
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function rcmail_responses_list($attrib)
|
||||
{
|
||||
global $RCMAIL, $OUTPUT;
|
||||
|
||||
$attrib += array('id' => 'rcmresponseslist', 'tagname' => 'table');
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('responses_list', array(
|
||||
'list' => $RCMAIL->get_compose_responses(true),
|
||||
'cols' => array('name')
|
||||
));
|
||||
|
||||
$out = $RCMAIL->table_output($attrib, $plugin['list'], $plugin['cols'], 'key');
|
||||
|
||||
$readonly_responses = array();
|
||||
foreach ($plugin['list'] as $item) {
|
||||
if (!empty($item['static'])) {
|
||||
$readonly_responses[] = $item['key'];
|
||||
}
|
||||
}
|
||||
|
||||
// set client env
|
||||
$OUTPUT->add_gui_object('responseslist', $attrib['id']);
|
||||
$OUTPUT->set_env('readonly_responses', $readonly_responses);
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
// similar function as /steps/addressbook/func.inc::rcmail_contact_frame()
|
||||
function rcmail_response_frame($attrib)
|
||||
{
|
||||
global $OUTPUT;
|
||||
|
||||
if (!$attrib['id']) {
|
||||
$attrib['id'] = 'rcmResponseFrame';
|
||||
}
|
||||
|
||||
$OUTPUT->set_env('contentframe', $attrib['id']);
|
||||
|
||||
return $OUTPUT->frame($attrib, true);
|
||||
}
|
202
data/web/rc/program/steps/settings/save_folder.inc
Normal file
202
data/web/rc/program/steps/settings/save_folder.inc
Normal file
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/settings/save_folder.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Provide functionality to create/edit a folder |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// WARNING: folder names in UI are encoded with RCUBE_CHARSET
|
||||
|
||||
// init IMAP connection
|
||||
$STORAGE = $RCMAIL->get_storage();
|
||||
|
||||
$name = trim(rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true));
|
||||
$path = rcube_utils::get_input_value('_parent', rcube_utils::INPUT_POST, true);
|
||||
$old_imap = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
|
||||
$name_imap = rcube_charset::convert($name, RCUBE_CHARSET, 'UTF7-IMAP');
|
||||
// $path is in UTF7-IMAP already
|
||||
|
||||
$delimiter = $STORAGE->get_hierarchy_delimiter();
|
||||
$options = strlen($old_imap) ? rcmail_folder_options($old_imap) : array();
|
||||
|
||||
// Folder name checks
|
||||
if ($options['protected'] || $options['norename']) {
|
||||
}
|
||||
else if (!strlen($name)) {
|
||||
$error = $RCMAIL->gettext('namecannotbeempty');
|
||||
}
|
||||
else if (mb_strlen($name) > 128) {
|
||||
$error = $RCMAIL->gettext('nametoolong');
|
||||
}
|
||||
else if ($name[0] == '.' && $RCMAIL->config->get('imap_skip_hidden_folders')) {
|
||||
$error = $RCMAIL->gettext('namedotforbidden');
|
||||
}
|
||||
else {
|
||||
// these characters are problematic e.g. when used in LIST/LSUB
|
||||
foreach (array($delimiter, '%', '*') as $char) {
|
||||
if (strpos($name, $delimiter) !== false) {
|
||||
$error = $RCMAIL->gettext('forbiddencharacter') . " ($char)";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$OUTPUT->command('display_message', $error, 'error');
|
||||
}
|
||||
else {
|
||||
if ($options['protected'] || $options['norename']) {
|
||||
$name_imap = $old_imap;
|
||||
}
|
||||
else if (strlen($path)) {
|
||||
$name_imap = $path . $delimiter . $name_imap;
|
||||
}
|
||||
else {
|
||||
$name_imap = $STORAGE->mod_folder($name_imap, 'in');
|
||||
}
|
||||
}
|
||||
|
||||
// Check access rights to the parent folder
|
||||
if (!$error && strlen($path) && (!strlen($old_imap) || $old_imap != $name_imap)
|
||||
&& $STORAGE->get_capability('ACL')
|
||||
) {
|
||||
$parent_opts = $STORAGE->folder_info($path);
|
||||
if ($parent_opts['namespace'] != 'personal'
|
||||
&& (empty($parent_opts['rights']) || !preg_match('/[ck]/', implode($parent_opts['rights'])))
|
||||
) {
|
||||
$error = $RCMAIL->gettext('parentnotwritable');
|
||||
}
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$OUTPUT->command('display_message', $error, 'error');
|
||||
}
|
||||
else {
|
||||
$folder['name'] = $name_imap;
|
||||
$folder['oldname'] = $old_imap;
|
||||
$folder['class'] = '';
|
||||
$folder['options'] = $options;
|
||||
$folder['settings'] = array(
|
||||
// List view mode: 0-list, 1-threads
|
||||
'view_mode' => (int) rcube_utils::get_input_value('_viewmode', rcube_utils::INPUT_POST),
|
||||
'sort_column' => rcube_utils::get_input_value('_sortcol', rcube_utils::INPUT_POST),
|
||||
'sort_order' => rcube_utils::get_input_value('_sortord', rcube_utils::INPUT_POST),
|
||||
);
|
||||
}
|
||||
|
||||
// create a new mailbox
|
||||
if (!$error && !strlen($old_imap)) {
|
||||
$folder['subscribe'] = true;
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('folder_create', array('record' => $folder));
|
||||
|
||||
$folder = $plugin['record'];
|
||||
|
||||
if (!$plugin['abort']) {
|
||||
$created = $STORAGE->create_folder($folder['name'], $folder['subscribe']);
|
||||
}
|
||||
else {
|
||||
$created = $plugin['result'];
|
||||
}
|
||||
|
||||
if ($created) {
|
||||
// Save folder settings
|
||||
if (isset($_POST['_viewmode'])) {
|
||||
$a_threaded = (array) $RCMAIL->config->get('message_threading', array());
|
||||
|
||||
$a_threaded[$folder['name']] = (bool) $_POST['_viewmode'];
|
||||
|
||||
$RCMAIL->user->save_prefs(array('message_threading' => $a_threaded));
|
||||
}
|
||||
|
||||
rcmail_update_folder_row($folder['name'], null, $folder['subscribe'], $folder['class']);
|
||||
|
||||
$OUTPUT->show_message('foldercreated', 'confirmation');
|
||||
// reset folder preview frame
|
||||
$OUTPUT->command('subscription_select');
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
else {
|
||||
// show error message
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'errorsaving', 'error', null, false);
|
||||
}
|
||||
}
|
||||
// update a mailbox
|
||||
else if (!$error) {
|
||||
$plugin = $RCMAIL->plugins->exec_hook('folder_update', array('record' => $folder));
|
||||
|
||||
$folder = $plugin['record'];
|
||||
$rename = ($folder['oldname'] != $folder['name']);
|
||||
|
||||
if (!$plugin['abort']) {
|
||||
if ($rename) {
|
||||
$updated = $STORAGE->rename_folder($folder['oldname'], $folder['name']);
|
||||
}
|
||||
else {
|
||||
$updated = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$updated = $plugin['result'];
|
||||
}
|
||||
|
||||
if ($updated) {
|
||||
// Update folder settings,
|
||||
if (isset($_POST['_viewmode'])) {
|
||||
$a_threaded = (array) $RCMAIL->config->get('message_threading', array());
|
||||
|
||||
// In case of name change update names of childrens in settings
|
||||
if ($rename) {
|
||||
$oldprefix = '/^' . preg_quote($folder['oldname'] . $delimiter, '/') . '/';
|
||||
foreach ($a_threaded as $key => $val) {
|
||||
if ($key == $folder['oldname']) {
|
||||
unset($a_threaded[$key]);
|
||||
}
|
||||
else if (preg_match($oldprefix, $key)) {
|
||||
unset($a_threaded[$key]);
|
||||
$a_threaded[preg_replace($oldprefix, $folder['name'].$delimiter, $key)] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$a_threaded[$folder['name']] = (bool) $_POST['_viewmode'];
|
||||
|
||||
$RCMAIL->user->save_prefs(array('message_threading' => $a_threaded));
|
||||
}
|
||||
|
||||
$OUTPUT->show_message('folderupdated', 'confirmation');
|
||||
$OUTPUT->set_env('folder', $folder['name']);
|
||||
|
||||
if ($rename) {
|
||||
// #1488692: update session
|
||||
if ($_SESSION['mbox'] === $folder['oldname']) {
|
||||
$_SESSION['mbox'] = $folder['name'];
|
||||
}
|
||||
rcmail_update_folder_row($folder['name'], $folder['oldname'], $folder['subscribe'], $folder['class']);
|
||||
$OUTPUT->send('iframe');
|
||||
}
|
||||
else if (!empty($folder['class'])) {
|
||||
rcmail_update_folder_row($folder['name'], $folder['oldname'], $folder['subscribe'], $folder['class']);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// show error message
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'errorsaving', 'error', null, false);
|
||||
}
|
||||
}
|
||||
|
||||
$RCMAIL->overwrite_action('edit-folder');
|
266
data/web/rc/program/steps/settings/save_identity.inc
Normal file
266
data/web/rc/program/steps/settings/save_identity.inc
Normal file
@@ -0,0 +1,266 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/settings/save_identity.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Save an identity record or to add a new one |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
define('IDENTITIES_LEVEL', intval($RCMAIL->config->get('identities_level', 0)));
|
||||
|
||||
$a_save_cols = array('name', 'email', 'organization', 'reply-to', 'bcc', 'standard', 'signature', 'html_signature');
|
||||
$a_boolean_cols = array('standard', 'html_signature');
|
||||
$updated = $default_id = false;
|
||||
|
||||
// check input
|
||||
if (empty($_POST['_email']) && (IDENTITIES_LEVEL == 0 || IDENTITIES_LEVEL == 2)) {
|
||||
$OUTPUT->show_message('noemailwarning', 'warning');
|
||||
$RCMAIL->overwrite_action('edit-identity');
|
||||
return;
|
||||
}
|
||||
|
||||
$save_data = array();
|
||||
foreach ($a_save_cols as $col) {
|
||||
$fname = '_'.$col;
|
||||
if (isset($_POST[$fname])) {
|
||||
$save_data[$col] = rcube_utils::get_input_value($fname, rcube_utils::INPUT_POST, true);
|
||||
}
|
||||
}
|
||||
|
||||
// set "off" values for checkboxes that were not checked, and therefore
|
||||
// not included in the POST body.
|
||||
foreach ($a_boolean_cols as $col) {
|
||||
$fname = '_' . $col;
|
||||
if (!isset($_POST[$fname])) {
|
||||
$save_data[$col] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// make the identity a "default" if only one identity is allowed
|
||||
if (IDENTITIES_LEVEL > 1) {
|
||||
$save_data['standard'] = 1;
|
||||
}
|
||||
|
||||
// unset email address if user has no rights to change it
|
||||
if (IDENTITIES_LEVEL == 1 || IDENTITIES_LEVEL == 3) {
|
||||
unset($save_data['email']);
|
||||
}
|
||||
// unset all fields except signature
|
||||
else if (IDENTITIES_LEVEL == 4) {
|
||||
foreach ($save_data as $idx => $value) {
|
||||
if ($idx != 'signature' && $idx != 'html_signature') {
|
||||
unset($save_data[$idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate e-mail addresses
|
||||
$email_checks = array(rcube_utils::idn_to_ascii($save_data['email']));
|
||||
foreach (array('reply-to', 'bcc') as $item) {
|
||||
foreach (rcube_mime::decode_address_list($save_data[$item], null, false) as $rcpt) {
|
||||
$email_checks[] = rcube_utils::idn_to_ascii($rcpt['mailto']);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($email_checks as $email) {
|
||||
if ($email && !rcube_utils::check_email($email)) {
|
||||
// show error message
|
||||
$OUTPUT->show_message('emailformaterror', 'error', array('email' => rcube_utils::idn_to_utf8($email)), false);
|
||||
$RCMAIL->overwrite_action('edit-identity');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($save_data['signature']) && !empty($save_data['html_signature'])) {
|
||||
// replace uploaded images with data URIs
|
||||
$save_data['signature'] = rcmail_attach_images($save_data['signature']);
|
||||
|
||||
// XSS protection in HTML signature (#1489251)
|
||||
$save_data['signature'] = rcmail_wash_html($save_data['signature']);
|
||||
|
||||
// clear POST data of signature, we want to use safe content
|
||||
// when the form is displayed again
|
||||
unset($_POST['_signature']);
|
||||
}
|
||||
|
||||
// update an existing identity
|
||||
if ($_POST['_iid']) {
|
||||
$iid = rcube_utils::get_input_value('_iid', rcube_utils::INPUT_POST);
|
||||
|
||||
if (in_array(IDENTITIES_LEVEL, array(1,3,4))) {
|
||||
// merge with old identity data, fixes #1488834
|
||||
$identity = $RCMAIL->user->get_identity($iid);
|
||||
$save_data = array_merge($identity, $save_data);
|
||||
|
||||
unset($save_data['changed'], $save_data['del'], $save_data['user_id'], $save_data['identity_id']);
|
||||
}
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('identity_update', array('id' => $iid, 'record' => $save_data));
|
||||
$save_data = $plugin['record'];
|
||||
|
||||
if ($save_data['email']) {
|
||||
$save_data['email'] = rcube_utils::idn_to_ascii($save_data['email']);
|
||||
}
|
||||
|
||||
if (!$plugin['abort'])
|
||||
$updated = $RCMAIL->user->update_identity($iid, $save_data);
|
||||
else
|
||||
$updated = $plugin['result'];
|
||||
|
||||
if ($updated) {
|
||||
$OUTPUT->show_message('successfullysaved', 'confirmation');
|
||||
|
||||
if (!empty($save_data['standard'])) {
|
||||
$default_id = $iid;
|
||||
}
|
||||
|
||||
if ($_POST['_framed']) {
|
||||
// update the changed col in list
|
||||
$name = $save_data['name'] . ' <' . rcube_utils::idn_to_utf8($save_data['email']) .'>';
|
||||
$OUTPUT->command('parent.update_identity_row', $iid, rcube::Q(trim($name)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// show error message
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'errorsaving', 'error', null, false);
|
||||
$RCMAIL->overwrite_action('edit-identity');
|
||||
return;
|
||||
}
|
||||
}
|
||||
// insert a new identity record
|
||||
else if (IDENTITIES_LEVEL < 2) {
|
||||
if (IDENTITIES_LEVEL == 1) {
|
||||
$save_data['email'] = $RCMAIL->get_user_email();
|
||||
}
|
||||
|
||||
$plugin = $RCMAIL->plugins->exec_hook('identity_create', array('record' => $save_data));
|
||||
$save_data = $plugin['record'];
|
||||
|
||||
if ($save_data['email']) {
|
||||
$save_data['email'] = rcube_utils::idn_to_ascii($save_data['email']);
|
||||
}
|
||||
|
||||
if (!$plugin['abort'])
|
||||
$insert_id = $save_data['email'] ? $RCMAIL->user->insert_identity($save_data) : null;
|
||||
else
|
||||
$insert_id = $plugin['result'];
|
||||
|
||||
if ($insert_id) {
|
||||
$RCMAIL->plugins->exec_hook('identity_create_after', array('id' => $insert_id, 'record' => $save_data));
|
||||
|
||||
$OUTPUT->show_message('successfullysaved', 'confirmation', null, false);
|
||||
|
||||
$_GET['_iid'] = $insert_id;
|
||||
|
||||
if (!empty($save_data['standard'])) {
|
||||
$default_id = $insert_id;
|
||||
}
|
||||
|
||||
if ($_POST['_framed']) {
|
||||
// add a new row to the list
|
||||
$name = $save_data['name'] . ' <' . rcube_utils::idn_to_utf8($save_data['email']) .'>';
|
||||
$OUTPUT->command('parent.update_identity_row', $insert_id, rcube::Q(trim($name)), true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// show error message
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'errorsaving', 'error', null, false);
|
||||
$RCMAIL->overwrite_action('edit-identity');
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$OUTPUT->show_message('opnotpermitted', 'error');
|
||||
}
|
||||
|
||||
// mark all other identities as 'not-default'
|
||||
if ($default_id) {
|
||||
$RCMAIL->user->set_default($default_id);
|
||||
}
|
||||
|
||||
// go to next step
|
||||
if (!empty($_REQUEST['_framed'])) {
|
||||
$RCMAIL->overwrite_action('edit-identity');
|
||||
}
|
||||
else {
|
||||
$RCMAIL->overwrite_action('identities');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attach uploaded images into signature as data URIs
|
||||
*/
|
||||
function rcmail_attach_images($html)
|
||||
{
|
||||
global $RCMAIL;
|
||||
|
||||
$offset = 0;
|
||||
$regexp = '/\s(poster|src)\s*=\s*[\'"]*\S+upload-display\S+file=rcmfile(\w+)[\s\'"]*/';
|
||||
|
||||
while (preg_match($regexp, $html, $matches, 0, $offset)) {
|
||||
$file_id = $matches[2];
|
||||
$data_uri = ' ';
|
||||
|
||||
if ($file_id && ($file = $_SESSION['identity']['files'][$file_id])) {
|
||||
$file = $RCMAIL->plugins->exec_hook('attachment_get', $file);
|
||||
|
||||
$data_uri .= 'src="data:' . $file['mimetype'] . ';base64,';
|
||||
$data_uri .= base64_encode($file['data'] ?: file_get_contents($file['path']));
|
||||
$data_uri .= '" ';
|
||||
}
|
||||
|
||||
$html = str_replace($matches[0], $data_uri, $html);
|
||||
$offset += strlen($data_uri) - strlen($matches[0]) + 1;
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanity checks/cleanups on HTML body of signature
|
||||
*/
|
||||
function rcmail_wash_html($html)
|
||||
{
|
||||
// Add header with charset spec., washtml cannot work without that
|
||||
$html = '<html><head>'
|
||||
. '<meta http-equiv="Content-Type" content="text/html; charset='.RCUBE_CHARSET.'" />'
|
||||
. '</head><body>' . $html . '</body></html>';
|
||||
|
||||
// clean HTML with washhtml by Frederic Motte
|
||||
$wash_opts = array(
|
||||
'show_washed' => false,
|
||||
'allow_remote' => 1,
|
||||
'charset' => RCUBE_CHARSET,
|
||||
'html_elements' => array('body', 'link'),
|
||||
'html_attribs' => array('rel', 'type'),
|
||||
);
|
||||
|
||||
// initialize HTML washer
|
||||
$washer = new rcube_washtml($wash_opts);
|
||||
|
||||
//$washer->add_callback('form', 'rcmail_washtml_callback');
|
||||
//$washer->add_callback('style', 'rcmail_washtml_callback');
|
||||
|
||||
// Remove non-UTF8 characters (#1487813)
|
||||
$html = rcube_charset::clean($html);
|
||||
|
||||
$html = $washer->wash($html);
|
||||
|
||||
// remove unwanted comments and tags (produced by washtml)
|
||||
$html = preg_replace(array('/<!--[^>]+-->/', '/<\/?body>/'), '', $html);
|
||||
|
||||
return $html;
|
||||
}
|
223
data/web/rc/program/steps/settings/save_prefs.inc
Normal file
223
data/web/rc/program/steps/settings/save_prefs.inc
Normal file
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/settings/save_prefs.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2016, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Save user preferences to DB and to the current session |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$CURR_SECTION = rcube_utils::get_input_value('_section', rcube_utils::INPUT_POST);
|
||||
$a_user_prefs = array();
|
||||
|
||||
// set options for specified section
|
||||
switch ($CURR_SECTION) {
|
||||
case 'general':
|
||||
$a_user_prefs = array(
|
||||
'language' => isset($_POST['_language']) ? rcube_utils::get_input_value('_language', rcube_utils::INPUT_POST) : $CONFIG['language'],
|
||||
'timezone' => isset($_POST['_timezone']) ? rcube_utils::get_input_value('_timezone', rcube_utils::INPUT_POST) : $CONFIG['timezone'],
|
||||
'date_format' => isset($_POST['_date_format']) ? rcube_utils::get_input_value('_date_format', rcube_utils::INPUT_POST) : $CONFIG['date_format'],
|
||||
'time_format' => isset($_POST['_time_format']) ? rcube_utils::get_input_value('_time_format', rcube_utils::INPUT_POST) : ($CONFIG['time_format'] ? $CONFIG['time_format'] : 'H:i'),
|
||||
'prettydate' => isset($_POST['_pretty_date']),
|
||||
'refresh_interval' => isset($_POST['_refresh_interval']) ? intval($_POST['_refresh_interval'])*60 : $CONFIG['refresh_interval'],
|
||||
'standard_windows' => isset($_POST['_standard_windows']),
|
||||
'skin' => isset($_POST['_skin']) ? rcube_utils::get_input_value('_skin', rcube_utils::INPUT_POST) : $CONFIG['skin'],
|
||||
);
|
||||
|
||||
// compose derived date/time format strings
|
||||
if ((isset($_POST['_date_format']) || isset($_POST['_time_format'])) && $a_user_prefs['date_format'] && $a_user_prefs['time_format']) {
|
||||
$a_user_prefs['date_short'] = 'D ' . $a_user_prefs['time_format'];
|
||||
$a_user_prefs['date_long'] = $a_user_prefs['date_format'] . ' ' . $a_user_prefs['time_format'];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'mailbox':
|
||||
$a_user_prefs = array(
|
||||
'mail_read_time' => isset($_POST['_mail_read_time']) ? intval($_POST['_mail_read_time']) : $CONFIG['mail_read_time'],
|
||||
'autoexpand_threads' => isset($_POST['_autoexpand_threads']) ? intval($_POST['_autoexpand_threads']) : 0,
|
||||
'mdn_requests' => isset($_POST['_mdn_requests']) ? intval($_POST['_mdn_requests']) : 0,
|
||||
'check_all_folders' => isset($_POST['_check_all_folders']),
|
||||
'mail_pagesize' => is_numeric($_POST['_mail_pagesize']) ? max(2, intval($_POST['_mail_pagesize'])) : $CONFIG['mail_pagesize'],
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'mailview':
|
||||
$a_user_prefs = array(
|
||||
'message_extwin' => intval($_POST['_message_extwin']),
|
||||
'message_show_email' => isset($_POST['_message_show_email']),
|
||||
'prefer_html' => isset($_POST['_prefer_html']),
|
||||
'inline_images' => isset($_POST['_inline_images']),
|
||||
'show_images' => isset($_POST['_show_images']) ? intval($_POST['_show_images']) : 0,
|
||||
'display_next' => isset($_POST['_display_next']),
|
||||
'default_charset' => rcube_utils::get_input_value('_default_charset', rcube_utils::INPUT_POST),
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'compose':
|
||||
$a_user_prefs = array(
|
||||
'compose_extwin' => intval($_POST['_compose_extwin']),
|
||||
'htmleditor' => intval($_POST['_htmleditor']),
|
||||
'draft_autosave' => isset($_POST['_draft_autosave']) ? intval($_POST['_draft_autosave']) : 0,
|
||||
'mime_param_folding' => isset($_POST['_mime_param_folding']) ? intval($_POST['_mime_param_folding']) : 0,
|
||||
'force_7bit' => isset($_POST['_force_7bit']),
|
||||
'mdn_default' => isset($_POST['_mdn_default']),
|
||||
'dsn_default' => isset($_POST['_dsn_default']),
|
||||
'reply_same_folder' => isset($_POST['_reply_same_folder']),
|
||||
'spellcheck_before_send' => isset($_POST['_spellcheck_before_send']),
|
||||
'spellcheck_ignore_syms' => isset($_POST['_spellcheck_ignore_syms']),
|
||||
'spellcheck_ignore_nums' => isset($_POST['_spellcheck_ignore_nums']),
|
||||
'spellcheck_ignore_caps' => isset($_POST['_spellcheck_ignore_caps']),
|
||||
'show_sig' => isset($_POST['_show_sig']) ? intval($_POST['_show_sig']) : 1,
|
||||
'reply_mode' => isset($_POST['_reply_mode']) ? intval($_POST['_reply_mode']) : 0,
|
||||
'sig_below' => isset($_POST['_sig_below']),
|
||||
'strip_existing_sig' => isset($_POST['_strip_existing_sig']),
|
||||
'sig_separator' => isset($_POST['_sig_separator']),
|
||||
'default_font' => rcube_utils::get_input_value('_default_font', rcube_utils::INPUT_POST),
|
||||
'default_font_size' => rcube_utils::get_input_value('_default_font_size', rcube_utils::INPUT_POST),
|
||||
'reply_all_mode' => intval($_POST['_reply_all_mode']),
|
||||
'forward_attachment' => !empty($_POST['_forward_attachment']),
|
||||
'compose_save_localstorage' => intval($_POST['_compose_save_localstorage']),
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'addressbook':
|
||||
$a_user_prefs = array(
|
||||
'default_addressbook' => rcube_utils::get_input_value('_default_addressbook', rcube_utils::INPUT_POST, true),
|
||||
'autocomplete_single' => isset($_POST['_autocomplete_single']),
|
||||
'addressbook_sort_col' => rcube_utils::get_input_value('_addressbook_sort_col', rcube_utils::INPUT_POST),
|
||||
'addressbook_name_listing' => intval(rcube_utils::get_input_value('_addressbook_name_listing', rcube_utils::INPUT_POST)),
|
||||
'addressbook_pagesize' => is_numeric($_POST['_addressbook_pagesize']) ? max(2, intval($_POST['_addressbook_pagesize'])) : $CONFIG['addressbook_pagesize'],
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'server':
|
||||
$a_user_prefs = array(
|
||||
'read_when_deleted' => isset($_POST['_read_when_deleted']),
|
||||
'skip_deleted' => isset($_POST['_skip_deleted']),
|
||||
'flag_for_deletion' => isset($_POST['_flag_for_deletion']),
|
||||
'delete_always' => isset($_POST['_delete_always']),
|
||||
'delete_junk' => isset($_POST['_delete_junk']),
|
||||
'logout_purge' => isset($_POST['_logout_purge']),
|
||||
'logout_expunge' => isset($_POST['_logout_expunge']),
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'folders':
|
||||
$a_user_prefs = array(
|
||||
'show_real_foldernames' => isset($_POST['_show_real_foldernames']),
|
||||
// stop using SPECIAL-USE (#4782)
|
||||
'lock_special_folders' => !in_array('lock_special_folders', (array) $CONFIG['dont_override']),
|
||||
);
|
||||
|
||||
foreach (rcube_storage::$folder_types as $type) {
|
||||
$a_user_prefs[$type . '_mbox'] = rcube_utils::get_input_value('_' . $type . '_mbox', rcube_utils::INPUT_POST, true);
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$plugin = rcmail::get_instance()->plugins->exec_hook('preferences_save',
|
||||
array('prefs' => $a_user_prefs, 'section' => $CURR_SECTION));
|
||||
|
||||
$a_user_prefs = $plugin['prefs'];
|
||||
|
||||
// don't override these parameters
|
||||
foreach ((array)$CONFIG['dont_override'] as $p) {
|
||||
$a_user_prefs[$p] = $CONFIG[$p];
|
||||
}
|
||||
|
||||
|
||||
// verify some options
|
||||
switch ($CURR_SECTION) {
|
||||
case 'general':
|
||||
// switch UI language
|
||||
if (isset($_POST['_language']) && $a_user_prefs['language'] != $_SESSION['language']) {
|
||||
$RCMAIL->load_language($a_user_prefs['language']);
|
||||
$OUTPUT->command('reload', 500);
|
||||
}
|
||||
|
||||
// switch skin (if valid, otherwise unset the pref and fall back to default)
|
||||
if (!$OUTPUT->set_skin($a_user_prefs['skin']))
|
||||
unset($a_user_prefs['skin']);
|
||||
else if ($RCMAIL->config->get('skin') != $a_user_prefs['skin'])
|
||||
$OUTPUT->command('reload', 500);
|
||||
|
||||
$a_user_prefs['timezone'] = (string) $a_user_prefs['timezone'];
|
||||
|
||||
if (!empty($a_user_prefs['refresh_interval']) && !empty($CONFIG['min_refresh_interval'])) {
|
||||
if ($a_user_prefs['refresh_interval'] < $CONFIG['min_refresh_interval']) {
|
||||
$a_user_prefs['refresh_interval'] = $CONFIG['min_refresh_interval'];
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'mailbox':
|
||||
// force min size
|
||||
if ($a_user_prefs['mail_pagesize'] < 1) {
|
||||
$a_user_prefs['mail_pagesize'] = 10;
|
||||
}
|
||||
|
||||
if (isset($CONFIG['max_pagesize']) && ($a_user_prefs['mail_pagesize'] > $CONFIG['max_pagesize'])) {
|
||||
$a_user_prefs['mail_pagesize'] = (int) $CONFIG['max_pagesize'];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'addressbook':
|
||||
// force min size
|
||||
if ($a_user_prefs['addressbook_pagesize'] < 1) {
|
||||
$a_user_prefs['addressbook_pagesize'] = 10;
|
||||
}
|
||||
|
||||
if (isset($CONFIG['max_pagesize']) && ($a_user_prefs['addressbook_pagesize'] > $CONFIG['max_pagesize'])) {
|
||||
$a_user_prefs['addressbook_pagesize'] = (int) $CONFIG['max_pagesize'];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'folders':
|
||||
$storage = $RCMAIL->get_storage();
|
||||
$specials = array();
|
||||
|
||||
foreach (rcube_storage::$folder_types as $type) {
|
||||
$specials[$type] = $a_user_prefs[$type . '_mbox'];
|
||||
}
|
||||
|
||||
$storage->set_special_folders($specials);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Save preferences
|
||||
if (!$plugin['abort'])
|
||||
$saved = $RCMAIL->user->save_prefs($a_user_prefs);
|
||||
else
|
||||
$saved = $plugin['result'];
|
||||
|
||||
if ($saved)
|
||||
$OUTPUT->show_message('successfullysaved', 'confirmation');
|
||||
else
|
||||
$OUTPUT->show_message($plugin['message'] ?: 'errorsaving', 'error');
|
||||
|
||||
// display the form again
|
||||
$RCMAIL->overwrite_action('edit-prefs');
|
144
data/web/rc/program/steps/settings/upload.inc
Normal file
144
data/web/rc/program/steps/settings/upload.inc
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/settings/upload.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2014, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Handles image uploads |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// Upload progress update
|
||||
if (!empty($_GET['_progress'])) {
|
||||
$RCMAIL->upload_progress();
|
||||
}
|
||||
|
||||
$from = rcube_utils::get_input_value('_from', rcube_utils::INPUT_GET);
|
||||
$type = preg_replace('/(add|edit)-/', '', $from);
|
||||
|
||||
if ($RCMAIL->action == 'upload-display') {
|
||||
$id = 'undefined';
|
||||
|
||||
if (preg_match('/^rcmfile(\w+)$/', $_GET['_file'], $regs)) {
|
||||
$id = $regs[1];
|
||||
}
|
||||
|
||||
$RCMAIL->display_uploaded_file($_SESSION[$type]['files'][$id]);
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
// Supported image format types
|
||||
$IMAGE_TYPES = explode(',', 'jpeg,jpg,jp2,tiff,tif,bmp,eps,gif,png,png8,png24,png32,svg,ico');
|
||||
|
||||
// clear all stored output properties (like scripts and env vars)
|
||||
$OUTPUT->reset();
|
||||
|
||||
$max_size = $RCMAIL->config->get($type . '_image_size', 64) * 1024;
|
||||
$post_size = $RCMAIL->show_bytes(rcube_utils::max_upload_size());
|
||||
$uploadid = rcube_utils::get_input_value('_uploadid', rcube_utils::INPUT_GET);
|
||||
|
||||
|
||||
if (is_array($_FILES['_file']['tmp_name'])) {
|
||||
$multiple = count($_FILES['_file']['tmp_name']) > 1;
|
||||
|
||||
foreach ($_FILES['_file']['tmp_name'] as $i => $filepath) {
|
||||
// Process uploaded attachment if there is no error
|
||||
$err = $_FILES['_file']['error'][$i];
|
||||
|
||||
if (!$err) {
|
||||
if ($max_size < $_FILES['_file']['size'][$i]) {
|
||||
$err = 'size_error';
|
||||
}
|
||||
// check image file type
|
||||
else {
|
||||
$image = new rcube_image($filepath);
|
||||
$imageprop = $image->props();
|
||||
|
||||
if (!in_array(strtolower($imageprop['type']), $IMAGE_TYPES)) {
|
||||
$err = 'type_error';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// save uploaded image in storage backend
|
||||
if (!$err) {
|
||||
$attachment = $RCMAIL->plugins->exec_hook('attachment_upload', array(
|
||||
'path' => $filepath,
|
||||
'size' => $_FILES['_file']['size'][$i],
|
||||
'name' => $_FILES['_file']['name'][$i],
|
||||
'mimetype' => 'image/' . $imageprop['type'],
|
||||
'group' => $type,
|
||||
));
|
||||
}
|
||||
|
||||
if (!$err && $attachment['status'] && !$attachment['abort']) {
|
||||
$id = $attachment['id'];
|
||||
|
||||
// store new file in session
|
||||
unset($attachment['status'], $attachment['abort']);
|
||||
$RCMAIL->session->append($type . '.files', $id, $attachment);
|
||||
|
||||
$content = rcube::Q($attachment['name']);
|
||||
|
||||
$OUTPUT->command('add2attachment_list', "rcmfile$id", array(
|
||||
'html' => $content,
|
||||
'name' => $attachment['name'],
|
||||
'mimetype' => $attachment['mimetype'],
|
||||
'classname' => rcube_utils::file2class($attachment['mimetype'], $attachment['name']),
|
||||
'complete' => true
|
||||
),
|
||||
$uploadid
|
||||
);
|
||||
}
|
||||
else {
|
||||
if ($err == 'type_error') {
|
||||
$msg = $RCMAIL->gettext('invalidimageformat');
|
||||
}
|
||||
else if ($err == 'size_error') {
|
||||
$msg = $RCMAIL->gettext(array('name' => 'filesizeerror', 'vars' => array('size' => $max_size)));
|
||||
}
|
||||
else if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
|
||||
$msg = $RCMAIL->gettext(array('name' => 'filesizeerror', 'vars' => array('size' => $post_size)));
|
||||
}
|
||||
else if ($attachment['error']) {
|
||||
$msg = $attachment['error'];
|
||||
}
|
||||
else {
|
||||
$msg = $RCMAIL->gettext('fileuploaderror');
|
||||
}
|
||||
|
||||
$OUTPUT->command('display_message', $msg, 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
// if filesize exceeds post_max_size then $_FILES array is empty,
|
||||
// show filesizeerror instead of fileuploaderror
|
||||
if ($maxsize = ini_get('post_max_size')) {
|
||||
$msg = $RCMAIL->gettext(array(
|
||||
'name' => 'filesizeerror',
|
||||
'vars' => array('size' => $RCMAIL->show_bytes(parse_bytes($maxsize)))
|
||||
));
|
||||
}
|
||||
else {
|
||||
$msg = $RCMAIL->gettext('fileuploaderror');
|
||||
}
|
||||
|
||||
$OUTPUT->command('display_message', $msg, 'error');
|
||||
$OUTPUT->command('remove_from_attachment_list', $uploadid);
|
||||
}
|
||||
|
||||
$OUTPUT->send('iframe');
|
168
data/web/rc/program/steps/utils/error.inc
Normal file
168
data/web/rc/program/steps/utils/error.inc
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/utils/error.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2015, 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: |
|
||||
| Display error message page |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
// browser is not compatible with this application
|
||||
if ($ERROR_CODE == 409) {
|
||||
$user_agent = htmlentities($_SERVER['HTTP_USER_AGENT']);
|
||||
$__error_title = 'Your browser does not suit the requirements for this application';
|
||||
$__error_text = <<<EOF
|
||||
<i>Supported browsers:</i><br />
|
||||
» Microsoft Internet Explorer 7+<br />
|
||||
» Mozilla Firefox 3+<br />
|
||||
» Chrome 10+<br />
|
||||
» Safari 4+<br />
|
||||
» Opera 8+<br />
|
||||
<br />
|
||||
» JavaScript enabled<br />
|
||||
» Support for XMLHTTPRequest<br />
|
||||
|
||||
<p><i>Your configuration:</i><br />
|
||||
$user_agent</p>
|
||||
EOF;
|
||||
}
|
||||
|
||||
// authorization error
|
||||
else if ($ERROR_CODE == 401) {
|
||||
$__error_title = mb_strtoupper($rcmail->gettext('errauthorizationfailed'));
|
||||
$__error_text = nl2br($rcmail->gettext('errunauthorizedexplain') . "\n" .
|
||||
$rcmail->gettext('errcontactserveradmin'));
|
||||
}
|
||||
|
||||
// forbidden due to request check
|
||||
else if ($ERROR_CODE == 403) {
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'GET' && $rcmail->request_status == rcube::REQUEST_ERROR_URL) {
|
||||
$url = $rcmail->url($_GET, true, false, true);
|
||||
$add = html::a($url, $rcmail->gettext('clicktoresumesession'));
|
||||
}
|
||||
else {
|
||||
$add = $rcmail->gettext('errcontactserveradmin');
|
||||
}
|
||||
|
||||
$__error_title = mb_strtoupper($rcmail->gettext('errrequestcheckfailed'));
|
||||
$__error_text = nl2br($rcmail->gettext('errcsrfprotectionexplain')) . '<p>' . $add . '</p>';
|
||||
}
|
||||
|
||||
// failed request (wrong step in URL)
|
||||
else if ($ERROR_CODE == 404) {
|
||||
$request_url = htmlentities($_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
|
||||
$__error_title = mb_strtoupper($rcmail->gettext('errnotfound'));
|
||||
$__error_text = nl2br($rcmail->gettext('errnotfoundexplain') . "\n" .
|
||||
$rcmail->gettext('errcontactserveradmin'));
|
||||
|
||||
$__error_text .= '<p><i>' . $rcmail->gettext('errfailedrequest') . ":</i><br />\n<tt>//$request_url</tt></p>";
|
||||
}
|
||||
|
||||
// invalid compose ID
|
||||
else if ($ERROR_CODE == 450 && $_SERVER['REQUEST_METHOD'] == 'GET' && $rcmail->action == 'compose') {
|
||||
$url = $rcmail->url('compose');
|
||||
|
||||
$__error_title = mb_strtoupper($rcmail->gettext('errcomposesession'));
|
||||
$__error_text = nl2br($rcmail->gettext('errcomposesessionexplain'))
|
||||
. '<p>' . html::a($url, $rcmail->gettext('clicktocompose')) . '</p>';
|
||||
}
|
||||
|
||||
// database connection error
|
||||
else if ($ERROR_CODE == 601) {
|
||||
$__error_title = "CONFIGURATION ERROR";
|
||||
$__error_text = nl2br($ERROR_MESSAGE) . "<br />Please read the INSTALL instructions!";
|
||||
}
|
||||
|
||||
// database connection error
|
||||
else if ($ERROR_CODE == 603) {
|
||||
$__error_title = "DATABASE ERROR: CONNECTION FAILED!";
|
||||
$__error_text = "Unable to connect to the database!<br />Please contact your server-administrator.";
|
||||
}
|
||||
|
||||
// system error
|
||||
else {
|
||||
$__error_title = "SERVICE CURRENTLY NOT AVAILABLE!";
|
||||
$__error_text = "Please contact your server-administrator.";
|
||||
|
||||
if (($rcmail->config->get('debug_level') & 4) && $ERROR_MESSAGE) {
|
||||
$__error_text = $ERROR_MESSAGE;
|
||||
}
|
||||
else {
|
||||
$__error_text = sprintf('Error No. [%s]', $ERROR_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
// inform plugins
|
||||
if ($rcmail && $rcmail->plugins) {
|
||||
$plugin = $rcmail->plugins->exec_hook('error_page', array(
|
||||
'code' => $ERROR_CODE,
|
||||
'title' => $__error_title,
|
||||
'text' => $__error_text,
|
||||
));
|
||||
|
||||
if (!empty($plugin['title']))
|
||||
$__error_title = $plugin['title'];
|
||||
if (!empty($plugin['text']))
|
||||
$__error_text = $plugin['text'];
|
||||
}
|
||||
|
||||
$HTTP_ERR_CODE = $ERROR_CODE && $ERROR_CODE < 600 ? $ERROR_CODE : 500;
|
||||
|
||||
// Ajax request
|
||||
if ($rcmail->output && $rcmail->output->type == 'js') {
|
||||
header("HTTP/1.0 $HTTP_ERR_CODE $__error_title");
|
||||
die;
|
||||
}
|
||||
|
||||
// compose page content
|
||||
$__page_content = <<<EOF
|
||||
<div>
|
||||
<h3 class="error-title">$__error_title</h3>
|
||||
<div class="error-text">$__error_text</div>
|
||||
</div>
|
||||
EOF;
|
||||
|
||||
if ($rcmail->output && $rcmail->output->template_exists('error')) {
|
||||
$rcmail->output->reset();
|
||||
$rcmail->output->set_env('server_error', $ERROR_CODE);
|
||||
$rcmail->output->set_env('comm_path', $rcmail->comm_path);
|
||||
$rcmail->output->send('error');
|
||||
}
|
||||
|
||||
$__skin = $rcmail->config->get('skin', 'default');
|
||||
$__productname = $rcmail->config->get('product_name', 'Roundcube Webmail');
|
||||
|
||||
// print system error page
|
||||
print <<<EOF
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head>
|
||||
<title>$__productname :: ERROR</title>
|
||||
<link rel="stylesheet" type="text/css" href="skins/$__skin/common.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table border="0" cellsapcing="0" cellpadding="0" width="100%" height="80%"><tr><td align="center">
|
||||
|
||||
$__page_content
|
||||
|
||||
</td></tr></table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
EOF;
|
||||
|
||||
exit;
|
31
data/web/rc/program/steps/utils/html2text.inc
Normal file
31
data/web/rc/program/steps/utils/html2text.inc
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/utils/html2text.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2015, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Convert HTML message to plain text |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$html = stream_get_contents(fopen('php://input', 'r'));
|
||||
|
||||
$params['links'] = (bool) rcube_utils::get_input_value('_do_links', rcube_utils::INPUT_GET);
|
||||
$params['width'] = (int) rcube_utils::get_input_value('_width', rcube_utils::INPUT_GET);
|
||||
|
||||
$text = $RCMAIL->html2text($html, $params);
|
||||
|
||||
header('Content-Type: text/plain; charset=' . RCUBE_CHARSET);
|
||||
print $text;
|
||||
exit;
|
55
data/web/rc/program/steps/utils/killcache.inc
Normal file
55
data/web/rc/program/steps/utils/killcache.inc
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/utils/killcache.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2010, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Delete rows from cache tables |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Dennis P. Nikolaenko <dennis@nikolaenko.ru> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// don't allow public access if not in devel_mode
|
||||
if (!$RCMAIL->config->get('devel_mode')) {
|
||||
header("HTTP/1.0 401 Access denied");
|
||||
die("Access denied!");
|
||||
}
|
||||
|
||||
// @TODO: transaction here (if supported by DB) would be a good thing
|
||||
$res = $RCMAIL->db->query("DELETE FROM " . $RCMAIL->db->table_name('cache', true));
|
||||
if ($err = $RCMAIL->db->is_error($res)) {
|
||||
exit($err);
|
||||
}
|
||||
|
||||
$res = $RCMAIL->db->query("DELETE FROM " . $RCMAIL->db->table_name('cache_shared', true));
|
||||
if ($err = $RCMAIL->db->is_error($res)) {
|
||||
exit($err);
|
||||
}
|
||||
|
||||
$res = $RCMAIL->db->query("DELETE FROM " . $RCMAIL->db->table_name('cache_messages', true));
|
||||
if ($err = $RCMAIL->db->is_error($res)) {
|
||||
exit($err);
|
||||
}
|
||||
|
||||
$res = $RCMAIL->db->query("DELETE FROM " . $RCMAIL->db->table_name('cache_index', true));
|
||||
if ($err = $RCMAIL->db->is_error($res)) {
|
||||
exit($err);
|
||||
}
|
||||
|
||||
$res = $RCMAIL->db->query("DELETE FROM " . $RCMAIL->db->table_name('cache_thread', true));
|
||||
if ($err = $RCMAIL->db->is_error($res)) {
|
||||
exit($err);
|
||||
}
|
||||
|
||||
echo "Cache cleared\n";
|
||||
exit;
|
83
data/web/rc/program/steps/utils/modcss.inc
Normal file
83
data/web/rc/program/steps/utils/modcss.inc
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/utils/modcss.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2007-2014, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Modify CSS source from a URL |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$url = preg_replace('![^a-z0-9.-]!i', '', $_GET['_u']);
|
||||
|
||||
if ($url === null || !($realurl = $_SESSION['modcssurls'][$url])) {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
exit("Unauthorized request");
|
||||
}
|
||||
|
||||
// don't allow any other connections than http(s)
|
||||
if (!preg_match('~^(https?)://~i', $realurl, $matches)) {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
exit("Invalid URL");
|
||||
}
|
||||
|
||||
if (ini_get('allow_url_fopen')) {
|
||||
$scheme = strtolower($matches[1]);
|
||||
$options = array(
|
||||
$scheme => array(
|
||||
'method' => 'GET',
|
||||
'timeout' => 15,
|
||||
)
|
||||
);
|
||||
|
||||
$context = stream_context_create($options);
|
||||
$source = @file_get_contents($realurl, false, $context);
|
||||
|
||||
// php.net/manual/en/reserved.variables.httpresponseheader.php
|
||||
$headers = implode("\n", (array) $http_response_header);
|
||||
}
|
||||
else if (function_exists('curl_init')) {
|
||||
$curl = curl_init($realurl);
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, 15);
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 15);
|
||||
curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
|
||||
curl_setopt($curl, CURLOPT_ENCODING, '');
|
||||
curl_setopt($curl, CURLOPT_HEADER, true);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
$data = curl_exec($curl);
|
||||
|
||||
if ($data !== false) {
|
||||
list($headers, $source) = explode("\r\n\r\n", $data, 2);
|
||||
}
|
||||
else {
|
||||
$headers = false;
|
||||
$source = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
exit("HTTP connections disabled");
|
||||
}
|
||||
|
||||
$ctype_regexp = '~Content-Type:\s+text/(css|plain)~i';
|
||||
|
||||
if ($source !== false && preg_match($ctype_regexp, $headers)) {
|
||||
header('Content-Type: text/css');
|
||||
echo rcube_utils::mod_css_styles($source, preg_replace('/[^a-z0-9]/i', '', $_GET['_c']));
|
||||
exit;
|
||||
}
|
||||
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
exit("Invalid response returned by server");
|
68
data/web/rc/program/steps/utils/save_pref.inc
Normal file
68
data/web/rc/program/steps/utils/save_pref.inc
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/utils/save_pref.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2013, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Save preferences setting in database |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$name = rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST);
|
||||
$value = rcube_utils::get_input_value('_value', rcube_utils::INPUT_POST);
|
||||
$sessname = rcube_utils::get_input_value('_session', rcube_utils::INPUT_POST);
|
||||
|
||||
// Whitelisted preferences and session variables, others
|
||||
// can be added by plugins
|
||||
$whitelist = array(
|
||||
'list_cols',
|
||||
'collapsed_folders',
|
||||
'collapsed_abooks',
|
||||
);
|
||||
$whitelist_sess = array(
|
||||
'list_attrib/columns',
|
||||
);
|
||||
|
||||
$whitelist = array_merge($whitelist, $RCMAIL->plugins->allowed_prefs);
|
||||
$whitelist_sess = array_merge($whitelist_sess, $RCMAIL->plugins->allowed_session_prefs);
|
||||
|
||||
if (!in_array($name, $whitelist) || ($sessname && !in_array($sessname, $whitelist_sess))) {
|
||||
rcube::raise_error(array('code' => 500, 'type' => 'php',
|
||||
'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => sprintf("Hack attempt detected (user: %s)", $RCMAIL->get_user_name())),
|
||||
true, false);
|
||||
|
||||
$OUTPUT->reset();
|
||||
$OUTPUT->send();
|
||||
}
|
||||
|
||||
// save preference value
|
||||
$RCMAIL->user->save_prefs(array($name => $value));
|
||||
|
||||
// update also session if requested
|
||||
if ($sessname) {
|
||||
// Support multidimensional arrays...
|
||||
$vars = explode('/', $sessname);
|
||||
|
||||
// ... up to 3 levels
|
||||
if (count($vars) == 1)
|
||||
$_SESSION[$vars[0]] = $value;
|
||||
else if (count($vars) == 2)
|
||||
$_SESSION[$vars[0]][$vars[1]] = $value;
|
||||
else if (count($vars) == 3)
|
||||
$_SESSION[$vars[0]][$vars[1]][$vars[2]] = $value;
|
||||
}
|
||||
|
||||
$OUTPUT->reset();
|
||||
$OUTPUT->send();
|
64
data/web/rc/program/steps/utils/spell.inc
Normal file
64
data/web/rc/program/steps/utils/spell.inc
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/utils/spell.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2011, 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: |
|
||||
| Invoke the configured or default spell checking engine. |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Kris Steinhoff <steinhof@umich.edu> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
// read input
|
||||
$lang = rcube_utils::get_input_value('lang', rcube_utils::INPUT_GET);
|
||||
$data = file_get_contents('php://input');
|
||||
|
||||
$learn_word = strpos($data, '<learnword>');
|
||||
|
||||
// Get data string
|
||||
$left = strpos($data, '<text>');
|
||||
$right = strrpos($data, '</text>');
|
||||
$data = substr($data, $left+6, $right-($left+6));
|
||||
$data = html_entity_decode($data, ENT_QUOTES, RCUBE_CHARSET);
|
||||
|
||||
$spellchecker = new rcube_spellchecker($lang);
|
||||
|
||||
if ($learn_word) {
|
||||
$spellchecker->add_word($data);
|
||||
$result = '<?xml version="1.0" encoding="'.RCUBE_CHARSET.'"?><learnwordresult></learnwordresult>';
|
||||
}
|
||||
else if (empty($data)) {
|
||||
$result = '<?xml version="1.0" encoding="'.RCUBE_CHARSET.'"?><spellresult charschecked="0"></spellresult>';
|
||||
}
|
||||
else {
|
||||
$spellchecker->check($data);
|
||||
$result = $spellchecker->get_xml();
|
||||
}
|
||||
|
||||
if ($err = $spellchecker->error()) {
|
||||
rcube::raise_error(array('code' => 500, 'type' => 'php',
|
||||
'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Spell check engine error: " . trim($err)),
|
||||
true, false);
|
||||
|
||||
header("HTTP/1.0 500 Internal Server Error");
|
||||
exit;
|
||||
}
|
||||
|
||||
// set response length
|
||||
header("Content-Length: " . strlen($result));
|
||||
|
||||
// Don't use server's default Content-Type charset (#1486406)
|
||||
header("Content-Type: text/xml; charset=" . RCUBE_CHARSET);
|
||||
print $result;
|
||||
exit;
|
57
data/web/rc/program/steps/utils/spell_html.inc
Normal file
57
data/web/rc/program/steps/utils/spell_html.inc
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/utils/spell_html.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2011, 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: |
|
||||
| Spellchecker for TinyMCE |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Aleksander Machniak <alec@alec.pl> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$method = rcube_utils::get_input_value('method', rcube_utils::INPUT_POST);
|
||||
$lang = rcube_utils::get_input_value('lang', rcube_utils::INPUT_POST);
|
||||
$result = array();
|
||||
|
||||
$spellchecker = new rcube_spellchecker($lang);
|
||||
|
||||
if ($method == 'addToDictionary') {
|
||||
$data = rcube_utils::get_input_value('word', rcube_utils::INPUT_POST);
|
||||
|
||||
$spellchecker->add_word($data);
|
||||
$result['result'] = true;
|
||||
}
|
||||
else {
|
||||
$data = rcube_utils::get_input_value('text', rcube_utils::INPUT_POST, true);
|
||||
$data = html_entity_decode($data, ENT_QUOTES, RCUBE_CHARSET);
|
||||
|
||||
if ($data && !$spellchecker->check($data)) {
|
||||
$result['words'] = $spellchecker->get();
|
||||
$result['dictionary'] = (bool) $RCMAIL->config->get('spellcheck_dictionary');
|
||||
}
|
||||
}
|
||||
|
||||
if ($error = $spellchecker->error()) {
|
||||
rcube::raise_error(array('code' => 500, 'type' => 'php',
|
||||
'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => sprintf("Spell check engine error: " . $error)),
|
||||
true, false);
|
||||
|
||||
echo json_encode(array('error' => $error));
|
||||
exit;
|
||||
}
|
||||
|
||||
// send output
|
||||
header("Content-Type: application/json; charset=".RCUBE_CHARSET);
|
||||
echo json_encode($result);
|
||||
exit;
|
28
data/web/rc/program/steps/utils/text2html.inc
Normal file
28
data/web/rc/program/steps/utils/text2html.inc
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/steps/utils/text2html.inc |
|
||||
| |
|
||||
| This file is part of the Roundcube Webmail client |
|
||||
| Copyright (C) 2005-2014, The Roundcube Dev Team |
|
||||
| |
|
||||
| Licensed under the GNU General Public License version 3 or |
|
||||
| any later version with exceptions for skins & plugins. |
|
||||
| See the README file for a full license statement. |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Convert plain text to HTML |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
$text = stream_get_contents(fopen('php://input', 'r'));
|
||||
|
||||
$converter = new rcube_text2html($text, false, array('wrap' => true));
|
||||
|
||||
header('Content-Type: text/html; charset=' . RCUBE_CHARSET);
|
||||
print $converter->get_html();
|
||||
exit;
|
Reference in New Issue
Block a user