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');
|
Reference in New Issue
Block a user