diff options
| author | thomasb <thomasb@208e9e7b-5314-0410-a742-e7e81cd9613c> | 2010-10-25 17:32:58 +0000 |
|---|---|---|
| committer | thomasb <thomasb@208e9e7b-5314-0410-a742-e7e81cd9613c> | 2010-10-25 17:32:58 +0000 |
| commit | f7f0624c07eb4e13a0e777f1f0a0fe740463538e (patch) | |
| tree | 83bb6e22e54141622ec5dce9cd24633556459f02 /plugins | |
| parent | 20d07a78a8dbb49df6c94ddbdb45b19cad27039a (diff) | |
Work-in-progress Kolab address book plugin
git-svn-id: https://svn.roundcube.net/trunk@4134 208e9e7b-5314-0410-a742-e7e81cd9613c
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/kolab_addressbook/README.txt | 32 | ||||
| -rw-r--r-- | plugins/kolab_addressbook/config.inc.php.dist | 8 | ||||
| -rw-r--r-- | plugins/kolab_addressbook/kolab_addressbook.php | 32 | ||||
| -rw-r--r-- | plugins/kolab_addressbook/lib/rcube_kolab.php | 39 | ||||
| -rw-r--r-- | plugins/kolab_addressbook/rcube_kolab_contacts.php | 176 |
5 files changed, 253 insertions, 34 deletions
diff --git a/plugins/kolab_addressbook/README.txt b/plugins/kolab_addressbook/README.txt new file mode 100644 index 000000000..87537c0b8 --- /dev/null +++ b/plugins/kolab_addressbook/README.txt @@ -0,0 +1,32 @@ +Kolab Integration Plugin README +------------------------------- + +This plugin relies on classes from the Horde project. In order to have all +the required files available you need to install the following packages from +Horde: + Horde_Framework + Kolab_Format + Kolab_Storage + Horde_NLS + Horde_DOM + +This is best done using PEAR. Make sure that the local PEAR directory is in +the PHP isntall path and execute the following commands to install the +required packages: + +pear channel-discover pear.horde.org + +pear install horde/Horde_Framework +pear install horde/Horde_DOM +pear install horde/Horde_NLS +pear install horde/Horde_Share +pear install horde/Log +pear install horde/Kolab_Format +pear install horde/Kolab_Storage + + +Configuration +------------- + +Rename the config.inc.php.dist to config.inc.php within this plugin directory +and add the corresponding values for your local Kolab server. diff --git a/plugins/kolab_addressbook/config.inc.php.dist b/plugins/kolab_addressbook/config.inc.php.dist new file mode 100644 index 000000000..b6ac25a4d --- /dev/null +++ b/plugins/kolab_addressbook/config.inc.php.dist @@ -0,0 +1,8 @@ +<?php + +// Sample configuration for Kolab LDAP binding used by Kolab_Storage +$rcmail_config['kolab']['ldap']['basedn'] = 'dc=kolabserver,dc=local'; +$rcmail_config['kolab']['ldap']['phpdn'] = 'cn=nobody,cn=internal,dc=kolabserver,dc=local'; +$rcmail_config['kolab']['ldap']['phppw'] = '<ldap-pwd-goes-here>'; + +?> diff --git a/plugins/kolab_addressbook/kolab_addressbook.php b/plugins/kolab_addressbook/kolab_addressbook.php index 0e29c2ebb..9c8383e3d 100644 --- a/plugins/kolab_addressbook/kolab_addressbook.php +++ b/plugins/kolab_addressbook/kolab_addressbook.php @@ -17,23 +17,31 @@ require_once(dirname(__FILE__) . '/rcube_kolab_contacts.php'); class kolab_addressbook extends rcube_plugin { private $abook_id = 'kolab'; + private $abook; /** * Required startup method of a Roundcube plugin */ public function init() { + // load local config + $this->load_config(); + $this->add_hook('addressbooks_list', array($this, 'address_sources')); $this->add_hook('addressbook_get', array($this, 'get_address_book')); + $this->add_hook('imap_init', array($this, 'imap_init')); // use this address book for autocompletion queries - // (maybe this should be configurable by the user?) $config = rcmail::get_instance()->config; $sources = (array) $config->get('autocomplete_addressbooks', array('sql')); if (!in_array($this->abook_id, $sources)) { $sources[] = $this->abook_id; $config->set('autocomplete_addressbooks', $sources); } + + // extend include path to load bundled Horde classes + $include_path = $this->home . '/lib' . PATH_SEPARATOR . ini_get('include_path'); + set_include_path($include_path); } /** @@ -47,10 +55,10 @@ class kolab_addressbook extends rcube_plugin */ public function address_sources($p) { - // could be changed to a factory call - $abook = new rcube_kolab_contacts; + // get single instance (for now) + $abook = rcube_kolab_contacts::singleton(); - // maybe here we add more than one item. + // maybe here we'll add more than one item $p['sources'][$this->abook_id] = array( 'id' => $this->abook_id, 'name' => 'Kolab', @@ -60,16 +68,26 @@ class kolab_addressbook extends rcube_plugin return $p; } + /** - * + * Getter for the rcube_addressbook instance */ public function get_address_book($p) { if ($p['id'] === $this->abook_id) { - $p['instance'] = new rcube_kolab_contacts; + $p['instance'] = rcube_kolab_contacts::singleton(); } - + return $p; } + + /** + * Make sure the X-Kolab-Type headers are also fetched when listing messages + */ + function imap_init($p) + { + $p['fetch_headers'] = strtoupper('X-Kolab-Type'); + return $p; + } } diff --git a/plugins/kolab_addressbook/lib/rcube_kolab.php b/plugins/kolab_addressbook/lib/rcube_kolab.php index e3588f8f5..44c37a68f 100644 --- a/plugins/kolab_addressbook/lib/rcube_kolab.php +++ b/plugins/kolab_addressbook/lib/rcube_kolab.php @@ -1,5 +1,11 @@ <?php +require_once 'Horde/Kolab/Format/XML.php'; +require_once 'Horde/Kolab/Storage/List.php'; +require_once 'Horde/Auth.php'; +require_once 'Horde/Auth/kolab.php'; +require_once 'Horde/Perms.php'; + /** * Glue class to handle access to the Kolab data using the Kolab_* classes * from the Horde project. @@ -8,24 +14,39 @@ */ class rcube_kolab { + private static $horde_auth; + /** * Setup the environment needed by the Kolab_* classes to access Kolab data */ public static function setup() { + global $conf; + + // setup already done + if (self::$horde_auth) + return; + $rcmail = rcmail::get_instance(); - // if we need IMAP access through Roundcube IMAP class - // $rcmail->imap_init(); - - // get some config settings for the IMAP connection - $imap_auth_method = $rcmail->config->get('imap_auth_type', 'check'); - $imap_delimiter = isset($_SESSION['imap_delimiter']) ? $_SESSION['imap_delimiter'] : $rcmail->config->get('imap_delimiter'); - - // this is how we get the current IMAP authentication credentials: - // $_SESSION['imap_host'], $_SESSION['username'], $rcmail->decrypt($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl'] + // load ldap credentials from local config + $conf['kolab'] = $rcmail->config->get('kolab'); + $conf['kolab']['ldap']['server'] = 'ldap://' . $_SESSION['imap_host'] . ':389'; + $conf['kolab']['imap']['server'] = $_SESSION['imap_host']; + $conf['kolab']['imap']['port'] = $_SESSION['imap_port']; + // pass the current IMAP authentication credentials to the Horde auth system + self::$horde_auth = Auth::singleton('kolab'); + if (self::$horde_auth->authenticate($_SESSION['username'], array('password' => ($pwd = $rcmail->decrypt($_SESSION['password']))), false)) { + $_SESSION['__auth'] = array( + 'authenticated' => true, + 'userId' => $_SESSION['username'], + 'timestamp' => time(), + 'remote_addr' => $_SERVER['REMOTE_ADDR'], + ); + Auth::setCredential('password', $pwd); + } } diff --git a/plugins/kolab_addressbook/rcube_kolab_contacts.php b/plugins/kolab_addressbook/rcube_kolab_contacts.php index d209cce63..476202e33 100644 --- a/plugins/kolab_addressbook/rcube_kolab_contacts.php +++ b/plugins/kolab_addressbook/rcube_kolab_contacts.php @@ -1,7 +1,5 @@ <?php -require_once(dirname(__FILE__) . '/lib/rcube_kolab.php'); - /** * Backend class for a custom address book @@ -18,8 +16,29 @@ class rcube_kolab_contacts extends rcube_addressbook public $readonly = true; public $groups = true; + private static $instance; + + private $_gid; + private $_imap; + private $_kolab; + private $_folder; + private $_data; + private $_groups; + private $_uid2index; private $filter; private $result; + private $imap_folder = 'INBOX/Contacts'; + + + /** + * Singleton getter + */ + public static function singleton() + { + if (!self::$instance) + self::$instance = new rcube_kolab_contacts; + return self::$instance; + } public function __construct() @@ -27,9 +46,36 @@ class rcube_kolab_contacts extends rcube_addressbook // setup Kolab backend rcube_kolab::setup(); - // $this->share = Kolab_Storage::getShare(); + // fetch objects from Cotnacts folder + $this->_kolab = Kolab_List::singleton(); + $this->_folder = $this->_kolab->getFolder($this->imap_folder); + $this->_storage = $this->_folder->getData(); + $this->_objects = $this->_storage->getObjects(); + + // dump objects to log/console + console($this->_objects); + + // TEMPORARY SOLUTION: use Roundcube's IMAP connection to fetch data + $rcmail = rcmail::get_instance(); + $rcmail->imap_connect(); + $this->_imap = $rcmail->imap; + + $folders = $this->_imap->list_unsubscribed(); - $this->ready = true; + if (in_array($this->imap_folder, $folders)) { + $this->_imap->set_pagesize(9999); + $this->_imap->set_mailbox($this->imap_folder); + $this->ready = true; + } + } + + + /** + * Setter for the current group + */ + function set_group($gid) + { + $this->_gid = $gid; } @@ -72,10 +118,11 @@ class rcube_kolab_contacts extends rcube_addressbook */ function list_groups($search = null) { - return array( - #array('ID' => 'testgroup1', 'name' => "Testgroup"), - #array('ID' => 'testgroup2', 'name' => "Sample Group"), - ); + $this->_fetch_data(); + $groups = array(); + foreach ($this->_groups as $group) + $groups[] = array('ID' => $group['ID'], 'name' => $group['last-name']); + return $groups; } /** @@ -87,13 +134,76 @@ class rcube_kolab_contacts extends rcube_addressbook */ public function list_records($cols=null, $subset=0) { - $this->result = $this->count(); + if ($this->_gid) { + $data = $this->_fetch_data(); + $this->result = $this->count(); + + foreach ((array)$this->_groups[$this->_gid]['member'] as $member) { + $this->result->add($data->records[$this->_uid2index[$member['uid']]]); + } + } + else + $this->result = $this->_fetch_data(); - // Just return a sample contact record for now - $this->result->add(array('ID' => '111', 'name' => "Kolab Contact", 'firstname' => "Kolab", 'surname' => "Contact", 'email' => "example@kolab.org")); - return $this->result; } + + + /** + * Simply fetch all records and store them in a result_set object + */ + private function _fetch_data() + { + if ($this->_data) + return $this->_data; + + $this->_data = new rcube_result_set(0, ($this->list_page-1) * $this->page_size); + $this->_groups = $this->_uid2index = array(); + + $xml_contact = Horde_Kolab_Format_XML::factory('contact'); + $xml_list = Horde_Kolab_Format_XML::factory('distributionlist'); + + $index = 0; + $headers = $this->_imap->list_headers(); + foreach ($headers as $header) { + if ($type = $header->others['x-kolab-type']) { + if ($type == 'application/x-vnd.kolab.contact') + $loader = $xml_contact; + else if ($type == 'application/x-vnd.kolab.distribution-list') + $loader = $xml_list; + else + continue; + + $record = $loader->load($this->_imap->get_message_part($header->uid, '2')); + if (PEAR::isError($record)) { + raise_error(array( + 'code' => 600, 'type' => 'php', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "Failed to load XML data from IMAP record:" . $record->getMessage()), + true, false); + } + else if ($type == 'application/x-vnd.kolab.contact') { + $this->_data->add(array( + 'ID' => md5($record['uid']), + 'name' => $record['full-name'], + 'firstname' => $record['given-name'], + 'surname' => $record['last-name'], + 'email' => $record['emails'], + )); + $this->_data->count++; + $this->_uid2index[$record['uid']] = $index++; + } + else if ($type == 'application/x-vnd.kolab.distribution-list') { + $record['ID'] = md5($record['uid']); + foreach ($record['member'] as $i => $member) + $record['member'][$i]['ID'] = md5($member['uid']); + $this->_groups[$record['ID']] = $record; + } + } + } + + return $this->_data; + } /** @@ -118,7 +228,9 @@ class rcube_kolab_contacts extends rcube_addressbook */ public function count() { - return new rcube_result_set(1, ($this->list_page-1) * $this->page_size); + $this->_fetch_data(); + $count = $this->_gid ? count($this->_groups[$this->_gid]['member']) : $this->_data->count; + return new rcube_result_set($count, ($this->list_page-1) * $this->page_size); } @@ -141,15 +253,43 @@ class rcube_kolab_contacts extends rcube_addressbook */ public function get_record($id, $assoc=false) { - $this->list_records(); - $first = $this->result->first(); - $sql_arr = $first['ID'] == $id ? $first : null; - - return $assoc && $sql_arr ? $sql_arr : $this->result; + $list = $this->_fetch_data(); + $rec = $list->first(); + do { + if ($rec['ID'] == $id) + break; + } + while ($rec = $list->next()); + + $this->result = new rcube_result_set(1); + $this->result->add($rec); + + return $assoc ? $rec : $this->result; } /** + * Get group assignments of a specific contact record + * + * @param mixed Record identifier + * @return array List of assigned groups as ID=>Name pairs + */ + function get_record_groups($id) + { + $out = array(); + + foreach ($this->_groups as $gid => $group) { + foreach ($group['member'] as $member) { + if ($member['ID'] == $id) + $out[$gid] = $group['last-name']; + } + } + + return $out; + } + + + /** * Close connection to source * Called on script shutdown */ |
