diff options
author | fiaxh <git@lightrise.org> | 2024-11-02 22:24:59 +0100 |
---|---|---|
committer | fiaxh <git@lightrise.org> | 2024-11-15 14:40:08 -0600 |
commit | 79f792e090330a05753f9edb27332a946eb0840d (patch) | |
tree | 5a6f1ad3ac0af0beea44ca9e83e7a9b052263025 /xmpp-vala/src/module/xep/0447_stateless_file_sharing.vala | |
parent | aaf4542e6208460c305db4be36b15dc832ddc95a (diff) | |
download | dino-79f792e090330a05753f9edb27332a946eb0840d.tar.gz dino-79f792e090330a05753f9edb27332a946eb0840d.zip |
Fix and improve stateless file-sharing
Diffstat (limited to 'xmpp-vala/src/module/xep/0447_stateless_file_sharing.vala')
-rw-r--r-- | xmpp-vala/src/module/xep/0447_stateless_file_sharing.vala | 267 |
1 files changed, 82 insertions, 185 deletions
diff --git a/xmpp-vala/src/module/xep/0447_stateless_file_sharing.vala b/xmpp-vala/src/module/xep/0447_stateless_file_sharing.vala index 285bfe78..c63f7ea6 100644 --- a/xmpp-vala/src/module/xep/0447_stateless_file_sharing.vala +++ b/xmpp-vala/src/module/xep/0447_stateless_file_sharing.vala @@ -1,225 +1,122 @@ +using Gee; using Xmpp; namespace Xmpp.Xep.StatelessFileSharing { + public const string NS_URI = "urn:xmpp:sfs:0"; - public const string STANZA_NAME = "file-transfer"; + public static Gee.List<FileShare> get_file_shares(MessageStanza message) { + var ret = new ArrayList<FileShare>(); + foreach (StanzaNode file_sharing_node in message.stanza.get_subnodes("file-sharing", NS_URI)) { + var metadata = Xep.FileMetadataElement.get_file_metadata(file_sharing_node); + if (metadata == null) continue; - public interface SfsSource: Object { - public abstract string type(); - public abstract string serialize(); - - public abstract StanzaNode to_stanza_node(); - } - - public class HttpSource: Object, SfsSource { - public string url; + var sources_node = message.stanza.get_subnode("sources", NS_URI); - public const string HTTP_NS_URI = "http://jabber.org/protocol/url-data"; - public const string HTTP_STANZA_NAME = "url-data"; - public const string HTTP_URL_ATTRIBUTE = "target"; - public const string SOURCE_TYPE = "http"; - - public string type() { - return SOURCE_TYPE; + ret.add(new FileShare() { + id = file_sharing_node.get_attribute("id", NS_URI), + metadata = Xep.FileMetadataElement.get_file_metadata(file_sharing_node), + sources = sources_node != null ? get_sources(sources_node) : null + }); } - public string serialize() { - return this.to_stanza_node().to_xml(); - } + if (ret.size == 0) return null; - public StanzaNode to_stanza_node() { - StanzaNode node = new StanzaNode.build(HTTP_STANZA_NAME, HTTP_NS_URI).add_self_xmlns(); - node.put_attribute(HTTP_URL_ATTRIBUTE, this.url); - return node; - } + return ret; + } - public static async HttpSource deserialize(string data) { - StanzaNode node = yield new StanzaReader.for_string(data).read_stanza_node(); - HttpSource source = HttpSource.from_stanza_node(node); - assert(source != null); - return source; - } + public static Gee.List<SourceAttachment>? get_source_attachments(MessageStanza message) { + Gee.List<StanzaNode> sources_nodes = message.stanza.get_subnodes("sources", NS_URI); + if (sources_nodes.is_empty) return null; - public static HttpSource? from_stanza_node(StanzaNode node) { - string? url = node.get_attribute(HTTP_URL_ATTRIBUTE); - if (url == null) { - return null; - } - HttpSource source = new HttpSource(); - source.url = url; - return source; - } + string? attach_to_id = MessageAttaching.get_attach_to(message.stanza); + if (attach_to_id == null) return null; - public static Gee.List<HttpSource> extract_sources(StanzaNode node) { - Gee.List<HttpSource> sources = new Gee.ArrayList<HttpSource>(); - foreach (StanzaNode http_node in node.get_subnodes(HTTP_STANZA_NAME, HTTP_NS_URI)) { - HttpSource? source = HttpSource.from_stanza_node(http_node); - if (source != null) { - sources.add(source); - } - } - return sources; - } - } + var ret = new ArrayList<SourceAttachment>(); - public class SfsElement { - public Xep.FileMetadataElement.FileMetadata metadata = new Xep.FileMetadataElement.FileMetadata(); - public Gee.List<SfsSource> sources = new Gee.ArrayList<SfsSource>(); - - public static SfsElement? from_stanza_node(StanzaNode node) { - SfsElement element = new SfsElement(); - StanzaNode? metadata_node = node.get_subnode("file", Xep.FileMetadataElement.NS_URI); - if (metadata_node == null) { - return null; - } - Xep.FileMetadataElement.FileMetadata metadata = Xep.FileMetadataElement.FileMetadata.from_stanza_node(metadata_node); - if (metadata == null) { - return null; - } - element.metadata = metadata; - StanzaNode? sources_node = node.get_subnode("sources"); - if (sources_node == null) { - return null; - } - Gee.List<HttpSource> sources = HttpSource.extract_sources(sources_node); - if (sources.is_empty) { - return null; - } - element.sources = sources; - return element; - } - - public StanzaNode to_stanza_node() { - StanzaNode node = new StanzaNode.build(STANZA_NAME, NS_URI).add_self_xmlns(); - node.put_node(this.metadata.to_stanza_node()); - StanzaNode sources_node = new StanzaNode.build("sources", NS_URI); - Gee.List<StanzaNode> sources = new Gee.ArrayList<StanzaNode>(); - foreach (SfsSource source in this.sources) { - sources.add(source.to_stanza_node()); - } - sources_node.sub_nodes = sources; - node.put_node(sources_node); - return node; + foreach (StanzaNode sources_node in sources_nodes) { + ret.add(new SourceAttachment() { + to_message_id = attach_to_id, + to_file_transfer_id = sources_node.get_attribute("id", NS_URI), + sources = get_sources(sources_node) + }); } + return ret; } - public class SfsSourceAttachment { - public string sfs_id; - public Gee.List<SfsSource> sources = new Gee.ArrayList<SfsSource>(); - - public const string ATTACHMENT_NS_URI = "urn:xmpp:message-attaching:1"; - public const string ATTACH_TO_STANZA_NAME = "attach-to"; - public const string SOURCES_STANZA_NAME = "sources"; - public const string ID_ATTRIBUTE_NAME = "id"; - - - public static SfsSourceAttachment? from_message_stanza(MessageStanza stanza) { - StanzaNode? attach_to = stanza.stanza.get_subnode(ATTACH_TO_STANZA_NAME, ATTACHMENT_NS_URI); - StanzaNode? sources = stanza.stanza.get_subnode(SOURCES_STANZA_NAME, NS_URI); - if (attach_to == null || sources == null) { - return null; - } - string? id = attach_to.get_attribute(ID_ATTRIBUTE_NAME, ATTACHMENT_NS_URI); - if (id == null) { - return null; - } - SfsSourceAttachment attachment = new SfsSourceAttachment(); - attachment.sfs_id = id; - Gee.List<HttpSource> http_sources = HttpSource.extract_sources(sources); - if (http_sources.is_empty) { - return null; - } - attachment.sources = http_sources; - return attachment; - } + // Currently only returns a single http source + private static Gee.List<Source>? get_sources(StanzaNode sources_node) { + string? url = HttpSchemeForUrlData.get_url(sources_node); + if (url == null) return null; - public MessageStanza to_message_stanza(Jid to, string message_type) { - MessageStanza stanza = new MessageStanza() { to=to, type_=message_type }; - Xep.MessageProcessingHints.set_message_hint(stanza, Xep.MessageProcessingHints.HINT_STORE); + var http_source = new HttpSource() { url=url }; + var sources = new Gee.ArrayList<Source>(); + sources.add(http_source); - StanzaNode attach_to = new StanzaNode.build(ATTACH_TO_STANZA_NAME, ATTACHMENT_NS_URI); - attach_to.add_attribute(new StanzaAttribute.build(ATTACHMENT_NS_URI, "id", this.sfs_id)); - stanza.stanza.put_node(attach_to); - - StanzaNode sources = new StanzaNode.build(SOURCES_STANZA_NAME, NS_URI); - Gee.List<StanzaNode> sources_nodes = new Gee.ArrayList<StanzaNode>(); - foreach (SfsSource source in this.sources) { - sources_nodes.add(source.to_stanza_node()); - } - sources.sub_nodes = sources_nodes; - stanza.stanza.put_node(sources); - - return stanza; - } + return sources; } - public class MessageFlag : Xmpp.MessageFlag { - public const string ID = "stateless_file_sharing"; - - public static MessageFlag? get_flag(MessageStanza message) { - return (MessageFlag) message.get_flag(NS_URI, ID); + public static void set_sfs_element(MessageStanza message, string file_sharing_id, FileMetadataElement.FileMetadata metadata, Gee.List<Xep.StatelessFileSharing.Source>? sources) { + var file_sharing_node = new StanzaNode.build("file-sharing", NS_URI).add_self_xmlns() + .put_attribute("id", file_sharing_id, NS_URI) + .put_node(metadata.to_stanza_node()); + if (sources != null && !sources.is_empty) { + file_sharing_node.put_node(create_sources_node(file_sharing_id, sources)); } + message.stanza.put_node(file_sharing_node); + } - public override string get_ns() { - return NS_URI; - } + public static void set_sfs_attachment(MessageStanza message, string attach_to_id, string attach_to_file_id, Gee.List<Xep.StatelessFileSharing.Source> sources) { + message.stanza.put_node(MessageAttaching.to_stanza_node(attach_to_id)); + message.stanza.put_node(create_sources_node(attach_to_file_id, sources).add_self_xmlns()); + } - public override string get_id() { - return ID; + private static StanzaNode create_sources_node(string file_sharing_id, Gee.List<Xep.StatelessFileSharing.Source> sources) { + StanzaNode sources_node = new StanzaNode.build("sources", NS_URI) + .put_attribute("id", file_sharing_id, NS_URI); + foreach (var source in sources) { + sources_node.put_node(source.to_stanza_node()); } + return sources_node; } - public class Module : XmppStreamModule { - public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, "stateless_file_sharing"); - - public signal void received_sfs(Jid from, Jid to, SfsElement sfs_element, MessageStanza message); - public signal void received_sfs_attachment(Jid from, Jid to, SfsSourceAttachment attachment, MessageStanza message); - - public void send_stateless_file_transfer(XmppStream stream, MessageStanza sfs_message, SfsElement sfs_element) { - StanzaNode sfs_node = sfs_element.to_stanza_node(); - printerr(sfs_node.to_ansi_string(true)); + public class FileShare : Object { + public string? id { get; set; } + public Xep.FileMetadataElement.FileMetadata metadata { get; set; } + public Gee.List<Source>? sources { get; set; } + } - sfs_message.stanza.put_node(sfs_node); - printerr("Sending message:\n"); - printerr(sfs_message.stanza.to_ansi_string(true)); - stream.get_module(MessageModule.IDENTITY).send_message.begin(stream, sfs_message); - } + public class SourceAttachment : Object { + public string to_message_id { get; set; } + public string? to_file_transfer_id { get; set; } + public Gee.List<Source>? sources { get; set; } + } - public void send_stateless_file_transfer_attachment(XmppStream stream, Jid to, string message_type, SfsSourceAttachment attachment) { - MessageStanza message = attachment.to_message_stanza(to, message_type); + public interface Source: Object { + public abstract string type(); + public abstract StanzaNode to_stanza_node(); + public abstract bool equals(Source source); - printerr("Sending message:\n"); - printerr(message.stanza.to_ansi_string(true)); - stream.get_module(MessageModule.IDENTITY).send_message.begin(stream, message); + public static bool equals_func(Source s1, Source s2) { + return s1.equals(s2); } + } - private void on_received_message(XmppStream stream, MessageStanza message) { - StanzaNode? sfs_node = message.stanza.get_subnode(STANZA_NAME, NS_URI); - if (sfs_node != null) { - SfsElement? sfs_element = SfsElement.from_stanza_node(sfs_node); - if (sfs_element == null) { - return; - } - message.add_flag(new MessageFlag()); - received_sfs(message.from, message.to, sfs_element, message); - } - SfsSourceAttachment? attachment = SfsSourceAttachment.from_message_stanza(message); - if (attachment != null) { - received_sfs_attachment(message.from, message.to, attachment, message); - } + public class HttpSource : Object, Source { + public string url { get; set; } + public string type() { + return "http"; } - public override void attach(XmppStream stream) { - stream.get_module(MessageModule.IDENTITY).received_message.connect(on_received_message); + public StanzaNode to_stanza_node() { + return HttpSchemeForUrlData.to_stanza_node(url); } - public override void detach(XmppStream stream) { - stream.get_module(MessageModule.IDENTITY).received_message.disconnect(on_received_message); + public bool equals(Source source) { + HttpSource? http_source = source as HttpSource; + if (http_source == null) return false; + return http_source.url == this.url; } - - public override string get_ns() { return NS_URI; } - public override string get_id() { return IDENTITY.id; } } } |