Fixed bug where Error No.700 was thrown by Roundcube in cases

when there's no addressbook (no subscribed contact folders and no
global addressbooks). It's fixed by forcing folder creation/subscription
and forcing of kolab_addressbook_prio value accordingly (Bug #2086).
This commit is contained in:
Aleksander Machniak 2013-08-07 09:39:21 +02:00
parent cb22497440
commit 27eb706939
2 changed files with 178 additions and 48 deletions

View file

@ -31,7 +31,6 @@ class kolab_addressbook extends rcube_plugin
{
public $task = 'mail|settings|addressbook|calendar';
private $folders;
private $sources;
private $rc;
private $ui;
@ -93,11 +92,8 @@ class kolab_addressbook extends rcube_plugin
*/
public function address_sources($p)
{
// Load configuration
$this->load_config();
$abook_prio = (int) $this->rc->config->get('kolab_addressbook_prio');
$undelete = $this->rc->config->get('undo_timeout');
$abook_prio = $this->addressbook_prio();
$undelete = $this->rc->config->get('undo_timeout');
// Disable all global address books
// Assumes that all non-kolab_addressbook sources are global
@ -155,10 +151,7 @@ class kolab_addressbook extends rcube_plugin
return $args;
}
// Load configuration
$this->load_config();
$abook_prio = (int) $this->rc->config->get('kolab_addressbook_prio');
$abook_prio = $this->addressbook_prio();
// here we cannot use rc->config->get()
$sources = $GLOBALS['CONFIG']['autocomplete_addressbooks'];
@ -222,10 +215,7 @@ class kolab_addressbook extends rcube_plugin
$this->sources = array();
// Load configuration
$this->load_config();
$abook_prio = (int) $this->rc->config->get('kolab_addressbook_prio');
$abook_prio = $this->addressbook_prio();
// Personal address source(s) disabled?
if ($abook_prio == self::GLOBAL_ONLY) {
@ -233,19 +223,27 @@ class kolab_addressbook extends rcube_plugin
}
// get all folders that have "contact" type
$this->folders = kolab_storage::sort_folders(kolab_storage::get_folders('contact'));
$folders = kolab_storage::sort_folders(kolab_storage::get_folders('contact'));
if (PEAR::isError($this->folders)) {
if (PEAR::isError($folders)) {
rcube::raise_error(array(
'code' => 600, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Failed to list contact folders from Kolab server:" . $this->folders->getMessage()),
'message' => "Failed to list contact folders from Kolab server:" . $folders->getMessage()),
true, false);
}
else {
// we need at least one folder to prevent from errors in Roundcube core
// when there's also no sql nor ldap addressbook (Bug #2086)
if (empty($folders)) {
if ($folder = kolab_storage::create_default_folder('contact')) {
$folders = array(new kolab_storage_folder($folder, 'contact'));
}
}
// convert to UTF8 and sort
$names = array();
foreach ($this->folders as $folder) {
foreach ($folders as $folder) {
// create instance of rcube_contacts
$abook_id = kolab_storage::folder_id($folder->name);
$abook = new rcube_kolab_contacts($folder->name);
@ -325,16 +323,22 @@ class kolab_addressbook extends rcube_plugin
return $args;
}
// Load configuration
$this->load_config();
$ldap_public = $this->rc->config->get('ldap_public');
$abook_type = $this->rc->config->get('address_book_type');
// Load localization
$this->add_texts('localization');
// Hide option if there's no global addressbook
if (empty($ldap_public) || $abook_type != 'ldap') {
return $args;
}
// Check that configuration is not disabled
$dont_override = (array) $this->rc->config->get('dont_override', array());
$dont_override = (array) $this->rc->config->get('dont_override', array());
$prio = $this->addressbook_prio();
if (!in_array('kolab_addressbook_prio', $dont_override)) {
// Load localization
$this->add_texts('localization');
$field_id = '_kolab_addressbook_prio';
$select = new html_select(array('name' => $field_id, 'id' => $field_id));
@ -345,7 +349,7 @@ class kolab_addressbook extends rcube_plugin
$args['blocks']['main']['options']['kolab_addressbook_prio'] = array(
'title' => html::label($field_id, Q($this->gettext('addressbookprio'))),
'content' => $select->show((int)$this->rc->config->get('kolab_addressbook_prio')),
'content' => $select->show($prio),
);
}
@ -365,14 +369,11 @@ class kolab_addressbook extends rcube_plugin
return $args;
}
// Load configuration
$this->load_config();
// Check that configuration is not disabled
$dont_override = (array) $this->rc->config->get('dont_override', array());
$dont_override = (array) $this->rc->config->get('dont_override', array());
$key = 'kolab_addressbook_prio';
if (!in_array('kolab_addressbook_prio', $dont_override)) {
$key = 'kolab_addressbook_prio';
if (!in_array('kolab_addressbook_prio', $dont_override) || !isset($_POST['_'.$key])) {
$args['prefs'][$key] = (int) get_input_value('_'.$key, RCUBE_INPUT_POST);
}
@ -506,4 +507,30 @@ class kolab_addressbook extends rcube_plugin
$this->rc->output->send();
}
/**
* Returns value of kolab_addressbook_prio setting
*/
private function addressbook_prio()
{
// Load configuration
if (!$this->config_loaded) {
$this->load_config();
$this->config_loaded = true;
}
$abook_prio = (int) $this->rc->config->get('kolab_addressbook_prio');
// Make sure any global addressbooks are defined
if ($abook_prio == 0 || $abook_prio == 2) {
$ldap_public = $this->rc->config->get('ldap_public');
$abook_type = $this->rc->config->get('address_book_type');
if (empty($ldap_public) || $abook_type != 'ldap') {
$abook_prio = 1;
}
}
return $abook_prio;
}
}

View file

@ -41,6 +41,23 @@ class kolab_storage
private static $config;
private static $imap;
// Default folder names
private static $default_folders = array(
'event' => 'Calendar',
'contact' => 'Contacts',
'task' => 'Tasks',
'note' => 'Notes',
'file' => 'Files',
'configuration' => 'Configuration',
'journal' => 'Journal',
'mail.inbox' => 'INBOX',
'mail.drafts' => 'Drafts',
'mail.sentitems' => 'Sent',
'mail.wastebasket' => 'Trash',
'mail.outbox' => 'Outbox',
'mail.junkemail' => 'Junk',
);
/**
* Setup the environment needed by the libs
@ -349,25 +366,8 @@ class kolab_storage
$result = self::folder_create($folder, $prop['type'], $prop['subscribed'], $prop['active']);
}
// save displayname and color in METADATA
// TODO: also save 'showalarams' and other properties here
if ($result) {
$ns = null;
foreach (array('color' => array(self::COLOR_KEY_SHARED,self::COLOR_KEY_PRIVATE),
'displayname' => array(self::NAME_KEY_SHARED,self::NAME_KEY_PRIVATE)) as $key => $metakeys) {
if (!empty($prop[$key])) {
if (!isset($ns))
$ns = self::$imap->folder_namespace($folder);
$meta_saved = false;
if ($ns == 'personal') // save in shared namespace for personal folders
$meta_saved = self::$imap->set_metadata($folder, array($metakeys[0] => $prop[$key]));
if (!$meta_saved) // try in private namespace
$meta_saved = self::$imap->set_metadata($folder, array($metakeys[1] => $prop[$key]));
if ($meta_saved)
unset($prop[$key]); // unsetting will prevent fallback to local user prefs
}
}
self::set_folder_props($folder, $prop);
}
return $result ? $folder : false;
@ -913,4 +913,107 @@ class kolab_storage
$rcube = rcube::get_instance();
return $rcube->user->save_prefs(array('kolab_active_folders' => $folders));
}
/**
* Creates default folder of specified type
* To be run when none of subscribed folders (of specified type) is found
*
* @param string $type Folder type
* @param string $props Folder properties (color, etc)
*
* @return string Folder name
*/
public static function create_default_folder($type, $props = array())
{
if (!self::setup()) {
return;
}
$folders = self::$imap->get_metadata('*', array(kolab_storage::CTYPE_KEY_PRIVATE));
// from kolab_folders config
$folder_type = strpos($type, '.') ? str_replace('.', '_', $type) : $type . '_default';
$default_name = self::$config->get('kolab_folders_' . $folder_type);
$folder_type = str_replace('_', '.', $folder_type);
// check if we have any folder in personal namespace
// folder(s) may exist but not subscribed
foreach ($folders as $f => $data) {
if (strpos($data[self::CTYPE_KEY_PRIVATE], $type) === 0) {
$folder = $f;
break;
}
}
if (!$folder) {
if (!$default_name) {
$default_name = self::$default_folders[$type];
}
if (!$default_name) {
return;
}
$folder = rcube_charset::convert($default_name, RCUBE_CHARSET, 'UTF7-IMAP');
$prefix = self::$imap->get_namespace('prefix');
// add personal namespace prefix if needed
if ($prefix && strpos($folder, $prefix) !== 0 && $folder != 'INBOX') {
$folder = $prefix . $folder;
}
if (!self::$imap->folder_exists($folder)) {
if (!self::$imap->folder_create($folder)) {
return;
}
}
self::set_folder_type($folder, $folder_type);
}
self::folder_subscribe($folder);
if ($props['active']) {
self::set_state($folder, true);
}
if (!empty($props)) {
self::set_folder_props($folder, $props);
}
return $folder;
}
/**
* Sets folder metadata properties
*
* @param string $folder Folder name
* @param array $prop Folder properties
*/
public static function set_folder_props($folder, &$prop)
{
if (!self::setup()) {
return;
}
// TODO: also save 'showalarams' and other properties here
$ns = self::$imap->folder_namespace($folder);
$supported = array(
'color' => array(self::COLOR_KEY_SHARED, self::COLOR_KEY_PRIVATE),
'displayname' => array(self::NAME_KEY_SHARED, self::NAME_KEY_PRIVATE),
);
foreach ($supported as $key => $metakeys) {
if (array_key_exists($key, $prop)) {
$meta_saved = false;
if ($ns == 'personal') // save in shared namespace for personal folders
$meta_saved = self::$imap->set_metadata($folder, array($metakeys[0] => $prop[$key]));
if (!$meta_saved) // try in private namespace
$meta_saved = self::$imap->set_metadata($folder, array($metakeys[1] => $prop[$key]));
if ($meta_saved)
unset($prop[$key]); // unsetting will prevent fallback to local user prefs
}
}
}
}