diff -r 000000000000 -r d17a1b659852 capscan.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/capscan.lua Sat Sep 18 18:19:37 2010 +0100 @@ -0,0 +1,154 @@ +require "verse" +require "verse.client" +local array = require "array"; +local calculate_hash = require "caps".calculate_hash; + +-- Configurable: +local jid, pass = arg[1], nil; +--- -- -- -- --- + +local escape_table = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" }; +local function escape(str) return (string.gsub(str, "['&<>\"]", escape_table)); end + +local xmlns_caps = "http://jabber.org/protocol/caps"; +local xmlns_disco = "http://jabber.org/protocol/disco#info"; + +if not pass then + io.write("Password (not blanked): "); + pass = io.read("*l"); +end + +local conn = verse.new(verse.logger()); + +conn:add_plugin("version"); + +conn:connect_client(jid, pass); + +local contacts = {}; + +conn:hook("ready", function () + conn:hook("presence", function (presence) + if contacts[presence.attr.from] then return; end; + + local contact = { jid = presence.attr.from }; + contacts[contact.jid] = contact; + + local caps_tag = presence:get_child("c", xmlns_caps); + if not caps_tag then + conn:debug("No caps from %s: %s", presence.attr.from, tostring(presence)); + return; + end + + contact.hash_type = caps_tag.attr.hash; + contact.ver = caps_tag.attr.ver; + contact.node = caps_tag.attr.node; + + local node_string = contact.node.."#"..contact.ver; + + conn:query_version(contact.jid, function (version) + contact.version = ("%s%s%s"):format( + version.name or "[no name]", + version.version and (" "..version.version) or "", + version.platform and (" ("..version.platform..")") or "" + ); + end); + + conn:send_iq(verse.iq({ to = contact.jid, type = "get" }) + :tag("query", { xmlns = xmlns_disco, node = node_string }), + function (result) + if result.attr.type == "error" then + contact.error = { result:get_error() }; + return; + end + contact.calculated_ver, contact.calculated_S + = calculate_hash(result.tags[1]); + if contact.calculated_ver ~= contact.ver then + conn:warn("Invalid caps hash: %s", contact.jid); + conn:warn("Received: %s Calculated: %s", contact.ver, contact.calculated_ver); + conn:warn("Received stanza: %s", tostring(result)); + conn:warn("Calculated S: %s", contact.calculated_S); + else + conn:warn("Valid caps hash: %s", contact.jid); + end + end); + end, 1000); + conn:send(verse.presence():tag("priority"):text("-1")); +end); + +verse.loop(); + +--- Write report + +local report = io.open("report.html", "w+"); +report:write[[ +
+", tostring(#contact_jids), " contacts
\n"); + +local function write_section(title, jids, show) + report:write("\n", tostring(#jids), " contacts
\n"); + report:write("