From 1c51c1a9d94582da32109cc21b58178d6d4b32e1 Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Wed, 15 Jun 2011 11:23:59 +0200 Subject: [PATCH 1/9] Added rcube_kolab::folder_id() with improved ID generation method --- plugins/calendar/drivers/kolab/kolab_calendar.php | 8 ++++---- plugins/kolab_addressbook/kolab_addressbook.php | 2 +- plugins/kolab_core/rcube_kolab.php | 10 ++++++++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/plugins/calendar/drivers/kolab/kolab_calendar.php b/plugins/calendar/drivers/kolab/kolab_calendar.php index ecb58939..8f85c619 100644 --- a/plugins/calendar/drivers/kolab/kolab_calendar.php +++ b/plugins/calendar/drivers/kolab/kolab_calendar.php @@ -39,7 +39,6 @@ class kolab_calendar 'sensitivity'=>'sensitivity', 'show-time-as' => 'free_busy', 'alarm','alarms' - ); /** @@ -47,11 +46,11 @@ class kolab_calendar */ public function __construct($imap_folder = null) { - if ($imap_folder) + if (strlen($imap_folder)) $this->imap_folder = $imap_folder; - write_log('err_log',$imap_folder); + // ID is derrived from folder name - $this->id = strtolower(asciiwords(strtr($this->imap_folder, '/.', '--'))); + $this->id = rcube_kolab::folder_id($this->imap_folder); // fetch objects from the given IMAP folder $this->storage = rcube_kolab::get_storage($this->imap_folder); @@ -68,6 +67,7 @@ class kolab_calendar */ public function get_name() { + // @TODO: get namespace prefixes from IMAP $dispname = preg_replace(array('!INBOX/Calendar/!', '!^INBOX/!', '!^shared/!', '!^user/([^/]+)/!'), array('','','','(\\1) '), $this->imap_folder); return strlen($dispname) ? $dispname : $this->imap_folder; } diff --git a/plugins/kolab_addressbook/kolab_addressbook.php b/plugins/kolab_addressbook/kolab_addressbook.php index 20d986bd..7a97e672 100644 --- a/plugins/kolab_addressbook/kolab_addressbook.php +++ b/plugins/kolab_addressbook/kolab_addressbook.php @@ -202,7 +202,7 @@ class kolab_addressbook extends rcube_plugin else { foreach ($this->folders as $c_folder) { // create instance of rcube_contacts - $abook_id = strtolower(asciiwords(strtr($c_folder->name, '/.', '--'))); + $abook_id = rcube_kolab::folder_id($c_folder->name); $abook = new rcube_kolab_contacts($c_folder->name); $this->sources[$abook_id] = $abook; } diff --git a/plugins/kolab_core/rcube_kolab.php b/plugins/kolab_core/rcube_kolab.php index 7c837de0..d800d773 100644 --- a/plugins/kolab_core/rcube_kolab.php +++ b/plugins/kolab_core/rcube_kolab.php @@ -119,4 +119,14 @@ class rcube_kolab if (isset($_SESSION['__auth'])) unset($_SESSION['__auth']); } + + /** + * Creates folder ID from folder name + */ + public static function folder_id($folder) + { + $folder = rcube_charset_convert($folder, RCMAIL_CHARSET, 'UTF7-IMAP'); + return asciiwords(strtr($folder, '/.', '--')); + } + } From 431c1b4e1c001b3c23d2fc3e31a9012ffecea01d Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Wed, 15 Jun 2011 12:31:36 +0200 Subject: [PATCH 2/9] Horde classes are using UTF7-IMAP encoding (see also https://bugzilla.kolabsys.com/show_bug.cgi?id=116) --- plugins/kolab_addressbook/rcube_kolab_contacts.php | 4 +++- plugins/kolab_core/README.txt | 1 + plugins/kolab_core/rcube_kolab.php | 9 ++++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/plugins/kolab_addressbook/rcube_kolab_contacts.php b/plugins/kolab_addressbook/rcube_kolab_contacts.php index 2774cd65..af3daa8d 100644 --- a/plugins/kolab_addressbook/rcube_kolab_contacts.php +++ b/plugins/kolab_addressbook/rcube_kolab_contacts.php @@ -130,7 +130,9 @@ class rcube_kolab_contacts extends rcube_addressbook */ public function get_name() { - return strtr(preg_replace('!^(INBOX|user)/!i', '', $this->imap_folder), '/', ':'); + $folder = rcube_charset_convert($this->imap_folder, 'UTF7-IMAP'); + // @TODO: use namespace prefixes + return strtr(preg_replace('!^(INBOX|user)/!i', '', $folder), '/', ':'); } diff --git a/plugins/kolab_core/README.txt b/plugins/kolab_core/README.txt index 89c64a60..3b82e898 100644 --- a/plugins/kolab_core/README.txt +++ b/plugins/kolab_core/README.txt @@ -20,6 +20,7 @@ pear install Net_DNS2 pear install Net_SMTP pear install Mail_mimeDecode pear install Auth_SASL +pear install Date Configuration diff --git a/plugins/kolab_core/rcube_kolab.php b/plugins/kolab_core/rcube_kolab.php index d800d773..92ec41fa 100644 --- a/plugins/kolab_core/rcube_kolab.php +++ b/plugins/kolab_core/rcube_kolab.php @@ -87,7 +87,7 @@ class rcube_kolab * Get a list of storage folders for the given data type * * @param string Data type to list folders for (contact,event,task,note) - * @return array List of Kolab_Folder objects + * @return array List of Kolab_Folder objects (folder names in UTF7-IMAP) */ public static function get_folders($type) { @@ -99,7 +99,7 @@ class rcube_kolab /** * Get storage object for read/write access to the Kolab backend * - * @param string IMAP folder to access + * @param string IMAP folder to access (UTF7-IMAP) * @param string Object type to deal with (leave empty for auto-detection using annotations) * @return object Kolab_Data The data storage object */ @@ -122,10 +122,13 @@ class rcube_kolab /** * Creates folder ID from folder name + * + * @param string $folder Folder name (UTF7-IMAP) + * + * @return string Folder ID string */ public static function folder_id($folder) { - $folder = rcube_charset_convert($folder, RCMAIL_CHARSET, 'UTF7-IMAP'); return asciiwords(strtr($folder, '/.', '--')); } From ea20b03cf326f674f97334ba5416eeff65ec0faf Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Wed, 15 Jun 2011 15:28:13 +0200 Subject: [PATCH 3/9] Add css classes to folders table rows. E.g. "type-default type-event" Don't subscribe to non-mail folders on folder creation --- plugins/kolab_folders/README | 1 + plugins/kolab_folders/kolab_folders.php | 80 ++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 8 deletions(-) diff --git a/plugins/kolab_folders/README b/plugins/kolab_folders/README index 9edf913b..ac4a56d7 100644 --- a/plugins/kolab_folders/README +++ b/plugins/kolab_folders/README @@ -10,6 +10,7 @@ The plugin extends folders handling with features of the Kolab Suite. With this plugin enabled it is possible to: - set/get/change folder's type - filter folders list by folder type. + - style folders list rows (in folder manager) http://www.kolab.org/doc/kolabformat-2.0-html diff --git a/plugins/kolab_folders/kolab_folders.php b/plugins/kolab_folders/kolab_folders.php index c64daf10..7f0a3330 100644 --- a/plugins/kolab_folders/kolab_folders.php +++ b/plugins/kolab_folders/kolab_folders.php @@ -3,7 +3,7 @@ /** * Type-aware folder management/listing for Kolab * - * @version 0.2 + * @version 0.3 * @author Aleksander Machniak * * @@ -46,6 +46,7 @@ class kolab_folders extends rcube_plugin $this->add_hook('folder_form', array($this, 'folder_form')); $this->add_hook('folder_update', array($this, 'folder_save')); $this->add_hook('folder_create', array($this, 'folder_save')); + $this->add_hook('folders_list', array($this, 'folders_list')); } /** @@ -116,6 +117,43 @@ class kolab_folders extends rcube_plugin return $args; } + /** + * Handler for folders_list hook. Add css classes to folder rows. + */ + function folders_list($args) + { + if (!$this->metadata_support()) { + return $args; + } + + $table = $args['table']; + + // get folders types + $folderdata = $this->get_folder_type_list('*'); + + if (!is_array($folderdata)) { + return $args; + } + + // Add type-based style for table rows + // See kolab_folders::folder_class_name() + for ($i=0, $cnt=$table->size(); $i<$cnt; $i++) { + $attrib = $table->get_row_attribs($i); + $folder = $attrib['foldername']; // UTF7-IMAP + $data = $folderdata[$folder]; + + if (!empty($data) + && ($type = $data[kolab_folders::CTYPE_KEY]) + && ($class_name = self::folder_class_name($type)) + ) { + $attrib['class'] = trim($attrib['class'] . ' ' . $class_name); + $table->set_row_attribs($attrib, $i); + } + } + + return $args; + } + /** * Handler for folder info/edit form (folder_form hook). * Adds folder type selector. @@ -177,10 +215,11 @@ class kolab_folders extends rcube_plugin */ function folder_save($args) { - $ctype = trim(get_input_value('_ctype', RCUBE_INPUT_POST)); - $subtype = trim(get_input_value('_subtype', RCUBE_INPUT_POST)); - $mbox = $args['record']['name']; - $old_mbox = $args['record']['oldname']; + $ctype = trim(get_input_value('_ctype', RCUBE_INPUT_POST)); + $subtype = trim(get_input_value('_subtype', RCUBE_INPUT_POST)); + $mbox = $args['record']['name']; + $old_mbox = $args['record']['oldname']; + $subscribe = $args['record']['subscribe']; if (empty($ctype)) { return $args; @@ -190,7 +229,7 @@ class kolab_folders extends rcube_plugin if ($subtype == 'default') { } // Subtype sanity-checks - else if ($subtype && $ctype != 'mail' || !in_array($subtype, $this->mail_types)) { + else if ($subtype && ($ctype != 'mail' || !in_array($subtype, $this->mail_types))) { $subtype = ''; } @@ -198,7 +237,11 @@ class kolab_folders extends rcube_plugin // Create folder if (!strlen($old_mbox)) { - $result = $this->rc->imap->create_mailbox($mbox, true); + // By default don't subscribe to non-mail folders + if ($subscribe) + $subscribe = preg_match('/^mail/', $ctype); + + $result = $this->rc->imap->create_mailbox($mbox, $subscribe); // Set folder type if ($result) { $this->set_folder_type($mbox, $ctype); @@ -223,6 +266,9 @@ class kolab_folders extends rcube_plugin } } + $args['record']['class'] = self::folder_class_name($ctype); + $args['record']['subscribe'] = $subscribe; + // Skip folder creation/rename in core // @TODO: Maybe we should provide folder_create_after and folder_update_after hooks? // Using create_mailbox/rename_mailbox here looks bad @@ -340,5 +386,23 @@ class kolab_folders extends rcube_plugin return $metadata; } -} + /** + * Returns CSS class name for specified folder type + * + * @param string $type Folder type + * + * @return string Class name + */ + static function folder_class_name($type) + { + list($ctype, $subtype) = explode('.', $type); + + $class[] = 'type-' . ($ctype ? $ctype : 'mail'); + + if ($subtype == 'default') + $class[] = 'type-default'; + + return implode(' ', $class); + } +} From 406722b756c0c471798843ced9bf153bd4045a7f Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Wed, 15 Jun 2011 15:31:29 +0200 Subject: [PATCH 4/9] Add class for subtypes other than "default" --- plugins/kolab_folders/kolab_folders.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/kolab_folders/kolab_folders.php b/plugins/kolab_folders/kolab_folders.php index 7f0a3330..38154e30 100644 --- a/plugins/kolab_folders/kolab_folders.php +++ b/plugins/kolab_folders/kolab_folders.php @@ -400,8 +400,8 @@ class kolab_folders extends rcube_plugin $class[] = 'type-' . ($ctype ? $ctype : 'mail'); - if ($subtype == 'default') - $class[] = 'type-default'; + if ($subtype) + $class[] = 'subtype-' . $subtype; return implode(' ', $class); } From 625e8f4f051091840c879d11a636289c26b86e58 Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Wed, 15 Jun 2011 15:42:58 +0200 Subject: [PATCH 5/9] Add type-mail class to all folders without specified type --- plugins/kolab_folders/kolab_folders.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/plugins/kolab_folders/kolab_folders.php b/plugins/kolab_folders/kolab_folders.php index 38154e30..69d8b29f 100644 --- a/plugins/kolab_folders/kolab_folders.php +++ b/plugins/kolab_folders/kolab_folders.php @@ -142,13 +142,16 @@ class kolab_folders extends rcube_plugin $folder = $attrib['foldername']; // UTF7-IMAP $data = $folderdata[$folder]; - if (!empty($data) - && ($type = $data[kolab_folders::CTYPE_KEY]) - && ($class_name = self::folder_class_name($type)) - ) { - $attrib['class'] = trim($attrib['class'] . ' ' . $class_name); - $table->set_row_attribs($attrib, $i); - } + if (!empty($data)) + $type = $data[kolab_folders::CTYPE_KEY]; + + if (!$type) + $type = 'mail'; + + $class_name = self::folder_class_name($type); + + $attrib['class'] = trim($attrib['class'] . ' ' . $class_name); + $table->set_row_attribs($attrib, $i); } return $args; @@ -239,7 +242,7 @@ class kolab_folders extends rcube_plugin if (!strlen($old_mbox)) { // By default don't subscribe to non-mail folders if ($subscribe) - $subscribe = preg_match('/^mail/', $ctype); + $subscribe = (bool) preg_match('/^mail/', $ctype); $result = $this->rc->imap->create_mailbox($mbox, $subscribe); // Set folder type From 6de3f3666ef0782fbb2a79b792b26f6a91f764a2 Mon Sep 17 00:00:00 2001 From: "Jeroen van Meeuwen (Kolab Systems)" Date: Wed, 15 Jun 2011 14:12:56 -0500 Subject: [PATCH 6/9] Illegal operands are not a good idea. --- plugins/kolab_core/rcube_kolab.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/kolab_core/rcube_kolab.php b/plugins/kolab_core/rcube_kolab.php index 92ec41fa..e01de1cf 100644 --- a/plugins/kolab_core/rcube_kolab.php +++ b/plugins/kolab_core/rcube_kolab.php @@ -51,8 +51,8 @@ class rcube_kolab } // Re-set LDAP/IMAP host config - $conf['kolab']['ldap'] += array('server' => 'ldap://' . $_SESSION['imap_host'] . ':389'); - $conf['kolab']['imap'] += array('server' => $_SESSION['imap_host'], 'port' => $_SESSION['imap_port']); + $conf['kolab']['ldap'] = array('server' => 'ldap://' . $_SESSION['imap_host'] . ':389'); + $conf['kolab']['imap'] = array('server' => $_SESSION['imap_host'], 'port' => $_SESSION['imap_port']); // pass the current IMAP authentication credentials to the Horde auth system self::$horde_auth = Auth::singleton('kolab'); From 7c72f38ef56a0daa6ba7a6c6607d7486638ee055 Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Thu, 16 Jun 2011 09:59:03 +0200 Subject: [PATCH 7/9] Don't read .dist config file --- plugins/calendar/calendar.php | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php index 9089383a..72be17ab 100644 --- a/plugins/calendar/calendar.php +++ b/plugins/calendar/calendar.php @@ -33,28 +33,31 @@ class calendar extends rcube_plugin public $ical; public $ui; + private $default_categories = array( + 'Personal' => 'c0c0c0', + 'Work' => 'ff0000', + 'Family' => '00ff00', + 'Holiday' => 'ff6600', + ); + /** * Plugin initialization. */ function init() { $this->rc = rcmail::get_instance(); - + $this->register_task('calendar', 'calendar'); - + // load calendar configuration - if(file_exists($this->home . "/config.inc.php")) { - $this->load_config('config.inc.php'); - } else { - $this->load_config('config.inc.php.dist'); - } - + $this->load_config(); + // load localizations $this->add_texts('localization/', !$this->rc->action || $this->rc->task != 'calendar'); // load Calendar user interface which includes jquery-ui $this->require_plugin('jqueryui'); - + require($this->home . '/lib/calendar_ui.php'); $this->ui = new calendar_ui($this); $this->ui->init(); @@ -254,9 +257,9 @@ class calendar extends rcube_plugin if (!$this->driver->categoriesimmutable) { $p['blocks']['categories']['name'] = $this->gettext('categories'); - $categories = $this->rc->config->get('calendar_categories', array()); + $categories = (array) $this->rc->config->get('calendar_categories', $this->default_categories); $categories_list = ''; - foreach ($categories as $name => $color){ + foreach ($categories as $name => $color) { $key = md5($name); $field_class = 'rcmfd_category_' . str_replace(' ', '_', $name); $category_remove = new html_inputfield(array('type' => 'button', 'value' => 'X', 'class' => 'button', 'onclick' => '$(this).parent().remove()', 'title' => $this->gettext('remove_category'))); @@ -549,7 +552,7 @@ class calendar extends rcube_plugin $this->rc->gettext('nov'), $this->rc->gettext('dec') ); $settings['today'] = rcube_label('today'); - + // user prefs $settings['hidden_calendars'] = array_filter(explode(',', $this->rc->config->get('hidden_calendars', ''))); From a672f926b8221883c4f088efd189a40ccaf320bc Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Thu, 16 Jun 2011 14:51:11 +0200 Subject: [PATCH 8/9] Fixed last commit, better handling of malformed/incomplete configuration --- plugins/kolab_core/config.inc.php.dist | 13 ++++++++----- plugins/kolab_core/rcube_kolab.php | 15 +++++++++------ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/plugins/kolab_core/config.inc.php.dist b/plugins/kolab_core/config.inc.php.dist index 888820a4..9aecf8bd 100644 --- a/plugins/kolab_core/config.inc.php.dist +++ b/plugins/kolab_core/config.inc.php.dist @@ -1,14 +1,17 @@ array()); +// Horde/Kolab classes configuration +$rcmail_config['kolab'] = array( + // IMAP configuration (e.g. connection info, namespaces) + 'imap' => array(), + // Global Horde classes configuration (e.g. cache settings) + 'global' => array(), +); +// Sample configuration for Kolab LDAP binding used by Kolab_Storage //$rcmail_config['kolab']['ldap']['server'] = ''; $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'] = ''; -// Global Horde classes configuration (e.g. Cache settings) -$rcmail_config['kolab']['global'] = array(); - ?> diff --git a/plugins/kolab_core/rcube_kolab.php b/plugins/kolab_core/rcube_kolab.php index e01de1cf..429e1cfa 100644 --- a/plugins/kolab_core/rcube_kolab.php +++ b/plugins/kolab_core/rcube_kolab.php @@ -34,15 +34,15 @@ class rcube_kolab $rcmail = rcmail::get_instance(); // Set Horde configuration - $GLOBALS['conf']['sql'] = MDB2::parseDSN($rcmail->config->get('db_dsnw')); - $GLOBALS['conf']['sql']['charset'] = 'utf-8'; - $GLOBALS['conf']['sql']['phptype'] = 'mysql'; + $conf['sql'] = MDB2::parseDSN($rcmail->config->get('db_dsnw')); + $conf['sql']['charset'] = 'utf-8'; + $conf['sql']['phptype'] = 'mysql'; // get password of logged user $pwd = $rcmail->decrypt($_SESSION['password']); // load ldap credentials from local config - $conf['kolab'] = $rcmail->config->get('kolab'); + $conf['kolab'] = (array) $rcmail->config->get('kolab'); // Set global Horde config (e.g. Cache settings) if (!empty($conf['kolab']['global'])) { @@ -51,8 +51,11 @@ class rcube_kolab } // Re-set LDAP/IMAP host config - $conf['kolab']['ldap'] = array('server' => 'ldap://' . $_SESSION['imap_host'] . ':389'); - $conf['kolab']['imap'] = array('server' => $_SESSION['imap_host'], 'port' => $_SESSION['imap_port']); + $ldap = array('server' => 'ldap://' . $_SESSION['imap_host'] . ':389'); + $imap = array('server' => $_SESSION['imap_host'], 'port' => $_SESSION['imap_port']); + + $conf['kolab']['ldap'] = array_merge($ldap, (array)$conf['kolab']['ldap']); + $conf['kolab']['imap'] = array_merge($imap, (array)$conf['kolab']['imap']); // pass the current IMAP authentication credentials to the Horde auth system self::$horde_auth = Auth::singleton('kolab'); From 120dc7cb6336454fa033b6189e1a165d21565d82 Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Thu, 16 Jun 2011 15:01:09 +0200 Subject: [PATCH 9/9] Configure read-only DB for Horde cache --- plugins/kolab_core/rcube_kolab.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/plugins/kolab_core/rcube_kolab.php b/plugins/kolab_core/rcube_kolab.php index 429e1cfa..03d5a25d 100644 --- a/plugins/kolab_core/rcube_kolab.php +++ b/plugins/kolab_core/rcube_kolab.php @@ -33,10 +33,18 @@ class rcube_kolab $rcmail = rcmail::get_instance(); - // Set Horde configuration - $conf['sql'] = MDB2::parseDSN($rcmail->config->get('db_dsnw')); + // Set Horde configuration (for cache db) + $dsnw = MDB2::parseDSN($rcmail->config->get('db_dsnw')); + $dsnr = MDB2::parseDSN($rcmail->config->get('db_dsnr')); + + $conf['sql'] = MDB2::parseDSN($dsnw); $conf['sql']['charset'] = 'utf-8'; - $conf['sql']['phptype'] = 'mysql'; + + if (!empty($dsnr) && $dsnr != $dsnw) { + $conf['sql']['read'] = MDB2::parseDSN($dsnr); + $conf['sql']['read']['charset'] = 'utf-8'; + $conf['sql']['splitread'] = true; + } // get password of logged user $pwd = $rcmail->decrypt($_SESSION['password']);