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', ''))); diff --git a/plugins/calendar/drivers/kolab/kolab_calendar.php b/plugins/calendar/drivers/kolab/kolab_calendar.php index 7b23b2cf..0b6dbbf6 100644 --- a/plugins/calendar/drivers/kolab/kolab_calendar.php +++ b/plugins/calendar/drivers/kolab/kolab_calendar.php @@ -40,7 +40,6 @@ class kolab_calendar 'sensitivity'=>'sensitivity', 'show-time-as' => 'free_busy', 'alarm','alarms' - ); /** @@ -48,11 +47,11 @@ class kolab_calendar */ public function __construct($imap_folder = null) { - if ($imap_folder) + if (strlen($imap_folder)) $this->imap_folder = $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); @@ -69,6 +68,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 rcube_charset_convert(strlen($dispname) ? $dispname : $this->imap_folder, "UTF7-IMAP"); } 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_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/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 7c837de0..03d5a25d 100644 --- a/plugins/kolab_core/rcube_kolab.php +++ b/plugins/kolab_core/rcube_kolab.php @@ -33,16 +33,24 @@ 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'; + // 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'; + + 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']); // 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 +59,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'); @@ -87,7 +98,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 +110,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 */ @@ -119,4 +130,17 @@ class rcube_kolab if (isset($_SESSION['__auth'])) unset($_SESSION['__auth']); } + + /** + * Creates folder ID from folder name + * + * @param string $folder Folder name (UTF7-IMAP) + * + * @return string Folder ID string + */ + public static function folder_id($folder) + { + return asciiwords(strtr($folder, '/.', '--')); + } + } 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..69d8b29f 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,46 @@ 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]; + + 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; + } + /** * Handler for folder info/edit form (folder_form hook). * Adds folder type selector. @@ -177,10 +218,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 +232,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 +240,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 = (bool) 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 +269,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 +389,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) + $class[] = 'subtype-' . $subtype; + + return implode(' ', $class); + } +}