aboutsummaryrefslogtreecommitdiff
path: root/xmpp-vala/src/module/xep/0447_stateless_file_sharing.vala
blob: 86da6a3ae218ef9424afa653cb2ae8cd4987b991 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
using Gee;
using Xmpp;

namespace Xmpp.Xep.StatelessFileSharing {

    public const string NS_URI = "urn:xmpp:sfs:0";

    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;

            var sources_node = file_sharing_node.get_subnode("sources", NS_URI);

            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
            });
        }

        if (ret.size == 0) return null;

        return ret;
    }

    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;

        string? attach_to_id = MessageAttaching.get_attach_to(message.stanza);
        if (attach_to_id == null) return null;

        var ret = new ArrayList<SourceAttachment>();

        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 static bool is_sfs_fallback_message(MessageStanza message) {
        Gee.List<FallbackIndication.Fallback> fallbacks = Xep.FallbackIndication.get_fallbacks(message);
        foreach (var fallback in fallbacks) {
            if (fallback.ns_uri == StatelessFileSharing.NS_URI && fallback.locations.any_match((it) => it.is_whole)) {
                return true;
            }
        }
        return false;
    }

    // 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;

        var http_source = new HttpSource() { url=url };
        var sources = new Gee.ArrayList<Source>();
        sources.add(http_source);

        return sources;
    }

    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 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());
    }

    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 FileShare : Object {
        public string? id { get; set; }
        public Xep.FileMetadataElement.FileMetadata metadata { get; set; }
        public Gee.List<Source>? sources { get; set; }
    }

    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 interface Source: Object {
        public abstract string type();
        public abstract StanzaNode to_stanza_node();
        public abstract bool equals(Source source);

        public static bool equals_func(Source s1, Source s2) {
            return s1.equals(s2);
        }
    }

    public class HttpSource : Object, Source {
        public string url { get; set; }

        public string type() {
            return "http";
        }

        public StanzaNode to_stanza_node() {
            return HttpSchemeForUrlData.to_stanza_node(url);
        }

        public bool equals(Source source) {
            HttpSource? http_source = source as HttpSource;
            if (http_source == null) return false;
            return http_source.url == this.url;
        }
    }
}