Merge branch 'master' of ssh://git.kolabsys.com/git/roundcube
This commit is contained in:
commit
8c5d9db9cc
14 changed files with 1087 additions and 42 deletions
|
@ -95,6 +95,8 @@ abstract class calendar_driver
|
|||
/**
|
||||
* Delete the given calendar with all its contents
|
||||
*
|
||||
* @param array Hash array with calendar properties
|
||||
* id: Calendar Identifier
|
||||
* @return boolean True on success, Fales on failure
|
||||
*/
|
||||
abstract function remove_calendar($prop);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
| |
|
||||
+-------------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
| Author: Aleksander Machniak <machniak@kolabsys.com> |
|
||||
+-------------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
|
@ -20,7 +21,7 @@ class kolab_calendar
|
|||
public $id;
|
||||
public $ready = false;
|
||||
public $readonly = true;
|
||||
|
||||
|
||||
private $cal;
|
||||
private $storage;
|
||||
private $events;
|
||||
|
@ -29,7 +30,7 @@ class kolab_calendar
|
|||
private $sensitivity_map = array('public', 'private', 'confidential');
|
||||
private $priority_map = array('low', 'normal', 'high');
|
||||
|
||||
|
||||
|
||||
private $fieldmap = array(
|
||||
// kolab => roundcube
|
||||
'summary' => 'title',
|
||||
|
@ -42,14 +43,14 @@ class kolab_calendar
|
|||
'show-time-as' => 'free_busy',
|
||||
'alarm','alarms'
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public function __construct($imap_folder, $calendar)
|
||||
{
|
||||
$this->cal = $calendar;
|
||||
|
||||
|
||||
if (strlen($imap_folder))
|
||||
$this->imap_folder = $imap_folder;
|
||||
|
||||
|
@ -75,7 +76,19 @@ class kolab_calendar
|
|||
$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");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Getter for the IMAP folder name
|
||||
*
|
||||
* @return string Name of the IMAP folder
|
||||
*/
|
||||
public function get_realname()
|
||||
{
|
||||
return $this->imap_folder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Getter for the top-end calendar folder name (not the entire path)
|
||||
*
|
||||
|
@ -84,22 +97,24 @@ class kolab_calendar
|
|||
public function get_foldername()
|
||||
{
|
||||
$parts = explode('/', $this->imap_folder);
|
||||
return end($parts);
|
||||
return rcube_charset_convert(end($parts), 'UTF7-IMAP');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return color to display this calendar
|
||||
*/
|
||||
public function get_color($owner)
|
||||
public function get_color()
|
||||
{
|
||||
// TODO: read color from backend (not yet supported)
|
||||
//temporary color deffirence between own calendars and the rest
|
||||
if ($owner == $_SESSION['username'])
|
||||
return 'd63355';
|
||||
return '1f9ebe';
|
||||
// Store temporarily calendar color in user prefs (will be changed)
|
||||
$prefs = $this->cal->rc->config->get('kolab_calendars', array());
|
||||
|
||||
if (!empty($prefs[$this->id]) && !empty($prefs[$this->id]['color']))
|
||||
return $prefs[$this->id]['color'];
|
||||
|
||||
return 'cc0000';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Getter for a single event object
|
||||
*/
|
||||
|
|
|
@ -71,7 +71,7 @@ class kolab_driver extends calendar_driver
|
|||
'id' => $calendar->id,
|
||||
'name' => $calendar->get_name(),
|
||||
'editname' => $calendar->get_foldername(),
|
||||
'color' => $calendar->get_color($c_folder->_owner),
|
||||
'color' => $calendar->get_color(),
|
||||
'readonly' => $c_folder->_owner != $_SESSION['username'],
|
||||
);
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ class kolab_driver extends calendar_driver
|
|||
if ($this->create_calendar(array('name' => 'Default', 'color' => 'cc0000')))
|
||||
$this->_read_calendars();
|
||||
}
|
||||
|
||||
|
||||
return $this->calendars;
|
||||
}
|
||||
|
||||
|
@ -117,10 +117,30 @@ class kolab_driver extends calendar_driver
|
|||
*/
|
||||
public function create_calendar($prop)
|
||||
{
|
||||
|
||||
$folder = rcube_charset_convert($prop['name'], RCMAIL_CHARSET, 'UTF7-IMAP');
|
||||
|
||||
// add namespace prefix (when needed)
|
||||
$this->rc->imap_init();
|
||||
$folder = $this->rc->imap->mod_mailbox($folder, 'in');
|
||||
|
||||
// create ID
|
||||
$id = rcube_kolab::folder_id($folder);
|
||||
|
||||
// create IMAP folder
|
||||
if (rcube_kolab::folder_create($folder, 'event')) {
|
||||
// save color in user prefs (temp. solution)
|
||||
$prefs['kolab_calendars'] = $this->rc->config->get('kolab_calendars', array());
|
||||
$prefs['kolab_calendars'][$id]['color'] = $prop['color'];
|
||||
|
||||
$this->rc->user->save_prefs($prefs);
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update properties of an existing calendar
|
||||
*
|
||||
|
@ -128,9 +148,36 @@ class kolab_driver extends calendar_driver
|
|||
*/
|
||||
public function edit_calendar($prop)
|
||||
{
|
||||
if ($prop['id'] && ($cal = $this->folders[$prop['id']])) {
|
||||
$newfolder = rcube_charset_convert($prop['name'], RCMAIL_CHARSET, 'UTF7-IMAP');
|
||||
$oldfolder = $cal->get_realname();
|
||||
// add namespace prefix (when needed)
|
||||
$this->rc->imap_init();
|
||||
$newfolder = $this->rc->imap->mod_mailbox($newfolder, 'in');
|
||||
|
||||
if ($newfolder != $oldfolder)
|
||||
$result = rcube_kolab::folder_rename($oldfolder, $newfolder);
|
||||
else
|
||||
$result = true;
|
||||
|
||||
if ($result) {
|
||||
// create ID
|
||||
$id = rcube_kolab::folder_id($newfolder);
|
||||
// save color in user prefs (temp. solution)
|
||||
$prefs['kolab_calendars'] = $this->rc->config->get('kolab_calendars', array());
|
||||
$prefs['kolab_calendars'][$id]['color'] = $prop['color'];
|
||||
unset($prefs['kolab_calendars'][$prop['id']]);
|
||||
|
||||
$this->rc->user->save_prefs($prefs);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete the given calendar with all its contents
|
||||
*
|
||||
|
@ -138,7 +185,18 @@ class kolab_driver extends calendar_driver
|
|||
*/
|
||||
public function remove_calendar($prop)
|
||||
{
|
||||
|
||||
if ($prop['id'] && ($cal = $this->folders[$prop['id']])) {
|
||||
$folder = $cal->get_realname();
|
||||
if (rcube_kolab::folder_delete($folder)) {
|
||||
// remove color in user prefs (temp. solution)
|
||||
$prefs['kolab_calendars'] = $this->rc->config->get('kolab_calendars', array());
|
||||
unset($prefs['kolab_calendars'][$prop['id']]);
|
||||
|
||||
$this->rc->user->save_prefs($prefs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -153,7 +211,7 @@ class kolab_driver extends calendar_driver
|
|||
$cid = $event['calendar'] ? $event['calendar'] : reset(array_keys($this->calendars));
|
||||
if ($storage = $this->_get_storage($cid))
|
||||
return $storage->insert_event($event);
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -167,7 +225,7 @@ class kolab_driver extends calendar_driver
|
|||
{
|
||||
if ($storage = $this->_get_storage($event['calendar']))
|
||||
return $storage->update_event($event);
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -181,7 +239,7 @@ class kolab_driver extends calendar_driver
|
|||
{
|
||||
if (($storage = $this->_get_storage($event['calendar'])) && ($ev = $storage->get_event($event['id'])))
|
||||
return $storage->update_event($event + $ev);
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
256
plugins/kolab_addressbook/kolab_addressbook.js
Normal file
256
plugins/kolab_addressbook/kolab_addressbook.js
Normal file
|
@ -0,0 +1,256 @@
|
|||
if (window.rcmail) {
|
||||
rcmail.addEventListener('init', function() {
|
||||
rcmail.set_book_actions();
|
||||
if (rcmail.gui_objects.editform && rcmail.env.action.match(/^plugin\.book/)) {
|
||||
rcmail.enable_command('book-save', true);
|
||||
}
|
||||
});
|
||||
rcmail.addEventListener('listupdate', function() {
|
||||
rcmail.set_book_actions();
|
||||
});
|
||||
}
|
||||
|
||||
// (De-)activates address book management commands
|
||||
rcube_webmail.prototype.set_book_actions = function()
|
||||
{
|
||||
var source = this.env.source,
|
||||
sources = this.env.address_sources;
|
||||
|
||||
this.enable_command('book-create', true);
|
||||
this.enable_command('book-edit', 'book-delete', source && sources[source] && sources[source].kolab && sources[source].editable);
|
||||
};
|
||||
|
||||
rcube_webmail.prototype.book_create = function()
|
||||
{
|
||||
this.book_show_contentframe('create');
|
||||
};
|
||||
|
||||
rcube_webmail.prototype.book_edit = function()
|
||||
{
|
||||
this.book_show_contentframe('edit');
|
||||
};
|
||||
|
||||
rcube_webmail.prototype.book_delete = function()
|
||||
{
|
||||
if (this.env.source != '' && confirm(this.get_label('kolab_addressbook.bookdeleteconfirm'))) {
|
||||
var lock = this.set_busy(true, 'kolab_addressbook.bookdeleting');
|
||||
this.http_request('plugin.book', '_act=delete&_source='+urlencode(this.book_realname()), lock);
|
||||
}
|
||||
};
|
||||
|
||||
// displays page with book edit/create form
|
||||
rcube_webmail.prototype.book_show_contentframe = function(action, framed)
|
||||
{
|
||||
var add_url = '', target = window;
|
||||
|
||||
// unselect contact
|
||||
this.contact_list.clear_selection();
|
||||
this.enable_command('edit', 'delete', 'compose', false);
|
||||
|
||||
if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) {
|
||||
add_url = '&_framed=1';
|
||||
target = window.frames[this.env.contentframe];
|
||||
this.show_contentframe(true);
|
||||
}
|
||||
else if (framed)
|
||||
return false;
|
||||
|
||||
if (action) {
|
||||
this.set_busy(true);
|
||||
this.location_href(this.env.comm_path+'&_action=plugin.book&_act='+action
|
||||
+'&_source='+urlencode(this.book_realname())
|
||||
+add_url, target);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// submits book create/update form
|
||||
rcube_webmail.prototype.book_save = function()
|
||||
{
|
||||
var form = this.gui_objects.editform,
|
||||
input = $("input[name='_name']", form)
|
||||
|
||||
if (input.length && input.val() == '') {
|
||||
alert(this.get_label('kolab_addressbook.nobooknamewarning'));
|
||||
input.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
input = this.display_message(this.get_label('kolab_addressbook.booksaving'), 'loading');
|
||||
$('<input type="hidden" name="_unlock" />').val(input).appendTo(form);
|
||||
|
||||
form.submit();
|
||||
};
|
||||
|
||||
// action executed after book delete
|
||||
rcube_webmail.prototype.book_delete_done = function(id)
|
||||
{
|
||||
var n, g, li = this.get_folder_li(id), groups = this.env.contactgroups;
|
||||
|
||||
// remove folder and its groups rows
|
||||
for (n in groups)
|
||||
if (groups[n].source == id && (g = this.get_folder_li(n))) {
|
||||
$(g).remove();
|
||||
delete this.env.contactgroups[n];
|
||||
}
|
||||
$(li).remove();
|
||||
|
||||
delete this.env.address_sources[id];
|
||||
delete this.env.contactfolders[id];
|
||||
};
|
||||
|
||||
// action executed after book create/update
|
||||
rcube_webmail.prototype.book_update = function(data, old)
|
||||
{
|
||||
var n, i, id, len, row, refrow, olddata, name = '', realname = '', sources, level,
|
||||
folders = [], class_name = 'addressbook',
|
||||
list = this.gui_objects.folderlist,
|
||||
groups = this.env.contactgroups;
|
||||
|
||||
this.env.contactfolders[data.id] = this.env.address_sources[data.id] = data;
|
||||
this.show_contentframe(false);
|
||||
|
||||
// update
|
||||
if (old && old != data.id) {
|
||||
olddata = this.env.address_sources[old];
|
||||
delete this.env.address_sources[old];
|
||||
delete this.env.contactfolders[old];
|
||||
|
||||
// update source ID in groups
|
||||
for (n in groups)
|
||||
if (groups[n].source == old)
|
||||
this.env.contactgroups[n].source = data.id;
|
||||
|
||||
refrow = $('#rcmli'+old);
|
||||
}
|
||||
// create
|
||||
else if (!old) {
|
||||
refrow = $('li', list).get(0);
|
||||
|
||||
// this shouldn't happen
|
||||
if (!refrow)
|
||||
this.redirect(this.get_task_url('addressbook'));
|
||||
}
|
||||
|
||||
if (!refrow)
|
||||
return;
|
||||
|
||||
sources = this.env.address_sources;
|
||||
|
||||
// clone a table row if there are existing rows
|
||||
row = $(refrow).clone();
|
||||
|
||||
// set row attributes
|
||||
if (data.readonly)
|
||||
class_name += ' readonly';
|
||||
if (data.class_name)
|
||||
class_name += ' '+data.class_name;
|
||||
// updated currently selected book
|
||||
if (this.env.source != '' && this.env.source == old) {
|
||||
class_name += ' selected';
|
||||
this.env.source = data.id;
|
||||
}
|
||||
|
||||
row.attr({id: 'rcmli'+data.id, 'class': class_name});
|
||||
$('a', row).html(data.name).attr({onclick: '', rel: data.id, href: '#'})
|
||||
.click({id: data.id}, function(e) { return rcmail.command('list', e.data.id, this); });
|
||||
|
||||
// sort kolab folders, to put the new one in order
|
||||
for (n in sources)
|
||||
if (sources[n].kolab && (name = sources[n].realname))
|
||||
folders.push(name);
|
||||
folders.sort();
|
||||
|
||||
// find current id
|
||||
for (n=0, len=folders.length; n<len; n++)
|
||||
if (folders[n] == data.realname)
|
||||
break;
|
||||
|
||||
// add row
|
||||
if (n && n < len) {
|
||||
// find the row before
|
||||
name = folders[n-1];
|
||||
for (n in sources)
|
||||
if (sources[n].realname && sources[n].realname == name) {
|
||||
row.insertAfter('#rcmli'+n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (olddata) {
|
||||
row.insertBefore(refrow);
|
||||
}
|
||||
else {
|
||||
row.appendTo(list);
|
||||
}
|
||||
|
||||
if (olddata) {
|
||||
// remove old row (just after the new row has been inserted)
|
||||
refrow.remove();
|
||||
old += '-';
|
||||
level = olddata.realname.split(this.env.delimiter).length - data.realname.split(this.env.delimiter).length;
|
||||
// update (realname and ID of) subfolders
|
||||
for (n in sources) {
|
||||
if (n.indexOf(old) == 0) {
|
||||
// new ID
|
||||
id = data.id + '-' + n.substr(old.length);
|
||||
name = sources[n].name;
|
||||
realname = data.realname + sources[n].realname.substr(olddata.realname.length);
|
||||
|
||||
// update display name
|
||||
if (level > 0) {
|
||||
for (i=level; i>0; i--)
|
||||
name = name.replace(/^ /, '');
|
||||
}
|
||||
else if (level < 0) {
|
||||
for (i=level; i<0; i++)
|
||||
name = ' ' + name;
|
||||
}
|
||||
|
||||
// update existing row
|
||||
refrow = $('#rcmli'+n);
|
||||
refrow.remove().attr({id: 'rcmli'+id});
|
||||
$('a', refrow).html(name).attr({onclick: '', rel: id, href: '#'})
|
||||
.click({id: id}, function(e) { return rcmail.command('list', e.data.id, this); });
|
||||
|
||||
// move the row to the new place
|
||||
refrow.insertAfter(row);
|
||||
row = refrow;
|
||||
|
||||
// update list data
|
||||
sources[n].id = id;
|
||||
sources[n].name = name;
|
||||
sources[n].realname = realname;
|
||||
this.env.address_sources[id] = this.env.contactfolders[id] = sources[n];
|
||||
delete this.env.address_sources[n];
|
||||
delete this.env.contactfolders[n];
|
||||
|
||||
// update groups
|
||||
for (i in groups) {
|
||||
if (groups[i].source == n) {
|
||||
// update existing row
|
||||
refrow = $('#rcmli'+i);
|
||||
refrow.remove().attr({id: 'rcmliG'+id+groups[i].id});
|
||||
$('a', refrow).attr('onclick', '')
|
||||
.click({source: id, id: groups[i].id}, function(e) {
|
||||
return rcmail.command('listgroup', {'source': e.data.source, 'id': e.data.id}, this); });
|
||||
refrow.insertAfter(row);
|
||||
row = refrow;
|
||||
|
||||
// update group data
|
||||
groups[i].source = id;
|
||||
this.env.contactgroups['G'+id+groups[i].id] = groups[i];
|
||||
delete this.env.contactgroups[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// returns real IMAP folder name
|
||||
rcube_webmail.prototype.book_realname = function()
|
||||
{
|
||||
var source = this.env.source, sources = this.env.address_sources;
|
||||
return source != '' && sources[source] && sources[source].realname ? sources[source].realname : '';
|
||||
};
|
|
@ -1,12 +1,11 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(__FILE__) . '/rcube_kolab_contacts.php');
|
||||
|
||||
/**
|
||||
* Kolab address book
|
||||
* Kolab address book 0.5
|
||||
*
|
||||
* Sample plugin to add a new address book source with data from Kolab storage
|
||||
* This is work-in-progress for the Roundcube+Kolab integration.
|
||||
* It provides also a possibilities to manage contact folders
|
||||
* (create/rename/delete/acl) directly in Addressbook UI.
|
||||
*
|
||||
* @author Thomas Bruederli <roundcube@gmail.com>
|
||||
* @author Aleksander Machniak <machniak@kolabsys.com>
|
||||
|
@ -28,9 +27,12 @@ require_once(dirname(__FILE__) . '/rcube_kolab_contacts.php');
|
|||
*/
|
||||
class kolab_addressbook extends rcube_plugin
|
||||
{
|
||||
public $task = 'mail|settings|addressbook';
|
||||
|
||||
private $folders;
|
||||
private $sources;
|
||||
private $rc;
|
||||
private $ui;
|
||||
|
||||
const GLOBAL_FIRST = 0;
|
||||
const PERSONAL_FIRST = 1;
|
||||
|
@ -42,6 +44,8 @@ class kolab_addressbook extends rcube_plugin
|
|||
*/
|
||||
public function init()
|
||||
{
|
||||
require_once(dirname(__FILE__) . '/lib/rcube_kolab_contacts.php');
|
||||
|
||||
$this->rc = rcmail::get_instance();
|
||||
|
||||
// load required plugin
|
||||
|
@ -54,6 +58,16 @@ class kolab_addressbook extends rcube_plugin
|
|||
if ($this->rc->task == 'addressbook') {
|
||||
$this->add_texts('localization');
|
||||
$this->add_hook('contact_form', array($this, 'contact_form'));
|
||||
|
||||
// Plugin actions
|
||||
$this->register_action('plugin.book', array($this, 'book_actions'));
|
||||
$this->register_action('plugin.book-save', array($this, 'book_save'));
|
||||
|
||||
// Load UI elements
|
||||
if ($this->api->output->type == 'html') {
|
||||
require_once($this->home . '/lib/kolab_addressbook_ui.php');
|
||||
$this->ui = new kolab_addressbook_ui($this);
|
||||
}
|
||||
}
|
||||
else if ($this->rc->task == 'settings') {
|
||||
$this->add_texts('localization');
|
||||
|
@ -92,13 +106,33 @@ class kolab_addressbook extends rcube_plugin
|
|||
}
|
||||
|
||||
$sources = array();
|
||||
$names = array();
|
||||
|
||||
foreach ($this->_list_sources() as $abook_id => $abook) {
|
||||
$name = $origname = $abook->get_name();
|
||||
|
||||
// find folder prefix to truncate
|
||||
for ($i = count($names)-1; $i >= 0; $i--) {
|
||||
if (strpos($name, $names[$i].' » ') === 0) {
|
||||
$length = strlen($names[$i].' » ');
|
||||
$prefix = substr($name, 0, $length);
|
||||
$count = count(explode(' » ', $prefix));
|
||||
$name = str_repeat(' ', $count-1) . '» ' . substr($name, $length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$names[] = $origname;
|
||||
|
||||
// register this address source
|
||||
$sources[$abook_id] = array(
|
||||
'id' => $abook_id,
|
||||
'name' => $abook->get_name(),
|
||||
'id' => $abook_id,
|
||||
'name' => $name,
|
||||
'readonly' => $abook->readonly,
|
||||
'groups' => $abook->groups,
|
||||
'editable' => $abook->editable,
|
||||
'groups' => $abook->groups,
|
||||
'realname' => rcube_charset_convert($abook->get_realname(), 'UTF7-IMAP'), // IMAP folder name
|
||||
'class_name' => $abook->get_namespace(),
|
||||
'kolab' => true,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -200,10 +234,17 @@ class kolab_addressbook extends rcube_plugin
|
|||
true, false);
|
||||
}
|
||||
else {
|
||||
foreach ($this->folders as $c_folder) {
|
||||
// convert to UTF8 and sort
|
||||
$names = array();
|
||||
foreach ($this->folders as $c_folder)
|
||||
$names[$c_folder->name] = rcube_charset_convert($c_folder->name, 'UTF7-IMAP');
|
||||
|
||||
asort($names, SORT_LOCALE_STRING);
|
||||
|
||||
foreach ($names as $utf7name => $name) {
|
||||
// create instance of rcube_contacts
|
||||
$abook_id = rcube_kolab::folder_id($c_folder->name);
|
||||
$abook = new rcube_kolab_contacts($c_folder->name);
|
||||
$abook_id = rcube_kolab::folder_id($utf7name);
|
||||
$abook = new rcube_kolab_contacts($utf7name);
|
||||
$this->sources[$abook_id] = $abook;
|
||||
}
|
||||
}
|
||||
|
@ -282,7 +323,7 @@ class kolab_addressbook extends rcube_plugin
|
|||
// Load configuration
|
||||
$this->load_config();
|
||||
|
||||
// Load localization and configuration
|
||||
// Load localization
|
||||
$this->add_texts('localization');
|
||||
|
||||
// Check that configuration is not disabled
|
||||
|
@ -333,4 +374,180 @@ class kolab_addressbook extends rcube_plugin
|
|||
return $args;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler for plugin actions
|
||||
*/
|
||||
public function book_actions()
|
||||
{
|
||||
$action = trim(get_input_value('_act', RCUBE_INPUT_GPC));
|
||||
|
||||
if ($action == 'create') {
|
||||
$this->ui->book_edit();
|
||||
}
|
||||
else if ($action == 'edit') {
|
||||
$this->ui->book_edit();
|
||||
}
|
||||
else if ($action == 'delete') {
|
||||
$this->book_delete();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler for address book create/edit form submit
|
||||
*/
|
||||
public function book_save()
|
||||
{
|
||||
$folder = trim(get_input_value('_name', RCUBE_INPUT_POST, true, 'UTF7-IMAP'));
|
||||
$oldfolder = trim(get_input_value('_oldname', RCUBE_INPUT_POST, true)); // UTF7-IMAP
|
||||
$path = trim(get_input_value('_parent', RCUBE_INPUT_POST, true)); // UTF7-IMAP
|
||||
$delimiter = $_SESSION['imap_delimiter'];
|
||||
|
||||
// sanity checks (from steps/settings/save_folder.inc)
|
||||
if (!strlen($folder)) {
|
||||
$error = rcube_label('cannotbeempty');
|
||||
}
|
||||
else if (strlen($name) > 128) {
|
||||
$error = rcube_label('nametoolong');
|
||||
}
|
||||
else {
|
||||
// these characters are problematic e.g. when used in LIST/LSUB
|
||||
foreach (array($delimiter, '%', '*') as $char) {
|
||||
if (strpos($name, $delimiter) !== false) {
|
||||
$error = rcube_label('forbiddencharacter') . " ($char)";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$error) {
|
||||
// @TODO: $options
|
||||
$options = array();
|
||||
if ($options['protected'] || $options['norename']) {
|
||||
$folder = $oldfolder;
|
||||
}
|
||||
else if (strlen($path)) {
|
||||
$folder = $path . $delimiter . $folder;
|
||||
}
|
||||
else {
|
||||
// add namespace prefix (when needed)
|
||||
$this->rc->imap_init();
|
||||
$folder = $this->rc->imap->mod_mailbox($folder, 'in');
|
||||
}
|
||||
|
||||
// update the folder name
|
||||
if (strlen($oldfolder)) {
|
||||
$type = 'update';
|
||||
$plugin = $this->rc->plugins->exec_hook('addressbook_update', array(
|
||||
'name' => $folder, 'oldname' => $oldfolder));
|
||||
|
||||
if (!$plugin['abort']) {
|
||||
if ($oldfolder != $folder)
|
||||
$result = rcube_kolab::folder_rename($oldfolder, $folder);
|
||||
else
|
||||
$result = true;
|
||||
}
|
||||
else {
|
||||
$result = $plugin['result'];
|
||||
}
|
||||
}
|
||||
// create new folder
|
||||
else {
|
||||
$type = 'create';
|
||||
$plugin = $this->rc->plugins->exec_hook('addressbook_create', array('name' => $folder));
|
||||
|
||||
$folder = $plugin['name'];
|
||||
|
||||
if (!$plugin['abort']) {
|
||||
$result = rcube_kolab::folder_create($folder, 'contact', false);
|
||||
}
|
||||
else {
|
||||
$result = $plugin['result'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
$kolab_folder = new rcube_kolab_contacts($folder);
|
||||
|
||||
// create display name for the folder (see self::address_sources())
|
||||
if (strpos($folder, $delimiter)) {
|
||||
$names = array();
|
||||
foreach ($this->_list_sources() as $abook_id => $abook) {
|
||||
$realname = $abook->get_realname();
|
||||
// The list can be not updated yet, handle old folder name
|
||||
if ($type == 'update' && $realname == $oldfolder) {
|
||||
$abook = $kolab_folder;
|
||||
$realname = $folder;
|
||||
}
|
||||
|
||||
$name = $origname = $abook->get_name();
|
||||
|
||||
// find folder prefix to truncate
|
||||
for ($i = count($names)-1; $i >= 0; $i--) {
|
||||
if (strpos($name, $names[$i].' » ') === 0) {
|
||||
$length = strlen($names[$i].' » ');
|
||||
$prefix = substr($name, 0, $length);
|
||||
$count = count(explode(' » ', $prefix));
|
||||
$name = str_repeat(' ', $count-1) . '» ' . substr($name, $length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$names[] = $origname;
|
||||
|
||||
if ($realname == $folder) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$name = $kolab_folder->get_name();
|
||||
}
|
||||
|
||||
$this->rc->output->show_message('kolab_addressbook.book'.$type.'d', 'confirmation');
|
||||
$this->rc->output->command('set_env', 'delimiter', $delimiter);
|
||||
$this->rc->output->command('book_update', array(
|
||||
'id' => rcube_kolab::folder_id($folder),
|
||||
'name' => $name,
|
||||
'readonly' => false,
|
||||
'editable' => true,
|
||||
'groups' => true,
|
||||
'realname' => rcube_charset_convert($folder, 'UTF7-IMAP'), // IMAP folder name
|
||||
'class_name' => $kolab_folder->get_namespace(),
|
||||
'kolab' => true,
|
||||
), rcube_kolab::folder_id($oldfolder));
|
||||
|
||||
$this->rc->output->send('iframe');
|
||||
}
|
||||
|
||||
if (!$error)
|
||||
$error = $plugin['message'] ? $plugin['message'] : 'kolab_addressbook.book'.$type.'error';
|
||||
|
||||
$this->rc->output->show_message($error, 'error');
|
||||
// display the form again
|
||||
$this->ui->book_edit();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler for address book delete action (AJAX)
|
||||
*/
|
||||
private function book_delete()
|
||||
{
|
||||
$folder = trim(get_input_value('_source', RCUBE_INPUT_GPC, true, 'UTF7-IMAP'));
|
||||
|
||||
if (rcube_kolab::folder_delete($folder)) {
|
||||
$this->rc->output->show_message('kolab_addressbook.bookdeleted', 'confirmation');
|
||||
$this->rc->output->set_env('pagecount', 0);
|
||||
$this->rc->output->command('set_rowcount', rcmail_get_rowcount_text(new rcube_result_set()));
|
||||
$this->rc->output->command('list_contacts_clear');
|
||||
$this->rc->output->command('book_delete_done', rcube_kolab::folder_id($folder));
|
||||
}
|
||||
else {
|
||||
$this->rc->output->show_message('kolab_addressbook.bookdeleteerror', 'error');
|
||||
}
|
||||
|
||||
$this->rc->output->send();
|
||||
}
|
||||
}
|
||||
|
|
273
plugins/kolab_addressbook/lib/kolab_addressbook_ui.php
Normal file
273
plugins/kolab_addressbook/lib/kolab_addressbook_ui.php
Normal file
|
@ -0,0 +1,273 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Kolab address book UI
|
||||
*
|
||||
* @author Aleksander Machniak <machniak@kolabsys.com>
|
||||
*
|
||||
* Copyright (C) 2011, Kolab Systems AG
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
class kolab_addressbook_ui
|
||||
{
|
||||
private $plugin;
|
||||
private $rc;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param kolab_addressbook $plugin Plugin object
|
||||
*/
|
||||
public function __construct($plugin)
|
||||
{
|
||||
$this->rc = rcmail::get_instance();
|
||||
$this->plugin = $plugin;
|
||||
|
||||
$this->init_ui();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds folders management functionality to Addressbook UI
|
||||
*/
|
||||
private function init_ui()
|
||||
{
|
||||
if (!empty($this->rc->action) && !preg_match('/^plugin\.book/', $this->rc->action)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Include script
|
||||
$this->plugin->include_script('kolab_addressbook.js');
|
||||
|
||||
if (empty($this->rc->action)) {
|
||||
// Include stylesheet (for directorylist)
|
||||
$this->plugin->include_stylesheet($this->plugin->local_skin_path().'/kolab_addressbook.css');
|
||||
|
||||
// Add actions on address books
|
||||
$options = array('book-create', 'book-edit', 'book-delete');
|
||||
$idx = 0;
|
||||
|
||||
foreach ($options as $command) {
|
||||
$content = html::tag('li', $idx ? null : array('class' => 'separator_above'),
|
||||
$this->plugin->api->output->button(array(
|
||||
'label' => 'kolab_addressbook.'.str_replace('-', '', $command),
|
||||
'domain' => $this->ID,
|
||||
'classact' => 'active',
|
||||
'command' => $command
|
||||
)));
|
||||
$this->plugin->api->add_content($content, 'groupoptions');
|
||||
$idx++;
|
||||
}
|
||||
|
||||
$this->rc->output->add_label('kolab_addressbook.bookdeleteconfirm',
|
||||
'kolab_addressbook.bookdeleting');
|
||||
}
|
||||
// book create/edit form
|
||||
else {
|
||||
$this->rc->output->add_label('kolab_addressbook.nobooknamewarning',
|
||||
'kolab_addressbook.booksaving');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler for address book create/edit action
|
||||
*/
|
||||
public function book_edit()
|
||||
{
|
||||
$this->rc->output->add_handler('bookdetails', array($this, 'book_form'));
|
||||
$this->rc->output->send('kolab_addressbook.bookedit');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler for 'bookdetails' object returning form content for book create/edit
|
||||
*
|
||||
* @param array $attr Object attributes
|
||||
*
|
||||
* @return string HTML output
|
||||
*/
|
||||
public function book_form($attrib)
|
||||
{
|
||||
$action = trim(get_input_value('_act', RCUBE_INPUT_GPC));
|
||||
$folder = trim(get_input_value('_source', RCUBE_INPUT_GPC, true)); // UTF8
|
||||
$name = trim(get_input_value('_name', RCUBE_INPUT_GPC, true)); // UTF8
|
||||
$old = trim(get_input_value('_oldname', RCUBE_INPUT_GPC, true)); // UTF7-IMAP
|
||||
$path_imap = trim(get_input_value('_parent', RCUBE_INPUT_GPC, true)); // UTF7-IMAP
|
||||
|
||||
$hidden_fields[] = array('name' => '_source', 'value' => $folder);
|
||||
|
||||
$folder = rcube_charset_convert($folder, RCMAIL_CHARSET, 'UTF7-IMAP');
|
||||
$delim = $_SESSION['imap_delimiter'];
|
||||
$form = array();
|
||||
|
||||
if ($this->rc->action == 'plugin.book-save') {
|
||||
// save error
|
||||
$path_imap = $folder;
|
||||
$hidden_fields[] = array('name' => '_oldname', 'value' => $old);
|
||||
|
||||
if (strlen($old)) {
|
||||
$this->rc->imap_connect();
|
||||
$options = $this->rc->imap->mailbox_info($old);
|
||||
}
|
||||
}
|
||||
else if ($action == 'edit') {
|
||||
$path_imap = explode($delim, $folder);
|
||||
$name = rcube_charset_convert(array_pop($path_imap), 'UTF7-IMAP');
|
||||
$path_imap = implode($path_imap, $delim);
|
||||
|
||||
$this->rc->imap_connect();
|
||||
$options = $this->rc->imap->mailbox_info($folder);
|
||||
|
||||
$hidden_fields[] = array('name' => '_oldname', 'value' => $folder);
|
||||
}
|
||||
else {
|
||||
$path_imap = $folder;
|
||||
$name = '';
|
||||
}
|
||||
|
||||
// General tab
|
||||
$form['props'] = array(
|
||||
'name' => $this->rc->gettext('properties'),
|
||||
);
|
||||
|
||||
$foldername = new html_inputfield(array('name' => '_name', 'id' => '_name', 'size' => 30));
|
||||
$foldername = $foldername->show($name);
|
||||
|
||||
$form['props']['fieldsets']['location'] = array(
|
||||
'name' => $this->rc->gettext('location'),
|
||||
'content' => array(
|
||||
'name' => array(
|
||||
'label' => $this->plugin->gettext('bookname'),
|
||||
'value' => $foldername,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (strlen($path_imap)) {
|
||||
$path = rcube_charset_convert($path_imap, 'UTF7-IMAP');
|
||||
// @TODO: $options
|
||||
if (!empty($options) && ($options['norename'] || $options['namespace'] != 'personal')) {
|
||||
// prevent user from moving folder
|
||||
$hidden_fields[] = array('name' => '_parent', 'value' => $path_imap);
|
||||
}
|
||||
else {
|
||||
$radio1 = new html_radiobutton(array('name' => '_parent', 'value' => ''));
|
||||
$radio2 = new html_radiobutton(array('name' => '_parent', 'value' => $path_imap));
|
||||
|
||||
$html_path = str_replace($delim, ' » ', $path);
|
||||
|
||||
$folderpath = $radio1->show($path_imap) . Q(rcube_label('none')) . ' '
|
||||
.$radio2->show($path_imap) . Q($html_path);
|
||||
|
||||
$form['props']['fieldsets']['location']['content']['path'] = array(
|
||||
'label' => $this->plugin->gettext('parentbook'),
|
||||
'value' => $folderpath,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Allow plugins to modify address book form content (e.g. with ACL form)
|
||||
$plugin = $this->rc->plugins->exec_hook('addressbook_form',
|
||||
array('form' => $form, 'options' => $options, 'name' => $folder));
|
||||
|
||||
$form = $plugin['form'];
|
||||
|
||||
// Set form tags and hidden fields
|
||||
list($form_start, $form_end) = $this->get_form_tags($attrib, 'plugin.book-save', null, $hidden_fields);
|
||||
|
||||
unset($attrib['form']);
|
||||
|
||||
// return the complete edit form as table
|
||||
$out = "$form_start\n";
|
||||
|
||||
// Create form output
|
||||
foreach ($form as $tab) {
|
||||
if (!empty($tab['fieldsets']) && is_array($tab['fieldsets'])) {
|
||||
$content = '';
|
||||
foreach ($tab['fieldsets'] as $fieldset) {
|
||||
$subcontent = $this->get_form_part($fieldset);
|
||||
if ($subcontent) {
|
||||
$content .= html::tag('fieldset', null, html::tag('legend', null, Q($fieldset['name'])) . $subcontent) ."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$content = $this->get_form_part($tab);
|
||||
}
|
||||
|
||||
if ($content) {
|
||||
$out .= html::tag('fieldset', null, html::tag('legend', null, Q($tab['name'])) . $content) ."\n";
|
||||
}
|
||||
}
|
||||
|
||||
$out .= "\n$form_end";
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
private function get_form_part($form)
|
||||
{
|
||||
$content = '';
|
||||
|
||||
if (is_array($form['content']) && !empty($form['content'])) {
|
||||
$table = new html_table(array('cols' => 2));
|
||||
foreach ($form['content'] as $col => $colprop) {
|
||||
$colprop['id'] = '_'.$col;
|
||||
$label = !empty($colprop['label']) ? $colprop['label'] : rcube_label($col);
|
||||
|
||||
$table->add('title', sprintf('<label for="%s">%s</label>', $colprop['id'], Q($label)));
|
||||
$table->add(null, $colprop['value']);
|
||||
}
|
||||
$content = $table->show();
|
||||
}
|
||||
else {
|
||||
$content = $form['content'];
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
|
||||
private function get_form_tags($attrib, $action, $id = null, $hidden = null)
|
||||
{
|
||||
$form_start = $form_end = '';
|
||||
|
||||
$request_key = $action . (isset($id) ? '.'.$id : '');
|
||||
$form_start = $this->rc->output->request_form(array(
|
||||
'name' => 'form',
|
||||
'method' => 'post',
|
||||
'task' => $this->rc->task,
|
||||
'action' => $action,
|
||||
'request' => $request_key,
|
||||
'noclose' => true,
|
||||
) + $attrib);
|
||||
|
||||
if (is_array($hidden)) {
|
||||
foreach ($hidden as $field) {
|
||||
$hiddenfield = new html_hiddenfield($field);
|
||||
$form_start .= $hiddenfield->show();
|
||||
}
|
||||
}
|
||||
|
||||
$form_end = !strlen($attrib['form']) ? '</form>' : '';
|
||||
|
||||
$EDIT_FORM = !empty($attrib['form']) ? $attrib['form'] : 'form';
|
||||
$this->rc->output->add_gui_object('editform', $EDIT_FORM);
|
||||
|
||||
return array($form_start, $form_end);
|
||||
}
|
||||
|
||||
}
|
|
@ -13,8 +13,9 @@
|
|||
class rcube_kolab_contacts extends rcube_addressbook
|
||||
{
|
||||
public $primary_key = 'ID';
|
||||
public $readonly = false;
|
||||
public $groups = true;
|
||||
public $readonly = true;
|
||||
public $editable = false;
|
||||
public $groups = false;
|
||||
public $coltypes = array(
|
||||
'name' => array('limit' => 1),
|
||||
'firstname' => array('limit' => 1),
|
||||
|
@ -55,9 +56,6 @@ class rcube_kolab_contacts extends rcube_addressbook
|
|||
);
|
||||
|
||||
private $gid;
|
||||
private $imap;
|
||||
private $kolab;
|
||||
private $folder;
|
||||
private $contactstorage;
|
||||
private $liststorage;
|
||||
private $contacts;
|
||||
|
@ -66,6 +64,7 @@ class rcube_kolab_contacts extends rcube_addressbook
|
|||
private $id2uid;
|
||||
private $filter;
|
||||
private $result;
|
||||
private $namespace;
|
||||
private $imap_folder = 'INBOX/Contacts';
|
||||
private $gender_map = array(0 => 'male', 1 => 'female');
|
||||
private $phonetypemap = array('home' => 'home1', 'work' => 'business1', 'work2' => 'business2', 'workfax' => 'businessfax');
|
||||
|
@ -120,6 +119,25 @@ class rcube_kolab_contacts extends rcube_addressbook
|
|||
$this->liststorage = rcube_kolab::get_storage($this->imap_folder, 'distributionlist');
|
||||
|
||||
$this->ready = !PEAR::isError($this->contactstorage) && !PEAR::isError($this->liststorage);
|
||||
|
||||
// Set readonly and editable flags according to folder permissions
|
||||
if ($this->ready) {
|
||||
if ($this->get_owner() == $_SESSION['username']) {
|
||||
$this->editable = true;
|
||||
$this->readonly = false;
|
||||
}
|
||||
else {
|
||||
$acl = $this->contactstorage->_folder->getACL();
|
||||
$acl = $acl[$_SESSION['username']];
|
||||
if (strpos($acl, 'i') !== false)
|
||||
$this->readonly = false;
|
||||
if (strpos($acl, 'a') !== false || strpos($acl, 'x') !== false)
|
||||
$this->editable = true;
|
||||
}
|
||||
|
||||
if (!$this->readonly)
|
||||
$this->groups = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -130,9 +148,113 @@ class rcube_kolab_contacts extends rcube_addressbook
|
|||
*/
|
||||
public function get_name()
|
||||
{
|
||||
$folder = rcube_charset_convert($this->imap_folder, 'UTF7-IMAP');
|
||||
// @TODO: use namespace prefixes
|
||||
return strtr(preg_replace('!^(INBOX|user)/!i', '', $folder), '/', ':');
|
||||
$folder = $this->imap_folder;
|
||||
$namespace = $_SESSION['imap_namespace']; // from rcube_imap class
|
||||
$found = false;
|
||||
|
||||
if (!empty($namespace['shared'])) {
|
||||
foreach ($namespace['shared'] as $ns) {
|
||||
if (strlen($ns[0]) && strpos($folder, $ns[0]) === 0) {
|
||||
$prefix = '';
|
||||
$folder = substr($folder, strlen($ns[0]));
|
||||
$delim = $ns[1];
|
||||
$found = true;
|
||||
$this->namespace = 'shared';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$found && !empty($namespace['other'])) {
|
||||
foreach ($namespace['other'] as $ns) {
|
||||
if (strlen($ns[0]) && strpos($folder, $ns[0]) === 0) {
|
||||
// remove namespace prefix
|
||||
$folder = substr($folder, strlen($ns[0]));
|
||||
$delim = $ns[1];
|
||||
// get username
|
||||
$pos = strpos($folder, $delim);
|
||||
$prefix = '('.substr($folder, 0, $pos).') ';
|
||||
$found = true;
|
||||
$this->namespace = 'other';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$found && !empty($namespace['personal'])) {
|
||||
foreach ($namespace['personal'] as $ns) {
|
||||
if (strlen($ns[0]) && strpos($folder, $ns[0]) === 0) {
|
||||
// remove namespace prefix
|
||||
$folder = substr($folder, strlen($ns[0]));
|
||||
$prefix = '';
|
||||
$delim = $ns[1];
|
||||
$found = true;
|
||||
$this->namespace = 'personal';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($delim))
|
||||
$delim = $_SESSION['imap_delimiter']; // from rcube_imap class
|
||||
|
||||
$folder = rcube_charset_convert($folder, 'UTF7-IMAP');
|
||||
$folder = str_replace($delim, ' » ', $folder);
|
||||
|
||||
if ($prefix)
|
||||
$folder = $prefix . ' ' . $folder;
|
||||
|
||||
return $folder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Getter for the IMAP folder name
|
||||
*
|
||||
* @return string Name of the IMAP folder
|
||||
*/
|
||||
public function get_realname()
|
||||
{
|
||||
return $this->imap_folder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Getter for the IMAP folder owner
|
||||
*
|
||||
* @return string Name of the folder owner
|
||||
*/
|
||||
public function get_owner()
|
||||
{
|
||||
return $this->contactstorage->_folder->getOwner();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Getter for the name of the namespace to which the IMAP folder belongs
|
||||
*
|
||||
* @return string Name of the namespace (personal, other, shared)
|
||||
*/
|
||||
public function get_namespace()
|
||||
{
|
||||
if ($this->namespace) {
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
$folder = $this->imap_folder;
|
||||
$namespace = $_SESSION['imap_namespace']; // from rcube_imap class
|
||||
|
||||
if (!empty($namespace)) {
|
||||
foreach ($namespace as $nsname => $nsvalue) {
|
||||
if (in_array($nsname, array('personal', 'other', 'shared')) && !empty($nsvalue)) {
|
||||
foreach ($nsvalue as $ns) {
|
||||
if (strlen($ns[0]) && strpos($folder, $ns[0]) === 0) {
|
||||
return $this->namespace = $nsname;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->namespace = 'personal';
|
||||
}
|
||||
|
||||
|
||||
|
@ -770,6 +892,10 @@ class rcube_kolab_contacts extends rcube_addressbook
|
|||
// read contacts
|
||||
$this->contacts = $this->id2uid = array();
|
||||
foreach ((array)$this->contactstorage->getObjects() as $record) {
|
||||
// Because of a bug, sometimes group records are returned
|
||||
if ($record['__type'] == 'Group')
|
||||
continue;
|
||||
|
||||
$contact = $this->_to_rcube_contact($record);
|
||||
$id = $contact['ID'];
|
||||
$this->contacts[$id] = $contact;
|
|
@ -9,10 +9,28 @@ $labels['pgppublickey'] = 'PGP publickey';
|
|||
$labels['freebusyurl'] = 'Free-busy URL';
|
||||
$labels['settings'] = 'Settings';
|
||||
|
||||
$labels['bookcreate'] = 'Create address book';
|
||||
$labels['bookedit'] = 'Edit address book';
|
||||
$labels['bookdelete'] = 'Delete address book';
|
||||
$labels['bookproperties'] = 'Address book properties';
|
||||
$labels['bookname'] = 'Book name';
|
||||
$labels['parentbook'] = 'Superior book';
|
||||
|
||||
$labels['addressbookprio'] = 'Address book(s) selection/behaviour';
|
||||
$labels['personalfirst'] = 'Personal address book(s) first';
|
||||
$labels['globalfirst'] = 'Global address book(s) first';
|
||||
$labels['personalonly'] = 'Personal address book(s) only';
|
||||
$labels['globalonly'] = 'Global address book(s) only';
|
||||
|
||||
$messages['bookdeleteconfirm'] = 'Do you really want to delete the selected address book and all contacts in it?';
|
||||
$messages['bookdeleting'] = 'Deleting address book...';
|
||||
$messages['booksaving'] = 'Saving address book...';
|
||||
$messages['bookdeleted'] = 'Address book deleted successfully';
|
||||
$messages['bookupdated'] = 'Address book updated successfully';
|
||||
$messages['bookcreated'] = 'Address book created successfully';
|
||||
$messages['bookdeleteerror'] = 'An error occured while deleting address book';
|
||||
$messages['bookupdateerror'] = 'An error occured while updating address book';
|
||||
$messages['bookcreateerror'] = 'An error occured while creating address book';
|
||||
$messages['nobooknamewarning'] = 'Please, enter address book name';
|
||||
|
||||
?>
|
||||
|
|
|
@ -15,4 +15,22 @@ $labels['globalfirst'] = 'Najpierw globalne książki adresowe';
|
|||
$labels['personalonly'] = 'Tylko osobiste książki adresowe';
|
||||
$labels['globalonly'] = 'Tylko globalne książki adresowe';
|
||||
|
||||
$labels['bookcreate'] = 'Utwórz książkę';
|
||||
$labels['bookedit'] = 'Edytuj książkę';
|
||||
$labels['bookdelete'] = 'Usuń książkę';
|
||||
$labels['bookproperties'] = 'Właściwości książki adresowej';
|
||||
$labels['bookname'] = 'Nazwa książki';
|
||||
$labels['parentbook'] = 'Książka nadrzędna';
|
||||
|
||||
$messages['bookdeleteconfirm'] = 'Czy na pewno chcesz usunąć wybraną książkę i wszystkie kontakty w niej zapisane?';
|
||||
$messages['bookdeleting'] = 'Usuwanie książki adresowej...';
|
||||
$messages['booksaving'] = 'Zapisywanie książki adresowej...';
|
||||
$messages['bookdeleted'] = 'Książka adresowa została usunięta';
|
||||
$messages['bookupdated'] = 'Książka adresowa została zaktualizowana';
|
||||
$messages['bookcreated'] = 'Książka adresowa została utworzona';
|
||||
$messages['bookdeleteerror'] = 'Wystąpił błąd podczas usuwania książki adresowej';
|
||||
$messages['bookupdateerror'] = 'Wystąpił błąd podczas zmiany książki adresowej';
|
||||
$messages['bookcreateerror'] = 'Wystąpił błąd podczas tworzenia książki adresowej';
|
||||
$messages['nobooknamewarning'] = 'Proszę podać nazwę książki adresowej';
|
||||
|
||||
?>
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
#directorylist li.addressbook.readonly
|
||||
{
|
||||
/* don't use 'background' to not reset background color */
|
||||
background-image: url(kolab_folders.png);
|
||||
background-position: 5px 0px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#directorylist li.addressbook.shared
|
||||
{
|
||||
background-image: url(kolab_folders.png);
|
||||
background-position: 5px -54px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#directorylist li.addressbook.shared.readonly
|
||||
{
|
||||
background-image: url(kolab_folders.png);
|
||||
background-position: 5px -72px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#directorylist li.addressbook.other
|
||||
{
|
||||
background-image: url(kolab_folders.png);
|
||||
background-position: 5px -18px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#directorylist li.addressbook.other.readonly
|
||||
{
|
||||
background-image: url(kolab_folders.png);
|
||||
background-position: 5px -36px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
BIN
plugins/kolab_addressbook/skins/default/kolab_folders.png
Normal file
BIN
plugins/kolab_addressbook/skins/default/kolab_folders.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title><roundcube:object name="pagetitle" /></title>
|
||||
<roundcube:include file="/includes/links.html" />
|
||||
<link rel="stylesheet" type="text/css" href="/settings.css" />
|
||||
<script type="text/javascript" src="/functions.js"></script>
|
||||
</head>
|
||||
<body class="iframe">
|
||||
|
||||
<div id="folder-title" class="boxtitle"><roundcube:label name="kolab_addressbook.bookproperties" /></div>
|
||||
|
||||
<div id="folder-details" class="boxcontent">
|
||||
<roundcube:object name="bookdetails" />
|
||||
<p>
|
||||
<!--
|
||||
<roundcube:if condition="!strlen(request:_source)" />
|
||||
<input type="button" value="<roundcube:label name="cancel" />" class="button" onclick="history.back()" />
|
||||
<roundcube:endif />
|
||||
-->
|
||||
<roundcube:button command="book-save" type="input" class="button mainaction" label="save" />
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">rcube_init_tabs('folder-details > form')</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -21,7 +21,7 @@ pear install Net_SMTP
|
|||
pear install Mail_mimeDecode
|
||||
pear install Auth_SASL
|
||||
pear install Date
|
||||
|
||||
pear install HTTP_Request
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
|
|
@ -137,7 +137,7 @@ class kolab_folders extends rcube_plugin
|
|||
|
||||
// Add type-based style for table rows
|
||||
// See kolab_folders::folder_class_name()
|
||||
for ($i=0, $cnt=$table->size(); $i<$cnt; $i++) {
|
||||
for ($i=1, $cnt=$table->size(); $i<=$cnt; $i++) {
|
||||
$attrib = $table->get_row_attribs($i);
|
||||
$folder = $attrib['foldername']; // UTF7-IMAP
|
||||
$data = $folderdata[$folder];
|
||||
|
|
Loading…
Add table
Reference in a new issue