Projects
Kolab:Winterfell
roundcubemail-plugins-kolab
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 46
View file
roundcubemail-plugins-kolab.spec
Changed
@@ -11,10 +11,16 @@ %global httpd_name apache2 %global httpd_user wwwrun %else +%if 0%{?plesk} +%global httpd_group roundcube_sysgroup +%global httpd_name httpd +%global httpd_user roundcube_sysuser +%else %global httpd_group apache %global httpd_name httpd %global httpd_user apache %endif +%endif %global roundcube_version 1.2 %global datadir %{_datadir}/roundcubemail @@ -24,7 +30,7 @@ Name: roundcubemail-plugins-kolab Version: 3.3 -Release: 0.20161115.git%{?dist} +Release: 0.20170125.git%{?dist} Summary: Kolab Groupware plugins for Roundcube Webmail Group: Applications/Internet @@ -35,6 +41,8 @@ Source0: roundcubemail-plugins-kolab-3.3.tar.gz Source1: comm.py +Patch0001: roundcubemail-plugins-kolab-3.3-kolab-files-manticore-api.patch + BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) BuildArch: noarch @@ -828,6 +836,8 @@ pushd %{name}-%{version} +%patch0001 -p1 + find -type d -name "helpdocs" -exec rm -rvf {} \; 2>/dev/null || : rm -rf plugins/kolab_zpush
View file
roundcubemail-plugins-kolab-3.3-kolab-files-manticore-api.patch
Added
@@ -0,0 +1,15 @@ +diff --git a/plugins/kolab_files/kolab_files.js b/plugins/kolab_files/kolab_files.js +index 8081f43..c16007e 100644 +--- a/plugins/kolab_files/kolab_files.js ++++ b/plugins/kolab_files/kolab_files.js +@@ -224,8 +224,10 @@ function kolab_files_init() + + if (window.document_editor_api) + document_editor = new document_editor_api(editor_config); ++/* Patch away whatever a undefined manticore_api thing means + else + document_editor = new manticore_api(editor_config); ++*/ + }; + + // returns API authorization token
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/calendar/calendar.php
Changed
@@ -1975,8 +1975,8 @@ private function write_preprocess(&$event, $action) { // convert dates into DateTime objects in user's current timezone - $event['start'] = new DateTime($event['start'], $this->timezone); - $event['end'] = new DateTime($event['end'], $this->timezone); + $event['start'] = new DateTime($event['start'], $this->timezone); + $event['end'] = new DateTime($event['end'], $this->timezone); $event['allday'] = (bool)$event['allday']; // start/end is all we need for 'move' action (#1480) @@ -2026,7 +2026,7 @@ foreach ((array)$event['attendees'] as $i => $attendee) { if ($attendee['role'] == 'ORGANIZER') $organizer = $i; - if ($attendee['email'] == in_array(strtolower($attendee['email']), $emails)) + if ($attendee['email'] && in_array(strtolower($attendee['email']), $emails)) $owner = $i; if (!isset($attendee['rsvp'])) $event['attendees'][$i]['rsvp'] = true;
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/calendar/calendar_ui.js
Changed
@@ -734,6 +734,10 @@ var invite = $('#edit-attendees-invite').get(0); var comment = $('#edit-attendees-comment'); + // make sure any calendar is selected + if (!calendars.val()) + calendars.val($('option:first', calendars).attr('value')); + invite.checked = settings.itip_notify & 1 > 0; notify.checked = has_attendees(event) && invite.checked; @@ -1942,9 +1946,9 @@ + (!data.noreply && settings.itip_notify & 1 ? 'checked="checked" ' : '') + '/>'; if (data['delegated-to']) - tooltip = rcmail.gettext('delegatedto', 'calendar') + data['delegated-to']; + tooltip = rcmail.gettext('libcalendaring.delegatedto') + ' ' + data['delegated-to']; else if (data['delegated-from']) - tooltip = rcmail.gettext('delegatedfrom', 'calendar') + data['delegated-from']; + tooltip = rcmail.gettext('libcalendaring.delegatedfrom') + ' ' + data['delegated-from']; else if (status) tooltip = status_label; @@ -3542,6 +3546,8 @@ rcmail.triggerEvent('selectfolder', { folder:id, prefix:'rcmlical' }); this.selected_calendar = id; + + rcmail.update_state({source: id}); }; // register the given calendar to the current view @@ -3748,7 +3754,9 @@ }); // select default calendar - if (settings.default_calendar && this.calendars[settings.default_calendar] && this.calendars[settings.default_calendar].editable) + if (rcmail.env.source && this.calendars[rcmail.env.source]) + this.selected_calendar = rcmail.env.source; + else if (settings.default_calendar && this.calendars[settings.default_calendar] && this.calendars[settings.default_calendar].editable) this.selected_calendar = settings.default_calendar; if (this.selected_calendar)
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/calendar/drivers/database/database_driver.php
Changed
@@ -391,7 +391,7 @@ if ($event['id'] == $master['id']) { $event += $old; $event['recurrence_id'] = $master['id']; - $event['_instance'] = libcalendaring::recurrence_instance_identifier($old); + $event['_instance'] = libcalendaring::recurrence_instance_identifier($old, $master['allday']); $event['isexception'] = 1; $event_id = $this->_insert_event($event); return $event_id;
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/calendar/drivers/kolab/kolab_calendar.php
Changed
@@ -207,7 +207,7 @@ if ($master) { // check for match in top-level exceptions (aka loose single occurrences) if ($master['_formatobj'] && ($instance = $master['_formatobj']->get_instance($instance_id))) { - $this->events[$id] = $this->_to_driver_event($instance); + $this->events[$id] = $this->_to_driver_event($instance, false, true, $master); } // check for match on the first instance already else if ($master['_instance'] && $master['_instance'] == $instance_id) { @@ -354,7 +354,7 @@ // add top-level exceptions (aka loose single occurrences) else if (is_array($record['exceptions'])) { foreach ($record['exceptions'] as $ex) { - $component = $this->_to_driver_event($ex, false, false); + $component = $this->_to_driver_event($ex, false, false, $record); if ($component['start'] <= $end && $component['end'] >= $start) { $events[] = $component; } @@ -629,9 +629,9 @@ if (is_array($event['recurrence']['EXCEPTIONS'])) { foreach ($event['recurrence']['EXCEPTIONS'] as $exception) { if (!$exception['_instance']) - $exception['_instance'] = libcalendaring::recurrence_instance_identifier($exception); + $exception['_instance'] = libcalendaring::recurrence_instance_identifier($exception, $event['allday']); - $rec_event = $this->_to_driver_event($exception, false, false); + $rec_event = $this->_to_driver_event($exception, false, false, $event); $rec_event['id'] = $event['uid'] . '-' . $exception['_instance']; $rec_event['isexception'] = 1; @@ -692,7 +692,7 @@ // add to output if in range if (($event_start <= $end && $event_end >= $start) || ($event_id && $rec_id == $event_id)) { - $rec_event = $this->_to_driver_event($next_event, false, false); + $rec_event = $this->_to_driver_event($next_event, false, false, $event); $rec_event['_instance'] = $instance_id; $rec_event['_count'] = $i + 1; @@ -724,7 +724,7 @@ /** * Convert from Kolab_Format to internal representation */ - private function _to_driver_event($record, $noinst = false, $links = true) + private function _to_driver_event($record, $noinst = false, $links = true, $master_event = null) { $record['calendar'] = $this->id; @@ -738,7 +738,7 @@ } // add instance identifier to first occurrence (master event) - $recurrence_id_format = libcalendaring::recurrence_id_format($record); + $recurrence_id_format = libcalendaring::recurrence_id_format($master_event ? $master_event : $record); if (!$noinst && $record['recurrence'] && !$record['recurrence_id'] && !$record['_instance']) { $record['_instance'] = $record['start']->format($recurrence_id_format); } @@ -763,11 +763,25 @@ private function _from_driver_event($event, $old = array()) { // set current user as ORGANIZER - $identity = $this->cal->rc->user->list_emails(true); - if (empty($event['attendees']) && $identity['email']) - $event['attendees'] = array(array('role' => 'ORGANIZER', 'name' => $identity['name'], 'email' => $identity['email'])); + if ($identity = $this->cal->rc->user->list_emails(true)) { + $event['attendees'] = (array) $event['attendees']; + $found = false; + + // there can be only resources on attendees list (T1484) + // let's check the existence of an organizer + foreach ($event['attendees'] as $attendee) { + if ($attendee['role'] == 'ORGANIZER') { + $found = true; + break; + } + } - $event['_owner'] = $identity['email']; + if (!$found) { + $event['attendees'][] = array('role' => 'ORGANIZER', 'name' => $identity['name'], 'email' => $identity['email']); + } + + $event['_owner'] = $identity['email']; + } // remove EXDATE values if RDATE is given if (!empty($event['recurrence']['RDATE'])) { @@ -792,7 +806,6 @@ }); } - // remove some internal properties which should not be saved unset($event['_savemode'], $event['_fromcalendar'], $event['_identity'], $event['_folder_id'], $event['recurrence_id'], $event['attachments'], $event['deleted_attachments'], $event['className']);
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/calendar/drivers/kolab/kolab_driver.php
Changed
@@ -1141,21 +1141,21 @@ // use start date from master but try to be smart on time or duration changes $old_start_date = $old['start']->format('Y-m-d'); $old_start_time = $old['allday'] ? '' : $old['start']->format('H:i'); - $old_duration = $old['end']->format('U') - $old['start']->format('U'); - + $old_duration = $old['allday'] ? 0 : $old['end']->format('U') - $old['start']->format('U'); + $new_start_date = $event['start']->format('Y-m-d'); $new_start_time = $event['allday'] ? '' : $event['start']->format('H:i'); - $new_duration = $event['end']->format('U') - $event['start']->format('U'); - + $new_duration = $event['allday'] ? 0 : $event['end']->format('U') - $event['start']->format('U'); + $diff = $old_start_date != $new_start_date || $old_start_time != $new_start_time || $old_duration != $new_duration; $date_shift = $old['start']->diff($event['start']); - + // shifted or resized if ($diff && ($old_start_date == $new_start_date || $old_duration == $new_duration)) { $event['start'] = $master['start']->add($date_shift); $event['end'] = clone $event['start']; $event['end']->add(new DateInterval('PT'.$new_duration.'S')); - + // remove fixed weekday, will be re-set to the new weekday in kolab_calendar::update_event() if ($old_start_date != $new_start_date) { if (strlen($event['recurrence']['BYDAY']) == 2) @@ -1173,6 +1173,7 @@ // when saving an instance in 'all' mode, copy recurrence exceptions over if ($old['recurrence_id']) { $event['recurrence']['EXCEPTIONS'] = $master['recurrence']['EXCEPTIONS']; + $event['recurrence']['EXDATE'] = $master['recurrence']['EXDATE']; } else if ($master['_instance']) { $event['_instance'] = $master['_instance']; @@ -1225,7 +1226,7 @@ if ($success && $this->freebusy_trigger) $this->rc->output->command('plugin.ping_url', array('action' => 'calendar/push-freebusy', 'source' => $storage->id)); - + return $success; } @@ -1361,7 +1362,7 @@ } if (!$event['_instance'] && is_a($event['recurrence_date'], 'DateTime')) { - $event['_instance'] = libcalendaring::recurrence_instance_identifier($event); + $event['_instance'] = libcalendaring::recurrence_instance_identifier($event, $master['allday']); } if (!is_array($master['exceptions']) && is_array($master['recurrence']['EXCEPTIONS'])) {
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/calendar/helpdocs/en_US/invitations.rst
Changed
@@ -29,6 +29,8 @@ the event into your personal calendar. The selector right next to the buttons lets you choose the right one. +.. note:: It is sometimes useful (especially when declining or delegating an event) to respond without saving the event in your calendar. To do this use "--" entry in calendars selector. + The copy in your calendar now knows about the invitation and its original sender. If you now delete it from your calendar, you'll be asked whether this should send a declination message to the person who organizes the event. @@ -52,4 +54,3 @@ When you now look at the event details in the calendar view, the status icons next to each participant now displays the new status. -
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/calendar/helpdocs/en_US/manage.rst
Changed
@@ -153,21 +153,19 @@ Invitations will be sent out when you click *Save* and the event is created. -.. only:: kolab +.. index:: Availability +.. _calendar-availability-finder: - .. index:: Availability - .. _calendar-availability-finder: +Find Availability +^^^^^^^^^^^^^^^^^ - Find Availability - ^^^^^^^^^^^^^^^^^ +Once all the participants are added to the list, you see the individual availability status for each one +of them, given that this information is available. In case not everybody is free, click the *Find availability...* +button to open the scheduling dialog. In that dialog, detailed availability information for all participants is +displayed. Use the *Previous/Next Slot* buttons to find the next time slot where all required participants are +available. Or drag the gray area representing the event duration with the mouse to manually select a free slot. - Once all the participants are added to the list, you see the individual availability status for each one - of them, given that this information is available. In case not everybody is free, click the *Find availability...* - button to open the scheduling dialog. In that dialog, detailed availability information for all participants is - displayed. Use the *Previous/Next Slot* buttons to find the next time slot where all required participants are - available. Or drag the gray area representing the event duration with the mouse to manually select a free slot. - - Click *Select* to copy the rescheduled date/time back into the event form and to close this dialog. +Click *Select* to copy the rescheduled date/time back into the event form and to close this dialog. Receive Event Invitations
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/calendar/helpdocs/en_US/overview.rst
Changed
@@ -92,11 +92,9 @@ Events can be organized in different calendars which are all displayed in the lower left list. Use the checkboxes in that list to show or hide events from the specific calendars in the main view. -.. only:: kolab - - Beside your personal calendars, the list also displays calendars shared by other users - or ones that are shared amongst your workgroup. Small icons in the list give a hint - about the origin and some of them are possibly read-only which is denoted with a small lock icon. +Beside your personal calendars, the list also displays calendars shared by other users +or ones that are shared amongst your workgroup. Small icons in the list give a hint +about the origin and some of them are possibly read-only which is denoted with a small lock icon. Colorized Events
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/calendar/helpdocs/en_US/settings.rst
Changed
@@ -24,11 +24,9 @@ When opening the day or week view, the listing of events starts at this time. Of course all hours of a day are visible by scrolling further up. -.. only:: kolab - - **Working hours** - This time range will be used in the :ref:`availability finder <calendar-availability-finder>` - when automatically selecting free slots for a meeting. +**Working hours** + This time range will be used in the :ref:`availability finder <calendar-availability-finder>` + when automatically selecting free slots for a meeting. **Event coloring** The coloring of the title of an event block ("outline") as well as the background color of the box ("content")
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/calendar/helpdocs/en_US/sharing.rst
Changed
@@ -1,49 +1,46 @@ +.. index:: Sharing .. _calendar-sharing: -.. only:: kolab +Sharing Calendars +================= - .. index:: Sharing +For collaboration, sharing calendars is an important feature. In the :ref:`overview <calendar-lists>`, +we have already learned how calendars others share with you appear in the calendars list. The following +now explains how to make personal calendars accessible to fellow users. - Sharing Calendars - ================= - For collaboration, sharing calendars is an important feature. In the :ref:`overview <calendar-lists>`, - we have already learned how calendars others share with you appear in the calendars list. The following - now explains how to make personal calendars accessible to fellow users. +Share a Calendar with others +---------------------------- +Sharing is controlled through the :ref:`Calendar Settings Dialog <calendar-edit-properties>`. +Double-click a calendar in the list on the left and then select the *Sharing* tab at the top of +the dialog box: - Share a Calendar with others - ---------------------------- +.. image:: _static/_skin/calendar-acl.png - Sharing is controlled through the :ref:`Calendar Settings Dialog <calendar-edit-properties>`. - Double-click a calendar in the list on the left and then select the *Sharing* tab at the top of - the dialog box: +The table displays who already has permission to see and modify the selected calendar. +In order to share the calendar with a new user do - .. image:: _static/_skin/calendar-acl.png +1. Click the *Add entry* button (+) in the table footer +2. Enter the username or choose one from the autocompletion menu that appears when you start typing. + Instead of a specific user, permissons can be granted for all users or guests. +3. Select the access rights you want to grant for the user +4. Click *Save* to add the permission - The table displays who already has permission to see and modify the selected calendar. - In order to share the calendar with a new user do +Double-click an entry to edit the permissions for a particular user or group. - 1. Click the *Add entry* button (+) in the table footer - 2. Enter the username or choose one from the autocompletion menu that appears when you start typing. - Instead of a specific user, permissons can be granted for all users or guests. - 3. Select the access rights you want to grant for the user - 4. Click *Save* to add the permission +For removing existing permissions, select the according entry in the list and then choose +*Delete* from the menu behind the gear icon in the footer of the list. - Double-click an entry to edit the permissions for a particular user or group. - For removing existing permissions, select the according entry in the list and then choose - *Delete* from the menu behind the gear icon in the footer of the list. +Subscribe to Shared Calendars +----------------------------- +Calendars shared by others are not showing up right away in the list within the calendar view. +Switch to :ref:`Settings > Folders <settings-folders>` to see all resources you can access. +There's a shortcut to this: click *Manage folders* in the options menu behind the gear icon +located the footer of the calendars list. - Subscribe to Shared Calendars - ----------------------------- - - Calendars shared by others are not showing up right away in the list within the calendar view. - Switch to :ref:`Settings > Folders <settings-folders>` to see all resources you can access. - There's a shortcut to this: click *Manage folders* in the options menu behind the gear icon - located the footer of the calendars list. - - In order to make a shared calendar appear in the calendars list, locate it in the folder manager - and check the *Subscribed* mark in the list. Only subscribed calendars are visible in the calendar view. +In order to make a shared calendar appear in the calendars list, locate it in the folder manager +and check the *Subscribed* mark in the list. Only subscribed calendars are visible in the calendar view.
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/calendar/helpdocs/po/invitations.pot
Changed
@@ -1,14 +1,14 @@ # SOME DESCRIPTIVE TITLE. -# Copyright (C) 2014, roundcube.net +# Copyright (C) 2015, roundcube.net # This file is distributed under the same license as the Roundcube Webmail Help package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Roundcube Webmail Help 1.0\n" +"Project-Id-Version: Roundcube Webmail Help 1.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-11-26 23:28+0100\n" +"POT-Creation-Date: 2017-01-12 11:31+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -45,30 +45,34 @@ msgstr "" #: ../../en_US/_plugins/calendar/invitations.rst:35 +msgid "It is sometimes useful (especially when declining or delegating an event) to respond without saving the event in your calendar. To do this use \"--\" entry in calendars selector." +msgstr "" + +#: ../../en_US/_plugins/calendar/invitations.rst:37 msgid "The copy in your calendar now knows about the invitation and its original sender. If you now delete it from your calendar, you'll be asked whether this should send a declination message to the person who organizes the event." msgstr "" -#: ../../en_US/_plugins/calendar/invitations.rst:39 +#: ../../en_US/_plugins/calendar/invitations.rst:41 msgid "After acceping or declining, the email message containing the invitation can be deleted." msgstr "" -#: ../../en_US/_plugins/calendar/invitations.rst:43 +#: ../../en_US/_plugins/calendar/invitations.rst:45 msgid "Process Invitation Replies" msgstr "" -#: ../../en_US/_plugins/calendar/invitations.rst:45 +#: ../../en_US/_plugins/calendar/invitations.rst:47 msgid "As an organizer who has invited others to an event, you'll receive responses to the automatically sent invitations when the attendees either accept or decline them." msgstr "" -#: ../../en_US/_plugins/calendar/invitations.rst:48 +#: ../../en_US/_plugins/calendar/invitations.rst:50 msgid "Such messages are also identified by the webmail system and again a yellow box appears in the message view:" msgstr "" -#: ../../en_US/_plugins/calendar/invitations.rst:53 +#: ../../en_US/_plugins/calendar/invitations.rst:55 msgid "By clicking the *Update the participant's status* button, the original event in your calendar will be updated with the RSVP status from the person who responded here." msgstr "" -#: ../../en_US/_plugins/calendar/invitations.rst:56 +#: ../../en_US/_plugins/calendar/invitations.rst:58 msgid "When you now look at the event details in the calendar view, the status icons next to each participant now displays the new status." msgstr ""
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/calendar/lib/calendar_recurrence.php
Changed
@@ -75,7 +75,7 @@ } $next['recurrence_date'] = clone $next_start; - $next['_instance'] = libcalendaring::recurrence_instance_identifier($next); + $next['_instance'] = libcalendaring::recurrence_instance_identifier($next, $this->event['allday']); unset($next['_formatobj']);
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/calendar/lib/calendar_ui.php
Changed
@@ -235,6 +235,7 @@ ); } + $this->rc->output->set_env('source', rcube_utils::get_input_value('source', rcube_utils::INPUT_GET)); $this->rc->output->set_env('calendars', $jsenv); $this->rc->output->add_gui_object('calendarslist', $attrib['id']);
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/calendar/localization/en_US.inc
Changed
@@ -164,8 +164,6 @@ $labels['availunknown'] = 'Unknown'; $labels['availtentative'] = 'Tentative'; $labels['availoutofoffice'] = 'Out of Office'; -$labels['delegatedto'] = 'Delegated to: '; -$labels['delegatedfrom'] = 'Delegated from: '; $labels['scheduletime'] = 'Find availability'; $labels['sendinvitations'] = 'Send invitations'; $labels['sendnotifications'] = 'Notify participants about modifications';
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/kolab_auth/kolab_auth.php
Changed
@@ -389,17 +389,10 @@ $ldap = self::ldap(); if (!$ldap || !$ldap->ready) { - $args['abort'] = true; - $args['kolab_ldap_error'] = true; - $message = sprintf( - 'Login failure for user %s from %s in session %s (error %s)', - $user, - rcube_utils::remote_ip(), - session_id(), - "LDAP not ready" - ); + self::log_login_error($user, "LDAP not ready"); - rcube::write_log('userlogins', $message); + $args['abort'] = true; + $args['kolab_ldap_error'] = true; return $args; } @@ -408,16 +401,9 @@ $record = $ldap->get_user_record($user, $host); if (empty($record)) { - $args['abort'] = true; - $message = sprintf( - 'Login failure for user %s from %s in session %s (error %s)', - $user, - rcube_utils::remote_ip(), - session_id(), - "No user record found" - ); + self::log_login_error($user, "No user record found"); - rcube::write_log('userlogins', $message); + $args['abort'] = true; return $args; } @@ -451,16 +437,9 @@ $result = $ldap->bind($record['dn'], $pass); if (!$result) { - $args['abort'] = true; - $message = sprintf( - 'Login failure for user %s from %s in session %s (error %s)', - $user, - rcube_utils::remote_ip(), - session_id(), - "Unable to bind with '" . $record['dn'] . "'" - ); + self::log_login_error($user, "Unable to bind with '" . $record['dn'] . "'"); - rcube::write_log('userlogins', $message); + $args['abort'] = true; return $args; } @@ -548,16 +527,7 @@ 'vars' => array('user' => rcube::Q($loginas)), )); - $message = sprintf( - 'Login failure for user %s (as user %s) from %s in session %s (error %s)', - $user, - $loginas, - rcube_utils::remote_ip(), - session_id(), - "No privileges to login as '" . $loginas . "'" - ); - - rcube::write_log('userlogins', $message); + self::log_login_error($user, "No privileges to login as '" . $loginas . "'", $loginas); return $args; } @@ -795,4 +765,35 @@ return $str; } + + /** + * Log failed logins + * + * @param string $username Username/Login + * @param string $message Error message (failure reason) + * @param string $login_as Username/Login of "login as" user + */ + public static function log_login_error($username, $message = null, $login_as = null) + { + $config = rcube::get_instance()->config; + + if ($config->get('log_logins')) { + if ($login_as) { + $username = sprintf('%s (as user %s)', $username, $login_as); + } + + $message = sprintf( + "Failed login for %s from %s in session %s %s", + $username, + rcube_utils::remote_ip(), + session_id(), + $message ? "($message)" : '' + ); + + rcube::write_log('userlogins', $message); + + // disable log_logins to prevent from duplicate log entries + $config->set('log_logins', false); + } + } }
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/kolab_delegation/kolab_delegation.js
Changed
@@ -7,7 +7,7 @@ * @licstart The following is the entire license notice for the * JavaScript code in this file. * - * Copyright (C) 2011-2015, Kolab Systems AG <contact@kolabsys.com> + * Copyright (C) 2011-2016, 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 @@ -27,20 +27,32 @@ */ window.rcmail && rcmail.addEventListener('init', function(evt) { - if (rcmail.env.task == 'mail' || rcmail.env.task == 'calendar') { - // set delegator context for calendar requests on invitation message - rcmail.addEventListener('requestcalendar/event', function(o) { rcmail.event_delegator_request(o); }); - rcmail.addEventListener('requestcalendar/mailimportevent', function(o) { rcmail.event_delegator_request(o); }); - rcmail.addEventListener('requestcalendar/mailimportitip', function(o) { rcmail.event_delegator_request(o); }); - rcmail.addEventListener('requestcalendar/itip-status', function(o) { rcmail.event_delegator_request(o); }); - rcmail.addEventListener('requestcalendar/itip-remove', function(o) { rcmail.event_delegator_request(o); }); - + if (rcmail.env.task == 'mail' || rcmail.env.task == 'calendar' || rcmail.env.task == 'tasks') { + // set delegator context for calendar/tasklist requests on invitation message + rcmail.addEventListener('requestcalendar/event', function(o) { rcmail.event_delegator_request(o); }) + .addEventListener('requestcalendar/mailimportitip', function(o) { rcmail.event_delegator_request(o); }) + .addEventListener('requestcalendar/itip-status', function(o) { rcmail.event_delegator_request(o); }) + .addEventListener('requestcalendar/itip-remove', function(o) { rcmail.event_delegator_request(o); }) + .addEventListener('requesttasks/task', function(o) { rcmail.event_delegator_request(o); }) + .addEventListener('requesttasks/mailimportitip', function(o) { rcmail.event_delegator_request(o); }) + .addEventListener('requesttasks/itip-status', function(o) { rcmail.event_delegator_request(o); }) + .addEventListener('requesttasks/itip-remove', function(o) { rcmail.event_delegator_request(o); }); + + // Calendar UI if (rcmail.env.delegators && window.rcube_calendar_ui) { - rcmail.calendar_identity_init(); + rcmail.calendar_identity_init('calendar'); // delegator context for calendar event form - rcmail.addEventListener('calendar-event-init', function(o) { return rcmail.calendar_event_init(o); }); + rcmail.addEventListener('calendar-event-init', function(o) { return rcmail.calendar_event_init(o, 'calendar'); }); // change organizer identity on calendar folder change - $('#edit-calendar').change(function() { rcmail.calendar_change(); }); + $('#edit-calendar').change(function() { rcmail.calendar_folder_change(this); }); + } + // Tasks UI + else if (rcmail.env.delegators && window.rcube_tasklist_ui) { + rcmail.calendar_identity_init('tasklist'); + // delegator context for task form + rcmail.addEventListener('tasklist-task-init', function(o) { return rcmail.calendar_event_init(o, 'tasklist'); }); + // change organizer identity on tasks folder change + $('#taskedit-tasklist').change(function() { rcmail.calendar_folder_change(this); }); } } else if (rcmail.env.task != 'settings') @@ -251,27 +263,31 @@ return data; }; -// callback for calendar event form initialization -rcube_webmail.prototype.calendar_event_init = function(data) +// callback for calendar event/task form initialization +rcube_webmail.prototype.calendar_event_init = function(data, type) { + var folder = data.o[type == 'calendar' ? 'calendar' : 'list'] + // set identity for delegator context - this.env.calendar_settings.identity = this.calendar_folder_delegator(data.o.calendar); + this.env[type + '_settings'].identity = this.calendar_folder_delegator(folder, type); }; -// returns delegator's identity data according to selected calendar folder -rcube_webmail.prototype.calendar_folder_delegator = function(calendar) +// returns delegator's identity data according to selected calendar/tasks folder +rcube_webmail.prototype.calendar_folder_delegator = function(folder, type) { - var d, delegator; + var d, delegator, + settings = this.env[type + '_settings'], + list = this.env[type == 'calendar' ? 'calendars' : 'tasklists']; // derive delegator from the calendar owner property - if (this.env.calendars[calendar] && this.env.calendars[calendar].owner) { - delegator = this.env.calendars[calendar].owner.replace(/@.+$/, ''); + if (list[folder] && list[folder].owner) { + delegator = list[folder].owner.replace(/@.+$/, ''); } if (delegator && (d = this.env.delegators[delegator])) { // find delegator's identity id if (!d.identity_id) - $.each(this.env.calendar_settings.identities, function(i, v) { + $.each(settings.identities, function(i, v) { if (d.email == v) { d.identity_id = i; return false; @@ -288,26 +304,28 @@ return d; }; -// handler for calendar folder change -rcube_webmail.prototype.calendar_change = function() +// handler for calendar/tasklist folder change +rcube_webmail.prototype.calendar_folder_change = function(element) { - var calendar = $('#edit-calendar').val(), + var folder = $(element).val(), + type = element.id.indexOf('task') > -1 ? 'tasklist' : 'calendar', + sname = type + '_settings', select = $('#edit-identities-list'), - old = this.env.calendar_settings.identity; + old = this.env[sname].identity; - this.env.calendar_settings.identity = this.calendar_folder_delegator(calendar); + this.env[sname].identity = this.calendar_folder_delegator(folder, type); // change organizer identity in identity selector - if (select.length && old != this.env.calendar_settings.identity) { - var id = this.env.calendar_settings.identity.identity_id; + if (select.length && old != this.env[sname].identity) { + var id = this.env[sname].identity.identity_id; select.val(id || select.find('option').first().val()).change(); } }; // modify default identity of the user -rcube_webmail.prototype.calendar_identity_init = function() +rcube_webmail.prototype.calendar_identity_init = function(type) { - var identity = this.env.calendar_settings.identity, + var identity = this.env[type + '_settings'].identity, emails = identity.emails.split(';'); // remove delegators' emails from list of emails of the current user @@ -320,4 +338,4 @@ identity.emails = emails.join(';'); this.env.original_identity = identity; -} +};
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/kolab_delegation/kolab_delegation.php
Changed
@@ -25,7 +25,7 @@ class kolab_delegation extends rcube_plugin { - public $task = 'login|mail|settings|calendar'; + public $task = 'login|mail|settings|calendar|tasks'; private $rc; private $engine; @@ -49,11 +49,12 @@ // on-message-send delegation support $this->add_hook('message_before_send', array($this, 'message_before_send')); - // delegation support in Calendar plugin + // delegation support in Calendar and Tasklist plugins $this->add_hook('message_load', array($this, 'message_load')); $this->add_hook('calendar_user_emails', array($this, 'calendar_user_emails')); $this->add_hook('calendar_list_filter', array($this, 'calendar_list_filter')); $this->add_hook('calendar_load_itip', array($this, 'calendar_load_itip')); + $this->add_hook('tasklist_list_filter', array($this, 'tasklist_list_filter')); // delegation support in kolab_auth plugin $this->add_hook('kolab_auth_emails', array($this, 'kolab_auth_emails')); @@ -80,8 +81,10 @@ $this->include_stylesheet($this->skin_path . '/style.css'); } } - // Calendar plugin UI bindings - else if ($this->rc->task == 'calendar' && empty($_REQUEST['_framed'])) { + // Calendar/Tasklist plugin UI bindings + else if (($this->rc->task == 'calendar' || $this->rc->task == 'tasks') + && empty($_REQUEST['_framed']) + ) { if ($this->rc->output->type == 'html') { $this->calendar_ui(); } @@ -200,7 +203,7 @@ return $args; } - $engine = $this->engine(); + $engine = $this->engine(); $context = $engine->delegator_context_from_message($args['object']); if ($context) { @@ -237,7 +240,23 @@ if (!empty($_SESSION['delegators'])) { $engine = $this->engine(); - $engine->delegator_folder_filter($args); + $engine->delegator_folder_filter($args, 'calendars'); + } + + return $args; + } + + /** + * tasklist_driver::get_lists() handler + */ + public function tasklist_list_filter($args) + { + // In delegator context we'll use delegator's folders + // instead of current user folders + + if (!empty($_SESSION['delegators'])) { + $engine = $this->engine(); + $engine->delegator_folder_filter($args, 'tasklists'); } return $args; @@ -260,7 +279,7 @@ } /** - * Delegation support in Calendar plugin UI + * Delegation support in Calendar/Tasks plugin UI */ public function calendar_ui() { @@ -331,15 +350,15 @@ // Delegate delete if ($this->rc->action == 'plugin.delegation-delete') { - $id = rcube_utils::get_input_value('id', rcube_utils::INPUT_GPC); - $success = $engine->delegate_delete($id, (bool) rcube_utils::get_input_value('acl', rcube_utils::INPUT_GPC)); + $id = rcube_utils::get_input_value('id', rcube_utils::INPUT_GPC); + $error = $engine->delegate_delete($id, (bool) rcube_utils::get_input_value('acl', rcube_utils::INPUT_GPC)); - if ($success) { + if (!$error) { $this->rc->output->show_message($this->gettext('deletesuccess'), 'confirmation'); $this->rc->output->command('plugin.delegate_save_complete', array('deleted' => $id)); } else { - $this->rc->output->show_message($this->gettext('deleteerror'), 'error'); + $this->rc->output->show_message($this->gettext($error), 'error'); } } // Delegate add/update @@ -350,23 +369,23 @@ // update if ($id) { $delegate = $engine->delegate_get($id); - $success = $engine->delegate_acl_update($delegate['uid'], $acl); + $error = $engine->delegate_acl_update($delegate['uid'], $acl); - if ($success) { + if (!$error) { $this->rc->output->show_message($this->gettext('updatesuccess'), 'confirmation'); $this->rc->output->command('plugin.delegate_save_complete', array('updated' => $id)); } else { - $this->rc->output->show_message($this->gettext('updateerror'), 'error'); + $this->rc->output->show_message($this->gettext($error), 'error'); } } // new else { $login = rcube_utils::get_input_value('newid', rcube_utils::INPUT_GPC); $delegate = $engine->delegate_get_by_name($login); - $success = $engine->delegate_add($delegate, $acl); + $error = $engine->delegate_add($delegate, $acl); - if ($success) { + if (!$error) { $this->rc->output->show_message($this->gettext('createsuccess'), 'confirmation'); $this->rc->output->command('plugin.delegate_save_complete', array( 'created' => $delegate['ID'], @@ -374,7 +393,7 @@ )); } else { - $this->rc->output->show_message($this->gettext('createerror'), 'error'); + $this->rc->output->show_message($this->gettext($error), 'error'); } } }
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/kolab_delegation/kolab_delegation_engine.php
Changed
@@ -54,6 +54,8 @@ * * @param string|array $delegate Delegate DN (encoded) or delegate data (result of delegate_get()) * @param array $acl List of folder->right map + * + * @return string On error returns an error label, on success returns null */ public function delegate_add($delegate, $acl) { @@ -63,18 +65,20 @@ $dn = $delegate['ID']; if (empty($delegate) || empty($dn)) { - return false; + return 'createerror'; } $list = $this->list_delegates(); - - // add delegate to the list $list = array_keys((array)$list); $list = array_filter($list); - if (!in_array($dn, $list)) { - $list[] = $dn; + + if (in_array($dn, $list)) { + return 'delegationexisterror'; } - $list = array_map(array('kolab_auth_ldap', 'dn_decode'), $list); + + // add delegate to the list + $list[] = $dn; + $list = array_map(array('kolab_auth_ldap', 'dn_decode'), $list); // update user record $result = $this->user_update_delegates($list); @@ -84,7 +88,7 @@ $this->delegate_acl_update($delegate['uid'], $acl); } - return $result; + return $result ? null : 'createerror'; } /** @@ -93,6 +97,8 @@ * @param string $uid Delegate authentication identifier * @param array $acl List of folder->right map * @param bool $update Update (remove) old rights + * + * @return string On error returns an error label, on success returns null */ public function delegate_acl_update($uid, $acl, $update = false) { @@ -119,8 +125,6 @@ $storage->delete_acl($folder_name, $uid); } } - - return true; } /** @@ -128,6 +132,8 @@ * * @param string $dn Delegate DN (encoded) * @param bool $acl_del Enable ACL deletion on delegator folders + * + * @return string On error returns an error label, on success returns null */ public function delegate_delete($dn, $acl_del = false) { @@ -136,7 +142,7 @@ $user = $this->user(); if (empty($delegate) || !isset($list[$dn])) { - return false; + return 'deleteerror'; } // remove delegate from the list @@ -153,7 +159,7 @@ $this->delegate_acl_update($delegate['uid'], array(), true); } - return $result; + return $result ? null : 'deleteerror'; } /** @@ -777,11 +783,11 @@ } /** - * Filters list of calendars according to delegator context + * Filters list of calendar/task folders according to delegator context * * @param array $args Reference to plugin hook arguments */ - public function delegator_folder_filter(&$args) + public function delegator_folder_filter(&$args, $mode = 'calendars') { $context = $this->delegator_context(); @@ -789,28 +795,40 @@ return $args; } - $storage = $this->rc->get_storage(); - $other_ns = $storage->get_namespace('other'); - $delim = $storage->get_hierarchy_delimiter(); - $editable = $args['filter'] & calendar_driver::FILTER_WRITEABLE; - $active = $args['filter'] & calendar_driver::FILTER_ACTIVE; - $personal = $args['filter'] & calendar_driver::FILTER_PERSONAL; - $shared = $args['filter'] & calendar_driver::FILTER_SHARED; - $calendars = array(); + $storage = $this->rc->get_storage(); + $other_ns = $storage->get_namespace('other'); + $delim = $storage->get_hierarchy_delimiter(); - // code parts derived from kolab_driver::filter_calendars() - foreach ($args['list'] as $cal) { - if (!$cal->ready) { + if ($mode == 'calendars') { + $editable = $args['filter'] & calendar_driver::FILTER_WRITEABLE; + $active = $args['filter'] & calendar_driver::FILTER_ACTIVE; + $personal = $args['filter'] & calendar_driver::FILTER_PERSONAL; + $shared = $args['filter'] & calendar_driver::FILTER_SHARED; + } + else { + $editable = $args['filter'] & tasklist_driver::FILTER_WRITEABLE; + $active = $args['filter'] & tasklist_driver::FILTER_ACTIVE; + $personal = $args['filter'] & tasklist_driver::FILTER_PERSONAL; + $shared = $args['filter'] & tasklist_driver::FILTER_SHARED; + } + + $folders = array(); + + foreach ($args['list'] as $folder) { + if (isset($folder->ready) && !$folder->ready) { continue; } - if ($editable && !$cal->editable) { + + if ($editable && !$folder->editable) { continue; } - if ($active && !$cal->storage->is_active()) { + + if ($active && !$folder->storage->is_active()) { continue; } + if ($personal || $shared) { - $ns = $cal->get_namespace(); + $ns = $folder->get_namespace(); if ($personal && $ns == 'personal') { continue; @@ -818,8 +836,8 @@ else if ($personal && $ns == 'other') { $found = false; foreach ($other_ns as $ns) { - $folder = $ns[0] . $context . $delim; - if (strpos($cal->name, $folder) === 0) { + $c_folder = $ns[0] . $context . $delim; + if (strpos($folder->name, $c_folder) === 0) { $found = true; } } @@ -833,11 +851,11 @@ } } - $calendars[$cal->id] = $cal; + $folders[$folder->id] = $folder; } - $args['calendars'] = $calendars; - $args['abort'] = true; + $args[$mode] = $folders; + $args['abort'] = true; } /**
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/kolab_delegation/localization/en_US.inc
Changed
@@ -35,6 +35,7 @@ $labels['updateerror'] = 'Could not update delegate.'; $labels['createsuccess'] = 'The delegate was successfully added.'; $labels['createerror'] = 'Could not add delegate.'; +$labels['delegationexisterror'] = 'Specified user already is your delegate.'; $labels['arialabeldelegatedelete'] = 'Delegate deletion dialog'; $labels['arialabeldelegateform'] = 'Delegate properties form';
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/kolab_files/kolab_files.js
Changed
@@ -193,6 +193,8 @@ file_api.request('folder_info', {folder: file_api.file_path(rcmail.env.file), sessions: 1}, 'folder_info_response'); } else { + file_api.env.folder = rcmail.env.folder; + file_api.env.collection = rcmail.env.collection; file_api.folder_list(); file_api.browser_capabilities_check(); } @@ -360,7 +362,7 @@ buttons[rcmail.gettext('kolab_files.attachsel')] = function () { var list = []; - $('#fileslist tr.selected').each(function() { + $('#filelist tr.selected').each(function() { list.push($(this).data('file')); }); @@ -2059,7 +2061,8 @@ }); // select first folder? - if (response.result.auth_errors) { } + if (response.result.auth_errors && response.result.auth_errors.length) + this.env.folder = this.env.collection = null; else if (this.env.folder) rcmail.folder_list.select(this.env.folder); else if (this.env.collection) @@ -2085,6 +2088,9 @@ var is_collection = folder.match(/^folder-collection-(.*)$/), collection = RegExp.$1 || null; + if (rcmail.task == 'files' && !rcmail.env.action) + rcmail.update_state(is_collection ? {collection: collection} : {folder: folder}); + if (collection == 'sessions') { rcmail.enable_command('files-list', 'files-folder-delete', 'folder-rename', 'files-upload', false); this.sessions_list(); @@ -2839,7 +2845,7 @@ this.file_list_sort = function(col, reverse) { var n, len, list = this.env.file_list, - table = $('#fileslist'), tbody = $('<tbody>', table); + table = $('#filelist'), tbody = $('<tbody>', table); this.env.sort_col = col; this.env.sort_reverse = reverse;
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/kolab_files/lib/kolab_files_engine.php
Changed
@@ -961,6 +961,11 @@ $this->folder_list_env(); + if ($this->rc->task == 'files') { + $this->rc->output->set_env('folder', rcube_utils::get_input_value('folder', rcube_utils::INPUT_GET)); + $this->rc->output->set_env('collection', rcube_utils::get_input_value('collection', rcube_utils::INPUT_GET)); + } + $this->rc->output->add_label('uploadprogress', 'GB', 'MB', 'KB', 'B'); $this->rc->output->set_pagetitle($this->plugin->gettext('files')); $this->rc->output->set_env('file_mimetypes', $this->get_mimetypes()); @@ -1280,7 +1285,7 @@ 'html' => $content, 'name' => $attachment['name'], 'mimetype' => $attachment['mimetype'], - 'classname' => rcmail_filetype2classname($attachment['mimetype'], $attachment['name']), + 'classname' => rcube_utils::file2class($attachment['mimetype'], $attachment['name']), 'complete' => true), $uploadid); } else if ($attachment['error']) {
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/libcalendaring/libcalendaring.js
Changed
@@ -1026,9 +1026,9 @@ } if (data['delegated-to']) - tooltip = rcmail.gettext('delegatedto', context) + data['delegated-to']; + tooltip = rcmail.gettext('delegatedto', context) + ' ' + data['delegated-to']; else if (data['delegated-from']) - tooltip = rcmail.gettext('delegatedfrom', context) + data['delegated-from']; + tooltip = rcmail.gettext('delegatedfrom', context) + ' ' + data['delegated-from']; return $('<span>').append( $('<span>').attr({'class': 'attendee ' + status, title: tooltip}).append(name.text(dispname))
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/libcalendaring/libcalendaring.php
Changed
@@ -131,12 +131,13 @@ $this->include_script('libcalendaring.js'); $this->include_stylesheet($this->local_skin_path() . '/libcal.css'); - $this->rc->output->add_label( - 'libcalendaring.itipaccepted', 'libcalendaring.itiptentative', 'libcalendaring.itipdeclined', - 'libcalendaring.itipdelegated', 'libcalendaring.expandattendeegroup', 'libcalendaring.expandattendeegroupnodata', - 'libcalendaring.statusorganizer', 'libcalendaring.statusaccepted', 'libcalendaring.statusdeclined', - 'libcalendaring.statusdelegated', 'libcalendaring.statusunknown', 'libcalendaring.statusneeds-action', - 'libcalendaring.statustentative', 'libcalendaring.statuscompleted', 'libcalendaring.statusin-process' + $this->add_label( + 'itipaccepted', 'itiptentative', 'itipdeclined', + 'itipdelegated', 'expandattendeegroup', 'expandattendeegroupnodata', + 'statusorganizer', 'statusaccepted', 'statusdeclined', + 'statusdelegated', 'statusunknown', 'statusneeds-action', + 'statustentative', 'statuscompleted', 'statusin-process', + 'delegatedto', 'delegatedfrom' ); } @@ -1492,18 +1493,23 @@ * Return the identifer for the given instance of a recurring event * * @param array Hash array with event properties + * @param bool All-day flag from the main event + * * @return mixed Format string or null if identifier cannot be generated */ - public static function recurrence_instance_identifier($event) + public static function recurrence_instance_identifier($event, $allday = null) { $instance_date = $event['recurrence_date'] ?: $event['start']; if ($instance_date && is_a($instance_date, 'DateTime')) { - $recurrence_id_format = $event['allday'] ? 'Ymd' : 'Ymd\THis'; - return $instance_date->format($recurrence_id_format); - } + // According to RFC5545 (3.8.4.4) RECURRENCE-ID format should + // be date/date-time depending on the main event type, not the exception + if ($allday === null) { + $allday = $event['allday']; + } - return null; + return $instance_date->format($allday ? 'Ymd' : 'Ymd\THis'); + } }
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/libcalendaring/localization/de_CH.inc
Changed
@@ -85,6 +85,8 @@ $labels['statusunknown'] = 'Unbekannt'; $labels['statuscompleted'] = 'Abgeschlossen'; $labels['statusin-process'] = 'In Bearbeitung'; +$labels['delegatedto'] = 'Delegiert an:'; +$labels['delegatedfrom'] = 'Delegiert von:'; $labels['itipinvitation'] = 'Einladung zu'; $labels['itipupdate'] = 'Aktialisiert:'; $labels['itipcancellation'] = 'Abgesagt:';
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/libcalendaring/localization/de_DE.inc
Changed
@@ -84,6 +84,8 @@ $labels['statusneeds-action'] = 'Braucht Aktion'; $labels['statusunknown'] = 'Unbekannt'; $labels['statuscompleted'] = 'Abgeschlossen'; +$labels['delegatedto'] = 'Delegiert an:'; +$labels['delegatedfrom'] = 'Delegiert von:'; $labels['statusin-process'] = 'In Bearbeitung'; $labels['itipinvitation'] = 'Einladung zu'; $labels['itipupdate'] = 'Aktialisiert:';
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/libcalendaring/localization/en_US.inc
Changed
@@ -97,6 +97,8 @@ $labels['statusunknown'] = 'Unknown'; $labels['statuscompleted'] = 'Completed'; $labels['statusin-process'] = 'In process'; +$labels['delegatedto'] = 'Delegated to: '; +$labels['delegatedfrom'] = 'Delegated from: '; // itip related labels $labels['itipinvitation'] = 'Invitation to';
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/libkolab/lib/kolab_format.php
Changed
@@ -234,7 +234,10 @@ if (!$dateonly) $result->setTime($datetime->format('G'), $datetime->format('i'), $datetime->format('s')); - if ($tz && in_array($tz->getName(), array('UTC', 'GMT', '+00:00', 'Z'))) { + // libkolabxml throws errors on some deprecated timezone names + $utc_aliases = array('UTC', 'GMT', '+00:00', 'Z', 'Etc/GMT'); + + if ($tz && in_array($tz->getName(), $utc_aliases)) { $result->setUTC(true); } else if ($tz !== false) { @@ -525,6 +528,7 @@ $created = $object['created'] ?: new DateTime('now'); $created->setTimezone(new DateTimeZone('UTC')); // must be UTC $this->obj->setCreated(self::get_datetime($created)); + $object['created'] = $created; } $object['changed'] = new DateTime('now', new DateTimeZone('UTC'));
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/libkolab/lib/kolab_format_event.php
Changed
@@ -291,7 +291,9 @@ } // preserve this property for date serialization - $exception['allday'] = $master['allday']; + if (!isset($exception['allday'])) { + $exception['allday'] = $master['allday']; + } return $exception; } @@ -304,7 +306,7 @@ // Note: If an exception has no attendees it means there's "no attendees // for this occurrence", not "attendees are the same as in the event" (#5300) - $forbidden = array('exceptions', 'attendees'); + $forbidden = array('exceptions', 'attendees', 'allday'); $is_recurring = !empty($master['recurrence']); foreach ($master as $prop => $value) {
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/libkolab/lib/kolab_format_xcal.php
Changed
@@ -420,7 +420,10 @@ $rr->setFrequency(RecurrenceRule::FreqNone); if ($object['recurrence'] && !empty($object['recurrence']['FREQ'])) { - $rr->setFrequency($this->rrule_type_map[$object['recurrence']['FREQ']]); + $freq = $object['recurrence']['FREQ']; + $bysetpos = explode(',', $object['recurrence']['BYSETPOS']); + + $rr->setFrequency($this->rrule_type_map[$freq]); if ($object['recurrence']['INTERVAL']) $rr->setInterval(intval($object['recurrence']['INTERVAL'])); @@ -433,8 +436,19 @@ $occurrence = intval($m[1]); $day = $m[2]; } - if (isset($this->weekday_map[$day])) - $byday->push(new DayPos($occurrence, $this->weekday_map[$day])); + + if (isset($this->weekday_map[$day])) { + // @TODO: libkolabxml does not support BYSETPOS, neither we. + // However, we can convert most common cases to BYDAY + if (!$occurence && $freq == 'MONTHLY' && !empty($bysetpos)) { + foreach ($bysetpos as $pos) { + $byday->push(new DayPos(intval($pos), $this->weekday_map[$day])); + } + } + else { + $byday->push(new DayPos($occurrence, $this->weekday_map[$day])); + } + } } $rr->setByday($byday); }
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/libkolab/lib/kolab_storage_cache.php
Changed
@@ -893,6 +893,12 @@ $object['_size'] = strlen($sql_arr['xml']); $object['_formatobj'] = kolab_format::factory($format_type, 3.0, $sql_arr['xml']); + // Fix old broken objects with missing creation date + if (empty($object['created']) && method_exists($object['_formatobj'], 'to_array')) { + $new_object = $object['_formatobj']->to_array(); + $object['created'] = $new_object['created']; + } + return $object; }
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/tasklist/drivers/database/tasklist_database_driver.php
Changed
@@ -89,7 +89,7 @@ /** * Get a list of available tasks lists from this source */ - public function get_lists() + public function get_lists($filter = 0) { // attempt to create a default list for this user if (empty($this->lists)) { @@ -361,10 +361,13 @@ /** * Return data of a specific task * - * @param mixed Hash array with task properties or task UID + * @param mixed Hash array with task properties or task UID + * @param integer Bitmask defining filter criterias. + * See FILTER_* constants for possible values. + * * @return array Hash array with task properties or false if not found */ - public function get_task($prop) + public function get_task($prop, $filter = 0) { if (is_string($prop)) $prop['uid'] = $prop;
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
Changed
@@ -120,10 +120,10 @@ $alarms = false; $rights = 'lr'; $editable = false; - if (($myrights = $folder->get_myrights()) && !PEAR::isError($myrights)) { + if ($myrights = $folder->get_myrights()) { $rights = $myrights; if (strpos($rights, 't') !== false || strpos($rights, 'd') !== false) - $editable = strpos($rights, 'i'); + $editable = strpos($rights, 'i') !== false; } $info = $folder->get_folder_info(); $norename = $readonly || $info['norename'] || $info['protected']; @@ -147,6 +147,7 @@ 'rights' => $rights, 'norename' => $norename, 'active' => $folder->is_active(), + 'owner' => $folder->get_owner(), 'parentfolder' => $folder->get_parent(), 'default' => $folder->default, 'virtual' => $folder->virtual, @@ -163,8 +164,11 @@ /** * Get a list of available task lists from this source + * + * @param integer Bitmask defining filter criterias. + * See FILTER_* constants for possible values. */ - public function get_lists(&$tree = null) + public function get_lists($filter = 0, &$tree = null) { $this->_read_lists(); @@ -175,12 +179,7 @@ $this->_read_lists(true); } - $folders = array(); - foreach ($this->lists as $id => $list) { - if (!empty($this->folders[$id])) { - $folders[] = $this->folders[$id]; - } - } + $folders = $this->filter_folders($filter); // include virtual folders for a full folder tree if (!is_null($tree)) { @@ -252,6 +251,80 @@ } /** + * Get list of folders according to specified filters + * + * @param integer Bitmask defining restrictions. See FILTER_* constants for possible values. + * + * @return array List of task folders + */ + protected function filter_folders($filter) + { + $this->_read_lists(); + + $folders = array(); + foreach ($this->lists as $id => $list) { + if (!empty($this->folders[$id])) { + $folder = $this->folders[$id]; + + if ($folder->get_namespace() == 'personal') { + $folder->editable = true; + } + else if ($rights = $folder->get_myrights()) { + if (strpos($rights, 't') !== false || strpos($rights, 'd') !== false) { + $folder->editable = strpos($rights, 'i') !== false; + } + } + + $folders[] = $folder; + } + } + + $plugin = $this->rc->plugins->exec_hook('tasklist_list_filter', array( + 'list' => $folders, + 'filter' => $filter, + 'tasklists' => $folders, + )); + + if ($plugin['abort'] || !$filter) { + return $plugin['tasklists']; + } + + $personal = $filter & self::FILTER_PERSONAL; + $shared = $filter & self::FILTER_SHARED; + + $tasklists = array(); + foreach ($folders as $folder) { + if (($filter & self::FILTER_WRITEABLE) && !$folder->editable) { + continue; + } +/* + if (($filter & self::FILTER_INSERTABLE) && !$folder->insert) { + continue; + } + if (($filter & self::FILTER_ACTIVE) && !$folder->is_active()) { + continue; + } + if (($filter & self::FILTER_PRIVATE) && $folder->subtype != 'private') { + continue; + } + if (($filter & self::FILTER_CONFIDENTIAL) && $folder->subtype != 'confidential') { + continue; + } +*/ + if ($personal || $shared) { + $ns = $folder->get_namespace(); + if (!(($personal && $ns == 'personal') || ($shared && $ns == 'shared'))) { + continue; + } + } + + $tasklists[$folder->id] = $folder; + } + + return $tasklists; + } + + /** * Get the kolab_calendar instance for the given calendar ID * * @param string List identifier (encoded imap folder name) @@ -616,20 +689,24 @@ /** * Return data of a specific task * - * @param mixed Hash array with task properties or task UID + * @param mixed Hash array with task properties or task UID + * @param integer Bitmask defining filter criterias for folders. + * See FILTER_* constants for possible values. + * * @return array Hash array with task properties or false if not found */ - public function get_task($prop) + public function get_task($prop, $filter = 0) { - $this->_read_lists(); $this->_parse_id($prop); $id = $prop['uid']; $list_id = $prop['list']; - $folders = $list_id ? array($list_id => $this->get_folder($list_id)) : $this->folders; + $folders = $list_id ? array($list_id => $this->get_folder($list_id)) : $this->get_lists($filter); // find task in the available folders foreach ($folders as $list_id => $folder) { + if (is_array($folder)) + $folder = $this->folders[$list_id]; if (is_numeric($list_id) || !$folder) continue; if (!$this->tasks[$id] && ($object = $folder->get_object($id))) {
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/tasklist/drivers/tasklist_driver.php
Changed
@@ -79,10 +79,22 @@ public $alarm_absolute = true; public $last_error; + const FILTER_ALL = 0; + const FILTER_WRITEABLE = 1; + const FILTER_INSERTABLE = 2; + const FILTER_ACTIVE = 4; + const FILTER_PERSONAL = 8; + const FILTER_PRIVATE = 16; + const FILTER_CONFIDENTIAL = 32; + const FILTER_SHARED = 64; + + /** * Get a list of available task lists from this source + * @param integer Bitmask defining filter criterias. + * See FILTER_* constants for possible values. */ - abstract function get_lists(); + abstract function get_lists($filter = 0); /** * Create a new list assigned to the current user @@ -196,10 +208,13 @@ /** * Return data of a specific task * - * @param mixed Hash array with task properties or task UID + * @param mixed Hash array with task properties or task UID + * @param integer Bitmask defining filter criterias for folders. + * See FILTER_* constants for possible values. + * * @return array Hash array with task properties or false if not found */ - abstract public function get_task($prop); + abstract public function get_task($prop, $filter = 0); /** * Get decendents of the given task record
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/tasklist/helpdocs/en_US/index.rst
Changed
@@ -12,3 +12,4 @@ overview manage + invitations
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/tasklist/helpdocs/en_US/invitations.rst
Added
@@ -0,0 +1,12 @@ +.. index:: Invitation, RSVP +.. _tasklist-invitations: + +Handle Task Assignments +======================= + +You can assign other people to a task. This will send out invitation emails to all +assignees with the task data attached. That allows one to directly accept +or decline the invitation. + +Chapter :ref:`calendar-invitations` describes how email invitations work +for event participants. The same applies for task assignees.
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/tasklist/helpdocs/en_US/manage.rst
Changed
@@ -50,11 +50,7 @@ * ``Complete``: The completeness state of a task in percent. Use the slider or enter a number. * ``Tasklist``: The list the task is saved in. Change it to move an event from one list to another. - -.. only:: kolab - - - **Recurrence** +**Recurrence** For periodically recurring task series, this tab has the settings how a task is repeated over time. @@ -64,15 +60,15 @@ If you choose a frequency of weekly or monthly you can select which days of the week or month the task will occur. * ``Until``: Determines the duration of the repetition. The recurrence can either run forever, for a number of times or until a specific date. - **Assignments** +**Assignments** One, or a list of, users can be assigned to the task. The list is managed in this tab. * ``Organizer``: The user organizing (creating) the task. This is set to the default identity of the logged in user, but a diferent identity for this user can be selected. * ``Add Assignee``: Type three letters of the username, and the search box will show a dropdown list of relevant users. Then clieck the 'Add Assignee' button. -* ``Invitation/notification comment``: When a user is assigned to a task, an email notificatino is sent out. This field is giving the opportunity to add extra test to this mail notification. +* ``Invitation/notification comment``: When a user is assigned to a task, an email notification is sent out. This field is giving the opportunity to add extra text to this mail notification. - **Attachments** +**Attachments** Sometimes a description text isn't enough to collect information for a specific task. Switch to this tab to attach files to the current task or to remove them again. Adding
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/tasklist/helpdocs/po/invitations.pot
Added
@@ -0,0 +1,30 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2015, roundcube.net +# This file is distributed under the same license as the Roundcube Webmail Help package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Roundcube Webmail Help 1.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-12 11:31+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../../en_US/_plugins/tasklist/invitations.rst:8 +msgid "Handle Task Assignments" +msgstr "" + +#: ../../en_US/_plugins/tasklist/invitations.rst:10 +msgid "You can assign other people to a task. This will send out invitation emails to all assignees with the task data attached. That allows one to directly accept or decline the invitation." +msgstr "" + +#: ../../en_US/_plugins/tasklist/invitations.rst:14 +msgid "Chapter :ref:`calendar-invitations` describes how email invitations work for event participants. The same applies for task assignees." +msgstr "" +
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/tasklist/localization/en_US.inc
Changed
@@ -197,8 +197,6 @@ $labels['delegateinvitation'] = 'Delegate assignment'; $labels['andnmore'] = '$nr more...'; -$labels['delegatedto'] = 'Delegated to: '; -$labels['delegatedfrom'] = 'Delegated from: '; $labels['savetotasklist'] = 'Save to tasks'; $labels['comment'] = 'Comment'; $labels['errorimportingtask'] = 'Failed to import task(s)';
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/tasklist/tasklist.js
Changed
@@ -156,6 +156,9 @@ } } + if (rcmail.env.source && me.tasklists[rcmail.env.source]) + me.selected_list = rcmail.env.source; + // initialize treelist widget that controls the tasklists list var widget_class = window.kolab_folderlist || rcube_treelist_widget; tasklists_widget = new widget_class(rcmail.gui_objects.tasklistslist, { @@ -176,6 +179,7 @@ rcmail.enable_command('list-remove', me.tasklists[node.id] && me.tasklists[node.id].removable); rcmail.enable_command('list-showurl', me.tasklists[node.id] && !!me.tasklists[node.id].caldavurl); me.selected_list = node.id; + rcmail.update_state({source: node.id}); }); tasklists_widget.addEventListener('subscribe', function(p) { var list; @@ -1886,9 +1890,9 @@ + (!data.noreply && settings.itip_notify & 1 ? 'checked="checked" ' : '') + '/>'; if (data['delegated-to']) - tooltip = rcmail.gettext('delegatedto', 'tasklist') + data['delegated-to']; + tooltip = rcmail.gettext('libcalendaring.delegatedto') + ' ' + data['delegated-to']; else if (data['delegated-from']) - tooltip = rcmail.gettext('delegatedfrom', 'tasklist') + data['delegated-from']; + tooltip = rcmail.gettext('libcalendaring.delegatedfrom') + ' ' + data['delegated-from']; else if (status) tooltip = status_label; @@ -2373,6 +2377,9 @@ // reset dialog first $('#taskeditform').get(0).reset(); + // allow other plugins to do actions when task form is opened + rcmail.triggerEvent('tasklist-task-init', {o: rec}); + // fill form data var title = $('#taskedit-title').val(rec.title || ''); var description = $('#taskedit-description').val(rec.description || ''); @@ -2936,7 +2943,7 @@ } } - return $.unqiqueStrings(itags); + return $.uniqueStrings(itags); } /** @@ -3411,7 +3418,7 @@ })(); // equivalent to $.unique() but working on arrays of strings -jQuery.unqiqueStrings = (function() { +jQuery.uniqueStrings = (function() { return function(arr) { var hash = {}, out = [];
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/tasklist/tasklist.php
Changed
@@ -1338,9 +1338,9 @@ if (empty($rec['recurrence']) || $duedate < $today || $start > $weeklimit) { if ($duedate <= $today || ($rec['startdate'] && $start <= $today)) $mask |= self::FILTER_MASK_TODAY; - if ($duedate <= $tomorrow || ($rec['startdate'] && $start <= $tomorrow)) + else if (($start > $today && $start <= $tomorrow) || ($duedate > $today && $duedate <= $tomorrow)) $mask |= self::FILTER_MASK_TOMORROW; - if (($start > $tomorrow && $start <= $weeklimit) || ($duedate > $tomorrow && $duedate <= $weeklimit)) + else if (($start > $tomorrow && $start <= $weeklimit) || ($duedate > $tomorrow && $duedate <= $weeklimit)) $mask |= self::FILTER_MASK_WEEK; else if ($start > $weeklimit || $duedate > $weeklimit) $mask |= self::FILTER_MASK_LATER; @@ -1871,9 +1871,12 @@ /** * Get properties of the tasklist this user has specified as default */ - public function get_default_tasklist($sensitivity = null) + public function get_default_tasklist($sensitivity = null, $lists = null) { - $lists = $this->driver->get_lists(); + if ($lists === null) { + $lists = $this->driver->get_lists(tasklist_driver::FILTER_PERSONAL | tasklist_driver::FILTER_WRITEABLE); + } + $list = null; foreach ($lists as $l) { @@ -2005,15 +2008,19 @@ unset($task['comment']); } + $mode = tasklist_driver::FILTER_PERSONAL + | tasklist_driver::FILTER_SHARED + | tasklist_driver::FILTER_WRITEABLE; + // find writeable list to store the task $list_id = !empty($_REQUEST['_folder']) ? rcube_utils::get_input_value('_folder', rcube_utils::INPUT_POST) : null; - $lists = $this->driver->get_lists(); + $lists = $this->driver->get_lists($mode); $list = $lists[$list_id]; $dontsave = ($_REQUEST['_folder'] === '' && $task['_method'] == 'REQUEST'); // select default list except user explicitly selected 'none' if (!$list && !$dontsave) { - $list = $this->get_default_tasklist($task['sensitivity']); + $list = $this->get_default_tasklist($task['sensitivity'], $lists); } $metadata = array( @@ -2061,7 +2068,7 @@ $task['list'] = $list['id']; // check for existing task with the same UID - $existing = $this->driver->get_task($task['uid']); + $existing = $this->find_task($task['uid'], $mode); if ($existing) { // only update attendee status @@ -2226,6 +2233,28 @@ } /** + * Find a task in user tasklists + */ + protected function find_task($task, &$mode) + { + $this->load_driver(); + + // We search for writeable folders in personal namespace by default + $mode = tasklist_driver::FILTER_WRITEABLE | tasklist_driver::FILTER_PERSONAL; + $result = $this->driver->get_task($task, $mode); + + // ... now check shared folders if not found + if (!$result) { + $result = $this->driver->get_task($task, tasklist_driver::FILTER_WRITEABLE | tasklist_driver::FILTER_SHARED); + if ($result) { + $mode |= tasklist_driver::FILTER_SHARED; + } + } + + return $result; + } + + /** * Handler for task/itip-status requests */ public function task_itip_status() @@ -2233,13 +2262,14 @@ $data = rcube_utils::get_input_value('data', rcube_utils::INPUT_POST, true); // find local copy of the referenced task - $existing = $this->driver->get_task($data); - $itip = $this->load_itip(); - $response = $itip->get_itip_status($data, $existing); + $existing = $this->find_task($data, $mode); + $is_shared = $mode & tasklist_driver::FILTER_SHARED; + $itip = $this->load_itip(); + $response = $itip->get_itip_status($data, $existing); // get a list of writeable lists to save new tasks to - if (!$existing && $response['action'] == 'rsvp' || $response['action'] == 'import') { - $lists = $this->driver->get_lists(); + if ((!$existing || $is_shared) && $response['action'] == 'rsvp' || $response['action'] == 'import') { + $lists = $this->driver->get_lists($mode); $select = new html_select(array('name' => 'tasklist', 'id' => 'itip-saveto', 'is_escaped' => true)); $select->add('--', ''); @@ -2251,9 +2281,9 @@ } if ($select) { - $default_list = $this->get_default_tasklist($data['sensitivity']); + $default_list = $this->get_default_tasklist($data['sensitivity'], $lists); $response['select'] = html::span('folder-select', $this->gettext('saveintasklist') . ' ' . - $select->show($default_list['id'])); + $select->show($is_shared ? $existing['list'] : $default_list['id'])); } $this->rc->output->command('plugin.update_itip_object_status', $response);
View file
roundcubemail-plugins-kolab-3.3.tar.gz/plugins/tasklist/tasklist_ui.php
Changed
@@ -178,7 +178,7 @@ { $tree = true; $jsenv = array(); - $lists = $this->plugin->driver->get_lists($tree); + $lists = $this->plugin->driver->get_lists(0, $tree); // walk folder tree if (is_object($tree)) { @@ -202,6 +202,7 @@ } } + $this->rc->output->set_env('source', rcube_utils::get_input_value('source', rcube_utils::INPUT_GET)); $this->rc->output->set_env('tasklists', $jsenv); $this->register_gui_object('tasklistslist', $attrib['id']);
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.