1-- Prosody IM
2-- Copyright (C) 2008-2010 Matthew Wild
3-- Copyright (C) 2008-2010 Waqas Hussain
4--
5-- This project is MIT/X11 licensed. Please see the
6-- COPYING file in the source package for more information.
7--
8
9local base64 = require "util.encodings".base64.encode;
10local sha1 = require "util.hashes".sha1;
11
12local t_insert, t_sort, t_concat = table.insert, table.sort, table.concat;
13local ipairs = ipairs;
14
15local _ENV = nil;
16-- luacheck: std none
17
18local function calculate_hash(disco_info)
19	local identities, features, extensions = {}, {}, {};
20	for _, tag in ipairs(disco_info) do
21		if tag.name == "identity" then
22			t_insert(identities, (tag.attr.category or "").."\0"..(tag.attr.type or "").."\0"..(tag.attr["xml:lang"] or "").."\0"..(tag.attr.name or ""));
23		elseif tag.name == "feature" then
24			t_insert(features, tag.attr.var or "");
25		elseif tag.name == "x" and tag.attr.xmlns == "jabber:x:data" then
26			local form = {};
27			local FORM_TYPE;
28			for _, field in ipairs(tag.tags) do
29				if field.name == "field" and field.attr.var then
30					local values = {};
31					for _, val in ipairs(field.tags) do
32						val = #val.tags == 0 and val:get_text();
33						if val then t_insert(values, val); end
34					end
35					t_sort(values);
36					if field.attr.var == "FORM_TYPE" then
37						FORM_TYPE = values[1];
38					elseif #values > 0 then
39						t_insert(form, field.attr.var.."\0"..t_concat(values, "<"));
40					else
41						t_insert(form, field.attr.var);
42					end
43				end
44			end
45			t_sort(form);
46			form = t_concat(form, "<");
47			if FORM_TYPE then form = FORM_TYPE.."\0"..form; end
48			t_insert(extensions, form);
49		end
50	end
51	t_sort(identities);
52	t_sort(features);
53	t_sort(extensions);
54	if #identities > 0 then identities = t_concat(identities, "<"):gsub("%z", "/").."<"; else identities = ""; end
55	if #features > 0 then features = t_concat(features, "<").."<"; else features = ""; end
56	if #extensions > 0 then extensions = t_concat(extensions, "<"):gsub("%z", "<").."<"; else extensions = ""; end
57	local S = identities..features..extensions;
58	local ver = base64(sha1(S));
59	return ver, S;
60end
61
62return {
63	calculate_hash = calculate_hash;
64};
65