aboutsummaryrefslogtreecommitdiff
path: root/xmpp-vala/src/module/xep/0428_fallback_indication.vala
blob: 3cad689b004d6dc2d1c6be0bc205ad55dae81520 (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
using Gee;

namespace Xmpp.Xep.FallbackIndication {

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

    public class Fallback {
        public string ns_uri { get; set; }
        public FallbackLocation[] locations;


        public Fallback(string ns_uri, FallbackLocation[] locations) {
            this.ns_uri = ns_uri;
            this.locations = locations;
        }
    }

    public class FallbackLocation {
        public bool is_whole { get { return from_char == -1 && to_char == -1; } }
        public int from_char { get; set; }
        public int to_char { get; set; }

        public FallbackLocation.partial_body(int from_char, int to_char) {
            this.from_char = from_char;
            this.to_char = to_char;
        }

        public FallbackLocation.whole_body() {
            this.from_char = -1;
            this.to_char = -1;
        }
    }

    public static void set_fallback(MessageStanza message, Fallback fallback) {
        StanzaNode fallback_node = (new StanzaNode.build("fallback", NS_URI))
                .add_self_xmlns()
                .put_attribute("for", fallback.ns_uri);
        foreach (FallbackLocation location in fallback.locations) {
            var node = new StanzaNode.build("body", NS_URI).add_self_xmlns();
            if (!location.is_whole) {
                node.put_attribute("start", location.from_char.to_string())
                        .put_attribute("end", location.to_char.to_string());
            }
            fallback_node.put_node(node);
        }
        message.stanza.put_node(fallback_node);
    }

    public Gee.List<Fallback> get_fallbacks(MessageStanza message) {
        var ret = new ArrayList<Fallback>();

        Gee.List<StanzaNode> fallback_nodes = message.stanza.get_subnodes("fallback", NS_URI);
        if (fallback_nodes.is_empty) return ret;

        foreach (StanzaNode fallback_node in fallback_nodes) {
            string? ns_uri = fallback_node.get_attribute("for");
            if (ns_uri == null) continue;

            var locations = new ArrayList<FallbackLocation>();
            if (fallback_node.get_all_subnodes().is_empty) {
                locations.add(new FallbackLocation.whole_body());
            } else {
                Gee.List<StanzaNode> body_nodes = fallback_node.get_subnodes("body", NS_URI);
                foreach (StanzaNode body_node in body_nodes) {
                    int start_char = body_node.get_attribute_int("start", -1);
                    int end_char = body_node.get_attribute_int("end", -1);
                    if (start_char == -1 && end_char == -1) {
                        locations.add(new FallbackLocation.whole_body());
                        continue;
                    }
                    if (start_char == -1 || end_char == -1) continue;
                    locations.add(new FallbackLocation.partial_body(start_char, end_char));
                }
            }
            if (locations.is_empty) continue;
            ret.add(new Fallback(ns_uri, locations.to_array()));
        }

        return ret;
    }
}