Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117692604
D3086.1774878904.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
10 KB
Referenced Files
None
Subscribers
None
D3086.1774878904.diff
View Options
diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -3431,39 +3431,38 @@
// only update attendee status
if ($event['_method'] == 'REPLY') {
- // try to identify the attendee using the email sender address
- $existing_attendee = -1;
- $existing_attendee_emails = [];
-
- foreach ($existing['attendees'] as $i => $attendee) {
- $existing_attendee_emails[] = $attendee['email'];
- if ($this->itip->compare_email($attendee['email'], $event['_sender'], $event['_sender_utf'])) {
- $existing_attendee = $i;
- }
- }
+ $existing_attendee_index = -1;
$event_attendee = null;
$update_attendees = [];
- foreach ($event['attendees'] as $attendee) {
- if ($this->itip->compare_email($attendee['email'], $event['_sender'], $event['_sender_utf'])) {
- $event_attendee = $attendee;
- $update_attendees[] = $attendee;
- $metadata['fallback'] = $attendee['status'];
- $metadata['attendee'] = $attendee['email'];
- $metadata['rsvp'] = !empty($attendee['rsvp']) || $attendee['role'] != 'NON-PARTICIPANT';
+ if ($attendee = $this->itip->find_reply_attendee($event)) {
+ $event_attendee = $attendee;
+ $update_attendees[] = $attendee;
+ $metadata['fallback'] = $attendee['status'];
+ $metadata['attendee'] = $attendee['email'];
+ $metadata['rsvp'] = !empty($attendee['rsvp']) || $attendee['role'] != 'NON-PARTICIPANT';
- if ($attendee['status'] != 'DELEGATED') {
- break;
+ $existing_attendee_emails = [];
+
+ // Find the attendee to update
+ foreach ($existing['attendees'] as $i => $existing_attendee) {
+ $existing_attendee_emails[] = $existing_attendee['email'];
+ if ($this->itip->compare_email($existing_attendee['email'], $attendee['email'])) {
+ $existing_attendee_index = $i;
}
}
- // also copy delegate attendee
- else if (!empty($attendee['delegated-from'])
- && $this->itip->compare_email($attendee['delegated-from'], $event['_sender'], $event['_sender_utf'])
- ) {
- $update_attendees[] = $attendee;
- if (!in_array_nocase($attendee['email'], $existing_attendee_emails)) {
- $existing['attendees'][] = $attendee;
+
+ if ($attendee['status'] == 'DELEGATED') {
+ //Also find and copy the delegatee
+ $delegatee_email = $attendee['email'];
+ $delegatees = array_filter($event['attendees'], function($attendee) use ($delegatee_email){ return $attendee['role'] != 'ORGANIZER' && $this->itip->compare_email($attendee['delegated-from'], $delegatee_email); });
+
+ if ($delegatee = $this->itip->find_attendee_by_email($event['attendees'], 'delegated-from', $attendee['email'])) {
+ $update_attendees[] = $delegatee;
+ if (!in_array_nocase($delegatee['email'], $existing_attendee_emails)) {
+ $existing['attendees'][] = $delegated_attendee;
+ }
}
}
}
@@ -3481,29 +3480,9 @@
}
}
- // Accept sender as a new participant (different email in From: and the iTip)
- // Use ATTENDEE entry from the iTip with replaced email address
- if (!$event_attendee) {
- // remove the organizer
- $itip_attendees = array_filter(
- $event['attendees'],
- function($item) { return $item['role'] != 'ORGANIZER'; }
- );
-
- // there must be only one attendee
- if (is_array($itip_attendees) && count($itip_attendees) == 1) {
- $event_attendee = $itip_attendees[key($itip_attendees)];
- $event_attendee['email'] = $event['_sender'];
- $update_attendees[] = $event_attendee;
- $metadata['fallback'] = $event_attendee['status'];
- $metadata['attendee'] = $event_attendee['email'];
- $metadata['rsvp'] = !empty($event_attendee['rsvp']) || $event_attendee['role'] != 'NON-PARTICIPANT';
- }
- }
-
// found matching attendee entry in both existing and new events
- if ($existing_attendee >= 0 && $event_attendee) {
- $existing['attendees'][$existing_attendee] = $event_attendee;
+ if ($existing_attendee_index >= 0 && $event_attendee) {
+ $existing['attendees'][$existing_attendee_index] = $event_attendee;
$success = $this->driver->update_attendees($existing, $update_attendees);
}
// update the entire attendees block
diff --git a/plugins/libcalendaring/lib/libcalendaring_itip.php b/plugins/libcalendaring/lib/libcalendaring_itip.php
--- a/plugins/libcalendaring/lib/libcalendaring_itip.php
+++ b/plugins/libcalendaring/lib/libcalendaring_itip.php
@@ -633,30 +633,13 @@
if ($method == 'REPLY') {
$title = $this->gettext('itipreply');
- foreach ($event['attendees'] as $attendee) {
- if (!empty($attendee['email']) && $attendee['role'] != 'ORGANIZER') {
- if (empty($event['_sender']) || self::compare_email($attendee['email'], $event['_sender'], $event['_sender_utf'])) {
- $metadata['attendee'] = $attendee['email'];
- $rsvp_status = strtoupper($attendee['status']);
- if ($attendee['delegated-to']) {
- $metadata['delegated-to'] = $attendee['delegated-to'];
- }
- break;
- }
- }
- }
-
- // It may happen that sender's address is different in From: and the attached iTip
- // In such case use the ATTENDEE entry with the address from From: header
- if (empty($metadata['attendee']) && !empty($event['_sender'])) {
- // remove the organizer
- $itip_attendees = array_filter($event['attendees'], function($item) { return $item['role'] != 'ORGANIZER'; });
+ $attendee = self::find_reply_attendee($event);
- // there must be only one attendee
- if (is_array($itip_attendees) && count($itip_attendees) == 1) {
- $event_attendee = $itip_attendees[key($itip_attendees)];
- $metadata['attendee'] = $event['_sender'];
- $rsvp_status = strtoupper($event_attendee['status']);
+ if ($attendee) {
+ $metadata['attendee'] = $attendee['email'];
+ $rsvp_status = strtoupper($attendee['status']);
+ if ($attendee['delegated-to']) {
+ $metadata['delegated-to'] = $attendee['delegated-to'];
}
}
@@ -1013,4 +996,50 @@
return $v1 || $v2;
}
+
+ /**
+ * Find an attendee that is not the organizer and has an email matching $email_field
+ */
+ public function find_attendee_by_email($attendees, $email_field, $email, $email_utf = null) {
+ foreach ($attendees as $_attendee) {
+ if ($attendee['role'] == 'ORGANIZER') {
+ continue;
+ }
+ if (!empty($attendee[$email_field]) && self::compare_email($attendee[$email_field], $email, $email_utf)) {
+ return $attendee;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find the replying attendee in a REPLY
+ */
+ public static function find_reply_attendee($event) {
+ // remove the organizer
+ $itip_attendees = array_filter($event['attendees'], function($item) { return $item['role'] != 'ORGANIZER' && !empty($item['email']); });
+ $attendee = null;
+
+ // According to rfc there should only be one attendee for a REPLY
+ if (count($itip_attendees) == 1) {
+ return array_pop($itip_attendees);
+ }
+
+ // If we don't have anything to match by, pick the first and hope for the best.
+ if (empty($event['_sender'])) {
+ return array_shift($itip_attendees);
+ }
+
+ // try to match by sent-by
+ if ($attendee = self::find_attendee_by_email($itip_attendees, 'sent-by', $event['_sender'], $event['_sender_utf'])) {
+ return $attendee;
+ }
+
+ // try to match by email
+ if ($attendee = self::find_attendee_by_email($itip_attendees, 'email', $event['_sender'], $event['_sender_utf'])) {
+ return $attendee;
+ }
+
+ return null;
+ }
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Mar 30, 1:55 PM (6 d, 8 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18785142
Default Alt Text
D3086.1774878904.diff (10 KB)
Attached To
Mode
D3086: Avoid relying on the sender for REPLY attendee matching.
Attached
Detach File
Event Timeline