diff --git a/parsers/ChangeLog b/parsers/ChangeLog index 8f0f9619..9908c723 100644 --- a/parsers/ChangeLog +++ b/parsers/ChangeLog @@ -38,6 +38,7 @@ XXXX-YY-ZZ RELEASER the optional nickname instead of a String (!485) * New parsers/serialisers: - Stream Features (RFC 6120) (!400) + - Spam Reporting (XEP-0377) (!506) - Extensible SASL Profile (XEP-0388) - SASL Channel-Binding Type Capability (XEP-0440) - Stream Limits Advertisement (XEP-0478) diff --git a/parsers/doap.xml b/parsers/doap.xml index e3fc1eb0..dca2e434 100644 --- a/parsers/doap.xml +++ b/parsers/doap.xml @@ -578,6 +578,14 @@ 0.16.0 + + + + complete + 0.3.1 + NEXT + + diff --git a/parsers/src/lib.rs b/parsers/src/lib.rs index 9e9a9fdb..8b1607d3 100644 --- a/parsers/src/lib.rs +++ b/parsers/src/lib.rs @@ -257,6 +257,9 @@ pub mod mix; /// XEP-0373: OpenPGP for XMPP pub mod openpgp; +/// XEP-0377: Spam Reporting +pub mod spam_reporting; + /// XEP-0380: Explicit Message Encryption pub mod eme; diff --git a/parsers/src/ns.rs b/parsers/src/ns.rs index da2abc5f..ba5552a5 100644 --- a/parsers/src/ns.rs +++ b/parsers/src/ns.rs @@ -265,6 +265,9 @@ pub const OX: &str = "urn:xmpp:openpgp:0"; /// XEP-0373: OpenPGP for XMPP pub const OX_PUBKEYS: &str = "urn:xmpp:openpgp:0:public-keys"; +/// XEP-0377: Spam Reporting +pub const SPAM_REPORTING: &str = "urn:xmpp:reporting:1"; + /// XEP-0380: Explicit Message Encryption pub const EME: &str = "urn:xmpp:eme:0"; diff --git a/parsers/src/spam_reporting.rs b/parsers/src/spam_reporting.rs new file mode 100644 index 00000000..42214c23 --- /dev/null +++ b/parsers/src/spam_reporting.rs @@ -0,0 +1,102 @@ +// Copyright (c) 2024 Emmanuel Gil Peyrot +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +use xso::{AsXml, FromXml}; + +use crate::ns; +use crate::stanza_id::StanzaId; +use alloc::collections::BTreeMap; + +generate_attribute!( + /// The possible reasons for a report. + Reason, "reason", { + /// Used for reporting a JID that is sending unwanted messages. + Spam => "urn:xmpp:reporting:spam", + + /// Used for reporting general abuse. + Abuse => "urn:xmpp:reporting:abuse", + } +); + +type Lang = String; + +/// Represents an abuse or spam report. +#[derive(FromXml, AsXml, Debug, Clone, PartialEq)] +#[xml(namespace = ns::SPAM_REPORTING, name = "report")] +pub struct Report { + /// The reason for this report. + #[xml(attribute)] + reason: Reason, + + /// Ids of the incriminated stanzas. + #[xml(child(n = ..))] + stanza_ids: Vec, + + /// Some text explaining the reason for this report. + #[xml(extract(n = .., name = "text", fields( + attribute(name = "xml:lang", type_ = Lang), + text(type_ = String) + )))] + texts: BTreeMap, +} + +#[cfg(test)] +mod tests { + use super::*; + use jid::Jid; + use minidom::Element; + + #[cfg(target_pointer_width = "32")] + #[test] + fn test_size() { + assert_size!(Reason, 1); + assert_size!(Report, 28); + } + + #[cfg(target_pointer_width = "64")] + #[test] + fn test_size() { + assert_size!(Reason, 1); + assert_size!(Report, 56); + } + + #[test] + // Comes from https://xmpp.org/extensions/xep-0377.html#example-2 + fn test_example_1() { + let elem: Element = + "" + .parse() + .unwrap(); + let report = Report::try_from(elem).unwrap(); + assert_eq!(report.reason, Reason::Spam); + assert!(report.stanza_ids.is_empty()); + assert!(report.texts.is_empty()); + } + + #[test] + // Comes from https://xmpp.org/extensions/xep-0377.html#example-5 + fn test_example_5() { + let elem: Element = " + + + Never came trouble to my house like this. + " + .parse() + .unwrap(); + let report = Report::try_from(elem).unwrap(); + let romeo = Jid::new("romeo@example.net").unwrap(); + assert_eq!(report.reason, Reason::Spam); + assert_eq!(report.stanza_ids.len(), 2); + assert_eq!(report.stanza_ids[0].by, romeo); + assert_eq!(report.stanza_ids[0].id, "28482-98726-73623"); + assert_eq!(report.stanza_ids[1].by, romeo); + assert_eq!(report.stanza_ids[1].id, "38383-38018-18385"); + assert_eq!( + report.texts["en"], + "Never came trouble to my house like this." + ); + } +}