| 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 | module "caps" |
| 16 | |
| 17 | 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 _M; |