Tue, 21 Sep 2010 10:22:30 +0100
Correctly close <title> tag in report.html
0 | 1 | require "verse" |
2 | require "verse.client" | |
3 | local array = require "array"; | |
4 | local calculate_hash = require "caps".calculate_hash; | |
5 | ||
6 | -- Configurable: | |
7 | local jid, pass = arg[1], nil; | |
8 | --- -- -- -- --- | |
9 | ||
10 | local escape_table = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" }; | |
11 | local function escape(str) return (string.gsub(str, "['&<>\"]", escape_table)); end | |
12 | ||
13 | local xmlns_caps = "http://jabber.org/protocol/caps"; | |
14 | local xmlns_disco = "http://jabber.org/protocol/disco#info"; | |
15 | ||
1
ce892ac8bec2
Warn and exit when no JID is supplied
Matthew Wild <mwild1@gmail.com>
parents:
0
diff
changeset
|
16 | if not jid then |
ce892ac8bec2
Warn and exit when no JID is supplied
Matthew Wild <mwild1@gmail.com>
parents:
0
diff
changeset
|
17 | io.write("Please give a JID as the first argument\n"); |
ce892ac8bec2
Warn and exit when no JID is supplied
Matthew Wild <mwild1@gmail.com>
parents:
0
diff
changeset
|
18 | os.exit(1); |
ce892ac8bec2
Warn and exit when no JID is supplied
Matthew Wild <mwild1@gmail.com>
parents:
0
diff
changeset
|
19 | end |
ce892ac8bec2
Warn and exit when no JID is supplied
Matthew Wild <mwild1@gmail.com>
parents:
0
diff
changeset
|
20 | |
0 | 21 | if not pass then |
22 | io.write("Password (not blanked): "); | |
23 | pass = io.read("*l"); | |
24 | end | |
25 | ||
26 | local conn = verse.new(verse.logger()); | |
27 | ||
28 | conn:add_plugin("version"); | |
29 | ||
30 | conn:connect_client(jid, pass); | |
31 | ||
32 | local contacts = {}; | |
33 | ||
34 | conn:hook("ready", function () | |
35 | conn:hook("presence", function (presence) | |
4
9a4a18d11166
Discard presence of type error/unavailable
Matthew Wild <mwild1@gmail.com>
parents:
2
diff
changeset
|
36 | if contacts[presence.attr.from] or presence.attr.type then return; end; |
0 | 37 | |
38 | local contact = { jid = presence.attr.from }; | |
39 | contacts[contact.jid] = contact; | |
40 | ||
41 | local caps_tag = presence:get_child("c", xmlns_caps); | |
42 | if not caps_tag then | |
43 | conn:debug("No caps from %s: %s", presence.attr.from, tostring(presence)); | |
44 | return; | |
45 | end | |
46 | ||
47 | contact.hash_type = caps_tag.attr.hash; | |
48 | contact.ver = caps_tag.attr.ver; | |
49 | contact.node = caps_tag.attr.node; | |
50 | ||
51 | local node_string = contact.node.."#"..contact.ver; | |
52 | ||
53 | conn:query_version(contact.jid, function (version) | |
54 | contact.version = ("%s%s%s"):format( | |
55 | version.name or "[no name]", | |
56 | version.version and (" "..version.version) or "", | |
57 | version.platform and (" ("..version.platform..")") or "" | |
58 | ); | |
59 | end); | |
60 | ||
61 | conn:send_iq(verse.iq({ to = contact.jid, type = "get" }) | |
62 | :tag("query", { xmlns = xmlns_disco, node = node_string }), | |
63 | function (result) | |
64 | if result.attr.type == "error" then | |
65 | contact.error = { result:get_error() }; | |
66 | return; | |
67 | end | |
68 | contact.calculated_ver, contact.calculated_S | |
69 | = calculate_hash(result.tags[1]); | |
70 | if contact.calculated_ver ~= contact.ver then | |
71 | conn:warn("Invalid caps hash: %s", contact.jid); | |
72 | conn:warn("Received: %s Calculated: %s", contact.ver, contact.calculated_ver); | |
73 | conn:warn("Received stanza: %s", tostring(result)); | |
74 | conn:warn("Calculated S: %s", contact.calculated_S); | |
75 | else | |
76 | conn:warn("Valid caps hash: %s", contact.jid); | |
77 | end | |
78 | end); | |
79 | end, 1000); | |
80 | conn:send(verse.presence():tag("priority"):text("-1")); | |
81 | end); | |
82 | ||
83 | verse.loop(); | |
84 | ||
85 | --- Write report | |
86 | ||
87 | local report = io.open("report.html", "w+"); | |
88 | report:write[[<html> | |
89 | <head> | |
90 | <title>]]; | |
91 | report:write("Entity capabilities validity for contacts of ", jid); | |
5
db500386b9c4
Correctly close <title> tag in report.html
will@willthompson.co.uk
parents:
4
diff
changeset
|
92 | report:write[[</title> |
db500386b9c4
Correctly close <title> tag in report.html
will@willthompson.co.uk
parents:
4
diff
changeset
|
93 | </head> |
0 | 94 | <body> |
95 | ]]; | |
96 | ||
97 | local contact_jids = array.collect(keys(contacts)):sort(); | |
98 | ||
99 | report:write("<h1>Entity capabilities report for contacts of ", jid, "</h1>\n"); | |
100 | report:write("<p>", tostring(#contact_jids), " contacts</p>\n"); | |
101 | ||
102 | local function write_section(title, jids, show) | |
103 | report:write("\n<h1>", title, "</h1>\n"); | |
104 | report:write("<p>", tostring(#jids), " contacts</p>\n"); | |
105 | report:write("<ul>\n"); | |
106 | for _, jid in ipairs(jids) do | |
107 | local contact = contacts[jid]; | |
108 | local client_link = (" <a href='%s'>%s</a>"):format( | |
109 | escape(contacts[jid].node or "#"), | |
110 | escape(contacts[jid].version or "Unknown client") | |
111 | ); | |
112 | report:write(" <li>", escape(jid), client_link); | |
113 | ||
114 | if show then | |
115 | report:write("\n <ul>\n"); | |
116 | for _, field in ipairs(show) do | |
117 | local friendly_field = field:gsub("^.", string.upper):gsub("_", " "); | |
118 | local value = escape(contacts[jid][field] or ""); | |
119 | report:write((" "):rep(12), "<li>", friendly_field, ": ", value, "</li>\n"); | |
120 | end | |
121 | report:write(" </ul>\n"); | |
122 | end | |
123 | ||
124 | report:write("</li>\n"); | |
125 | end | |
126 | report:write("</ul>\n"); | |
127 | end | |
128 | ||
129 | local function no_caps_filter(jid) | |
130 | return not contacts[jid].ver; | |
131 | end | |
132 | ||
133 | local function legacy_caps_filter(jid) | |
134 | return contacts[jid].ver and not contacts[jid].hash_type; | |
135 | end | |
136 | ||
137 | local function valid_caps_filter(jid) | |
138 | return not(legacy_caps_filter(jid)) | |
139 | and (contacts[jid].ver == contacts[jid].calculated_ver); | |
140 | end | |
141 | ||
142 | local function invalid_caps_filter(jid) | |
143 | return not(legacy_caps_filter(jid)) and not(no_caps_filter(jid)) and not(valid_caps_filter(jid)); | |
144 | end | |
145 | ||
146 | write_section("Valid caps", array.filter(contact_jids, valid_caps_filter)); | |
147 | write_section("Invalid caps", array.filter(contact_jids, invalid_caps_filter), { "ver", "calculated_ver", "calculated_S" }); | |
148 | write_section("No caps", array.filter(contact_jids, no_caps_filter)); | |
149 | write_section("Legacy caps", array.filter(contact_jids, legacy_caps_filter), { "ver" }); | |
150 | ||
151 | report:write("</body></html>"); |