34 |
34 |
35 module:add_identity("server", "im", "Prosody"); -- FIXME should be in the non-existing mod_router |
35 module:add_identity("server", "im", "Prosody"); -- FIXME should be in the non-existing mod_router |
36 module:add_feature("http://jabber.org/protocol/disco#info"); |
36 module:add_feature("http://jabber.org/protocol/disco#info"); |
37 module:add_feature("http://jabber.org/protocol/disco#items"); |
37 module:add_feature("http://jabber.org/protocol/disco#items"); |
38 |
38 |
39 -- Handle disco requests to the server |
39 -- Generate and cache disco result and caps hash |
40 |
40 local _cached_server_disco_info, _cached_server_caps_feature, _cached_server_caps_hash; |
41 local function build_server_disco_info(stanza) |
41 local function build_server_disco_info() |
|
42 local query = st.stanza("query", { xmlns = "http://jabber.org/protocol/disco#info" }); |
42 local done = {}; |
43 local done = {}; |
43 for _,identity in ipairs(module:get_host_items("identity")) do |
44 for _,identity in ipairs(module:get_host_items("identity")) do |
44 local identity_s = identity.category.."\0"..identity.type; |
45 local identity_s = identity.category.."\0"..identity.type; |
45 if not done[identity_s] then |
46 if not done[identity_s] then |
46 stanza:tag("identity", identity):up(); |
47 query:tag("identity", identity):up(); |
47 done[identity_s] = true; |
48 done[identity_s] = true; |
48 end |
49 end |
49 end |
50 end |
50 for _,feature in ipairs(module:get_host_items("feature")) do |
51 for _,feature in ipairs(module:get_host_items("feature")) do |
51 if not done[feature] then |
52 if not done[feature] then |
52 stanza:tag("feature", {var=feature}):up(); |
53 query:tag("feature", {var=feature}):up(); |
53 done[feature] = true; |
54 done[feature] = true; |
54 end |
55 end |
55 end |
56 end |
|
57 _cached_server_disco_info = query; |
|
58 _cached_server_caps_hash = calculate_hash(query); |
|
59 _cached_server_caps_feature = st.stanza("c", { |
|
60 xmlns = "http://jabber.org/protocol/caps"; |
|
61 hash = "sha-1"; |
|
62 node = "http://prosody.im"; |
|
63 ver = _cached_server_caps_hash; |
|
64 }); |
56 end |
65 end |
|
66 local function clear_disco_cache() |
|
67 _cached_server_disco_info, _cached_server_caps_feature, _cached_server_caps_hash = nil, nil, nil; |
|
68 end |
|
69 local function get_server_disco_info() |
|
70 if not _cached_server_disco_info then build_server_disco_info(); end |
|
71 return _cached_server_disco_info; |
|
72 end |
|
73 local function get_server_caps_feature() |
|
74 if not _cached_server_caps_feature then build_server_disco_info(); end |
|
75 return _cached_server_caps_feature; |
|
76 end |
|
77 local function get_server_caps_hash() |
|
78 if not _cached_server_caps_hash then build_server_disco_info(); end |
|
79 return _cached_server_caps_hash; |
|
80 end |
|
81 |
|
82 module:hook("item-added/identity", clear_disco_cache); |
|
83 module:hook("item-added/feature", clear_disco_cache); |
|
84 |
|
85 -- Handle disco requests to the server |
57 module:hook("iq/host/http://jabber.org/protocol/disco#info:query", function(event) |
86 module:hook("iq/host/http://jabber.org/protocol/disco#info:query", function(event) |
58 local origin, stanza = event.origin, event.stanza; |
87 local origin, stanza = event.origin, event.stanza; |
59 if stanza.attr.type ~= "get" then return; end |
88 if stanza.attr.type ~= "get" then return; end |
60 local node = stanza.tags[1].attr.node; |
89 local node = stanza.tags[1].attr.node; |
61 if node and node ~= "" then return; end -- TODO fire event? |
90 if node and node ~= "" and node ~= get_server_caps_hash() then return; end -- TODO fire event? |
62 local reply = st.reply(stanza):query("http://jabber.org/protocol/disco#info"); |
91 local reply = st.reply(stanza):add_child(get_server_disco_info()); |
63 build_server_disco_info(reply); |
|
64 origin.send(reply); |
92 origin.send(reply); |
65 return true; |
93 return true; |
66 end); |
94 end); |
67 module:hook("iq/host/http://jabber.org/protocol/disco#items:query", function(event) |
95 module:hook("iq/host/http://jabber.org/protocol/disco#items:query", function(event) |
68 local origin, stanza = event.origin, event.stanza; |
96 local origin, stanza = event.origin, event.stanza; |
79 end |
107 end |
80 origin.send(reply); |
108 origin.send(reply); |
81 return true; |
109 return true; |
82 end); |
110 end); |
83 |
111 |
84 -- Server caps hash calculation |
112 -- Handle caps stream feature |
85 local caps_hash_feature; |
|
86 |
|
87 local function recalculate_server_caps() |
|
88 local caps_hash = calculate_hash(st.stanza()); |
|
89 caps_hash_feature = st.stanza("c", { |
|
90 xmlns = "http://jabber.org/protocol/caps"; |
|
91 hash = "sha-1"; |
|
92 node = "http://prosody.im"; |
|
93 ver = caps_hash; |
|
94 }); |
|
95 end |
|
96 recalculate_server_caps(); |
|
97 |
|
98 module:hook("item-added/identity", recalculate_server_caps); |
|
99 module:hook("item-added/feature", recalculate_server_caps); |
|
100 |
|
101 module:hook("stream-features", function (event) |
113 module:hook("stream-features", function (event) |
102 if caps_hash_feature then |
114 event.features:add_child(get_server_caps_feature()); |
103 event.features:add_child(caps_hash_feature); |
|
104 end |
|
105 end); |
115 end); |
106 |
116 |
107 -- Handle disco requests to user accounts |
117 -- Handle disco requests to user accounts |
108 module:hook("iq/bare/http://jabber.org/protocol/disco#info:query", function(event) |
118 module:hook("iq/bare/http://jabber.org/protocol/disco#info:query", function(event) |
109 local origin, stanza = event.origin, event.stanza; |
119 local origin, stanza = event.origin, event.stanza; |