- Added searching in all addressbook sources (global-search)

- Added addressbook source selection in contacts import
release-0.6
alecpl 13 years ago
parent 6f3fa964c6
commit ecf295f6ef

@ -1,6 +1,8 @@
CHANGELOG Roundcube Webmail
===========================
- Added searching in all addressbook sources
- Added addressbook source selection in contacts import
- Implement LDAPv3 Virtual List View (VLV) for paged results listing
- Use 'address_template' config option when adding a new address block (#1487944)
- Added addressbook advanced search

@ -450,6 +450,7 @@ $rcmail_config['address_book_type'] = 'sql';
// In order to enable public ldap search, configure an array like the Verisign
// example further below. if you would like to test, simply uncomment the example.
// Array key must contain only safe characters, ie. a-zA-Z0-9_
$rcmail_config['ldap_public'] = array();
// If you are going to use LDAP for individual address books, you will need to

@ -336,7 +336,7 @@ function rcube_webmail()
if (this.contact_list && this.contact_list.rowcount > 0)
this.enable_command('export', true);
this.enable_command('add', 'import', !this.env.readonly);
this.enable_command('add', 'import', this.env.writable_source);
this.enable_command('list', 'listgroup', 'advanced-search', true);
break;
@ -529,12 +529,12 @@ function rcube_webmail()
if (this.env.trash_mailbox)
this.set_alttext('delete', this.env.mailbox != this.env.trash_mailbox ? 'movemessagetotrash' : 'deletemessage');
}
else if (this.task=='addressbook') {
else if (this.task == 'addressbook') {
if (!this.env.search_request || (props != this.env.source))
this.reset_qsearch();
this.list_contacts(props);
this.enable_command('add', 'import', (this.env.address_sources && !this.env.address_sources[this.env.source].readonly));
this.enable_command('add', 'import', this.env.writable_source);
}
break;
@ -988,8 +988,14 @@ function rcube_webmail()
if (s && this.env.mailbox)
this.list_mailbox(this.env.mailbox);
else if (s && this.task == 'addressbook')
else if (s && this.task == 'addressbook') {
if (this.env.source == '') {
for (var n in this.env.address_sources) break;
this.env.source = n;
this.env.group = '';
}
this.list_contacts(this.env.source, this.env.group);
}
break;
case 'listgroup':
@ -3651,15 +3657,34 @@ function rcube_webmail()
if (this.preview_timer)
clearTimeout(this.preview_timer);
var id, frame, ref = this;
var n, id, sid, ref = this, writable = false,
source = this.env.source ? this.env.address_sources[this.env.source] : null;
if (id = list.get_single_selection())
this.preview_timer = window.setTimeout(function(){ ref.load_contact(id, 'show'); }, 200);
else if (this.env.contentframe)
this.show_contentframe(false);
// no source = search result, we'll need to detect if any of
// selected contacts are in writable addressbook to enable edit/delete
if (list.selection.length) {
if (!source) {
for (n in list.selection) {
sid = String(list.selection[n]).replace(/^[^-]+-/, '');
if (sid && this.env.address_sources[sid] && !this.env.address_sources[sid].readonly) {
writable = true;
break;
}
}
}
else {
writable = !source.readonly;
}
}
this.enable_command('compose', list.selection.length > 0);
this.enable_command('edit', (id && this.env.address_sources && !this.env.address_sources[this.env.source].readonly) ? true : false);
this.enable_command('delete', list.selection.length && this.env.address_sources && !this.env.address_sources[this.env.source].readonly);
this.enable_command('edit', id && writable);
this.enable_command('delete', list.selection.length && writable);
return false;
};
@ -3797,12 +3822,12 @@ function rcube_webmail()
if (!(selection.length || this.env.cid) || !confirm(this.get_label('deletecontactconfirm')))
return;
var id, a_cids = [], qs = '';
var id, n, a_cids = [], qs = '';
if (this.env.cid)
a_cids.push(this.env.cid);
else {
for (var n=0; n<selection.length; n++) {
for (n=0; n<selection.length; n++) {
id = selection[n];
a_cids.push(id);
this.contact_list.remove_row(id, (n == selection.length-1));
@ -3817,7 +3842,7 @@ function rcube_webmail()
qs += '&_gid='+urlencode(this.env.group);
// also send search request to get the right records from the next page
if (this.env.search_request)
if (this.env.search_request)
qs += '&_search='+this.env.search_request;
// send request to server
@ -4119,7 +4144,7 @@ function rcube_webmail()
for (childcol in colprop.childs)
cols.push(childcol);
}
for (var i=0; i < cols.length; i++) {
childcol = cols[i];
cp = colprop.childs[childcol];
@ -4241,16 +4266,22 @@ function rcube_webmail()
target = window.frames[this.env.contentframe];
this.contact_list.clear_selection();
}
else if (framed)
return false;
this.location_href(this.env.comm_path+'&_action=search'+add_url
+'&_source='+urlencode(this.env.source)
+(this.env.group ? '&_gid='+urlencode(this.env.group) : ''), target);
this.location_href(this.env.comm_path+'&_action=search'+add_url, target);
return true;
};
// unselect directory/group
this.unselect_directory = function()
{
if (this.env.address_sources.length > 1 || this.env.group != '') {
this.select_folder('', (this.env.group ? 'G'+this.env.source+this.env.group : this.env.source));
this.env.group = '';
this.env.source = '';
}
};
/*********************************************************/
/********* user settings methods *********/
@ -5468,9 +5499,20 @@ function rcube_webmail()
switch (response.action) {
case 'delete':
if (this.task == 'addressbook') {
var uid = this.contact_list.get_selection();
var sid, uid = this.contact_list.get_selection(), writable = false;
if (uid && this.contact_list.rows[uid]) {
// search results, get source ID from record ID
if (this.env.source == '') {
sid = String(uid).replace(/^[^-]+-/, '');
writable = sid && this.env.address_sources[sid] && !this.env.address_sources[sid].readonly;
}
else {
writable = !this.env.address_sources[this.env.source].readonly;
}
}
this.enable_command('compose', (uid && this.contact_list.rows[uid]));
this.enable_command('delete', 'edit', (uid && this.contact_list.rows[uid] && this.env.address_sources && !this.env.address_sources[this.env.source].readonly));
this.enable_command('delete', 'edit', writable);
this.enable_command('export', (this.contact_list && this.contact_list.rowcount > 0));
}
@ -5519,10 +5561,9 @@ function rcube_webmail()
this.enable_command('export', (this.contact_list && this.contact_list.rowcount > 0));
if (response.action == 'list' || response.action == 'search') {
this.enable_command('group-create',
(this.env.address_sources[this.env.source].groups && !this.env.address_sources[this.env.source].readonly));
this.enable_command('group-rename', 'group-delete',
(this.env.address_sources[this.env.source].groups && this.env.group && !this.env.address_sources[this.env.source].readonly));
var source = this.env.source != '' ? this.env.address_sources[this.env.source] : null;
this.enable_command('group-create', (source && source.groups && !source.readonly));
this.enable_command('group-rename', 'group-delete', (source && source.groups && this.env.group && !source.readonly));
this.triggerEvent('listupdate', { folder:this.env.source, rowcount:this.contact_list.rowcount });
}
}
@ -5580,7 +5621,7 @@ function rcube_webmail()
return frame_name;
};
// starts interval for keep-alive/check-recent signal
this.start_keepalive = function()
{

@ -326,6 +326,7 @@ $labels['personaladrbook'] = 'Personal Addresses';
$labels['import'] = 'Import';
$labels['importcontacts'] = 'Import contacts';
$labels['importfromfile'] = 'Import from file:';
$labels['importtarget'] = 'Add new contacts to address book:';
$labels['importreplace'] = 'Replace the entire address book';
$labels['importtext'] = 'You can upload contacts from an existing address book.<br/>We currently support importing addresses from the <a href="http://en.wikipedia.org/wiki/VCard">vCard</a> data format.';
$labels['done'] = 'Done';

@ -413,5 +413,6 @@ $labels['allfields'] = 'Wszystkie pola';
$labels['search'] = 'Szukaj';
$labels['advsearch'] = 'Wyszukiwanie zaawansowane';
$labels['other'] = 'Inne';
$labels['importtarget'] = 'Dodaj nowe kontakty do książki adresowej:';
?>

@ -23,75 +23,91 @@
if (!$OUTPUT->ajax_call)
return;
$cid = get_input_value('_cid', RCUBE_INPUT_POST);
$target = get_input_value('_to', RCUBE_INPUT_POST);
$cids = rcmail_get_cids();
$target = get_input_value('_to', RCUBE_INPUT_POST);
$target_group = get_input_value('_togid', RCUBE_INPUT_POST);
if ($cid && preg_match('/^[a-zA-Z0-9\+\/=_-]+(,[a-zA-Z0-9\+\/=_-]+)*$/', $cid) && strlen($target) && $target !== $source)
$success = 0;
$maxnum = $RCMAIL->config->get('max_group_members', 0);
foreach ($cids as $source => $cid)
{
$success = 0;
$TARGET = $RCMAIL->get_address_book($target);
// Something wrong, target not specified
if (!strlen($target)) {
break;
}
if ($TARGET && $TARGET->ready && !$TARGET->readonly) {
$arr_cids = explode(',', $cid);
$ids = array();
// It maight happen when copying records from search result
// Do nothing, go to next source
if ($target == $source) {
continue;
}
foreach ($arr_cids as $cid) {
$a_record = $CONTACTS->get_record($cid, true);
$CONTACTS = $RCMAIL->get_address_book($source);
$TARGET = $RCMAIL->get_address_book($target);
// check if contact exists, if so, we'll need it's ID
$result = $TARGET->search('email', $a_record['email'], true, true);
if (!$TARGET || !$TARGET->ready || $TARGET->readonly) {
break;
}
// insert contact record
if (!$result->count) {
$plugin = $RCMAIL->plugins->exec_hook('contact_create', array(
'record' => $a_record, 'source' => $target, 'group' => $target_group));
$ids = array();
if (!$plugin['abort']) {
if ($insert_id = $TARGET->insert($plugin['record'], false)) {
$ids[] = $insert_id;
$success++;
}
foreach ($cid as $cid) {
$a_record = $CONTACTS->get_record($cid, true);
// check if contact exists, if so, we'll need it's ID
$result = $TARGET->search('email', $a_record['email'], true, true);
// 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 if ($plugin['result']) {
$ids = array_merge($ids, $plugin['result']);
$success++;
else {
$record = $result->first();
$ids[] = $record['ID'];
}
}
else {
$record = $result->first();
$ids[] = $record['ID'];
}
}
// 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));
$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 (!$plugin['abort']) {
$TARGET->reset();
$TARGET->set_group($target_group);
if (($maxnum = $RCMAIL->config->get('max_group_members', 0)) && ($TARGET->count()->count + count($plugin['ids']) > $maxnum)) {
$OUTPUT->show_message('maxgroupmembersreached', 'warning', array('max' => $maxnum));
$OUTPUT->send();
}
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'];
if (($cnt = $TARGET->add_to_group($target_group, $plugin['ids'])) && $cnt > $success)
$success = $cnt;
}
else if ($plugin['result']) {
$success = $plugin['result'];
}
}
}
}
if ($success == 0)
if ($success == 0)
$OUTPUT->show_message('copyerror', 'error');
else
else
$OUTPUT->show_message('copysuccess', 'notice', array('nr' => $success));
}
// send response
$OUTPUT->send();

@ -19,42 +19,126 @@
*/
if ($OUTPUT->ajax_call &&
($cid = get_input_value('_cid', RCUBE_INPUT_POST)) &&
preg_match('/^[a-zA-Z0-9\+\/=_-]+(,[a-zA-Z0-9\+\/=_-]+)*$/', $cid)
) {
// process ajax requests only
if (!$OUTPUT->ajax_call)
return;
$cids = rcmail_get_cids();
$delcnt = 0;
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');
}
continue;
}
$plugin = $RCMAIL->plugins->exec_hook('contact_delete', array(
'id' => $cid, 'source' => get_input_value('_source', RCUBE_INPUT_GPC)));
'id' => $cid, 'source' => $source));
$deleted = !$plugin['abort'] ? $CONTACTS->delete($cid) : $plugin['result'];
if (!$deleted) {
$OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'contactdelerror', 'error');
$OUTPUT->command('list_contacts');
$OUTPUT->send();
}
else {
$OUTPUT->show_message('contactdeleted', 'confirmation');
$delcnt += $deleted;
}
}
// count contacts for this user
$result = $CONTACTS->count();
$OUTPUT->show_message('contactdeleted', 'confirmation');
// update saved search after data changed
if (($search_request = $_REQUEST['_search']) && isset($_SESSION['search'][$search_request]))
$_SESSION['search'][$search_request] = $CONTACTS->refresh_search();
$page = isset($_SESSION['page']) ? $_SESSION['page'] : 1;
// update message count display
$OUTPUT->set_env('pagecount', ceil($result->count / $CONTACTS->page_size));
$OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result->count));
// update saved search after data changed
if (($search_request = $_REQUEST['_search']) && isset($_SESSION['search'][$search_request])) {
$search = (array)$_SESSION['search'][$search_request];
$records = array();
// add new rows from next page (if any)
$pages = ceil(($result->count + $deleted) / $CONTACTS->page_size);
if ($_GET['_from'] != 'show' && $pages > 1 && $CONTACTS->list_page < $pages)
rcmail_js_contacts_list($CONTACTS->list_records(null, -$deleted));
// Get records from all sources (refresh search)
foreach ($search as $s => $set) {
$source = $RCMAIL->get_address_book($s);
// reset page
$source->set_page(1);
$source->set_pagesize(9999);
$source->set_search_set($set);
// get records
$result = $source->list_records(array('name', 'email'));
if (!$result->count) {
unset($search[$s]);
continue;
}
while ($row = $result->next()) {
$row['sourceid'] = $s;
$key = $row['name'] . ':' . $row['sourceid'];
$records[$key] = $row;
}
unset($result);
$search[$s] = $source->get_search_set();
}
// send response
$OUTPUT->send();
$_SESSION['search'][$search_request] = $search;
// create resultset object
$count = count($records);
$first = ($page-1) * $CONFIG['pagesize'];
$result = new rcube_result_set($count, $first);
// get records from the next page to add to the list
$pages = ceil((count($records) + $delcnt) / $CONFIG['pagesize']);
if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) {
// sort the records
ksort($records, SORT_LOCALE_STRING);
$first += $CONFIG['pagesize'];
// create resultset object
$res = new rcube_result_set($count, $first - $delcnt);
if ($CONFIG['pagesize'] < $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();
// get records from the next page to add to the list
$pages = ceil(($result->count + $delcnt) / $CONFIG['pagesize']);
if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) {
$CONTACTS->set_page($page);
$records = $CONTACTS->list_records(null, -$delcnt);
}
}
exit;
// update message count display
$OUTPUT->set_env('pagecount', ceil($result->count / $CONFIG['pagesize']));
$OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result));
// add new rows from next page (if any)
if (!empty($records)) {
rcmail_js_contacts_list($records);
}
// send response
$OUTPUT->send();

