aboutsummaryrefslogtreecommitdiff
path: root/vala-xmpp/src/module/xep/0054_vcard/module.vala
blob: 58b71d2cc1b139843817c219704c9d1bea1436a9 (plain) (blame)
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
using Xmpp.Core;

namespace Xmpp.Xep.VCard {
private const string NS_URI = "vcard-temp";
private const string NS_URI_UPDATE = NS_URI + ":x:update";

public class Module : XmppStreamModule {
    public const string ID = "0027_current_pgp_usage";

    public signal void received_avatar(XmppStream stream, string jid, string id);

    private PixbufStorage storage;

    public Module(PixbufStorage storage) {
        this.storage = storage;
    }

    public override void attach(XmppStream stream) {
        Iq.Module.require(stream);
        Presence.Module.require(stream);
        Presence.Module.get_module(stream).received_presence.connect(on_received_presence);
    }

    public override void detach(XmppStream stream) {
        Presence.Module.get_module(stream).received_presence.disconnect(on_received_presence);
    }

    public static Module? get_module(XmppStream stream) {
        return (Module?) stream.get_module(NS_URI, ID);
    }

    public static void require(XmppStream stream) {
        if (get_module(stream) == null) stderr.printf("VCardModule required but not attached!\n"); ;
    }

    public override string get_ns() { return NS_URI; }
    public override string get_id() { return ID; }

    private void on_received_presence(XmppStream stream, Presence.Stanza presence) {
        StanzaNode? update_node = presence.stanza.get_subnode("x", NS_URI_UPDATE);
        if (update_node == null) return;
        StanzaNode? photo_node = update_node.get_subnode("photo", NS_URI_UPDATE);
        if (photo_node == null) return;
        string? sha1 = photo_node.get_string_content();
        if (sha1 == null) return;
        if (storage.has_image(sha1)) {
            if (Muc.Flag.get_flag(stream).is_occupant(presence.from)) {
                received_avatar(stream, presence.from, sha1);
            } else {
                received_avatar(stream, get_bare_jid(presence.from), sha1);
            }
        } else {
            Iq.Stanza iq = new Iq.Stanza.get(new StanzaNode.build("vCard", NS_URI).add_self_xmlns());
            if (Muc.Flag.get_flag(stream).is_occupant(presence.from)) {
                iq.to = presence.from;
            } else {
                iq.to = get_bare_jid(presence.from);
            }
            Iq.Module.get_module(stream).send_iq(stream, iq, new IqResponseListenerImpl(this, storage, sha1));
        }
    }

    private class IqResponseListenerImpl : Iq.ResponseListener, Object {
        Module outer;
        PixbufStorage storage;
        string id;
        public IqResponseListenerImpl(Module outer, PixbufStorage storage, string id) {
            this.outer = outer;
            this.id = id;
            this.storage = storage;
        }
        public void on_result(XmppStream stream, Iq.Stanza iq) {
            if (iq.is_error()) return;
            StanzaNode? vcard_node = iq.stanza.get_subnode("vCard", NS_URI);
            if (vcard_node == null) return;
            StanzaNode? photo_node = vcard_node.get_subnode("PHOTO", NS_URI);
            if (photo_node == null) return;
            StanzaNode? binary_node = photo_node.get_subnode("BINVAL", NS_URI);
            if (binary_node == null) return;
            string? content = binary_node.get_string_content();
            if (content == null) return;
            storage.store(id, Base64.decode(content));
            outer.received_avatar(stream, iq.from, id);
        }
    }
}
}