Overview
Request 2897 (accepted)
Check in 3.5.11
- Created by vanmeeuwen about 3 years ago
- In state accepted
Submit package Kolab:Winterfell / roundcubema...gins-kolab to package Kolab:16 / roundcubemail-plugins-kolab
roundcubemail-plugins-kolab.spec
Changed
x
1
2
%global dash_rel_suffix %{?rc_rel_suffix:-%{rc_rel_suffix}}
3
4
Name: roundcubemail-plugins-kolab
5
-Version: 3.5.10
6
+Version: 3.5.11
7
8
Release: 1%{?dot_rel_suffix}%{?dist}
9
10
debian.changelog
Changed
11
1
2
+roundcubemail-plugins-kolab (1:3.5.11-0~kolab1) unstable; urgency=low
3
+
4
+ * Release version 3.5.11
5
+
6
+ -- Jeroen van Meeuwen <vanmeeuwen@apheleia-it.ch> Fri, 14 Jan 2022 11:11:11 +0200
7
+
8
roundcubemail-plugins-kolab (1:3.5.10-0~kolab1) unstable; urgency=low
9
10
* Release version 3.5.10
11
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/calendar/calendar.php -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/calendar/calendar.php
Changed
208
1
2
$noreply = intval($noreply) || $status == 'needs-action' || $itip_sending === 0;
3
$reload = $event['calendar'] != $ev['calendar'] || !empty($event['recurrence']) ? 2 : 1;
4
$emails = $this->get_user_emails();
5
+ $ownedResourceEmails = $this->owned_resources_emails();
6
$organizer = null;
7
+ $resourceConfirmation = false;
8
9
foreach ($event['attendees'] as $i => $attendee) {
10
if ($attendee['role'] == 'ORGANIZER') {
11
$organizer = $attendee;
12
}
13
- else if (!empty($attendee['email']) && in_array(strtolower($attendee['email']), $emails)) {
14
+ else if (!empty($attendee['email']) && in_array_nocase($attendee['email'], $emails)) {
15
$reply_sender = $attendee['email'];
16
}
17
+ else if (!empty($attendee['cutype']) && $attendee['cutype'] == 'RESOURCE' && !empty($attendee['email']) && in_array_nocase($attendee['email'], $ownedResourceEmails)) {
18
+ $resourceConfirmation = true;
19
+ // Note on behalf of which resource this update is going to be sent out
20
+ $event['_resource'] = $attendee['email'];
21
+ }
22
}
23
24
if (!$noreply) {
25
$itip = $this->load_itip();
26
$itip->set_sender_email($reply_sender);
27
$event['thisandfuture'] = $event['_savemode'] == 'future';
28
+ $bodytextprefix = $resourceConfirmation ? 'itipmailbodyresource' : 'itipmailbody';
29
30
- if ($organizer && $itip->send_itip_message($event, 'REPLY', $organizer, 'itipsubject' . $status, 'itipmailbody' . $status)) {
31
+ if ($organizer && $itip->send_itip_message($event, 'REPLY', $organizer, 'itipsubject' . $status, $bodytextprefix . $status)) {
32
$mailto = !empty($organizer['name']) ? $organizer['name'] : $organizer['email'];
33
$msg = $this->gettext(['name' => 'sentresponseto', 'vars' => ['mailto' => $mailto]]);
34
35
36
}
37
38
$identity['emails'][] = $this->rc->user->get_username();
39
+ $identity['ownedResources'] = $this->owned_resources_emails();
40
$settings['identity'] = [
41
'name' => $identity['name'],
42
'email' => strtolower($identity['email']),
43
- 'emails' => ';' . strtolower(join(';', $identity['emails']))
44
+ 'emails' => ';' . strtolower(join(';', $identity['emails'])),
45
+ 'ownedResources' => ';' . strtolower(join(';', $identity['ownedResources']))
46
];
47
}
48
49
50
}
51
52
$attachments = [];
53
- $eventid = 'cal-' . (!empty($event['id']) ? $event['id'] : 'new-event');
54
+ $eventid = 'cal-' . (!empty($event['id']) ? $event['id'] : 'new');
55
56
if (!empty($_SESSION[self::SESSION_KEY]) && $_SESSION[self::SESSION_KEY]['id'] == $eventid) {
57
if (!empty($_SESSION[self::SESSION_KEY]['attachments'])) {
58
59
exit;
60
}
61
62
+ /**
63
+ * List email addressed of owned resources
64
+ */
65
+ private function owned_resources_emails()
66
+ {
67
+ $results = [];
68
+ if ($directory = $this->resources_directory()) {
69
+ foreach ($directory->load_resources($_SESSION['kolab_dn'], 5000, 'owner') as $rec) {
70
+ $results[] = $rec['email'];
71
+ }
72
+ }
73
+ return $results;
74
+ }
75
+
76
+
77
/**** Event invitation plugin hooks ****/
78
79
/**
80
81
*/
82
private function mail_agenda_event_row($event, $class = '')
83
{
84
- $time = !empty($event['allday']) ? $this->gettext('all-day') :
85
- $this->rc->format_date($event['start'], $this->rc->config->get('time_format'))
86
- . ' - ' .
87
- $this->rc->format_date($event['end'], $this->rc->config->get('time_format'));
88
+ if (!empty($event['allday'])) {
89
+ $time = $this->gettext('all-day');
90
+ }
91
+ else {
92
+ $start = is_object($event['start']) ? clone $event['start'] : $event['start'];
93
+ $end = is_object($event['end']) ? clone $event['end'] : $event['end'];
94
+
95
+ $time = $this->rc->format_date($start, $this->rc->config->get('time_format'))
96
+ . ' - ' . $this->rc->format_date($end, $this->rc->config->get('time_format'));
97
+ }
98
99
return html::div(rtrim('event-row ' . ($class ?: $event['className'])),
100
html::span('event-date', $time)
101
102
// get prepared inline UI for this event object
103
if ($ical_objects->method) {
104
$append = '';
105
- $date_str = $this->rc->format_date($event['start'], $this->rc->config->get('date_format'), empty($event['start']->_dateonly));
106
+ $date_str = $this->rc->format_date(clone $event['start'], $this->rc->config->get('date_format'), empty($event['start']->_dateonly));
107
$date = new DateTime($event['start']->format('Y-m-d') . ' 12:00:00', new DateTimeZone('UTC'));
108
109
// prepare a small agenda preview to be filled with actual event data on async request
110
111
112
// only update attendee status
113
if ($event['_method'] == 'REPLY') {
114
- // try to identify the attendee using the email sender address
115
- $existing_attendee = -1;
116
- $existing_attendee_emails = [];
117
-
118
- foreach ($existing['attendees'] as $i => $attendee) {
119
- $existing_attendee_emails[] = $attendee['email'];
120
- if ($this->itip->compare_email($attendee['email'], $event['_sender'], $event['_sender_utf'])) {
121
- $existing_attendee = $i;
122
- }
123
- }
124
+ $existing_attendee_index = -1;
125
126
$event_attendee = null;
127
$update_attendees = [];
128
129
- foreach ($event['attendees'] as $attendee) {
130
- if ($this->itip->compare_email($attendee['email'], $event['_sender'], $event['_sender_utf'])) {
131
- $event_attendee = $attendee;
132
- $update_attendees[] = $attendee;
133
- $metadata['fallback'] = $attendee['status'];
134
- $metadata['attendee'] = $attendee['email'];
135
- $metadata['rsvp'] = !empty($attendee['rsvp']) || $attendee['role'] != 'NON-PARTICIPANT';
136
-
137
- if ($attendee['status'] != 'DELEGATED') {
138
- break;
139
+ if ($attendee = $this->itip->find_reply_attendee($event)) {
140
+ $event_attendee = $attendee;
141
+ $update_attendees[] = $attendee;
142
+ $metadata['fallback'] = $attendee['status'];
143
+ $metadata['attendee'] = $attendee['email'];
144
+ $metadata['rsvp'] = !empty($attendee['rsvp']) || $attendee['role'] != 'NON-PARTICIPANT';
145
+
146
+ $existing_attendee_emails = [];
147
+
148
+ // Find the attendee to update
149
+ foreach ($existing['attendees'] as $i => $existing_attendee) {
150
+ $existing_attendee_emails[] = $existing_attendee['email'];
151
+ if ($this->itip->compare_email($existing_attendee['email'], $attendee['email'])) {
152
+ $existing_attendee_index = $i;
153
}
154
}
155
- // also copy delegate attendee
156
- else if (!empty($attendee['delegated-from'])
157
- && $this->itip->compare_email($attendee['delegated-from'], $event['_sender'], $event['_sender_utf'])
158
- ) {
159
- $update_attendees[] = $attendee;
160
- if (!in_array_nocase($attendee['email'], $existing_attendee_emails)) {
161
- $existing['attendees'][] = $attendee;
162
+
163
+ if ($attendee['status'] == 'DELEGATED') {
164
+ //Also find and copy the delegatee
165
+ $delegatee_email = $attendee['email'];
166
+ $delegatees = array_filter($event['attendees'], function($attendee) use ($delegatee_email){ return $attendee['role'] != 'ORGANIZER' && $this->itip->compare_email($attendee['delegated-from'], $delegatee_email); });
167
+
168
+ if ($delegatee = $this->itip->find_attendee_by_email($event['attendees'], 'delegated-from', $attendee['email'])) {
169
+ $update_attendees[] = $delegatee;
170
+ if (!in_array_nocase($delegatee['email'], $existing_attendee_emails)) {
171
+ $existing['attendees'][] = $delegated_attendee;
172
+ }
173
}
174
}
175
}
176
177
}
178
}
179
180
- // Accept sender as a new participant (different email in From: and the iTip)
181
- // Use ATTENDEE entry from the iTip with replaced email address
182
- if (!$event_attendee) {
183
- // remove the organizer
184
- $itip_attendees = array_filter(
185
- $event['attendees'],
186
- function($item) { return $item['role'] != 'ORGANIZER'; }
187
- );
188
-
189
- // there must be only one attendee
190
- if (is_array($itip_attendees) && count($itip_attendees) == 1) {
191
- $event_attendee = $itip_attendees[key($itip_attendees)];
192
- $event_attendee['email'] = $event['_sender'];
193
- $update_attendees[] = $event_attendee;
194
- $metadata['fallback'] = $event_attendee['status'];
195
- $metadata['attendee'] = $event_attendee['email'];
196
- $metadata['rsvp'] = !empty($event_attendee['rsvp']) || $event_attendee['role'] != 'NON-PARTICIPANT';
197
- }
198
- }
199
-
200
// found matching attendee entry in both existing and new events
201
- if ($existing_attendee >= 0 && $event_attendee) {
202
- $existing['attendees'][$existing_attendee] = $event_attendee;
203
+ if ($existing_attendee_index >= 0 && $event_attendee) {
204
+ $existing['attendees'][$existing_attendee_index] = $event_attendee;
205
$success = $this->driver->update_attendees($existing, $update_attendees);
206
}
207
// update the entire attendees block
208
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/calendar/calendar_ui.js -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/calendar/calendar_ui.js
Changed
44
1
2
$('#event-alarm').show().find('.event-text').html(Q(event.alarms_text).replace(',', ',<br>'));
3
if (calendar.name)
4
$('#event-calendar').show().find('.event-text').html(Q(calendar.name)).addClass('cal-'+calendar.id);
5
- if (event.categories)
6
+ if (event.categories && String(event.categories).length)
7
$('#event-category').show().find('.event-text').text(event.categories).addClass('cat-'+String(event.categories).toLowerCase().replace(rcmail.identifier_expr, ''));
8
if (event.free_busy)
9
$('#event-free-busy').show().find('.event-text').text(rcmail.gettext(event.free_busy, 'calendar'));
10
11
for (var j=0; j < num_attendees; j++) {
12
data = event.attendees[j];
13
if (data.email) {
14
- if (data.role != 'ORGANIZER' && settings.identity.emails.indexOf(';'+data.email) >= 0) {
15
+ if (data.role != 'ORGANIZER' && is_this_me(data.email)) {
16
mystatus = (data.status || 'UNKNOWN').toLowerCase();
17
if (data.status == 'NEEDS-ACTION' || data.status == 'TENTATIVE' || data.rsvp)
18
rsvp = mystatus;
19
20
add_attendee($.extend({ role:'REQ-PARTICIPANT', status:'NEEDS-ACTION', cutype:'RESOURCE' }, resource));
21
}
22
23
+ var is_this_me = function(email)
24
+ {
25
+ if (settings.identity.emails.indexOf(';'+email) >= 0 || settings.identity.ownedResources.indexOf(';'+email) >= 0) {
26
+ return true;
27
+ }
28
+ return false;
29
+ };
30
+
31
// when the user accepts or declines an event invitation
32
var event_rsvp = function(response, delegate, replymode, event)
33
{
34
35
attendees = [];
36
for (var data, i=0; i < me.selected_event.attendees.length; i++) {
37
data = me.selected_event.attendees[i];
38
- if (settings.identity.emails.indexOf(';'+String(data.email).toLowerCase()) >= 0) {
39
+ //FIXME this can only work if there is a single resource per invitation
40
+ if (is_this_me(String(data.email).toLowerCase())) {
41
data.status = response.toUpperCase();
42
data.rsvp = 0; // unset RSVP flag
43
44
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/calendar/composer.json -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/calendar/composer.json
Changed
10
1
2
"description": "Calendar plugin",
3
"homepage": "https://git.kolab.org/diffusion/RPK/",
4
"license": "AGPLv3",
5
- "version": "3.5.10",
6
+ "version": "3.5.11",
7
"authors": [
8
{
9
"name": "Thomas Bruederli",
10
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/calendar/drivers/ldap/resources_driver_ldap.php -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/calendar/drivers/ldap/resources_driver_ldap.php
Changed
27
1
2
/**
3
* Fetch resource objects to be displayed for booking
4
*
5
- * @param string $query Search query (optional)
6
- * @param int $num Max size of the result
7
+ * @param string $query Search query (optional)
8
+ * @param int $num Max size of the result
9
+ * @param string $searchField Field to search with query
10
*
11
* @return array List of resource records available for booking
12
*/
13
- public function load_resources($query = null, $num = 5000)
14
+ public function load_resources($query = null, $num = 5000, $searchField = '*')
15
{
16
if (!($ldap = $this->connect())) {
17
return [];
18
19
$ldap->set_pagesize($num);
20
21
if (isset($query)) {
22
- $results = $ldap->search('*', $query, 0, true, true);
23
+ $results = $ldap->search($searchField, $query, 0, true, true);
24
}
25
else {
26
$results = $ldap->list_records();
27
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/calendar/localization/en_US.inc -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/calendar/localization/en_US.inc
Changed
12
1
2
$labels['itipmailbodydelegated'] = "\$sender has delegated the participation in the following event:\n\n*\$title*\n\nWhen: \$date";
3
$labels['itipmailbodydelegatedto'] = "\$sender has delegated the participation in the following event to you:\n\n*\$title*\n\nWhen: \$date";
4
5
+$labels['itipmailbodyresourceaccepted'] = "\$sender has accepted the following resource booking:\n\n*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees";
6
+$labels['itipmailbodyresourcetentative'] = "\$sender has tentatively accepted the following resource booking:\n\n*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees";
7
+$labels['itipmailbodyresourcedeclined'] = "\$sender has declined the the following resource booking:\n\n*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees";
8
+
9
$labels['itipdeclineevent'] = 'Do you want to decline your invitation to this event?';
10
$labels['declinedeleteconfirm'] = 'Do you also want to delete this declined event from your calendar?';
11
$labels['itipcomment'] = 'Invitation/notification comment';
12
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/kolab_2fa/composer.json -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/kolab_2fa/composer.json
Changed
10
1
2
"description": "Kolab 2-Factor Authentication",
3
"homepage": "https://git.kolab.org/diffusion/RPK/",
4
"license": "AGPLv3",
5
- "version": "3.5.8",
6
+ "version": "3.5.11",
7
"authors": [
8
{
9
"name": "Thomas Bruederli",
10
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/kolab_2fa/kolab2fa.js -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/kolab_2fa/kolab2fa.js
Changed
31
1
2
* Remove the given factor from the account
3
*/
4
function remove_factor(id) {
5
- if (rcmail.env.kolab_2fa_factors[id]) {
6
- rcmail.env.kolab_2fa_factors[id].active = false;
7
- }
8
- render();
9
-
10
var lock = rcmail.set_busy(true, 'saving');
11
rcmail.http_post('plugin.kolab-2fa-save', { _method: id, _data: 'false' }, lock);
12
}
13
14
function require_high_security(func, exclude)
15
{
16
// request 2nd factor auth
17
- if (!rcmail.env.session_secured || rcmail.env.session_secured < time() - 120) {
18
+ if (rcmail.env.session_secured !== true && rcmail.env.session_secured < time() - 180) {
19
var method, name;
20
21
// find an active factor
22
23
24
// callback for save failure
25
rcmail.addEventListener('plugin.reset_form', function(method) {
26
- if (rcmail.env.kolab_2fa_factors[method]) {
27
+ if (method && rcmail.env.kolab_2fa_factors[method]) {
28
rcmail.env.kolab_2fa_factors[method].active = false;
29
}
30
31
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/kolab_2fa/kolab_2fa.php -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/kolab_2fa/kolab_2fa.php
Changed
49
1
2
$this->include_script('kolab2fa.js');
3
$this->include_stylesheet($this->local_skin_path() . '/kolab2fa.css');
4
5
- if ($this->check_secure_mode()) {
6
- $this->api->output->set_env('session_secured', $_SESSION['kolab_2fa_secure_mode']);
7
- }
8
-
9
+ $this->api->output->set_env('session_secured', $this->check_secure_mode());
10
$this->api->output->add_label('save','cancel');
11
$this->api->output->set_pagetitle($this->gettext('settingstitle'));
12
$this->api->output->send('kolab_2fa.config');
13
14
}
15
else if ($errors) {
16
$this->api->output->show_message($this->gettext('factorsaveerror'), 'error');
17
- $this->api->output->command('plugin.reset_form', $method);
18
+ $this->api->output->command('plugin.reset_form', $data !== false ? $method : null);
19
}
20
21
$this->api->output->send();
22
23
}
24
25
/**
26
- *
27
+ * Check whether the session is secured with 2FA (excluding the logon)
28
*/
29
protected function check_secure_mode()
30
{
31
- $valid = ($_SESSION['kolab_2fa_secure_mode'] && $_SESSION['kolab_2fa_secure_mode'] > time() - 180);
32
- return $valid;
33
- }
34
+ // Allow admins that used kolab_auth's "login as" feature to act without
35
+ // being asked for the user's second factor
36
+ if (!empty($_SESSION['kolab_auth_admin']) && !empty($_SESSION['kolab_auth_password'])) {
37
+ return true;
38
+ }
39
40
-}
41
\ No newline at end of file
42
+ if ($_SESSION['kolab_2fa_secure_mode'] && $_SESSION['kolab_2fa_secure_mode'] > time() - 180) {
43
+ return $_SESSION['kolab_2fa_secure_mode'];
44
+ }
45
+
46
+ return false;
47
+ }
48
+}
49
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/kolab_delegation/composer.json -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/kolab_delegation/composer.json
Changed
10
1
2
"description": "Kolab delegation feature",
3
"homepage": "https://git.kolab.org/diffusion/RPK/",
4
"license": "AGPLv3",
5
- "version": "3.5.6",
6
+ "version": "3.5.11",
7
"authors": [
8
{
9
"name": "Aleksander Machniak",
10
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/kolab_delegation/kolab_delegation_engine.php -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/kolab_delegation/kolab_delegation_engine.php
Changed
21
1
2
// Definition of read and write ACL
3
$right_types = $this->right_types();
4
5
+ $delegate_lc = strtolower($delegate);
6
+
7
foreach ($folders as $folder) {
8
// get only folders in personal namespace
9
if ($storage->folder_namespace($folder) != 'personal') {
10
11
// in edit mode, get folder ACL
12
if ($delegate) {
13
// @TODO: cache ACL
14
- $acl = $storage->get_acl($folder);
15
- if ($acl = $acl[$delegate]) {
16
+ $imap_acl = $storage->get_acl($folder);
17
+ if (!empty($imap_acl) && (($acl = $imap_acl[$delegate]) || ($acl = $imap_acl[$delegate_lc]))) {
18
if ($this->acl_compare($acl, $right_types[self::ACL_WRITE])) {
19
$rights = self::ACL_WRITE;
20
}
21
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/libcalendaring/composer.json -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/libcalendaring/composer.json
Changed
10
1
2
"description": "Library providing common functions for calendaring plugins",
3
"homepage": "https://git.kolab.org/diffusion/RPK/",
4
"license": "AGPLv3",
5
- "version": "3.5.10",
6
+ "version": "3.5.11",
7
"authors": [
8
{
9
"name": "Thomas Bruederli",
10
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/libcalendaring/lib/libcalendaring_itip.php -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/libcalendaring/lib/libcalendaring_itip.php
Changed
110
1
2
'name' => $bodytext,
3
'vars' => array(
4
'title' => $event['title'],
5
- 'date' => $this->lib->event_date_text($event, true) . $recurrence_info,
6
+ 'date' => $this->lib->event_date_text($event) . $recurrence_info,
7
'attendees' => join(",\n ", $attendees_list),
8
'sender' => $this->sender['name'],
9
'organizer' => $this->sender['name'],
10
11
if ($attendee['role'] == 'ORGANIZER') {
12
$reply_attendees[] = $attendee;
13
}
14
+ // we accept on behalf of a resource
15
+ else if (strcasecmp($attendee['email'], $event['_resource']) == 0) {
16
+ $replying_attendee = $attendee;
17
+ $replying_attendee['sent-by'] = 'mailto:' . $from_utf;
18
+ }
19
else if (strcasecmp($attendee['email'], $from) == 0 || strcasecmp($attendee['email'], $from_utf) == 0) {
20
$replying_attendee = $attendee;
21
if ($attendee['status'] != 'DELEGATED') {
22
23
if ($method == 'REPLY') {
24
$title = $this->gettext('itipreply');
25
26
- foreach ($event['attendees'] as $attendee) {
27
- if (!empty($attendee['email']) && $attendee['role'] != 'ORGANIZER') {
28
- if (empty($event['_sender']) || self::compare_email($attendee['email'], $event['_sender'], $event['_sender_utf'])) {
29
- $metadata['attendee'] = $attendee['email'];
30
- $rsvp_status = strtoupper($attendee['status']);
31
- if ($attendee['delegated-to']) {
32
- $metadata['delegated-to'] = $attendee['delegated-to'];
33
- }
34
- break;
35
- }
36
- }
37
- }
38
-
39
- // It may happen that sender's address is different in From: and the attached iTip
40
- // In such case use the ATTENDEE entry with the address from From: header
41
- if (empty($metadata['attendee']) && !empty($event['_sender'])) {
42
- // remove the organizer
43
- $itip_attendees = array_filter($event['attendees'], function($item) { return $item['role'] != 'ORGANIZER'; });
44
+ $attendee = self::find_reply_attendee($event);
45
46
- // there must be only one attendee
47
- if (is_array($itip_attendees) && count($itip_attendees) == 1) {
48
- $event_attendee = $itip_attendees[key($itip_attendees)];
49
- $metadata['attendee'] = $event['_sender'];
50
- $rsvp_status = strtoupper($event_attendee['status']);
51
+ if ($attendee) {
52
+ $metadata['attendee'] = $attendee['email'];
53
+ $rsvp_status = strtoupper($attendee['status']);
54
+ if ($attendee['delegated-to']) {
55
+ $metadata['delegated-to'] = $attendee['delegated-to'];
56
}
57
}
58
59
60
61
return $v1 || $v2;
62
}
63
+
64
+ /**
65
+ * Find an attendee that is not the organizer and has an email matching $email_field
66
+ */
67
+ public function find_attendee_by_email($attendees, $email_field, $email, $email_utf = null) {
68
+ foreach ($attendees as $_attendee) {
69
+ if ($attendee['role'] == 'ORGANIZER') {
70
+ continue;
71
+ }
72
+ if (!empty($attendee[$email_field]) && self::compare_email($attendee[$email_field], $email, $email_utf)) {
73
+ return $attendee;
74
+ }
75
+ }
76
+ return null;
77
+ }
78
+
79
+ /**
80
+ * Find the replying attendee in a REPLY
81
+ */
82
+ public static function find_reply_attendee($event) {
83
+ // remove the organizer
84
+ $itip_attendees = array_filter($event['attendees'], function($item) { return $item['role'] != 'ORGANIZER' && !empty($item['email']); });
85
+ $attendee = null;
86
+
87
+ // According to rfc there should only be one attendee for a REPLY
88
+ if (count($itip_attendees) == 1) {
89
+ return array_pop($itip_attendees);
90
+ }
91
+
92
+ // If we don't have anything to match by, pick the first and hope for the best.
93
+ if (empty($event['_sender'])) {
94
+ return array_shift($itip_attendees);
95
+ }
96
+
97
+ // try to match by sent-by
98
+ if ($attendee = self::find_attendee_by_email($itip_attendees, 'sent-by', $event['_sender'], $event['_sender_utf'])) {
99
+ return $attendee;
100
+ }
101
+
102
+ // try to match by email
103
+ if ($attendee = self::find_attendee_by_email($itip_attendees, 'email', $event['_sender'], $event['_sender_utf'])) {
104
+ return $attendee;
105
+ }
106
+
107
+ return null;
108
+ }
109
}
110
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/libcalendaring/libcalendaring.php -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/libcalendaring/libcalendaring.php
Changed
90
1
2
/**
3
* Compose a date string for the given event
4
*/
5
- public function event_date_text($event, $tzinfo = false)
6
+ public function event_date_text($event)
7
{
8
$fromto = '--';
9
$is_task = !empty($event['_type']) && $event['_type'] == 'task';
10
11
+ $this->date_format_defaults();
12
+
13
+ $date_format = self::to_php_date_format($this->rc->config->get('calendar_date_format', $this->defaults['calendar_date_format']));
14
+ $time_format = self::to_php_date_format($this->rc->config->get('calendar_time_format', $this->defaults['calendar_time_format']));
15
+
16
+ $getTimezone = function ($date) {
17
+ if ($newTz = $date->getTimezone()) {
18
+ return $newTz->getName();
19
+ }
20
+
21
+ return '';
22
+ };
23
+
24
+ $formatDate = function ($date, $format) use ($getTimezone) {
25
+ // This is a workaround for the rcmail::format_date() which does not play nice with timezone
26
+ $tz = $this->rc->config->get('timezone');
27
+ if ($dateTz = $getTimezone($date)) {
28
+ $this->rc->config->set('timezone', $dateTz);
29
+ }
30
+ $result = $this->rc->format_date($date, $format);
31
+ $this->rc->config->set('timezone', $tz);
32
+
33
+ return $result;
34
+ };
35
+
36
// handle task objects
37
if ($is_task && !empty($event['due']) && is_object($event['due'])) {
38
- $date_format = !empty($event['due']->_dateonly) ? self::to_php_date_format($this->rc->config->get('calendar_date_format', $this->defaults['calendar_date_format'])) : null;
39
- $fromto = $this->rc->format_date($event['due'], $date_format, false);
40
+ $fromto = $formatDate($event['due'], !empty($event['due']->_dateonly) ? $date_format : null);
41
42
// add timezone information
43
- if ($fromto && $tzinfo && ($tzname = $this->timezone->getName())) {
44
- $fromto .= ' (' . strtr($tzname, '_', ' ') . ')';
45
+ if ($fromto && empty($event['due']->_dateonly) && ($tz = $getTimezone($event['due']))) {
46
+ $fromto .= ' (' . strtr($tz, '_', ' ') . ')';
47
}
48
49
return $fromto;
50
51
return $fromto;
52
}
53
54
- $duration = $event['start']->diff($event['end'])->format('s');
55
-
56
- $this->date_format_defaults();
57
- $date_format = self::to_php_date_format($this->rc->config->get('calendar_date_format', $this->defaults['calendar_date_format']));
58
- $time_format = self::to_php_date_format($this->rc->config->get('calendar_time_format', $this->defaults['calendar_time_format']));
59
-
60
if ($event['allday']) {
61
- $fromto = $this->rc->format_date($event['start'], $date_format, false);
62
- if (($todate = $this->rc->format_date($event['end'], $date_format, false)) != $fromto)
63
+ $fromto = $formatDate($event['start'], $date_format);
64
+ if (($todate = $formatDate($event['end'], $date_format)) != $fromto) {
65
$fromto .= ' - ' . $todate;
66
+ }
67
}
68
- else if ($duration < 86400 && $event['start']->format('d') == $event['end']->format('d')) {
69
- $fromto = $this->rc->format_date($event['start'], $date_format) . ' ' . $this->rc->format_date($event['start'], $time_format) .
70
- ' - ' . $this->rc->format_date($event['end'], $time_format);
71
+ else if ($event['start']->format('Ymd') === $event['end']->format('Ymd')) {
72
+ $fromto = $formatDate($event['start'], $date_format) . ' ' . $formatDate($event['start'], $time_format) .
73
+ ' - ' . $formatDate($event['end'], $time_format);
74
}
75
else {
76
- $fromto = $this->rc->format_date($event['start'], $date_format) . ' ' . $this->rc->format_date($event['start'], $time_format) .
77
- ' - ' . $this->rc->format_date($event['end'], $date_format) . ' ' . $this->rc->format_date($event['end'], $time_format);
78
+ $fromto = $formatDate($event['start'], $date_format) . ' ' . $formatDate($event['start'], $time_format) .
79
+ ' - ' . $formatDate($event['end'], $date_format) . ' ' . $formatDate($event['end'], $time_format);
80
}
81
82
// add timezone information
83
- if ($tzinfo && ($tzname = $this->timezone->getName())) {
84
- $fromto .= ' (' . strtr($tzname, '_', ' ') . ')';
85
+ if ($fromto && empty($event['allday']) && ($tz = $getTimezone($event['start']))) {
86
+ $fromto .= ' (' . strtr($tz, '_', ' ') . ')';
87
}
88
89
return $fromto;
90
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/libkolab/composer.json -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/libkolab/composer.json
Changed
10
1
2
"description": "Plugin to setup a basic environment for the interaction with a Kolab server.",
3
"homepage": "https://git.kolab.org/diffusion/RPK/",
4
"license": "AGPLv3",
5
- "version": "3.5.10",
6
+ "version": "3.5.11",
7
"authors": [
8
{
9
"name": "Thomas Bruederli",
10
roundcubemail-plugins-kolab-3.5.10.tar.gz/plugins/libkolab/lib/kolab_attachments_handler.php -> roundcubemail-plugins-kolab-3.5.11.tar.gz/plugins/libkolab/lib/kolab_attachments_handler.php
Changed
12
1
2
$this->rc->upload_progress();
3
}
4
5
- $recid = $id_prefix . rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC);
6
+ $id = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC);
7
$uploadid = rcube_utils::get_input_value('_uploadid', rcube_utils::INPUT_GPC);
8
+ $recid = $id_prefix . ($id ?: 'new');
9
10
if (empty($_SESSION[$session_key]) || $_SESSION[$session_key]['id'] != $recid) {
11
$_SESSION[$session_key] = array();
12
roundcubemail-plugins-kolab.dsc
Changed
17
1
2
Source: roundcubemail-plugins-kolab
3
Binary: roundcubemail-plugins-kolab
4
Architecture: all
5
-Version: 1:3.5.10-0~kolab1
6
+Version: 1:3.5.11-0~kolab1
7
Maintainer: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
8
Uploaders: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
9
Standards-Version: 3.9.3
10
11
roundcubemail-plugin-tinymce-config deb web extra
12
roundcubemail-plugin-wap-client deb web extra
13
Files:
14
- 00000000000000000000000000000000 0 roundcubemail-plugins-kolab-3.5.10.tar.gz
15
+ 00000000000000000000000000000000 0 roundcubemail-plugins-kolab-3.5.11.tar.gz
16
00000000000000000000000000000000 0 debian.tar.gz
17
Refresh
Refresh
Login required, please
login
in order to comment
Request History
vanmeeuwen created request about 3 years ago
Check in 3.5.11
vanmeeuwen accepted review about 3 years ago
Accept
vanmeeuwen accepted review about 3 years ago
Accept
vanmeeuwen approved review about 3 years ago
Accept
vanmeeuwen accepted request about 3 years ago
Accept