From 6c6e7e3aa7935ec513b7e5ea9b53a92b741ecf92 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Fri, 8 Jul 2022 16:33:40 +0200 Subject: Rewrite MAM logic and add MUC MAM --- .../xep/0313_message_archive_management.vala | 146 ++++++++++----------- 1 file changed, 66 insertions(+), 80 deletions(-) (limited to 'xmpp-vala/src/module/xep/0313_message_archive_management.vala') diff --git a/xmpp-vala/src/module/xep/0313_message_archive_management.vala b/xmpp-vala/src/module/xep/0313_message_archive_management.vala index c24c6b04..36a43ac9 100644 --- a/xmpp-vala/src/module/xep/0313_message_archive_management.vala +++ b/xmpp-vala/src/module/xep/0313_message_archive_management.vala @@ -1,11 +1,18 @@ -namespace Xmpp.Xep.MessageArchiveManagement { +using Gee; +using Xmpp.Xep; + +namespace Xmpp.MessageArchiveManagement { public const string NS_URI = "urn:xmpp:mam:2"; public const string NS_URI_2 = "urn:xmpp:mam:2"; public const string NS_URI_1 = "urn:xmpp:mam:1"; -private static string NS_VER(XmppStream stream) { - return stream.get_flag(Flag.IDENTITY).ns_ver; +public class QueryResult { + public bool error { get; set; default=false; } + public bool malformed { get; set; default=false; } + public bool complete { get; set; default=false; } + public string first { get; set; } + public string last { get; set; } } public class Module : XmppStreamModule { @@ -15,54 +22,6 @@ public class Module : XmppStreamModule { private ReceivedPipelineListener received_pipeline_listener = new ReceivedPipelineListener(); - private StanzaNode crate_base_query(XmppStream stream, string? jid, string? queryid, DateTime? start, DateTime? end) { - DataForms.DataForm data_form = new DataForms.DataForm(); - DataForms.DataForm.HiddenField form_type_field = new DataForms.DataForm.HiddenField() { var="FORM_TYPE" }; - form_type_field.set_value_string(NS_VER(stream)); - data_form.add_field(form_type_field); - if (jid != null) { - DataForms.DataForm.Field field = new DataForms.DataForm.Field() { var="with" }; - field.set_value_string(jid); - data_form.add_field(field); - } - if (start != null) { - DataForms.DataForm.Field field = new DataForms.DataForm.Field() { var="start" }; - field.set_value_string(DateTimeProfiles.to_datetime(start)); - data_form.add_field(field); - } - if (end != null) { - DataForms.DataForm.Field field = new DataForms.DataForm.Field() { var="end" }; - field.set_value_string(DateTimeProfiles.to_datetime(end)); - data_form.add_field(field); - } - StanzaNode query_node = new StanzaNode.build("query", NS_VER(stream)).add_self_xmlns().put_node(data_form.get_submit_node()); - if (queryid != null) { - query_node.put_attribute("queryid", queryid); - } - return query_node; - } - - private StanzaNode create_set_rsm_node(string? before_id) { - var before_node = new StanzaNode.build("before", "http://jabber.org/protocol/rsm"); - if (before_id != null) { - before_node.put_node(new StanzaNode.text(before_id)); - } - var max_node = (new StanzaNode.build("max", "http://jabber.org/protocol/rsm")).put_node(new StanzaNode.text("20")); - return (new StanzaNode.build("set", "http://jabber.org/protocol/rsm")).add_self_xmlns() - .put_node(before_node) - .put_node(max_node); - } - - public async Iq.Stanza? query_archive(XmppStream stream, string? jid, string? query_id, DateTime? start_time, string? start_id, DateTime? end_time, string? end_id) { - if (stream.get_flag(Flag.IDENTITY) == null) return null; - - var query_node = crate_base_query(stream, jid, query_id, start_time, end_time); - query_node.put_node(create_set_rsm_node(end_id)); - Iq.Stanza iq = new Iq.Stanza.set(query_node); - - return yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); - } - public override void attach(XmppStream stream) { stream.get_module(MessageModule.IDENTITY).received_pipeline.connect(received_pipeline_listener); stream.stream_negotiated.connect(query_availability); @@ -75,25 +34,6 @@ public class Module : XmppStreamModule { public override string get_ns() { return NS_URI; } public override string get_id() { return IDENTITY.id; } - public async Iq.Stanza? page_through_results(XmppStream stream, string? jid, string? query_id, DateTime? start_time, DateTime? end_time, Iq.Stanza iq) { - - string? complete = iq.stanza.get_deep_attribute("urn:xmpp:mam:2:fin", "complete"); - if (complete == "true") { - return null; - } - string? first = iq.stanza.get_deep_string_content(NS_VER(stream) + ":fin", "http://jabber.org/protocol/rsm" + ":set", "first"); - if (first == null) { - return null; - } - - var query_node = crate_base_query(stream, jid, query_id, start_time, end_time); - query_node.put_node(create_set_rsm_node(first)); - - Iq.Stanza paging_iq = new Iq.Stanza.set(query_node); - - return yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, paging_iq); - } - private async void query_availability(XmppStream stream) { Jid own_jid = stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid; @@ -113,6 +53,52 @@ public class Module : XmppStreamModule { } } + internal StanzaNode create_base_query(XmppStream stream, string ns, string? queryid, Gee.List fields) { + DataForms.DataForm data_form = new DataForms.DataForm(); + + DataForms.DataForm.HiddenField form_type_field = new DataForms.DataForm.HiddenField() { var="FORM_TYPE" }; + form_type_field.set_value_string(NS_VER(stream)); + data_form.add_field(form_type_field); + + foreach (var field in fields) { + data_form.add_field(field); + } + + StanzaNode query_node = new StanzaNode.build("query", NS_VER(stream)).add_self_xmlns().put_node(data_form.get_submit_node()); + if (queryid != null) { + query_node.put_attribute("queryid", queryid); + } + return query_node; + } + + internal async QueryResult query_archive(XmppStream stream, string ns, Jid? mam_server, StanzaNode query_node) { + var res = new QueryResult(); + + if (stream.get_flag(Flag.IDENTITY) == null) { res.error = true; return res; } + + // Build and send query + Iq.Stanza iq = new Iq.Stanza.set(query_node) { to=mam_server }; + + print(@"OUT:\n$(iq.stanza.to_string())\n"); + Iq.Stanza result_iq = yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); + + print(result_iq.stanza.to_string() + "\n"); + + // Parse the response IQ into a QueryResult. + StanzaNode? fin_node = result_iq.stanza.get_subnode("fin", ns); + if (fin_node == null) { print(@"$ns a1\n"); res.malformed = true; return res; } + + StanzaNode? rsm_node = fin_node.get_subnode("set", Xmpp.ResultSetManagement.NS_URI); + if (rsm_node == null) { print("a2\n"); res.malformed = true; return res; } + + res.first = rsm_node.get_deep_string_content("first"); + res.last = rsm_node.get_deep_string_content("last"); + if ((res.first == null) != (res.last == null)) { print("a3\n"); res.malformed = true; } + res.complete = fin_node.get_attribute_bool("complete", false, ns); + + return res; + } + public class ReceivedPipelineListener : StanzaListener { private string[] after_actions_const = {}; @@ -123,19 +109,13 @@ public class ReceivedPipelineListener : StanzaListener { public override async bool run(XmppStream stream, MessageStanza message) { if (stream.get_flag(Flag.IDENTITY) == null) return false; - StanzaNode? message_node = message.stanza.get_deep_subnode(NS_VER(stream) + ":result", "urn:xmpp:forward:0:forwarded", Xmpp.NS_URI + ":message"); + StanzaNode? message_node = message.stanza.get_deep_subnode(NS_VER(stream) + ":result", StanzaForwarding.NS_URI + ":forwarded", Xmpp.NS_URI + ":message"); if (message_node != null) { - // MAM messages must come from our server // TODO or a MUC server - if (!message.from.equals(stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid)) { - warning("Received alleged MAM message from %s, ignoring", message.from.to_string()); - return true; - } - - StanzaNode? forward_node = message.stanza.get_deep_subnode(NS_VER(stream) + ":result", "urn:xmpp:forward:0:forwarded", DelayedDelivery.NS_URI + ":delay"); + StanzaNode? forward_node = message.stanza.get_deep_subnode(NS_VER(stream) + ":result", StanzaForwarding.NS_URI + ":forwarded", DelayedDelivery.NS_URI + ":delay"); DateTime? datetime = DelayedDelivery.get_time_for_node(forward_node); string? mam_id = message.stanza.get_deep_attribute(NS_VER(stream) + ":result", NS_VER(stream) + ":id"); string? query_id = message.stanza.get_deep_attribute(NS_VER(stream) + ":result", NS_VER(stream) + ":queryid"); - message.add_flag(new MessageFlag(datetime, mam_id, query_id)); + message.add_flag(new MessageFlag(message.from, datetime, mam_id, query_id)); message.stanza = message_node; message.rerun_parsing = true; @@ -160,11 +140,13 @@ public class Flag : XmppStreamFlag { public class MessageFlag : Xmpp.MessageFlag { public const string ID = "message_archive_management"; + public Jid sender_jid { get; private set; } public DateTime? server_time { get; private set; } public string? mam_id { get; private set; } public string? query_id { get; private set; } - public MessageFlag(DateTime? server_time, string? mam_id, string? query_id) { + public MessageFlag(Jid sender_jid, DateTime? server_time, string? mam_id, string? query_id) { + this.sender_jid = sender_jid; this.server_time = server_time; this.mam_id = mam_id; this.query_id = query_id; @@ -176,4 +158,8 @@ public class MessageFlag : Xmpp.MessageFlag { public override string get_id() { return ID; } } +private static string NS_VER(XmppStream stream) { + return stream.get_flag(Flag.IDENTITY).ns_ver; } + +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf