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