Import upstream v0.16.22, stripped
Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use crate::scheduling::{
|
||||
InstanceId, ItipError, ItipMessage, ItipSummary,
|
||||
attendee::attendee_decline,
|
||||
itip::{itip_add_tz, itip_build_envelope},
|
||||
snapshot::itip_snapshot,
|
||||
};
|
||||
use ahash::AHashSet;
|
||||
use calcard::{
|
||||
common::PartialDateTime,
|
||||
icalendar::{
|
||||
ICalendar, ICalendarComponent, ICalendarComponentType, ICalendarMethod,
|
||||
ICalendarParticipationStatus, ICalendarProperty, ICalendarStatus, ICalendarValue,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn itip_cancel(
|
||||
ical: &ICalendar,
|
||||
account_emails: &[String],
|
||||
is_deletion: bool,
|
||||
) -> Result<ItipMessage<ICalendar>, ItipError> {
|
||||
// Prepare iTIP message
|
||||
let itip = itip_snapshot(ical, account_emails, false)?;
|
||||
let dt_stamp = PartialDateTime::now();
|
||||
let mut message = ICalendar {
|
||||
components: Vec::with_capacity(2),
|
||||
};
|
||||
|
||||
if itip.organizer.email.is_local {
|
||||
// Send cancel message
|
||||
let mut comp = itip_build_envelope(ICalendarMethod::Cancel);
|
||||
comp.component_ids.push(1);
|
||||
message.components.push(comp);
|
||||
|
||||
// Fetch guest emails
|
||||
let mut recipients = AHashSet::new();
|
||||
let mut cancel_guests = AHashSet::new();
|
||||
let mut component_type = &ICalendarComponentType::VEvent;
|
||||
let mut sequence = 0;
|
||||
for (instance_id, comp) in &itip.components {
|
||||
component_type = &comp.comp.component_type;
|
||||
for attendee in &comp.attendees {
|
||||
if attendee.send_update_messages() {
|
||||
recipients.insert(attendee.email.email.clone());
|
||||
}
|
||||
cancel_guests.insert(&attendee.email);
|
||||
}
|
||||
|
||||
// Increment sequence if needed
|
||||
if instance_id == &InstanceId::Main {
|
||||
sequence = comp.sequence.unwrap_or_default() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if !recipients.is_empty() && component_type != &ICalendarComponentType::VFreebusy {
|
||||
let instance = itip.main_instance_or_default();
|
||||
message.components.push(build_cancel_component(
|
||||
instance.comp,
|
||||
sequence,
|
||||
dt_stamp,
|
||||
&[],
|
||||
));
|
||||
|
||||
// Add timezones
|
||||
itip_add_tz(&mut message, ical);
|
||||
|
||||
Ok(ItipMessage {
|
||||
to: recipients.into_iter().collect(),
|
||||
summary: ItipSummary::Cancel(instance.build_summary(None, &[])),
|
||||
from: itip.organizer.email.email,
|
||||
from_organizer: true,
|
||||
message,
|
||||
})
|
||||
} else {
|
||||
Err(ItipError::NothingToSend)
|
||||
}
|
||||
} else {
|
||||
// Send decline message
|
||||
message
|
||||
.components
|
||||
.push(itip_build_envelope(ICalendarMethod::Reply));
|
||||
|
||||
// Decline attendance for all instances that have local attendees
|
||||
let mut mail_from = None;
|
||||
let mut email_rcpt = AHashSet::new();
|
||||
for (instance_id, comp) in &itip.components {
|
||||
if let Some((cancel_comp, attendee_email)) = attendee_decline(
|
||||
instance_id,
|
||||
&itip,
|
||||
comp,
|
||||
&dt_stamp,
|
||||
&mut email_rcpt,
|
||||
is_deletion,
|
||||
) {
|
||||
// Add cancel component
|
||||
let comp_id = message.components.len() as u32;
|
||||
message.components[0].component_ids.push(comp_id);
|
||||
message.components.push(cancel_comp);
|
||||
mail_from = Some(&attendee_email.email);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(from) = mail_from {
|
||||
// Add timezone information if needed
|
||||
itip_add_tz(&mut message, ical);
|
||||
|
||||
email_rcpt.insert(&itip.organizer.email.email);
|
||||
|
||||
Ok(ItipMessage {
|
||||
from: from.to_string(),
|
||||
from_organizer: false,
|
||||
to: email_rcpt.into_iter().map(|e| e.to_string()).collect(),
|
||||
summary: ItipSummary::Rsvp {
|
||||
part_stat: ICalendarParticipationStatus::Declined,
|
||||
current: itip.main_instance_or_default().build_summary(None, &[]),
|
||||
},
|
||||
message,
|
||||
})
|
||||
} else {
|
||||
Err(ItipError::NothingToSend)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn build_cancel_component(
|
||||
component: &ICalendarComponent,
|
||||
sequence: i64,
|
||||
dt_stamp: PartialDateTime,
|
||||
attendees: &[&str],
|
||||
) -> ICalendarComponent {
|
||||
let mut cancel_comp = ICalendarComponent {
|
||||
component_type: component.component_type.clone(),
|
||||
entries: Vec::with_capacity(7),
|
||||
component_ids: vec![],
|
||||
};
|
||||
cancel_comp.add_property(
|
||||
ICalendarProperty::Status,
|
||||
ICalendarValue::Status(ICalendarStatus::Cancelled),
|
||||
);
|
||||
cancel_comp.add_dtstamp(dt_stamp);
|
||||
cancel_comp.add_sequence(sequence);
|
||||
cancel_comp.entries.extend(
|
||||
component
|
||||
.entries
|
||||
.iter()
|
||||
.filter(|e| match e.name {
|
||||
ICalendarProperty::Organizer
|
||||
| ICalendarProperty::Uid
|
||||
| ICalendarProperty::Summary
|
||||
| ICalendarProperty::Dtstart
|
||||
| ICalendarProperty::Dtend
|
||||
| ICalendarProperty::Duration
|
||||
| ICalendarProperty::Due
|
||||
| ICalendarProperty::RecurrenceId
|
||||
| ICalendarProperty::Created
|
||||
| ICalendarProperty::LastModified
|
||||
| ICalendarProperty::Description
|
||||
| ICalendarProperty::Location => true,
|
||||
ICalendarProperty::Attendee => {
|
||||
attendees.is_empty()
|
||||
|| e.values
|
||||
.first()
|
||||
.and_then(|v| v.as_text())
|
||||
.is_some_and(|email| {
|
||||
attendees.iter().any(|attendee| {
|
||||
email
|
||||
.strip_suffix(attendee)
|
||||
.is_some_and(|v| v.ends_with(':') || v.is_empty())
|
||||
})
|
||||
})
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
.cloned(),
|
||||
);
|
||||
|
||||
cancel_comp
|
||||
}
|
||||
Reference in New Issue
Block a user