aboutsummaryrefslogtreecommitdiff
path: root/xmpp-vala/src/module/xep/0054_vcard/module.vala
blob: b1ad3f48af228199b6ee34543a9f2818c466db4e (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
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 static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, "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);
        stream.get_module(Presence.Module.IDENTITY).received_presence.connect(on_received_presence);
    }

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

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

    public override string get_ns() { return NS_URI; }
    public override string get_id() { return IDENTITY.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 (stream.get_flag(Muc.Flag.IDENTITY).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 (stream.get_flag(Muc.Flag.IDENTITY).is_occupant(presence.from)) {
                iq.to = presence.from;
            } else {
                iq.to = get_bare_jid(presence.from);
            }
            stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, on_received_vcard);
        }
    }

    private void on_received_vcard(XmppStream stream, Iq.Stanza iq) {
        if (iq.is_error()) return;
        string? res = iq.stanza.get_deep_string_content(@"$NS_URI:vCard", "PHOTO", "BINVAL");
        if (res == null) return;
        uint8[] content = Base64.decode(res);
        string sha1 = Checksum.compute_for_data(ChecksumType.SHA1, content);
        storage.store(sha1, content);
        stream.get_module(IDENTITY).received_avatar(stream, iq.from, sha1);
    }
}
}