@ -19,15 +19,38 @@
*/
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']);
}
// adding not allowed here
if ($CONTACTS->readonly) {
$OUTPUT->show_message('sourceisreadonly');
rcmail_overwrite_action('show');
return;
}
}
else {
$source = get_input_value('_source', RCUBE_INPUT_GPC);
$CONTACTS = $RCMAIL->get_address_book($source);
if (($cid = get_input_value('_cid', RCUBE_INPUT_GPC)) && ($record = $CONTACTS->get_record($cid, true)))
$OUTPUT->set_env('cid', $record['ID']);
// find writable addressbook
if (!$CONTACTS || $CONTACTS->readonly)
$source = rcmail_default_source(true);
// adding not allowed here
if ($CONTACTS->readonly) {
$OUTPUT->show_message('sourceisreadonly');
rcmail_overwrite_action('show');
return;
// Initialize addressbook
$CONTACTS = rcmail_contact_source($source, true);
}
@ -45,7 +68,7 @@ function rcmail_get_edit_record()
$RCMAIL->output->show_message('contactnotfound');
return false;
}
return $record;
}
@ -90,7 +113,7 @@ function rcmail_contact_editform($attrib)
// add some labels to client
$RCMAIL->output->add_label('noemailwarning', 'nonamewarning');
// 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);
@ -123,7 +146,7 @@ function rcmail_contact_editform($attrib)
),
),
);
if (isset($CONTACT_COLTYPES['notes'])) {
$form['notes'] = array(
'name' => rcube_label('notes'),
@ -158,11 +181,11 @@ function rcmail_upload_photo_form($attrib)
if ($max_postsize && $max_postsize < $max_filesize)
$max_filesize = $max_postsize;
$max_filesize = show_bytes($max_filesize);
$hidden = new html_hiddenfield(array('name' => '_cid', 'value' => $GLOBALS['cid']));
$input = new html_inputfield(array('type' => 'file', 'name' => '_photo', 'size' => $attrib['size']));
$button = new html_inputfield(array('type' => 'button'));
$out = html::div($attrib,
$OUTPUT->form_tag(array('name' => 'uploadform', 'method' => 'post', 'enctype' => 'multipart/form-data'),
$hidden->show() .
@ -174,7 +197,7 @@ function rcmail_upload_photo_form($attrib)
)
)
);
$OUTPUT->add_label('addphoto','replacephoto');
$OUTPUT->add_gui_object('uploadbox', $attrib['id']);
return $out;
@ -211,12 +234,14 @@ function get_form_tags($attrib)
}
$OUTPUT->add_handler('contactedithead', 'rcmail_contact_edithead');
$OUTPUT->add_handler('contacteditform', 'rcmail_contact_editform');
$OUTPUT->add_handler('contactphoto', 'rcmail_contact_photo');
$OUTPUT->add_handler('photouploadform', 'rcmail_upload_photo_form');
$OUTPUT->add_handlers(array(
'contactedithead' => 'rcmail_contact_edithead',
'contacteditform' => 'rcmail_contact_editform',
'contactphoto' => 'rcmail_contact_photo',
'photouploadform' => 'rcmail_upload_photo_form',
));
if (!$CONTACTS->get_result() && $OUTPUT->template_exists('contactadd'))
if ($RCMAIL->action == 'add' && $OUTPUT->template_exists('contactadd'))
$OUTPUT->send('contactadd');
// this will be executed if no template for addcontact exists

