Software / code / verse
Comparison
plugins/disco.lua @ 399:82ad158714e5
Merge with Zash
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Tue, 12 Jan 2016 13:14:36 +0000 |
| parent | 392:cdea6a28369e |
| child | 423:e98cef597393 |
comparison
equal
deleted
inserted
replaced
| 378:6042c938e369 | 399:82ad158714e5 |
|---|---|
| 1 -- Verse XMPP Library | 1 -- Verse XMPP Library |
| 2 -- Copyright (C) 2010 Hubert Chathi <hubert@uhoreg.ca> | 2 -- Copyright (C) 2010 Hubert Chathi <hubert@uhoreg.ca> |
| 3 -- Copyright (C) 2010 Matthew Wild <mwild1@gmail.com> | 3 -- Copyright (C) 2010 Matthew Wild <mwild1@gmail.com> |
| 4 -- | 4 -- |
| 5 -- This project is MIT/X11 licensed. Please see the | 5 -- This project is MIT/X11 licensed. Please see the |
| 6 -- COPYING file in the source package for more information. | 6 -- COPYING file in the source package for more information. |
| 7 -- | 7 -- |
| 8 | 8 |
| 9 local verse = require "verse"; | 9 local verse = require "verse"; |
| 10 local b64 = require("mime").b64; | 10 local b64 = require("mime").b64; |
| 11 local sha1 = require("util.sha1").sha1; | 11 local sha1 = require("util.hashes").sha1; |
| 12 | 12 |
| 13 local xmlns_caps = "http://jabber.org/protocol/caps"; | 13 local xmlns_caps = "http://jabber.org/protocol/caps"; |
| 14 local xmlns_disco = "http://jabber.org/protocol/disco"; | 14 local xmlns_disco = "http://jabber.org/protocol/disco"; |
| 15 local xmlns_disco_info = xmlns_disco.."#info"; | 15 local xmlns_disco_info = xmlns_disco.."#info"; |
| 16 local xmlns_disco_items = xmlns_disco.."#items"; | 16 local xmlns_disco_items = xmlns_disco.."#items"; |
| 116 node = stream.caps.node, | 116 node = stream.caps.node, |
| 117 ver = hash | 117 ver = hash |
| 118 }) | 118 }) |
| 119 end | 119 end |
| 120 }) | 120 }) |
| 121 | 121 |
| 122 function stream:set_identity(identity, node) | 122 function stream:set_identity(identity, node) |
| 123 self.disco.info[node or false].identities = { identity }; | 123 self.disco.info[node or false].identities = { identity }; |
| 124 stream:resend_presence(); | 124 stream:resend_presence(); |
| 125 end | 125 end |
| 126 | 126 |
| 133 function stream:add_disco_feature(feature, node) | 133 function stream:add_disco_feature(feature, node) |
| 134 local feature = feature.var or feature; | 134 local feature = feature.var or feature; |
| 135 self.disco.info[node or false].features[feature] = true; | 135 self.disco.info[node or false].features[feature] = true; |
| 136 stream:resend_presence(); | 136 stream:resend_presence(); |
| 137 end | 137 end |
| 138 | 138 |
| 139 function stream:remove_disco_feature(feature, node) | 139 function stream:remove_disco_feature(feature, node) |
| 140 local feature = feature.var or feature; | 140 local feature = feature.var or feature; |
| 141 self.disco.info[node or false].features[feature] = nil; | 141 self.disco.info[node or false].features[feature] = nil; |
| 142 stream:resend_presence(); | 142 stream:resend_presence(); |
| 143 end | 143 end |
| 179 if not cached_disco or not cached_disco.features then | 179 if not cached_disco or not cached_disco.features then |
| 180 return nil, "no-cache"; | 180 return nil, "no-cache"; |
| 181 end | 181 end |
| 182 return cached_disco.features[feature] or false; | 182 return cached_disco.features[feature] or false; |
| 183 end | 183 end |
| 184 | 184 |
| 185 function stream:get_local_services(category, type) | 185 function stream:get_local_services(category, type) |
| 186 local host_disco = self.disco.cache[self.host]; | 186 local host_disco = self.disco.cache[self.host]; |
| 187 if not(host_disco) or not(host_disco.items) then | 187 if not(host_disco) or not(host_disco.items) then |
| 188 return nil, "no-cache"; | 188 return nil, "no-cache"; |
| 189 end | 189 end |
| 190 | 190 |
| 191 local results = {}; | 191 local results = {}; |
| 192 for _, service in ipairs(host_disco.items) do | 192 for _, service in ipairs(host_disco.items) do |
| 193 if self:jid_has_identity(service.jid, category, type) then | 193 if self:jid_has_identity(service.jid, category, type) then |
| 194 table.insert(results, service.jid); | 194 table.insert(results, service.jid); |
| 195 end | 195 end |
| 196 end | 196 end |
| 197 return results; | 197 return results; |
| 198 end | 198 end |
| 199 | 199 |
| 200 function stream:disco_local_services(callback) | 200 function stream:disco_local_services(callback) |
| 201 self:disco_items(self.host, nil, function (items) | 201 self:disco_items(self.host, nil, function (items) |
| 202 if not items then | 202 if not items then |
| 203 return callback({}); | 203 return callback({}); |
| 204 end | 204 end |
| 207 n_items = n_items - 1; | 207 n_items = n_items - 1; |
| 208 if n_items == 0 then | 208 if n_items == 0 then |
| 209 return callback(items); | 209 return callback(items); |
| 210 end | 210 end |
| 211 end | 211 end |
| 212 | 212 |
| 213 for _, item in ipairs(items) do | 213 for _, item in ipairs(items) do |
| 214 if item.jid then | 214 if item.jid then |
| 215 n_items = n_items + 1; | 215 n_items = n_items + 1; |
| 216 self:disco_info(item.jid, nil, item_callback); | 216 self:disco_info(item.jid, nil, item_callback); |
| 217 end | 217 end |
| 219 if n_items == 0 then | 219 if n_items == 0 then |
| 220 return callback(items); | 220 return callback(items); |
| 221 end | 221 end |
| 222 end); | 222 end); |
| 223 end | 223 end |
| 224 | 224 |
| 225 function stream:disco_info(jid, node, callback) | 225 function stream:disco_info(jid, node, callback) |
| 226 local disco_request = verse.iq({ to = jid, type = "get" }) | 226 local disco_request = verse.iq({ to = jid, type = "get" }) |
| 227 :tag("query", { xmlns = xmlns_disco_info, node = node }); | 227 :tag("query", { xmlns = xmlns_disco_info, node = node }); |
| 228 self:send_iq(disco_request, function (result) | 228 self:send_iq(disco_request, function (result) |
| 229 if result.attr.type == "error" then | 229 if result.attr.type == "error" then |
| 230 return callback(nil, result:get_error()); | 230 return callback(nil, result:get_error()); |
| 231 end | 231 end |
| 232 | 232 |
| 233 local identities, features = {}, {}; | 233 local identities, features = {}, {}; |
| 234 | 234 |
| 235 for tag in result:get_child("query", xmlns_disco_info):childtags() do | 235 for tag in result:get_child("query", xmlns_disco_info):childtags() do |
| 236 if tag.name == "identity" then | 236 if tag.name == "identity" then |
| 237 identities[tag.attr.category.."/"..tag.attr.type] = tag.attr.name or true; | 237 identities[tag.attr.category.."/"..tag.attr.type] = tag.attr.name or true; |
| 238 elseif tag.name == "feature" then | 238 elseif tag.name == "feature" then |
| 239 features[tag.attr.var] = true; | 239 features[tag.attr.var] = true; |
| 240 end | 240 end |
| 241 end | 241 end |
| 242 | 242 |
| 243 | 243 |
| 244 if not self.disco.cache[jid] then | 244 if not self.disco.cache[jid] then |
| 245 self.disco.cache[jid] = { nodes = {} }; | 245 self.disco.cache[jid] = { nodes = {} }; |
| 246 end | 246 end |
| 247 | 247 |
| 256 self.disco.cache[jid].features = features; | 256 self.disco.cache[jid].features = features; |
| 257 end | 257 end |
| 258 return callback(self.disco.cache[jid]); | 258 return callback(self.disco.cache[jid]); |
| 259 end); | 259 end); |
| 260 end | 260 end |
| 261 | 261 |
| 262 function stream:disco_items(jid, node, callback) | 262 function stream:disco_items(jid, node, callback) |
| 263 local disco_request = verse.iq({ to = jid, type = "get" }) | 263 local disco_request = verse.iq({ to = jid, type = "get" }) |
| 264 :tag("query", { xmlns = xmlns_disco_items, node = node }); | 264 :tag("query", { xmlns = xmlns_disco_items, node = node }); |
| 265 self:send_iq(disco_request, function (result) | 265 self:send_iq(disco_request, function (result) |
| 266 if result.attr.type == "error" then | 266 if result.attr.type == "error" then |
| 274 jid = tag.attr.jid; | 274 jid = tag.attr.jid; |
| 275 node = tag.attr.node; | 275 node = tag.attr.node; |
| 276 }); | 276 }); |
| 277 end | 277 end |
| 278 end | 278 end |
| 279 | 279 |
| 280 if not self.disco.cache[jid] then | 280 if not self.disco.cache[jid] then |
| 281 self.disco.cache[jid] = { nodes = {} }; | 281 self.disco.cache[jid] = { nodes = {} }; |
| 282 end | 282 end |
| 283 | 283 |
| 284 if node then | 284 if node then |
| 285 if not self.disco.cache[jid].nodes[node] then | 285 if not self.disco.cache[jid].nodes[node] then |
| 286 self.disco.cache[jid].nodes[node] = { nodes = {} }; | 286 self.disco.cache[jid].nodes[node] = { nodes = {} }; |
| 287 end | 287 end |
| 288 self.disco.cache[jid].nodes[node].items = disco_items; | 288 self.disco.cache[jid].nodes[node].items = disco_items; |
| 290 self.disco.cache[jid].items = disco_items; | 290 self.disco.cache[jid].items = disco_items; |
| 291 end | 291 end |
| 292 return callback(disco_items); | 292 return callback(disco_items); |
| 293 end); | 293 end); |
| 294 end | 294 end |
| 295 | 295 |
| 296 stream:hook("iq/"..xmlns_disco_info, function (stanza) | 296 stream:hook("iq/"..xmlns_disco_info, function (stanza) |
| 297 local query = stanza.tags[1]; | 297 local query = stanza.tags[1]; |
| 298 if stanza.attr.type == 'get' and query.name == "query" then | 298 if stanza.attr.type == 'get' and query.name == "query" then |
| 299 local query_node = query.attr.node; | 299 local query_node = query.attr.node; |
| 300 local node = stream.disco.info[query_node or false]; | 300 local node = stream.disco.info[query_node or false]; |
| 335 end | 335 end |
| 336 stream:send(result); | 336 stream:send(result); |
| 337 return true | 337 return true |
| 338 end | 338 end |
| 339 end); | 339 end); |
| 340 | 340 |
| 341 local initial_disco_started; | 341 local initial_disco_started; |
| 342 stream:hook("ready", function () | 342 stream:hook("ready", function () |
| 343 if initial_disco_started then return; end | 343 if initial_disco_started then return; end |
| 344 initial_disco_started = true; | 344 initial_disco_started = true; |
| 345 stream:disco_local_services(function (services) | 345 stream:disco_local_services(function (services) |
| 356 end | 356 end |
| 357 stream:event("ready"); | 357 stream:event("ready"); |
| 358 end); | 358 end); |
| 359 return true; | 359 return true; |
| 360 end, 50); | 360 end, 50); |
| 361 | 361 |
| 362 stream:hook("presence-out", function (presence) | 362 stream:hook("presence-out", function (presence) |
| 363 if not presence:get_child("c", xmlns_caps) then | 363 if not presence:get_child("c", xmlns_caps) then |
| 364 presence:reset():add_child(stream:caps()):reset(); | 364 presence:reset():add_child(stream:caps()):reset(); |
| 365 end | 365 end |
| 366 end, 10); | 366 end, 10); |