11 local xmlns_occupant_id = "urn:xmpp:occupant-id:0"; |
11 local xmlns_occupant_id = "urn:xmpp:occupant-id:0"; |
12 |
12 |
13 local function generate_id(occupant, room) |
13 local function generate_id(occupant, room) |
14 local bare = occupant.bare_jid; |
14 local bare = occupant.bare_jid; |
15 |
15 |
16 -- TODO: Move the salt on the MUC component. Setting the salt on the room |
|
17 -- can be problematic when the room is destroyed. Next time it's recreated |
|
18 -- the salt will be different and so will be the unique_id. Or maybe we want |
|
19 -- this anyway? |
|
20 if room._data.occupant_id_salt == nil then |
16 if room._data.occupant_id_salt == nil then |
21 local salt = uuid.generate(); |
17 room._data.occupant_id_salt = uuid.generate(); |
22 room._data.occupant_id_salt = salt; |
|
23 end |
18 end |
24 |
19 |
25 return b64encode(hmac_sha256(bare, room._data.occupant_id_salt)); |
20 if room._data.occupant_ids == nil then |
|
21 room._data.occupant_ids = {}; |
|
22 end |
|
23 |
|
24 if room._data.occupant_ids[bare] == nil then |
|
25 local unique_id = b64encode(hmac_sha256(bare, room._data.occupant_id_salt)); |
|
26 room._data.occupant_ids[bare] = unique_id; |
|
27 end |
|
28 |
|
29 return room._data.occupant_ids[bare]; |
26 end |
30 end |
27 |
31 |
28 local function edit_occupant(event) |
32 local function update_occupant(event) |
29 local unique_id = generate_id(event.occupant, event.room); |
|
30 |
|
31 -- TODO: Store this only once per bare jid and not once per occupant? |
|
32 local stanza = event.stanza; |
|
33 stanza:tag("occupant-id", { xmlns = xmlns_occupant_id }) |
|
34 :text(unique_id) |
|
35 :up(); |
|
36 end |
|
37 |
|
38 local function handle_stanza(event) |
|
39 local stanza, occupant, room = event.stanza, event.occupant, event.room; |
33 local stanza, occupant, room = event.stanza, event.occupant, event.room; |
40 |
34 |
41 -- strip any existing <occupant-id/> tags to avoid forgery |
35 -- strip any existing <occupant-id/> tags to avoid forgery |
42 stanza:remove_children("occupant-id", xmlns_occupant_id); |
36 stanza:remove_children("occupant-id", xmlns_occupant_id); |
43 |
37 |
44 local occupant_tag = occupant.sessions[stanza.attr.from] |
38 local unique_id = generate_id(occupant, room); |
45 :get_child("occupant-id", xmlns_occupant_id); |
|
46 |
|
47 local unique_id; |
|
48 if occupant_tag == nil then |
|
49 unique_id = generate_id(occupant, room); |
|
50 else |
|
51 unique_id = occupant.sessions[stanza.attr.from] |
|
52 :get_child("occupant-id", xmlns_occupant_id) |
|
53 :get_text(); |
|
54 end |
|
55 |
|
56 stanza:tag("occupant-id", { xmlns = xmlns_occupant_id }) |
39 stanza:tag("occupant-id", { xmlns = xmlns_occupant_id }) |
57 :text(unique_id) |
40 :text(unique_id) |
58 :up(); |
41 :up(); |
59 end |
42 end |
60 |
43 |
61 module:add_feature(xmlns_occupant_id); |
44 module:add_feature(xmlns_occupant_id); |
62 module:hook("muc-disco#info", function (event) |
45 module:hook("muc-disco#info", function (event) |
63 event.reply:tag("feature", { var = xmlns_occupant_id }):up(); |
46 event.reply:tag("feature", { var = xmlns_occupant_id }):up(); |
64 end); |
47 end); |
65 |
48 |
66 module:hook("muc-occupant-pre-join", edit_occupant); |
49 module:hook("muc-occupant-pre-join", update_occupant); |
67 module:hook("muc-occupant-groupchat", handle_stanza); |
50 module:hook("muc-occupant-groupchat", update_occupant); |