diff --git a/crates/common/src/config/scripts.rs b/crates/common/src/config/scripts.rs index 1e6b25df..aa9d7448 100644 --- a/crates/common/src/config/scripts.rs +++ b/crates/common/src/config/scripts.rs @@ -11,9 +11,12 @@ use sieve::{Compiler, Runtime, Sieve, compiler::grammar::Capability}; use store::Stores; use utils::config::Config; -use crate::scripts::{ - functions::{register_functions_trusted, register_functions_untrusted}, - plugins::RegisterSievePlugins, +use crate::{ + VERSION_PUBLIC, + scripts::{ + functions::{register_functions_trusted, register_functions_untrusted}, + plugins::RegisterSievePlugins, + }, }; use super::{if_block::IfBlock, smtp::SMTP_RCPT_TO_VARS, tokenizer::TokenMap}; @@ -182,8 +185,8 @@ impl Scripting { .unwrap_or("Auto: ") .to_string(), ) - .with_env_variable("name", "Stalwart Mail Server") - .with_env_variable("version", env!("CARGO_PKG_VERSION")) + .with_env_variable("name", "Stalwart Server") + .with_env_variable("version", VERSION_PUBLIC) .with_env_variable("location", "MS") .with_env_variable("phase", "during"); diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs index ba729acb..60ad883c 100644 --- a/crates/common/src/lib.rs +++ b/crates/common/src/lib.rs @@ -71,8 +71,12 @@ pub mod telemetry; pub use psl; -pub static USER_AGENT: &str = concat!("Stalwart/", env!("CARGO_PKG_VERSION"),); -pub static DAEMON_NAME: &str = concat!("Stalwart Mail Server v", env!("CARGO_PKG_VERSION"),); +pub static VERSION_PRIVATE: &str = env!("CARGO_PKG_VERSION"); +pub static VERSION_PUBLIC: &str = "1.0.0"; + +pub static USER_AGENT: &str = "Stalwart/1.0.0"; +pub static DAEMON_NAME: &str = concat!("Stalwart v", env!("CARGO_PKG_VERSION"),); +pub static PROD_ID: &str = "-//Stalwart Labs Ltd.//Stalwart Server//EN"; pub const LONG_1D_SLUMBER: Duration = Duration::from_secs(60 * 60 * 24); pub const LONG_1Y_SLUMBER: Duration = Duration::from_secs(60 * 60 * 24 * 365); @@ -253,9 +257,22 @@ pub struct DavResource { pub document_id: u32, pub parent_id: Option, pub name: String, - pub size: u32, - pub hierarchy_sequence: u32, - pub is_container: bool, + pub data: DavResourceMetadata, +} + +#[derive(Debug, Default)] +pub enum DavResourceMetadata { + File { + size: u32, + hierarchy_sequence: u32, + is_container: bool, + }, + Calendar { + start: i64, + duration: u32, + }, + #[default] + None, } #[derive(Clone, Default)] @@ -506,7 +523,7 @@ impl DavResources { } pub fn format_resource(&self, resource: &DavResource) -> String { - if resource.is_container { + if resource.is_container() { format!("{}{}/", self.base_path, resource.name) } else { format!("{}{}", self.base_path, resource.name) @@ -522,6 +539,46 @@ impl DavResources { } } +impl DavResource { + pub fn event_time_range(&self) -> Option<(i64, i64)> { + match &self.data { + DavResourceMetadata::Calendar { start, duration } => { + Some((*start, *start + *duration as i64)) + } + _ => None, + } + } + + pub fn is_container(&self) -> bool { + match &self.data { + DavResourceMetadata::File { is_container, .. } => *is_container, + _ => self.parent_id.is_none(), + } + } + + pub fn size(&self) -> u32 { + match &self.data { + DavResourceMetadata::File { size, .. } => *size, + _ => 0, + } + } + + pub fn hierarchy_sequence(&self) -> u32 { + match &self.data { + DavResourceMetadata::File { + hierarchy_sequence, .. + } => *hierarchy_sequence, + _ => { + if self.parent_id.is_none() { + 0 + } else { + 1 + } + } + } + } +} + impl IdBimapItem for DavResource { fn id(&self) -> &u32 { &self.document_id diff --git a/crates/common/src/manager/boot.rs b/crates/common/src/manager/boot.rs index 5fe6efd7..92da2351 100644 --- a/crates/common/src/manager/boot.rs +++ b/crates/common/src/manager/boot.rs @@ -52,7 +52,7 @@ pub struct IpcReceivers { } const HELP: &str = concat!( - "Stalwart Mail Server v", + "Stalwart Server v", env!("CARGO_PKG_VERSION"), r#" diff --git a/crates/common/src/manager/console.rs b/crates/common/src/manager/console.rs index 59b2f6e9..c0bd92d8 100644 --- a/crates/common/src/manager/console.rs +++ b/crates/common/src/manager/console.rs @@ -16,7 +16,7 @@ use store::{ }; const HELP: &str = concat!( - "Stalwart Mail Server v", + "Stalwart Server v", env!("CARGO_PKG_VERSION"), r#" Data Store CLI diff --git a/crates/common/src/sharing/document.rs b/crates/common/src/sharing/document.rs index a2073416..49bed421 100644 --- a/crates/common/src/sharing/document.rs +++ b/crates/common/src/sharing/document.rs @@ -17,9 +17,10 @@ impl Server { access_token: &AccessToken, to_account_id: u32, to_collection: Collection, - check_acls: impl Into>, + check_acls: impl IntoIterator, + match_any: bool, ) -> trc::Result { - let check_acls = check_acls.into(); + let check_acls = Bitmap::::from_iter(check_acls); let mut document_ids = RoaringBitmap::new(); let to_collection = u8::from(to_collection); for &grant_account_id in [access_token.primary_id] @@ -39,9 +40,8 @@ impl Server { .caused_by(trc::location!())? { let mut acls = Bitmap::::from(acl_item.permissions); - acls.intersection(&check_acls); - if !acls.is_empty() { + if acls == check_acls || (match_any && !acls.is_empty()) { document_ids.insert(acl_item.to_document_id); } } @@ -50,26 +50,6 @@ impl Server { Ok(document_ids) } - pub async fn owned_or_shared_containers( - &self, - access_token: &AccessToken, - account_id: u32, - collection: Collection, - check_acls: impl Into>, - ) -> trc::Result { - let check_acls = check_acls.into(); - let mut document_ids = self - .get_document_ids(account_id, collection) - .await? - .unwrap_or_default(); - if !document_ids.is_empty() && !access_token.is_member(account_id) { - document_ids &= self - .shared_containers(access_token, account_id, collection, check_acls) - .await?; - } - Ok(document_ids) - } - pub async fn has_access_to_document( &self, access_token: &AccessToken, diff --git a/crates/common/src/storage/index.rs b/crates/common/src/storage/index.rs index fb92877d..cf84b7c4 100644 --- a/crates/common/src/storage/index.rs +++ b/crates/common/src/storage/index.rs @@ -130,6 +130,12 @@ impl From for IndexItem<'_> { } } +impl From for IndexItem<'_> { + fn from(value: i64) -> Self { + IndexItem::LongInt(value.to_be_bytes()) + } +} + impl<'x> From<&'x [u8]> for IndexItem<'x> { fn from(value: &'x [u8]) -> Self { IndexItem::Slice(value) diff --git a/crates/imap/src/op/capability.rs b/crates/imap/src/op/capability.rs index a811ecee..05f414eb 100644 --- a/crates/imap/src/op/capability.rs +++ b/crates/imap/src/op/capability.rs @@ -64,9 +64,7 @@ impl Session { .with_tag(request.tag) .serialize( concat!( - "* ID (\"name\" \"Stalwart IMAP\" \"version\" \"", - env!("CARGO_PKG_VERSION"), - "\" \"vendor\" \"Stalwart Labs Ltd.\" ", + "* ID (\"name\" \"Stalwart\" \"version\" \"1.0.0\" \"vendor\" \"Stalwart Labs Ltd.\" ", "\"support-url\" \"https://stalw.art\")\r\n" ) .as_bytes() diff --git a/crates/imap/src/op/logout.rs b/crates/imap/src/op/logout.rs index 9193b20c..8905de96 100644 --- a/crates/imap/src/op/logout.rs +++ b/crates/imap/src/op/logout.rs @@ -14,15 +14,8 @@ impl Session { pub async fn handle_logout(&mut self, request: Request) -> trc::Result<()> { let op_start = Instant::now(); - let mut response = StatusResponse::bye( - concat!( - "Stalwart IMAP4rev2 v", - env!("CARGO_PKG_VERSION"), - " bids you farewell." - ) - .to_string(), - ) - .into_bytes(); + let mut response = + StatusResponse::bye("Stalwart IMAP4rev2 bids you farewell.".to_string()).into_bytes(); trc::event!( Imap(trc::ImapEvent::Logout), diff --git a/crates/jmap-proto/src/request/capability.rs b/crates/jmap-proto/src/request/capability.rs index 2603d172..3fe83746 100644 --- a/crates/jmap-proto/src/request/capability.rs +++ b/crates/jmap-proto/src/request/capability.rs @@ -300,7 +300,7 @@ impl Account { impl Default for SieveSessionCapabilities { fn default() -> Self { Self { - implementation: concat!("Stalwart JMAP v", env!("CARGO_PKG_VERSION"),), + implementation: "Stalwart v1.0.0", } } } diff --git a/crates/jmap/src/api/session.rs b/crates/jmap/src/api/session.rs index 9e6114cd..c914a70f 100644 --- a/crates/jmap/src/api/session.rs +++ b/crates/jmap/src/api/session.rs @@ -48,7 +48,13 @@ impl SessionHandler for Server { let is_personal = !access_token.is_member(*id); let is_readonly = is_personal && self - .shared_containers(&access_token, *id, Collection::Mailbox, Acl::AddItems) + .shared_containers( + &access_token, + *id, + Collection::Mailbox, + [Acl::AddItems], + false, + ) .await .caused_by(trc::location!())? .is_empty(); diff --git a/crates/managesieve/src/op/logout.rs b/crates/managesieve/src/op/logout.rs index 73b3c7c0..7ce8bc08 100644 --- a/crates/managesieve/src/op/logout.rs +++ b/crates/managesieve/src/op/logout.rs @@ -16,11 +16,6 @@ impl Session { Elapsed = trc::Value::Duration(0) ); - Ok(StatusResponse::ok(concat!( - "Stalwart ManageSieve v", - env!("CARGO_PKG_VERSION"), - " bids you farewell." - )) - .into_bytes()) + Ok(StatusResponse::ok("Stalwart ManageSieve bids you farewell.").into_bytes()) } } diff --git a/crates/pop3/src/protocol/response.rs b/crates/pop3/src/protocol/response.rs index 425a5a2b..bfd3eb07 100644 --- a/crates/pop3/src/protocol/response.rs +++ b/crates/pop3/src/protocol/response.rs @@ -114,7 +114,7 @@ impl Response { "EXPIRE NEVER", "UIDL", "UTF8", - "IMPLEMENTATION Stalwart Mail Server", + "IMPLEMENTATION Stalwart Server", ] { buf.extend_from_slice(capa.as_bytes()); buf.extend_from_slice(b"\r\n"); @@ -201,7 +201,7 @@ mod tests { "EXPIRE NEVER\r\n", "UIDL\r\n", "UTF8\r\n", - "IMPLEMENTATION Stalwart Mail Server\r\n.\r\n" + "IMPLEMENTATION Stalwart Server\r\n.\r\n" ), ), (