summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/main.inc.php.dist1
-rw-r--r--program/js/app.js16
-rw-r--r--program/lib/Roundcube/rcube_ldap.php32
-rw-r--r--program/localization/en_US/labels.inc1
-rw-r--r--program/steps/addressbook/func.inc36
-rw-r--r--skins/larry/addressbook.css11
6 files changed, 85 insertions, 12 deletions
diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist
index b113b41a8..d4246a001 100644
--- a/config/main.inc.php.dist
+++ b/config/main.inc.php.dist
@@ -680,6 +680,7 @@ $rcmail_config['ldap_public']['Verisign'] = array(
'object_classes' => array("top", "groupOfNames"),
'member_attr' => 'member', // name of the member attribute, e.g. uniqueMember
'name_attr' => 'cn', // attribute to be used as group name
+ 'member_filter' => '(objectclass=*)', // optional filter to use when querying for group members
),
);
*/
diff --git a/program/js/app.js b/program/js/app.js
index dbb65eea4..0445004f2 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -322,7 +322,7 @@ function rcube_webmail()
this.env.contactfolders = $.extend($.extend({}, this.env.address_sources), this.env.contactgroups);
this.enable_command('add', 'import', this.env.writable_source);
- this.enable_command('list', 'listgroup', 'listsearch', 'advanced-search', true);
+ this.enable_command('list', 'listgroup', 'pushgroup', 'listsearch', 'advanced-search', true);
if (this.gui_objects.contactslist) {
this.contact_list = new rcube_list_widget(this.gui_objects.contactslist,
@@ -1080,6 +1080,8 @@ function rcube_webmail()
}
break;
+ case 'pushgroup':
+ // TODO: so some magic stuff here
case 'listgroup':
this.reset_qsearch();
this.list_contacts(props.source, props.id);
@@ -4151,6 +4153,7 @@ function rcube_webmail()
this.list_contacts_clear = function()
{
+ this.contact_list.data = {};
this.contact_list.clear(true);
this.show_contentframe(false);
this.enable_command('delete', false);
@@ -4160,7 +4163,12 @@ function rcube_webmail()
// load contact record
this.load_contact = function(cid, action, framed)
{
- var win, url = {}, target = window;
+ var win, url = {}, target = window,
+ rec = this.contact_list.data[cid];
+
+ if (rec && rec.type == 'group') {
+ alert('group ' + cid)
+ }
if (win = this.get_frame_window(this.env.contentframe)) {
url._framed = 1;
@@ -4311,7 +4319,7 @@ function rcube_webmail()
};
// add row to contacts list
- this.add_contact_row = function(cid, cols, classes)
+ this.add_contact_row = function(cid, cols, classes, data)
{
if (!this.gui_objects.contactslist)
return false;
@@ -4333,6 +4341,8 @@ function rcube_webmail()
row.appendChild(col);
}
+ // store data in list member
+ list.data[cid] = data;
list.insert_row(row);
this.enable_command('export', list.rowcount > 0);
diff --git a/program/lib/Roundcube/rcube_ldap.php b/program/lib/Roundcube/rcube_ldap.php
index a2dd163e9..80b85d45b 100644
--- a/program/lib/Roundcube/rcube_ldap.php
+++ b/program/lib/Roundcube/rcube_ldap.php
@@ -657,6 +657,21 @@ class rcube_ldap extends rcube_addressbook
if (empty($entry[$attr]))
return $group_members;
+ // add group record to cache if it isn't yet there
+ $group_id = self::dn_encode($dn);
+ $group_cache = $this->cache->get('groups');
+ if (!$group_cache[$group_id]) {
+ $name_attr = $this->prop['groups']['name_attr'];
+ $group_name = is_array($ldap_data[$i][$name_attr]) ? $ldap_data[$i][$name_attr][0] : $ldap_data[$i][$name_attr];
+
+ $group_cache[$group_id]['ID'] = $group_id;
+ $group_cache[$group_id]['dn'] = $dn;
+ $group_cache[$group_id]['name'] = $group_name;
+ $group_cache[$group_id]['member_attr'] = $this->get_group_member_attr($entry[$i]['objectclass']);
+
+ $this->cache->set('groups', $group_cache);
+ }
+
// read these attributes for all members
$attrib = $count ? array('dn') : array_values($this->fieldmap);
$attrib[] = 'objectClass';
@@ -664,12 +679,14 @@ class rcube_ldap extends rcube_addressbook
$attrib[] = 'uniqueMember';
$attrib[] = 'memberURL';
+ $filter = $this->prop['groups']['member_filter'] ? $this->prop['groups']['member_filter'] : '(objectclass=*)';
+
for ($i=0; $i < $entry[$attr]['count']; $i++)
{
if (empty($entry[$attr][$i]))
continue;
- $result = @ldap_read($this->conn, $entry[$attr][$i], '(objectclass=*)',
+ $result = @ldap_read($this->conn, $entry[$attr][$i], $filter,
$attrib, 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit']);
$members = @ldap_get_entries($this->conn, $result);
@@ -1522,11 +1539,20 @@ class rcube_ldap extends rcube_addressbook
*/
private function _ldap2result($rec)
{
- $out = array();
+ $out = array('_type' => 'person');
if ($rec['dn'])
$out[$this->primary_key] = self::dn_encode($rec['dn']);
+ // determine record type
+ if (array_intersect(array('groupofuniquenames','kolabgroupofuniquenames'), (array)$rec['objectclass'])) {
+ $out['_type'] = 'group';
+ $out['readonly'] = true;
+ if ($this->fieldmap['groupname']) {
+ $this->fieldmap['name'] = $this->fieldmap['groupname'];
+ }
+ }
+
foreach ($this->fieldmap as $rf => $lf)
{
for ($i=0; $i < $rec[$lf]['count']; $i++) {
@@ -1780,7 +1806,7 @@ class rcube_ldap extends rcube_addressbook
for ($i=0; $i < $group_count; $i++)
{
$group_name = is_array($ldap_data[$i][$name_attr]) ? $ldap_data[$i][$name_attr][0] : $ldap_data[$i][$name_attr];
- $group_id = self::dn_encode($group_name);
+ $group_id = self::dn_encode($ldap_data[$i]['dn']);
$groups[$group_id]['ID'] = $group_id;
$groups[$group_id]['dn'] = $ldap_data[$i]['dn'];
$groups[$group_id]['name'] = $group_name;
diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc
index a0b6e6a31..2fce96ca1 100644
--- a/program/localization/en_US/labels.inc
+++ b/program/localization/en_US/labels.inc
@@ -350,6 +350,7 @@ $labels['lastpage'] = 'Show last page';
$labels['group'] = 'Group';
$labels['groups'] = 'Groups';
+$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Personal Addresses';
$labels['searchsave'] = 'Save search';
diff --git a/program/steps/addressbook/func.inc b/program/steps/addressbook/func.inc
index 80631cd61..f921c8cda 100644
--- a/program/steps/addressbook/func.inc
+++ b/program/steps/addressbook/func.inc
@@ -310,7 +310,7 @@ function rcmail_contacts_list($attrib)
global $CONTACTS, $OUTPUT;
// define list of cols to be displayed
- $a_show_cols = array('name');
+ $a_show_cols = array('name','action');
// add id to message list table if not specified
if (!strlen($attrib['id']))
@@ -339,27 +339,51 @@ function rcmail_js_contacts_list($result, $prefix='')
return;
// define list of cols to be displayed
- $a_show_cols = array('name');
+ $a_show_cols = array('name','action');
while ($row = $result->next()) {
+ $row['CID'] = $row['ID'];
+ $source_id = $OUTPUT->get_env('source');
$a_row_cols = array();
- $classes = array('person'); // org records will follow some day
+ $classes = array($row['_type'] ? $row['_type'] : 'person');
// build contact ID with source ID
if (isset($row['sourceid'])) {
$row['ID'] = $row['ID'].'-'.$row['sourceid'];
+ $source_id = $row['sourceid'];
}
// format each col
foreach ($a_show_cols as $col) {
- $val = $col == 'name' ? rcube_addressbook::compose_list_name($row) : $row[$col];
- $a_row_cols[$col] = Q($val);
+ $val = '';
+ switch ($col) {
+ case 'name':
+ $val = Q(rcube_addressbook::compose_list_name($row));
+ break;
+
+ case 'action':
+ if ($row['_type'] == 'group') {
+ $val = html::a(array(
+ 'href' => '#list',
+ 'rel' => $row['ID'],
+ 'title' => rcube_label('listgroup'),
+ 'onclick' => sprintf("return %s.command('pushgroup',{'source':'%s','id':'%s'},this)", JS_OBJECT_NAME, $source_id, $row['CID']),
+ ), '&raquo;');
+ }
+ break;
+
+ default:
+ $val = Q($row[$col]);
+ break;
+ }
+
+ $a_row_cols[$col] = $val;
}
if ($row['readonly'])
$classes[] = 'readonly';
- $OUTPUT->command($prefix.'add_contact_row', $row['ID'], $a_row_cols, join(' ', $classes));
+ $OUTPUT->command($prefix.'add_contact_row', $row['ID'], $a_row_cols, join(' ', $classes), $row);
}
}
diff --git a/skins/larry/addressbook.css b/skins/larry/addressbook.css
index ff3951497..bd2b05b26 100644
--- a/skins/larry/addressbook.css
+++ b/skins/larry/addressbook.css
@@ -141,6 +141,17 @@
font-weight: bold;
}
+#contacts-table .group td.name {
+ background-position: 6px -1555px;
+}
+
+#contacts-table .group.selected td.name,
+#contacts-table .group.unfocused td.name {
+ background-position: 6px -1579px;
+ font-weight: bold;
+}
+
+
#contact-frame {
position: absolute;
top: 0;