plugins/mod_disco.lua
changeset 3347 99f56bed5228
parent 3343 c70c6d5bf270
child 3348 3b84a84f472a
equal deleted inserted replaced
3346:c9294e190bb6 3347:99f56bed5228
    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;