diff --git a/crates/groupware/src/scheduling/itip.rs b/crates/groupware/src/scheduling/itip.rs index 3263c34a..46bb33ca 100644 --- a/crates/groupware/src/scheduling/itip.rs +++ b/crates/groupware/src/scheduling/itip.rs @@ -67,49 +67,54 @@ pub(crate) fn itip_export_component( comp.add_uid(uid); for (entry_id, entry) in component.entries.iter().enumerate() { - match &entry.name { - ICalendarProperty::Organizer | ICalendarProperty::Attendee => match &export_as { - ItipExportAs::Organizer(partstat) => { - let mut new_entry = ICalendarEntry { - name: entry.name.clone(), - params: Vec::with_capacity(entry.params.len()), - values: entry.values.clone(), - }; - let mut has_partstat = false; - let mut rsvp = true; + match (&entry.name, &export_as) { + ( + ICalendarProperty::Organizer | ICalendarProperty::Attendee, + ItipExportAs::Organizer(partstat), + ) => { + let mut new_entry = ICalendarEntry { + name: entry.name.clone(), + params: Vec::with_capacity(entry.params.len()), + values: entry.values.clone(), + }; + let mut has_partstat = false; + let mut rsvp = true; - for entry in &entry.params { - match entry { - ICalendarParameter::ScheduleStatus(_) - | ICalendarParameter::ScheduleAgent(_) - | ICalendarParameter::ScheduleForceSend(_) => {} - _ => { - match entry { - ICalendarParameter::Rsvp(false) => { - rsvp = false; - } - ICalendarParameter::Partstat(_) => { - has_partstat = true; - } - _ => {} + for entry in &entry.params { + match entry { + ICalendarParameter::ScheduleStatus(_) + | ICalendarParameter::ScheduleAgent(_) + | ICalendarParameter::ScheduleForceSend(_) => {} + _ => { + match entry { + ICalendarParameter::Rsvp(false) => { + rsvp = false; } - - new_entry.params.push(entry.clone()) + ICalendarParameter::Partstat(_) => { + has_partstat = true; + } + _ => {} } + + new_entry.params.push(entry.clone()) } } - - if !has_partstat && rsvp && entry.name == ICalendarProperty::Attendee { - new_entry - .params - .push(ICalendarParameter::Partstat((*partstat).clone())); - } - - comp.entries.push(new_entry); } - ItipExportAs::Attendee(attendee_entry_ids) - if attendee_entry_ids.contains(&(entry_id as u16)) - || entry.name == ICalendarProperty::Organizer => + + if !has_partstat && rsvp && entry.name == ICalendarProperty::Attendee { + new_entry + .params + .push(ICalendarParameter::Partstat((*partstat).clone())); + } + + comp.entries.push(new_entry); + } + ( + ICalendarProperty::Organizer | ICalendarProperty::Attendee, + ItipExportAs::Attendee(attendee_entry_ids), + ) => { + if attendee_entry_ids.contains(&(entry_id as u16)) + || entry.name == ICalendarProperty::Organizer { comp.entries.push(ICalendarEntry { name: entry.name.clone(), @@ -129,26 +134,36 @@ pub(crate) fn itip_export_component( values: entry.values.clone(), }); } - _ => {} - }, - ICalendarProperty::RequestStatus - | ICalendarProperty::Dtstamp - | ICalendarProperty::Sequence - | ICalendarProperty::Uid => {} - _ => { - if matches!(export_as, ItipExportAs::Organizer(_)) - || matches!(entry.name, ICalendarProperty::RecurrenceId) - || (is_todo - && matches!( - entry.name, - ICalendarProperty::Status - | ICalendarProperty::PercentComplete - | ICalendarProperty::Completed - )) - { - comp.entries.push(entry.clone()); - } } + ( + ICalendarProperty::RequestStatus + | ICalendarProperty::Dtstamp + | ICalendarProperty::Sequence + | ICalendarProperty::Uid, + _, + ) => {} + (_, ItipExportAs::Organizer(_)) + | ( + ICalendarProperty::RecurrenceId + | ICalendarProperty::Dtstart + | ICalendarProperty::Dtend + | ICalendarProperty::Duration + | ICalendarProperty::Due + | ICalendarProperty::Description + | ICalendarProperty::Summary, + _, + ) => { + comp.entries.push(entry.clone()); + } + ( + ICalendarProperty::Status + | ICalendarProperty::PercentComplete + | ICalendarProperty::Completed, + _, + ) if is_todo => { + comp.entries.push(entry.clone()); + } + _ => {} } } diff --git a/tests/resources/itip/rfc5546_event_single.txt b/tests/resources/itip/rfc5546_event_single.txt index bb7bb1b4..aaab7981 100644 --- a/tests/resources/itip/rfc5546_event_single.txt +++ b/tests/resources/itip/rfc5546_event_single.txt @@ -122,6 +122,9 @@ METHOD:REPLY PRODID:-//Stalwart Labs LLC//Stalwart Server//EN VERSION:2.0 BEGIN:VEVENT +SUMMARY:Conference +DTEND:19970701T2100000Z +DTSTART:19970701T200000Z ATTENDEE;RSVP=TRUE;CUTYPE=INDIVIDUAL;CN=B;PARTSTAT=ACCEPTED:mailto:b@example .com ORGANIZER:mailto:a@example.com @@ -283,6 +286,9 @@ METHOD:REPLY PRODID:-//Stalwart Labs LLC//Stalwart Server//EN VERSION:2.0 BEGIN:VEVENT +SUMMARY:Phone Conference +DTEND:19970701T190000Z +DTSTART:19970701T180000Z ATTENDEE;PARTSTAT=DELEGATED;DELEGATED-TO="mailto:e@example.com":mailto:c@ex ample.com ATTENDEE;RSVP=TRUE;DELEGATED-FROM="mailto:c@example.com":mailto:e@example.c @@ -419,6 +425,9 @@ METHOD:REPLY PRODID:-//Stalwart Labs LLC//Stalwart Server//EN VERSION:2.0 BEGIN:VEVENT +SUMMARY:Phone Conference +DTEND:19970701T190000Z +DTSTART:19970701T180000Z ATTENDEE;PARTSTAT=DELEGATED;DELEGATED-TO="mailto:e@example.com":mailto:c@ex ample.com ATTENDEE;RSVP=TRUE;DELEGATED-FROM="mailto:c@example.com";PARTSTAT=ACCEPTED: @@ -523,6 +532,9 @@ METHOD:REPLY PRODID:-//Stalwart Labs LLC//Stalwart Server//EN VERSION:2.0 BEGIN:VEVENT +SUMMARY:Phone Conference +DTEND:19970701T190000Z +DTSTART:19970701T180000Z ATTENDEE;PARTSTAT=DELEGATED;DELEGATED-TO="mailto:e@example.com":mailto:c@ex ample.com ATTENDEE;RSVP=TRUE;DELEGATED-FROM="mailto:c@example.com";PARTSTAT=DECLINED: diff --git a/tests/resources/itip/rfc5546_todo.txt b/tests/resources/itip/rfc5546_todo.txt index db578403..8abde70e 100644 --- a/tests/resources/itip/rfc5546_todo.txt +++ b/tests/resources/itip/rfc5546_todo.txt @@ -107,6 +107,8 @@ PRODID:-//Stalwart Labs LLC//Stalwart Server//EN VERSION:2.0 BEGIN:VTODO STATUS:IN-PROCESS +DUE:19970722T170000Z +DTSTART:19970701T170000Z ATTENDEE;PARTSTAT=ACCEPTED:mailto:b@example.com ORGANIZER:mailto:a@example.com UID:calsrv.example.com-873970198738777-00@example.com @@ -175,6 +177,8 @@ VERSION:2.0 BEGIN:VTODO PERCENT-COMPLETE:75 STATUS:IN-PROCESS +DUE:19970722T170000Z +DTSTART:19970701T170000Z ATTENDEE;PARTSTAT=IN-PROCESS:mailto:b@example.com ORGANIZER:mailto:a@example.com UID:calsrv.example.com-873970198738777-00@example.com @@ -240,6 +244,8 @@ METHOD:REPLY PRODID:-//Stalwart Labs LLC//Stalwart Server//EN VERSION:2.0 BEGIN:VTODO +DUE:19970722T170000Z +DTSTART:19970701T170000Z ATTENDEE;PARTSTAT=COMPLETED:mailto:d@example.com ORGANIZER:mailto:a@example.com UID:calsrv.example.com-873970198738777-00@example.com diff --git a/tests/resources/itip/rfc6638_recurring.txt b/tests/resources/itip/rfc6638_recurring.txt index c336f566..7627b74f 100644 --- a/tests/resources/itip/rfc6638_recurring.txt +++ b/tests/resources/itip/rfc6638_recurring.txt @@ -188,6 +188,9 @@ METHOD:REPLY PRODID:-//Stalwart Labs LLC//Stalwart Server//EN VERSION:2.0 BEGIN:VEVENT +SUMMARY:Review Internet-Draft +DTEND;TZID=America/Montreal:20090601T160000 +DTSTART;TZID=America/Montreal:20090601T150000 ATTENDEE;CN="Bernard Desruisseaux";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED;ROLE= REQ-PARTICIPANT;RSVP=TRUE:mailto:bernard@example.net ORGANIZER;CN="Cyrus Daboo":mailto:cyrus@example.com @@ -197,6 +200,9 @@ SEQUENCE:1 REQUEST-STATUS:2.0;Success END:VEVENT BEGIN:VEVENT +SUMMARY:Review Internet-Draft +DTEND;TZID=America/Montreal:20090602T160000 +DTSTART;TZID=America/Montreal:20090602T150000 ATTENDEE;CN="Bernard Desruisseaux";CUTYPE=INDIVIDUAL;PARTSTAT=DECLINED;ROLE= REQ-PARTICIPANT;RSVP=TRUE:mailto:bernard@example.net ORGANIZER;CN="Cyrus Daboo":mailto:cyrus@example.com diff --git a/tests/resources/itip/rfc6638_single.txt b/tests/resources/itip/rfc6638_single.txt index 13665ec5..91468201 100644 --- a/tests/resources/itip/rfc6638_single.txt +++ b/tests/resources/itip/rfc6638_single.txt @@ -173,6 +173,9 @@ METHOD:REPLY PRODID:-//Stalwart Labs LLC//Stalwart Server//EN VERSION:2.0 BEGIN:VEVENT +SUMMARY:Lunch +DTEND:20090602T170000Z +DTSTART:20090602T160000Z ATTENDEE;CN="Wilfredo Sanchez Vega";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED;ROLE= REQ-PARTICIPANT;RSVP=TRUE:mailto:wilfredo@example.com ORGANIZER;CN="Cyrus Daboo":mailto:cyrus@example.com