Merge branch 'master' of ssh://git.kolabsys.com/git/roundcube
This commit is contained in:
commit
d5c5194dc5
66 changed files with 3480 additions and 246 deletions
|
@ -38,6 +38,7 @@ class calendar extends rcube_plugin
|
|||
public $home; // declare public to be used in other classes
|
||||
public $urlbase;
|
||||
public $timezone;
|
||||
public $timezone_offset;
|
||||
public $gmt_offset;
|
||||
|
||||
public $ical;
|
||||
|
@ -96,10 +97,11 @@ class calendar extends rcube_plugin
|
|||
$this->add_texts('localization/', $this->rc->task == 'calendar' && (!$this->rc->action || $this->rc->action == 'print'));
|
||||
|
||||
// set user's timezone
|
||||
$this->timezone = $this->rc->config->get('timezone');
|
||||
$this->dst_active = $this->rc->config->get('dst_active');
|
||||
$this->gmt_offset = ($this->timezone + $this->dst_active) * 3600;
|
||||
$this->user_timezone = new DateTimeZone($this->timezone ? timezone_name_from_abbr("", $this->gmt_offset, $this->dst_active) : 'GMT');
|
||||
$this->timezone = new DateTimeZone($this->rc->config->get('timezone', 'GMT'));
|
||||
$now = new DateTime('now', $this->timezone);
|
||||
$this->timezone_offset = $now->format('Z') / 3600;
|
||||
$this->dst_active = $now->format('I');
|
||||
$this->gmt_offset = $now->getOffset();
|
||||
|
||||
require($this->home . '/lib/calendar_ui.php');
|
||||
$this->ui = new calendar_ui($this);
|
||||
|
@ -119,6 +121,9 @@ class calendar extends rcube_plugin
|
|||
if ($this->rc->action == 'attend' && !empty($_REQUEST['_t'])) {
|
||||
$this->add_hook('startup', array($this, 'itip_attend_response'));
|
||||
}
|
||||
else if ($this->rc->action == 'feed' && !empty($_REQUEST['_cal'])) {
|
||||
$this->add_hook('startup', array($this, 'ical_feed_export'));
|
||||
}
|
||||
else if ($this->rc->task == 'calendar' && $this->rc->action != 'save-pref') {
|
||||
if ($this->rc->action != 'upload') {
|
||||
$this->load_driver();
|
||||
|
@ -172,8 +177,9 @@ class calendar extends rcube_plugin
|
|||
'command' => 'calendar-create-from-mail',
|
||||
'label' => 'calendar.createfrommail',
|
||||
'type' => 'link',
|
||||
'classact' => 'calendarlink active',
|
||||
'class' => 'calendarlink',
|
||||
'classact' => 'icon calendarlink active',
|
||||
'class' => 'icon calendarlink',
|
||||
'innerclass' => 'icon calendar',
|
||||
))),
|
||||
'messagemenu');
|
||||
}
|
||||
|
@ -232,6 +238,26 @@ class calendar extends rcube_plugin
|
|||
return $this->ical;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function get_default_calendar($writeable = false)
|
||||
{
|
||||
$cal_id = $this->rc->config->get('calendar_default_calendar');
|
||||
$calendars = $this->driver->list_calendars();
|
||||
$calendar = $calendars[$cal_id] ? $calendars[$cal_id] : null;
|
||||
if (!$calendar || ($writeable && $calendar['readonly'])) {
|
||||
foreach ($calendars as $cal) {
|
||||
if (!$writeable || !$cal['readonly']) {
|
||||
$calendar = $cal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $calendar;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render the main calendar view from skin template
|
||||
|
@ -890,7 +916,7 @@ class calendar extends rcube_plugin
|
|||
/**
|
||||
* Construct the ics file for exporting events to iCalendar format;
|
||||
*/
|
||||
function export_events()
|
||||
function export_events($terminate = true)
|
||||
{
|
||||
$start = get_input_value('start', RCUBE_INPUT_GET);
|
||||
$end = get_input_value('end', RCUBE_INPUT_GET);
|
||||
|
@ -903,14 +929,73 @@ class calendar extends rcube_plugin
|
|||
$calname = $calendars[$calid]['name'] ? $calendars[$calid]['name'] : $calid;
|
||||
$events = $this->driver->load_events($start, $end, null, $calid, 0);
|
||||
}
|
||||
else
|
||||
$events = array();
|
||||
|
||||
header("Content-Type: text/calendar");
|
||||
header("Content-Disposition: inline; filename=".$calname.'.ics');
|
||||
|
||||
|
||||
$this->get_ical()->export($events, '', true);
|
||||
|
||||
if ($terminate)
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler for iCal feed requests
|
||||
*/
|
||||
function ical_feed_export()
|
||||
{
|
||||
// process HTTP auth info
|
||||
if (!empty($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
|
||||
$_POST['_user'] = $_SERVER['PHP_AUTH_USER']; // used for rcmail::autoselect_host()
|
||||
$auth = $this->rc->plugins->exec_hook('authenticate', array(
|
||||
'host' => $this->rc->autoselect_host(),
|
||||
'user' => trim($_SERVER['PHP_AUTH_USER']),
|
||||
'pass' => $_SERVER['PHP_AUTH_PW'],
|
||||
'cookiecheck' => true,
|
||||
'valid' => true,
|
||||
));
|
||||
if ($auth['valid'] && !$auth['abort'])
|
||||
$this->rc->login($auth['user'], $auth['pass'], $auth['host']);
|
||||
}
|
||||
|
||||
// require HTTP auth
|
||||
if (empty($_SESSION['user_id'])) {
|
||||
header('WWW-Authenticate: Basic realm="Roundcube Calendar"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
exit;
|
||||
}
|
||||
|
||||
// decode calendar feed hash
|
||||
$format = 'ics';
|
||||
$calhash = get_input_value('_cal', RCUBE_INPUT_GET);
|
||||
if (preg_match(($suff_regex = '/\.([a-z0-9]{3,5})$/i'), $calhash, $m)) {
|
||||
$format = strtolower($m[1]);
|
||||
$calhash = preg_replace($suff_regex, '', $calhash);
|
||||
}
|
||||
|
||||
if (!strpos($calhash, ':'))
|
||||
$calhash = base64_decode($calhash);
|
||||
|
||||
list($user, $_GET['source']) = explode(':', $calhash, 2);
|
||||
|
||||
// sanity check user
|
||||
if ($this->rc->user->get_username() == $user) {
|
||||
$this->load_driver();
|
||||
$this->export_events(false);
|
||||
}
|
||||
else {
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
}
|
||||
|
||||
// don't save session data
|
||||
session_destroy();
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -939,7 +1024,7 @@ class calendar extends rcube_plugin
|
|||
$settings['agenda_sections'] = $this->rc->config->get('calendar_agenda_sections', $this->defaults['calendar_agenda_sections']);
|
||||
$settings['event_coloring'] = (int)$this->rc->config->get('calendar_event_coloring', $this->defaults['calendar_event_coloring']);
|
||||
$settings['time_indicator'] = (int)$this->rc->config->get('calendar_time_indicator', $this->defaults['calendar_time_indicator']);
|
||||
$settings['timezone'] = $this->timezone;
|
||||
$settings['timezone'] = $this->timezone_offset;
|
||||
$settings['dst'] = $this->dst_active;
|
||||
|
||||
// localization
|
||||
|
@ -1052,6 +1137,10 @@ class calendar extends rcube_plugin
|
|||
if ($event['recurrence'])
|
||||
$event['recurrence_text'] = $this->_recurrence_text($event['recurrence']);
|
||||
|
||||
foreach ((array)$event['attachments'] as $k => $attachment) {
|
||||
$event['attachments'][$k]['classname'] = rcmail_filetype2classname($attachment['mimetype'], $attachment['name']);
|
||||
}
|
||||
|
||||
return array(
|
||||
'start' => gmdate('c', $this->fromGMT($event['start'])), // client treats date strings as they were in users's timezone
|
||||
'end' => gmdate('c', $this->fromGMT($event['end'])), // so shift timestamps to users's timezone and render a date string
|
||||
|
@ -1373,6 +1462,7 @@ class calendar extends rcube_plugin
|
|||
|
||||
$content = html::a(array(
|
||||
'href' => "#delete",
|
||||
'class' => 'delete',
|
||||
'onclick' => sprintf("return %s.remove_from_attachment_list('rcmfile%s')", JS_OBJECT_NAME, $id),
|
||||
'title' => rcube_label('delete'),
|
||||
), $button);
|
||||
|
@ -1383,6 +1473,7 @@ class calendar extends rcube_plugin
|
|||
'html' => $content,
|
||||
'name' => $attachment['name'],
|
||||
'mimetype' => $attachment['mimetype'],
|
||||
'classname' => rcmail_filetype2classname($attachment['mimetype'], $attachment['name']),
|
||||
'complete' => true), $uploadid);
|
||||
}
|
||||
else { // upload failed
|
||||
|
@ -1661,8 +1752,8 @@ class calendar extends rcube_plugin
|
|||
}
|
||||
|
||||
// add timezone information
|
||||
if ($tzinfo && ($tzname = $this->user_timezone->getName())) {
|
||||
$fromto .= ' (' . $tzname . ')';
|
||||
if ($tzinfo && ($tzname = $this->timezone->getName())) {
|
||||
$fromto .= ' (' . strtr($tzname, '_', ' ') . ')';
|
||||
}
|
||||
|
||||
return $fromto;
|
||||
|
@ -1873,13 +1964,26 @@ class calendar extends rcube_plugin
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// send itip reply to organizer
|
||||
if ($status && $itip->update_invitation($invitation, $invitation['attendee'], strtoupper($status))) {
|
||||
$this->invitestatus = html::div('rsvp-status ' . strtolower($status), $this->gettext('youhave'.strtolower($status)));
|
||||
}
|
||||
else
|
||||
$this->rc->output->command('display_message', $this->gettext('errorsaving'), 'error', -1);
|
||||
|
||||
// if user is logged in...
|
||||
if ($this->rc->user->ID) {
|
||||
$this->load_driver();
|
||||
$invitation = $itip->get_invitation($token);
|
||||
|
||||
// save the event to his/her default calendar if not yet present
|
||||
if (!$this->driver->get_event($this->event) && ($calendar = $this->get_default_calendar(true))) {
|
||||
$invitation['event']['calendar'] = $calendar['id'];
|
||||
if ($this->driver->new_event($invitation['event']))
|
||||
$this->rc->output->command('display_message', $this->gettext(array('name' => 'importedsuccessfully', 'vars' => array('calendar' => $calendar['name']))), 'confirmation');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->register_handler('plugin.event_inviteform', array($this, 'itip_event_inviteform'));
|
||||
|
@ -1900,10 +2004,10 @@ class calendar extends rcube_plugin
|
|||
/**
|
||||
*
|
||||
*/
|
||||
public function itip_event_inviteform($p)
|
||||
public function itip_event_inviteform($attrib)
|
||||
{
|
||||
$hidden = new html_hiddenfield(array('name' => "_t", 'value' => $this->token));
|
||||
return html::tag('form', array('action' => $this->rc->url(array('task' => 'calendar', 'action' => 'attend')), 'method' => 'post', 'noclose' => true)) . $hidden->show();
|
||||
return html::tag('form', array('action' => $this->rc->url(array('task' => 'calendar', 'action' => 'attend')), 'method' => 'post', 'noclose' => true) + $attrib) . $hidden->show();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2299,7 +2403,7 @@ class calendar extends rcube_plugin
|
|||
$default_port = 80;
|
||||
if (rcube_https_check()) {
|
||||
$schema = 'https';
|
||||
$default_port = 143;
|
||||
$default_port = 443;
|
||||
}
|
||||
$url = $schema . '://' . $_SERVER['HTTP_HOST'];
|
||||
if ($_SERVER['SERVER_PORT'] != $default_port)
|
||||
|
@ -2311,4 +2415,10 @@ class calendar extends rcube_plugin
|
|||
return $url;
|
||||
}
|
||||
|
||||
|
||||
public function ical_feed_hash($source)
|
||||
{
|
||||
return base64_encode($this->rc->user->get_username() . ':' . $source);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* @author Thomas Bruederli <bruederli@kolabsys.com>
|
||||
*
|
||||
* Copyright (C) 2010, Lazlo Westerhof <hello@lazlo.me>
|
||||
* Copyright (C) 2011, Kolab Systems AG <contact@kolabsys.com>
|
||||
* Copyright (C) 2012, Kolab Systems AG <contact@kolabsys.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
|
@ -276,10 +276,12 @@ function rcube_calendar_ui(settings)
|
|||
{
|
||||
var i, id, len, img, content, li, elem,
|
||||
ul = document.createElement('UL');
|
||||
ul.className = 'attachmentslist';
|
||||
|
||||
for (i=0, len=list.length; i<len; i++) {
|
||||
li = document.createElement('LI');
|
||||
elem = list[i];
|
||||
li = document.createElement('LI');
|
||||
li.className = elem.classname;
|
||||
|
||||
if (edit) {
|
||||
rcmail.env.attachments[elem.id] = elem;
|
||||
|
@ -287,6 +289,7 @@ function rcube_calendar_ui(settings)
|
|||
content = document.createElement('A');
|
||||
content.href = '#delete';
|
||||
content.title = rcmail.gettext('delete');
|
||||
content.className = 'delete';
|
||||
$(content).click({id: elem.id}, function(e) { remove_attachment(this, e.data.id); return false; });
|
||||
|
||||
if (!rcmail.env.deleteicon)
|
||||
|
@ -303,7 +306,8 @@ function rcube_calendar_ui(settings)
|
|||
|
||||
// name/link
|
||||
content = document.createElement('A');
|
||||
content.innerHTML = list[i].name;
|
||||
content.innerHTML = elem.name;
|
||||
content.className = 'file';
|
||||
content.href = '#load';
|
||||
$(content).click({event: event, att: elem}, function(e) {
|
||||
load_attachment(e.data.event, e.data.att); return false; });
|
||||
|
@ -343,7 +347,8 @@ function rcube_calendar_ui(settings)
|
|||
$('#event-description').show().children('.event-text').html(text2html(event.description, 300, 6));
|
||||
|
||||
// render from-to in a nice human-readable way
|
||||
$('#event-date').html(Q(me.event_date_text(event))).show();
|
||||
// -> now shown in dialog title
|
||||
// $('#event-date').html(Q(me.event_date_text(event))).show();
|
||||
|
||||
if (event.recurrence && event.recurrence_text)
|
||||
$('#event-repeat').show().children('.event-text').html(Q(event.recurrence_text));
|
||||
|
@ -432,7 +437,7 @@ function rcube_calendar_ui(settings)
|
|||
modal: false,
|
||||
resizable: !bw.ie6,
|
||||
closeOnEscape: (!bw.ie6 && !bw.ie7), // disable for performance reasons
|
||||
title: null,
|
||||
title: Q(me.event_date_text(event)),
|
||||
close: function() {
|
||||
$dialog.dialog('destroy').hide();
|
||||
},
|
||||
|
@ -1953,6 +1958,26 @@ function rcube_calendar_ui(settings)
|
|||
this.refresh(p);
|
||||
};
|
||||
|
||||
// show URL of the given calendar in a dialog box
|
||||
this.showurl = function(calendar)
|
||||
{
|
||||
var $dialog = $('#calendarurlbox').dialog('close');
|
||||
|
||||
if (calendar.feedurl) {
|
||||
$dialog.dialog({
|
||||
resizable: true,
|
||||
closeOnEscape: true,
|
||||
title: rcmail.gettext('showurl', 'calendar'),
|
||||
close: function() {
|
||||
$dialog.dialog("destroy").hide();
|
||||
},
|
||||
width: 520
|
||||
}).show();
|
||||
|
||||
$('#calfeedurl').val(calendar.feedurl).select();
|
||||
}
|
||||
};
|
||||
|
||||
// refresh the calendar view after saving event data
|
||||
this.refresh = function(p)
|
||||
{
|
||||
|
@ -2126,15 +2151,15 @@ function rcube_calendar_ui(settings)
|
|||
this.dialog_resize = function(id, height, width)
|
||||
{
|
||||
var win = $(window), w = win.width(), h = win.height();
|
||||
$(id).dialog('option', { height: Math.min(h-20, height+110), width: Math.min(w-20, width+50) })
|
||||
$(id).dialog('option', { height: Math.min(h-20, height+130), width: Math.min(w-20, width+50) })
|
||||
.dialog('option', 'position', ['center', 'center']); // only works in a separate call (!?)
|
||||
};
|
||||
|
||||
// adjust calendar view size
|
||||
this.view_resize = function()
|
||||
{
|
||||
var footer = fc.fullCalendar('getView').name == 'table' ? $('#agendaoptions').height() + 2 : 0;
|
||||
fc.fullCalendar('option', 'height', $('#main').height() - footer);
|
||||
var footer = fc.fullCalendar('getView').name == 'table' ? $('#agendaoptions').outerHeight() : 0;
|
||||
fc.fullCalendar('option', 'height', $('#calendar').height() - footer);
|
||||
};
|
||||
|
||||
|
||||
|
@ -2183,7 +2208,7 @@ function rcube_calendar_ui(settings)
|
|||
var id = $(this).data('id');
|
||||
rcmail.select_folder(id, 'rcmlical');
|
||||
rcmail.enable_command('calendar-edit', true);
|
||||
rcmail.enable_command('calendar-remove', 'events-import', !me.calendars[id].readonly);
|
||||
rcmail.enable_command('calendar-remove', 'events-import', 'calendar-showurl', true);
|
||||
me.selected_calendar = id;
|
||||
})
|
||||
.dblclick(function(){ me.calendar_edit_dialog(me.calendars[me.selected_calendar]); })
|
||||
|
@ -2216,7 +2241,7 @@ function rcube_calendar_ui(settings)
|
|||
month: viewdate.getMonth(),
|
||||
year: viewdate.getFullYear(),
|
||||
ignoreTimezone: true, // will treat the given date strings as in local (browser's) timezone
|
||||
height: $('#main').height(),
|
||||
height: $('#calendar').height(),
|
||||
eventSources: event_sources,
|
||||
monthNames : settings['months'],
|
||||
monthNamesShort : settings['months_short'],
|
||||
|
@ -2673,6 +2698,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) {
|
|||
rcmail.register_command('calendar-edit', function(){ cal.calendar_edit_dialog(cal.calendars[cal.selected_calendar]); }, false);
|
||||
rcmail.register_command('calendar-remove', function(){ cal.calendar_remove(cal.calendars[cal.selected_calendar]); }, false);
|
||||
rcmail.register_command('events-import', function(){ cal.import_events(cal.calendars[cal.selected_calendar]); }, false);
|
||||
rcmail.register_command('calendar-showurl', function(){ cal.showurl(cal.calendars[cal.selected_calendar]); }, false);
|
||||
|
||||
// search and export events
|
||||
rcmail.register_command('export', function(){ rcmail.goto_url('export_events', { source:cal.selected_calendar }); }, true);
|
||||
|
|
|
@ -578,7 +578,7 @@ class database_driver extends calendar_driver
|
|||
|
||||
// read master if deleting a recurring event
|
||||
if ($event['recurrence'] || $event['recurrence_id']) {
|
||||
$master = $event['recurrence_id'] ? $this->get_event(array('id' => $old['recurrence_id'])) : $event;
|
||||
$master = $event['recurrence_id'] ? $this->get_event(array('id' => $event['recurrence_id'])) : $event;
|
||||
$savemode = $event['_savemode'];
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ class kolab_calendar
|
|||
public function get_foldername()
|
||||
{
|
||||
$parts = explode('/', $this->imap_folder);
|
||||
return rcube_charset_convert(end($parts), 'UTF7-IMAP');
|
||||
return rcube_charset::convert(end($parts), 'UTF7-IMAP');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -78,7 +78,7 @@ class kolab_driver extends calendar_driver
|
|||
// convert to UTF8 and sort
|
||||
$names = array();
|
||||
foreach ($folders as $folder)
|
||||
$names[$folder->name] = rcube_charset_convert($folder->name, 'UTF7-IMAP');
|
||||
$names[$folder->name] = rcube_charset::convert($folder->name, 'UTF7-IMAP');
|
||||
|
||||
asort($names, SORT_LOCALE_STRING);
|
||||
|
||||
|
@ -160,8 +160,8 @@ class kolab_driver extends calendar_driver
|
|||
}
|
||||
|
||||
// subscribe to new calendar by default
|
||||
$this->rc->imap_connect();
|
||||
$this->rc->imap->subscribe($folder);
|
||||
$storage = $this->rc->get_storage();
|
||||
$storage->subscribe($folder);
|
||||
|
||||
// create ID
|
||||
$id = rcube_kolab::folder_id($folder);
|
||||
|
@ -226,11 +226,11 @@ class kolab_driver extends calendar_driver
|
|||
public function subscribe_calendar($prop)
|
||||
{
|
||||
if ($prop['id'] && ($cal = $this->calendars[$prop['id']])) {
|
||||
$this->rc->imap_connect();
|
||||
$storage = $this->rc->get_storage();
|
||||
if ($prop['active'])
|
||||
return $this->rc->imap->subscribe($cal->get_realname());
|
||||
return $storage->subscribe($cal->get_realname());
|
||||
else
|
||||
return $this->rc->imap->unsubscribe($cal->get_realname());
|
||||
return $storage->unsubscribe($cal->get_realname());
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -246,14 +246,14 @@ class kolab_driver extends calendar_driver
|
|||
*/
|
||||
private function folder_update(&$prop)
|
||||
{
|
||||
$folder = rcube_charset_convert($prop['name'], RCMAIL_CHARSET, 'UTF7-IMAP');
|
||||
$folder = rcube_charset::convert($prop['name'], RCMAIL_CHARSET, 'UTF7-IMAP');
|
||||
$oldfolder = $prop['oldname']; // UTF7
|
||||
$parent = $prop['parent']; // UTF7
|
||||
$delimiter = $_SESSION['imap_delimiter'];
|
||||
$storage = $this->rc->get_storage();
|
||||
$delimiter = $storage->get_hierarchy_delimiter();
|
||||
|
||||
if (strlen($oldfolder)) {
|
||||
$this->rc->imap_connect();
|
||||
$options = $this->rc->imap->mailbox_info($oldfolder);
|
||||
$options = $storage->folder_info($oldfolder);
|
||||
}
|
||||
|
||||
if (!empty($options) && ($options['norename'] || $options['protected'])) {
|
||||
|
@ -285,14 +285,12 @@ class kolab_driver extends calendar_driver
|
|||
}
|
||||
else {
|
||||
// add namespace prefix (when needed)
|
||||
$this->rc->imap_init();
|
||||
$folder = $this->rc->imap->mod_mailbox($folder, 'in');
|
||||
$folder = $storage->mod_folder($folder, 'in');
|
||||
}
|
||||
|
||||
// Check access rights to the parent folder
|
||||
if (strlen($parent) && (!strlen($oldfolder) || $oldfolder != $folder)) {
|
||||
$this->rc->imap_connect();
|
||||
$parent_opts = $this->rc->imap->mailbox_info($parent);
|
||||
$parent_opts = $storage->folder_info($parent);
|
||||
if ($parent_opts['namespace'] != 'personal'
|
||||
&& (empty($parent_opts['rights']) || !preg_match('/[ck]/', implode($parent_opts['rights'])))
|
||||
) {
|
||||
|
@ -320,8 +318,8 @@ class kolab_driver extends calendar_driver
|
|||
// TODO: also save 'showalarams' and other properties here
|
||||
|
||||
if ($result && $prop['color']) {
|
||||
if (!($meta_saved = $this->rc->imap->set_metadata($folder, array('/shared/vendor/kolab/color' => $prop['color'])))) // try in shared namespace
|
||||
$meta_saved = $this->rc->imap->set_metadata($folder, array('/private/vendor/kolab/color' => $prop['color'])); // try in private namespace
|
||||
if (!($meta_saved = $storage->set_metadata($folder, array('/shared/vendor/kolab/color' => $prop['color'])))) // try in shared namespace
|
||||
$meta_saved = $storage->set_metadata($folder, array('/private/vendor/kolab/color' => $prop['color'])); // try in private namespace
|
||||
if ($meta_saved)
|
||||
unset($prop['color']); // unsetting will prevent fallback to local user prefs
|
||||
}
|
||||
|
@ -1016,7 +1014,8 @@ class kolab_driver extends calendar_driver
|
|||
|
||||
$hidden_fields[] = array('name' => 'oldname', 'value' => $folder);
|
||||
|
||||
$delim = $_SESSION['imap_delimiter'];
|
||||
$storage = $this->rc->get_storage();
|
||||
$delim = $storage->get_hierarchy_delimiter();
|
||||
$form = array();
|
||||
|
||||
if (strlen($folder)) {
|
||||
|
@ -1024,8 +1023,7 @@ class kolab_driver extends calendar_driver
|
|||
array_pop($path_imap); // pop off name part
|
||||
$path_imap = implode($path_imap, $delim);
|
||||
|
||||
$this->rc->imap_connect();
|
||||
$options = $this->rc->imap->mailbox_info($folder);
|
||||
$options = $storage->folder_info($folder);
|
||||
}
|
||||
else {
|
||||
$path_imap = '';
|
||||
|
@ -1179,7 +1177,8 @@ class kolab_driver extends calendar_driver
|
|||
|
||||
$hidden_fields[] = array('name' => 'oldname', 'value' => $folder);
|
||||
|
||||
$delim = $_SESSION['imap_delimiter'];
|
||||
$storage = $this->rc->get_storage();
|
||||
$delim = $storage->get_hierarchy_delimiter();
|
||||
$form = array();
|
||||
|
||||
if (strlen($folder)) {
|
||||
|
@ -1187,14 +1186,16 @@ class kolab_driver extends calendar_driver
|
|||
array_pop($path_imap); // pop off name part
|
||||
$path_imap = implode($path_imap, $delim);
|
||||
|
||||
$this->rc->imap_connect();
|
||||
$options = $this->rc->imap->mailbox_info($folder);
|
||||
$options = $storage->folder_info($folder);
|
||||
|
||||
// Allow plugins to modify the form content (e.g. with ACL form)
|
||||
$plugin = $this->rc->plugins->exec_hook('calendar_form_kolab',
|
||||
array('form' => $form, 'options' => $options, 'name' => $folder));
|
||||
}
|
||||
|
||||
if (!$plugin['form']['sharing']['content'])
|
||||
$plugin['form']['sharing']['content'] = html::div('hint', $this->cal->gettext('aclnorights'));
|
||||
|
||||
return $plugin['form']['sharing']['content'];
|
||||
}
|
||||
|
||||
|
|
|
@ -40,8 +40,7 @@ class calendar_ical
|
|||
|
||||
private $rc;
|
||||
private $cal;
|
||||
private $timezone = 'Z';
|
||||
|
||||
|
||||
public $method;
|
||||
public $events = array();
|
||||
|
||||
|
@ -49,12 +48,6 @@ class calendar_ical
|
|||
{
|
||||
$this->cal = $cal;
|
||||
$this->rc = $cal->rc;
|
||||
|
||||
// compose timezone string
|
||||
if ($cal->timezone) {
|
||||
$hours = floor($cal->timezone + $cal->dst_active);
|
||||
$this->timezone = sprintf('%s%02d:%02d', ($hours >= 0 ? '+' : ''), $hours, ($cal->timezone - $hours) * 60);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -313,7 +306,12 @@ class calendar_ical
|
|||
private function _date2time($prop)
|
||||
{
|
||||
// create timestamp at 12:00 in user's timezone
|
||||
return is_array($prop) ? strtotime(sprintf('%04d%02d%02dT120000%s', $prop['year'], $prop['month'], $prop['mday'], $this->timezone)) : $prop;
|
||||
if (is_array($prop)) {
|
||||
$date = new DateTime(sprintf('%04d%02d%02dT120000', $prop['year'], $prop['month'], $prop['mday']), $this->cal->timezone);
|
||||
console($prop, $date->format('r'));
|
||||
return $date->getTimestamp();
|
||||
}
|
||||
return $prop;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -96,8 +96,8 @@ class calendar_itip
|
|||
}
|
||||
|
||||
$message->headers($headers, true);
|
||||
$message->setTXTBody(rcube_message::format_flowed($mailbody, 79));
|
||||
|
||||
$message->setTXTBody(rcube_mime::format_flowed($mailbody, 79));
|
||||
|
||||
// finally send the message
|
||||
return rcmail_deliver_message($message, $headers['X-Sender'], $mailto, $smtp_error);
|
||||
}
|
||||
|
|
|
@ -48,11 +48,11 @@ class calendar_ui
|
|||
|
||||
// add taskbar button
|
||||
$this->cal->add_button(array(
|
||||
'name' => 'calendar',
|
||||
'command' => 'calendar',
|
||||
'class' => 'button-calendar',
|
||||
'classsel' => 'button-calendar button-selected',
|
||||
'innerclass' => 'button-inner',
|
||||
'label' => 'calendar.calendar',
|
||||
'href' => './?_task=calendar',
|
||||
'onclick' => sprintf("%s.command('plugin.calendar');return false", JS_OBJECT_NAME),
|
||||
), 'taskbar');
|
||||
|
||||
// load basic client script (which - unfortunately - requires fullcalendar)
|
||||
|
@ -168,6 +168,7 @@ class calendar_ui
|
|||
$css .= " border-color: #$color;";
|
||||
$css .= "}\n";
|
||||
}
|
||||
$css .= ".$class .handle { background-color: #$color; }";
|
||||
}
|
||||
|
||||
return html::tag('style', array('type' => 'text/css'), $css);
|
||||
|
@ -191,6 +192,7 @@ class calendar_ui
|
|||
$prop['freebusy'] = $this->cal->driver->freebusy;
|
||||
$prop['attachments'] = $this->cal->driver->attachments;
|
||||
$prop['undelete'] = $this->cal->driver->undelete;
|
||||
$prop['feedurl'] = $this->cal->get_url(array('_cal' => $this->cal->ical_feed_hash($id) . '.ics', 'action' => 'feed'));
|
||||
$jsenv[$id] = $prop;
|
||||
|
||||
$html_id = html_identifier($id);
|
||||
|
@ -202,7 +204,9 @@ class calendar_ui
|
|||
$class .= ' '.$prop['class_name'];
|
||||
|
||||
$li .= html::tag('li', array('id' => 'rcmlical' . $html_id, 'class' => $class),
|
||||
html::tag('input', array('type' => 'checkbox', 'name' => '_cal[]', 'value' => $id, 'checked' => $prop['active']), '') . html::span(null, Q($prop['name'])));
|
||||
html::tag('input', array('type' => 'checkbox', 'name' => '_cal[]', 'value' => $id, 'checked' => $prop['active']), '') .
|
||||
html::span('handle', ' ') .
|
||||
html::span('calname', Q($prop['name'])));
|
||||
}
|
||||
|
||||
$this->rc->output->set_env('calendars', $jsenv);
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
/**
|
||||
* @preserve
|
||||
* FullCalendar v1.5.2
|
||||
* http://arshaw.com/fullcalendar/
|
||||
* FullCalendar v1.5.3-rcube-0.7.1
|
||||
* https://github.com/roundcube/fullcalendar
|
||||
*
|
||||
* Use fullcalendar.css for basic styling.
|
||||
* For event drag & drop, requires jQuery UI draggable.
|
||||
* For event resizing, requires jQuery UI resizable.
|
||||
*
|
||||
* Copyright (c) 2011 Adam Shaw
|
||||
* Copyright (c) 2011, Kolab Systems AG
|
||||
* Dual licensed under the MIT and GPL licenses, located in
|
||||
* MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
|
||||
*
|
||||
* Date: Sun Aug 21 22:06:09 2011 -0700
|
||||
* Date: Mon Feb 13 23:00:46 2012 +0100
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -57,7 +58,7 @@ var defaults = {
|
|||
week: 'ddd M/d',
|
||||
day: 'dddd M/d',
|
||||
list: 'dddd, MMM d, yyyy',
|
||||
table: 'dddd, MMM d, yyyy'
|
||||
table: 'MMM d, yyyy'
|
||||
},
|
||||
timeFormat: { // for event elements
|
||||
'': 'h(:mm)t' // default
|
||||
|
@ -136,7 +137,7 @@ var rtlDefaults = {
|
|||
|
||||
|
||||
|
||||
var fc = $.fullCalendar = { version: "1.5.2" };
|
||||
var fc = $.fullCalendar = { version: "1.5.3-rcube-0.7.1" };
|
||||
var fcViews = fc.views = {};
|
||||
|
||||
|
||||
|
@ -662,8 +663,7 @@ function Calendar(element, options, eventSources) {
|
|||
} else if (name.indexOf('list') == 0 || name == 'tableCols') {
|
||||
options[name] = value;
|
||||
currentView.start = null; // force re-render
|
||||
}
|
||||
else if (name == 'maxHeight') {
|
||||
} else if (name == 'maxHeight') {
|
||||
options[name] = value;
|
||||
}
|
||||
}
|
||||
|
@ -933,6 +933,7 @@ function EventManager(options, _sources) {
|
|||
function fetchEvents(start, end, src) {
|
||||
rangeStart = start;
|
||||
rangeEnd = end;
|
||||
// partially clear cache if refreshing one source only (issue #1061)
|
||||
cache = typeof src != 'undefined' ? $.grep(cache, function(e) { return !isSourcesEqual(e.source, src); }) : [];
|
||||
var fetchID = ++currentFetchID;
|
||||
var len = sources.length;
|
||||
|
@ -942,6 +943,7 @@ function EventManager(options, _sources) {
|
|||
fetchEventSource(sources[i], fetchID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function fetchEventSource(source, fetchID) {
|
||||
|
@ -1127,7 +1129,7 @@ function EventManager(options, _sources) {
|
|||
event.source = stickySource;
|
||||
}
|
||||
}
|
||||
|
||||
// always push event to cache (issue #1112:)
|
||||
cache.push(event);
|
||||
reportEvents(cache);
|
||||
}
|
||||
|
@ -1616,7 +1618,7 @@ var dateFormatters = {
|
|||
return 'th';
|
||||
}
|
||||
return ['st', 'nd', 'rd'][date%10-1] || 'th';
|
||||
},
|
||||
} ,
|
||||
W : function(d) { return iso8601Week(d); }
|
||||
};
|
||||
|
||||
|
@ -3702,6 +3704,7 @@ function AgendaEventRenderer() {
|
|||
var timeLineInterval;
|
||||
|
||||
|
||||
|
||||
/* Rendering
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -4011,7 +4014,7 @@ function AgendaEventRenderer() {
|
|||
}
|
||||
|
||||
|
||||
// draw a horizontal line across the agenda view indicating the current time (#143)
|
||||
// draw a horizontal line indicating the current time (#143)
|
||||
function setTimeIndicator()
|
||||
{
|
||||
var container = getBodyContent();
|
||||
|
@ -4941,7 +4944,7 @@ function DayEventRenderer() {
|
|||
}
|
||||
seg.outerHeight = element[0].offsetHeight + val;
|
||||
}
|
||||
else
|
||||
else // always set a value (issue #1108 )
|
||||
seg.outerHeight = 0;
|
||||
}
|
||||
}
|
||||
|
@ -5296,6 +5299,7 @@ function HoverListener(coordinateGrid) {
|
|||
|
||||
|
||||
function mouse(ev) {
|
||||
_fixUIEvent(ev); // see below
|
||||
var newCell = coordinateGrid.cell(ev.pageX, ev.pageY);
|
||||
if (!newCell != !cell || newCell && (newCell.row != cell.row || newCell.col != cell.col)) {
|
||||
if (newCell) {
|
||||
|
@ -5319,6 +5323,19 @@ function HoverListener(coordinateGrid) {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// this fix was only necessary for jQuery UI 1.8.16 (and jQuery 1.7 or 1.7.1)
|
||||
// upgrading to jQuery UI 1.8.17 (and using either jQuery 1.7 or 1.7.1) fixed the problem
|
||||
// but keep this in here for 1.8.16 users
|
||||
// and maybe remove it down the line
|
||||
|
||||
function _fixUIEvent(event) { // for issue 1168
|
||||
if (event.pageX === undefined) {
|
||||
event.pageX = event.originalEvent.pageX;
|
||||
event.pageY = event.originalEvent.pageY;
|
||||
}
|
||||
}
|
||||
function HorizontalPositionCache(getElement) {
|
||||
|
||||
var t = this,
|
||||
|
@ -5346,7 +5363,6 @@ function HorizontalPositionCache(getElement) {
|
|||
|
||||
}
|
||||
|
||||
|
||||
/* Additional view: list (by bruederli@kolabsys.com)
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -5464,7 +5480,7 @@ function ListEventRenderer() {
|
|||
var tm = opt('theme') ? 'ui' : 'fc';
|
||||
var headerClass = tm + "-widget-header";
|
||||
var contentClass = tm + "-widget-content";
|
||||
var i, j, seg, event, times, s, skinCss, skinCssAttr, classes, segContainer, eventElements;
|
||||
var i, j, seg, event, times, s, skinCss, skinCssAttr, classes, segContainer, eventElement, eventElements, triggerRes;
|
||||
|
||||
for (j=0; j < segs.length; j++) {
|
||||
seg = segs[j];
|
||||
|
@ -5669,7 +5685,6 @@ function ListView(element, calendar) {
|
|||
|
||||
}
|
||||
|
||||
|
||||
/* Additional view: table (by bruederli@kolabsys.com)
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -5722,7 +5737,7 @@ function TableEventRenderer() {
|
|||
var contentClass = tm + "-widget-content";
|
||||
var tableCols = opt('tableCols');
|
||||
var timecol = $.inArray('time', tableCols) >= 0;
|
||||
var i, j, seg, event, times, s, skinCss, skinCssAttr, skinClasses, rowClasses, segContainer, eventElements;
|
||||
var i, j, seg, event, times, s, skinCss, skinCssAttr, skinClasses, rowClasses, segContainer, eventElements, eventElement, triggerRes;
|
||||
|
||||
for (j=0; j < segs.length; j++) {
|
||||
seg = segs[j];
|
||||
|
@ -5900,6 +5915,5 @@ function TableView(element, calendar) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
})(jQuery);
|
||||
|
||||
})(jQuery);
|
||||
|
|
|
@ -31,6 +31,7 @@ $labels['day'] = 'Tag';
|
|||
$labels['week'] = 'Woche';
|
||||
$labels['month'] = 'Monat';
|
||||
$labels['agenda'] = 'Agenda';
|
||||
$labels['new'] = 'Neu';
|
||||
$labels['new_event'] = 'Neuer Termin';
|
||||
$labels['edit_event'] = 'Termin bearbeiten';
|
||||
$labels['edit'] = 'Bearbeiten';
|
||||
|
@ -38,11 +39,13 @@ $labels['save'] = 'Speichern';
|
|||
$labels['remove'] = 'Entfernen';
|
||||
$labels['cancel'] = 'Abbrechen';
|
||||
$labels['select'] = 'Auswählen';
|
||||
$labels['print'] = 'Kalender drucken';
|
||||
$labels['print'] = 'Drucken';
|
||||
$labels['printtitle'] = 'Kalender drucken';
|
||||
$labels['title'] = 'Titel';
|
||||
$labels['description'] = 'Beschrieb';
|
||||
$labels['all-day'] = 'ganztägig';
|
||||
$labels['export'] = 'Exportieren...';
|
||||
$labels['export'] = 'Exportieren';
|
||||
$labels['exporttitle'] = 'Kalender als iCalendar exportieren';
|
||||
$labels['location'] = 'Ort';
|
||||
$labels['date'] = 'Datum';
|
||||
$labels['start'] = 'Beginn';
|
||||
|
@ -61,7 +64,7 @@ $labels['confidential'] = 'vertraulich';
|
|||
$labels['alarms'] = 'Erinnerung';
|
||||
$labels['generated'] = 'erstellt am';
|
||||
$labels['printdescriptions'] = 'Beschrieb drucken';
|
||||
$labels['parentcalendar'] = 'Übergeordneter Kalender';
|
||||
$labels['parentcalendar'] = 'Erstellen in';
|
||||
$labels['searchearlierdates'] = '« Frühere Termine suchen';
|
||||
$labels['searchlaterdates'] = 'Spätere Termine suchen »';
|
||||
$labels['andnmore'] = '$nr weitere...';
|
||||
|
@ -72,6 +75,8 @@ $labels['importevents'] = 'Termine importieren';
|
|||
$labels['importrange'] = 'Termine ab';
|
||||
$labels['onemonthback'] = '1 Monat zurück';
|
||||
$labels['nmonthsback'] = '$nr Monate zurück';
|
||||
$labels['showurl'] = 'URL anzeigen';
|
||||
$labels['showurldescription'] = 'Über die folgende Adresse können Sie mit einem beliebigen Kalenderprogramm auf Ihren Kalender zugreifen, sofern dieses das iCal-Format unterstützt.';
|
||||
|
||||
// agenda view
|
||||
$labels['listrange'] = 'Angezeigter Bereich:';
|
||||
|
|
|
@ -31,6 +31,7 @@ $labels['day'] = 'Tag';
|
|||
$labels['week'] = 'Woche';
|
||||
$labels['month'] = 'Monat';
|
||||
$labels['agenda'] = 'Agenda';
|
||||
$labels['new'] = 'Neu';
|
||||
$labels['new_event'] = 'Neuer Termin';
|
||||
$labels['edit_event'] = 'Termin bearbeiten';
|
||||
$labels['edit'] = 'Bearbeiten';
|
||||
|
@ -38,11 +39,13 @@ $labels['save'] = 'Speichern';
|
|||
$labels['remove'] = 'Entfernen';
|
||||
$labels['cancel'] = 'Abbrechen';
|
||||
$labels['select'] = 'Auswählen';
|
||||
$labels['print'] = 'Kalender drucken';
|
||||
$labels['print'] = 'Drucken';
|
||||
$labels['printtitle'] = 'Kalender drucken';
|
||||
$labels['title'] = 'Titel';
|
||||
$labels['description'] = 'Beschrieb';
|
||||
$labels['all-day'] = 'ganztägig';
|
||||
$labels['export'] = 'Exportieren...';
|
||||
$labels['export'] = 'Exportieren';
|
||||
$labels['exporttitle'] = 'Kalender als iCalendar exportieren';
|
||||
$labels['location'] = 'Ort';
|
||||
$labels['date'] = 'Datum';
|
||||
$labels['start'] = 'Beginn';
|
||||
|
@ -61,7 +64,7 @@ $labels['confidential'] = 'vertraulich';
|
|||
$labels['alarms'] = 'Erinnerung';
|
||||
$labels['generated'] = 'erstellt am';
|
||||
$labels['printdescriptions'] = 'Beschrieb drucken';
|
||||
$labels['parentcalendar'] = 'Übergeordneter Kalender';
|
||||
$labels['parentcalendar'] = 'Erstellen in';
|
||||
$labels['searchearlierdates'] = '« Frühere Termine suchen';
|
||||
$labels['searchlaterdates'] = 'Spätere Termine suchen »';
|
||||
$labels['andnmore'] = '$nr weitere...';
|
||||
|
@ -72,6 +75,8 @@ $labels['importevents'] = 'Termine importieren';
|
|||
$labels['importrange'] = 'Termine ab';
|
||||
$labels['onemonthback'] = '1 Monat zurück';
|
||||
$labels['nmonthsback'] = '$nr Monate zurück';
|
||||
$labels['showurl'] = 'URL anzeigen';
|
||||
$labels['showurldescription'] = 'Über die folgende Adresse können Sie mit einem beliebigen Kalenderprogramm auf Ihren Kalender zugreifen, sofern dieses das iCal-Format unterstützt.';
|
||||
|
||||
// agenda view
|
||||
$labels['listrange'] = 'Angezeigter Bereich:';
|
||||
|
|
|
@ -31,6 +31,7 @@ $labels['day'] = 'Day';
|
|||
$labels['week'] = 'Week';
|
||||
$labels['month'] = 'Month';
|
||||
$labels['agenda'] = 'Agenda';
|
||||
$labels['new'] = 'New';
|
||||
$labels['new_event'] = 'New event';
|
||||
$labels['edit_event'] = 'Edit event';
|
||||
$labels['edit'] = 'Edit';
|
||||
|
@ -38,11 +39,13 @@ $labels['save'] = 'Save';
|
|||
$labels['remove'] = 'Remove';
|
||||
$labels['cancel'] = 'Cancel';
|
||||
$labels['select'] = 'Select';
|
||||
$labels['print'] = 'Print calendars';
|
||||
$labels['print'] = 'Print';
|
||||
$labels['printtitle'] = 'Print calendars';
|
||||
$labels['title'] = 'Summary';
|
||||
$labels['description'] = 'Description';
|
||||
$labels['all-day'] = 'all-day';
|
||||
$labels['export'] = 'Export to iCalendar';
|
||||
$labels['export'] = 'Export';
|
||||
$labels['exporttitle'] = 'Export to iCalendar';
|
||||
$labels['location'] = 'Location';
|
||||
$labels['date'] = 'Date';
|
||||
$labels['start'] = 'Start';
|
||||
|
@ -61,7 +64,7 @@ $labels['confidential'] = 'confidential';
|
|||
$labels['alarms'] = 'Reminder';
|
||||
$labels['generated'] = 'generated at';
|
||||
$labels['printdescriptions'] = 'Print descriptions';
|
||||
$labels['parentcalendar'] = 'Superior calendar';
|
||||
$labels['parentcalendar'] = 'Insert inside';
|
||||
$labels['searchearlierdates'] = '« Search for earlier events';
|
||||
$labels['searchlaterdates'] = 'Search for later events »';
|
||||
$labels['andnmore'] = '$nr more...';
|
||||
|
@ -72,6 +75,8 @@ $labels['importevents'] = 'Import events';
|
|||
$labels['importrange'] = 'Events from';
|
||||
$labels['onemonthback'] = '1 month back';
|
||||
$labels['nmonthsback'] = '$nr months back';
|
||||
$labels['showurl'] = 'Show calendar URL';
|
||||
$labels['showurldescription'] = 'Use the following address to access your calendar from other applications. You can copy and paste this into any calendar software that supports the iCal format.';
|
||||
|
||||
// agenda view
|
||||
$labels['listrange'] = 'Range to display:';
|
||||
|
@ -205,6 +210,7 @@ $labels['localchangeswarning'] = 'You are about to make changes that will only b
|
|||
$labels['importsuccess'] = 'Successfully imported $nr events';
|
||||
$labels['importnone'] = 'No events found to be imported';
|
||||
$labels['importerror'] = 'An error occured while importing';
|
||||
$labels['aclnorights'] = 'You do not have administrator rights on this calendar.';
|
||||
|
||||
// recurrence form
|
||||
$labels['repeat'] = 'Repeat';
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
http://pear.php.net/dtd/package-2.0
|
||||
http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<name>calendar</name>
|
||||
<uri>http://kolabsys.com</uri>
|
||||
<uri>http://git.kolab.org/roundcube-plugins-kolab/</uri>
|
||||
<summary>Calendar plugin</summary>
|
||||
<description>-</description>
|
||||
<lead>
|
||||
|
|
|
@ -22,7 +22,7 @@ body.calendarmain {
|
|||
bottom: 10px;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
#calendarsidebar {
|
||||
position: absolute;
|
||||
top: 37px;
|
||||
left: 10px;
|
||||
|
@ -58,7 +58,7 @@ body.calendarmain {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
#sidebartoggle {
|
||||
#calendarsidebartoggle {
|
||||
position: absolute;
|
||||
left: 244px;
|
||||
width: 8px;
|
||||
|
@ -72,7 +72,7 @@ div.sidebarclosed {
|
|||
background-position: -8px 48% !important;
|
||||
}
|
||||
|
||||
#sidebartoggle:hover {
|
||||
#calendarsidebartoggle:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
|
@ -123,10 +123,11 @@ pre {
|
|||
display: block;
|
||||
}
|
||||
|
||||
#calendarslist li span {
|
||||
#calendarslist li span.handle {
|
||||
cursor: default;
|
||||
background: url(images/calendars.png) 0 -2px no-repeat;
|
||||
padding-left: 18px;
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
#calendarslist li input {
|
||||
|
@ -142,26 +143,34 @@ pre {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
#calendarslist li.readonly span {
|
||||
#calendarslist li.readonly span.handle {
|
||||
background-position: 0 -20px;
|
||||
}
|
||||
|
||||
#calendarslist li.other span {
|
||||
#calendarslist li.other span.handle {
|
||||
background-position: 0 -38px;
|
||||
}
|
||||
|
||||
#calendarslist li.other.readonly span {
|
||||
#calendarslist li.other.readonly span.handle {
|
||||
background-position: 0 -56px;
|
||||
}
|
||||
|
||||
#calendarslist li.shared span {
|
||||
#calendarslist li.shared span.handle {
|
||||
background-position: 0 -74px;
|
||||
}
|
||||
|
||||
#calendarslist li.shared.readonly span {
|
||||
#calendarslist li.shared.readonly span.handle {
|
||||
background-position: 0 -92px;
|
||||
}
|
||||
|
||||
#calfeedurl {
|
||||
width: 98%;
|
||||
background: #fbfbfb;
|
||||
padding: 4px;
|
||||
margin-bottom: 1em;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
#agendalist {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
|
@ -1164,7 +1173,9 @@ fieldset #calendarcategories div {
|
|||
/* Invitation UI in mail */
|
||||
|
||||
#messagemenu li a.calendarlink {
|
||||
background: url(images/calendars.png) 7px -109px no-repeat;
|
||||
background-image: url(images/calendars.png);
|
||||
background-position: 7px -109px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
div.calendar-invitebox {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
/*
|
||||
* FullCalendar v1.5.2 Stylesheet
|
||||
* FullCalendar v1.5.3-rcube-0.7.1 Stylesheet
|
||||
*
|
||||
* Copyright (c) 2011 Adam Shaw
|
||||
* Copyright (c) 2011, Kolab Systems AG
|
||||
* Dual licensed under the MIT and GPL licenses, located in
|
||||
* MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
|
||||
*
|
||||
* Date: Sun Aug 21 22:06:09 2011 -0700
|
||||
* Date: Mon Feb 13 23:00:46 2012 +0100
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -477,7 +478,7 @@ table.fc-border-separate {
|
|||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
padding: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Agenda Week View, Agenda Day View
|
||||
------------------------------------------------------------------------*/
|
||||
|
@ -620,8 +621,7 @@ table.fc-border-separate {
|
|||
.fc-agenda .ui-resizable-resizing { /* TODO: better selector */
|
||||
_overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.fc-timeline {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
|
|
|
@ -20,6 +20,10 @@ body, td, th, div, p, h3, select, input, textarea {
|
|||
overflow: visible;
|
||||
}
|
||||
|
||||
#calendar .fc-header-right {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
#printconfig {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<roundcube:include file="/includes/header.html" />
|
||||
|
||||
<div id="main">
|
||||
<div id="sidebar">
|
||||
<div id="calendarsidebar">
|
||||
<div id="datepicker"></div>
|
||||
<div id="calendars" style="visibility:hidden">
|
||||
<div class="boxtitle"><roundcube:label name="calendar.calendars" /></div>
|
||||
|
@ -25,7 +25,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="sidebartoggle"></div>
|
||||
<div id="calendarsidebartoggle"></div>
|
||||
<div id="calendar">
|
||||
<roundcube:object name="plugin.angenda_options" class="boxfooter" id="agendaoptions" />
|
||||
</div>
|
||||
|
@ -36,6 +36,7 @@
|
|||
<li><roundcube:button command="calendar-edit" label="calendar.edit" classAct="active" /></li>
|
||||
<li><roundcube:button command="calendar-remove" label="calendar.remove" classAct="active" /></li>
|
||||
<li><roundcube:button command="events-import" label="calendar.importevents" classAct="active" /></li>
|
||||
<li><roundcube:button command="calendar-showurl" label="calendar.showurl" classAct="active" /></li>
|
||||
<roundcube:if condition="env:calendar_driver == 'kolab'" />
|
||||
<li class="separator_above"><roundcube:button command="folders" task="settings" type="link" label="managefolders" classAct="active" /></li>
|
||||
<roundcube:endif />
|
||||
|
@ -142,6 +143,11 @@
|
|||
<roundcube:object name="plugin.events_import_form" id="events-import-form" uploadFieldSize="30" />
|
||||
</div>
|
||||
|
||||
<div id="calendarurlbox" class="uidialog">
|
||||
<p><roundcube:label name="calendar.showurldescription" /></p>
|
||||
<textarea id="calfeedurl" rows="2" readonly="readonly"></textarea>
|
||||
</div>
|
||||
|
||||
<div id="alarm-snooze-dropdown" class="popupmenu">
|
||||
<roundcube:object name="plugin.snooze_select" type="ul" />
|
||||
</div>
|
||||
|
@ -169,24 +175,24 @@ rcmail_ui.popups.calendaroptions = { id:'calendaroptionsmenu', above:1, obj:$('#
|
|||
|
||||
$(document).ready(function(e){
|
||||
// initialize sidebar toggle
|
||||
$('#sidebartoggle').click(function() {
|
||||
$('#calendarsidebartoggle').click(function() {
|
||||
var width = $(this).data('sidebarwidth');
|
||||
var offset = $(this).data('offset');
|
||||
var $sidebar = $('#sidebar'), time = 250;
|
||||
var $sidebar = $('#calendarsidebar'), time = 250;
|
||||
|
||||
if ($sidebar.is(':visible')) {
|
||||
$sidebar.animate({ left:'-'+(width+10)+'px' }, time, function(){ $('#sidebar').hide(); });
|
||||
$(this).animate({ left:'8px'}, time, function(){ $('#sidebartoggle').addClass('sidebarclosed') });
|
||||
$sidebar.animate({ left:'-'+(width+10)+'px' }, time, function(){ $('#calendarsidebar').hide(); });
|
||||
$(this).animate({ left:'8px'}, time, function(){ $('#calendarsidebartoggle').addClass('sidebarclosed') });
|
||||
$('#calendar').animate({ left:'20px'}, time, function(){ $(this).fullCalendar('render'); });
|
||||
}
|
||||
else {
|
||||
$sidebar.show().animate({ left:'10px' }, time);
|
||||
$(this).animate({ left:offset+'px'}, time, function(){ $('#sidebartoggle').removeClass('sidebarclosed'); });
|
||||
$(this).animate({ left:offset+'px'}, time, function(){ $('#calendarsidebartoggle').removeClass('sidebarclosed'); });
|
||||
$('#calendar').animate({ left:(width+16)+'px'}, time, function(){ $(this).fullCalendar('render'); });
|
||||
}
|
||||
})
|
||||
.data('offset', $('#sidebartoggle').position().left)
|
||||
.data('sidebarwidth', $('#sidebar').width() + $('#sidebar').position().left);
|
||||
.data('offset', $('#calendarsidebartoggle').position().left)
|
||||
.data('sidebarwidth', $('#calendarsidebar').width() + $('#calendarsidebar').position().left);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
5
plugins/calendar/skins/larry/.htaccess
Normal file
5
plugins/calendar/skins/larry/.htaccess
Normal file
|
@ -0,0 +1,5 @@
|
|||
# get all unknown files from default skin folder
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule (.*) ../default/$1 [qsappend,last]
|
1332
plugins/calendar/skins/larry/calendar.css
Normal file
1332
plugins/calendar/skins/larry/calendar.css
Normal file
File diff suppressed because it is too large
Load diff
36
plugins/calendar/skins/larry/templates/attachment.html
Normal file
36
plugins/calendar/skins/larry/templates/attachment.html
Normal file
|
@ -0,0 +1,36 @@
|
|||
<roundcube:object name="doctype" value="html5" />
|
||||
<html>
|
||||
<head>
|
||||
<title><roundcube:object name="pagetitle" /></title>
|
||||
<roundcube:include file="/includes/links.html" />
|
||||
</head>
|
||||
<body class="extwin">
|
||||
|
||||
<div id="header">
|
||||
<div id="topline">
|
||||
<div class="topright">
|
||||
<a href="#close" class="closelink" onclick="self.close()"><roundcube:label name="close" /></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="topnav">
|
||||
<roundcube:object name="logo" src="/images/roundcube_logo.png" id="toplogo" border="0" alt="Logo" />
|
||||
</div>
|
||||
|
||||
<br style="clear:both" />
|
||||
</div>
|
||||
|
||||
<div id="mainscreen">
|
||||
<div id="partheader" class="uibox">
|
||||
<roundcube:object name="plugin.attachmentcontrols" class="headers-table" />
|
||||
</div>
|
||||
|
||||
<div id="attachmentcontainer" class="uibox">
|
||||
<roundcube:object name="plugin.attachmentframe" id="attachmentframe" style="width:100%; height:100%" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
202
plugins/calendar/skins/larry/templates/calendar.html
Normal file
202
plugins/calendar/skins/larry/templates/calendar.html
Normal file
|
@ -0,0 +1,202 @@
|
|||
<roundcube:object name="doctype" value="html5" />
|
||||
<html>
|
||||
<head>
|
||||
<title><roundcube:object name="pagetitle" /></title>
|
||||
<roundcube:include file="/includes/links.html" />
|
||||
<!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="./plugins/calendar/$__skin_path/iehacks.css" /><![endif]-->
|
||||
</head>
|
||||
<body class="calendarmain noscroll">
|
||||
|
||||
<roundcube:include file="/includes/header.html" />
|
||||
|
||||
<div id="mainscreen">
|
||||
<div id="calendarsidebar">
|
||||
<div id="quicksearchbar">
|
||||
<roundcube:object name="plugin.searchform" id="quicksearchbox" />
|
||||
<a id="searchmenulink" class="iconbutton searchoptions" > </a>
|
||||
<roundcube:button command="reset-search" id="searchreset" class="iconbutton reset" title="resetsearch" content=" " />
|
||||
</div>
|
||||
|
||||
<div id="datepicker" class="uibox"></div>
|
||||
|
||||
<div id="calendars" class="uibox listbox" style="visibility:hidden">
|
||||
<h2 class="boxtitle"><roundcube:label name="calendar.calendars" /></h2>
|
||||
<div class="scroller withfooter">
|
||||
<roundcube:object name="plugin.calendar_list" id="calendarslist" class="listing" />
|
||||
</div>
|
||||
<div class="boxfooter">
|
||||
<roundcube:button command="calendar-create" type="link" title="calendar.createcalendar" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" content="+" /><roundcube:button name="calendaroptionslink" id="calendaroptionsmenulink" type="link" title="calendar.calendaractions" class="listbutton groupactions" onclick="UI.show_popup('calendaroptionsmenu', undefined, { above:true });return false" innerClass="inner" content="⚙" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="calendarsidebartoggle"></div>
|
||||
|
||||
<div id="calendartoolbar" class="toolbar">
|
||||
<roundcube:button command="addevent" type="link" class="button addevent disabled" classAct="button addevent" classSel="button addevent pressed" label="calendar.new_event" title="calendar.new_event" />
|
||||
<roundcube:button command="print" type="link" class="button print disabled" classAct="button print" classSel="button print pressed" label="calendar.print" title="calendar.printtitle" />
|
||||
<roundcube:button command="export" type="link" class="button export disabled" classAct="button export" classSel="button export pressed" label="calendar.export" title="calendar.exporttitle" />
|
||||
<roundcube:container name="toolbar" id="calendartoolbar" />
|
||||
</div>
|
||||
|
||||
<div id="calendar">
|
||||
<roundcube:object name="plugin.angenda_options" class="boxfooter" id="agendaoptions" />
|
||||
<roundcube:object name="message" id="message" class="statusbar" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="calendaroptionsmenu" class="popupmenu">
|
||||
<ul class="toolbarmenu">
|
||||
<li><roundcube:button command="calendar-edit" label="calendar.edit" classAct="active" /></li>
|
||||
<li><roundcube:button command="calendar-remove" label="calendar.remove" classAct="active" /></li>
|
||||
<li><roundcube:button command="events-import" label="calendar.importevents" classAct="active" /></li>
|
||||
<li><roundcube:button command="calendar-showurl" label="calendar.showurl" classAct="active" /></li>
|
||||
<roundcube:if condition="env:calendar_driver == 'kolab'" />
|
||||
<li class="separator_above"><roundcube:button command="folders" task="settings" type="link" label="managefolders" classAct="active" /></li>
|
||||
<roundcube:endif />
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="eventshow" class="uidialog">
|
||||
<h1 id="event-title">Event Title</h1>
|
||||
<div class="event-section" id="event-location">Location</div>
|
||||
<div class="event-section" id="event-date">From-To</div>
|
||||
<div class="event-section" id="event-description">
|
||||
<h5 class="label"><roundcube:label name="calendar.description" /></h5>
|
||||
<div class="event-text"></div>
|
||||
</div>
|
||||
<div class="event-section" id="event-repeat">
|
||||
<h5 class="label"><roundcube:label name="calendar.repeat" /></h5>
|
||||
<div class="event-text"></div>
|
||||
</div>
|
||||
<div class="event-section" id="event-alarm">
|
||||
<h5 class="label"><roundcube:label name="calendar.alarms" /></h5>
|
||||
<div class="event-text"></div>
|
||||
</div>
|
||||
<div class="event-section" id="event-attendees">
|
||||
<h5 class="label"><roundcube:label name="calendar.tabattendees" /></h5>
|
||||
<div class="event-text"></div>
|
||||
</div>
|
||||
<div class="event-line" id="event-calendar">
|
||||
<label><roundcube:label name="calendar.calendar" /></label>
|
||||
<span class="event-text">Default</span>
|
||||
</div>
|
||||
<div class="event-line" id="event-category">
|
||||
<label><roundcube:label name="calendar.category" /></label>
|
||||
<span class="event-text"></span>
|
||||
</div>
|
||||
<div class="event-line" id="event-free-busy">
|
||||
<label><roundcube:label name="calendar.freebusy" /></label>
|
||||
<span class="event-text"></span>
|
||||
</div>
|
||||
<div class="event-line" id="event-priority">
|
||||
<label><roundcube:label name="calendar.priority" /></label>
|
||||
<span class="event-text"></span>
|
||||
</div>
|
||||
<div class="event-line" id="event-sensitivity">
|
||||
<label><roundcube:label name="calendar.sensitivity" /></label>
|
||||
<span class="event-text"></span>
|
||||
</div>
|
||||
<div class="event-section" id="event-attachments">
|
||||
<label><roundcube:label name="attachments" /></label>
|
||||
<div class="event-text"></div>
|
||||
</div>
|
||||
|
||||
<roundcube:object name="plugin.event_rsvp_buttons" id="event-rsvp" style="display:none" />
|
||||
</div>
|
||||
|
||||
<roundcube:include file="/templates/eventedit.html" />
|
||||
|
||||
<div id="eventfreebusy" class="uidialog">
|
||||
<roundcube:object name="plugin.attendees_freebusy_table" id="attendees-freebusy-table" cellspacing="0" cellpadding="0" border="0" />
|
||||
|
||||
<div class="schedule-options">
|
||||
|
||||
<div class="schedule-buttons">
|
||||
<button id="shedule-freebusy-prev" title="<roundcube:label name='previouspage' />">◄</button><button id="shedule-freebusy-next" title="<roundcube:label name='nextpage' />">►</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="float:left; width:28em">
|
||||
<div class="form-section">
|
||||
<label for="schedule-startdate"><roundcube:label name="calendar.start" /></label>
|
||||
<input type="text" name="startdate" size="10" id="schedule-startdate" disabled="true" />
|
||||
<input type="text" name="starttime" size="6" id="schedule-starttime" disabled="true" />
|
||||
</div>
|
||||
<div class="form-section">
|
||||
<label for="schedule-enddate"><roundcube:label name="calendar.end" /></label>
|
||||
<input type="text" name="enddate" size="10" id="schedule-enddate" disabled="true" />
|
||||
<input type="text" name="endtime" size="6" id="schedule-endtime" disabled="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div style="float:left">
|
||||
<div class="schedule-find-buttons">
|
||||
<button id="shedule-find-prev">◄ <roundcube:label name="calendar.prevslot" /></button>
|
||||
<button id="shedule-find-next"><roundcube:label name="calendar.nextslot" /> ►</button>
|
||||
</div>
|
||||
<div class="schedule-options">
|
||||
<label><input type="checkbox" id="schedule-freebusy-workinghours" value="1" /><roundcube:label name="calendar.onlyworkinghours" /></label>
|
||||
</div>
|
||||
</div>
|
||||
<br style="clear:both;" />
|
||||
|
||||
<roundcube:include file="/templates/freebusylegend.html" />
|
||||
<div class="attendees-list">
|
||||
<span class="attendee organizer"><roundcube:label name="calendar.roleorganizer" /></span>
|
||||
<span class="attendee req-participant"><roundcube:label name="calendar.rolerequired" /></span>
|
||||
<span class="attendee opt-participant"><roundcube:label name="calendar.roleoptional" /></span>
|
||||
<span class="attendee chair"><roundcube:label name="calendar.roleresource" /></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="calendarform" class="uidialog">
|
||||
<roundcube:label name="loading" />
|
||||
</div>
|
||||
|
||||
<div id="eventsimport" class="uidialog">
|
||||
<roundcube:object name="plugin.events_import_form" id="events-import-form" uploadFieldSize="30" />
|
||||
</div>
|
||||
|
||||
<div id="calendarurlbox" class="uidialog">
|
||||
<p><roundcube:label name="calendar.showurldescription" /></p>
|
||||
<textarea id="calfeedurl" rows="2" readonly="readonly"></textarea>
|
||||
</div>
|
||||
|
||||
<div id="alarm-snooze-dropdown" class="popupmenu">
|
||||
<roundcube:object name="plugin.snooze_select" type="ul" />
|
||||
</div>
|
||||
|
||||
<roundcube:object name="plugin.calendar_css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
// UI startup
|
||||
var UI = new rcube_mail_ui();
|
||||
|
||||
$(document).ready(function(e){
|
||||
UI.init();
|
||||
|
||||
// initialize sidebar toggle
|
||||
$('#calendarsidebartoggle').click(function() {
|
||||
var width = $(this).data('sidebarwidth');
|
||||
var offset = $(this).data('offset');
|
||||
var $sidebar = $('#calendarsidebar'), time = 250;
|
||||
|
||||
if ($sidebar.is(':visible')) {
|
||||
$sidebar.animate({ left:'-'+(width+10)+'px' }, time, function(){ $('#calendarsidebar').hide(); });
|
||||
$(this).animate({ left:'8px'}, time, function(){ $('#calendarsidebartoggle').addClass('sidebarclosed') });
|
||||
$('#calendar').animate({ left:'20px'}, time, function(){ $(this).fullCalendar('render'); });
|
||||
}
|
||||
else {
|
||||
$sidebar.show().animate({ left:'10px' }, time);
|
||||
$(this).animate({ left:offset+'px'}, time, function(){ $('#calendarsidebartoggle').removeClass('sidebarclosed'); });
|
||||
$('#calendar').animate({ left:(width+16)+'px'}, time, function(){ $(this).fullCalendar('render'); });
|
||||
}
|
||||
})
|
||||
.data('offset', $('#calendarsidebartoggle').position().left)
|
||||
.data('sidebarwidth', $('#calendarsidebar').width() + $('#calendarsidebar').position().left);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
100
plugins/calendar/skins/larry/templates/eventedit.html
Normal file
100
plugins/calendar/skins/larry/templates/eventedit.html
Normal file
|
@ -0,0 +1,100 @@
|
|||
<div id="eventedit" class="uidialog uidialog-tabbed">
|
||||
<form id="eventtabs" action="#" method="post" enctype="multipart/form-data">
|
||||
<ul>
|
||||
<li><a href="#event-tab-1"><roundcube:label name="calendar.tabsummary" /></a></li><li id="edit-tab-recurrence"><a href="#event-tab-2"><roundcube:label name="calendar.tabrecurrence" /></a></li><li id="edit-tab-attendees"><a href="#event-tab-3"><roundcube:label name="calendar.tabattendees" /></a></li><li id="edit-tab-attachments"><a href="#event-tab-4"><roundcube:label name="calendar.tabattachments" /></a></li>
|
||||
</ul>
|
||||
<!-- basic info -->
|
||||
<div id="event-tab-1">
|
||||
<div class="event-section">
|
||||
<label for="edit-title"><roundcube:label name="calendar.title" /></label>
|
||||
<br />
|
||||
<input type="text" class="text" name="title" id="edit-title" size="40" />
|
||||
</div>
|
||||
<div class="event-section">
|
||||
<label for="edit-location"><roundcube:label name="calendar.location" /></label>
|
||||
<br />
|
||||
<input type="text" class="text" name="location" id="edit-location" size="40" />
|
||||
</div>
|
||||
<div class="event-section">
|
||||
<label for="edit-description"><roundcube:label name="calendar.description" /></label>
|
||||
<br />
|
||||
<textarea name="description" id="edit-description" class="text" rows="5" cols="40"></textarea>
|
||||
</div>
|
||||
<div class="event-section">
|
||||
<label style="float:right;padding-right:0.5em"><input type="checkbox" name="allday" id="edit-allday" value="1" /><roundcube:label name="calendar.all-day" /></label>
|
||||
<label for="edit-startdate"><roundcube:label name="calendar.start" /></label>
|
||||
<input type="text" name="startdate" size="10" id="edit-startdate" />
|
||||
<input type="text" name="starttime" size="6" id="edit-starttime" />
|
||||
</div>
|
||||
<div class="event-section">
|
||||
<label for="edit-enddate"><roundcube:label name="calendar.end" /></label>
|
||||
<input type="text" name="enddate" size="10" id="edit-enddate" />
|
||||
<input type="text" name="endtime" size="6" id="edit-endtime" />
|
||||
</div>
|
||||
<div class="event-section" id="edit-alarms">
|
||||
<label for="edit-alarm"><roundcube:label name="calendar.alarms" /></label>
|
||||
<roundcube:object name="plugin.alarm_select" />
|
||||
</div>
|
||||
<div class="event-section" id="calendar-select">
|
||||
<label for="edit-calendar"><roundcube:label name="calendar.calendar" /></label>
|
||||
<roundcube:object name="plugin.calendar_select" id="edit-calendar" />
|
||||
</div>
|
||||
<div class="event-section">
|
||||
<label for="edit-categories"><roundcube:label name="calendar.category" /></label>
|
||||
<roundcube:object name="plugin.category_select" id="edit-categories" />
|
||||
</div>
|
||||
<div class="event-section">
|
||||
<label for="edit-free-busy"><roundcube:label name="calendar.freebusy" /></label>
|
||||
<roundcube:object name="plugin.freebusy_select" id="edit-free-busy" />
|
||||
</div>
|
||||
<div class="event-section">
|
||||
<label for="edit-priority"><roundcube:label name="calendar.priority" /></label>
|
||||
<roundcube:object name="plugin.priority_select" id="edit-priority" />
|
||||
</div>
|
||||
<div class="event-section">
|
||||
<label for="edit-sensitivity"><roundcube:label name="calendar.sensitivity" /></label>
|
||||
<roundcube:object name="plugin.sensitivity_select" id="edit-sensitivity" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- recurrence settings -->
|
||||
<div id="event-tab-2">
|
||||
<div class="event-section border-after">
|
||||
<roundcube:object name="plugin.recurrence_form" part="frequency" />
|
||||
</div>
|
||||
<div class="recurrence-form border-after" id="recurrence-form-daily">
|
||||
<roundcube:object name="plugin.recurrence_form" part="daily" class="event-section" />
|
||||
</div>
|
||||
<div class="recurrence-form border-after" id="recurrence-form-weekly">
|
||||
<roundcube:object name="plugin.recurrence_form" part="weekly" class="event-section" />
|
||||
</div>
|
||||
<div class="recurrence-form border-after" id="recurrence-form-monthly">
|
||||
<roundcube:object name="plugin.recurrence_form" part="monthly" class="event-section" />
|
||||
</div>
|
||||
<div class="recurrence-form border-after" id="recurrence-form-yearly">
|
||||
<roundcube:object name="plugin.recurrence_form" part="yearly" class="event-section" />
|
||||
</div>
|
||||
<div class="recurrence-form" id="recurrence-form-until">
|
||||
<roundcube:object name="plugin.recurrence_form" part="until" class="event-section" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- attendees list -->
|
||||
<div id="event-tab-3">
|
||||
<roundcube:object name="plugin.attendees_list" id="edit-attendees-table" class="records-table" />
|
||||
<roundcube:object name="plugin.attendees_form" id="edit-attendees-form" />
|
||||
<roundcube:include file="/templates/freebusylegend.html" />
|
||||
</div>
|
||||
<!-- attachments list (with upload form) -->
|
||||
<div id="event-tab-4">
|
||||
<div id="edit-attachments">
|
||||
<roundcube:object name="plugin.attachments_list" id="attachment-list" class="attachmentslist" cancelIcon="/images/0.gif" />
|
||||
</div>
|
||||
<div id="edit-attachments-form">
|
||||
<roundcube:object name="plugin.attachments_form" id="calendar-attachment-form" attachmentFieldSize="30" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<roundcube:object name="plugin.edit_attendees_notify" id="edit-attendees-notify" class="event-dialog-message" style="display:none" />
|
||||
<roundcube:object name="plugin.edit_recurring_warning" class="event-dialog-message edit-recurring-warning" style="display:none" />
|
||||
<div id="edit-localchanges-warning" class="event-dialog-message" style="display:none"><roundcube:label name="calendar.localchangeswarning" /></div>
|
||||
</div>
|
|
@ -0,0 +1,7 @@
|
|||
<div id="edit-attendees-legend" class="availability">
|
||||
<span class="legend"><img class="availabilityicon free" src="./program/blank.gif" /> <roundcube:label name="calendar.availfree" /></span>
|
||||
<span class="legend"><img class="availabilityicon busy" src="./program/blank.gif" /> <roundcube:label name="calendar.availbusy" /></span>
|
||||
<span class="legend"><img class="availabilityicon tentative" src="./program/blank.gif" /> <roundcube:label name="calendar.availtentative" /></span>
|
||||
<span class="legend"><img class="availabilityicon out-of-office" src="./program/blank.gif" /> <roundcube:label name="calendar.availoutofoffice" /></span>
|
||||
<span class="legend"><img class="availabilityicon unknown" src="./program/blank.gif" /> <roundcube:label name="calendar.availunknown" /></span>
|
||||
</div>
|
36
plugins/calendar/skins/larry/templates/itipattend.html
Normal file
36
plugins/calendar/skins/larry/templates/itipattend.html
Normal file
|
@ -0,0 +1,36 @@
|
|||
<roundcube:object name="doctype" value="html5" />
|
||||
<html>
|
||||
<head>
|
||||
<title><roundcube:object name="pagetitle" /></title>
|
||||
<roundcube:include file="/includes/links.html" />
|
||||
</head>
|
||||
<body class="extwin calendaritipattend">
|
||||
|
||||
<div id="header">
|
||||
<div id="topline">
|
||||
<div class="topright">
|
||||
<a href="#close" class="closelink" onclick="self.close()"><roundcube:label name="close" /></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="topnav">
|
||||
<roundcube:object name="logo" src="/images/roundcube_logo.png" id="toplogo" border="0" alt="Logo" />
|
||||
</div>
|
||||
|
||||
<br style="clear:both" />
|
||||
</div>
|
||||
|
||||
<div id="mainscreen">
|
||||
|
||||
<div class="centerbox uibox">
|
||||
<roundcube:object name="plugin.event_inviteform" />
|
||||
<roundcube:object name="plugin.event_invitebox" class="calendar-invitebox" />
|
||||
<roundcube:object name="plugin.event_rsvp_buttons" type="submit" iname="rsvp" id="event-rsvp" />
|
||||
<roundcube:object name="message" id="message" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
24
plugins/calendar/skins/larry/templates/kolabacl.html
Normal file
24
plugins/calendar/skins/larry/templates/kolabacl.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
<roundcube:object name="doctype" value="html5" />
|
||||
<html>
|
||||
<head>
|
||||
<title><roundcube:object name="pagetitle" /></title>
|
||||
<roundcube:include file="/includes/links.html" />
|
||||
<style type="text/css" media="screen">
|
||||
|
||||
body.aclform {
|
||||
background: #efefef;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body.aclform .hint {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body class="iframe aclform">
|
||||
|
||||
<roundcube:object name="folderacl" />
|
||||
|
||||
</body>
|
||||
</html>
|
9
plugins/calendar/skins/larry/templates/kolabform.html
Normal file
9
plugins/calendar/skins/larry/templates/kolabform.html
Normal file
|
@ -0,0 +1,9 @@
|
|||
<div id="calendar-kolabform" class="propform tabbed">
|
||||
<roundcube:object name="calendarform" />
|
||||
</div>
|
||||
<style type="text/css">
|
||||
#calendarpropform { min-width:680px; margin-top:-12px; }
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
UI.init_tabs('#calendar-kolabform');
|
||||
</script>
|
28
plugins/calendar/skins/larry/templates/print.html
Normal file
28
plugins/calendar/skins/larry/templates/print.html
Normal file
|
@ -0,0 +1,28 @@
|
|||
<roundcube:object name="doctype" value="html5" />
|
||||
<html>
|
||||
<head>
|
||||
<title><roundcube:object name="pagetitle" /></title>
|
||||
</head>
|
||||
<body class="calendarprint">
|
||||
|
||||
<div id="printconfig" class="noprint">
|
||||
<div class="calwidth">
|
||||
<a href="#close" onclick="window.close()" class="rightalign"><roundcube:label name="close" /></a>
|
||||
<span class="prop"><input type="button" id="printme" value="<roundcube:label name='print' />" onclick="window.print()"></span>
|
||||
<span class="prop"><label><input type="checkbox" id="propdescription" checked="checked" /> <roundcube:label name="calendar.printdescriptions" /></label></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<roundcube:object name="message" id="message" class="noprint" />
|
||||
|
||||
<div id="calendar" class="calwidth"></div>
|
||||
|
||||
<div class="calwidth">
|
||||
<roundcube:object name="plugin.calendar_list" activeonly="true" id="calendarlist" />
|
||||
</div>
|
||||
|
||||
<roundcube:object name="plugin.calendar_css" printmode="true" />
|
||||
|
||||
<!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="./plugins/calendar/skins/default/print.iehacks.css" /><![endif]-->
|
||||
</body>
|
||||
</html>
|
|
@ -131,7 +131,7 @@ class kolab_addressbook extends rcube_plugin
|
|||
'editable' => $abook->editable,
|
||||
'groups' => $abook->groups,
|
||||
'undelete' => $abook->undelete && $undelete,
|
||||
'realname' => rcube_charset_convert($abook->get_realname(), 'UTF7-IMAP'), // IMAP folder name
|
||||
'realname' => rcube_charset::convert($abook->get_realname(), 'UTF7-IMAP'), // IMAP folder name
|
||||
'class_name' => $abook->get_namespace(),
|
||||
'kolab' => true,
|
||||
);
|
||||
|
@ -258,7 +258,7 @@ class kolab_addressbook extends rcube_plugin
|
|||
// 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');
|
||||
$names[$c_folder->name] = rcube_charset::convert($c_folder->name, 'UTF7-IMAP');
|
||||
|
||||
asort($names, SORT_LOCALE_STRING);
|
||||
|
||||
|
@ -420,14 +420,14 @@ class kolab_addressbook extends rcube_plugin
|
|||
*/
|
||||
public function book_save()
|
||||
{
|
||||
$storage = $this->rc->get_storage();
|
||||
$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'];
|
||||
$delimiter = $storage->get_hierarchy_delimiter();
|
||||
|
||||
if (strlen($oldfolder)) {
|
||||
$this->rc->imap_connect();
|
||||
$options = $this->rc->imap->mailbox_info($oldfolder);
|
||||
$options = $storage->folder_info($oldfolder);
|
||||
}
|
||||
|
||||
if (!empty($options) && ($options['norename'] || $options['protected'])) {
|
||||
|
@ -458,14 +458,12 @@ class kolab_addressbook extends rcube_plugin
|
|||
}
|
||||
else {
|
||||
// add namespace prefix (when needed)
|
||||
$this->rc->imap_init();
|
||||
$folder = $this->rc->imap->mod_mailbox($folder, 'in');
|
||||
$folder = $storage->mod_folder($folder, 'in');
|
||||
}
|
||||
|
||||
// Check access rights to the parent folder
|
||||
if (strlen($path) && (!strlen($oldfolder) || $oldfolder != $folder)) {
|
||||
$this->rc->imap_connect();
|
||||
$parent_opts = $this->rc->imap->mailbox_info($path);
|
||||
$parent_opts = $storage->folder_info($path);
|
||||
if ($parent_opts['namespace'] != 'personal'
|
||||
&& (empty($parent_opts['rights']) || !preg_match('/[ck]/', implode($parent_opts['rights'])))
|
||||
) {
|
||||
|
@ -552,7 +550,7 @@ class kolab_addressbook extends rcube_plugin
|
|||
'readonly' => false,
|
||||
'editable' => true,
|
||||
'groups' => true,
|
||||
'realname' => rcube_charset_convert($folder, 'UTF7-IMAP'), // IMAP folder name
|
||||
'realname' => rcube_charset::convert($folder, 'UTF7-IMAP'), // IMAP folder name
|
||||
'class_name' => $kolab_folder->get_namespace(),
|
||||
'kolab' => true,
|
||||
), rcube_kolab::folder_id($oldfolder));
|
||||
|
|
|
@ -131,8 +131,9 @@ class rcube_kolab_contacts extends rcube_addressbook
|
|||
|
||||
public function __construct($imap_folder = null)
|
||||
{
|
||||
if ($imap_folder)
|
||||
if ($imap_folder) {
|
||||
$this->imap_folder = $imap_folder;
|
||||
}
|
||||
|
||||
// extend coltypes configuration
|
||||
$format = rcube_kolab::get_format('contact');
|
||||
|
@ -653,8 +654,9 @@ class rcube_kolab_contacts extends rcube_addressbook
|
|||
}
|
||||
|
||||
// store IMAP uids for undelete()
|
||||
if (!$force)
|
||||
if (!$force) {
|
||||
$_SESSION['kolab_delete_uids'] = $imap_uids;
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
@ -1015,32 +1017,39 @@ class rcube_kolab_contacts extends rcube_addressbook
|
|||
*/
|
||||
private function _sort_contacts_comp($a, $b)
|
||||
{
|
||||
$a_name = $a['name'];
|
||||
$b_name = $b['name'];
|
||||
$a_value = $b_value = '';
|
||||
|
||||
if (!$a_name) {
|
||||
$a_name = join(' ', array_filter(array($a['prefix'], $a['firstname'],
|
||||
$a['middlename'], $a['surname'], $a['suffix'])));
|
||||
if (!$a_name) {
|
||||
$a_name = is_array($a['email']) ? $a['email'][0] : $a['email'];
|
||||
}
|
||||
}
|
||||
if (!$b_name) {
|
||||
$b_name = join(' ', array_filter(array($b['prefix'], $b['firstname'],
|
||||
$b['middlename'], $b['surname'], $b['suffix'])));
|
||||
if (!$b_name) {
|
||||
$b_name = is_array($b['email']) ? $b['email'][0] : $b['email'];
|
||||
}
|
||||
switch ($this->sort_col) {
|
||||
case 'name':
|
||||
$a_value = $a['name'] . $a['prefix'];
|
||||
$b_value = $b['name'] . $b['prefix'];
|
||||
case 'firstname':
|
||||
$a_value .= $a['firstname'] . $a['middlename'] . $a['surname'];
|
||||
$b_value .= $b['firstname'] . $b['middlename'] . $b['surname'];
|
||||
break;
|
||||
|
||||
case 'surname':
|
||||
$a_value = $a['surname'] . $a['firstname'] . $a['middlename'];
|
||||
$b_value = $b['surname'] . $b['firstname'] . $b['middlename'];
|
||||
break;
|
||||
|
||||
default:
|
||||
$a_value = $a[$this->sort_col];
|
||||
$b_value = $b[$this->sort_col];
|
||||
break;
|
||||
}
|
||||
|
||||
// return strcasecmp($a_name, $b_name);
|
||||
$a_value .= is_array($a['email']) ? $a['email'][0] : $a['email'];
|
||||
$b_value .= is_array($b['email']) ? $b['email'][0] : $b['email'];
|
||||
|
||||
// return strcasecmp($a_value, $b_value);
|
||||
// make sorting unicode-safe and locale-dependent
|
||||
if ($a_name == $b_name)
|
||||
if ($a_value == $b_value)
|
||||
return 0;
|
||||
|
||||
$arr = array($a_name, $b_name);
|
||||
$arr = array($a_value, $b_value);
|
||||
sort($arr, SORT_LOCALE_STRING);
|
||||
return $a_name == $arr[0] ? -1 : 1;
|
||||
return $a_value == $arr[0] ? -1 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
46
plugins/kolab_addressbook/localization/de_CH.inc
Normal file
46
plugins/kolab_addressbook/localization/de_CH.inc
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
$labels = array();
|
||||
$labels['initials'] = 'Initialen';
|
||||
$labels['profession'] = 'Berufsbezeichnung';
|
||||
$labels['officelocation'] = 'Büro Adresse';
|
||||
$labels['children'] = 'Kinder';
|
||||
$labels['pgppublickey'] = 'Öffentlicher PGP-Schlüssel';
|
||||
$labels['freebusyurl'] = 'Frei/Belegt URL';
|
||||
$labels['typebusiness'] = 'Dienstlich';
|
||||
$labels['typebusinessfax'] = 'Dienst';
|
||||
$labels['typecompany'] = 'Firma';
|
||||
$labels['typeprimary'] = 'Primär';
|
||||
$labels['typetelex'] = 'Telex';
|
||||
$labels['typeradio'] = 'Funk';
|
||||
$labels['typeisdn'] = 'ISDN';
|
||||
$labels['typettytdd'] = 'Telescrit';
|
||||
$labels['typecallback'] = 'Rückruf';
|
||||
$labels['settings'] = 'Einstellungen';
|
||||
|
||||
$labels['bookcreate'] = 'Adressbuch anlegen';
|
||||
$labels['bookedit'] = 'Adressbuch bearbeiten';
|
||||
$labels['bookdelete'] = 'Adressbuch löschen';
|
||||
$labels['bookproperties'] = 'Eigenschaften des Adressbuchs';
|
||||
$labels['bookname'] = 'Name des Buches';
|
||||
$labels['parentbook'] = 'Übergeordnetes Buch';
|
||||
|
||||
$labels['addressbookprio'] = 'Reihenfolge der Adressbücher';
|
||||
$labels['personalfirst'] = 'Private(s) Adressbuch/Adressbücher zuerst';
|
||||
$labels['globalfirst'] = 'Globale(s) Adressbuch/Adressbücher zuerst';
|
||||
$labels['personalonly'] = 'Nur persönliche(s) Adressbuch/Adressbücher';
|
||||
$labels['globalonly'] = 'Nur globale(s) Adressbuch/Adressbücher';
|
||||
|
||||
$messages['bookdeleteconfirm'] = 'Soll das gewählte Adressbuch und alle Kontakte darin wirklich gelöscht werden?';
|
||||
$messages['bookdeleting'] = 'Adressbuch wird gelöscht...';
|
||||
$messages['booksaving'] = 'Adressbuch wird gespeichert...';
|
||||
$messages['bookdeleted'] = 'Adressbuch erfolgreich gelöscht.';
|
||||
$messages['bookupdated'] = 'Adressbuch erfolgreich aktualisiert.';
|
||||
$messages['bookcreated'] = 'Adressbuch erfolgreich angelegt.';
|
||||
$messages['bookdeleteerror'] = 'Fehler beim Löschen des Adressbuchs.';
|
||||
$messages['bookupdateerror'] = 'Fehler beim Aktualisieren des Adressbuchs.';
|
||||
$messages['bookcreateerror'] = 'Fehler beim Anlegen des Adressbuchs.';
|
||||
$messages['nobooknamewarning'] = 'Bitte den Namen des Adressbuchs angeben.';
|
||||
$messages['noemailnamewarning'] = 'Bitte E-Mail-Adresse oder Namen des Kontakts angeben.';
|
||||
|
||||
?>
|
46
plugins/kolab_addressbook/localization/de_DE.inc
Normal file
46
plugins/kolab_addressbook/localization/de_DE.inc
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
$labels = array();
|
||||
$labels['initials'] = 'Initialen';
|
||||
$labels['profession'] = 'Berufsbezeichnung';
|
||||
$labels['officelocation'] = 'Büro Adresse';
|
||||
$labels['children'] = 'Kinder';
|
||||
$labels['pgppublickey'] = 'Öffentlicher PGP-Schlüssel';
|
||||
$labels['freebusyurl'] = 'Frei/Belegt URL';
|
||||
$labels['typebusiness'] = 'Dienstlich';
|
||||
$labels['typebusinessfax'] = 'Dienst';
|
||||
$labels['typecompany'] = 'Firma';
|
||||
$labels['typeprimary'] = 'Primär';
|
||||
$labels['typetelex'] = 'Fernschreiber';
|
||||
$labels['typeradio'] = 'Funktelefon';
|
||||
$labels['typeisdn'] = 'ISDN';
|
||||
$labels['typettytdd'] = 'Schreibtelefon';
|
||||
$labels['typecallback'] = 'Rückruf';
|
||||
$labels['settings'] = 'Einstellungen';
|
||||
|
||||
$labels['bookcreate'] = 'Adressbuch anlegen';
|
||||
$labels['bookedit'] = 'Adressbuch bearbeiten';
|
||||
$labels['bookdelete'] = 'Adressbuch löschen';
|
||||
$labels['bookproperties'] = 'Eigenschaften des Adressbuchs';
|
||||
$labels['bookname'] = 'Name des Buches';
|
||||
$labels['parentbook'] = 'Übergeordnetes Buch';
|
||||
|
||||
$labels['addressbookprio'] = 'Reihenfolge der Adressbücher';
|
||||
$labels['personalfirst'] = 'Private(s) Adressbuch/Adressbücher zuerst';
|
||||
$labels['globalfirst'] = 'Globale(s) Adressbuch/Adressbücher zuerst';
|
||||
$labels['personalonly'] = 'Nur persönliche(s) Adressbuch/Adressbücher';
|
||||
$labels['globalonly'] = 'Nur globale(s) Adressbuch/Adressbücher';
|
||||
|
||||
$messages['bookdeleteconfirm'] = 'Soll das gewählte Adressbuch und alle Kontakte darin wirklich gelöscht werden?';
|
||||
$messages['bookdeleting'] = 'Adressbuch wird gelöscht...';
|
||||
$messages['booksaving'] = 'Adressbuch wird gespeichert...';
|
||||
$messages['bookdeleted'] = 'Adressbuch erfolgreich gelöscht.';
|
||||
$messages['bookupdated'] = 'Adressbuch erfolgreich aktualisiert.';
|
||||
$messages['bookcreated'] = 'Adressbuch erfolgreich angelegt.';
|
||||
$messages['bookdeleteerror'] = 'Fehler beim Löschen des Adressbuchs.';
|
||||
$messages['bookupdateerror'] = 'Fehler beim Aktualisieren des Adressbuchs.';
|
||||
$messages['bookcreateerror'] = 'Fehler beim Anlegen des Adressbuchs.';
|
||||
$messages['nobooknamewarning'] = 'Bitte den Namen des Adressbuchs angeben.';
|
||||
$messages['noemailnamewarning'] = 'Bitte E-Mail-Adresse oder Namen des Kontakts angeben.';
|
||||
|
||||
?>
|
|
@ -4,7 +4,7 @@
|
|||
http://pear.php.net/dtd/package-2.0
|
||||
http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<name>kolab_addressbook</name>
|
||||
<uri>http://kolabsys.com</uri>
|
||||
<uri>http://git.kolab.org/roundcube-plugins-kolab/</uri>
|
||||
<summary>Kolab addressbook</summary>
|
||||
<description>
|
||||
Sample plugin to add a new address book source with data from Kolab storage.
|
||||
|
|
|
@ -43,7 +43,7 @@ class kolab_auth extends rcube_plugin
|
|||
|
||||
// Hooks related to "Login As" feature
|
||||
$this->add_hook('template_object_loginform', array($this, 'login_form'));
|
||||
$this->add_hook('imap_connect', array($this, 'imap_connect'));
|
||||
$this->add_hook('storage_connect', array($this, 'imap_connect'));
|
||||
$this->add_hook('managesieve_connect', array($this, 'imap_connect'));
|
||||
$this->add_hook('smtp_connect', array($this, 'smtp_connect'));
|
||||
|
||||
|
@ -135,7 +135,7 @@ class kolab_auth extends rcube_plugin
|
|||
} else {
|
||||
$dont_override = $rcmail->config->get('dont_override');
|
||||
if (in_array($setting_name, $dont_override)) {
|
||||
$_dont_override = Array();
|
||||
$_dont_override = array();
|
||||
foreach ($dont_override as $_setting) {
|
||||
if ($_setting != $setting_name) {
|
||||
$_dont_override[] = $_setting;
|
||||
|
@ -346,6 +346,9 @@ class kolab_auth extends rcube_plugin
|
|||
|
||||
// Set credentials
|
||||
if ($record) {
|
||||
// Store UID in session for use by other plugins
|
||||
$_SESSION['kolab_uid'] = is_array($record['uid']) ? $record['uid'][0] : $record['uid'];
|
||||
|
||||
if ($login_attr)
|
||||
$this->data['user_login'] = is_array($record[$login_attr]) ? $record[$login_attr][0] : $record[$login_attr];
|
||||
if ($alias_attr)
|
||||
|
@ -405,8 +408,9 @@ class kolab_auth extends rcube_plugin
|
|||
*/
|
||||
private function init_ldap()
|
||||
{
|
||||
if ($this->ldap)
|
||||
if ($this->ldap) {
|
||||
return $this->ldap->ready;
|
||||
}
|
||||
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
|
@ -447,8 +451,9 @@ class kolab_auth extends rcube_plugin
|
|||
$this->ldap->set_filter($filter);
|
||||
$results = $this->ldap->list_records();
|
||||
|
||||
if (count($results->records) == 1)
|
||||
if (count($results->records) == 1) {
|
||||
return $results->records[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -480,9 +485,16 @@ class kolab_auth extends rcube_plugin
|
|||
*/
|
||||
class kolab_auth_ldap_backend extends rcube_ldap
|
||||
{
|
||||
function __construct($p, $debug=false, $mail_domain=null)
|
||||
{
|
||||
parent::__construct($p, $debug, $mail_domain);
|
||||
$this->fieldmap['uid'] = 'uid';
|
||||
}
|
||||
|
||||
function set_filter($filter)
|
||||
{
|
||||
if ($filter)
|
||||
if ($filter) {
|
||||
$this->prop['filter'] = $filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
5
plugins/kolab_auth/localization/de_CH.inc
Normal file
5
plugins/kolab_auth/localization/de_CH.inc
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
$labels['loginas'] = 'Anmelden als';
|
||||
|
||||
?>
|
5
plugins/kolab_auth/localization/de_DE.inc
Normal file
5
plugins/kolab_auth/localization/de_DE.inc
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
$labels['loginas'] = 'Anmelden als';
|
||||
|
||||
?>
|
|
@ -4,7 +4,7 @@
|
|||
http://pear.php.net/dtd/package-2.0
|
||||
http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<name>kolab_auth</name>
|
||||
<uri>http://kolabsys.com</uri>
|
||||
<uri>http://git.kolab.org/roundcube-plugins-kolab/</uri>
|
||||
<summary>Kolab Authentication</summary>
|
||||
<description>
|
||||
Authenticates on LDAP server, finds canonized authentication ID for IMAP
|
||||
|
@ -18,9 +18,9 @@
|
|||
<email>machniak@kolabsys.com</email>
|
||||
<active>yes</active>
|
||||
</lead>
|
||||
<date>2011-11-01</date>
|
||||
<date>2012-02-29</date>
|
||||
<version>
|
||||
<release>0.1</release>
|
||||
<release>0.2</release>
|
||||
<api>0.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
|
@ -38,6 +38,8 @@
|
|||
<file name="config.inc.php.dist" role="data"></file>
|
||||
<file name="LICENSE" role="data"></file>
|
||||
|
||||
<file name="localization/de_CH.inc" role="data"></file>
|
||||
<file name="localization/de_DE.inc" role="data"></file>
|
||||
<file name="localization/en_US.inc" role="data"></file>
|
||||
<file name="localization/pl_PL.inc" role="data"></file>
|
||||
</dir>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
http://pear.php.net/dtd/package-2.0
|
||||
http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<name>kolab_config</name>
|
||||
<uri>http://kolabsys.com</uri>
|
||||
<uri>http://git.kolab.org/roundcube-plugins-kolab/</uri>
|
||||
<summary>Kolab configuration storage</summary>
|
||||
<description>
|
||||
Plugin to use Kolab server as a configuration storage. Provides an API to handle
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
http://pear.php.net/dtd/package-2.0
|
||||
http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<name>kolab_core</name>
|
||||
<uri>http://kolabsys.com</uri>
|
||||
<uri>http://git.kolab.org/roundcube-plugins-kolab/</uri>
|
||||
<summary>Kolab API</summary>
|
||||
<description>
|
||||
Plugin to setup a basic environment for interaction with a Kolab server.
|
||||
|
|
|
@ -222,15 +222,9 @@ class rcube_kolab
|
|||
static $subscribed; // local cache
|
||||
|
||||
if (!$subscribed) {
|
||||
$rcmail = rcmail::get_instance();
|
||||
// try without connection first (list could be served from cache)
|
||||
$subscribed = $rcmail->imap ? $rcmail->imap->list_mailboxes() : array();
|
||||
|
||||
// now really get the list from the IMAP server
|
||||
if (empty($subscribed) || $subscribed == array('INBOX')) {
|
||||
$rcmail->imap_connect();
|
||||
$subscribed = $rcmail->imap->list_mailboxes();
|
||||
}
|
||||
$rcmail = rcmail::get_instance();
|
||||
$storage = $rcmail->get_storage();
|
||||
$subscribed = $storage->list_folders();
|
||||
}
|
||||
|
||||
return in_array($folder, $subscribed);
|
||||
|
@ -390,10 +384,9 @@ class rcube_kolab
|
|||
*/
|
||||
public static function object_name($folder, &$folder_ns=null)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$rcmail->imap_init();
|
||||
|
||||
$namespace = $rcmail->imap->get_namespace();
|
||||
$rcmail = rcmail::get_instance();
|
||||
$storage = $rcmail->get_storage();
|
||||
$namespace = $storage->get_namespace();
|
||||
$found = false;
|
||||
|
||||
if (!empty($namespace['shared'])) {
|
||||
|
@ -444,9 +437,9 @@ class rcube_kolab
|
|||
}
|
||||
|
||||
if (empty($delim))
|
||||
$delim = $rcmail->imap->get_hierarchy_delimiter();
|
||||
$delim = $storage->get_hierarchy_delimiter();
|
||||
|
||||
$folder = rcube_charset_convert($folder, 'UTF7-IMAP');
|
||||
$folder = rcube_charset::convert($folder, 'UTF7-IMAP');
|
||||
$folder = str_replace($delim, ' » ', $folder);
|
||||
|
||||
if ($prefix)
|
||||
|
@ -467,10 +460,9 @@ class rcube_kolab
|
|||
*/
|
||||
public static function folder_namespace($folder)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$rcmail->imap_init();
|
||||
|
||||
$namespace = $rcmail->imap->get_namespace();
|
||||
$rcmail = rcmail::get_instance();
|
||||
$storage = $rcmail->get_storage();
|
||||
$namespace = $storage->get_namespace();
|
||||
|
||||
if (!empty($namespace)) {
|
||||
foreach ($namespace as $nsname => $nsvalue) {
|
||||
|
@ -498,10 +490,13 @@ class rcube_kolab
|
|||
*/
|
||||
public static function folder_selector($type, $attrs, $current = '')
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$storage = $rcmail->get_storage();
|
||||
|
||||
// get all folders of specified type
|
||||
$folders = self::get_folders($type);
|
||||
|
||||
$delim = $_SESSION['imap_delimiter'];
|
||||
$delim = $storage->get_hierarchy_delimiter();
|
||||
$names = array();
|
||||
$len = strlen($current);
|
||||
|
||||
|
@ -528,12 +523,12 @@ class rcube_kolab
|
|||
}
|
||||
}
|
||||
|
||||
$names[$name] = rcube_charset_convert($name, 'UTF7-IMAP');
|
||||
$names[$name] = rcube_charset::convert($name, 'UTF7-IMAP');
|
||||
}
|
||||
|
||||
// Make sure parent folder is listed (might be skipped e.g. if it's namespace root)
|
||||
if ($p_len && !isset($names[$parent])) {
|
||||
$names[$parent] = rcube_charset_convert($parent, 'UTF7-IMAP');
|
||||
$names[$parent] = rcube_charset::convert($parent, 'UTF7-IMAP');
|
||||
}
|
||||
|
||||
// Sort folders list
|
||||
|
|
|
@ -26,9 +26,9 @@ $rcmail_config['kolab_folders_mail_drafts'] = '';
|
|||
// Sent folder
|
||||
$rcmail_config['kolab_folders_mail_sentitems'] = '';
|
||||
// Trash folder
|
||||
$rcmail_config['kolab_folders_mail_junkemail'] = '';
|
||||
$rcmail_config['kolab_folders_mail_wastebasket'] = '';
|
||||
// Others folders
|
||||
$rcmail_config['kolab_folders_mail_outbox'] = '';
|
||||
$rcmail_config['kolab_folders_mail_wastebasket'] = '';
|
||||
$rcmail_config['kolab_folders_mail_junkemail'] = '';
|
||||
|
||||
?>
|
||||
|
|
|
@ -41,7 +41,7 @@ class kolab_folders extends rcube_plugin
|
|||
$this->rc = rcmail::get_instance();
|
||||
|
||||
// Folder listing hooks
|
||||
$this->add_hook('mailboxes_list', array($this, 'mailboxes_list'));
|
||||
$this->add_hook('storage_folders', array($this, 'mailboxes_list'));
|
||||
|
||||
// Folder manager hooks
|
||||
$this->add_hook('folder_form', array($this, 'folder_form'));
|
||||
|
@ -72,7 +72,6 @@ class kolab_folders extends rcube_plugin
|
|||
$folderdata = $this->get_folder_type_list($args['root'].$args['name'], true);
|
||||
|
||||
if (!is_array($folderdata)) {
|
||||
$args['folders'] = false;
|
||||
return $args;
|
||||
}
|
||||
|
||||
|
@ -91,9 +90,14 @@ class kolab_folders extends rcube_plugin
|
|||
return $args;
|
||||
}
|
||||
|
||||
$storage = $this->rc->get_storage();
|
||||
|
||||
// Get folders list
|
||||
if ($args['mode'] == 'LIST') {
|
||||
$args['folders'] = $this->rc->imap->conn->listMailboxes($args['root'], $args['name']);
|
||||
if (!$storage->check_connection()) {
|
||||
return $args;
|
||||
}
|
||||
$args['folders'] = $storage->conn->listMailboxes($args['root'], $args['name']);
|
||||
}
|
||||
else {
|
||||
$args['folders'] = $this->list_subscribed($args['root'], $args['name']);
|
||||
|
@ -200,16 +204,21 @@ class kolab_folders extends rcube_plugin
|
|||
$ctype = 'mail';
|
||||
}
|
||||
|
||||
$storage = $this->rc->get_storage();
|
||||
|
||||
// Don't allow changing type of shared folder, according to ACL
|
||||
if (strlen($mbox)) {
|
||||
$options = $this->rc->imap->mailbox_info($mbox);
|
||||
$options = $storage->folder_info($mbox);
|
||||
if ($options['namespace'] != 'personal' && !in_array('a', $options['rights'])) {
|
||||
if (in_array($ctype, $this->types))
|
||||
if (in_array($ctype, $this->types)) {
|
||||
$value = $this->gettext('foldertype'.$ctype);
|
||||
else
|
||||
}
|
||||
else {
|
||||
$value = $ctype;
|
||||
if ($subtype)
|
||||
}
|
||||
if ($subtype) {
|
||||
$value .= ' ('. ($subtype == 'default' ? $this->gettext('default') : $subtype) .')';
|
||||
}
|
||||
|
||||
$args['form']['props']['fieldsets']['settings']['content']['foldertype'] = array(
|
||||
'label' => $this->gettext('folderctype'),
|
||||
|
@ -298,13 +307,15 @@ class kolab_folders extends rcube_plugin
|
|||
|
||||
$ctype .= $subtype ? '.'.$subtype : '';
|
||||
|
||||
$storage = $this->rc->get_storage();
|
||||
|
||||
// Create folder
|
||||
if (!strlen($old_mbox)) {
|
||||
// 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);
|
||||
$result = $storage->create_folder($mbox, $subscribe);
|
||||
// Set folder type
|
||||
if ($result) {
|
||||
$this->set_folder_type($mbox, $ctype);
|
||||
|
@ -313,7 +324,7 @@ class kolab_folders extends rcube_plugin
|
|||
// Rename folder
|
||||
else {
|
||||
if ($old_mbox != $mbox) {
|
||||
$result = $this->rc->imap->rename_mailbox($old_mbox, $mbox);
|
||||
$result = $storage->rename_folder($old_mbox, $mbox);
|
||||
}
|
||||
else {
|
||||
$result = true;
|
||||
|
@ -348,9 +359,11 @@ class kolab_folders extends rcube_plugin
|
|||
*/
|
||||
function metadata_support()
|
||||
{
|
||||
return $this->rc->imap->get_capability('METADATA') ||
|
||||
$this->rc->imap->get_capability('ANNOTATEMORE') ||
|
||||
$this->rc->imap->get_capability('ANNOTATEMORE2');
|
||||
$storage = $this->rc->get_storage();
|
||||
|
||||
return $storage->get_capability('METADATA') ||
|
||||
$storage->get_capability('ANNOTATEMORE') ||
|
||||
$storage->get_capability('ANNOTATEMORE2');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -362,7 +375,8 @@ class kolab_folders extends rcube_plugin
|
|||
*/
|
||||
function get_folder_type($folder)
|
||||
{
|
||||
$folderdata = $this->rc->imap->get_metadata($folder, array(kolab_folders::CTYPE_KEY));
|
||||
$storage = $this->rc->get_storage();
|
||||
$folderdata = $storage->get_metadata($folder, array(kolab_folders::CTYPE_KEY));
|
||||
|
||||
return explode('.', $folderdata[$folder][kolab_folders::CTYPE_KEY]);
|
||||
}
|
||||
|
@ -377,7 +391,9 @@ class kolab_folders extends rcube_plugin
|
|||
*/
|
||||
function set_folder_type($folder, $type='mail')
|
||||
{
|
||||
return $this->rc->imap->set_metadata($folder, array(kolab_folders::CTYPE_KEY => $type));
|
||||
$storage = $this->rc->get_storage();
|
||||
|
||||
return $storage->set_metadata($folder, array(kolab_folders::CTYPE_KEY => $type));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -390,23 +406,27 @@ class kolab_folders extends rcube_plugin
|
|||
*/
|
||||
private function list_subscribed($root='', $name='*')
|
||||
{
|
||||
$imap = $this->rc->imap;
|
||||
$storage = $this->rc->get_storage();
|
||||
|
||||
if (!$storage->check_connection()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Code copied from rcube_imap::_list_mailboxes()
|
||||
// Server supports LIST-EXTENDED, we can use selection options
|
||||
// #1486225: Some dovecot versions returns wrong result using LIST-EXTENDED
|
||||
if (!$this->rc->config->get('imap_force_lsub') && $imap->get_capability('LIST-EXTENDED')) {
|
||||
// This will also set mailbox options, LSUB doesn't do that
|
||||
$a_folders = $imap->conn->listMailboxes($root, $name,
|
||||
$a_folders = $storage->conn->listMailboxes($root, $name,
|
||||
NULL, array('SUBSCRIBED'));
|
||||
|
||||
// remove non-existent folders
|
||||
if (is_array($a_folders) && $name = '*') {
|
||||
if (is_array($a_folders) && $name = '*' && !empty($storage->conn->data['LIST'])) {
|
||||
foreach ($a_folders as $idx => $folder) {
|
||||
if ($imap->conn->data['LIST'] && ($opts = $imap->conn->data['LIST'][$folder])
|
||||
if (($opts = $storage->conn->data['LIST'][$folder])
|
||||
&& in_array('\\NonExistent', $opts)
|
||||
) {
|
||||
$imap->conn->unsubscribe($folder);
|
||||
$storage->conn->unsubscribe($folder);
|
||||
unset($a_folders[$idx]);
|
||||
}
|
||||
}
|
||||
|
@ -414,17 +434,17 @@ class kolab_folders extends rcube_plugin
|
|||
}
|
||||
// retrieve list of folders from IMAP server using LSUB
|
||||
else {
|
||||
$a_folders = $imap->conn->listSubscribed($root, $name);
|
||||
$a_folders = $storage->conn->listSubscribed($root, $name);
|
||||
|
||||
// unsubscribe non-existent folders, remove from the list
|
||||
if (is_array($a_folders) && $name == '*') {
|
||||
if (is_array($a_folders) && $name == '*' && !empty($storage->conn->data['LIST'])) {
|
||||
foreach ($a_folders as $idx => $folder) {
|
||||
if ($imap->conn->data['LIST'] && ($opts = $imap->conn->data['LIST'][$folder])
|
||||
&& in_array('\\Noselect', $opts)
|
||||
if (!isset($storage->conn->data['LIST'][$folder])
|
||||
|| in_array('\\Noselect', $storage->conn->data['LIST'][$folder])
|
||||
) {
|
||||
// Some servers returns \Noselect for existing folders
|
||||
if (!$imap->mailbox_exists($folder)) {
|
||||
$imap->conn->unsubscribe($folder);
|
||||
if (!$storage->folder_exists($folder)) {
|
||||
$storage->conn->unsubscribe($folder);
|
||||
unset($a_folders[$idx]);
|
||||
}
|
||||
}
|
||||
|
@ -445,15 +465,17 @@ class kolab_folders extends rcube_plugin
|
|||
*/
|
||||
function get_folder_type_list($mbox, $create_defaults = false)
|
||||
{
|
||||
$storage = $this->rc->get_storage();
|
||||
|
||||
// Use mailboxes. prefix so the cache will be cleared by core
|
||||
// together with other mailboxes-related cache data
|
||||
$cache_key = 'mailboxes.folder-type.'.$mbox;
|
||||
|
||||
// get cached metadata
|
||||
$metadata = $this->rc->imap->get_cache($cache_key);
|
||||
$metadata = $storage->get_cache($cache_key);
|
||||
|
||||
if (!is_array($metadata)) {
|
||||
$metadata = $this->rc->imap->get_metadata($mbox, kolab_folders::CTYPE_KEY);
|
||||
$metadata = $storage->get_metadata($mbox, kolab_folders::CTYPE_KEY);
|
||||
$need_update = true;
|
||||
}
|
||||
|
||||
|
@ -473,7 +495,7 @@ class kolab_folders extends rcube_plugin
|
|||
|
||||
// write mailboxlist to cache
|
||||
if ($need_update) {
|
||||
$this->rc->imap->update_cache($cache_key, $metadata);
|
||||
$storage->update_cache($cache_key, $metadata);
|
||||
}
|
||||
|
||||
return $metadata;
|
||||
|
@ -488,6 +510,7 @@ class kolab_folders extends rcube_plugin
|
|||
*/
|
||||
function get_default_folder($type)
|
||||
{
|
||||
$storage = $this->rc->get_storage();
|
||||
$folderdata = $this->get_folder_type_list('*');
|
||||
|
||||
if (!is_array($folderdata)) {
|
||||
|
@ -495,7 +518,7 @@ class kolab_folders extends rcube_plugin
|
|||
}
|
||||
|
||||
$type .= '.default';
|
||||
$namespace = $this->rc->imap->get_namespace();
|
||||
$namespace = $storage->get_namespace();
|
||||
|
||||
// get all folders of specified type
|
||||
$folderdata = array_intersect($folderdata, array($type));
|
||||
|
@ -552,7 +575,8 @@ class kolab_folders extends rcube_plugin
|
|||
*/
|
||||
private function create_default_folders(&$folderdata, $cache_key = null)
|
||||
{
|
||||
$namespace = $this->rc->imap->get_namespace();
|
||||
$storage = $this->rc->get_storage();
|
||||
$namespace = $storage->get_namespace();
|
||||
$defaults = array();
|
||||
$need_update = false;
|
||||
|
||||
|
@ -573,7 +597,7 @@ class kolab_folders extends rcube_plugin
|
|||
$opt_name = 'kolab_folders_' . $type . '_' . $subtype;
|
||||
if ($folder = $this->rc->config->get($opt_name)) {
|
||||
// convert configuration value to UTF7-IMAP charset
|
||||
$folder = rcube_charset_convert($folder, RCMAIL_CHARSET, 'UTF7-IMAP');
|
||||
$folder = rcube_charset::convert($folder, RCMAIL_CHARSET, 'UTF7-IMAP');
|
||||
// and namespace prefix if needed
|
||||
if ($prefix && strpos($folder, $prefix) === false && $folder != 'INBOX') {
|
||||
$folder = $prefix . $folder;
|
||||
|
@ -621,8 +645,8 @@ class kolab_folders extends rcube_plugin
|
|||
list($type1, $type2) = explode('.', $type);
|
||||
|
||||
// create folder
|
||||
if ($type1 != 'mail' || !$this->rc->imap->mailbox_exists($foldername)) {
|
||||
$this->rc->imap->create_mailbox($foldername, $type1 == 'mail');
|
||||
if ($type1 != 'mail' || !$storage->folder_exists($foldername)) {
|
||||
$storage->create_folder($foldername, $type1 == 'mail');
|
||||
}
|
||||
|
||||
// set type
|
||||
|
@ -637,7 +661,8 @@ class kolab_folders extends rcube_plugin
|
|||
|
||||
// update cache
|
||||
if ($need_update && $cache_key) {
|
||||
$this->rc->imap->update_cache($cache_key, $folderdata);
|
||||
$storage->update_cache($cache_key, $folderdata);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
24
plugins/kolab_folders/localization/de_CH.inc
Normal file
24
plugins/kolab_folders/localization/de_CH.inc
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
$labels = array();
|
||||
|
||||
$labels['folderctype'] = 'Ordnerinhalt';
|
||||
$labels['foldertypemail'] = 'E-Mail';
|
||||
$labels['foldertypeevent'] = 'Kalender'; // Termine?
|
||||
$labels['foldertypejournal'] = 'Journal';
|
||||
$labels['foldertypetask'] = 'Aufgaben';
|
||||
$labels['foldertypenote'] = 'Notizen';
|
||||
$labels['foldertypecontact'] = 'Kontakte';
|
||||
$labels['foldertypeconfiguration'] = 'Konfiguration';
|
||||
|
||||
$labels['default'] = 'Standard';
|
||||
$labels['inbox'] = 'Posteingang';
|
||||
$labels['drafts'] = 'Entwürfe';
|
||||
$labels['sentitems'] = 'Gesendet';
|
||||
$labels['outbox'] = 'Postausgang';
|
||||
$labels['wastebasket'] = 'Gelöscht';
|
||||
$labels['junkemail'] = 'Spam';
|
||||
|
||||
$messages['defaultfolderexists'] = 'Es existiert bereits ein Standardordner für den angegebenen Typ';
|
||||
|
||||
?>
|
24
plugins/kolab_folders/localization/de_DE.inc
Normal file
24
plugins/kolab_folders/localization/de_DE.inc
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
$labels = array();
|
||||
|
||||
$labels['folderctype'] = 'Ordnerinhalt';
|
||||
$labels['foldertypemail'] = 'E-Mail';
|
||||
$labels['foldertypeevent'] = 'Kalender'; // Termine?
|
||||
$labels['foldertypejournal'] = 'Journal';
|
||||
$labels['foldertypetask'] = 'Aufgaben';
|
||||
$labels['foldertypenote'] = 'Notizen';
|
||||
$labels['foldertypecontact'] = 'Kontakte';
|
||||
$labels['foldertypeconfiguration'] = 'Konfiguration';
|
||||
|
||||
$labels['default'] = 'Standard';
|
||||
$labels['inbox'] = 'Posteingang';
|
||||
$labels['drafts'] = 'Entwürfe';
|
||||
$labels['sentitems'] = 'Gesendet';
|
||||
$labels['outbox'] = 'Postausgang';
|
||||
$labels['wastebasket'] = 'Gelöscht';
|
||||
$labels['junkemail'] = 'Spam';
|
||||
|
||||
$messages['defaultfolderexists'] = 'Es existiert bereits ein Standardordner für den angegebenen Typ';
|
||||
|
||||
?>
|
|
@ -4,7 +4,7 @@
|
|||
http://pear.php.net/dtd/package-2.0
|
||||
http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<name>kolab_folders</name>
|
||||
<uri>http://kolabsys.com</uri>
|
||||
<uri>http://git.kolab.org/roundcube-plugins-kolab/</uri>
|
||||
<summary>Type-aware folder management/listing for Kolab</summary>
|
||||
<description>
|
||||
The plugin extends folders handling with features of the Kolab Suite
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* @version 0.2
|
||||
* @author Thomas Bruederli <bruederli@kolabsys.com>
|
||||
*
|
||||
* Copyright (C) 2011, Kolab Systems AG <contact@kolabsys.com>
|
||||
* Copyright (C) 2012, Kolab Systems AG <contact@kolabsys.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
|
@ -64,11 +64,12 @@ class kolab_zpush extends rcube_plugin
|
|||
*/
|
||||
public function init_imap()
|
||||
{
|
||||
$this->rc->imap_connect();
|
||||
$storage = $this->rc->get_storage();
|
||||
|
||||
$this->cache = $this->rc->get_cache('zpush', 'db', 900);
|
||||
$this->cache->expunge();
|
||||
|
||||
if ($meta = $this->rc->imap->get_metadata(self::ROOT_MAILBOX, self::ACTIVESYNC_KEY)) {
|
||||
if ($meta = $storage->get_metadata(self::ROOT_MAILBOX, self::ACTIVESYNC_KEY)) {
|
||||
// clear cache if device config changed
|
||||
if (($oldmeta = $this->cache->read('devicemeta')) && $oldmeta != $meta)
|
||||
$this->cache->remove();
|
||||
|
@ -85,13 +86,13 @@ class kolab_zpush extends rcube_plugin
|
|||
*/
|
||||
public function json_command()
|
||||
{
|
||||
$cmd = get_input_value('cmd', RCUBE_INPUT_GPC);
|
||||
$imei = get_input_value('id', RCUBE_INPUT_GPC);
|
||||
$storage = $this->rc->get_storage();
|
||||
$cmd = get_input_value('cmd', RCUBE_INPUT_GPC);
|
||||
$imei = get_input_value('id', RCUBE_INPUT_GPC);
|
||||
|
||||
switch ($cmd) {
|
||||
case 'load':
|
||||
$result = array();
|
||||
$this->init_imap();
|
||||
$devices = $this->list_devices();
|
||||
if ($device = $devices[$imei]) {
|
||||
$result['id'] = $imei;
|
||||
|
@ -113,7 +114,6 @@ class kolab_zpush extends rcube_plugin
|
|||
break;
|
||||
|
||||
case 'save':
|
||||
$this->init_imap();
|
||||
$devices = $this->list_devices();
|
||||
$syncmode = intval(get_input_value('syncmode', RCUBE_INPUT_POST));
|
||||
$devicealias = get_input_value('devicealias', RCUBE_INPUT_POST, true);
|
||||
|
@ -132,13 +132,13 @@ class kolab_zpush extends rcube_plugin
|
|||
$this->root_meta['DEVICE'][$imei]['LAXPIC'] = $laxpic;
|
||||
$this->root_meta['FOLDER'][$imei]['S'] = intval($subsciptions[self::ROOT_MAILBOX]);
|
||||
|
||||
$err = !$this->rc->imap->set_metadata(self::ROOT_MAILBOX,
|
||||
$err = !$storage->set_metadata(self::ROOT_MAILBOX,
|
||||
array(self::ACTIVESYNC_KEY => $this->serialize_metadata($this->root_meta)));
|
||||
|
||||
// update cached meta data
|
||||
if (!$err) {
|
||||
$this->cache->remove('devicemeta');
|
||||
$this->cache->write('devicemeta', $this->rc->imap->get_metadata(self::ROOT_MAILBOX, self::ACTIVESYNC_KEY));
|
||||
$this->cache->write('devicemeta', $storage->get_metadata(self::ROOT_MAILBOX, self::ACTIVESYNC_KEY));
|
||||
}
|
||||
}
|
||||
// iterate over folders list and update metadata if necessary
|
||||
|
@ -153,12 +153,12 @@ class kolab_zpush extends rcube_plugin
|
|||
unset($meta['TYPE']);
|
||||
|
||||
// read metadata first
|
||||
$folderdata = $this->rc->imap->get_metadata($folder, array(self::ACTIVESYNC_KEY));
|
||||
$folderdata = $storage->get_metadata($folder, array(self::ACTIVESYNC_KEY));
|
||||
if ($asyncdata = $folderdata[$folder][self::ACTIVESYNC_KEY])
|
||||
$metadata = $this->unserialize_metadata($asyncdata);
|
||||
$metadata['FOLDER'] = $meta;
|
||||
|
||||
$err |= !$this->rc->imap->set_metadata($folder, array(self::ACTIVESYNC_KEY => $this->serialize_metadata($metadata)));
|
||||
$err |= !$storage->set_metadata($folder, array(self::ACTIVESYNC_KEY => $this->serialize_metadata($metadata)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,9 +184,9 @@ class kolab_zpush extends rcube_plugin
|
|||
unset($this->root_meta['DEVICE'][$imei], $this->root_meta['FOLDER'][$imei]);
|
||||
|
||||
// update annotation and cached meta data
|
||||
if ($success = $this->rc->imap->set_metadata(self::ROOT_MAILBOX, array(self::ACTIVESYNC_KEY => $this->serialize_metadata($this->root_meta)))) {
|
||||
if ($success = $storage->set_metadata(self::ROOT_MAILBOX, array(self::ACTIVESYNC_KEY => $this->serialize_metadata($this->root_meta)))) {
|
||||
$this->cache->remove('devicemeta');
|
||||
$this->cache->write('devicemeta', $this->rc->imap->get_metadata(self::ROOT_MAILBOX, self::ACTIVESYNC_KEY));
|
||||
$this->cache->write('devicemeta', $storage->get_metadata(self::ROOT_MAILBOX, self::ACTIVESYNC_KEY));
|
||||
|
||||
// remove device annotation in every folder
|
||||
foreach ($this->folders_meta() as $folder => $meta) {
|
||||
|
@ -199,12 +199,12 @@ class kolab_zpush extends rcube_plugin
|
|||
unset($meta[$imei], $meta['TYPE']);
|
||||
|
||||
// read metadata first and update FOLDER property
|
||||
$folderdata = $this->rc->imap->get_metadata($folder, array(self::ACTIVESYNC_KEY));
|
||||
$folderdata = $storage->get_metadata($folder, array(self::ACTIVESYNC_KEY));
|
||||
if ($asyncdata = $folderdata[$folder][self::ACTIVESYNC_KEY])
|
||||
$metadata = $this->unserialize_metadata($asyncdata);
|
||||
$metadata['FOLDER'] = $meta;
|
||||
|
||||
if ($this->rc->imap->set_metadata($folder, array(self::ACTIVESYNC_KEY => $this->serialize_metadata($metadata)))) {
|
||||
if ($storage->set_metadata($folder, array(self::ACTIVESYNC_KEY => $this->serialize_metadata($metadata)))) {
|
||||
$this->folders_meta[$folder] = $metadata;
|
||||
$this->folders_meta[$folder]['TYPE'] = $type;
|
||||
}
|
||||
|
@ -236,12 +236,12 @@ class kolab_zpush extends rcube_plugin
|
|||
*/
|
||||
public function config_view()
|
||||
{
|
||||
require_once($this->home . '/kolab_zpush_ui.php');
|
||||
require_once $this->home . '/kolab_zpush_ui.php';
|
||||
|
||||
$this->init_imap();
|
||||
$storage = $this->rc->get_storage();
|
||||
|
||||
// checks if IMAP server supports any of METADATA, ANNOTATEMORE, ANNOTATEMORE2
|
||||
if (!($this->rc->imap->get_capability('METADATA') || $this->rc->imap->get_capability('ANNOTATEMORE') || $this->rc->imap->get_capability('ANNOTATEMORE2'))) {
|
||||
if (!($storage->get_capability('METADATA') || $storage->get_capability('ANNOTATEMORE') || $storage->get_capability('ANNOTATEMORE2'))) {
|
||||
$this->rc->output->show_message($this->gettext('notsupported'), 'error');
|
||||
}
|
||||
|
||||
|
@ -286,9 +286,11 @@ class kolab_zpush extends rcube_plugin
|
|||
}
|
||||
// fetch folder data from server
|
||||
else {
|
||||
$this->folders = $this->rc->imap->list_unsubscribed();
|
||||
$storage = $this->rc->get_storage();
|
||||
$this->folders = $storage->list_folders();
|
||||
|
||||
foreach ($this->folders as $folder) {
|
||||
$folderdata = $this->rc->imap->get_metadata($folder, array(self::ACTIVESYNC_KEY, self::CTYPE_KEY));
|
||||
$folderdata = $storage->get_metadata($folder, array(self::ACTIVESYNC_KEY, self::CTYPE_KEY));
|
||||
$foldertype = explode('.', $folderdata[$folder][self::CTYPE_KEY]);
|
||||
|
||||
if ($asyncdata = $folderdata[$folder][self::ACTIVESYNC_KEY]) {
|
||||
|
|
|
@ -6,21 +6,21 @@ $labels['devices'] = 'Geräte';
|
|||
$labels['devicealias'] = 'Gerätename';
|
||||
$labels['syncmode'] = 'Modus';
|
||||
$labels['modeauto'] = 'Automatisch';
|
||||
$labels['modeflat'] = 'Forciere flache Struktur';
|
||||
$labels['modefolder'] = 'Forciere Ordnerstruktur';
|
||||
$labels['modeflat'] = 'Flache Struktur erzwingen';
|
||||
$labels['modefolder'] = 'Ordnerstruktur erzwingen';
|
||||
$labels['synchronize'] = 'Synchronisieren';
|
||||
$labels['withalarms'] = 'Mit Erinnerungen';
|
||||
$labels['syncsettings'] = 'Synchronisationseinstellungen';
|
||||
$labels['deviceconfig'] = 'Gerätekonfiguration';
|
||||
$labels['folderstosync'] = 'Order zum Synchronisieren';
|
||||
$labels['mail'] = 'E-Mail';
|
||||
$labels['contact'] = 'Adressbücher';
|
||||
$labels['event'] = 'Kalendar';
|
||||
$labels['contact'] = 'Kontakte';
|
||||
$labels['event'] = 'Kalender';
|
||||
$labels['task'] = 'Aufgaben';
|
||||
$labels['note'] = 'Notizen';
|
||||
$labels['deletedevice'] = 'Gerät löschen';
|
||||
$labels['imageformat'] = 'Bildformat';
|
||||
$labels['laxpiclabel'] = 'Erlaube PNG- und GIF-Bilder';
|
||||
$labels['laxpiclabel'] = 'PNG- und GIF-Bilder erlauben';
|
||||
$labels['introtext'] = 'Wählen Sie das zu konfigurierende Gerät aus';
|
||||
$labels['nodevices'] = 'Es sind noch keine Geräte registriert.<br/><br/>Um ein neues Gerät anzumelden, verbinden Sie dieses zuerst mit dem Server. Eine Anleitung dazu finden Sie im <a href="http://wiki.kolab.org/Z_push#Clients">Wiki</a>. Anschliessend laden Sie diese Seite neu und das Gerät wird hier aufgelistet.';
|
||||
$labels['savingdata'] = 'Daten werden gespeichert...';
|
||||
|
@ -29,4 +29,4 @@ $labels['notsupported'] = 'Ihr Server unterstützt keine Activesync-Konfiguratio
|
|||
$labels['devicedeleteconfirm'] = 'Wollen Sie wirklich alle Einstellungen für dieses Gerät löschen?';
|
||||
$labels['successfullydeleted'] = 'Die Geräteinstellungen wurden erfolgreich gelöscht';
|
||||
|
||||
?>
|
||||
?>
|
||||
|
|
32
plugins/kolab_zpush/localization/de_DE.inc
Normal file
32
plugins/kolab_zpush/localization/de_DE.inc
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
$labels = array();
|
||||
$labels['tabtitle'] = 'Activesync';
|
||||
$labels['devices'] = 'Geräte';
|
||||
$labels['devicealias'] = 'Gerätename';
|
||||
$labels['syncmode'] = 'Modus';
|
||||
$labels['modeauto'] = 'Automatisch';
|
||||
$labels['modeflat'] = 'Flache Struktur erzwingen';
|
||||
$labels['modefolder'] = 'Ordnerstruktur erzwingen';
|
||||
$labels['synchronize'] = 'Synchronisieren';
|
||||
$labels['withalarms'] = 'Mit Erinnerungen';
|
||||
$labels['syncsettings'] = 'Synchronisationseinstellungen';
|
||||
$labels['deviceconfig'] = 'Gerätekonfiguration';
|
||||
$labels['folderstosync'] = 'Order zum Synchronisieren';
|
||||
$labels['mail'] = 'E-Mail';
|
||||
$labels['contact'] = 'Kontakte';
|
||||
$labels['event'] = 'Kalender';
|
||||
$labels['task'] = 'Aufgaben';
|
||||
$labels['note'] = 'Notizen';
|
||||
$labels['deletedevice'] = 'Gerät löschen';
|
||||
$labels['imageformat'] = 'Bildformat';
|
||||
$labels['laxpiclabel'] = 'PNG- und GIF-Bilder erlauben';
|
||||
$labels['introtext'] = 'Wählen Sie das zu konfigurierende Gerät aus';
|
||||
$labels['nodevices'] = 'Es sind noch keine Geräte registriert.<br/><br/>Um ein neues Gerät anzumelden, verbinden Sie dieses zuerst mit dem Server. Eine Anleitung dazu finden Sie im <a href="http://wiki.kolab.org/Z_push#Clients">Wiki</a>. Anschliessend laden Sie diese Seite neu und das Gerät wird hier aufgelistet.';
|
||||
$labels['savingdata'] = 'Daten werden gespeichert...';
|
||||
$labels['savingerror'] = 'Fehler beim Speichern';
|
||||
$labels['notsupported'] = 'Ihr Server unterstützt keine Activesync-Konfiguration';
|
||||
$labels['devicedeleteconfirm'] = 'Wollen Sie wirklich alle Einstellungen für dieses Gerät löschen?';
|
||||
$labels['successfullydeleted'] = 'Die Geräteinstellungen wurden erfolgreich gelöscht';
|
||||
|
||||
?>
|
|
@ -18,6 +18,7 @@ $labels['contact'] = 'Address Books';
|
|||
$labels['event'] = 'Calendars';
|
||||
$labels['task'] = 'Tasks';
|
||||
$labels['note'] = 'Notes';
|
||||
$labels['configuration'] = 'Configuration';
|
||||
$labels['deletedevice'] = 'Delete device';
|
||||
$labels['imageformat'] = 'Image format';
|
||||
$labels['laxpiclabel'] = 'Allow PNG and GIF images';
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
http://pear.php.net/dtd/package-2.0
|
||||
http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<name>kolab_zpush</name>
|
||||
<uri>http://kolabsys.com</uri>
|
||||
<uri>http://git.kolab.org/roundcube-plugins-kolab/</uri>
|
||||
<summary>Z-Push configuration utility for Kolab accounts</summary>
|
||||
<description></description>
|
||||
<lead>
|
||||
|
@ -16,7 +16,7 @@
|
|||
<date>2011-11-14</date>
|
||||
<time>12:12:00</time>
|
||||
<version>
|
||||
<release>0.2</release>
|
||||
<release>0.3</release>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
|
@ -38,6 +38,13 @@
|
|||
<file name="skins/default/foldertypes.png" role="data"></file>
|
||||
<file name="skins/default/pointer-left.gif" role="data"></file>
|
||||
<file name="skins/default/synchronize.png" role="data"></file>
|
||||
<file name="skins/larry/templates/config.html" role="data"></file>
|
||||
<file name="skins/larry/config.css" role="data"></file>
|
||||
<file name="skins/larry/alarm-clock.png" role="data"></file>
|
||||
<file name="skins/larry/deviceactions.png" role="data"></file>
|
||||
<file name="skins/larry/foldertypes.png" role="data"></file>
|
||||
<file name="skins/larry/pointer-left.png" role="data"></file>
|
||||
<file name="skins/larry/synchronize.png" role="data"></file>
|
||||
<file name="README" role="data"></file>
|
||||
<file name="LICENSE" role="data"></file>
|
||||
</dir>
|
||||
|
|
BIN
plugins/kolab_zpush/skins/larry/alarm-clock.png
Executable file
BIN
plugins/kolab_zpush/skins/larry/alarm-clock.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 841 B |
135
plugins/kolab_zpush/skins/larry/config.css
Normal file
135
plugins/kolab_zpush/skins/larry/config.css
Normal file
|
@ -0,0 +1,135 @@
|
|||
/* Stylesheets for the Kolab Z-Push configuration UI */
|
||||
|
||||
#configform {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
#sectionslist {
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
#prefs-box {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 232px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#devices-table {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
#devices-table td {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#devices-table td span.devicetype {
|
||||
padding-left: 1em;
|
||||
font-style: italic;
|
||||
color: #69939e;
|
||||
}
|
||||
|
||||
div.subscriptionblock {
|
||||
float: left;
|
||||
margin: 0 3em 2em 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.subscriptionblock h3 {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
margin: 0 0 0.6em 0;
|
||||
padding: 2px 4px 2px 30px;
|
||||
background: url(foldertypes.png) 4px 2px no-repeat;
|
||||
}
|
||||
|
||||
div.subscriptionblock h3.contact {
|
||||
background-position: 4px -18px;
|
||||
}
|
||||
|
||||
div.subscriptionblock h3.event {
|
||||
background-position: 4px -38px;
|
||||
}
|
||||
|
||||
div.subscriptionblock h3.task {
|
||||
background-position: 4px -58x;
|
||||
}
|
||||
|
||||
div.subscriptionblock h3.note {
|
||||
background-position: 4px -78px;
|
||||
}
|
||||
|
||||
#foldersubscriptions thead td {
|
||||
color: #69939e;
|
||||
font-weight: bold;
|
||||
padding: 3px 5px;
|
||||
min-width: 2em;
|
||||
background: #d6eaf3;
|
||||
border-bottom: 2px solid #fff;
|
||||
}
|
||||
|
||||
#foldersubscriptions tbody td {
|
||||
background: #eee;
|
||||
padding: 2px 5px;
|
||||
border-bottom: 2px solid #fff;
|
||||
}
|
||||
|
||||
#foldersubscriptions td label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#foldersubscriptions td.mailbox {
|
||||
padding-right: 3em;
|
||||
padding-left: 2px;
|
||||
min-width: 12em;
|
||||
}
|
||||
|
||||
#foldersubscriptions td.virtual {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
#foldersubscriptions {
|
||||
overflow: auto;
|
||||
max-height: 400px;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
#introtext {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 5px;
|
||||
padding-left: 10px;
|
||||
max-width: 40em;
|
||||
}
|
||||
|
||||
#introtext .pointer-left {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 12px;
|
||||
height: 80%;
|
||||
background: url(pointer-left.png) right center no-repeat;
|
||||
}
|
||||
|
||||
#introtext .inner {
|
||||
color: #eee;
|
||||
padding: 12px;
|
||||
border: 1px solid #333;
|
||||
border-radius: 4px;
|
||||
text-shadow: 0px 1px 1px #333;
|
||||
background: #5b5b5b;
|
||||
background: -moz-linear-gradient(top, #5b5b5b 0%, #3a3a3a 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#5b5b5b), color-stop(100%,#3a3a3a));
|
||||
background: -o-linear-gradient(top, #5b5b5b 0%, #3a3a3a 100%);
|
||||
background: -ms-linear-gradient(top, #5b5b5b 0%, #3a3a3a 100%);
|
||||
background: linear-gradient(top, #5b5b5b 0%, #3a3a3a 100%);
|
||||
-webkit-box-shadow: inset 0px 0px 0px 1px #7e7e7e, 0 2px 6px 0 #333;
|
||||
-moz-box-shadow: inset 0px 0px 0px 1px #7e7e7e, 0 2px 6px 0 #333;
|
||||
box-shadow: inset 0px 0px 0px 1px #7e7e7e, 0 2px 6px 0 #333;
|
||||
}
|
||||
|
||||
#introtext a {
|
||||
color: #b0ccd7;
|
||||
}
|
BIN
plugins/kolab_zpush/skins/larry/foldertypes.png
Normal file
BIN
plugins/kolab_zpush/skins/larry/foldertypes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
BIN
plugins/kolab_zpush/skins/larry/pointer-left.png
Normal file
BIN
plugins/kolab_zpush/skins/larry/pointer-left.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
BIN
plugins/kolab_zpush/skins/larry/synchronize.png
Executable file
BIN
plugins/kolab_zpush/skins/larry/synchronize.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 836 B |
71
plugins/kolab_zpush/skins/larry/templates/config.html
Normal file
71
plugins/kolab_zpush/skins/larry/templates/config.html
Normal file
|
@ -0,0 +1,71 @@
|
|||
<roundcube:object name="doctype" value="html5" />
|
||||
<html>
|
||||
<head>
|
||||
<title><roundcube:object name="pagetitle" /></title>
|
||||
<roundcube:include file="/includes/links.html" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<roundcube:include file="/includes/header.html" />
|
||||
|
||||
<div id="mainscreen" class="offset">
|
||||
|
||||
<roundcube:include file="/includes/settingstabs.html" />
|
||||
|
||||
<div id="settings-right">
|
||||
|
||||
<div id="sectionslist" class="uibox listbox">
|
||||
<h2 id="directorylist-title" class="boxtitle"><roundcube:label name="kolab_zpush.devices" /></h2>
|
||||
<div class="boxlistcontent">
|
||||
<roundcube:object name="plugin.devicelist" id="devices-table" class="listing" cellspacing="0" />
|
||||
</div>
|
||||
<div class="boxfooter">
|
||||
<roundcube:button type="link" command="plugin.delete-device" title="kolab_zpush.deletedevice" class="listbutton delete disabled" classAct="listbutton delete" innerClass="inner" content="x" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="prefs-box" class="uibox contentbox">
|
||||
<h1 class="boxtitle" style="display:none"><roundcube:label name="kolab_zpush.syncsettings"></h1>
|
||||
<form action="#" method="post" id="configform" class="boxcontent tabbed" style="display:none">
|
||||
<fieldset>
|
||||
<legend><roundcube:label name="kolab_zpush.folderstosync" /></legend>
|
||||
<roundcube:object name="plugin.foldersubscriptions" form="configform" id="foldersubscriptions" syncicon="synchronize.png" alarmicon="alarm-clock.png" />
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend><roundcube:label name="kolab_zpush.deviceconfig" /></legend>
|
||||
<roundcube:object name="plugin.deviceconfigform" form="configform" class="propform" />
|
||||
</fieldset>
|
||||
|
||||
<p class="formbuttons">
|
||||
<roundcube:button type="input" class="button mainaction" command="plugin.save-config" label="save" />
|
||||
<roundcube:button type="input" class="button" command="plugin.delete-device" label="kolab_zpush.deletedevice" />
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<div id="introtext">
|
||||
<div class="inner">
|
||||
<roundcube:if condition="env:devicecount" />
|
||||
<roundcube:label name="kolab_zpush.introtext" />
|
||||
<roundcube:else />
|
||||
<roundcube:label name="kolab_zpush.nodevices" html="true" />
|
||||
<roundcube:endif />
|
||||
</div>
|
||||
<div class="pointer-left"></div>
|
||||
</div>
|
||||
|
||||
<roundcube:object name="message" id="message" class="statusbar" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<roundcube:include file="/includes/footer.html" />
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var viewsplit = new rcube_splitter({ id:'devicelistsplitter', p1:'#sectionslist', p2:'#prefs-box', orientation:'v', relative:true, start:226, min:150, size:12 });
|
||||
rcmail.add_onload('viewsplit.init()');
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
661
plugins/owncloud/LICENSE
Normal file
661
plugins/owncloud/LICENSE
Normal file
|
@ -0,0 +1,661 @@
|
|||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
4
plugins/owncloud/config.inc.php.dist
Normal file
4
plugins/owncloud/config.inc.php.dist
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
// ownCloud URL
|
||||
$rcmail_config['owncloud_url'] = 'https://owncloud.webmail.tld';
|
6
plugins/owncloud/localization/en_US.inc
Normal file
6
plugins/owncloud/localization/en_US.inc
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
$labels = array();
|
||||
$labels['owncloud'] = 'Files';
|
||||
|
||||
?>
|
6
plugins/owncloud/localization/pl_PL.inc
Normal file
6
plugins/owncloud/localization/pl_PL.inc
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
$labels = array();
|
||||
$labels['owncloud'] = 'Pliki';
|
||||
|
||||
?>
|
84
plugins/owncloud/owncloud.php
Normal file
84
plugins/owncloud/owncloud.php
Normal file
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* OwnCloud Plugin
|
||||
*
|
||||
* @author Aleksander 'A.L.E.C' Machniak <machniak@kolabsys.com>
|
||||
* @licence GNU AGPL
|
||||
*
|
||||
* Configuration (see config.inc.php.dist)
|
||||
*
|
||||
*/
|
||||
|
||||
class owncloud extends rcube_plugin
|
||||
{
|
||||
// all task excluding 'login' and 'logout'
|
||||
public $task = '?(?!login|logout).*';
|
||||
// we've got no ajax handlers
|
||||
public $noajax = true;
|
||||
// skip frames
|
||||
public $noframe = true;
|
||||
|
||||
function init()
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
// requires kolab_auth plugin
|
||||
if (empty($_SESSION['kolab_uid'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->add_texts('localization/', false);
|
||||
|
||||
// register task
|
||||
$this->register_task('owncloud');
|
||||
|
||||
// register actions
|
||||
$this->register_action('index', array($this, 'action'));
|
||||
$this->register_action('redirect', array($this, 'redirect'));
|
||||
|
||||
// add taskbar button
|
||||
$this->add_button(array(
|
||||
'command' => 'owncloud',
|
||||
'class' => 'button-owncloud',
|
||||
'classsel' => 'button-owncloud button-selected',
|
||||
'innerclass' => 'button-inner',
|
||||
'label' => 'owncloud.owncloud',
|
||||
), 'taskbar');
|
||||
|
||||
$skin = $rcmail->config->get('skin');
|
||||
if (!file_exists($this->home."/skins/$skin/owncloud.css")) {
|
||||
$skin = 'default';
|
||||
}
|
||||
|
||||
// add style for taskbar button (must be here) and Help UI
|
||||
$this->include_stylesheet("skins/$skin/owncloud.css");
|
||||
}
|
||||
|
||||
function action()
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
$rcmail->output->add_handlers(array('owncloudframe' => array($this, 'frame')));
|
||||
$rcmail->output->set_pagetitle($this->gettext('owncloud'));
|
||||
$rcmail->output->send('owncloud.owncloud');
|
||||
}
|
||||
|
||||
function frame()
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
$this->load_config();
|
||||
|
||||
$src = $rcmail->config->get('owncloud_url');
|
||||
$user = $_SESSION['kolab_uid']; // requires kolab_auth plugin
|
||||
$pass = $rcmail->decrypt($_SESSION['password']);
|
||||
|
||||
$src = preg_replace('/^(https?:\/\/)/',
|
||||
'\\1' . urlencode($user) . ':' . urlencode($pass) . '@', $src);
|
||||
|
||||
return '<iframe id="owncloudframe" width="100%" height="100%" frameborder="0"'
|
||||
.' src="' . $src. '"></iframe>';
|
||||
}
|
||||
|
||||
}
|
BIN
plugins/owncloud/skins/default/cloud.png
Normal file
BIN
plugins/owncloud/skins/default/cloud.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
12
plugins/owncloud/skins/default/owncloud.css
Normal file
12
plugins/owncloud/skins/default/owncloud.css
Normal file
|
@ -0,0 +1,12 @@
|
|||
/***** ownCloud plugin styles *****/
|
||||
|
||||
#taskbar a.button-owncloud
|
||||
{
|
||||
background-image: url(cloud.png);
|
||||
}
|
||||
|
||||
.owncloud-box
|
||||
{
|
||||
overflow: auto;
|
||||
background-color: #F2F2F2;
|
||||
}
|
19
plugins/owncloud/skins/default/templates/owncloud.html
Normal file
19
plugins/owncloud/skins/default/templates/owncloud.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!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="/this/owncloud.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/settings.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<roundcube:include file="/includes/taskbar.html" />
|
||||
<roundcube:include file="/includes/header.html" />
|
||||
|
||||
<div id="mainscreen" class="box owncloud-box">
|
||||
<roundcube:object name="owncloudframe" />
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
plugins/owncloud/skins/larry/cloud.png
Normal file
BIN
plugins/owncloud/skins/larry/cloud.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
14
plugins/owncloud/skins/larry/owncloud.css
Normal file
14
plugins/owncloud/skins/larry/owncloud.css
Normal file
|
@ -0,0 +1,14 @@
|
|||
/***** ownCloud plugin styles *****/
|
||||
|
||||
#taskbar a.button-owncloud span.button-inner
|
||||
{
|
||||
background: url(cloud.png) 5px 5px no-repeat;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
#taskbar a.button-owncloud:hover span.button-inner,
|
||||
#taskbar a.button-owncloud.button-selected span.button-inner
|
||||
{
|
||||
background: url(cloud.png) 5px -16px no-repeat;
|
||||
height: 14px;
|
||||
}
|
20
plugins/owncloud/skins/larry/templates/owncloud.html
Normal file
20
plugins/owncloud/skins/larry/templates/owncloud.html
Normal file
|
@ -0,0 +1,20 @@
|
|||
<roundcube:object name="doctype" value="html5" />
|
||||
<html>
|
||||
<head>
|
||||
<title><roundcube:object name="pagetitle" /></title>
|
||||
<roundcube:include file="/includes/links.html" />
|
||||
<link rel="stylesheet" type="text/css" href="/this/owncloud.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/settings.css" />
|
||||
</head>
|
||||
<body class="noscroll">
|
||||
|
||||
<roundcube:include file="/includes/header.html" />
|
||||
|
||||
<div id="mainscreen" class="offset uibox" style="overflow: hidden">
|
||||
<roundcube:object name="owncloudframe" />
|
||||
</div>
|
||||
|
||||
<roundcube:include file="/includes/footer.html" />
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Reference in a new issue