@ -6,6 +6,7 @@
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2008-2011, The Roundcube Dev Team |
| Copyright (C) 2011, Kolab Systems AG |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
@ -13,16 +14,56 @@
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
| Author: Aleksander Machniak <machniak@kolabsys.com> |
+-----------------------------------------------------------------------+
$Id: $
$Id$
*/
// get contacts for this user
$CONTACTS->set_page(1);
$CONTACTS->set_pagesize(99999);
$result = $CONTACTS->list_records(null, 0, true);
// Use search result
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']]))
{
$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 ($row = $result->next()) {
$row['sourceid'] = $s;
$key = $row['name'] . ':' . $row['sourceid'];
$records[$key] = $row;
}
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 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);
}
// send downlaod headers
send_nocacheing_headers();
@ -30,25 +71,25 @@ header('Content-Type: text/x-vcard; charset='.RCMAIL_CHARSET);
header('Content-Disposition: attachment; filename="rcube_contacts.vcf"');
while ($result && ($row = $result->next())) {
// we already have a vcard record
if ($row['vcard'] && $row['name']) {
echo rcube_vcard::rfc2425_fold($row['vcard']) . "\n";
}
// copy values into vcard object
else {
$vcard = new rcube_vcard($row['vcard']);
$vcard->reset();
foreach ($row as $key => $values) {
list($field, $section) = explode(':', $key);
foreach ((array)$values as $value) {
if (is_array($value) || strlen($value))
$vcard->set($field, $value, strtoupper($section));
}
// we already have a vcard record
if ($row['vcard'] && $row['name']) {
echo rcube_vcard::rfc2425_fold($row['vcard']) . "\n";
}
// copy values into vcard object
else {
$vcard = new rcube_vcard($row['vcard']);
$vcard->reset();
echo $vcard->export(true) . "\n";
}
foreach ($row as $key => $values) {
list($field, $section) = explode(':', $key);
foreach ((array)$values as $value) {
if (is_array($value) || strlen($value))
$vcard->set($field, $value, strtoupper($section));
}
}
echo $vcard->export(true) . "\n";
}
}
exit;

@ -21,46 +21,6 @@
$SEARCH_MODS_DEFAULT = array('name'=>1, 'firstname'=>1, 'surname'=>1, 'email'=>1, '*'=>1);
// select source
$source = get_input_value('_source', RCUBE_INPUT_GPC);
if (!$RCMAIL->action && !$OUTPUT->ajax_call) {
// add list of address sources to client env
$js_list = $RCMAIL->get_address_sources();
// if source is not set use first directory
if (empty($source))
$source = $js_list[key($js_list)]['id'];
$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);
}
// instantiate a contacts object according to the given source
$CONTACTS = $RCMAIL->get_address_book($source);
$CONTACTS->set_pagesize($CONFIG['pagesize']);
// 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']))
$CONTACTS->set_group(get_input_value('_gid', RCUBE_INPUT_GPC));
// set data source env
$OUTPUT->set_env('source', $source ? $source : '0');
$OUTPUT->set_env('readonly', $CONTACTS->readonly);
if (!$OUTPUT->ajax_call) {
$search_mods = $RCMAIL->config->get('addressbook_search_mods', $SEARCH_MODS_DEFAULT);
$OUTPUT->set_env('search_mods', $search_mods);
$OUTPUT->set_pagetitle(rcube_label('addressbook'));
}
// general definition of contact coltypes
$CONTACT_COLTYPES = array(
'name' => array('type' => 'text', 'size' => 40, 'limit' => 1, 'label' => rcube_label('name'), 'category' => 'main'),
@ -96,19 +56,93 @@ $CONTACT_COLTYPES = array(
// TODO: define fields for vcards like GEO, KEY
);
// 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)
$CONTACT_COLTYPES[$col] = $CONTACT_COLTYPES[$col] ? array_merge($CONTACT_COLTYPES[$col], $colprop) : $colprop;
// Addressbook UI
if (!$RCMAIL->action && !$OUTPUT->ajax_call) {
// add list of address sources to client env
$js_list = $RCMAIL->get_address_sources();
// use first directory by default
$source = $js_list[key($js_list)]['id'];
// find writeable source
foreach ($js_list as $s) {
if (!$s['readonly']) {
$OUTPUT->set_env('writable_source', $s['id']);
break;
}
}
$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_pagetitle(rcube_label('addressbook'));
$CONTACTS = rcmail_contact_source($source, true);
}
$OUTPUT->set_env('photocol', is_array($CONTACT_COLTYPES['photo']));
// instantiate a contacts object according to the given source
function rcmail_contact_source($source=null, $init_env=false)
{
global $RCMAIL, $OUTPUT, $CONFIG, $CONTACT_COLTYPES;
if (!strlen($source)) {
$source = get_input_value('_source', RCUBE_INPUT_GPC);
}
if (!strlen($source)) {
return null;
}
// Get object
$CONTACTS = $RCMAIL->get_address_book($source);
$CONTACTS->set_pagesize($CONFIG['pagesize']);
// 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']))
$CONTACTS->set_group(get_input_value('_gid', RCUBE_INPUT_GPC));
if (!$init_env)
return $CONTACTS;
$OUTPUT->set_env('readonly', $CONTACTS->readonly);
$OUTPUT->set_env('source', $source);
// 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)
$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_default_source($writable=false)
{
global $RCMAIL;
// get list of address sources
$list = $RCMAIL->get_address_sources($writable);
// use first directory by default
return $list[key($list)]['id'];
}
function rcmail_directory_list($attrib)
@ -230,6 +264,11 @@ function rcmail_js_contacts_list($result, $prefix='')
while ($row = $result->next()) {
$a_row_cols = array();
// build contact ID with source ID
if (isset($row['sourceid'])) {
$row['ID'] = $row['ID'].'-'.$row['sourceid'];
}
// format each col
foreach ($a_show_cols as $col)
$a_row_cols[$col] = Q($row[$col]);
@ -246,7 +285,7 @@ function rcmail_contact_frame($attrib)
if (!$attrib['id'])
$attrib['id'] = 'rcmcontactframe';
$attrib['name'] = $attrib['id'];
$OUTPUT->set_env('contentframe', $attrib['name']);
@ -269,12 +308,14 @@ function rcmail_rowcount_display($attrib)
}
function rcmail_get_rowcount_text()
function rcmail_get_rowcount_text($result=null)
{
global $CONTACTS;
global $CONTACTS, $CONFIG;
// read nr of contacts
$result = $CONTACTS->get_result();
if (!$result) {
$result = $CONTACTS->get_result();
}
if (!$result) {
$result = $CONTACTS->count();
}
@ -286,7 +327,7 @@ function rcmail_get_rowcount_text()
'name' => 'contactsfromto',
'vars' => array(
'from' => $result->first + 1,
'to' => min($result->count, $result->first + $CONTACTS->page_size),
'to' => min($result->count, $result->first + $CONFIG['pagesize']),
'count' => $result->count)
));
@ -303,7 +344,7 @@ function rcmail_get_type_label($type)
&& ($label = preg_replace('/(\d+)$/', '', $label))
&& rcube_label_exists($label))
return rcube_label($label) . ' ' . $m[1];
return ucfirst($type);
}
@ -322,11 +363,11 @@ function rcmail_contact_form($form, $record, $attrib = null)
$del_button = $attrib['deleteicon'] ? html::img(array('src' => $CONFIG['skin_path'] . $attrib['deleteicon'], 'alt' => rcube_label('delete'))) : rcube_label('delete');
unset($attrib['deleteicon']);
$out = '';
// 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']);
@ -369,7 +410,7 @@ function rcmail_contact_form($form, $record, $attrib = null)
// skip cols unknown to the backend
if (!$coltypes[$col])
continue;
// only string values are expected here
if (is_array($record[$col]))
$record[$col] = join(' ', $record[$col]);
@ -390,7 +431,7 @@ function rcmail_contact_form($form, $record, $attrib = null)
}
$content .= html::div($blockname, $fields);
}
if ($edit_mode)
$content .= html::p('addfield', $select_add->show(null));
@ -522,13 +563,13 @@ function rcmail_contact_form($form, $record, $attrib = null)
else // row without label
$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
$content .= html::tag('fieldset', array('class' => 'contactfieldgroup ' . ($colprop['subtypes'] ? 'contactfieldgroupmulti ' : '') . 'contactcontroller' . $col, 'style' => ($rows ? null : 'display:none')),
($colprop['subtypes'] ? html::tag('legend', null, Q($colprop['label'])) : ' ') .
@ -599,6 +640,48 @@ function rcmail_format_date_col($val)
}
/**
* Returns contact ID(s) and source(s) from GET/POST data
*
* @return array List of contact IDs per-source
*/
function rcmail_get_cids()
{
// 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 = get_input_value('_cid', RCUBE_INPUT_GPC);
$source = get_input_value('_source', RCUBE_INPUT_GPC);
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) {
// if _source is not specified we'll find it from decoded ID
if (!$got_source) {
list ($c, $s) = explode('-', $id, 2);
if (strlen($s)) {
$result[$s][] = $c;
}
else if (strlen($source)) {
$result[$source][] = $c;
}
}
else {
$result[$source][] = $id;
}
}
return $result;
}
// register UI objects
$OUTPUT->add_handlers(array(
'directorylist' => 'rcmail_directory_list',

@ -19,13 +19,14 @@
*/
$source = get_input_value('_source', RCUBE_INPUT_GPC);
$CONTACTS = rcmail_contact_source($source, true);
if ($CONTACTS->readonly || !$CONTACTS->groups) {
$OUTPUT->show_message('sourceisreadonly', 'warning');
$OUTPUT->send();
}
$source = get_input_value('_source', RCUBE_INPUT_GPC);
if ($RCMAIL->action == 'group-addmembers') {
if (($gid = get_input_value('_gid', RCUBE_INPUT_POST)) && ($ids = get_input_value('_cid', RCUBE_INPUT_POST))) {
$plugin = $RCMAIL->plugins->exec_hook('group_addmembers', array('group_id' => $gid, 'ids' => $ids, 'source' => $source));

@ -13,9 +13,10 @@
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
| Author: Aleksander Machniak <machniak@kolabsys.com> |
+-----------------------------------------------------------------------+
$Id: $
$Id$
*/
@ -26,30 +27,44 @@ function rcmail_import_form($attrib)
{
global $RCMAIL, $OUTPUT;
$target = get_input_value('_target', RCUBE_INPUT_GPC);
$attrib += array('id' => "rcmImportForm");
$abook = new html_hiddenfield(array('name' => '_target', 'value' => $target));
$form = $abook->show();
$writable_books = $RCMAIL->get_address_sources(true);
$upload = new html_inputfield(array('type' => 'file', 'name' => '_file', 'id' => 'rcmimportfile', 'size' => 40));
$form .= html::p(null, html::label('rcmimportfile', rcube_label('importfromfile')) . html::br() . $upload->show());
$form = html::p(null, html::label('rcmimportfile', rcube_label('importfromfile')) . $upload->show());
// addressbook selector
if (count($writable_books) > 1) {
$select = new html_select(array('name' => '_target', 'id' => 'rcmimporttarget'));
foreach ($writable_books as $book)
$select->add($book['name'], $book['id']);
$form .= html::p(null, html::label('rcmimporttarget', rcube_label('importtarget'))
. $select->show($target));
}
else {
$abook = new html_hiddenfield(array('name' => '_target', 'value' => key($writable_books)));
$form .= $abook->show();
}
$check_replace = new html_checkbox(array('name' => '_replace', 'value' => 1, 'id' => 'rcmimportreplace'));
$form .= html::p(null, $check_replace->show(get_input_value('_replace', RCUBE_INPUT_GPC)) .
html::label('rcmimportreplace', rcube_label('importreplace')));
$OUTPUT->add_label('selectimportfile','importwait');
$OUTPUT->add_gui_object('importform', $attrib['id']);
$out = html::p(null, Q(rcube_label('importtext'), 'show'));
$out .= $OUTPUT->form_tag(array(
'action' => $RCMAIL->url('import'),
'method' => 'post',
'enctype' => 'multipart/form-data') + $attrib,
$form);
return $out;
}
@ -60,19 +75,19 @@ function rcmail_import_form($attrib)
function rcmail_import_confirm($attrib)
{
global $IMPORT_STATS;
$vars = get_object_vars($IMPORT_STATS);
$vars['names'] = $vars['skipped_names'] = '';
$content = html::p(null, rcube_label(array(
'name' => 'importconfirm',
'nr' => $IMORT_STATS->inserted,
'vars' => $vars,
)) . ($IMPORT_STATS->names ? ':' : '.'));
if ($IMPORT_STATS->names)
$content .= html::p('em', join(', ', array_map('Q', $IMPORT_STATS->names)));
if ($IMPORT_STATS->skipped) {
$content .= html::p(null, rcube_label(array(
'name' => 'importconfirmskipped',
@ -81,7 +96,7 @@ function rcmail_import_confirm($attrib)
)) . ':');
$content .= html::p('em', join(', ', array_map('Q', $IMPORT_STATS->skipped_names)));
}
return html::div($attrib, $content);
}
@ -93,10 +108,10 @@ function rcmail_import_buttons($attrib)
{
global $IMPORT_STATS, $OUTPUT;
$target = get_input_value('_target', RCUBE_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);
@ -107,7 +122,7 @@ function rcmail_import_buttons($attrib)
$attrib['class'] = trim($attrib['class'] . ' mainaction');
$out .= $OUTPUT->button(array('command' => 'import', 'label' => 'import') + $attrib);
}
return $out;
}
@ -137,13 +152,13 @@ if ($_FILES['_file']['tmp_name'] && is_uploaded_file($_FILES['_file']['tmp_name'
$IMPORT_STATS->skipped_names = array();
$IMPORT_STATS->count = count($vcards);
$IMPORT_STATS->inserted = $IMPORT_STATS->skipped = $IMPORT_STATS->nomail = $IMPORT_STATS->errors = 0;
if ($replace)
$CONTACTS->delete_all();
foreach ($vcards as $vcard) {
$email = $vcard->email[0];
// skip entries without an e-mail address
if (empty($email)) {
$IMPORT_STATS->nomail++;
@ -152,7 +167,7 @@ if ($_FILES['_file']['tmp_name'] && is_uploaded_file($_FILES['_file']['tmp_name'
// We're using UTF8 internally
$email = rcube_idn_to_utf8($email);
if (!$replace && $email) {
// compare e-mail address
$existing = $CONTACTS->search('email', $email, false, false);
@ -165,10 +180,10 @@ if ($_FILES['_file']['tmp_name'] && is_uploaded_file($_FILES['_file']['tmp_name'
continue;
}
}
$a_record = $vcard->get_assoc();
$a_record['vcard'] = $vcard->export();
$plugin = $RCMAIL->plugins->exec_hook('contact_create', array('record' => $a_record, 'source' => null));
$a_record = $plugin['record'];

@ -19,20 +19,68 @@
*/
// set message set for search result
// Use search result
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']]))
$CONTACTS->set_search_set($_SESSION['search'][$_REQUEST['_search']]);
{
$search = (array)$_SESSION['search'][$_REQUEST['_search']];
$records = array();
// get contacts for this user
$result = $CONTACTS->list_records(array('name'));
if (!empty($_GET['_page']))
$page = intval($_GET['_page']);
else
$page = isset($_SESSION['page']) ? $_SESSION['page'] : 1;
$_SESSION['page'] = $page;
// Get records from all sources
foreach ($search as $s => $set) {
$source = $RCMAIL->get_address_book($s);
// reset page
$source->set_page(1);
$source->set_pagesize(9999);
$source->set_search_set($set);
// get records
$result = $source->list_records(array('name', 'email'));
while ($row = $result->next()) {
$row['sourceid'] = $s;
$key = $row['name'] . ':' . $row['sourceid'];
$records[$key] = $row;
}
unset($result);
}
// sort the records
ksort($records, SORT_LOCALE_STRING);
// create resultset object
$count = count($records);
$first = ($page-1) * $CONFIG['pagesize'];
$result = new rcube_result_set($count, $first);
// we need only records for current page
if ($CONFIG['pagesize'] < $count) {
$records = array_slice($records, $first, $CONFIG['pagesize']);
}
$result->records = array_values($records);
}
// List selected directory
else {
$CONTACTS = rcmail_contact_source(null, true);
// get contacts for this user
$result = $CONTACTS->list_records(array('name'));
}
// update message count display
$OUTPUT->set_env('pagecount', ceil($result->count / $CONTACTS->page_size));
$OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($rowcount));
$OUTPUT->set_env('pagecount', ceil($result->count / $CONFIG['pagesize']));
$OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result));
// create javascript list
rcmail_js_contacts_list($result);
// send response
$OUTPUT->send();

@ -19,33 +19,36 @@
*/
$cid = get_input_value('_cid', RCUBE_INPUT_POST);
$recipients = null;
$cids = rcmail_get_cids();
$mailto = array();
if ($cid && preg_match('/^[a-z0-9\+\/=_-]+(,[a-z0-9\+\/=_-]+)*$/i', $cid) && $CONTACTS->ready)
foreach ($cids as $source => $cid)
{
$CONTACTS->set_page(1);
$CONTACTS->set_pagesize(substr_count($cid, ',')+2); // +2 to skip counting query
$recipients = $CONTACTS->search($CONTACTS->primary_key, $cid);
while (is_object($recipients) && ($rec = $recipients->iterate())) {
$emails = $CONTACTS->get_col_values('email', $rec, true);
$mailto[] = format_email_recipient($emails[0], $rec['name']);
}
$CONTACTS = $RCMAIL->get_address_book($source);
if ($CONTACTS->ready)
{
$CONTACTS->set_page(1);
$CONTACTS->set_pagesize(count($cid) + 2); // +2 to skip counting query
$recipients = $CONTACTS->search($CONTACTS->primary_key, $cid, false, true, true, 'email');
while (is_object($recipients) && ($rec = $recipients->iterate())) {
$emails = $CONTACTS->get_col_values('email', $rec, true);
$mailto[] = format_email_recipient($emails[0], $rec['name']);
}
}
}
if (!empty($mailto))
{
$mailto_str = join(', ', $mailto);
$mailto_id = substr(md5($mailto_str), 0, 16);
$_SESSION['mailto'][$mailto_id] = urlencode($mailto_str);
$OUTPUT->redirect(array('task' => 'mail', '_action' => 'compose', '_mailto' => $mailto_id));
$mailto_str = join(', ', $mailto);
$mailto_id = substr(md5($mailto_str), 0, 16);
$_SESSION['mailto'][$mailto_id] = urlencode($mailto_str);
$OUTPUT->redirect(array('task' => 'mail', '_action' => 'compose', '_mailto' => $mailto_id));
}
else {
$OUTPUT->show_message('nocontactsfound', 'warning');
}
else
$OUTPUT->show_message('nocontactsfound', 'warning');
// send response
$OUTPUT->send();

@ -19,9 +19,11 @@
*/
$cid = get_input_value('_cid', RCUBE_INPUT_POST);
$CONTACTS = rcmail_contact_source(null, true);
$cid = get_input_value('_cid', RCUBE_INPUT_POST);
$return_action = empty($cid) ? 'add' : 'edit';
// cannot edit record
if ($CONTACTS->readonly) {
$OUTPUT->show_message('contactreadonly', 'error');
@ -38,19 +40,19 @@ if ($RCMAIL->action == 'upload-photo') {
if ($filepath = $_FILES['_photo']['tmp_name']) {
// check file type and resize image
$imageprop = rcmail::imageprops($_FILES['_photo']['tmp_name']);
if ($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) &&
(rcmail::imageconvert(array('in' => $filepath, 'out' => $tmpfname, 'size' => $maxsize.'x'.$maxsize, 'type' => $imageprop['type'])) !== false)) {
$filepath = $tmpfname;
$save_hook = 'attachment_save';
}
// save uploaded file in storage backend
$attachment = $RCMAIL->plugins->exec_hook($save_hook, array(
'path' => $filepath,
@ -87,10 +89,10 @@ if ($RCMAIL->action == 'upload-photo') {
$msg = rcube_label(array('name' => 'filesizeerror', 'vars' => array('size' => show_bytes(parse_bytes($maxsize)))));
else
$msg = rcube_label('fileuploaderror');
$OUTPUT->command('display_message', $msg, 'error');
}
$OUTPUT->command('photo_upload_end');
$OUTPUT->send('iframe');
}
@ -155,7 +157,7 @@ if (isset($a_record['photo'])) {
}
else
unset($a_record['photo']);
// cleanup session data
$RCMAIL->plugins->exec_hook('attachments_cleanup', array('group' => 'contact'));
$RCMAIL->session->remove('contacts');
@ -240,7 +242,7 @@ else {
$CONTACTS->add_to_group($gid, $plugin['ids']);
}
}
// add contact row or jump to the page where it should appear
$CONTACTS->reset();
$result = $CONTACTS->search($CONTACTS->primary_key, $insert_id);

@ -31,17 +31,17 @@ $OUTPUT->send('contactsearch');
function rcmail_contact_search()
{
global $RCMAIL, $OUTPUT, $CONTACTS, $CONTACT_COLTYPES, $SEARCH_MODS_DEFAULT;
global $RCMAIL, $OUTPUT, $CONFIG, $SEARCH_MODS_DEFAULT;
$adv = isset($_POST['_adv']);
// get fields/values from advanced search form
if ($adv) {
foreach ($CONTACT_COLTYPES as $col => $colprop) {
$s = trim(get_input_value('_'.$col, RCUBE_INPUT_POST, true));
if (strlen($s)) {
foreach (array_keys($_POST) as $key) {
$s = trim(get_input_value($key, RCUBE_INPUT_POST, true));
if (strlen($s) && preg_match('/^_search_([a-zA-Z0-9_-]+)$/', $key, $m)) {
$search[] = $s;
$fields[] = $col;
$fields[] = $m[1];
}
}
@ -71,20 +71,77 @@ function rcmail_contact_search()
}
}
// get sources list
$sources = $RCMAIL->get_address_sources();
$search_set = array();
$records = array();
foreach ($sources as $s) {
$source = $RCMAIL->get_address_book($s['id']);
// check if all 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 ++;
}
}
// ...if not, we can skip this source
if ($supported < count($fields)) {
continue;
}
}
// reset page
$source->set_page(1);
$source->set_pagesize(9999);
// get contacts count
$result = $source->search($fields, $search, false, false);
if (!$result->count) {
continue;
}
// get records
$result = $source->list_records(array('name', 'email'));
while ($row = $result->next()) {
$row['sourceid'] = $s['id'];
$key = $row['name'] . ':' . $row['sourceid'];
$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 ($CONFIG['pagesize'] < $count) {
$records = array_slice($records, 0, $CONFIG['pagesize']);
}
$result->records = array_values($records);
// search request ID
$search_request = md5('addr'
.(is_array($fields) ? implode($fields, ',') : $fields)
.(is_array($search) ? implode($search, ',') : $search));
// reset page
$CONTACTS->set_page(1);
$_SESSION['page'] = 1;
// get contacts for this user
$result = $CONTACTS->search($fields, $search);
// save search settings in session
$_SESSION['search'][$search_request] = $CONTACTS->get_search_set();
$_SESSION['search'][$search_request] = $search_set;
$_SESSION['page'] = 1;
if ($adv)
$OUTPUT->command('list_contacts_clear');
@ -99,8 +156,11 @@ function rcmail_contact_search()
// update message count display
$OUTPUT->command('set_env', 'search_request', $search_request);
$OUTPUT->command('set_env', 'pagecount', ceil($result->count / $CONTACTS->page_size));
$OUTPUT->command('set_rowcount', rcmail_get_rowcount_text());
$OUTPUT->command('set_env', 'pagecount', ceil($result->count / $CONFIG['pagesize']));
$OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result));
// unselect currently selected directory/group
$OUTPUT->command('unselect_directory');
// send response
$OUTPUT->send($adv ? 'iframe' : null);
@ -108,7 +168,7 @@ function rcmail_contact_search()
function rcmail_contact_search_form($attrib)
{
global $RCMAIL, $CONTACTS, $CONTACT_COLTYPES;
global $RCMAIL, $CONTACT_COLTYPES;
$i_size = !empty($attrib['size']) ? $attrib['size'] : 30;
@ -130,7 +190,26 @@ function rcmail_contact_search_form($attrib)
),
);
foreach ($CONTACT_COLTYPES as $col => $colprop)
// 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'])
{
@ -142,15 +221,13 @@ function rcmail_contact_search_form($attrib)
$colprop['size'] = $i_size;
$content = html::div('row', html::div('contactfieldlabel label', Q($label))
. html::div('contactfieldcontent', rcmail_get_edit_field($col, '', $colprop, $ftype)));
. html::div('contactfieldcontent', rcmail_get_edit_field('search_'.$col, '', $colprop, $ftype)));
$form[$category]['content'][] = $content;
}
}
$hiddenfields = new html_hiddenfield(array(
'name' => '_source', 'value' => get_input_value('_source', RCUBE_INPUT_GPC)));
$hiddenfields->add(array('name' => '_gid', 'value' => $CONTACTS->group_id));
$hiddenfields = new html_hiddenfield();
$hiddenfields->add(array('name' => '_adv', 'value' => 1));
$out = $RCMAIL->output->request_form(array(

@ -19,9 +19,16 @@
*/
// Get contact ID and source ID from request
$cids = rcmail_get_cids();
$source = key($cids);
$cid = array_shift($cids[$source]);
// Initialize addressbook source
$CONTACTS = rcmail_contact_source($source, true);
// read contact record
if (($cid = get_input_value('_cid', RCUBE_INPUT_GPC)) && ($record = $CONTACTS->get_record($cid, true))) {
if ($cid && ($record = $CONTACTS->get_record($cid, true))) {
$OUTPUT->set_env('cid', $record['ID']);
}
@ -41,7 +48,7 @@ if ($RCMAIL->action == 'photo') {
if (!preg_match('![^a-z0-9/=+-]!i', $data))
$data = base64_decode($data, true);
}
header('Content-Type: ' . rc_image_content_type($data));
echo $data ? $data : file_get_contents('program/blank.gif');
exit;
@ -190,14 +197,15 @@ function rcmail_contact_record_groups($contact_id)
$form_end = '</form>';
$RCMAIL->output->add_gui_object('editform', 'form');
return $form_start . $table->show() . $form_end;
}
//$OUTPUT->framed = $_framed;
$OUTPUT->add_handler('contacthead', 'rcmail_contact_head');
$OUTPUT->add_handler('contactdetails', 'rcmail_contact_details');
$OUTPUT->add_handler('contactphoto', 'rcmail_contact_photo');
$OUTPUT->add_handlers(array(
'contacthead' => 'rcmail_contact_head',
'contactdetails' => 'rcmail_contact_details',
'contactphoto' => 'rcmail_contact_photo',
));
$OUTPUT->send('contact');

Loading…
Cancel
Save