Merge 0.10->trunk
[prosody.git] / util / caps.lua
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
9 local base64 = require "util.encodings".base64.encode;
10 local sha1 = require "util.hashes".sha1;
11
12 local t_insert, t_sort, t_concat = table.insert, table.sort, table.concat;
13 local ipairs = ipairs;
14
15 local _ENV = nil;
16
17 local function calculate_hash(disco_info)
18         local identities, features, extensions = {}, {}, {};
19         for _, tag in ipairs(disco_info) do
20                 if tag.name == "identity" then
21                         t_insert(identities, (tag.attr.category or "").."\0"..(tag.attr.type or "").."\0"..(tag.attr["xml:lang"] or "").."\0"..(tag.attr.name or ""));
22                 elseif tag.name == "feature" then
23                         t_insert(features, tag.attr.var or "");
24                 elseif tag.name == "x" and tag.attr.xmlns == "jabber:x:data" then
25                         local form = {};
26                         local FORM_TYPE;
27                         for _, field in ipairs(tag.tags) do
28                                 if field.name == "field" and field.attr.var then
29                                         local values = {};
30                                         for _, val in ipairs(field.tags) do
31                                                 val = #val.tags == 0 and val:get_text();
32                                                 if val then t_insert(values, val); end
33                                         end
34                                         t_sort(values);
35                                         if field.attr.var == "FORM_TYPE" then
36                                                 FORM_TYPE = values[1];
37                                         elseif #values > 0 then
38                                                 t_insert(form, field.attr.var.."\0"..t_concat(values, "<"));
39                                         else
40                                                 t_insert(form, field.attr.var);
41                                         end
42                                 end
43                         end
44                         t_sort(form);
45                         form = t_concat(form, "<");
46                         if FORM_TYPE then form = FORM_TYPE.."\0"..form; end
47                         t_insert(extensions, form);
48                 end
49         end
50         t_sort(identities);
51         t_sort(features);
52         t_sort(extensions);
53         if #identities > 0 then identities = t_concat(identities, "<"):gsub("%z", "/").."<"; else identities = ""; end
54         if #features > 0 then features = t_concat(features, "<").."<"; else features = ""; end
55         if #extensions > 0 then extensions = t_concat(extensions, "<"):gsub("%z", "<").."<"; else extensions = ""; end
56         local S = identities..features..extensions;
57         local ver = base64(sha1(S));
58         return ver, S;
59 end
60
61 return {
62         calculate_hash = calculate_hash;
63 };