|
1 package.preload['util.encodings']=(function(...) |
|
2 local _ENV=_ENV; |
|
3 local function a(t,...) |
|
4 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
5 package.loaded[t]=e; |
|
6 for t=1,select("#",...)do |
|
7 (select(t,...))(e); |
|
8 end |
|
9 _ENV=e; |
|
10 _M=e; |
|
11 return e; |
|
12 end |
|
13 local function e() |
|
14 error("Function not implemented"); |
|
15 end |
|
16 local e=require"mime"; |
|
17 a"encodings" |
|
18 idna={}; |
|
19 stringprep={}; |
|
20 base64={encode=e.b64,decode=e.unb64}; |
|
21 utf8={ |
|
22 valid=(utf8 and utf8.len)and function(e)return not not utf8.len(e);end or function()return true;end; |
|
23 }; |
|
24 return _M; |
|
25 end) |
|
26 package.preload['util.hashes']=(function(...) |
|
27 local _ENV=_ENV; |
|
28 local function e(t,...) |
|
29 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
30 package.loaded[t]=e; |
|
31 for t=1,select("#",...)do |
|
32 (select(t,...))(e); |
|
33 end |
|
34 _ENV=e; |
|
35 _M=e; |
|
36 return e; |
|
37 end |
|
38 local function e(t,e) |
|
39 error("Hash method "..e.." not available",2); |
|
40 end |
|
41 local e=setmetatable({},{__index=e}); |
|
42 local function t(e,a) |
|
43 local e,o=pcall(require,e); |
|
44 if e then a(o);end |
|
45 end |
|
46 t("bgcrypto.md5",function(t) |
|
47 e.md5=t.digest; |
|
48 e.hmac_md5=t.hmac.digest; |
|
49 end); |
|
50 t("bgcrypto.sha1",function(t) |
|
51 e.sha1=t.digest; |
|
52 e.hmac_sha1=t.hmac.digest; |
|
53 e.scram_Hi_sha1=function(a,o,e)return t.pbkdf2(a,o,e,20);end; |
|
54 end); |
|
55 t("bgcrypto.sha256",function(t) |
|
56 e.sha256=t.digest; |
|
57 e.hmac_sha256=t.hmac.digest; |
|
58 end); |
|
59 t("bgcrypto.sha512",function(t) |
|
60 e.sha512=t.digest; |
|
61 e.hmac_sha512=t.hmac.digest; |
|
62 end); |
|
63 t("sha1",function(t) |
|
64 e.sha1=function(e,a) |
|
65 if a then |
|
66 return t.sha1(e); |
|
67 else |
|
68 return(t.binary(e)); |
|
69 end |
|
70 end; |
|
71 end); |
|
72 return e; |
|
73 end) |
|
74 package.preload['lib.adhoc']=(function(...) |
|
75 local _ENV=_ENV; |
|
76 local function d(t,...) |
|
77 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
78 package.loaded[t]=e; |
|
79 for t=1,select("#",...)do |
|
80 (select(t,...))(e); |
|
81 end |
|
82 _ENV=e; |
|
83 _M=e; |
|
84 return e; |
|
85 end |
|
86 local s,i=require"util.stanza",require"util.uuid"; |
|
87 local r="http://jabber.org/protocol/commands"; |
|
88 local n={} |
|
89 local h={}; |
|
90 local function o(e,o,a,t) |
|
91 local e=s.stanza("command",{xmlns=r,node=e.node,status=o}); |
|
92 if a then e.attr.sessionid=a;end |
|
93 if t then e.attr.action=t;end |
|
94 return e; |
|
95 end |
|
96 function h.new(t,i,e,a) |
|
97 return{name=t,node=i,handler=e,cmdtag=o,permission=(a or"user")}; |
|
98 end |
|
99 function h.handle_cmd(o,h,t) |
|
100 local e=t.tags[1].attr.sessionid or i.generate(); |
|
101 local a={}; |
|
102 a.to=t.attr.to; |
|
103 a.from=t.attr.from; |
|
104 a.action=t.tags[1].attr.action or"execute"; |
|
105 a.form=t.tags[1]:child_with_ns("jabber:x:data"); |
|
106 local a,i=o:handler(a,n[e]); |
|
107 n[e]=i; |
|
108 local i=s.reply(t); |
|
109 local t; |
|
110 if a.status=="completed"then |
|
111 n[e]=nil; |
|
112 t=o:cmdtag("completed",e); |
|
113 elseif a.status=="canceled"then |
|
114 n[e]=nil; |
|
115 t=o:cmdtag("canceled",e); |
|
116 elseif a.status=="error"then |
|
117 n[e]=nil; |
|
118 i=s.error_reply(i,a.error.type,a.error.condition,a.error.message); |
|
119 h.send(i); |
|
120 return true; |
|
121 else |
|
122 t=o:cmdtag("executing",e); |
|
123 end |
|
124 for a,e in pairs(a)do |
|
125 if a=="info"then |
|
126 t:tag("note",{type="info"}):text(e):up(); |
|
127 elseif a=="warn"then |
|
128 t:tag("note",{type="warn"}):text(e):up(); |
|
129 elseif a=="error"then |
|
130 t:tag("note",{type="error"}):text(e.message):up(); |
|
131 elseif a=="actions"then |
|
132 local a=s.stanza("actions"); |
|
133 for i,e in ipairs(e)do |
|
134 if(e=="prev")or(e=="next")or(e=="complete")then |
|
135 a:tag(e):up(); |
|
136 else |
|
137 d:log("error",'Command "'..o.name.. |
|
138 '" at node "'..o.node..'" provided an invalid action "'..e..'"'); |
|
139 end |
|
140 end |
|
141 t:add_child(a); |
|
142 elseif a=="form"then |
|
143 t:add_child((e.layout or e):form(e.values)); |
|
144 elseif a=="result"then |
|
145 t:add_child((e.layout or e):form(e.values,"result")); |
|
146 elseif a=="other"then |
|
147 t:add_child(e); |
|
148 end |
|
149 end |
|
150 i:add_child(t); |
|
151 h.send(i); |
|
152 return true; |
|
153 end |
|
154 return h; |
|
155 end) |
|
156 package.preload['util.stanza']=(function(...) |
|
157 local _ENV=_ENV; |
|
158 local function e(t,...) |
|
159 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
160 package.loaded[t]=e; |
|
161 for t=1,select("#",...)do |
|
162 (select(t,...))(e); |
|
163 end |
|
164 _ENV=e; |
|
165 _M=e; |
|
166 return e; |
|
167 end |
|
168 local i=error; |
|
169 local t=table.insert; |
|
170 local l=table.remove; |
|
171 local p=table.concat; |
|
172 local r=string.format; |
|
173 local c=string.match; |
|
174 local f=tostring; |
|
175 local w=setmetatable; |
|
176 local q=getmetatable; |
|
177 local n=pairs; |
|
178 local s=ipairs; |
|
179 local a=type; |
|
180 local j=string.gsub; |
|
181 local m=string.sub; |
|
182 local u=string.find; |
|
183 local e=os; |
|
184 local h=require"util.encodings".utf8.valid; |
|
185 local y=not e.getenv("WINDIR"); |
|
186 local d,o; |
|
187 if y then |
|
188 local t,e=pcall(require,"util.termcolours"); |
|
189 if t then |
|
190 d,o=e.getstyle,e.getstring; |
|
191 else |
|
192 y=nil; |
|
193 end |
|
194 end |
|
195 local v="urn:ietf:params:xml:ns:xmpp-stanzas"; |
|
196 local _ENV=nil; |
|
197 local e={__name="stanza"}; |
|
198 e.__index=e; |
|
199 local function g(e,t) |
|
200 if a(e)~="string"then |
|
201 i("invalid "..t.." name: expected string, got "..a(e)); |
|
202 elseif#e==0 then |
|
203 i("invalid "..t.." name: empty string"); |
|
204 elseif u(e,"[<>& '\"]")then |
|
205 i("invalid "..t.." name: contains invalid characters"); |
|
206 elseif not h(e)then |
|
207 i("invalid "..t.." name: contains invalid utf8"); |
|
208 end |
|
209 end |
|
210 local function b(e,t) |
|
211 if a(e)~="string"then |
|
212 i("invalid "..t.." value: expected string, got "..a(e)); |
|
213 elseif not h(e)then |
|
214 i("invalid "..t.." value: contains invalid utf8"); |
|
215 end |
|
216 end |
|
217 local function k(e) |
|
218 if e~=nil then |
|
219 if a(e)~="table"then |
|
220 i("invalid attributes, expected table got "..a(e)); |
|
221 end |
|
222 for t,e in n(e)do |
|
223 g(t,"attribute"); |
|
224 b(e,"attribute"); |
|
225 if a(e)~="string"then |
|
226 i("invalid attribute value for '"..t.."': expected string, got "..a(e)); |
|
227 elseif not h(e)then |
|
228 i("invalid attribute value for '"..t.."': contains invalid utf8"); |
|
229 end |
|
230 end |
|
231 end |
|
232 end |
|
233 local function h(t,a,o) |
|
234 g(t,"tag"); |
|
235 k(a); |
|
236 local t={name=t,attr=a or{},namespaces=o,tags={}}; |
|
237 return w(t,e); |
|
238 end |
|
239 local function g(t) |
|
240 return q(t)==e; |
|
241 end |
|
242 function e:query(e) |
|
243 return self:tag("query",{xmlns=e}); |
|
244 end |
|
245 function e:body(t,e) |
|
246 return self:tag("body",e):text(t); |
|
247 end |
|
248 function e:text_tag(o,a,t,e) |
|
249 return self:tag(o,t,e):text(a):up(); |
|
250 end |
|
251 function e:tag(e,a,o) |
|
252 local a=h(e,a,o); |
|
253 local e=self.last_add; |
|
254 if not e then e={};self.last_add=e;end |
|
255 (e[#e]or self):add_direct_child(a); |
|
256 t(e,a); |
|
257 return self; |
|
258 end |
|
259 function e:text(t) |
|
260 if t~=nil and t~=""then |
|
261 local e=self.last_add; |
|
262 (e and e[#e]or self):add_direct_child(t); |
|
263 end |
|
264 return self; |
|
265 end |
|
266 function e:up() |
|
267 local e=self.last_add; |
|
268 if e then l(e);end |
|
269 return self; |
|
270 end |
|
271 function e:reset() |
|
272 self.last_add=nil; |
|
273 return self; |
|
274 end |
|
275 function e:add_direct_child(e) |
|
276 if g(e)then |
|
277 t(self.tags,e); |
|
278 t(self,e); |
|
279 else |
|
280 b(e,"text"); |
|
281 t(self,e); |
|
282 end |
|
283 end |
|
284 function e:add_child(t) |
|
285 local e=self.last_add; |
|
286 (e and e[#e]or self):add_direct_child(t); |
|
287 return self; |
|
288 end |
|
289 function e:remove_children(a,e) |
|
290 e=e or self.attr.xmlns; |
|
291 return self:maptags(function(t) |
|
292 if(not a or t.name==a)and t.attr.xmlns==e then |
|
293 return nil; |
|
294 end |
|
295 return t; |
|
296 end); |
|
297 end |
|
298 function e:get_child(a,t) |
|
299 for o,e in s(self.tags)do |
|
300 if(not a or e.name==a) |
|
301 and((not t and self.attr.xmlns==e.attr.xmlns) |
|
302 or e.attr.xmlns==t)then |
|
303 return e; |
|
304 end |
|
305 end |
|
306 end |
|
307 function e:get_child_text(t,e) |
|
308 local e=self:get_child(t,e); |
|
309 if e then |
|
310 return e:get_text(); |
|
311 end |
|
312 return nil; |
|
313 end |
|
314 function e:child_with_name(t) |
|
315 for a,e in s(self.tags)do |
|
316 if e.name==t then return e;end |
|
317 end |
|
318 end |
|
319 function e:child_with_ns(t) |
|
320 for a,e in s(self.tags)do |
|
321 if e.attr.xmlns==t then return e;end |
|
322 end |
|
323 end |
|
324 function e:children() |
|
325 local e=0; |
|
326 return function(t) |
|
327 e=e+1 |
|
328 return t[e]; |
|
329 end,self,e; |
|
330 end |
|
331 function e:childtags(t,a) |
|
332 local e=self.tags; |
|
333 local o,i=1,#e; |
|
334 return function() |
|
335 for i=o,i do |
|
336 local e=e[i]; |
|
337 if(not t or e.name==t) |
|
338 and((not a and self.attr.xmlns==e.attr.xmlns) |
|
339 or e.attr.xmlns==a)then |
|
340 o=i+1; |
|
341 return e; |
|
342 end |
|
343 end |
|
344 end; |
|
345 end |
|
346 function e:maptags(h) |
|
347 local o,t=self.tags,1; |
|
348 local n,a=#self,#o; |
|
349 local s=n+1; |
|
350 local e=1; |
|
351 while t<=a and a>0 do |
|
352 if self[e]==o[t]then |
|
353 local i=h(self[e]); |
|
354 if i==nil then |
|
355 l(self,e); |
|
356 l(o,t); |
|
357 n=n-1; |
|
358 a=a-1; |
|
359 e=e-1; |
|
360 t=t-1; |
|
361 else |
|
362 self[e]=i; |
|
363 o[t]=i; |
|
364 end |
|
365 t=t+1; |
|
366 end |
|
367 e=e+1; |
|
368 if e>s then |
|
369 i("Invalid stanza state! Please report this error."); |
|
370 end |
|
371 end |
|
372 return self; |
|
373 end |
|
374 function e:find(a) |
|
375 local e=1; |
|
376 local s=#a+1; |
|
377 repeat |
|
378 local o,t,i; |
|
379 local n=m(a,e,e); |
|
380 if n=="@"then |
|
381 return self.attr[m(a,e+1)]; |
|
382 elseif n=="{"then |
|
383 o,e=c(a,"^([^}]+)}()",e+1); |
|
384 end |
|
385 t,i,e=c(a,"^([^@/#]*)([/#]?)()",e); |
|
386 t=t~=""and t or nil; |
|
387 if e==s then |
|
388 if i=="#"then |
|
389 return self:get_child_text(t,o); |
|
390 end |
|
391 return self:get_child(t,o); |
|
392 end |
|
393 self=self:get_child(t,o); |
|
394 until not self |
|
395 end |
|
396 local i={["'"]="'",["\""]=""",["<"]="<",[">"]=">",["&"]="&"}; |
|
397 local function l(e)return(j(e,"['&<>\"]",i));end |
|
398 local function m(o,e,s,a,r) |
|
399 local i=0; |
|
400 local h=o.name |
|
401 t(e,"<"..h); |
|
402 for o,n in n(o.attr)do |
|
403 if u(o,"\1",1,true)then |
|
404 local o,s=c(o,"^([^\1]*)\1?(.*)$"); |
|
405 i=i+1; |
|
406 t(e," xmlns:ns"..i.."='"..a(o).."' ".."ns"..i..":"..s.."='"..a(n).."'"); |
|
407 elseif not(o=="xmlns"and n==r)then |
|
408 t(e," "..o.."='"..a(n).."'"); |
|
409 end |
|
410 end |
|
411 local i=#o; |
|
412 if i==0 then |
|
413 t(e,"/>"); |
|
414 else |
|
415 t(e,">"); |
|
416 for i=1,i do |
|
417 local i=o[i]; |
|
418 if i.name then |
|
419 s(i,e,s,a,o.attr.xmlns); |
|
420 else |
|
421 t(e,a(i)); |
|
422 end |
|
423 end |
|
424 t(e,"</"..h..">"); |
|
425 end |
|
426 end |
|
427 function e.__tostring(t) |
|
428 local e={}; |
|
429 m(t,e,m,l,nil); |
|
430 return p(e); |
|
431 end |
|
432 function e.top_tag(e) |
|
433 local t=""; |
|
434 if e.attr then |
|
435 for e,o in n(e.attr)do if a(e)=="string"then t=t..r(" %s='%s'",e,l(f(o)));end end |
|
436 end |
|
437 return r("<%s%s>",e.name,t); |
|
438 end |
|
439 function e.get_text(e) |
|
440 if#e.tags==0 then |
|
441 return p(e); |
|
442 end |
|
443 end |
|
444 function e.get_error(a) |
|
445 local o,t,e; |
|
446 local a=a:get_child("error"); |
|
447 if not a then |
|
448 return nil,nil,nil; |
|
449 end |
|
450 o=a.attr.type; |
|
451 for o,a in s(a.tags)do |
|
452 if a.attr.xmlns==v then |
|
453 if not e and a.name=="text"then |
|
454 e=a:get_text(); |
|
455 elseif not t then |
|
456 t=a.name; |
|
457 end |
|
458 if t and e then |
|
459 break; |
|
460 end |
|
461 end |
|
462 end |
|
463 return o,t or"undefined-condition",e; |
|
464 end |
|
465 local function m(o) |
|
466 local i={name=o.name,attr=o.attr}; |
|
467 for o,e in s(o)do |
|
468 if a(e)=="table"then |
|
469 t(i,m(e)); |
|
470 else |
|
471 t(i,e); |
|
472 end |
|
473 end |
|
474 return i; |
|
475 end |
|
476 e.__freeze=m; |
|
477 local function p(o) |
|
478 if o then |
|
479 local i=o.attr; |
|
480 for e=1,#i do i[e]=nil;end |
|
481 local h={}; |
|
482 for e in n(i)do |
|
483 if u(e,"|",1,true)and not u(e,"\1",1,true)then |
|
484 local a,t=c(e,"^([^|]+)|(.+)$"); |
|
485 h[a.."\1"..t]=i[e]; |
|
486 i[e]=nil; |
|
487 end |
|
488 end |
|
489 for e,t in n(h)do |
|
490 i[e]=t; |
|
491 end |
|
492 w(o,e); |
|
493 for t,e in s(o)do |
|
494 if a(e)=="table"then |
|
495 p(e); |
|
496 end |
|
497 end |
|
498 if not o.tags then |
|
499 local e={}; |
|
500 for n,i in s(o)do |
|
501 if a(i)=="table"then |
|
502 t(e,i); |
|
503 end |
|
504 end |
|
505 o.tags=e; |
|
506 end |
|
507 end |
|
508 return o; |
|
509 end |
|
510 local function u(a) |
|
511 local i,h={},{}; |
|
512 for t,e in n(a.attr)do i[t]=e;end |
|
513 local s,o=a.namespaces; |
|
514 if s then |
|
515 o={}; |
|
516 for e,t in n(s)do o[e]=t;end |
|
517 end |
|
518 local o={name=a.name,attr=i,namespaces=o,tags=h}; |
|
519 for e=1,#a do |
|
520 local e=a[e]; |
|
521 if e.name then |
|
522 e=u(e); |
|
523 t(h,e); |
|
524 end |
|
525 t(o,e); |
|
526 end |
|
527 return w(o,e); |
|
528 end |
|
529 local function w(t,e) |
|
530 if not e then |
|
531 return h("message",t); |
|
532 else |
|
533 return h("message",t):tag("body"):text(e):up(); |
|
534 end |
|
535 end |
|
536 local function b(e) |
|
537 if not(e and e.id)then |
|
538 end |
|
539 return h("iq",e); |
|
540 end |
|
541 local function c(e) |
|
542 return h(e.name, |
|
543 e.attr and{ |
|
544 to=e.attr.from, |
|
545 from=e.attr.to, |
|
546 id=e.attr.id, |
|
547 type=((e.name=="iq"and"result")or e.attr.type) |
|
548 }); |
|
549 end |
|
550 local t={xmlns=v}; |
|
551 local function v(e,i,o,a) |
|
552 local e=c(e); |
|
553 e.attr.type="error"; |
|
554 e:tag("error",{type=i}) |
|
555 :tag(o,t):up(); |
|
556 if a then e:tag("text",t):text(a):up();end |
|
557 return e; |
|
558 end |
|
559 local function k(e) |
|
560 return h("presence",e); |
|
561 end |
|
562 if y then |
|
563 local i=d("yellow"); |
|
564 local u=d("red"); |
|
565 local h=d("red"); |
|
566 local t=d("magenta"); |
|
567 local i=" "..o(i,"%s")..o(t,"=")..o(u,"'%s'"); |
|
568 local d=o(t,"<")..o(h,"%s").."%s"..o(t,">"); |
|
569 local h=d.."%s"..o(t,"</")..o(h,"%s")..o(t,">"); |
|
570 function e.pretty_print(t) |
|
571 local e=""; |
|
572 for o,t in s(t)do |
|
573 if a(t)=="string"then |
|
574 e=e..l(t); |
|
575 else |
|
576 e=e..t:pretty_print(); |
|
577 end |
|
578 end |
|
579 local o=""; |
|
580 if t.attr then |
|
581 for e,t in n(t.attr)do if a(e)=="string"then o=o..r(i,e,f(t));end end |
|
582 end |
|
583 return r(h,t.name,o,e,t.name); |
|
584 end |
|
585 function e.pretty_top_tag(t) |
|
586 local e=""; |
|
587 if t.attr then |
|
588 for t,o in n(t.attr)do if a(t)=="string"then e=e..r(i,t,f(o));end end |
|
589 end |
|
590 return r(d,t.name,e); |
|
591 end |
|
592 else |
|
593 e.pretty_print=e.__tostring; |
|
594 e.pretty_top_tag=e.top_tag; |
|
595 end |
|
596 return{ |
|
597 stanza_mt=e; |
|
598 stanza=h; |
|
599 is_stanza=g; |
|
600 preserialize=m; |
|
601 deserialize=p; |
|
602 clone=u; |
|
603 message=w; |
|
604 iq=b; |
|
605 reply=c; |
|
606 error_reply=v; |
|
607 presence=k; |
|
608 xml_escape=l; |
|
609 }; |
|
610 end) |
|
611 package.preload['util.timer']=(function(...) |
|
612 local _ENV=_ENV; |
|
613 local function u(t,...) |
|
614 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
615 package.loaded[t]=e; |
|
616 for t=1,select("#",...)do |
|
617 (select(t,...))(e); |
|
618 end |
|
619 _ENV=e; |
|
620 _M=e; |
|
621 return e; |
|
622 end |
|
623 local o=require"net.server"; |
|
624 local h=math.min |
|
625 local l=math.huge |
|
626 local i=require"socket".gettime; |
|
627 local s=table.insert; |
|
628 local d=pairs; |
|
629 local r=type; |
|
630 local n={}; |
|
631 local a={}; |
|
632 u"timer" |
|
633 local e; |
|
634 if not o.event then |
|
635 function e(t,n) |
|
636 local i=i(); |
|
637 t=t+i; |
|
638 if t>=i then |
|
639 s(a,{t,n}); |
|
640 else |
|
641 local t=n(i); |
|
642 if t and r(t)=="number"then |
|
643 return e(t,n); |
|
644 end |
|
645 end |
|
646 end |
|
647 o._addtimer(function() |
|
648 local o=i(); |
|
649 if#a>0 then |
|
650 for t,e in d(a)do |
|
651 s(n,e); |
|
652 end |
|
653 a={}; |
|
654 end |
|
655 local t=l; |
|
656 for d,a in d(n)do |
|
657 local s,i=a[1],a[2]; |
|
658 if s<=o then |
|
659 n[d]=nil; |
|
660 local a=i(o); |
|
661 if r(a)=="number"then |
|
662 e(a,i); |
|
663 t=h(t,a); |
|
664 end |
|
665 else |
|
666 t=h(t,s-o); |
|
667 end |
|
668 end |
|
669 return t; |
|
670 end); |
|
671 else |
|
672 local t=o.event; |
|
673 local n=o.event_base; |
|
674 local o=(t.core and t.core.LEAVE)or-1; |
|
675 function e(a,e) |
|
676 local t; |
|
677 t=n:addevent(nil,0,function() |
|
678 local e=e(i()); |
|
679 if e then |
|
680 return 0,e; |
|
681 elseif t then |
|
682 return o; |
|
683 end |
|
684 end |
|
685 ,a); |
|
686 end |
|
687 end |
|
688 add_task=e; |
|
689 return _M; |
|
690 end) |
|
691 package.preload['util.termcolours']=(function(...) |
|
692 local _ENV=_ENV; |
|
693 local function s(t,...) |
|
694 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
695 package.loaded[t]=e; |
|
696 for t=1,select("#",...)do |
|
697 (select(t,...))(e); |
|
698 end |
|
699 _ENV=e; |
|
700 _M=e; |
|
701 return e; |
|
702 end |
|
703 local i,n=table.concat,table.insert; |
|
704 local t,a=string.char,string.format; |
|
705 local h=tonumber; |
|
706 local r=ipairs; |
|
707 local d=io.write; |
|
708 local e; |
|
709 if os.getenv("WINDIR")then |
|
710 e=require"util.windows"; |
|
711 end |
|
712 local o=e and e.get_consolecolor and e.get_consolecolor(); |
|
713 s"termcolours" |
|
714 local s={ |
|
715 reset=0;bright=1,dim=2,underscore=4,blink=5,reverse=7,hidden=8; |
|
716 black=30;red=31;green=32;yellow=33;blue=34;magenta=35;cyan=36;white=37; |
|
717 ["black background"]=40;["red background"]=41;["green background"]=42;["yellow background"]=43;["blue background"]=44;["magenta background"]=45;["cyan background"]=46;["white background"]=47; |
|
718 bold=1,dark=2,underline=4,underlined=4,normal=0; |
|
719 } |
|
720 local l={ |
|
721 ["0"]=o, |
|
722 ["1"]=7+8, |
|
723 ["1;33"]=2+4+8, |
|
724 ["1;31"]=4+8 |
|
725 } |
|
726 local u={ |
|
727 [1]="font-weight: bold",[2]="opacity: 0.5",[4]="text-decoration: underline",[8]="visibility: hidden", |
|
728 [30]="color:black",[31]="color:red",[32]="color:green",[33]="color:#FFD700", |
|
729 [34]="color:blue",[35]="color: magenta",[36]="color:cyan",[37]="color: white", |
|
730 [40]="background-color:black",[41]="background-color:red",[42]="background-color:green", |
|
731 [43]="background-color:yellow",[44]="background-color:blue",[45]="background-color: magenta", |
|
732 [46]="background-color:cyan",[47]="background-color: white"; |
|
733 }; |
|
734 local c=t(27).."[%sm%s"..t(27).."[0m"; |
|
735 function getstring(t,e) |
|
736 if t then |
|
737 return a(c,t,e); |
|
738 else |
|
739 return e; |
|
740 end |
|
741 end |
|
742 function getstyle(...) |
|
743 local e,t={...},{}; |
|
744 for a,e in r(e)do |
|
745 e=s[e]; |
|
746 if e then |
|
747 n(t,e); |
|
748 end |
|
749 end |
|
750 return i(t,";"); |
|
751 end |
|
752 local a="0"; |
|
753 function setstyle(e) |
|
754 e=e or"0"; |
|
755 if e~=a then |
|
756 d("\27["..e.."m"); |
|
757 a=e; |
|
758 end |
|
759 end |
|
760 if e then |
|
761 function setstyle(t) |
|
762 t=t or"0"; |
|
763 if t~=a then |
|
764 e.set_consolecolor(l[t]or o); |
|
765 a=t; |
|
766 end |
|
767 end |
|
768 if not o then |
|
769 function setstyle(e)end |
|
770 end |
|
771 end |
|
772 local function a(t) |
|
773 if t=="0"then return"</span>";end |
|
774 local e={}; |
|
775 for t in t:gmatch("[^;]+")do |
|
776 n(e,u[h(t)]); |
|
777 end |
|
778 return"</span><span style='"..i(e,";").."'>"; |
|
779 end |
|
780 function tohtml(e) |
|
781 return e:gsub("\027%[(.-)m",a); |
|
782 end |
|
783 return _M; |
|
784 end) |
|
785 package.preload['util.uuid']=(function(...) |
|
786 local _ENV=_ENV; |
|
787 local function a(t,...) |
|
788 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
789 package.loaded[t]=e; |
|
790 for t=1,select("#",...)do |
|
791 (select(t,...))(e); |
|
792 end |
|
793 _ENV=e; |
|
794 _M=e; |
|
795 return e; |
|
796 end |
|
797 local i=tostring; |
|
798 local e=os.time; |
|
799 local o=os.clock; |
|
800 local n=require"util.hashes".sha1; |
|
801 a"uuid" |
|
802 local t=0; |
|
803 local function a() |
|
804 local e=e(); |
|
805 if t>=e then e=t+1;end |
|
806 t=e; |
|
807 return e; |
|
808 end |
|
809 local function t(e) |
|
810 return n(e..o()..i({}),true); |
|
811 end |
|
812 local e=t(a()); |
|
813 local function o(a) |
|
814 e=t(e..a); |
|
815 end |
|
816 local function t(t) |
|
817 if#e<t then o(a());end |
|
818 local a=e:sub(0,t); |
|
819 e=e:sub(t+1); |
|
820 return a; |
|
821 end |
|
822 local function e() |
|
823 return("%x"):format(t(1):byte()%4+8); |
|
824 end |
|
825 function generate() |
|
826 return t(8).."-"..t(4).."-4"..t(3).."-"..(e())..t(3).."-"..t(12); |
|
827 end |
|
828 seed=o; |
|
829 return _M; |
|
830 end) |
|
831 package.preload['net.dns']=(function(...) |
|
832 local _ENV=_ENV; |
|
833 local function c(t,...) |
|
834 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
835 package.loaded[t]=e; |
|
836 for t=1,select("#",...)do |
|
837 (select(t,...))(e); |
|
838 end |
|
839 _ENV=e; |
|
840 _M=e; |
|
841 return e; |
|
842 end |
|
843 local n=require"socket"; |
|
844 local j=require"util.timer"; |
|
845 local e,y=pcall(require,"util.windows"); |
|
846 local E=(e and y)or os.getenv("WINDIR"); |
|
847 local u,_,v,a,i= |
|
848 coroutine,io,math,string,table; |
|
849 local f,s,o,m,r,b,z,x,t,e,q= |
|
850 ipairs,next,pairs,print,setmetatable,tostring,assert,error,unpack,select,type; |
|
851 local e={ |
|
852 get=function(t,...) |
|
853 local a=e('#',...); |
|
854 for a=1,a do |
|
855 t=t[e(a,...)]; |
|
856 if t==nil then break;end |
|
857 end |
|
858 return t; |
|
859 end; |
|
860 set=function(a,...) |
|
861 local i=e('#',...); |
|
862 local h,o=e(i-1,...); |
|
863 local t,n; |
|
864 for i=1,i-2 do |
|
865 local i=e(i,...) |
|
866 local e=a[i] |
|
867 if o==nil then |
|
868 if e==nil then |
|
869 return; |
|
870 elseif s(e,s(e))then |
|
871 t=nil;n=nil; |
|
872 elseif t==nil then |
|
873 t=a;n=i; |
|
874 end |
|
875 elseif e==nil then |
|
876 e={}; |
|
877 a[i]=e; |
|
878 end |
|
879 a=e |
|
880 end |
|
881 if o==nil and t then |
|
882 t[n]=nil; |
|
883 else |
|
884 a[h]=o; |
|
885 return o; |
|
886 end |
|
887 end; |
|
888 }; |
|
889 local d,l=e.get,e.set; |
|
890 local k=15; |
|
891 c('dns') |
|
892 local t=_M; |
|
893 local h=i.insert |
|
894 local function c(e) |
|
895 return(e-(e%256))/256; |
|
896 end |
|
897 local function p(e) |
|
898 local t={}; |
|
899 for o,e in o(e)do |
|
900 t[o]=e; |
|
901 t[e]=e; |
|
902 t[a.lower(e)]=e; |
|
903 end |
|
904 return t; |
|
905 end |
|
906 local function w(i) |
|
907 local e={}; |
|
908 for t,i in o(i)do |
|
909 local o=a.char(c(t),t%256); |
|
910 e[t]=o; |
|
911 e[i]=o; |
|
912 e[a.lower(i)]=o; |
|
913 end |
|
914 return e; |
|
915 end |
|
916 t.types={ |
|
917 'A','NS','MD','MF','CNAME','SOA','MB','MG','MR','NULL','WKS', |
|
918 'PTR','HINFO','MINFO','MX','TXT', |
|
919 [28]='AAAA',[29]='LOC',[33]='SRV', |
|
920 [252]='AXFR',[253]='MAILB',[254]='MAILA',[255]='*'}; |
|
921 t.classes={'IN','CS','CH','HS',[255]='*'}; |
|
922 t.type=p(t.types); |
|
923 t.class=p(t.classes); |
|
924 t.typecode=w(t.types); |
|
925 t.classcode=w(t.classes); |
|
926 local function g(e,o,i) |
|
927 if a.byte(e,-1)~=46 then e=e..'.';end |
|
928 e=a.lower(e); |
|
929 return e,t.type[o or'A'],t.class[i or'IN']; |
|
930 end |
|
931 local function p(t,a,o) |
|
932 a=a or n.gettime(); |
|
933 for n,e in f(t)do |
|
934 if e.tod then |
|
935 e.ttl=v.floor(e.tod-a); |
|
936 if e.ttl<=0 then |
|
937 t[e[e.type:lower()]]=nil; |
|
938 i.remove(t,n); |
|
939 return p(t,a,o); |
|
940 end |
|
941 elseif o=='soft'then |
|
942 z(e.ttl==0); |
|
943 t[e[e.type:lower()]]=nil; |
|
944 i.remove(t,n); |
|
945 end |
|
946 end |
|
947 end |
|
948 local e={}; |
|
949 e.__index=e; |
|
950 e.timeout=k; |
|
951 local function k(e) |
|
952 local e=e.type and e[e.type:lower()]; |
|
953 if q(e)~="string"then |
|
954 return"<UNKNOWN RDATA TYPE>"; |
|
955 end |
|
956 return e; |
|
957 end |
|
958 local w={ |
|
959 LOC=e.LOC_tostring; |
|
960 MX=function(e) |
|
961 return a.format('%2i %s',e.pref,e.mx); |
|
962 end; |
|
963 SRV=function(e) |
|
964 local e=e.srv; |
|
965 return a.format('%5d %5d %5d %s',e.priority,e.weight,e.port,e.target); |
|
966 end; |
|
967 }; |
|
968 local q={}; |
|
969 function q.__tostring(e) |
|
970 local t=(w[e.type]or k)(e); |
|
971 return a.format('%2s %-5s %6i %-28s %s',e.class,e.type,e.ttl,e.name,t); |
|
972 end |
|
973 local k={}; |
|
974 function k.__tostring(t) |
|
975 local e={}; |
|
976 for a,t in f(t)do |
|
977 h(e,b(t)..'\n'); |
|
978 end |
|
979 return i.concat(e); |
|
980 end |
|
981 local w={}; |
|
982 function w.__tostring(t) |
|
983 local a=n.gettime(); |
|
984 local e={}; |
|
985 for i,t in o(t)do |
|
986 for i,t in o(t)do |
|
987 for o,t in o(t)do |
|
988 p(t,a); |
|
989 h(e,b(t)); |
|
990 end |
|
991 end |
|
992 end |
|
993 return i.concat(e); |
|
994 end |
|
995 function e:new() |
|
996 local t={active={},cache={},unsorted={}}; |
|
997 r(t,e); |
|
998 r(t.cache,w); |
|
999 r(t.unsorted,{__mode='kv'}); |
|
1000 return t; |
|
1001 end |
|
1002 function t.random(...) |
|
1003 v.randomseed(v.floor(1e4*n.gettime())%2147483648); |
|
1004 t.random=v.random; |
|
1005 return t.random(...); |
|
1006 end |
|
1007 local function v(e) |
|
1008 e=e or{}; |
|
1009 e.id=e.id or t.random(0,65535); |
|
1010 e.rd=e.rd or 1; |
|
1011 e.tc=e.tc or 0; |
|
1012 e.aa=e.aa or 0; |
|
1013 e.opcode=e.opcode or 0; |
|
1014 e.qr=e.qr or 0; |
|
1015 e.rcode=e.rcode or 0; |
|
1016 e.z=e.z or 0; |
|
1017 e.ra=e.ra or 0; |
|
1018 e.qdcount=e.qdcount or 1; |
|
1019 e.ancount=e.ancount or 0; |
|
1020 e.nscount=e.nscount or 0; |
|
1021 e.arcount=e.arcount or 0; |
|
1022 local t=a.char( |
|
1023 c(e.id),e.id%256, |
|
1024 e.rd+2*e.tc+4*e.aa+8*e.opcode+128*e.qr, |
|
1025 e.rcode+16*e.z+128*e.ra, |
|
1026 c(e.qdcount),e.qdcount%256, |
|
1027 c(e.ancount),e.ancount%256, |
|
1028 c(e.nscount),e.nscount%256, |
|
1029 c(e.arcount),e.arcount%256 |
|
1030 ); |
|
1031 return t,e.id; |
|
1032 end |
|
1033 local function c(t) |
|
1034 local e={}; |
|
1035 for t in a.gmatch(t,'[^.]+')do |
|
1036 h(e,a.char(a.len(t))); |
|
1037 h(e,t); |
|
1038 end |
|
1039 h(e,a.char(0)); |
|
1040 return i.concat(e); |
|
1041 end |
|
1042 local function z(o,a,e) |
|
1043 o=c(o); |
|
1044 a=t.typecode[a or'a']; |
|
1045 e=t.classcode[e or'in']; |
|
1046 return o..a..e; |
|
1047 end |
|
1048 function e:byte(e) |
|
1049 e=e or 1; |
|
1050 local o=self.offset; |
|
1051 local t=o+e-1; |
|
1052 if t>#self.packet then |
|
1053 x(a.format('out of bounds: %i>%i',t,#self.packet)); |
|
1054 end |
|
1055 self.offset=o+e; |
|
1056 return a.byte(self.packet,o,t); |
|
1057 end |
|
1058 function e:word() |
|
1059 local e,t=self:byte(2); |
|
1060 return 256*e+t; |
|
1061 end |
|
1062 function e:dword() |
|
1063 local t,e,a,o=self:byte(4); |
|
1064 return 16777216*t+65536*e+256*a+o; |
|
1065 end |
|
1066 function e:sub(e) |
|
1067 e=e or 1; |
|
1068 local t=a.sub(self.packet,self.offset,self.offset+e-1); |
|
1069 self.offset=self.offset+e; |
|
1070 return t; |
|
1071 end |
|
1072 function e:header(t) |
|
1073 local e=self:word(); |
|
1074 if not self.active[e]and not t then return nil;end |
|
1075 local e={id=e}; |
|
1076 local t,a=self:byte(2); |
|
1077 e.rd=t%2; |
|
1078 e.tc=t/2%2; |
|
1079 e.aa=t/4%2; |
|
1080 e.opcode=t/8%16; |
|
1081 e.qr=t/128; |
|
1082 e.rcode=a%16; |
|
1083 e.z=a/16%8; |
|
1084 e.ra=a/128; |
|
1085 e.qdcount=self:word(); |
|
1086 e.ancount=self:word(); |
|
1087 e.nscount=self:word(); |
|
1088 e.arcount=self:word(); |
|
1089 for a,t in o(e)do e[a]=t-t%1;end |
|
1090 return e; |
|
1091 end |
|
1092 function e:name() |
|
1093 local t,a=nil,0; |
|
1094 local e=self:byte(); |
|
1095 local o={}; |
|
1096 if e==0 then return"."end |
|
1097 while e>0 do |
|
1098 if e>=192 then |
|
1099 a=a+1; |
|
1100 if a>=20 then x('dns error: 20 pointers');end; |
|
1101 local e=((e-192)*256)+self:byte(); |
|
1102 t=t or self.offset; |
|
1103 self.offset=e+1; |
|
1104 else |
|
1105 h(o,self:sub(e)..'.'); |
|
1106 end |
|
1107 e=self:byte(); |
|
1108 end |
|
1109 self.offset=t or self.offset; |
|
1110 return i.concat(o); |
|
1111 end |
|
1112 function e:question() |
|
1113 local e={}; |
|
1114 e.name=self:name(); |
|
1115 e.type=t.type[self:word()]; |
|
1116 e.class=t.class[self:word()]; |
|
1117 return e; |
|
1118 end |
|
1119 function e:A(i) |
|
1120 local o,e,t,n=self:byte(4); |
|
1121 i.a=a.format('%i.%i.%i.%i',o,e,t,n); |
|
1122 end |
|
1123 function e:AAAA(a) |
|
1124 local e={}; |
|
1125 for t=1,a.rdlength,2 do |
|
1126 local a,t=self:byte(2); |
|
1127 i.insert(e,("%02x%02x"):format(a,t)); |
|
1128 end |
|
1129 e=i.concat(e,":"):gsub("%f[%x]0+(%x)","%1"); |
|
1130 local t={}; |
|
1131 for e in e:gmatch(":[0:]+:")do |
|
1132 i.insert(t,e) |
|
1133 end |
|
1134 if#t==0 then |
|
1135 a.aaaa=e; |
|
1136 return |
|
1137 elseif#t>1 then |
|
1138 i.sort(t,function(t,e)return#t>#e end); |
|
1139 end |
|
1140 a.aaaa=e:gsub(t[1],"::",1):gsub("^0::","::"):gsub("::0$","::"); |
|
1141 end |
|
1142 function e:CNAME(e) |
|
1143 e.cname=self:name(); |
|
1144 end |
|
1145 function e:MX(e) |
|
1146 e.pref=self:word(); |
|
1147 e.mx=self:name(); |
|
1148 end |
|
1149 function e:LOC_nibble_power() |
|
1150 local e=self:byte(); |
|
1151 return((e-(e%16))/16)*(10^(e%16)); |
|
1152 end |
|
1153 function e:LOC(e) |
|
1154 e.version=self:byte(); |
|
1155 if e.version==0 then |
|
1156 e.loc=e.loc or{}; |
|
1157 e.loc.size=self:LOC_nibble_power(); |
|
1158 e.loc.horiz_pre=self:LOC_nibble_power(); |
|
1159 e.loc.vert_pre=self:LOC_nibble_power(); |
|
1160 e.loc.latitude=self:dword(); |
|
1161 e.loc.longitude=self:dword(); |
|
1162 e.loc.altitude=self:dword(); |
|
1163 end |
|
1164 end |
|
1165 local function c(e,i,t) |
|
1166 e=e-2147483648; |
|
1167 if e<0 then i=t;e=-e;end |
|
1168 local n,o,t; |
|
1169 t=e%6e4; |
|
1170 e=(e-t)/6e4; |
|
1171 o=e%60; |
|
1172 n=(e-o)/60; |
|
1173 return a.format('%3d %2d %2.3f %s',n,o,t/1e3,i); |
|
1174 end |
|
1175 function e.LOC_tostring(e) |
|
1176 local t={}; |
|
1177 h(t,a.format( |
|
1178 '%s %s %.2fm %.2fm %.2fm %.2fm', |
|
1179 c(e.loc.latitude,'N','S'), |
|
1180 c(e.loc.longitude,'E','W'), |
|
1181 (e.loc.altitude-1e7)/100, |
|
1182 e.loc.size/100, |
|
1183 e.loc.horiz_pre/100, |
|
1184 e.loc.vert_pre/100 |
|
1185 )); |
|
1186 return i.concat(t); |
|
1187 end |
|
1188 function e:NS(e) |
|
1189 e.ns=self:name(); |
|
1190 end |
|
1191 function e:SOA(e) |
|
1192 end |
|
1193 function e:SRV(e) |
|
1194 e.srv={}; |
|
1195 e.srv.priority=self:word(); |
|
1196 e.srv.weight=self:word(); |
|
1197 e.srv.port=self:word(); |
|
1198 e.srv.target=self:name(); |
|
1199 end |
|
1200 function e:PTR(e) |
|
1201 e.ptr=self:name(); |
|
1202 end |
|
1203 function e:TXT(e) |
|
1204 e.txt=self:sub(self:byte()); |
|
1205 end |
|
1206 function e:rr() |
|
1207 local e={}; |
|
1208 r(e,q); |
|
1209 e.name=self:name(self); |
|
1210 e.type=t.type[self:word()]or e.type; |
|
1211 e.class=t.class[self:word()]or e.class; |
|
1212 e.ttl=65536*self:word()+self:word(); |
|
1213 e.rdlength=self:word(); |
|
1214 if e.ttl<=0 then |
|
1215 e.tod=self.time+30; |
|
1216 else |
|
1217 e.tod=self.time+e.ttl; |
|
1218 end |
|
1219 local a=self.offset; |
|
1220 local t=self[t.type[e.type]]; |
|
1221 if t then t(self,e);end |
|
1222 self.offset=a; |
|
1223 e.rdata=self:sub(e.rdlength); |
|
1224 return e; |
|
1225 end |
|
1226 function e:rrs(t) |
|
1227 local e={}; |
|
1228 for t=1,t do h(e,self:rr());end |
|
1229 return e; |
|
1230 end |
|
1231 function e:decode(t,o) |
|
1232 self.packet,self.offset=t,1; |
|
1233 local t=self:header(o); |
|
1234 if not t then return nil;end |
|
1235 local t={header=t}; |
|
1236 t.question={}; |
|
1237 local i=self.offset; |
|
1238 for e=1,t.header.qdcount do |
|
1239 h(t.question,self:question()); |
|
1240 end |
|
1241 t.question.raw=a.sub(self.packet,i,self.offset-1); |
|
1242 if not o then |
|
1243 if not self.active[t.header.id]or not self.active[t.header.id][t.question.raw]then |
|
1244 self.active[t.header.id]=nil; |
|
1245 return nil; |
|
1246 end |
|
1247 end |
|
1248 t.answer=self:rrs(t.header.ancount); |
|
1249 t.authority=self:rrs(t.header.nscount); |
|
1250 t.additional=self:rrs(t.header.arcount); |
|
1251 return t; |
|
1252 end |
|
1253 e.delays={1,3}; |
|
1254 function e:addnameserver(e) |
|
1255 self.server=self.server or{}; |
|
1256 h(self.server,e); |
|
1257 end |
|
1258 function e:setnameserver(e) |
|
1259 self.server={}; |
|
1260 self:addnameserver(e); |
|
1261 end |
|
1262 function e:adddefaultnameservers() |
|
1263 if E then |
|
1264 if y and y.get_nameservers then |
|
1265 for t,e in f(y.get_nameservers())do |
|
1266 self:addnameserver(e); |
|
1267 end |
|
1268 end |
|
1269 if not self.server or#self.server==0 then |
|
1270 self:addnameserver("208.67.222.222"); |
|
1271 self:addnameserver("208.67.220.220"); |
|
1272 end |
|
1273 else |
|
1274 local e=_.open("/etc/resolv.conf"); |
|
1275 if e then |
|
1276 for e in e:lines()do |
|
1277 e=e:gsub("#.*$","") |
|
1278 :match('^%s*nameserver%s+(.*)%s*$'); |
|
1279 if e then |
|
1280 e:gsub("%f[%d.](%d+%.%d+%.%d+%.%d+)%f[^%d.]",function(e) |
|
1281 self:addnameserver(e) |
|
1282 end); |
|
1283 end |
|
1284 end |
|
1285 end |
|
1286 if not self.server or#self.server==0 then |
|
1287 self:addnameserver("127.0.0.1"); |
|
1288 end |
|
1289 end |
|
1290 end |
|
1291 function e:getsocket(a) |
|
1292 self.socket=self.socket or{}; |
|
1293 self.socketset=self.socketset or{}; |
|
1294 local e=self.socket[a]; |
|
1295 if e then return e;end |
|
1296 local o,t; |
|
1297 e,t=n.udp(); |
|
1298 if e and self.socket_wrapper then e,t=self.socket_wrapper(e,self);end |
|
1299 if not e then |
|
1300 return nil,t; |
|
1301 end |
|
1302 e:settimeout(0); |
|
1303 self.socket[a]=e; |
|
1304 self.socketset[e]=a; |
|
1305 o,t=e:setsockname('*',0); |
|
1306 if not o then return self:servfail(e,t);end |
|
1307 o,t=e:setpeername(self.server[a],53); |
|
1308 if not o then return self:servfail(e,t);end |
|
1309 return e; |
|
1310 end |
|
1311 function e:voidsocket(e) |
|
1312 if self.socket[e]then |
|
1313 self.socketset[self.socket[e]]=nil; |
|
1314 self.socket[e]=nil; |
|
1315 elseif self.socketset[e]then |
|
1316 self.socket[self.socketset[e]]=nil; |
|
1317 self.socketset[e]=nil; |
|
1318 end |
|
1319 e:close(); |
|
1320 end |
|
1321 function e:socket_wrapper_set(e) |
|
1322 self.socket_wrapper=e; |
|
1323 end |
|
1324 function e:closeall() |
|
1325 for t,e in f(self.socket)do |
|
1326 self.socket[t]=nil; |
|
1327 self.socketset[e]=nil; |
|
1328 e:close(); |
|
1329 end |
|
1330 end |
|
1331 function e:remember(e,t) |
|
1332 local a,o,i=g(e.name,e.type,e.class); |
|
1333 if t~='*'then |
|
1334 t=o; |
|
1335 local t=d(self.cache,i,'*',a); |
|
1336 if t then h(t,e);end |
|
1337 end |
|
1338 self.cache=self.cache or r({},w); |
|
1339 local a=d(self.cache,i,t,a)or |
|
1340 l(self.cache,i,t,a,r({},k)); |
|
1341 if not a[e[o:lower()]]then |
|
1342 a[e[o:lower()]]=true; |
|
1343 h(a,e); |
|
1344 end |
|
1345 if t=='MX'then self.unsorted[a]=true;end |
|
1346 end |
|
1347 local function c(t,e) |
|
1348 return(t.pref==e.pref)and(t.mx<e.mx)or(t.pref<e.pref); |
|
1349 end |
|
1350 function e:peek(o,t,a,h) |
|
1351 o,t,a=g(o,t,a); |
|
1352 local e=d(self.cache,a,t,o); |
|
1353 if not e then |
|
1354 if h then if h<=0 then return end else h=3 end |
|
1355 e=d(self.cache,a,"CNAME",o); |
|
1356 if not(e and e[1])then return end |
|
1357 return self:peek(e[1].cname,t,a,h-1); |
|
1358 end |
|
1359 if p(e,n.gettime())and t=='*'or not s(e)then |
|
1360 l(self.cache,a,t,o,nil); |
|
1361 return nil; |
|
1362 end |
|
1363 if self.unsorted[e]then i.sort(e,c);self.unsorted[e]=nil;end |
|
1364 return e; |
|
1365 end |
|
1366 function e:purge(e) |
|
1367 if e=='soft'then |
|
1368 self.time=n.gettime(); |
|
1369 for t,e in o(self.cache or{})do |
|
1370 for t,e in o(e)do |
|
1371 for t,e in o(e)do |
|
1372 p(e,self.time,'soft') |
|
1373 end |
|
1374 end |
|
1375 end |
|
1376 else self.cache=r({},w);end |
|
1377 end |
|
1378 function e:query(a,t,e) |
|
1379 a,t,e=g(a,t,e) |
|
1380 local s=u.running(); |
|
1381 local o=d(self.wanted,e,t,a); |
|
1382 if s and o then |
|
1383 l(self.wanted,e,t,a,s,true); |
|
1384 return true; |
|
1385 end |
|
1386 if not self.server then self:adddefaultnameservers();end |
|
1387 local h=z(a,t,e); |
|
1388 local o=self:peek(a,t,e); |
|
1389 if o then return o;end |
|
1390 local o,i=v(); |
|
1391 local o={ |
|
1392 packet=o..h, |
|
1393 server=self.best_server, |
|
1394 delay=1, |
|
1395 retry=n.gettime()+self.delays[1] |
|
1396 }; |
|
1397 self.active[i]=self.active[i]or{}; |
|
1398 self.active[i][h]=o; |
|
1399 if s then |
|
1400 l(self.wanted,e,t,a,s,true); |
|
1401 end |
|
1402 local i,h=self:getsocket(o.server) |
|
1403 if not i then |
|
1404 return nil,h; |
|
1405 end |
|
1406 i:send(o.packet) |
|
1407 if j and self.timeout then |
|
1408 local r=#self.server; |
|
1409 local n=1; |
|
1410 j.add_task(self.timeout,function() |
|
1411 if d(self.wanted,e,t,a,s)then |
|
1412 if n<r then |
|
1413 n=n+1; |
|
1414 self:servfail(i); |
|
1415 o.server=self.best_server; |
|
1416 i,h=self:getsocket(o.server); |
|
1417 if i then |
|
1418 i:send(o.packet); |
|
1419 return self.timeout; |
|
1420 end |
|
1421 end |
|
1422 self:cancel(e,t,a); |
|
1423 end |
|
1424 end) |
|
1425 end |
|
1426 return true; |
|
1427 end |
|
1428 function e:servfail(t,i) |
|
1429 local h=self.socketset[t] |
|
1430 t=self:voidsocket(t); |
|
1431 self.time=n.gettime(); |
|
1432 for n,a in o(self.active)do |
|
1433 for o,e in o(a)do |
|
1434 if e.server==h then |
|
1435 e.server=e.server+1 |
|
1436 if e.server>#self.server then |
|
1437 e.server=1; |
|
1438 end |
|
1439 e.retries=(e.retries or 0)+1; |
|
1440 if e.retries>=#self.server then |
|
1441 a[o]=nil; |
|
1442 else |
|
1443 t,i=self:getsocket(e.server); |
|
1444 if t then t:send(e.packet);end |
|
1445 end |
|
1446 end |
|
1447 end |
|
1448 if s(a)==nil then |
|
1449 self.active[n]=nil; |
|
1450 end |
|
1451 end |
|
1452 if h==self.best_server then |
|
1453 self.best_server=self.best_server+1; |
|
1454 if self.best_server>#self.server then |
|
1455 self.best_server=1; |
|
1456 end |
|
1457 end |
|
1458 return t,i; |
|
1459 end |
|
1460 function e:settimeout(e) |
|
1461 self.timeout=e; |
|
1462 end |
|
1463 function e:receive(t) |
|
1464 self.time=n.gettime(); |
|
1465 t=t or self.socket; |
|
1466 local e; |
|
1467 for a,t in o(t)do |
|
1468 if self.socketset[t]then |
|
1469 local t=t:receive(); |
|
1470 if t then |
|
1471 e=self:decode(t); |
|
1472 if e and self.active[e.header.id] |
|
1473 and self.active[e.header.id][e.question.raw]then |
|
1474 for a,t in o(e.answer)do |
|
1475 self:remember(t,e.question[1].type) |
|
1476 end |
|
1477 local t=self.active[e.header.id]; |
|
1478 t[e.question.raw]=nil; |
|
1479 if not s(t)then self.active[e.header.id]=nil;end |
|
1480 if not s(self.active)then self:closeall();end |
|
1481 local e=e.question[1]; |
|
1482 local t=d(self.wanted,e.class,e.type,e.name); |
|
1483 if t then |
|
1484 for e in o(t)do |
|
1485 if u.status(e)=="suspended"then u.resume(e);end |
|
1486 end |
|
1487 l(self.wanted,e.class,e.type,e.name,nil); |
|
1488 end |
|
1489 end |
|
1490 end |
|
1491 end |
|
1492 end |
|
1493 return e; |
|
1494 end |
|
1495 function e:feed(a,t,e) |
|
1496 self.time=n.gettime(); |
|
1497 local e=self:decode(t,e); |
|
1498 if e and self.active[e.header.id] |
|
1499 and self.active[e.header.id][e.question.raw]then |
|
1500 for a,t in o(e.answer)do |
|
1501 self:remember(t,e.question[1].type); |
|
1502 end |
|
1503 local t=self.active[e.header.id]; |
|
1504 t[e.question.raw]=nil; |
|
1505 if not s(t)then self.active[e.header.id]=nil;end |
|
1506 if not s(self.active)then self:closeall();end |
|
1507 local e=e.question[1]; |
|
1508 if e then |
|
1509 local t=d(self.wanted,e.class,e.type,e.name); |
|
1510 if t then |
|
1511 for e in o(t)do |
|
1512 if u.status(e)=="suspended"then u.resume(e);end |
|
1513 end |
|
1514 l(self.wanted,e.class,e.type,e.name,nil); |
|
1515 end |
|
1516 end |
|
1517 end |
|
1518 return e; |
|
1519 end |
|
1520 function e:cancel(e,t,a) |
|
1521 local i=d(self.wanted,e,t,a); |
|
1522 if i then |
|
1523 for e in o(i)do |
|
1524 if u.status(e)=="suspended"then u.resume(e);end |
|
1525 end |
|
1526 l(self.wanted,e,t,a,nil); |
|
1527 end |
|
1528 end |
|
1529 function e:pulse() |
|
1530 while self:receive()do end |
|
1531 if not s(self.active)then return nil;end |
|
1532 self.time=n.gettime(); |
|
1533 for i,t in o(self.active)do |
|
1534 for a,e in o(t)do |
|
1535 if self.time>=e.retry then |
|
1536 e.server=e.server+1; |
|
1537 if e.server>#self.server then |
|
1538 e.server=1; |
|
1539 e.delay=e.delay+1; |
|
1540 end |
|
1541 if e.delay>#self.delays then |
|
1542 t[a]=nil; |
|
1543 if not s(t)then self.active[i]=nil;end |
|
1544 if not s(self.active)then return nil;end |
|
1545 else |
|
1546 local t=self.socket[e.server]; |
|
1547 if t then t:send(e.packet);end |
|
1548 e.retry=self.time+self.delays[e.delay]; |
|
1549 end |
|
1550 end |
|
1551 end |
|
1552 end |
|
1553 if s(self.active)then return true;end |
|
1554 return nil; |
|
1555 end |
|
1556 function e:lookup(o,a,t) |
|
1557 self:query(o,a,t) |
|
1558 while self:pulse()do |
|
1559 local e={} |
|
1560 for a,t in f(self.socket)do |
|
1561 e[a]=t |
|
1562 end |
|
1563 n.select(e,nil,4) |
|
1564 end |
|
1565 return self:peek(o,a,t); |
|
1566 end |
|
1567 function e:lookupex(o,e,t,a) |
|
1568 return self:peek(e,t,a)or self:query(e,t,a); |
|
1569 end |
|
1570 function e:tohostname(e) |
|
1571 return t.lookup(e:gsub("(%d+)%.(%d+)%.(%d+)%.(%d+)","%4.%3.%2.%1.in-addr.arpa."),"PTR"); |
|
1572 end |
|
1573 local i={ |
|
1574 qr={[0]='query','response'}, |
|
1575 opcode={[0]='query','inverse query','server status request'}, |
|
1576 aa={[0]='non-authoritative','authoritative'}, |
|
1577 tc={[0]='complete','truncated'}, |
|
1578 rd={[0]='recursion not desired','recursion desired'}, |
|
1579 ra={[0]='recursion not available','recursion available'}, |
|
1580 z={[0]='(reserved)'}, |
|
1581 rcode={[0]='no error','format error','server failure','name error','not implemented'}, |
|
1582 type=t.type, |
|
1583 class=t.class |
|
1584 }; |
|
1585 local function s(t,e) |
|
1586 return(i[e]and i[e][t[e]])or''; |
|
1587 end |
|
1588 function e.print(t) |
|
1589 for o,e in o{'id','qr','opcode','aa','tc','rd','ra','z', |
|
1590 'rcode','qdcount','ancount','nscount','arcount'}do |
|
1591 m(a.format('%-30s','header.'..e),t.header[e],s(t.header,e)); |
|
1592 end |
|
1593 for t,e in f(t.question)do |
|
1594 m(a.format('question[%i].name ',t),e.name); |
|
1595 m(a.format('question[%i].type ',t),e.type); |
|
1596 m(a.format('question[%i].class ',t),e.class); |
|
1597 end |
|
1598 local r={name=1,type=1,class=1,ttl=1,rdlength=1,rdata=1}; |
|
1599 local e; |
|
1600 for i,n in o({'answer','authority','additional'})do |
|
1601 for h,i in o(t[n])do |
|
1602 for o,t in o({'name','type','class','ttl','rdlength'})do |
|
1603 e=a.format('%s[%i].%s',n,h,t); |
|
1604 m(a.format('%-30s',e),i[t],s(i,t)); |
|
1605 end |
|
1606 for t,o in o(i)do |
|
1607 if not r[t]then |
|
1608 e=a.format('%s[%i].%s',n,h,t); |
|
1609 m(a.format('%-30s %s',b(e),b(o))); |
|
1610 end |
|
1611 end |
|
1612 end |
|
1613 end |
|
1614 end |
|
1615 function t.resolver() |
|
1616 local t={active={},cache={},unsorted={},wanted={},best_server=1}; |
|
1617 r(t,e); |
|
1618 r(t.cache,w); |
|
1619 r(t.unsorted,{__mode='kv'}); |
|
1620 return t; |
|
1621 end |
|
1622 local e=t.resolver(); |
|
1623 t._resolver=e; |
|
1624 function t.lookup(...) |
|
1625 return e:lookup(...); |
|
1626 end |
|
1627 function t.tohostname(...) |
|
1628 return e:tohostname(...); |
|
1629 end |
|
1630 function t.purge(...) |
|
1631 return e:purge(...); |
|
1632 end |
|
1633 function t.peek(...) |
|
1634 return e:peek(...); |
|
1635 end |
|
1636 function t.query(...) |
|
1637 return e:query(...); |
|
1638 end |
|
1639 function t.feed(...) |
|
1640 return e:feed(...); |
|
1641 end |
|
1642 function t.cancel(...) |
|
1643 return e:cancel(...); |
|
1644 end |
|
1645 function t.settimeout(...) |
|
1646 return e:settimeout(...); |
|
1647 end |
|
1648 function t.cache() |
|
1649 return e.cache; |
|
1650 end |
|
1651 function t.socket_wrapper_set(...) |
|
1652 return e:socket_wrapper_set(...); |
|
1653 end |
|
1654 return t; |
|
1655 end) |
|
1656 package.preload['net.adns']=(function(...) |
|
1657 local _ENV=_ENV; |
|
1658 local function o(t,...) |
|
1659 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
1660 package.loaded[t]=e; |
|
1661 for t=1,select("#",...)do |
|
1662 (select(t,...))(e); |
|
1663 end |
|
1664 _ENV=e; |
|
1665 _M=e; |
|
1666 return e; |
|
1667 end |
|
1668 local c=require"net.server"; |
|
1669 local a=require"net.dns"; |
|
1670 local e=require"util.logger".init("adns"); |
|
1671 local t,t=table.insert,table.remove; |
|
1672 local n,s,l=coroutine,tostring,pcall; |
|
1673 local function u(a,a,t,e)return(e-t)+1;end |
|
1674 o"adns" |
|
1675 function lookup(d,t,h,r) |
|
1676 return n.wrap(function(o) |
|
1677 if o then |
|
1678 e("debug","Records for %s already cached, using those...",t); |
|
1679 d(o); |
|
1680 return; |
|
1681 end |
|
1682 e("debug","Records for %s not in cache, sending query (%s)...",t,s(n.running())); |
|
1683 local i,o=a.query(t,h,r); |
|
1684 if i then |
|
1685 n.yield({r or"IN",h or"A",t,n.running()}); |
|
1686 e("debug","Reply for %s (%s)",t,s(n.running())); |
|
1687 end |
|
1688 if i then |
|
1689 i,o=l(d,a.peek(t,h,r)); |
|
1690 else |
|
1691 e("error","Error sending DNS query: %s",o); |
|
1692 i,o=l(d,nil,o); |
|
1693 end |
|
1694 if not i then |
|
1695 e("error","Error in DNS response handler: %s",s(o)); |
|
1696 end |
|
1697 end)(a.peek(t,h,r)); |
|
1698 end |
|
1699 function cancel(t,o,i) |
|
1700 e("warn","Cancelling DNS lookup for %s",s(t[3])); |
|
1701 a.cancel(t[1],t[2],t[3],t[4],o); |
|
1702 end |
|
1703 function new_async_socket(i,o) |
|
1704 local n="<unknown>"; |
|
1705 local s={}; |
|
1706 local t={}; |
|
1707 local h; |
|
1708 function s.onincoming(o,e) |
|
1709 if e then |
|
1710 a.feed(t,e); |
|
1711 end |
|
1712 end |
|
1713 function s.ondisconnect(i,a) |
|
1714 if a then |
|
1715 e("warn","DNS socket for %s disconnected: %s",n,a); |
|
1716 local t=o.server; |
|
1717 if o.socketset[i]==o.best_server and o.best_server==#t then |
|
1718 e("error","Exhausted all %d configured DNS servers, next lookup will try %s again",#t,t[1]); |
|
1719 end |
|
1720 o:servfail(i); |
|
1721 end |
|
1722 end |
|
1723 t,h=c.wrapclient(i,"dns",53,s); |
|
1724 if not t then |
|
1725 return nil,h; |
|
1726 end |
|
1727 t.settimeout=function()end |
|
1728 t.setsockname=function(e,...)return i:setsockname(...);end |
|
1729 t.setpeername=function(o,...)n=(...);local e,a=i:setpeername(...);o:set_send(u);return e,a;end |
|
1730 t.connect=function(e,...)return i:connect(...)end |
|
1731 t.send=function(a,t) |
|
1732 e("debug","Sending DNS query to %s",n); |
|
1733 return i:send(t); |
|
1734 end |
|
1735 return t; |
|
1736 end |
|
1737 a.socket_wrapper_set(new_async_socket); |
|
1738 return _M; |
|
1739 end) |
|
1740 package.preload['net.server']=(function(...) |
|
1741 local _ENV=_ENV; |
|
1742 local function e(t,...) |
|
1743 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
1744 package.loaded[t]=e; |
|
1745 for t=1,select("#",...)do |
|
1746 (select(t,...))(e); |
|
1747 end |
|
1748 _ENV=e; |
|
1749 _M=e; |
|
1750 return e; |
|
1751 end |
|
1752 local m=function(e) |
|
1753 return _G[e] |
|
1754 end |
|
1755 local W,e=require("util.logger").init("socket"),table.concat; |
|
1756 local n=function(...)return W("debug",e{...});end |
|
1757 local E=function(...)return W("warn",e{...});end |
|
1758 local ue=1 |
|
1759 local f=m"type" |
|
1760 local q=m"pairs" |
|
1761 local me=m"ipairs" |
|
1762 local y=m"tonumber" |
|
1763 local u=m"tostring" |
|
1764 local t=m"table" |
|
1765 local a=m"string" |
|
1766 local e=m"coroutine" |
|
1767 local Y=math.min |
|
1768 local ce=math.huge |
|
1769 local fe=t.concat |
|
1770 local de=t.insert |
|
1771 local ye=a.sub |
|
1772 local we=e.wrap |
|
1773 local pe=e.yield |
|
1774 local I,e=pcall(require,"ssl") |
|
1775 local b=m"socket"or require"socket" |
|
1776 local P=b.gettime |
|
1777 local le=b.dns.getaddrinfo |
|
1778 local ve=(I and e.wrap) |
|
1779 local se=b.bind |
|
1780 local be=b.select |
|
1781 local O |
|
1782 local Z |
|
1783 local ie |
|
1784 local V |
|
1785 local B |
|
1786 local l |
|
1787 local ne |
|
1788 local X |
|
1789 local oe |
|
1790 local te |
|
1791 local ae |
|
1792 local J |
|
1793 local s |
|
1794 local he |
|
1795 local ee |
|
1796 local re |
|
1797 local p |
|
1798 local i |
|
1799 local C |
|
1800 local r |
|
1801 local h |
|
1802 local A |
|
1803 local v |
|
1804 local w |
|
1805 local k |
|
1806 local z |
|
1807 local a |
|
1808 local o |
|
1809 local g |
|
1810 local F |
|
1811 local M |
|
1812 local T |
|
1813 local j |
|
1814 local R |
|
1815 local Q |
|
1816 local d |
|
1817 local S |
|
1818 local L |
|
1819 local U |
|
1820 local D |
|
1821 local H |
|
1822 local _ |
|
1823 local x |
|
1824 local N |
|
1825 p={} |
|
1826 i={} |
|
1827 r={} |
|
1828 C={} |
|
1829 h={} |
|
1830 v={} |
|
1831 w={} |
|
1832 A={} |
|
1833 k={} |
|
1834 a=0 |
|
1835 o=0 |
|
1836 g=0 |
|
1837 F=0 |
|
1838 M=0 |
|
1839 T=1 |
|
1840 j=128 |
|
1841 R=10 |
|
1842 S=51e3*1024 |
|
1843 L=25e3*1024 |
|
1844 U=30 |
|
1845 D=6e4 |
|
1846 H=14*60 |
|
1847 local e=package.config:sub(1,1)=="\\" |
|
1848 x=(e and math.huge)or b._SETSIZE or 1024 |
|
1849 _=b._SETSIZE or 1024 |
|
1850 N=30 |
|
1851 te=function(y,t,m,c,g,w) |
|
1852 if t:getfd()>=x then |
|
1853 E("server.lua: Disallowed FD number: "..t:getfd()) |
|
1854 t:close() |
|
1855 return nil,"fd-too-large" |
|
1856 end |
|
1857 local f=0 |
|
1858 local v,e=y.onconnect,y.ondisconnect |
|
1859 local b=t.accept |
|
1860 local e={} |
|
1861 e.shutdown=function()end |
|
1862 e.ssl=function() |
|
1863 return w~=nil |
|
1864 end |
|
1865 e.sslctx=function() |
|
1866 return w |
|
1867 end |
|
1868 e.remove=function() |
|
1869 f=f-1 |
|
1870 if e then |
|
1871 e.resume() |
|
1872 end |
|
1873 end |
|
1874 e.close=function() |
|
1875 t:close() |
|
1876 o=s(r,t,o) |
|
1877 a=s(i,t,a) |
|
1878 p[m..":"..c]=nil; |
|
1879 h[t]=nil |
|
1880 e=nil |
|
1881 t=nil |
|
1882 n"server.lua: closed server handler and removed sockets from list" |
|
1883 end |
|
1884 e.pause=function(o) |
|
1885 if not e.paused then |
|
1886 a=s(i,t,a) |
|
1887 if o then |
|
1888 h[t]=nil |
|
1889 t:close() |
|
1890 t=nil; |
|
1891 end |
|
1892 e.paused=true; |
|
1893 n("server.lua: server [",m,"]:",c," paused") |
|
1894 end |
|
1895 end |
|
1896 e.resume=function() |
|
1897 if e.paused then |
|
1898 if not t then |
|
1899 t=se(m,c,j); |
|
1900 t:settimeout(0) |
|
1901 end |
|
1902 a=l(i,t,a) |
|
1903 h[t]=e |
|
1904 k[e]=nil |
|
1905 e.paused=false; |
|
1906 n("server.lua: server [",m,"]:",c," resumed") |
|
1907 end |
|
1908 end |
|
1909 e.ip=function() |
|
1910 return m |
|
1911 end |
|
1912 e.serverport=function() |
|
1913 return c |
|
1914 end |
|
1915 e.socket=function() |
|
1916 return t |
|
1917 end |
|
1918 e.readbuffer=function() |
|
1919 if a>=_ or o>=_ then |
|
1920 e.pause() |
|
1921 k[e]=d |
|
1922 n("server.lua: refused new client connection: server full") |
|
1923 return false |
|
1924 end |
|
1925 local t,o=b(t) |
|
1926 if t then |
|
1927 local o,a=t:getpeername() |
|
1928 local e,i,t=ee(e,y,t,o,c,a,g,w) |
|
1929 if t then |
|
1930 return false |
|
1931 end |
|
1932 f=f+1 |
|
1933 n("server.lua: accepted new client connection from ",u(o),":",u(a)," to ",u(c)) |
|
1934 if v and not w then |
|
1935 return v(e); |
|
1936 end |
|
1937 return; |
|
1938 elseif o then |
|
1939 n("server.lua: error with new client connection: ",u(o)) |
|
1940 e.pause() |
|
1941 k[e]=d |
|
1942 return false |
|
1943 end |
|
1944 end |
|
1945 return e |
|
1946 end |
|
1947 ee=function(b,f,t,R,X,D,H,q) |
|
1948 if t:getfd()>=x then |
|
1949 E("server.lua: Disallowed FD number: "..t:getfd()) |
|
1950 t:close() |
|
1951 if b then |
|
1952 k[b]=d |
|
1953 b.pause() |
|
1954 end |
|
1955 return nil,nil,"fd-too-large" |
|
1956 end |
|
1957 t:settimeout(0) |
|
1958 local y |
|
1959 local T |
|
1960 local g |
|
1961 local K |
|
1962 local G=f.onincoming |
|
1963 local B=f.onstatus |
|
1964 local k=f.ondisconnect |
|
1965 local W=f.ondrain |
|
1966 local J=f.onreadtimeout; |
|
1967 local C=f.ondetach |
|
1968 local p={} |
|
1969 local c=0 |
|
1970 local Q |
|
1971 local U |
|
1972 local m=0 |
|
1973 local j=false |
|
1974 local E=false |
|
1975 local Y,P=0,0 |
|
1976 local x=S |
|
1977 local _=L |
|
1978 local e=p |
|
1979 e.dispatch=function() |
|
1980 return G |
|
1981 end |
|
1982 e.disconnect=function() |
|
1983 return k |
|
1984 end |
|
1985 e.onreadtimeout=J; |
|
1986 e.setlistener=function(a,t) |
|
1987 if C then |
|
1988 C(a) |
|
1989 end |
|
1990 G=t.onincoming |
|
1991 k=t.ondisconnect |
|
1992 B=t.onstatus |
|
1993 W=t.ondrain |
|
1994 e.onreadtimeout=t.onreadtimeout |
|
1995 C=t.ondetach |
|
1996 end |
|
1997 e.getstats=function() |
|
1998 return P,Y |
|
1999 end |
|
2000 e.ssl=function() |
|
2001 return K |
|
2002 end |
|
2003 e.sslctx=function() |
|
2004 return q |
|
2005 end |
|
2006 e.send=function(n,a,o,i) |
|
2007 return y(t,a,o,i) |
|
2008 end |
|
2009 e.receive=function(o,a) |
|
2010 return T(t,o,a) |
|
2011 end |
|
2012 e.shutdown=function(a) |
|
2013 return g(t,a) |
|
2014 end |
|
2015 e.setoption=function(i,a,o) |
|
2016 if t.setoption then |
|
2017 return t:setoption(a,o); |
|
2018 end |
|
2019 return false,"setoption not implemented"; |
|
2020 end |
|
2021 e.force_close=function(t,a) |
|
2022 if c~=0 then |
|
2023 n("server.lua: discarding unwritten data for ",u(R),":",u(D)) |
|
2024 c=0; |
|
2025 end |
|
2026 return t:close(a); |
|
2027 end |
|
2028 e.close=function(l,d) |
|
2029 if not e then return true;end |
|
2030 a=s(i,t,a) |
|
2031 v[e]=nil |
|
2032 if c~=0 then |
|
2033 e.sendbuffer() |
|
2034 if c~=0 then |
|
2035 if e then |
|
2036 e.write=nil |
|
2037 end |
|
2038 Q=true |
|
2039 return false |
|
2040 end |
|
2041 end |
|
2042 if t then |
|
2043 z=g and g(t) |
|
2044 t:close() |
|
2045 o=s(r,t,o) |
|
2046 h[t]=nil |
|
2047 t=nil |
|
2048 else |
|
2049 n"server.lua: socket already closed" |
|
2050 end |
|
2051 if e then |
|
2052 w[e]=nil |
|
2053 A[e]=nil |
|
2054 local t=e; |
|
2055 e=nil |
|
2056 if k then |
|
2057 k(t,d or false); |
|
2058 k=nil |
|
2059 end |
|
2060 end |
|
2061 if b then |
|
2062 b.remove() |
|
2063 end |
|
2064 n"server.lua: closed client handler and removed socket from list" |
|
2065 return true |
|
2066 end |
|
2067 e.server=function() |
|
2068 return b |
|
2069 end |
|
2070 e.ip=function() |
|
2071 return R |
|
2072 end |
|
2073 e.serverport=function() |
|
2074 return X |
|
2075 end |
|
2076 e.clientport=function() |
|
2077 return D |
|
2078 end |
|
2079 e.port=e.clientport |
|
2080 local b=function(i,a) |
|
2081 if not e then return false end |
|
2082 m=m+#a |
|
2083 if m>x then |
|
2084 A[e]="send buffer exceeded" |
|
2085 e.write=V |
|
2086 return false |
|
2087 elseif t and not r[t]then |
|
2088 o=l(r,t,o) |
|
2089 end |
|
2090 c=c+1 |
|
2091 p[c]=a |
|
2092 if e then |
|
2093 w[e]=w[e]or d |
|
2094 end |
|
2095 return true |
|
2096 end |
|
2097 e.write=b |
|
2098 e.bufferqueue=function(t) |
|
2099 return p |
|
2100 end |
|
2101 e.socket=function(a) |
|
2102 return t |
|
2103 end |
|
2104 e.set_mode=function(a,t) |
|
2105 H=t or H |
|
2106 return H |
|
2107 end |
|
2108 e.set_send=function(a,t) |
|
2109 y=t or y |
|
2110 return y |
|
2111 end |
|
2112 e.bufferlen=function(o,a,t) |
|
2113 x=t or x |
|
2114 _=a or _ |
|
2115 return m,_,x |
|
2116 end |
|
2117 e.lock_read=function(n,o) |
|
2118 if o==true then |
|
2119 local o=a |
|
2120 a=s(i,t,a) |
|
2121 v[e]=nil |
|
2122 if a~=o then |
|
2123 j=true |
|
2124 end |
|
2125 elseif o==false then |
|
2126 if j then |
|
2127 j=false |
|
2128 a=l(i,t,a) |
|
2129 v[e]=d |
|
2130 end |
|
2131 end |
|
2132 return j |
|
2133 end |
|
2134 e.pause=function(t) |
|
2135 return t:lock_read(true); |
|
2136 end |
|
2137 e.resume=function(t) |
|
2138 return t:lock_read(false); |
|
2139 end |
|
2140 e.lock=function(i,a) |
|
2141 e.lock_read(a) |
|
2142 if a==true then |
|
2143 e.write=V |
|
2144 local a=o |
|
2145 o=s(r,t,o) |
|
2146 w[e]=nil |
|
2147 if o~=a then |
|
2148 E=true |
|
2149 end |
|
2150 elseif a==false then |
|
2151 e.write=b |
|
2152 if E then |
|
2153 E=false |
|
2154 b("") |
|
2155 end |
|
2156 end |
|
2157 return j,E |
|
2158 end |
|
2159 local v=function() |
|
2160 local a,t,o=T(t,H) |
|
2161 if not t or(t=="wantread"or t=="timeout")then |
|
2162 local o=a or o or"" |
|
2163 local a=#o |
|
2164 if a>_ then |
|
2165 e:close("receive buffer exceeded") |
|
2166 return false |
|
2167 end |
|
2168 local a=a*ue |
|
2169 P=P+a |
|
2170 M=M+a |
|
2171 v[e]=d |
|
2172 return G(e,o,t) |
|
2173 else |
|
2174 n("server.lua: client ",u(R),":",u(D)," read error: ",u(t)) |
|
2175 z=e and e:force_close(t) |
|
2176 return false |
|
2177 end |
|
2178 end |
|
2179 local p=function() |
|
2180 local f,a,h,i,l; |
|
2181 if t then |
|
2182 i=fe(p,"",1,c) |
|
2183 f,a,h=y(t,i,1,m) |
|
2184 l=(f or h or 0)*ue |
|
2185 Y=Y+l |
|
2186 F=F+l |
|
2187 for e=c,1,-1 do |
|
2188 p[e]=nil |
|
2189 end |
|
2190 else |
|
2191 f,a,l=false,"unexpected close",0; |
|
2192 end |
|
2193 if f then |
|
2194 c=0 |
|
2195 m=0 |
|
2196 o=s(r,t,o) |
|
2197 w[e]=nil |
|
2198 if W then |
|
2199 W(e) |
|
2200 end |
|
2201 z=U and e:starttls(nil) |
|
2202 z=Q and e:force_close() |
|
2203 return true |
|
2204 elseif h and(a=="timeout"or a=="wantwrite")then |
|
2205 i=ye(i,h+1,m) |
|
2206 p[1]=i |
|
2207 c=1 |
|
2208 m=m-h |
|
2209 w[e]=d |
|
2210 return true |
|
2211 else |
|
2212 n("server.lua: client ",u(R),":",u(D)," write error: ",u(a)) |
|
2213 z=e and e:force_close(a) |
|
2214 return false |
|
2215 end |
|
2216 end |
|
2217 local d; |
|
2218 function e.set_sslctx(w,t) |
|
2219 q=t; |
|
2220 local u,m |
|
2221 d=we(function(h) |
|
2222 local t |
|
2223 for d=1,N do |
|
2224 o=(m and s(r,h,o))or o |
|
2225 a=(u and s(i,h,a))or a |
|
2226 u,m=nil,nil |
|
2227 d,t=h:dohandshake() |
|
2228 if not t then |
|
2229 n("server.lua: ssl handshake done") |
|
2230 e.readbuffer=v |
|
2231 e.sendbuffer=p |
|
2232 d=B and B(e,"ssl-handshake-complete") |
|
2233 if w.autostart_ssl and f.onconnect then |
|
2234 f.onconnect(w); |
|
2235 if c~=0 then |
|
2236 o=l(r,h,o) |
|
2237 end |
|
2238 end |
|
2239 a=l(i,h,a) |
|
2240 return true |
|
2241 else |
|
2242 if t=="wantwrite"then |
|
2243 o=l(r,h,o) |
|
2244 m=true |
|
2245 elseif t=="wantread"then |
|
2246 a=l(i,h,a) |
|
2247 u=true |
|
2248 else |
|
2249 break; |
|
2250 end |
|
2251 t=nil; |
|
2252 pe() |
|
2253 end |
|
2254 end |
|
2255 t="ssl handshake error: "..(t or"handshake too long"); |
|
2256 n("server.lua: ",t); |
|
2257 z=e and e:force_close(t) |
|
2258 return false,t |
|
2259 end |
|
2260 ) |
|
2261 end |
|
2262 if I then |
|
2263 e.starttls=function(f,m) |
|
2264 if m then |
|
2265 e:set_sslctx(m); |
|
2266 end |
|
2267 if c>0 then |
|
2268 n"server.lua: we need to do tls, but delaying until send buffer empty" |
|
2269 U=true |
|
2270 return |
|
2271 end |
|
2272 n("server.lua: attempting to start tls on "..u(t)) |
|
2273 local m,c=t |
|
2274 t,c=ve(t,q) |
|
2275 if not t then |
|
2276 n("server.lua: error while starting tls on client: ",u(c or"unknown error")) |
|
2277 return nil,c |
|
2278 end |
|
2279 t:settimeout(0) |
|
2280 y=t.send |
|
2281 T=t.receive |
|
2282 g=O |
|
2283 h[t]=e |
|
2284 a=l(i,t,a) |
|
2285 a=s(i,m,a) |
|
2286 o=s(r,m,o) |
|
2287 h[m]=nil |
|
2288 e.starttls=nil |
|
2289 U=nil |
|
2290 K=true |
|
2291 e.readbuffer=d |
|
2292 e.sendbuffer=d |
|
2293 return d(t) |
|
2294 end |
|
2295 end |
|
2296 e.readbuffer=v |
|
2297 e.sendbuffer=p |
|
2298 y=t.send |
|
2299 T=t.receive |
|
2300 g=(K and O)or t.shutdown |
|
2301 h[t]=e |
|
2302 a=l(i,t,a) |
|
2303 if q and I then |
|
2304 n"server.lua: auto-starting ssl negotiation..." |
|
2305 e.autostart_ssl=true; |
|
2306 local t,e=e:starttls(q); |
|
2307 if t==false then |
|
2308 return nil,nil,e |
|
2309 end |
|
2310 end |
|
2311 return e,t |
|
2312 end |
|
2313 O=function() |
|
2314 end |
|
2315 V=function() |
|
2316 return false |
|
2317 end |
|
2318 l=function(t,a,e) |
|
2319 if not t[a]then |
|
2320 e=e+1 |
|
2321 t[e]=a |
|
2322 t[a]=e |
|
2323 end |
|
2324 return e; |
|
2325 end |
|
2326 s=function(e,o,t) |
|
2327 local i=e[o] |
|
2328 if i then |
|
2329 e[o]=nil |
|
2330 local a=e[t] |
|
2331 e[t]=nil |
|
2332 if a~=o then |
|
2333 e[a]=i |
|
2334 e[i]=a |
|
2335 end |
|
2336 return t-1 |
|
2337 end |
|
2338 return t |
|
2339 end |
|
2340 J=function(e) |
|
2341 o=s(r,e,o) |
|
2342 a=s(i,e,a) |
|
2343 h[e]=nil |
|
2344 e:close() |
|
2345 end |
|
2346 local function z(e,a,o) |
|
2347 local t; |
|
2348 local i=a.sendbuffer; |
|
2349 function a.sendbuffer() |
|
2350 i(); |
|
2351 if t and a.bufferlen()<o then |
|
2352 e:lock_read(false); |
|
2353 t=nil; |
|
2354 end |
|
2355 end |
|
2356 local i=e.readbuffer; |
|
2357 function e.readbuffer() |
|
2358 i(); |
|
2359 if not t and a.bufferlen()>=o then |
|
2360 t=true; |
|
2361 e:lock_read(true); |
|
2362 end |
|
2363 end |
|
2364 e:set_mode("*a"); |
|
2365 end |
|
2366 ne=function(e,t,d,u,r) |
|
2367 e=e or"*" |
|
2368 local o |
|
2369 if f(d)~="table"then |
|
2370 o="invalid listener table" |
|
2371 elseif f(e)~="string"then |
|
2372 o="invalid address" |
|
2373 elseif f(t)~="number"or not(t>=0 and t<=65535)then |
|
2374 o="invalid port" |
|
2375 elseif p[e..":"..t]then |
|
2376 o="listeners on '["..e.."]:"..t.."' already exist" |
|
2377 elseif r and not I then |
|
2378 o="luasec not found" |
|
2379 end |
|
2380 if o then |
|
2381 E("server.lua, [",e,"]:",t,": ",o) |
|
2382 return nil,o |
|
2383 end |
|
2384 local o,s=se(e,t,j) |
|
2385 if s then |
|
2386 E("server.lua, [",e,"]:",t,": ",s) |
|
2387 return nil,s |
|
2388 end |
|
2389 local s,d=te(d,o,e,t,u,r) |
|
2390 if not s then |
|
2391 o:close() |
|
2392 return nil,d |
|
2393 end |
|
2394 o:settimeout(0) |
|
2395 a=l(i,o,a) |
|
2396 p[e..":"..t]=s |
|
2397 h[o]=s |
|
2398 n("server.lua: new "..(r and"ssl "or"").."server listener on '[",e,"]:",t,"'") |
|
2399 return s |
|
2400 end |
|
2401 oe=function(e,t) |
|
2402 return p[e..":"..t]; |
|
2403 end |
|
2404 he=function(e,t) |
|
2405 local a=p[e..":"..t] |
|
2406 if not a then |
|
2407 return nil,"no server found on '["..e.."]:"..u(t).."'" |
|
2408 end |
|
2409 a:close() |
|
2410 p[e..":"..t]=nil |
|
2411 return true |
|
2412 end |
|
2413 B=function() |
|
2414 for e,t in q(h)do |
|
2415 t:close() |
|
2416 h[e]=nil |
|
2417 end |
|
2418 a=0 |
|
2419 o=0 |
|
2420 g=0 |
|
2421 p={} |
|
2422 i={} |
|
2423 r={} |
|
2424 C={} |
|
2425 h={} |
|
2426 end |
|
2427 ae=function() |
|
2428 return{ |
|
2429 select_timeout=T; |
|
2430 tcp_backlog=j; |
|
2431 max_send_buffer_size=S; |
|
2432 max_receive_buffer_size=L; |
|
2433 select_idle_check_interval=U; |
|
2434 send_timeout=D; |
|
2435 read_timeout=H; |
|
2436 max_connections=_; |
|
2437 max_ssl_handshake_roundtrips=N; |
|
2438 highest_allowed_fd=x; |
|
2439 accept_retry_interval=R; |
|
2440 } |
|
2441 end |
|
2442 re=function(e) |
|
2443 if f(e)~="table"then |
|
2444 return nil,"invalid settings table" |
|
2445 end |
|
2446 T=y(e.select_timeout)or T |
|
2447 S=y(e.max_send_buffer_size)or S |
|
2448 L=y(e.max_receive_buffer_size)or L |
|
2449 U=y(e.select_idle_check_interval)or U |
|
2450 j=y(e.tcp_backlog)or j |
|
2451 D=y(e.send_timeout)or D |
|
2452 H=y(e.read_timeout)or H |
|
2453 R=y(e.accept_retry_interval)or R |
|
2454 _=e.max_connections or _ |
|
2455 N=e.max_ssl_handshake_roundtrips or N |
|
2456 x=e.highest_allowed_fd or x |
|
2457 return true |
|
2458 end |
|
2459 X=function(e) |
|
2460 if f(e)~="function"then |
|
2461 return nil,"invalid listener function" |
|
2462 end |
|
2463 g=g+1 |
|
2464 C[g]=e |
|
2465 return true |
|
2466 end |
|
2467 local u do |
|
2468 local o={}; |
|
2469 local t={}; |
|
2470 function u(e,a) |
|
2471 local o=P(); |
|
2472 e=e+o; |
|
2473 if e>=o then |
|
2474 de(t,{e,a}); |
|
2475 else |
|
2476 local e=a(o); |
|
2477 if e and f(e)=="number"then |
|
2478 return u(e,a); |
|
2479 end |
|
2480 end |
|
2481 end |
|
2482 X(function(a) |
|
2483 if#t>0 then |
|
2484 for a,e in q(t)do |
|
2485 de(o,e); |
|
2486 end |
|
2487 t={}; |
|
2488 end |
|
2489 local e=ce; |
|
2490 for s,t in q(o)do |
|
2491 local i,n=t[1],t[2]; |
|
2492 if i<=a then |
|
2493 o[s]=nil; |
|
2494 local t=n(a); |
|
2495 if f(t)=="number"then |
|
2496 u(t,n); |
|
2497 e=Y(e,t); |
|
2498 end |
|
2499 else |
|
2500 e=Y(e,i-a); |
|
2501 end |
|
2502 end |
|
2503 return e; |
|
2504 end); |
|
2505 end |
|
2506 ie=function() |
|
2507 return M,F,a,o,g |
|
2508 end |
|
2509 local e; |
|
2510 local function c(t) |
|
2511 e=t; |
|
2512 end |
|
2513 Z=function(t) |
|
2514 if e then return"quitting";end |
|
2515 if t then e="once";end |
|
2516 d=P() |
|
2517 repeat |
|
2518 local t=ce; |
|
2519 for e=1,g do |
|
2520 local e=C[e](d) |
|
2521 if e then t=Y(t,e);end |
|
2522 end |
|
2523 local t,a,o=be(i,r,Y(T,t)) |
|
2524 for t,e in me(t)do |
|
2525 local t=h[e] |
|
2526 if t then |
|
2527 t.readbuffer() |
|
2528 else |
|
2529 J(e) |
|
2530 n"server.lua: found no handler and closed socket (readlist)" |
|
2531 end |
|
2532 end |
|
2533 for e,t in me(a)do |
|
2534 local e=h[t] |
|
2535 if e then |
|
2536 e.sendbuffer() |
|
2537 else |
|
2538 J(t) |
|
2539 n"server.lua: found no handler and closed socket (writelist)" |
|
2540 end |
|
2541 end |
|
2542 for e,t in q(A)do |
|
2543 e.disconnect()(e,t) |
|
2544 e:force_close() |
|
2545 A[e]=nil; |
|
2546 end |
|
2547 d=P() |
|
2548 if d-Q>U then |
|
2549 Q=d |
|
2550 for e,t in q(w)do |
|
2551 if d-t>D then |
|
2552 e.disconnect()(e,"send timeout") |
|
2553 e:force_close() |
|
2554 end |
|
2555 end |
|
2556 for e,t in q(v)do |
|
2557 if d-t>H then |
|
2558 if not(e.onreadtimeout)or e:onreadtimeout()~=true then |
|
2559 e.disconnect()(e,"read timeout") |
|
2560 e:close() |
|
2561 else |
|
2562 v[e]=d |
|
2563 end |
|
2564 end |
|
2565 end |
|
2566 end |
|
2567 for e,t in q(k)do |
|
2568 if d-t>R then |
|
2569 k[e]=nil; |
|
2570 e.resume(); |
|
2571 end |
|
2572 end |
|
2573 until e; |
|
2574 if e=="once"then e=nil;return;end |
|
2575 B(); |
|
2576 return"quitting" |
|
2577 end |
|
2578 local function y() |
|
2579 return Z(true); |
|
2580 end |
|
2581 local function g() |
|
2582 return"select"; |
|
2583 end |
|
2584 local n=function(t,d,u,n,e,s) |
|
2585 local e,t,d=ee(nil,n,t,d,u,"clientport",e,s) |
|
2586 if not e then return nil,d end |
|
2587 h[t]=e |
|
2588 if not s then |
|
2589 a=l(i,t,a) |
|
2590 o=l(r,t,o) |
|
2591 if n.onconnect then |
|
2592 local t=e.sendbuffer; |
|
2593 e.sendbuffer=function() |
|
2594 e.sendbuffer=t; |
|
2595 n.onconnect(e); |
|
2596 return t(); |
|
2597 end |
|
2598 end |
|
2599 end |
|
2600 return e,t |
|
2601 end |
|
2602 local b=function(a,t,s,r,i,o) |
|
2603 local e |
|
2604 if f(s)~="table"then |
|
2605 e="invalid listener table" |
|
2606 elseif f(a)~="string"then |
|
2607 e="invalid address" |
|
2608 elseif f(t)~="number"or not(t>=0 and t<=65535)then |
|
2609 e="invalid port" |
|
2610 elseif i and not I then |
|
2611 e="luasec not found" |
|
2612 end |
|
2613 if le and not o then |
|
2614 local e,t=le(a) |
|
2615 if not e then return nil,t end |
|
2616 if e[1]and e[1].family=="inet6"then |
|
2617 o="tcp6" |
|
2618 end |
|
2619 end |
|
2620 local o=b[o or"tcp"] |
|
2621 if f(o)~="function"then |
|
2622 e="invalid socket type" |
|
2623 end |
|
2624 if e then |
|
2625 E("server.lua, addclient: ",e) |
|
2626 return nil,e |
|
2627 end |
|
2628 local o,e=o() |
|
2629 if e then |
|
2630 return nil,e |
|
2631 end |
|
2632 o:settimeout(0) |
|
2633 local h,e=o:connect(a,t) |
|
2634 if h or e=="timeout"or e=="Operation already in progress"then |
|
2635 return n(o,a,t,s,r,i) |
|
2636 else |
|
2637 return nil,e |
|
2638 end |
|
2639 end |
|
2640 local p=function(e) |
|
2641 local e=e.conn; |
|
2642 o=s(r,e,o) |
|
2643 a=s(i,e,a) |
|
2644 h[e]=nil |
|
2645 end; |
|
2646 local t=function(t,n,d) |
|
2647 local e=t.conn |
|
2648 h[e]=t |
|
2649 if n~=nil then |
|
2650 if n then |
|
2651 a=l(i,e,a) |
|
2652 else |
|
2653 o=s(r,e,o) |
|
2654 end |
|
2655 end |
|
2656 if d~=nil then |
|
2657 if d then |
|
2658 o=l(r,e,o) |
|
2659 else |
|
2660 a=s(i,e,a) |
|
2661 end |
|
2662 end |
|
2663 end |
|
2664 local a=function(e,a,i) |
|
2665 local o=e |
|
2666 if f(e)=="number"then |
|
2667 o={getfd=function()return e;end} |
|
2668 end |
|
2669 local e={ |
|
2670 conn=o; |
|
2671 readbuffer=a or O; |
|
2672 sendbuffer=i or O; |
|
2673 close=p; |
|
2674 setflags=t; |
|
2675 }; |
|
2676 t(e,a,i) |
|
2677 return e |
|
2678 end |
|
2679 m"setmetatable"(h,{__mode="k"}) |
|
2680 m"setmetatable"(v,{__mode="k"}) |
|
2681 m"setmetatable"(w,{__mode="k"}) |
|
2682 Q=P() |
|
2683 local function t(e) |
|
2684 local t=W; |
|
2685 if e then |
|
2686 W=e; |
|
2687 end |
|
2688 return t; |
|
2689 end |
|
2690 return{ |
|
2691 _addtimer=X, |
|
2692 add_task=u; |
|
2693 addclient=b, |
|
2694 wrapclient=n, |
|
2695 watchfd=a, |
|
2696 loop=Z, |
|
2697 link=z, |
|
2698 step=y, |
|
2699 stats=ie, |
|
2700 closeall=B, |
|
2701 addserver=ne, |
|
2702 getserver=oe, |
|
2703 setlogger=t, |
|
2704 getsettings=ae, |
|
2705 setquitting=c, |
|
2706 removeserver=he, |
|
2707 get_backend=g, |
|
2708 changesettings=re, |
|
2709 } |
|
2710 end) |
|
2711 package.preload['util.xmppstream']=(function(...) |
|
2712 local _ENV=_ENV; |
|
2713 local function o(t,...) |
|
2714 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
2715 package.loaded[t]=e; |
|
2716 for t=1,select("#",...)do |
|
2717 (select(t,...))(e); |
|
2718 end |
|
2719 _ENV=e; |
|
2720 _M=e; |
|
2721 return e; |
|
2722 end |
|
2723 local e=require"lxp"; |
|
2724 local t=require"util.stanza"; |
|
2725 local g=t.stanza_mt; |
|
2726 local c=error; |
|
2727 local t=tostring; |
|
2728 local d=table.insert; |
|
2729 local p=table.concat; |
|
2730 local k=table.remove; |
|
2731 local v=setmetatable; |
|
2732 local q=pcall(e.new,{StartDoctypeDecl=false}); |
|
2733 local x=pcall(e.new,{XmlDecl=false}); |
|
2734 local a=not not e.new({}).getcurrentbytecount; |
|
2735 local j=1024*1024*10; |
|
2736 o"xmppstream" |
|
2737 local b=e.new; |
|
2738 local z={ |
|
2739 ["http://www.w3.org/XML/1998/namespace\1lang"]="xml:lang"; |
|
2740 ["http://www.w3.org/XML/1998/namespace\1space"]="xml:space"; |
|
2741 ["http://www.w3.org/XML/1998/namespace\1base"]="xml:base"; |
|
2742 ["http://www.w3.org/XML/1998/namespace\1id"]="xml:id"; |
|
2743 }; |
|
2744 local o="http://etherx.jabber.org/streams"; |
|
2745 local r="\1"; |
|
2746 local y="^([^"..r.."]*)"..r.."?(.*)$"; |
|
2747 _M.ns_separator=r; |
|
2748 _M.ns_pattern=y; |
|
2749 local function h()end |
|
2750 function new_sax_handlers(n,e,s) |
|
2751 local i={}; |
|
2752 local w=e.streamopened; |
|
2753 local f=e.streamclosed; |
|
2754 local l=e.error or function(o,a,e)c("XML stream error: "..t(a)..(e and": "..t(e)or""),2);end; |
|
2755 local b=e.handlestanza; |
|
2756 s=s or h; |
|
2757 local t=e.stream_ns or o; |
|
2758 local m=e.stream_tag or"stream"; |
|
2759 if t~=""then |
|
2760 m=t..r..m; |
|
2761 end |
|
2762 local j=t..r..(e.error_tag or"error"); |
|
2763 local _=e.default_ns; |
|
2764 local u={}; |
|
2765 local h,e={}; |
|
2766 local t=0; |
|
2767 local r=0; |
|
2768 function i:StartElement(c,o) |
|
2769 if e and#h>0 then |
|
2770 d(e,p(h)); |
|
2771 h={}; |
|
2772 end |
|
2773 local h,i=c:match(y); |
|
2774 if i==""then |
|
2775 h,i="",h; |
|
2776 end |
|
2777 if h~=_ or r>0 then |
|
2778 o.xmlns=h; |
|
2779 r=r+1; |
|
2780 end |
|
2781 for t=1,#o do |
|
2782 local e=o[t]; |
|
2783 o[t]=nil; |
|
2784 local t=z[e]; |
|
2785 if t then |
|
2786 o[t]=o[e]; |
|
2787 o[e]=nil; |
|
2788 end |
|
2789 end |
|
2790 if not e then |
|
2791 if a then |
|
2792 t=self:getcurrentbytecount(); |
|
2793 end |
|
2794 if n.notopen then |
|
2795 if c==m then |
|
2796 r=0; |
|
2797 if w then |
|
2798 if a then |
|
2799 s(t); |
|
2800 t=0; |
|
2801 end |
|
2802 w(n,o); |
|
2803 end |
|
2804 else |
|
2805 l(n,"no-stream",c); |
|
2806 end |
|
2807 return; |
|
2808 end |
|
2809 if h=="jabber:client"and i~="iq"and i~="presence"and i~="message"then |
|
2810 l(n,"invalid-top-level-element"); |
|
2811 end |
|
2812 e=v({name=i,attr=o,tags={}},g); |
|
2813 else |
|
2814 if a then |
|
2815 t=t+self:getcurrentbytecount(); |
|
2816 end |
|
2817 d(u,e); |
|
2818 local t=e; |
|
2819 e=v({name=i,attr=o,tags={}},g); |
|
2820 d(t,e); |
|
2821 d(t.tags,e); |
|
2822 end |
|
2823 end |
|
2824 if x then |
|
2825 function i:XmlDecl(e,e,e) |
|
2826 if a then |
|
2827 s(self:getcurrentbytecount()); |
|
2828 end |
|
2829 end |
|
2830 end |
|
2831 function i:StartCdataSection() |
|
2832 if a then |
|
2833 if e then |
|
2834 t=t+self:getcurrentbytecount(); |
|
2835 else |
|
2836 s(self:getcurrentbytecount()); |
|
2837 end |
|
2838 end |
|
2839 end |
|
2840 function i:EndCdataSection() |
|
2841 if a then |
|
2842 if e then |
|
2843 t=t+self:getcurrentbytecount(); |
|
2844 else |
|
2845 s(self:getcurrentbytecount()); |
|
2846 end |
|
2847 end |
|
2848 end |
|
2849 function i:CharacterData(o) |
|
2850 if e then |
|
2851 if a then |
|
2852 t=t+self:getcurrentbytecount(); |
|
2853 end |
|
2854 d(h,o); |
|
2855 elseif a then |
|
2856 s(self:getcurrentbytecount()); |
|
2857 end |
|
2858 end |
|
2859 function i:EndElement(o) |
|
2860 if a then |
|
2861 t=t+self:getcurrentbytecount() |
|
2862 end |
|
2863 if r>0 then |
|
2864 r=r-1; |
|
2865 end |
|
2866 if e then |
|
2867 if#h>0 then |
|
2868 d(e,p(h)); |
|
2869 h={}; |
|
2870 end |
|
2871 if#u==0 then |
|
2872 if a then |
|
2873 s(t); |
|
2874 end |
|
2875 t=0; |
|
2876 if o~=j then |
|
2877 b(n,e); |
|
2878 else |
|
2879 l(n,"stream-error",e); |
|
2880 end |
|
2881 e=nil; |
|
2882 else |
|
2883 e=k(u); |
|
2884 end |
|
2885 else |
|
2886 if f then |
|
2887 f(n); |
|
2888 end |
|
2889 end |
|
2890 end |
|
2891 local function a(e) |
|
2892 l(n,"parse-error","restricted-xml","Restricted XML, see RFC 6120 section 11.1."); |
|
2893 if not e.stop or not e:stop()then |
|
2894 c("Failed to abort parsing"); |
|
2895 end |
|
2896 end |
|
2897 if q then |
|
2898 i.StartDoctypeDecl=a; |
|
2899 end |
|
2900 i.Comment=a; |
|
2901 i.ProcessingInstruction=a; |
|
2902 local function a() |
|
2903 e,h,t=nil,{},0; |
|
2904 u={}; |
|
2905 end |
|
2906 local function t(t,e) |
|
2907 n=e; |
|
2908 end |
|
2909 return i,{reset=a,set_session=t}; |
|
2910 end |
|
2911 function new(i,n,t) |
|
2912 local e=0; |
|
2913 local o; |
|
2914 if a then |
|
2915 function o(a) |
|
2916 e=e-a; |
|
2917 end |
|
2918 t=t or j; |
|
2919 elseif t then |
|
2920 c("Stanza size limits are not supported on this version of LuaExpat") |
|
2921 end |
|
2922 local i,s=new_sax_handlers(i,n,o); |
|
2923 local o=b(i,r,false); |
|
2924 local n=o.parse; |
|
2925 return{ |
|
2926 reset=function() |
|
2927 o=b(i,r,false); |
|
2928 n=o.parse; |
|
2929 e=0; |
|
2930 s.reset(); |
|
2931 end, |
|
2932 feed=function(s,i) |
|
2933 if a then |
|
2934 e=e+#i; |
|
2935 end |
|
2936 local o,i=n(o,i); |
|
2937 if a and e>t then |
|
2938 return nil,"stanza-too-large"; |
|
2939 end |
|
2940 return o,i; |
|
2941 end, |
|
2942 set_session=s.set_session; |
|
2943 }; |
|
2944 end |
|
2945 return _M; |
|
2946 end) |
|
2947 package.preload['util.jid']=(function(...) |
|
2948 local _ENV=_ENV; |
|
2949 local function a(t,...) |
|
2950 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
2951 package.loaded[t]=e; |
|
2952 for t=1,select("#",...)do |
|
2953 (select(t,...))(e); |
|
2954 end |
|
2955 _ENV=e; |
|
2956 _M=e; |
|
2957 return e; |
|
2958 end |
|
2959 local t,h=string.match,string.sub; |
|
2960 local r=require"util.encodings".stringprep.nodeprep; |
|
2961 local d=require"util.encodings".stringprep.nameprep; |
|
2962 local l=require"util.encodings".stringprep.resourceprep; |
|
2963 local n={ |
|
2964 [" "]="\\20";['"']="\\22"; |
|
2965 ["&"]="\\26";["'"]="\\27"; |
|
2966 ["/"]="\\2f";[":"]="\\3a"; |
|
2967 ["<"]="\\3c";[">"]="\\3e"; |
|
2968 ["@"]="\\40";["\\"]="\\5c"; |
|
2969 }; |
|
2970 local s={}; |
|
2971 for t,e in pairs(n)do s[e]=t;end |
|
2972 a"jid" |
|
2973 local function a(e) |
|
2974 if not e then return;end |
|
2975 local i,a=t(e,"^([^@/]+)@()"); |
|
2976 local a,o=t(e,"^([^@/]+)()",a) |
|
2977 if i and not a then return nil,nil,nil;end |
|
2978 local t=t(e,"^/(.+)$",o); |
|
2979 if(not a)or((not t)and#e>=o)then return nil,nil,nil;end |
|
2980 return i,a,t; |
|
2981 end |
|
2982 split=a; |
|
2983 function bare(e) |
|
2984 local t,e=a(e); |
|
2985 if t and e then |
|
2986 return t.."@"..e; |
|
2987 end |
|
2988 return e; |
|
2989 end |
|
2990 local function o(e) |
|
2991 local t,e,a=a(e); |
|
2992 if e then |
|
2993 if h(e,-1,-1)=="."then |
|
2994 e=h(e,1,-2); |
|
2995 end |
|
2996 e=d(e); |
|
2997 if not e then return;end |
|
2998 if t then |
|
2999 t=r(t); |
|
3000 if not t then return;end |
|
3001 end |
|
3002 if a then |
|
3003 a=l(a); |
|
3004 if not a then return;end |
|
3005 end |
|
3006 return t,e,a; |
|
3007 end |
|
3008 end |
|
3009 prepped_split=o; |
|
3010 function prep(e) |
|
3011 local t,e,a=o(e); |
|
3012 if e then |
|
3013 if t then |
|
3014 e=t.."@"..e; |
|
3015 end |
|
3016 if a then |
|
3017 e=e.."/"..a; |
|
3018 end |
|
3019 end |
|
3020 return e; |
|
3021 end |
|
3022 function join(t,e,a) |
|
3023 if t and e and a then |
|
3024 return t.."@"..e.."/"..a; |
|
3025 elseif t and e then |
|
3026 return t.."@"..e; |
|
3027 elseif e and a then |
|
3028 return e.."/"..a; |
|
3029 elseif e then |
|
3030 return e; |
|
3031 end |
|
3032 return nil; |
|
3033 end |
|
3034 function compare(t,e) |
|
3035 local n,o,i=a(t); |
|
3036 local a,t,e=a(e); |
|
3037 if((a~=nil and a==n)or a==nil)and |
|
3038 ((t~=nil and t==o)or t==nil)and |
|
3039 ((e~=nil and e==i)or e==nil)then |
|
3040 return true |
|
3041 end |
|
3042 return false |
|
3043 end |
|
3044 function escape(e)return e and(e:gsub(".",n));end |
|
3045 function unescape(e)return e and(e:gsub("\\%x%x",s));end |
|
3046 return _M; |
|
3047 end) |
|
3048 package.preload['util.events']=(function(...) |
|
3049 local _ENV=_ENV; |
|
3050 local function a(t,...) |
|
3051 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
3052 package.loaded[t]=e; |
|
3053 for t=1,select("#",...)do |
|
3054 (select(t,...))(e); |
|
3055 end |
|
3056 _ENV=e; |
|
3057 _M=e; |
|
3058 return e; |
|
3059 end |
|
3060 local i=pairs; |
|
3061 local o=table.insert; |
|
3062 local n=table.sort; |
|
3063 local s=setmetatable; |
|
3064 local h=next; |
|
3065 a"events" |
|
3066 function new() |
|
3067 local t={}; |
|
3068 local e={}; |
|
3069 local function r(s,a) |
|
3070 local e=e[a]; |
|
3071 if not e or h(e)==nil then return;end |
|
3072 local t={}; |
|
3073 for e in i(e)do |
|
3074 o(t,e); |
|
3075 end |
|
3076 n(t,function(a,t)return e[a]>e[t];end); |
|
3077 s[a]=t; |
|
3078 return t; |
|
3079 end; |
|
3080 s(t,{__index=r}); |
|
3081 local function s(o,n,i) |
|
3082 local a=e[o]; |
|
3083 if a then |
|
3084 a[n]=i or 0; |
|
3085 else |
|
3086 a={[n]=i or 0}; |
|
3087 e[o]=a; |
|
3088 end |
|
3089 t[o]=nil; |
|
3090 end; |
|
3091 local function n(o,i) |
|
3092 local a=e[o]; |
|
3093 if a then |
|
3094 a[i]=nil; |
|
3095 t[o]=nil; |
|
3096 if h(a)==nil then |
|
3097 e[o]=nil; |
|
3098 end |
|
3099 end |
|
3100 end; |
|
3101 local function h(e) |
|
3102 for t,e in i(e)do |
|
3103 s(t,e); |
|
3104 end |
|
3105 end; |
|
3106 local function o(e) |
|
3107 for e,t in i(e)do |
|
3108 n(e,t); |
|
3109 end |
|
3110 end; |
|
3111 local function a(e,...) |
|
3112 local e=t[e]; |
|
3113 if e then |
|
3114 for t=1,#e do |
|
3115 local e=e[t](...); |
|
3116 if e~=nil then return e;end |
|
3117 end |
|
3118 end |
|
3119 end; |
|
3120 return{ |
|
3121 add_handler=s; |
|
3122 remove_handler=n; |
|
3123 add_handlers=h; |
|
3124 remove_handlers=o; |
|
3125 fire_event=a; |
|
3126 _handlers=t; |
|
3127 _event_map=e; |
|
3128 }; |
|
3129 end |
|
3130 return _M; |
|
3131 end) |
|
3132 package.preload['util.dataforms']=(function(...) |
|
3133 local _ENV=_ENV; |
|
3134 local function o(t,...) |
|
3135 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
3136 package.loaded[t]=e; |
|
3137 for t=1,select("#",...)do |
|
3138 (select(t,...))(e); |
|
3139 end |
|
3140 _ENV=e; |
|
3141 _M=e; |
|
3142 return e; |
|
3143 end |
|
3144 local a=setmetatable; |
|
3145 local e,i=pairs,ipairs; |
|
3146 local n,s,c=tostring,type,next; |
|
3147 local r=table.concat; |
|
3148 local u=require"util.stanza"; |
|
3149 local d=require"util.jid".prep; |
|
3150 o"dataforms" |
|
3151 local l='jabber:x:data'; |
|
3152 local h={}; |
|
3153 local t={__index=h}; |
|
3154 function new(e) |
|
3155 return a(e,t); |
|
3156 end |
|
3157 function from_stanza(e) |
|
3158 local o={ |
|
3159 title=e:get_child_text("title"); |
|
3160 instructions=e:get_child_text("instructions"); |
|
3161 }; |
|
3162 for e in e:childtags("field")do |
|
3163 local a={ |
|
3164 name=e.attr.var; |
|
3165 label=e.attr.label; |
|
3166 type=e.attr.type; |
|
3167 required=e:get_child("required")and true or nil; |
|
3168 value=e:get_child_text("value"); |
|
3169 }; |
|
3170 o[#o+1]=a; |
|
3171 if a.type then |
|
3172 local t={}; |
|
3173 if a.type:match"list%-"then |
|
3174 for e in e:childtags("option")do |
|
3175 t[#t+1]={label=e.attr.label,value=e:get_child_text("value")}; |
|
3176 end |
|
3177 for e in e:childtags("value")do |
|
3178 t[#t+1]={label=e.attr.label,value=e:get_text(),default=true}; |
|
3179 end |
|
3180 elseif a.type:match"%-multi"then |
|
3181 for e in e:childtags("value")do |
|
3182 t[#t+1]=e.attr.label and{label=e.attr.label,value=e:get_text()}or e:get_text(); |
|
3183 end |
|
3184 if a.type=="text-multi"then |
|
3185 a.value=r(t,"\n"); |
|
3186 else |
|
3187 a.value=t; |
|
3188 end |
|
3189 end |
|
3190 end |
|
3191 end |
|
3192 return new(o); |
|
3193 end |
|
3194 function h.form(t,h,e) |
|
3195 local e=u.stanza("x",{xmlns=l,type=e or"form"}); |
|
3196 if t.title then |
|
3197 e:tag("title"):text(t.title):up(); |
|
3198 end |
|
3199 if t.instructions then |
|
3200 e:tag("instructions"):text(t.instructions):up(); |
|
3201 end |
|
3202 for t,o in i(t)do |
|
3203 local a=o.type or"text-single"; |
|
3204 e:tag("field",{type=a,var=o.name,label=o.label}); |
|
3205 local t=(h and h[o.name])or o.value; |
|
3206 if t then |
|
3207 if a=="hidden"then |
|
3208 if s(t)=="table"then |
|
3209 e:tag("value") |
|
3210 :add_child(t) |
|
3211 :up(); |
|
3212 else |
|
3213 e:tag("value"):text(n(t)):up(); |
|
3214 end |
|
3215 elseif a=="boolean"then |
|
3216 e:tag("value"):text((t and"1")or"0"):up(); |
|
3217 elseif a=="fixed"then |
|
3218 elseif a=="jid-multi"then |
|
3219 for a,t in i(t)do |
|
3220 e:tag("value"):text(t):up(); |
|
3221 end |
|
3222 elseif a=="jid-single"then |
|
3223 e:tag("value"):text(t):up(); |
|
3224 elseif a=="text-single"or a=="text-private"then |
|
3225 e:tag("value"):text(t):up(); |
|
3226 elseif a=="text-multi"then |
|
3227 for t in t:gmatch("([^\r\n]+)\r?\n*")do |
|
3228 e:tag("value"):text(t):up(); |
|
3229 end |
|
3230 elseif a=="list-single"then |
|
3231 local a=false; |
|
3232 for o,t in i(t)do |
|
3233 if s(t)=="table"then |
|
3234 e:tag("option",{label=t.label}):tag("value"):text(t.value):up():up(); |
|
3235 if t.default and(not a)then |
|
3236 e:tag("value"):text(t.value):up(); |
|
3237 a=true; |
|
3238 end |
|
3239 else |
|
3240 e:tag("option",{label=t}):tag("value"):text(n(t)):up():up(); |
|
3241 end |
|
3242 end |
|
3243 elseif a=="list-multi"then |
|
3244 for a,t in i(t)do |
|
3245 if s(t)=="table"then |
|
3246 e:tag("option",{label=t.label}):tag("value"):text(t.value):up():up(); |
|
3247 if t.default then |
|
3248 e:tag("value"):text(t.value):up(); |
|
3249 end |
|
3250 else |
|
3251 e:tag("option",{label=t}):tag("value"):text(n(t)):up():up(); |
|
3252 end |
|
3253 end |
|
3254 end |
|
3255 end |
|
3256 if o.required then |
|
3257 e:tag("required"):up(); |
|
3258 end |
|
3259 e:up(); |
|
3260 end |
|
3261 return e; |
|
3262 end |
|
3263 local e={}; |
|
3264 function h.data(t,n) |
|
3265 local o={}; |
|
3266 local a={}; |
|
3267 for i,t in i(t)do |
|
3268 local i; |
|
3269 for e in n:childtags()do |
|
3270 if t.name==e.attr.var then |
|
3271 i=e; |
|
3272 break; |
|
3273 end |
|
3274 end |
|
3275 if not i then |
|
3276 if t.required then |
|
3277 a[t.name]="Required value missing"; |
|
3278 end |
|
3279 else |
|
3280 local e=e[t.type]; |
|
3281 if e then |
|
3282 o[t.name],a[t.name]=e(i,t.required); |
|
3283 end |
|
3284 end |
|
3285 end |
|
3286 if c(a)then |
|
3287 return o,a; |
|
3288 end |
|
3289 return o; |
|
3290 end |
|
3291 e["text-single"]= |
|
3292 function(t,a) |
|
3293 local t=t:get_child_text("value"); |
|
3294 if t and#t>0 then |
|
3295 return t |
|
3296 elseif a then |
|
3297 return nil,"Required value missing"; |
|
3298 end |
|
3299 end |
|
3300 e["text-private"]= |
|
3301 e["text-single"]; |
|
3302 e["jid-single"]= |
|
3303 function(t,o) |
|
3304 local a=t:get_child_text("value") |
|
3305 local t=d(a); |
|
3306 if t and#t>0 then |
|
3307 return t |
|
3308 elseif a then |
|
3309 return nil,"Invalid JID: "..a; |
|
3310 elseif o then |
|
3311 return nil,"Required value missing"; |
|
3312 end |
|
3313 end |
|
3314 e["jid-multi"]= |
|
3315 function(o,i) |
|
3316 local a={}; |
|
3317 local t={}; |
|
3318 for e in o:childtags("value")do |
|
3319 local e=e:get_text(); |
|
3320 local o=d(e); |
|
3321 a[#a+1]=o; |
|
3322 if e and not o then |
|
3323 t[#t+1]=("Invalid JID: "..e); |
|
3324 end |
|
3325 end |
|
3326 if#a>0 then |
|
3327 return a,(#t>0 and r(t,"\n")or nil); |
|
3328 elseif i then |
|
3329 return nil,"Required value missing"; |
|
3330 end |
|
3331 end |
|
3332 e["list-multi"]= |
|
3333 function(a,o) |
|
3334 local t={}; |
|
3335 for e in a:childtags("value")do |
|
3336 t[#t+1]=e:get_text(); |
|
3337 end |
|
3338 return t,(o and#t==0 and"Required value missing"or nil); |
|
3339 end |
|
3340 e["text-multi"]= |
|
3341 function(t,a) |
|
3342 local t,a=e["list-multi"](t,a); |
|
3343 if t then |
|
3344 t=r(t,"\n"); |
|
3345 end |
|
3346 return t,a; |
|
3347 end |
|
3348 e["list-single"]= |
|
3349 e["text-single"]; |
|
3350 local a={ |
|
3351 ["1"]=true,["true"]=true, |
|
3352 ["0"]=false,["false"]=false, |
|
3353 }; |
|
3354 e["boolean"]= |
|
3355 function(t,o) |
|
3356 local t=t:get_child_text("value"); |
|
3357 local a=a[t~=nil and t]; |
|
3358 if a~=nil then |
|
3359 return a; |
|
3360 elseif t then |
|
3361 return nil,"Invalid boolean representation"; |
|
3362 elseif o then |
|
3363 return nil,"Required value missing"; |
|
3364 end |
|
3365 end |
|
3366 e["hidden"]= |
|
3367 function(e) |
|
3368 return e:get_child_text("value"); |
|
3369 end |
|
3370 return _M; |
|
3371 end) |
|
3372 package.preload['util.caps']=(function(...) |
|
3373 local _ENV=_ENV; |
|
3374 local function a(t,...) |
|
3375 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
3376 package.loaded[t]=e; |
|
3377 for t=1,select("#",...)do |
|
3378 (select(t,...))(e); |
|
3379 end |
|
3380 _ENV=e; |
|
3381 _M=e; |
|
3382 return e; |
|
3383 end |
|
3384 local d=require"util.encodings".base64.encode; |
|
3385 local l=require"util.hashes".sha1; |
|
3386 local n,s,h=table.insert,table.sort,table.concat; |
|
3387 local r=ipairs; |
|
3388 a"caps" |
|
3389 function calculate_hash(e) |
|
3390 local i,o,a={},{},{}; |
|
3391 for t,e in r(e)do |
|
3392 if e.name=="identity"then |
|
3393 n(i,(e.attr.category or"").."\0"..(e.attr.type or"").."\0"..(e.attr["xml:lang"]or"").."\0"..(e.attr.name or"")); |
|
3394 elseif e.name=="feature"then |
|
3395 n(o,e.attr.var or""); |
|
3396 elseif e.name=="x"and e.attr.xmlns=="jabber:x:data"then |
|
3397 local t={}; |
|
3398 local o; |
|
3399 for a,e in r(e.tags)do |
|
3400 if e.name=="field"and e.attr.var then |
|
3401 local a={}; |
|
3402 for t,e in r(e.tags)do |
|
3403 e=#e.tags==0 and e:get_text(); |
|
3404 if e then n(a,e);end |
|
3405 end |
|
3406 s(a); |
|
3407 if e.attr.var=="FORM_TYPE"then |
|
3408 o=a[1]; |
|
3409 elseif#a>0 then |
|
3410 n(t,e.attr.var.."\0"..h(a,"<")); |
|
3411 else |
|
3412 n(t,e.attr.var); |
|
3413 end |
|
3414 end |
|
3415 end |
|
3416 s(t); |
|
3417 t=h(t,"<"); |
|
3418 if o then t=o.."\0"..t;end |
|
3419 n(a,t); |
|
3420 end |
|
3421 end |
|
3422 s(i); |
|
3423 s(o); |
|
3424 s(a); |
|
3425 if#i>0 then i=h(i,"<"):gsub("%z","/").."<";else i="";end |
|
3426 if#o>0 then o=h(o,"<").."<";else o="";end |
|
3427 if#a>0 then a=h(a,"<"):gsub("%z","<").."<";else a="";end |
|
3428 local e=i..o..a; |
|
3429 local t=d(l(e)); |
|
3430 return t,e; |
|
3431 end |
|
3432 return _M; |
|
3433 end) |
|
3434 package.preload['util.vcard']=(function(...) |
|
3435 local _ENV=_ENV; |
|
3436 local function e(t,...) |
|
3437 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
3438 package.loaded[t]=e; |
|
3439 for t=1,select("#",...)do |
|
3440 (select(t,...))(e); |
|
3441 end |
|
3442 _ENV=e; |
|
3443 _M=e; |
|
3444 return e; |
|
3445 end |
|
3446 local n=require"util.stanza"; |
|
3447 local a,c=table.insert,table.concat; |
|
3448 local h=type; |
|
3449 local e,r,f=next,pairs,ipairs; |
|
3450 local d,l,u,m; |
|
3451 local w="\n"; |
|
3452 local i; |
|
3453 local function e() |
|
3454 error"Not implemented" |
|
3455 end |
|
3456 local function e() |
|
3457 error"Not implemented" |
|
3458 end |
|
3459 local function y(e) |
|
3460 return e:gsub("[,:;\\]","\\%1"):gsub("\n","\\n"); |
|
3461 end |
|
3462 local function s(e) |
|
3463 return e:gsub("\\?[\\nt:;,]",{ |
|
3464 ["\\\\"]="\\", |
|
3465 ["\\n"]="\n", |
|
3466 ["\\r"]="\r", |
|
3467 ["\\t"]="\t", |
|
3468 ["\\:"]=":", |
|
3469 ["\\;"]=";", |
|
3470 ["\\,"]=",", |
|
3471 [":"]="\29", |
|
3472 [";"]="\30", |
|
3473 [","]="\31", |
|
3474 }); |
|
3475 end |
|
3476 local function p(e) |
|
3477 local a=n.stanza(e.name,{xmlns="vcard-temp"}); |
|
3478 local t=i[e.name]; |
|
3479 if t=="text"then |
|
3480 a:text(e[1]); |
|
3481 elseif h(t)=="table"then |
|
3482 if t.types and e.TYPE then |
|
3483 if h(e.TYPE)=="table"then |
|
3484 for o,t in r(t.types)do |
|
3485 for o,e in r(e.TYPE)do |
|
3486 if e:upper()==t then |
|
3487 a:tag(t):up(); |
|
3488 break; |
|
3489 end |
|
3490 end |
|
3491 end |
|
3492 else |
|
3493 a:tag(e.TYPE:upper()):up(); |
|
3494 end |
|
3495 end |
|
3496 if t.props then |
|
3497 for o,t in r(t.props)do |
|
3498 if e[t]then |
|
3499 a:tag(t):up(); |
|
3500 end |
|
3501 end |
|
3502 end |
|
3503 if t.value then |
|
3504 a:tag(t.value):text(e[1]):up(); |
|
3505 elseif t.values then |
|
3506 local o=t.values; |
|
3507 local i=o.behaviour=="repeat-last"and o[#o]; |
|
3508 for o=1,#e do |
|
3509 a:tag(t.values[o]or i):text(e[o]):up(); |
|
3510 end |
|
3511 end |
|
3512 end |
|
3513 return a; |
|
3514 end |
|
3515 local function o(t) |
|
3516 local e=n.stanza("vCard",{xmlns="vcard-temp"}); |
|
3517 for a=1,#t do |
|
3518 e:add_child(p(t[a])); |
|
3519 end |
|
3520 return e; |
|
3521 end |
|
3522 function m(e) |
|
3523 if not e[1]or e[1].name then |
|
3524 return o(e) |
|
3525 else |
|
3526 local t=n.stanza("xCard",{xmlns="vcard-temp"}); |
|
3527 for a=1,#e do |
|
3528 t:add_child(o(e[a])); |
|
3529 end |
|
3530 return t; |
|
3531 end |
|
3532 end |
|
3533 function d(t) |
|
3534 t=t |
|
3535 :gsub("\r\n","\n") |
|
3536 :gsub("\n ","") |
|
3537 :gsub("\n\n+","\n"); |
|
3538 local h={}; |
|
3539 local e; |
|
3540 for t in t:gmatch("[^\n]+")do |
|
3541 local t=s(t); |
|
3542 local s,t,n=t:match("^([-%a]+)(\30?[^\29]*)\29(.*)$"); |
|
3543 n=n:gsub("\29",":"); |
|
3544 if#t>0 then |
|
3545 local a={}; |
|
3546 for e,o,i in t:gmatch("\30([^=]+)(=?)([^\30]*)")do |
|
3547 e=e:upper(); |
|
3548 local t={}; |
|
3549 for e in i:gmatch("[^\31]+")do |
|
3550 t[#t+1]=e |
|
3551 t[e]=true; |
|
3552 end |
|
3553 if o=="="then |
|
3554 a[e]=t; |
|
3555 else |
|
3556 a[e]=true; |
|
3557 end |
|
3558 end |
|
3559 t=a; |
|
3560 end |
|
3561 if s=="BEGIN"and n=="VCARD"then |
|
3562 e={}; |
|
3563 h[#h+1]=e; |
|
3564 elseif s=="END"and n=="VCARD"then |
|
3565 e=nil; |
|
3566 elseif e and i[s]then |
|
3567 local o=i[s]; |
|
3568 local i={name=s}; |
|
3569 e[#e+1]=i; |
|
3570 local s=e; |
|
3571 e=i; |
|
3572 if o.types then |
|
3573 for o,a in f(o.types)do |
|
3574 local a=a:lower(); |
|
3575 if(t.TYPE and t.TYPE[a]==true) |
|
3576 or t[a]==true then |
|
3577 e.TYPE=a; |
|
3578 end |
|
3579 end |
|
3580 end |
|
3581 if o.props then |
|
3582 for o,a in f(o.props)do |
|
3583 if t[a]then |
|
3584 if t[a]==true then |
|
3585 e[a]=true; |
|
3586 else |
|
3587 for o,t in f(t[a])do |
|
3588 e[a]=t; |
|
3589 end |
|
3590 end |
|
3591 end |
|
3592 end |
|
3593 end |
|
3594 if o=="text"or o.value then |
|
3595 a(e,n); |
|
3596 elseif o.values then |
|
3597 local t="\30"..n; |
|
3598 for t in t:gmatch("\30([^\30]*)")do |
|
3599 a(e,t); |
|
3600 end |
|
3601 end |
|
3602 e=s; |
|
3603 end |
|
3604 end |
|
3605 return h; |
|
3606 end |
|
3607 local function n(t) |
|
3608 local e={}; |
|
3609 for a=1,#t do |
|
3610 e[a]=y(t[a]); |
|
3611 end |
|
3612 e=c(e,";"); |
|
3613 local a=""; |
|
3614 for t,e in r(t)do |
|
3615 if h(t)=="string"and t~="name"then |
|
3616 a=a..(";%s=%s"):format(t,h(e)=="table"and c(e,",")or e); |
|
3617 end |
|
3618 end |
|
3619 return("%s%s:%s"):format(t.name,a,e) |
|
3620 end |
|
3621 local function o(t) |
|
3622 local e={}; |
|
3623 a(e,"BEGIN:VCARD") |
|
3624 for o=1,#t do |
|
3625 a(e,n(t[o])); |
|
3626 end |
|
3627 a(e,"END:VCARD") |
|
3628 return c(e,w); |
|
3629 end |
|
3630 function l(e) |
|
3631 if e[1]and e[1].name then |
|
3632 return o(e) |
|
3633 else |
|
3634 local a={}; |
|
3635 for t=1,#e do |
|
3636 a[t]=o(e[t]); |
|
3637 end |
|
3638 return c(a,w); |
|
3639 end |
|
3640 end |
|
3641 local function n(o) |
|
3642 local t=o.name; |
|
3643 local e=i[t]; |
|
3644 local t={name=t}; |
|
3645 if e=="text"then |
|
3646 t[1]=o:get_text(); |
|
3647 elseif h(e)=="table"then |
|
3648 if e.value then |
|
3649 t[1]=o:get_child_text(e.value)or""; |
|
3650 elseif e.values then |
|
3651 local e=e.values; |
|
3652 if e.behaviour=="repeat-last"then |
|
3653 for e=1,#o.tags do |
|
3654 a(t,o.tags[e]:get_text()or""); |
|
3655 end |
|
3656 else |
|
3657 for i=1,#e do |
|
3658 a(t,o:get_child_text(e[i])or""); |
|
3659 end |
|
3660 end |
|
3661 elseif e.names then |
|
3662 local e=e.names; |
|
3663 for a=1,#e do |
|
3664 if o:get_child(e[a])then |
|
3665 t[1]=e[a]; |
|
3666 break; |
|
3667 end |
|
3668 end |
|
3669 end |
|
3670 if e.props_verbatim then |
|
3671 for a,e in r(e.props_verbatim)do |
|
3672 t[a]=e; |
|
3673 end |
|
3674 end |
|
3675 if e.types then |
|
3676 local e=e.types; |
|
3677 t.TYPE={}; |
|
3678 for i=1,#e do |
|
3679 if o:get_child(e[i])then |
|
3680 a(t.TYPE,e[i]:lower()); |
|
3681 end |
|
3682 end |
|
3683 if#t.TYPE==0 then |
|
3684 t.TYPE=nil; |
|
3685 end |
|
3686 end |
|
3687 if e.props then |
|
3688 local e=e.props; |
|
3689 for i=1,#e do |
|
3690 local e=e[i] |
|
3691 local o=o:get_child_text(e); |
|
3692 if o then |
|
3693 t[e]=t[e]or{}; |
|
3694 a(t[e],o); |
|
3695 end |
|
3696 end |
|
3697 end |
|
3698 else |
|
3699 return nil |
|
3700 end |
|
3701 return t; |
|
3702 end |
|
3703 local function o(e) |
|
3704 local t=e.tags; |
|
3705 local e={}; |
|
3706 for o=1,#t do |
|
3707 a(e,n(t[o])); |
|
3708 end |
|
3709 return e |
|
3710 end |
|
3711 function u(e) |
|
3712 if e.attr.xmlns~="vcard-temp"then |
|
3713 return nil,"wrong-xmlns"; |
|
3714 end |
|
3715 if e.name=="xCard"then |
|
3716 local t={}; |
|
3717 local e=e.tags; |
|
3718 for a=1,#e do |
|
3719 t[a]=o(e[a]); |
|
3720 end |
|
3721 return t |
|
3722 elseif e.name=="vCard"then |
|
3723 return o(e) |
|
3724 end |
|
3725 end |
|
3726 i={ |
|
3727 VERSION="text", |
|
3728 FN="text", |
|
3729 N={ |
|
3730 values={ |
|
3731 "FAMILY", |
|
3732 "GIVEN", |
|
3733 "MIDDLE", |
|
3734 "PREFIX", |
|
3735 "SUFFIX", |
|
3736 }, |
|
3737 }, |
|
3738 NICKNAME="text", |
|
3739 PHOTO={ |
|
3740 props_verbatim={ENCODING={"b"}}, |
|
3741 props={"TYPE"}, |
|
3742 value="BINVAL", |
|
3743 }, |
|
3744 BDAY="text", |
|
3745 ADR={ |
|
3746 types={ |
|
3747 "HOME", |
|
3748 "WORK", |
|
3749 "POSTAL", |
|
3750 "PARCEL", |
|
3751 "DOM", |
|
3752 "INTL", |
|
3753 "PREF", |
|
3754 }, |
|
3755 values={ |
|
3756 "POBOX", |
|
3757 "EXTADD", |
|
3758 "STREET", |
|
3759 "LOCALITY", |
|
3760 "REGION", |
|
3761 "PCODE", |
|
3762 "CTRY", |
|
3763 } |
|
3764 }, |
|
3765 LABEL={ |
|
3766 types={ |
|
3767 "HOME", |
|
3768 "WORK", |
|
3769 "POSTAL", |
|
3770 "PARCEL", |
|
3771 "DOM", |
|
3772 "INTL", |
|
3773 "PREF", |
|
3774 }, |
|
3775 value="LINE", |
|
3776 }, |
|
3777 TEL={ |
|
3778 types={ |
|
3779 "HOME", |
|
3780 "WORK", |
|
3781 "VOICE", |
|
3782 "FAX", |
|
3783 "PAGER", |
|
3784 "MSG", |
|
3785 "CELL", |
|
3786 "VIDEO", |
|
3787 "BBS", |
|
3788 "MODEM", |
|
3789 "ISDN", |
|
3790 "PCS", |
|
3791 "PREF", |
|
3792 }, |
|
3793 value="NUMBER", |
|
3794 }, |
|
3795 EMAIL={ |
|
3796 types={ |
|
3797 "HOME", |
|
3798 "WORK", |
|
3799 "INTERNET", |
|
3800 "PREF", |
|
3801 "X400", |
|
3802 }, |
|
3803 value="USERID", |
|
3804 }, |
|
3805 JABBERID="text", |
|
3806 MAILER="text", |
|
3807 TZ="text", |
|
3808 GEO={ |
|
3809 values={ |
|
3810 "LAT", |
|
3811 "LON", |
|
3812 }, |
|
3813 }, |
|
3814 TITLE="text", |
|
3815 ROLE="text", |
|
3816 LOGO="copy of PHOTO", |
|
3817 AGENT="text", |
|
3818 ORG={ |
|
3819 values={ |
|
3820 behaviour="repeat-last", |
|
3821 "ORGNAME", |
|
3822 "ORGUNIT", |
|
3823 } |
|
3824 }, |
|
3825 CATEGORIES={ |
|
3826 values="KEYWORD", |
|
3827 }, |
|
3828 NOTE="text", |
|
3829 PRODID="text", |
|
3830 REV="text", |
|
3831 SORTSTRING="text", |
|
3832 SOUND="copy of PHOTO", |
|
3833 UID="text", |
|
3834 URL="text", |
|
3835 CLASS={ |
|
3836 names={ |
|
3837 "PUBLIC", |
|
3838 "PRIVATE", |
|
3839 "CONFIDENTIAL", |
|
3840 }, |
|
3841 }, |
|
3842 KEY={ |
|
3843 props={"TYPE"}, |
|
3844 value="CRED", |
|
3845 }, |
|
3846 DESC="text", |
|
3847 }; |
|
3848 i.LOGO=i.PHOTO; |
|
3849 i.SOUND=i.PHOTO; |
|
3850 return{ |
|
3851 from_text=d; |
|
3852 to_text=l; |
|
3853 from_xep54=u; |
|
3854 to_xep54=m; |
|
3855 lua_to_text=l; |
|
3856 lua_to_xep54=m; |
|
3857 text_to_lua=d; |
|
3858 text_to_xep54=function(...)return m(d(...));end; |
|
3859 xep54_to_lua=u; |
|
3860 xep54_to_text=function(...)return l(u(...))end; |
|
3861 }; |
|
3862 end) |
|
3863 package.preload['util.logger']=(function(...) |
|
3864 local _ENV=_ENV; |
|
3865 local function e(t,...) |
|
3866 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
3867 package.loaded[t]=e; |
|
3868 for t=1,select("#",...)do |
|
3869 (select(t,...))(e); |
|
3870 end |
|
3871 _ENV=e; |
|
3872 _M=e; |
|
3873 return e; |
|
3874 end |
|
3875 local e=pcall; |
|
3876 local e=string.find; |
|
3877 local e,i,e=ipairs,pairs,setmetatable; |
|
3878 local a={}; |
|
3879 local e={}; |
|
3880 local t; |
|
3881 function a.init(e) |
|
3882 local o=t(e,"debug"); |
|
3883 local a=t(e,"info"); |
|
3884 local i=t(e,"warn"); |
|
3885 local n=t(e,"error"); |
|
3886 return function(e,t,...) |
|
3887 if e=="debug"then |
|
3888 return o(t,...); |
|
3889 elseif e=="info"then |
|
3890 return a(t,...); |
|
3891 elseif e=="warn"then |
|
3892 return i(t,...); |
|
3893 elseif e=="error"then |
|
3894 return n(t,...); |
|
3895 end |
|
3896 end |
|
3897 end |
|
3898 function t(i,a) |
|
3899 local t=e[a]; |
|
3900 if not t then |
|
3901 t={}; |
|
3902 e[a]=t; |
|
3903 end |
|
3904 local e=function(o,...) |
|
3905 for e=1,#t do |
|
3906 t[e](i,a,o,...); |
|
3907 end |
|
3908 end |
|
3909 return e; |
|
3910 end |
|
3911 function a.reset() |
|
3912 for t,e in i(e)do |
|
3913 for t=1,#e do |
|
3914 e[t]=nil; |
|
3915 end |
|
3916 end |
|
3917 end |
|
3918 function a.add_level_sink(t,o) |
|
3919 if not e[t]then |
|
3920 e[t]={o}; |
|
3921 else |
|
3922 e[t][#e[t]+1]=o; |
|
3923 end |
|
3924 end |
|
3925 a.new=t; |
|
3926 return a; |
|
3927 end) |
|
3928 package.preload['util.datetime']=(function(...) |
|
3929 local _ENV=_ENV; |
|
3930 local function a(t,...) |
|
3931 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
3932 package.loaded[t]=e; |
|
3933 for t=1,select("#",...)do |
|
3934 (select(t,...))(e); |
|
3935 end |
|
3936 _ENV=e; |
|
3937 _M=e; |
|
3938 return e; |
|
3939 end |
|
3940 local e=os.date; |
|
3941 local i=os.time; |
|
3942 local u=os.difftime; |
|
3943 local t=error; |
|
3944 local r=tonumber; |
|
3945 a"datetime" |
|
3946 function date(t) |
|
3947 return e("!%Y-%m-%d",t); |
|
3948 end |
|
3949 function datetime(t) |
|
3950 return e("!%Y-%m-%dT%H:%M:%SZ",t); |
|
3951 end |
|
3952 function time(t) |
|
3953 return e("!%H:%M:%S",t); |
|
3954 end |
|
3955 function legacy(t) |
|
3956 return e("!%Y%m%dT%H:%M:%S",t); |
|
3957 end |
|
3958 function parse(t) |
|
3959 if t then |
|
3960 local n,d,l,s,h,a,o; |
|
3961 n,d,l,s,h,a,o=t:match("^(%d%d%d%d)%-?(%d%d)%-?(%d%d)T(%d%d):(%d%d):(%d%d)%.?%d*([Z+%-]?.*)$"); |
|
3962 if n then |
|
3963 local u=u(i(e("*t")),i(e("!*t"))); |
|
3964 local t=0; |
|
3965 if o~=""and o~="Z"then |
|
3966 local o,a,e=o:match("([+%-])(%d%d):?(%d*)"); |
|
3967 if not o then return;end |
|
3968 if#e~=2 then e="0";end |
|
3969 a,e=r(a),r(e); |
|
3970 t=a*60*60+e*60; |
|
3971 if o=="-"then t=-t;end |
|
3972 end |
|
3973 a=(a+u)-t; |
|
3974 return i({year=n,month=d,day=l,hour=s,min=h,sec=a,isdst=false}); |
|
3975 end |
|
3976 end |
|
3977 end |
|
3978 return _M; |
|
3979 end) |
|
3980 package.preload['util.json']=(function(...) |
|
3981 local _ENV=_ENV; |
|
3982 local function e(t,...) |
|
3983 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
3984 package.loaded[t]=e; |
|
3985 for t=1,select("#",...)do |
|
3986 (select(t,...))(e); |
|
3987 end |
|
3988 _ENV=e; |
|
3989 _M=e; |
|
3990 return e; |
|
3991 end |
|
3992 local y=type; |
|
3993 local t,p,v,j=table.insert,table.concat,table.remove,table.sort; |
|
3994 local s=string.char; |
|
3995 local q,m=tostring,tonumber; |
|
3996 local u,r=pairs,ipairs; |
|
3997 local n=next; |
|
3998 local e=error; |
|
3999 local e,h,g=newproxy,getmetatable,setmetatable; |
|
4000 local c=print; |
|
4001 local a,o=pcall(require,"util.array"); |
|
4002 local f=a and h(o())or{}; |
|
4003 local a={}; |
|
4004 local i=e and e(true)or{}; |
|
4005 if h and h(i)then |
|
4006 h(i).__tostring=function()return"null";end; |
|
4007 end |
|
4008 a.null=i; |
|
4009 local w={ |
|
4010 ["\""]="\\\"",["\\"]="\\\\",["\b"]="\\b", |
|
4011 ["\f"]="\\f",["\n"]="\\n",["\r"]="\\r",["\t"]="\\t"}; |
|
4012 local e={ |
|
4013 ["\""]="\"",["\\"]="\\",["/"]="/", |
|
4014 b="\b",f="\f",n="\n",r="\r",t="\t"}; |
|
4015 for t=0,31 do |
|
4016 local e=s(t); |
|
4017 if not w[e]then w[e]=("\\u%.4X"):format(t);end |
|
4018 end |
|
4019 local function x(e) |
|
4020 if e<128 then return s(e);end |
|
4021 local t=e%64; |
|
4022 if e<2048 then |
|
4023 local e=(e-t)/64; |
|
4024 return s(128+64+e,128+t); |
|
4025 end |
|
4026 local a=e%4096; |
|
4027 local o=(a-t)/64; |
|
4028 local e=(e-a)/4096; |
|
4029 return s(128+64+32+e,128+o,128+t); |
|
4030 end |
|
4031 local k={ |
|
4032 number=true, |
|
4033 string=true, |
|
4034 table=true, |
|
4035 boolean=true |
|
4036 }; |
|
4037 local z={ |
|
4038 __array=true; |
|
4039 __hash=true; |
|
4040 }; |
|
4041 local o,b,d,l; |
|
4042 function l(e,a) |
|
4043 t(a,"\""..(e:gsub(".",w)).."\""); |
|
4044 end |
|
4045 function d(a,e) |
|
4046 t(e,"["); |
|
4047 if n(a)then |
|
4048 for i,a in r(a)do |
|
4049 o(a,e); |
|
4050 t(e,","); |
|
4051 end |
|
4052 v(e); |
|
4053 end |
|
4054 t(e,"]"); |
|
4055 end |
|
4056 function b(c,e) |
|
4057 local a={}; |
|
4058 local h={}; |
|
4059 local s={}; |
|
4060 for e,t in r(c)do |
|
4061 a[e]=t; |
|
4062 end |
|
4063 for e,t in u(c)do |
|
4064 local o,n=y(e),y(t); |
|
4065 if k[n]or t==i then |
|
4066 if o=="string"and not z[e]then |
|
4067 s[e]=t; |
|
4068 elseif(k[o]or e==i)and a[e]==nil then |
|
4069 h[e]=t; |
|
4070 end |
|
4071 end |
|
4072 end |
|
4073 if n(h)~=nil or n(s)~=nil or n(a)==nil then |
|
4074 t(e,"{"); |
|
4075 local c=#e; |
|
4076 if e.ordered then |
|
4077 local a={}; |
|
4078 for e in u(s)do |
|
4079 t(a,e); |
|
4080 end |
|
4081 j(a); |
|
4082 for i,a in r(a)do |
|
4083 l(a,e); |
|
4084 t(e,":"); |
|
4085 o(s[a],e); |
|
4086 t(e,","); |
|
4087 end |
|
4088 else |
|
4089 for i,a in u(s)do |
|
4090 l(i,e); |
|
4091 t(e,":"); |
|
4092 o(a,e); |
|
4093 t(e,","); |
|
4094 end |
|
4095 end |
|
4096 if n(h)~=nil then |
|
4097 t(e,"\"__hash\":["); |
|
4098 for i,a in u(h)do |
|
4099 o(i,e); |
|
4100 t(e,","); |
|
4101 o(a,e); |
|
4102 t(e,","); |
|
4103 end |
|
4104 v(e); |
|
4105 t(e,"]"); |
|
4106 t(e,","); |
|
4107 end |
|
4108 if n(a)then |
|
4109 t(e,"\"__array\":"); |
|
4110 d(a,e); |
|
4111 t(e,","); |
|
4112 end |
|
4113 if c~=#e then v(e);end |
|
4114 t(e,"}"); |
|
4115 else |
|
4116 d(a,e); |
|
4117 end |
|
4118 end |
|
4119 function o(e,a) |
|
4120 local o=y(e); |
|
4121 if o=="number"then |
|
4122 t(a,q(e)); |
|
4123 elseif o=="string"then |
|
4124 l(e,a); |
|
4125 elseif o=="table"then |
|
4126 local t=h(e); |
|
4127 if t==f then |
|
4128 d(e,a); |
|
4129 else |
|
4130 b(e,a); |
|
4131 end |
|
4132 elseif o=="boolean"then |
|
4133 t(a,(e and"true"or"false")); |
|
4134 else |
|
4135 t(a,"null"); |
|
4136 end |
|
4137 end |
|
4138 function a.encode(t) |
|
4139 local e={}; |
|
4140 o(t,e); |
|
4141 return p(e); |
|
4142 end |
|
4143 function a.encode_ordered(t) |
|
4144 local e={ordered=true}; |
|
4145 o(t,e); |
|
4146 return p(e); |
|
4147 end |
|
4148 function a.encode_array(t) |
|
4149 local e={}; |
|
4150 d(t,e); |
|
4151 return p(e); |
|
4152 end |
|
4153 local function o(t,e) |
|
4154 return t:find("[^ \t\r\n]",e)or e; |
|
4155 end |
|
4156 local function d(e) |
|
4157 local a=e.__array; |
|
4158 if a then |
|
4159 e.__array=nil; |
|
4160 for o,a in r(a)do |
|
4161 t(e,a); |
|
4162 end |
|
4163 end |
|
4164 local a=e.__hash; |
|
4165 if a then |
|
4166 e.__hash=nil; |
|
4167 local t; |
|
4168 for o,a in r(a)do |
|
4169 if t~=nil then |
|
4170 e[t]=a;t=nil; |
|
4171 else |
|
4172 t=a; |
|
4173 end |
|
4174 end |
|
4175 end |
|
4176 return e; |
|
4177 end |
|
4178 local n,h; |
|
4179 local function u(t,e) |
|
4180 local s={}; |
|
4181 while true do |
|
4182 local a,i; |
|
4183 e=o(t,e+1); |
|
4184 if t:byte(e)~=34 then |
|
4185 if t:byte(e)==125 then return s,e+1;end |
|
4186 return nil,"key expected"; |
|
4187 end |
|
4188 a,e=h(t,e); |
|
4189 if a==nil then return nil,e;end |
|
4190 e=o(t,e); |
|
4191 if t:byte(e)~=58 then return nil,"colon expected";end |
|
4192 i,e=n(t,e+1); |
|
4193 if i==nil then return nil,e;end |
|
4194 s[a]=i; |
|
4195 e=o(t,e); |
|
4196 local t=t:byte(e); |
|
4197 if t==125 then return d(s),e+1;end |
|
4198 if t~=44 then return nil,"object eof";end |
|
4199 end |
|
4200 end |
|
4201 local function l(i,e) |
|
4202 local s={}; |
|
4203 local h=e; |
|
4204 while true do |
|
4205 local a; |
|
4206 a,e=n(i,e+1); |
|
4207 if a==nil then |
|
4208 if i:byte(h+1)==93 then return g(s,f),h+2;end |
|
4209 return a,e; |
|
4210 end |
|
4211 t(s,a); |
|
4212 e=o(i,e); |
|
4213 local t=i:byte(e); |
|
4214 if t==93 then return g(s,f),e+1;end |
|
4215 if t~=44 then return nil,"array eof";end |
|
4216 end |
|
4217 end |
|
4218 local t; |
|
4219 local function e(e) |
|
4220 local t,e=m(e:sub(3,6),16),m(e:sub(9,12),16); |
|
4221 local e=t*1024+e-56613888; |
|
4222 local o=e%64; |
|
4223 e=(e-o)/64; |
|
4224 local t=e%64; |
|
4225 e=(e-t)/64; |
|
4226 local a=e%64; |
|
4227 e=(e-a)/64; |
|
4228 return s(240+e,128+a,128+t,128+o); |
|
4229 end |
|
4230 local function s(e) |
|
4231 e=e:match("%x%x%x%x",3); |
|
4232 if e then |
|
4233 return x(m(e,16)); |
|
4234 end |
|
4235 t=true; |
|
4236 end |
|
4237 function h(o,e) |
|
4238 e=e+1; |
|
4239 local a=o:find("\"",e,true); |
|
4240 if a then |
|
4241 local e=o:sub(e,a-1); |
|
4242 t=nil; |
|
4243 e=e:gsub("\\u.?.?.?.?",s); |
|
4244 if t then return nil,"invalid escape";end |
|
4245 return e,a+1; |
|
4246 end |
|
4247 return nil,"string eof"; |
|
4248 end |
|
4249 local function d(t,e) |
|
4250 local t=t:match("[0-9%.%-eE%+]+",e); |
|
4251 return m(t),e+#t; |
|
4252 end |
|
4253 local function s(t,e) |
|
4254 local o,a,t=t:byte(e+1,e+3); |
|
4255 if o==117 and a==108 and t==108 then |
|
4256 return i,e+4; |
|
4257 end |
|
4258 return nil,"null parse failed"; |
|
4259 end |
|
4260 local function i(t,e) |
|
4261 local t,a,o=t:byte(e+1,e+3); |
|
4262 if t==114 and a==117 and o==101 then |
|
4263 return true,e+4; |
|
4264 end |
|
4265 return nil,"true parse failed"; |
|
4266 end |
|
4267 local function r(t,e) |
|
4268 local i,o,a,t=t:byte(e+1,e+4); |
|
4269 if i==97 and o==108 and a==115 and t==101 then |
|
4270 return false,e+5; |
|
4271 end |
|
4272 return nil,"false parse failed"; |
|
4273 end |
|
4274 function n(a,t) |
|
4275 t=o(a,t); |
|
4276 local e=a:byte(t); |
|
4277 if e==123 then |
|
4278 return u(a,t); |
|
4279 elseif e==91 then |
|
4280 return l(a,t); |
|
4281 elseif e==34 then |
|
4282 return h(a,t); |
|
4283 elseif e~=nil and e>=48 and e<=57 or e==45 then |
|
4284 return d(a,t); |
|
4285 elseif e==110 then |
|
4286 return s(a,t); |
|
4287 elseif e==116 then |
|
4288 return i(a,t); |
|
4289 elseif e==102 then |
|
4290 return r(a,t); |
|
4291 else |
|
4292 return nil,"value expected"; |
|
4293 end |
|
4294 end |
|
4295 local t={ |
|
4296 ["\\\""]="\\u0022"; |
|
4297 ["\\\\"]="\\u005c"; |
|
4298 ["\\/"]="\\u002f"; |
|
4299 ["\\b"]="\\u0008"; |
|
4300 ["\\f"]="\\u000C"; |
|
4301 ["\\n"]="\\u000A"; |
|
4302 ["\\r"]="\\u000D"; |
|
4303 ["\\t"]="\\u0009"; |
|
4304 ["\\u"]="\\u"; |
|
4305 }; |
|
4306 function a.decode(e) |
|
4307 e=e:gsub("\\.",t) |
|
4308 local t,a=n(e,1); |
|
4309 if t==nil then return t,a;end |
|
4310 if e:find("[^ \t\r\n]",a)then return nil,"garbage at eof";end |
|
4311 return t; |
|
4312 end |
|
4313 function a.test(e) |
|
4314 local e=a.encode(e); |
|
4315 local t=a.decode(e); |
|
4316 local t=a.encode(t); |
|
4317 if e~=t then |
|
4318 c("FAILED"); |
|
4319 c("encoded:",e); |
|
4320 c("recoded:",t); |
|
4321 else |
|
4322 c(e); |
|
4323 end |
|
4324 return e==t; |
|
4325 end |
|
4326 return a; |
|
4327 end) |
|
4328 package.preload['util.xml']=(function(...) |
|
4329 local _ENV=_ENV; |
|
4330 local function a(t,...) |
|
4331 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
4332 package.loaded[t]=e; |
|
4333 for t=1,select("#",...)do |
|
4334 (select(t,...))(e); |
|
4335 end |
|
4336 _ENV=e; |
|
4337 _M=e; |
|
4338 return e; |
|
4339 end |
|
4340 local t=require"util.stanza"; |
|
4341 local n=require"lxp"; |
|
4342 a("xml") |
|
4343 local e=(function() |
|
4344 local s={ |
|
4345 ["http://www.w3.org/XML/1998/namespace"]="xml"; |
|
4346 }; |
|
4347 local e="\1"; |
|
4348 local i="^([^"..e.."]*)"..e.."?(.*)$"; |
|
4349 return function(h) |
|
4350 local o={}; |
|
4351 local a=t.stanza("root"); |
|
4352 function o:StartElement(t,e) |
|
4353 local t,o=t:match(i); |
|
4354 if o==""then |
|
4355 t,o="",t; |
|
4356 end |
|
4357 if t~=""then |
|
4358 e.xmlns=t; |
|
4359 end |
|
4360 for t=1,#e do |
|
4361 local a=e[t]; |
|
4362 e[t]=nil; |
|
4363 local t,o=a:match(i); |
|
4364 if o~=""then |
|
4365 t=s[t]; |
|
4366 if t then |
|
4367 e[t..":"..o]=e[a]; |
|
4368 e[a]=nil; |
|
4369 end |
|
4370 end |
|
4371 end |
|
4372 a:tag(o,e); |
|
4373 end |
|
4374 function o:CharacterData(e) |
|
4375 a:text(e); |
|
4376 end |
|
4377 function o:EndElement(e) |
|
4378 a:up(); |
|
4379 end |
|
4380 local n=n.new(o,"\1"); |
|
4381 local e,i,o,t=n:parse(h); |
|
4382 if e then e,i,o,t=n:parse();end |
|
4383 if e then |
|
4384 return a.tags[1]; |
|
4385 else |
|
4386 return e,i.." (line "..o..", col "..t..")"; |
|
4387 end |
|
4388 end; |
|
4389 end)(); |
|
4390 parse=e; |
|
4391 return _M; |
|
4392 end) |
|
4393 package.preload['util.rsm']=(function(...) |
|
4394 local _ENV=_ENV; |
|
4395 local function e(t,...) |
|
4396 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
4397 package.loaded[t]=e; |
|
4398 for t=1,select("#",...)do |
|
4399 (select(t,...))(e); |
|
4400 end |
|
4401 _ENV=e; |
|
4402 _M=e; |
|
4403 return e; |
|
4404 end |
|
4405 local n=require"util.stanza".stanza; |
|
4406 local a,o=tostring,tonumber; |
|
4407 local s=type; |
|
4408 local h=pairs; |
|
4409 local i='http://jabber.org/protocol/rsm'; |
|
4410 local t={}; |
|
4411 do |
|
4412 local e=t; |
|
4413 local function t(e) |
|
4414 return o((e:get_text())); |
|
4415 end |
|
4416 local function a(t) |
|
4417 return t:get_text(); |
|
4418 end |
|
4419 e.after=a; |
|
4420 e.before=function(e) |
|
4421 local e=e:get_text(); |
|
4422 return e==""or e; |
|
4423 end; |
|
4424 e.max=t; |
|
4425 e.index=t; |
|
4426 e.first=function(e) |
|
4427 return{index=o(e.attr.index);e:get_text()}; |
|
4428 end; |
|
4429 e.last=a; |
|
4430 e.count=t; |
|
4431 end |
|
4432 local r=setmetatable({ |
|
4433 first=function(t,e) |
|
4434 if s(e)=="table"then |
|
4435 t:tag("first",{index=e.index}):text(e[1]):up(); |
|
4436 else |
|
4437 t:tag("first"):text(a(e)):up(); |
|
4438 end |
|
4439 end; |
|
4440 before=function(e,t) |
|
4441 if t==true then |
|
4442 e:tag("before"):up(); |
|
4443 else |
|
4444 e:tag("before"):text(a(t)):up(); |
|
4445 end |
|
4446 end |
|
4447 },{ |
|
4448 __index=function(e,o) |
|
4449 return function(t,e) |
|
4450 t:tag(o):text(a(e)):up(); |
|
4451 end |
|
4452 end; |
|
4453 }); |
|
4454 local function o(e) |
|
4455 local o={}; |
|
4456 for a in e:childtags()do |
|
4457 local e=a.name; |
|
4458 local t=e and t[e]; |
|
4459 if t then |
|
4460 o[e]=t(a); |
|
4461 end |
|
4462 end |
|
4463 return o; |
|
4464 end |
|
4465 local function s(e) |
|
4466 local a=n("set",{xmlns=i}); |
|
4467 for e,o in h(e)do |
|
4468 if t[e]then |
|
4469 r[e](a,o); |
|
4470 end |
|
4471 end |
|
4472 return a; |
|
4473 end |
|
4474 local function t(e) |
|
4475 local e=e:get_child("set",i); |
|
4476 if e and#e.tags>0 then |
|
4477 return o(e); |
|
4478 end |
|
4479 end |
|
4480 return{parse=o,generate=s,get=t}; |
|
4481 end) |
|
4482 package.preload['util.random']=(function(...) |
|
4483 local _ENV=_ENV; |
|
4484 local function e(t,...) |
|
4485 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
4486 package.loaded[t]=e; |
|
4487 for t=1,select("#",...)do |
|
4488 (select(t,...))(e); |
|
4489 end |
|
4490 _ENV=e; |
|
4491 _M=e; |
|
4492 return e; |
|
4493 end |
|
4494 local e=io.open("/dev/urandom","r"); |
|
4495 if e then |
|
4496 return{ |
|
4497 seed=function()end; |
|
4498 bytes=function(t)return e:read(t);end |
|
4499 }; |
|
4500 end |
|
4501 local e=require"crypto" |
|
4502 return e.rand; |
|
4503 end) |
|
4504 package.preload['util.ip']=(function(...) |
|
4505 local _ENV=_ENV; |
|
4506 local function e(t,...) |
|
4507 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
4508 package.loaded[t]=e; |
|
4509 for t=1,select("#",...)do |
|
4510 (select(t,...))(e); |
|
4511 end |
|
4512 _ENV=e; |
|
4513 _M=e; |
|
4514 return e; |
|
4515 end |
|
4516 local o={}; |
|
4517 local i={__index=function(e,t)return(o[t])(e);end, |
|
4518 __tostring=function(e)return e.addr;end, |
|
4519 __eq=function(t,e)return t.addr==e.addr;end}; |
|
4520 local n={["0"]="0000",["1"]="0001",["2"]="0010",["3"]="0011",["4"]="0100",["5"]="0101",["6"]="0110",["7"]="0111",["8"]="1000",["9"]="1001",["A"]="1010",["B"]="1011",["C"]="1100",["D"]="1101",["E"]="1110",["F"]="1111"}; |
|
4521 local function e(t,e) |
|
4522 if not e then |
|
4523 local a=t:match("^%x+(.)"); |
|
4524 if a==":"or(not(a)and t:sub(1,1)==":")then |
|
4525 e="IPv6" |
|
4526 elseif a=="."then |
|
4527 e="IPv4" |
|
4528 end |
|
4529 if not e then |
|
4530 return nil,"invalid address"; |
|
4531 end |
|
4532 elseif e~="IPv4"and e~="IPv6"then |
|
4533 return nil,"invalid protocol"; |
|
4534 end |
|
4535 local a; |
|
4536 if e=="IPv6"and t:find('%',1,true)then |
|
4537 t,a=t:match("^(.-)%%(.*)"); |
|
4538 end |
|
4539 if e=="IPv6"and t:find('.',1,true)then |
|
4540 local e; |
|
4541 t,e=t:gsub(":(%d+)%.(%d+)%.(%d+)%.(%d+)$",function(t,e,o,a) |
|
4542 return(":%04X:%04X"):format(t*256+e,o*256+a); |
|
4543 end); |
|
4544 if e~=1 then return nil,"invalid-address";end |
|
4545 end |
|
4546 return setmetatable({addr=t,proto=e,zone=a},i); |
|
4547 end |
|
4548 local function i(e) |
|
4549 local t=""; |
|
4550 local a={}; |
|
4551 if e.proto=="IPv4"then |
|
4552 e=e.toV4mapped; |
|
4553 end |
|
4554 e=(e.addr):upper(); |
|
4555 e:gsub("([^:]*):?",function(e)a[#a+1]=e end); |
|
4556 if not e:match(":$")then a[#a]=nil;end |
|
4557 for o,e in ipairs(a)do |
|
4558 if e:len()==0 and o~=1 and o~=#a then |
|
4559 for e=1,16*(9-#a)do |
|
4560 t=t.."0"; |
|
4561 end |
|
4562 else |
|
4563 for e=1,4-e:len()do |
|
4564 t=t.."0000"; |
|
4565 end |
|
4566 for a=1,e:len()do |
|
4567 t=t..n[e:sub(a,a)]; |
|
4568 end |
|
4569 end |
|
4570 end |
|
4571 return t; |
|
4572 end |
|
4573 local function t(a,t) |
|
4574 a,t=i(a),i(t); |
|
4575 for e=1,128 do |
|
4576 if a:sub(e,e)~=t:sub(e,e)then |
|
4577 return e-1; |
|
4578 end |
|
4579 end |
|
4580 return 128; |
|
4581 end |
|
4582 local function r(t) |
|
4583 local e={}; |
|
4584 t:gsub("([^.]*).?",function(t)e[#e+1]=tonumber(t)end); |
|
4585 if e[1]==127 then |
|
4586 return 2; |
|
4587 elseif e[1]==169 and e[2]==254 then |
|
4588 return 2; |
|
4589 else |
|
4590 return 14; |
|
4591 end |
|
4592 end |
|
4593 local function h(e) |
|
4594 if e:match("^[0:]*1$")then |
|
4595 return 2; |
|
4596 elseif e:match("^[Ff][Ee][89ABab]")then |
|
4597 return 2; |
|
4598 elseif e:match("^[Ff][Ee][CcDdEeFf]")then |
|
4599 return 5; |
|
4600 elseif e:match("^[Ff][Ff]")then |
|
4601 return tonumber("0x"..e:sub(4,4)); |
|
4602 else |
|
4603 return 14; |
|
4604 end |
|
4605 end |
|
4606 local function i(a) |
|
4607 if t(a,e("::1","IPv6"))==128 then |
|
4608 return 0; |
|
4609 elseif t(a,e("2002::","IPv6"))>=16 then |
|
4610 return 2; |
|
4611 elseif t(a,e("2001::","IPv6"))>=32 then |
|
4612 return 5; |
|
4613 elseif t(a,e("fc00::","IPv6"))>=7 then |
|
4614 return 13; |
|
4615 elseif t(a,e("fec0::","IPv6"))>=10 then |
|
4616 return 11; |
|
4617 elseif t(a,e("3ffe::","IPv6"))>=16 then |
|
4618 return 12; |
|
4619 elseif t(a,e("::","IPv6"))>=96 then |
|
4620 return 3; |
|
4621 elseif t(a,e("::ffff:0:0","IPv6"))>=96 then |
|
4622 return 4; |
|
4623 else |
|
4624 return 1; |
|
4625 end |
|
4626 end |
|
4627 local function n(a) |
|
4628 if t(a,e("::1","IPv6"))==128 then |
|
4629 return 50; |
|
4630 elseif t(a,e("2002::","IPv6"))>=16 then |
|
4631 return 30; |
|
4632 elseif t(a,e("2001::","IPv6"))>=32 then |
|
4633 return 5; |
|
4634 elseif t(a,e("fc00::","IPv6"))>=7 then |
|
4635 return 3; |
|
4636 elseif t(a,e("fec0::","IPv6"))>=10 then |
|
4637 return 1; |
|
4638 elseif t(a,e("3ffe::","IPv6"))>=16 then |
|
4639 return 1; |
|
4640 elseif t(a,e("::","IPv6"))>=96 then |
|
4641 return 1; |
|
4642 elseif t(a,e("::ffff:0:0","IPv6"))>=96 then |
|
4643 return 35; |
|
4644 else |
|
4645 return 40; |
|
4646 end |
|
4647 end |
|
4648 local function s(o) |
|
4649 local a={}; |
|
4650 local t="::ffff:"; |
|
4651 o:gsub("([^.]*).?",function(e)a[#a+1]=tonumber(e)end); |
|
4652 t=t..("%02x"):format(a[1]); |
|
4653 t=t..("%02x"):format(a[2]); |
|
4654 t=t..":" |
|
4655 t=t..("%02x"):format(a[3]); |
|
4656 t=t..("%02x"):format(a[4]); |
|
4657 return e(t,"IPv6"); |
|
4658 end |
|
4659 function o:toV4mapped() |
|
4660 if self.proto~="IPv4"then return nil,"No IPv4 address"end |
|
4661 local e=s(self.addr); |
|
4662 self.toV4mapped=e; |
|
4663 return e; |
|
4664 end |
|
4665 function o:label() |
|
4666 local e; |
|
4667 if self.proto=="IPv4"then |
|
4668 e=i(self.toV4mapped); |
|
4669 else |
|
4670 e=i(self); |
|
4671 end |
|
4672 self.label=e; |
|
4673 return e; |
|
4674 end |
|
4675 function o:precedence() |
|
4676 local e; |
|
4677 if self.proto=="IPv4"then |
|
4678 e=n(self.toV4mapped); |
|
4679 else |
|
4680 e=n(self); |
|
4681 end |
|
4682 self.precedence=e; |
|
4683 return e; |
|
4684 end |
|
4685 function o:scope() |
|
4686 local e; |
|
4687 if self.proto=="IPv4"then |
|
4688 e=r(self.addr); |
|
4689 else |
|
4690 e=h(self.addr); |
|
4691 end |
|
4692 self.scope=e; |
|
4693 return e; |
|
4694 end |
|
4695 return{new_ip=e, |
|
4696 commonPrefixLength=t}; |
|
4697 end) |
|
4698 package.preload['util.time']=(function(...) |
|
4699 local _ENV=_ENV; |
|
4700 local function e(t,...) |
|
4701 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
4702 package.loaded[t]=e; |
|
4703 for t=1,select("#",...)do |
|
4704 (select(t,...))(e); |
|
4705 end |
|
4706 _ENV=e; |
|
4707 _M=e; |
|
4708 return e; |
|
4709 end |
|
4710 end) |
|
4711 package.preload['util.sasl.scram']=(function(...) |
|
4712 local _ENV=_ENV; |
|
4713 local function e(t,...) |
|
4714 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
4715 package.loaded[t]=e; |
|
4716 for t=1,select("#",...)do |
|
4717 (select(t,...))(e); |
|
4718 end |
|
4719 _ENV=e; |
|
4720 _M=e; |
|
4721 return e; |
|
4722 end |
|
4723 local n,m=require"mime".b64,require"mime".unb64; |
|
4724 local e=require"util.hashes"; |
|
4725 local a=require"bit"; |
|
4726 local s=require"util.random"; |
|
4727 local u=tonumber; |
|
4728 local o,t=string.char,string.byte; |
|
4729 local i=string.gsub; |
|
4730 local a=a.bxor; |
|
4731 local function c(n,e) |
|
4732 return(i(n,"()(.)",function(n,i) |
|
4733 return o(a(t(i),t(e,n))) |
|
4734 end)); |
|
4735 end |
|
4736 local w,t=e.sha1,e.hmac_sha1; |
|
4737 local function y(o,e,i) |
|
4738 local e=t(o,e.."\0\0\0\1"); |
|
4739 local a=e; |
|
4740 for i=2,i do |
|
4741 e=t(o,e); |
|
4742 a=c(a,e); |
|
4743 end |
|
4744 return a; |
|
4745 end |
|
4746 local function f(e) |
|
4747 return e; |
|
4748 end |
|
4749 local function a(e) |
|
4750 return(i(e,"[,=]",{[","]="=2C",["="]="=3D"})); |
|
4751 end |
|
4752 local function d(e,o) |
|
4753 local a="n="..a(e.username); |
|
4754 local d=n(s.bytes(15)); |
|
4755 local r="r="..d; |
|
4756 local h=a..","..r; |
|
4757 local i=""; |
|
4758 local a=e.conn:ssl()and"y"or"n"; |
|
4759 if o=="SCRAM-SHA-1-PLUS"then |
|
4760 i=e.conn:socket():getfinished(); |
|
4761 a="p=tls-unique"; |
|
4762 end |
|
4763 local s=a..",,"; |
|
4764 local a=s..h; |
|
4765 local a,l=coroutine.yield(a); |
|
4766 if a~="challenge"then return false end |
|
4767 local a,o,p=l:match("(r=[^,]+),s=([^,]*),i=(%d+)"); |
|
4768 local u=u(p); |
|
4769 o=m(o); |
|
4770 if not a or not o or not u then |
|
4771 return false,"Could not parse server_first_message"; |
|
4772 elseif a:find(d,3,true)~=3 then |
|
4773 return false,"nonce sent by server does not match our nonce"; |
|
4774 elseif a==r then |
|
4775 return false,"server did not append s-nonce to nonce"; |
|
4776 end |
|
4777 local i=s..i; |
|
4778 local i="c="..n(i); |
|
4779 local r=i..","..a; |
|
4780 local a; |
|
4781 local i; |
|
4782 local s; |
|
4783 if e.client_key and e.server_key then |
|
4784 i=e.client_key; |
|
4785 s=e.server_key; |
|
4786 else |
|
4787 if e.salted_password then |
|
4788 a=e.salted_password; |
|
4789 elseif e.password then |
|
4790 a=y(f(e.password),o,u); |
|
4791 end |
|
4792 s=t(a,"Server Key"); |
|
4793 i=t(a,"Client Key"); |
|
4794 end |
|
4795 local a=w(i); |
|
4796 local e=h..","..l..","..r; |
|
4797 local a=t(a,e); |
|
4798 local a=c(i,a); |
|
4799 local o=t(s,e); |
|
4800 local e="p="..n(a); |
|
4801 local e=r..","..e; |
|
4802 local t,e=coroutine.yield(e); |
|
4803 if t~="success"then return false,"success-expected"end |
|
4804 local e=e:match("v=([^,]+)"); |
|
4805 if m(e)~=o then |
|
4806 return false,"server signature did not match"; |
|
4807 end |
|
4808 return true; |
|
4809 end |
|
4810 return function(e,t) |
|
4811 if e.username and(e.password or(e.client_key or e.server_key))then |
|
4812 if t=="SCRAM-SHA-1"then |
|
4813 return d,99; |
|
4814 elseif t=="SCRAM-SHA-1-PLUS"then |
|
4815 local e=e.conn:ssl()and e.conn:socket(); |
|
4816 if e and e.getfinished then |
|
4817 return d,100; |
|
4818 end |
|
4819 end |
|
4820 end |
|
4821 end |
|
4822 end) |
|
4823 package.preload['util.sasl.plain']=(function(...) |
|
4824 local _ENV=_ENV; |
|
4825 local function e(t,...) |
|
4826 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
4827 package.loaded[t]=e; |
|
4828 for t=1,select("#",...)do |
|
4829 (select(t,...))(e); |
|
4830 end |
|
4831 _ENV=e; |
|
4832 _M=e; |
|
4833 return e; |
|
4834 end |
|
4835 return function(e,t) |
|
4836 if t=="PLAIN"and e.username and e.password then |
|
4837 return function(e) |
|
4838 return"success"==coroutine.yield((e.authzid or"").."\0"..e.username.."\0"..e.password); |
|
4839 end,5; |
|
4840 end |
|
4841 end |
|
4842 end) |
|
4843 package.preload['util.sasl.anonymous']=(function(...) |
|
4844 local _ENV=_ENV; |
|
4845 local function e(t,...) |
|
4846 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
4847 package.loaded[t]=e; |
|
4848 for t=1,select("#",...)do |
|
4849 (select(t,...))(e); |
|
4850 end |
|
4851 _ENV=e; |
|
4852 _M=e; |
|
4853 return e; |
|
4854 end |
|
4855 return function(t,e) |
|
4856 if e=="ANONYMOUS"then |
|
4857 return function() |
|
4858 return coroutine.yield()=="success"; |
|
4859 end,0; |
|
4860 end |
|
4861 end |
|
4862 end) |
|
4863 package.preload['verse.plugins.tls']=(function(...) |
|
4864 local _ENV=_ENV; |
|
4865 local function e(t,...) |
|
4866 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
4867 package.loaded[t]=e; |
|
4868 for t=1,select("#",...)do |
|
4869 (select(t,...))(e); |
|
4870 end |
|
4871 _ENV=e; |
|
4872 _M=e; |
|
4873 return e; |
|
4874 end |
|
4875 local a=require"verse"; |
|
4876 local t="urn:ietf:params:xml:ns:xmpp-tls"; |
|
4877 function a.plugins.tls(e) |
|
4878 local function i(o) |
|
4879 if e.authenticated then return;end |
|
4880 if o:get_child("starttls",t)and e.conn.starttls then |
|
4881 e:debug("Negotiating TLS..."); |
|
4882 e:send(a.stanza("starttls",{xmlns=t})); |
|
4883 return true; |
|
4884 elseif not e.conn.starttls and not e.secure then |
|
4885 e:warn("SSL library (LuaSec) not loaded, so TLS not available"); |
|
4886 elseif not e.secure then |
|
4887 e:debug("Server doesn't offer TLS :("); |
|
4888 end |
|
4889 end |
|
4890 local function o(t) |
|
4891 if t.name=="proceed"then |
|
4892 e:debug("Server says proceed, handshake starting..."); |
|
4893 e.conn:starttls(e.ssl or{mode="client",protocol="sslv23",options="no_sslv2",capath="/etc/ssl/certs"},true); |
|
4894 end |
|
4895 end |
|
4896 local function a(t) |
|
4897 if t=="ssl-handshake-complete"then |
|
4898 e.secure=true; |
|
4899 e:debug("Re-opening stream..."); |
|
4900 e:reopen(); |
|
4901 end |
|
4902 end |
|
4903 e:hook("stream-features",i,400); |
|
4904 e:hook("stream/"..t,o); |
|
4905 e:hook("status",a,400); |
|
4906 return true; |
|
4907 end |
|
4908 end) |
|
4909 package.preload['verse.plugins.sasl']=(function(...) |
|
4910 local _ENV=_ENV; |
|
4911 local function e(t,...) |
|
4912 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
4913 package.loaded[t]=e; |
|
4914 for t=1,select("#",...)do |
|
4915 (select(t,...))(e); |
|
4916 end |
|
4917 _ENV=e; |
|
4918 _M=e; |
|
4919 return e; |
|
4920 end |
|
4921 local n=require"verse"; |
|
4922 local s,h=require"mime".b64,require"mime".unb64; |
|
4923 local a="urn:ietf:params:xml:ns:xmpp-sasl"; |
|
4924 function n.plugins.sasl(e) |
|
4925 local function r(t) |
|
4926 if e.authenticated then return;end |
|
4927 e:debug("Authenticating with SASL..."); |
|
4928 local t=t:get_child("mechanisms",a); |
|
4929 if not t then return end |
|
4930 local o={}; |
|
4931 local i={}; |
|
4932 for t in t:childtags("mechanism")do |
|
4933 t=t:get_text(); |
|
4934 e:debug("Server offers %s",t); |
|
4935 if not o[t]then |
|
4936 local n=t:match("[^-]+"); |
|
4937 local s,a=pcall(require,"util.sasl."..n:lower()); |
|
4938 if s then |
|
4939 e:debug("Loaded SASL %s module",n); |
|
4940 o[t],i[t]=a(e,t); |
|
4941 elseif not tostring(a):match("not found")then |
|
4942 e:debug("Loading failed: %s",tostring(a)); |
|
4943 end |
|
4944 end |
|
4945 end |
|
4946 local t={}; |
|
4947 for e in pairs(o)do |
|
4948 table.insert(t,e); |
|
4949 end |
|
4950 if not t[1]then |
|
4951 e:event("authentication-failure",{condition="no-supported-sasl-mechanisms"}); |
|
4952 e:close(); |
|
4953 return; |
|
4954 end |
|
4955 table.sort(t,function(e,t)return i[e]>i[t];end); |
|
4956 local t,i=t[1]; |
|
4957 e:debug("Selecting %s mechanism...",t); |
|
4958 e.sasl_mechanism=coroutine.wrap(o[t]); |
|
4959 i=e:sasl_mechanism(t); |
|
4960 local t=n.stanza("auth",{xmlns=a,mechanism=t}); |
|
4961 if i then |
|
4962 t:text(s(i)); |
|
4963 end |
|
4964 e:send(t); |
|
4965 return true; |
|
4966 end |
|
4967 local function i(t) |
|
4968 if t.name=="failure"then |
|
4969 local a=t.tags[1]; |
|
4970 local t=t:get_child_text("text"); |
|
4971 e:event("authentication-failure",{condition=a.name,text=t}); |
|
4972 e:close(); |
|
4973 return false; |
|
4974 end |
|
4975 local t,o=e.sasl_mechanism(t.name,h(t:get_text())); |
|
4976 if not t then |
|
4977 e:event("authentication-failure",{condition=o}); |
|
4978 e:close(); |
|
4979 return false; |
|
4980 elseif t==true then |
|
4981 e:event("authentication-success"); |
|
4982 e.authenticated=true |
|
4983 e:reopen(); |
|
4984 else |
|
4985 e:send(n.stanza("response",{xmlns=a}):text(s(t))); |
|
4986 end |
|
4987 return true; |
|
4988 end |
|
4989 e:hook("stream-features",r,300); |
|
4990 e:hook("stream/"..a,i); |
|
4991 return true; |
|
4992 end |
|
4993 end) |
|
4994 package.preload['verse.plugins.bind']=(function(...) |
|
4995 local _ENV=_ENV; |
|
4996 local function e(t,...) |
|
4997 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
4998 package.loaded[t]=e; |
|
4999 for t=1,select("#",...)do |
|
5000 (select(t,...))(e); |
|
5001 end |
|
5002 _ENV=e; |
|
5003 _M=e; |
|
5004 return e; |
|
5005 end |
|
5006 local t=require"verse"; |
|
5007 local o=require"util.jid"; |
|
5008 local a="urn:ietf:params:xml:ns:xmpp-bind"; |
|
5009 function t.plugins.bind(e) |
|
5010 local function i(i) |
|
5011 if e.bound then return;end |
|
5012 e:debug("Binding resource..."); |
|
5013 e:send_iq(t.iq({type="set"}):tag("bind",{xmlns=a}):tag("resource"):text(e.resource), |
|
5014 function(t) |
|
5015 if t.attr.type=="result"then |
|
5016 local t=t |
|
5017 :get_child("bind",a) |
|
5018 :get_child_text("jid"); |
|
5019 e.username,e.host,e.resource=o.split(t); |
|
5020 e.jid,e.bound=t,true; |
|
5021 e:event("bind-success",{jid=t}); |
|
5022 elseif t.attr.type=="error"then |
|
5023 local a=t:child_with_name("error"); |
|
5024 local t,a,o=t:get_error(); |
|
5025 e:event("bind-failure",{error=a,text=o,type=t}); |
|
5026 end |
|
5027 end); |
|
5028 end |
|
5029 e:hook("stream-features",i,200); |
|
5030 return true; |
|
5031 end |
|
5032 end) |
|
5033 package.preload['verse.plugins.session']=(function(...) |
|
5034 local _ENV=_ENV; |
|
5035 local function e(t,...) |
|
5036 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
5037 package.loaded[t]=e; |
|
5038 for t=1,select("#",...)do |
|
5039 (select(t,...))(e); |
|
5040 end |
|
5041 _ENV=e; |
|
5042 _M=e; |
|
5043 return e; |
|
5044 end |
|
5045 local a=require"verse"; |
|
5046 local t="urn:ietf:params:xml:ns:xmpp-session"; |
|
5047 function a.plugins.session(e) |
|
5048 local function i(o) |
|
5049 local o=o:get_child("session",t); |
|
5050 if o and not o:get_child("optional")then |
|
5051 local function o(o) |
|
5052 e:debug("Establishing Session..."); |
|
5053 e:send_iq(a.iq({type="set"}):tag("session",{xmlns=t}), |
|
5054 function(t) |
|
5055 if t.attr.type=="result"then |
|
5056 e:event("session-success"); |
|
5057 elseif t.attr.type=="error"then |
|
5058 local t,o,a=t:get_error(); |
|
5059 e:event("session-failure",{error=o,text=a,type=t}); |
|
5060 end |
|
5061 end); |
|
5062 return true; |
|
5063 end |
|
5064 e:hook("bind-success",o); |
|
5065 end |
|
5066 end |
|
5067 e:hook("stream-features",i); |
|
5068 return true; |
|
5069 end |
|
5070 end) |
|
5071 package.preload['verse.plugins.legacy']=(function(...) |
|
5072 local _ENV=_ENV; |
|
5073 local function e(t,...) |
|
5074 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
5075 package.loaded[t]=e; |
|
5076 for t=1,select("#",...)do |
|
5077 (select(t,...))(e); |
|
5078 end |
|
5079 _ENV=e; |
|
5080 _M=e; |
|
5081 return e; |
|
5082 end |
|
5083 local i=require"verse"; |
|
5084 local s=require"util.uuid".generate; |
|
5085 local a="jabber:iq:auth"; |
|
5086 function i.plugins.legacy(e) |
|
5087 local function n(t) |
|
5088 local o=t:get_child("query",a); |
|
5089 if t.attr.type~="result"or not o then |
|
5090 local t,a,o=t:get_error(); |
|
5091 e:debug("warn","%s %s: %s",t,a,o); |
|
5092 end |
|
5093 local t={ |
|
5094 username=e.username; |
|
5095 password=e.password; |
|
5096 resource=e.resource or s(); |
|
5097 digest=false,sequence=false,token=false; |
|
5098 }; |
|
5099 local a=i.iq({to=e.host,type="set"}) |
|
5100 :tag("query",{xmlns=a}); |
|
5101 if#o>0 then |
|
5102 for o in o:childtags()do |
|
5103 local o=o.name; |
|
5104 local i=t[o]; |
|
5105 if i then |
|
5106 a:tag(o):text(t[o]):up(); |
|
5107 elseif i==nil then |
|
5108 local t="feature-not-implemented"; |
|
5109 e:event("authentication-failure",{condition=t}); |
|
5110 return false; |
|
5111 end |
|
5112 end |
|
5113 else |
|
5114 for t,e in pairs(t)do |
|
5115 if e then |
|
5116 a:tag(t):text(e):up(); |
|
5117 end |
|
5118 end |
|
5119 end |
|
5120 e:send_iq(a,function(a) |
|
5121 if a.attr.type=="result"then |
|
5122 e.resource=t.resource; |
|
5123 e.jid=t.username.."@"..e.host.."/"..t.resource; |
|
5124 e:event("authentication-success"); |
|
5125 e:event("bind-success",e.jid); |
|
5126 else |
|
5127 local a,t,a=a:get_error(); |
|
5128 e:event("authentication-failure",{condition=t}); |
|
5129 end |
|
5130 end); |
|
5131 end |
|
5132 local function a(t) |
|
5133 if not t.version then |
|
5134 e:send_iq(i.iq({type="get"}) |
|
5135 :tag("query",{xmlns="jabber:iq:auth"}) |
|
5136 :tag("username"):text(e.username), |
|
5137 n); |
|
5138 end |
|
5139 end |
|
5140 e:hook("opened",a); |
|
5141 end |
|
5142 end) |
|
5143 package.preload['verse.plugins.compression']=(function(...) |
|
5144 local _ENV=_ENV; |
|
5145 local function e(t,...) |
|
5146 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
5147 package.loaded[t]=e; |
|
5148 for t=1,select("#",...)do |
|
5149 (select(t,...))(e); |
|
5150 end |
|
5151 _ENV=e; |
|
5152 _M=e; |
|
5153 return e; |
|
5154 end |
|
5155 local t=require"verse"; |
|
5156 local i=require"zlib"; |
|
5157 local e="http://jabber.org/features/compress" |
|
5158 local a="http://jabber.org/protocol/compress" |
|
5159 local e="http://etherx.jabber.org/streams"; |
|
5160 local o=9; |
|
5161 local function s(e) |
|
5162 local i,o=pcall(i.deflate,o); |
|
5163 if i==false then |
|
5164 local t=t.stanza("failure",{xmlns=a}):tag("setup-failed"); |
|
5165 e:send(t); |
|
5166 e:error("Failed to create zlib.deflate filter: %s",tostring(o)); |
|
5167 return |
|
5168 end |
|
5169 return o |
|
5170 end |
|
5171 local function n(o) |
|
5172 local i,e=pcall(i.inflate); |
|
5173 if i==false then |
|
5174 local t=t.stanza("failure",{xmlns=a}):tag("setup-failed"); |
|
5175 o:send(t); |
|
5176 o:error("Failed to create zlib.inflate filter: %s",tostring(e)); |
|
5177 return |
|
5178 end |
|
5179 return e |
|
5180 end |
|
5181 local function i(e,o) |
|
5182 function e:send(i) |
|
5183 local i,o,n=pcall(o,tostring(i),'sync'); |
|
5184 if i==false then |
|
5185 e:close({ |
|
5186 condition="undefined-condition"; |
|
5187 text=o; |
|
5188 extra=t.stanza("failure",{xmlns=a}):tag("processing-failed"); |
|
5189 }); |
|
5190 e:warn("Compressed send failed: %s",tostring(o)); |
|
5191 return; |
|
5192 end |
|
5193 e.conn:write(o); |
|
5194 end; |
|
5195 end |
|
5196 local function h(e,o) |
|
5197 local n=e.data |
|
5198 e.data=function(i,s) |
|
5199 e:debug("Decompressing data..."); |
|
5200 local s,o,h=pcall(o,s); |
|
5201 if s==false then |
|
5202 e:close({ |
|
5203 condition="undefined-condition"; |
|
5204 text=o; |
|
5205 extra=t.stanza("failure",{xmlns=a}):tag("processing-failed"); |
|
5206 }); |
|
5207 stream:warn("%s",tostring(o)); |
|
5208 return; |
|
5209 end |
|
5210 return n(i,o); |
|
5211 end; |
|
5212 end |
|
5213 function t.plugins.compression(e) |
|
5214 local function d(o) |
|
5215 if not e.compressed then |
|
5216 local o=o:child_with_name("compression"); |
|
5217 if o then |
|
5218 for o in o:children()do |
|
5219 local o=o[1] |
|
5220 if o=="zlib"then |
|
5221 e:send(t.stanza("compress",{xmlns=a}):tag("method"):text("zlib")) |
|
5222 e:debug("Enabled compression using zlib.") |
|
5223 return true; |
|
5224 end |
|
5225 end |
|
5226 session:debug("Remote server supports no compression algorithm we support.") |
|
5227 end |
|
5228 end |
|
5229 end |
|
5230 local function r(o) |
|
5231 if o.name=="compressed"then |
|
5232 e:debug("Activating compression...") |
|
5233 local a=s(e); |
|
5234 if not a then return end |
|
5235 local t=n(e); |
|
5236 if not t then return end |
|
5237 i(e,a); |
|
5238 h(e,t); |
|
5239 e.compressed=true; |
|
5240 e:reopen(); |
|
5241 elseif o.name=="failure"then |
|
5242 e:warn("Failed to establish compression"); |
|
5243 end |
|
5244 end |
|
5245 e:hook("stream-features",d,250); |
|
5246 e:hook("stream/"..a,r); |
|
5247 end |
|
5248 end) |
|
5249 package.preload['verse.plugins.smacks']=(function(...) |
|
5250 local _ENV=_ENV; |
|
5251 local function e(t,...) |
|
5252 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
5253 package.loaded[t]=e; |
|
5254 for t=1,select("#",...)do |
|
5255 (select(t,...))(e); |
|
5256 end |
|
5257 _ENV=e; |
|
5258 _M=e; |
|
5259 return e; |
|
5260 end |
|
5261 local n=require"verse"; |
|
5262 local h=require"socket".gettime; |
|
5263 local s="urn:xmpp:sm:3"; |
|
5264 function n.plugins.smacks(e) |
|
5265 local t={}; |
|
5266 local a=0; |
|
5267 local r=h(); |
|
5268 local o; |
|
5269 local i=0; |
|
5270 local function l(t) |
|
5271 if t.attr.xmlns=="jabber:client"or not t.attr.xmlns then |
|
5272 i=i+1; |
|
5273 e:debug("Increasing handled stanzas to %d for %s",i,t:top_tag()); |
|
5274 end |
|
5275 end |
|
5276 local function u(a) |
|
5277 if a.name and not a.attr.xmlns then |
|
5278 t[#t+1]=tostring(a); |
|
5279 r=h(); |
|
5280 if not o then |
|
5281 o=true; |
|
5282 e:debug("Waiting to send ack request..."); |
|
5283 n.add_task(1,function() |
|
5284 if#t==0 then |
|
5285 o=false; |
|
5286 return; |
|
5287 end |
|
5288 local a=h()-r; |
|
5289 if a<1 and#t<10 then |
|
5290 return 1-a; |
|
5291 end |
|
5292 e:debug("Time up, sending <r>..."); |
|
5293 o=false; |
|
5294 e:send(n.stanza("r",{xmlns=s})); |
|
5295 end); |
|
5296 end |
|
5297 end |
|
5298 end |
|
5299 local function h() |
|
5300 e:debug("smacks: connection lost"); |
|
5301 e.stream_management_supported=nil; |
|
5302 if e.resumption_token then |
|
5303 e:debug("smacks: have resumption token, reconnecting in 1s..."); |
|
5304 e.authenticated=nil; |
|
5305 n.add_task(1,function() |
|
5306 e:connect(e.connect_host or e.host,e.connect_port or 5222); |
|
5307 end); |
|
5308 return true; |
|
5309 end |
|
5310 end |
|
5311 local function d() |
|
5312 e.resumption_token=nil; |
|
5313 e:unhook("disconnected",h); |
|
5314 end |
|
5315 local function r(o) |
|
5316 if o.name=="r"then |
|
5317 e:debug("Ack requested... acking %d handled stanzas",i); |
|
5318 e:send(n.stanza("a",{xmlns=s,h=tostring(i)})); |
|
5319 elseif o.name=="a"then |
|
5320 local o=tonumber(o.attr.h); |
|
5321 if o>a then |
|
5322 local i=#t; |
|
5323 for a=a+1,o do |
|
5324 table.remove(t,1); |
|
5325 end |
|
5326 e:debug("Received ack: New ack: "..o.." Last ack: "..a.." Unacked stanzas now: "..#t.." (was "..i..")"); |
|
5327 a=o; |
|
5328 else |
|
5329 e:warn("Received bad ack for "..o.." when last ack was "..a); |
|
5330 end |
|
5331 elseif o.name=="enabled"then |
|
5332 if o.attr.id then |
|
5333 e.resumption_token=o.attr.id; |
|
5334 e:hook("closed",d,100); |
|
5335 e:hook("disconnected",h,100); |
|
5336 end |
|
5337 elseif o.name=="resumed"then |
|
5338 local o=tonumber(o.attr.h); |
|
5339 if o>a then |
|
5340 local i=#t; |
|
5341 for a=a+1,o do |
|
5342 table.remove(t,1); |
|
5343 end |
|
5344 e:debug("Received ack: New ack: "..o.." Last ack: "..a.." Unacked stanzas now: "..#t.." (was "..i..")"); |
|
5345 a=o; |
|
5346 end |
|
5347 for a=1,#t do |
|
5348 e:send(t[a]); |
|
5349 end |
|
5350 t={}; |
|
5351 e:debug("Resumed successfully"); |
|
5352 e:event("resumed"); |
|
5353 else |
|
5354 e:warn("Don't know how to handle "..s.."/"..o.name); |
|
5355 end |
|
5356 end |
|
5357 local function t() |
|
5358 if not e.smacks then |
|
5359 e:debug("smacks: sending enable"); |
|
5360 e:send(n.stanza("enable",{xmlns=s,resume="true"})); |
|
5361 e.smacks=true; |
|
5362 e:hook("stanza",l); |
|
5363 e:hook("outgoing",u); |
|
5364 end |
|
5365 end |
|
5366 local function o(a) |
|
5367 if a:get_child("sm",s)then |
|
5368 e.stream_management_supported=true; |
|
5369 if e.smacks and e.bound then |
|
5370 e:debug("Resuming stream with %d handled stanzas",i); |
|
5371 e:send(n.stanza("resume",{xmlns=s, |
|
5372 h=i,previd=e.resumption_token})); |
|
5373 return true; |
|
5374 else |
|
5375 e:hook("bind-success",t,1); |
|
5376 end |
|
5377 end |
|
5378 end |
|
5379 e:hook("stream-features",o,250); |
|
5380 e:hook("stream/"..s,r); |
|
5381 end |
|
5382 end) |
|
5383 package.preload['verse.plugins.keepalive']=(function(...) |
|
5384 local _ENV=_ENV; |
|
5385 local function e(t,...) |
|
5386 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
5387 package.loaded[t]=e; |
|
5388 for t=1,select("#",...)do |
|
5389 (select(t,...))(e); |
|
5390 end |
|
5391 _ENV=e; |
|
5392 _M=e; |
|
5393 return e; |
|
5394 end |
|
5395 local t=require"verse"; |
|
5396 function t.plugins.keepalive(e) |
|
5397 e.keepalive_timeout=e.keepalive_timeout or 300; |
|
5398 t.add_task(e.keepalive_timeout,function() |
|
5399 e.conn:write(" "); |
|
5400 return e.keepalive_timeout; |
|
5401 end); |
|
5402 end |
|
5403 end) |
|
5404 package.preload['verse.plugins.disco']=(function(...) |
|
5405 local _ENV=_ENV; |
|
5406 local function e(t,...) |
|
5407 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
5408 package.loaded[t]=e; |
|
5409 for t=1,select("#",...)do |
|
5410 (select(t,...))(e); |
|
5411 end |
|
5412 _ENV=e; |
|
5413 _M=e; |
|
5414 return e; |
|
5415 end |
|
5416 local t=require"verse"; |
|
5417 local e=require("mime").b64; |
|
5418 local e=require("util.hashes").sha1; |
|
5419 local s=require"util.caps".calculate_hash; |
|
5420 local n="http://jabber.org/protocol/caps"; |
|
5421 local e="http://jabber.org/protocol/disco"; |
|
5422 local i=e.."#info"; |
|
5423 local o=e.."#items"; |
|
5424 function t.plugins.disco(e) |
|
5425 e:add_plugin("presence"); |
|
5426 local a={ |
|
5427 __index=function(a,e) |
|
5428 local t={identities={},features={}}; |
|
5429 if e=="identities"or e=="features"then |
|
5430 return a[false][e] |
|
5431 end |
|
5432 a[e]=t; |
|
5433 return t; |
|
5434 end, |
|
5435 }; |
|
5436 local h={ |
|
5437 __index=function(t,a) |
|
5438 local e={}; |
|
5439 t[a]=e; |
|
5440 return e; |
|
5441 end, |
|
5442 }; |
|
5443 e.disco={ |
|
5444 cache={}, |
|
5445 info=setmetatable({ |
|
5446 [false]={ |
|
5447 identities={ |
|
5448 {category='client',type='pc',name='Verse'}, |
|
5449 }, |
|
5450 features={ |
|
5451 [n]=true, |
|
5452 [i]=true, |
|
5453 [o]=true, |
|
5454 }, |
|
5455 }, |
|
5456 },a); |
|
5457 items=setmetatable({[false]={}},h); |
|
5458 }; |
|
5459 e.caps={} |
|
5460 e.caps.node='http://code.matthewwild.co.uk/verse/' |
|
5461 local function h(a) |
|
5462 local o=e.disco.info[a or false]; |
|
5463 if a and a==e.caps.node.."#"..e.caps.hash then |
|
5464 o=e.disco.info[false]; |
|
5465 end |
|
5466 local n,o=o.identities,o.features |
|
5467 local e=t.stanza("query",{ |
|
5468 xmlns=i, |
|
5469 node=a, |
|
5470 }); |
|
5471 for a,t in pairs(n)do |
|
5472 e:tag('identity',t):up() |
|
5473 end |
|
5474 for t in pairs(o)do |
|
5475 e:tag('feature',{var=t}):up() |
|
5476 end |
|
5477 return e; |
|
5478 end |
|
5479 setmetatable(e.caps,{ |
|
5480 __call=function(...) |
|
5481 local a=s(h()) |
|
5482 e.caps.hash=a; |
|
5483 return t.stanza('c',{ |
|
5484 xmlns=n, |
|
5485 hash='sha-1', |
|
5486 node=e.caps.node, |
|
5487 ver=a |
|
5488 }) |
|
5489 end |
|
5490 }) |
|
5491 function e:set_identity(a,t) |
|
5492 self.disco.info[t or false].identities={a}; |
|
5493 e:resend_presence(); |
|
5494 end |
|
5495 function e:add_identity(a,t) |
|
5496 local t=self.disco.info[t or false].identities; |
|
5497 t[#t+1]=a; |
|
5498 e:resend_presence(); |
|
5499 end |
|
5500 function e:add_disco_feature(t,a) |
|
5501 local t=t.var or t; |
|
5502 self.disco.info[a or false].features[t]=true; |
|
5503 e:resend_presence(); |
|
5504 end |
|
5505 function e:remove_disco_feature(t,a) |
|
5506 local t=t.var or t; |
|
5507 self.disco.info[a or false].features[t]=nil; |
|
5508 e:resend_presence(); |
|
5509 end |
|
5510 function e:add_disco_item(t,e) |
|
5511 local e=self.disco.items[e or false]; |
|
5512 e[#e+1]=t; |
|
5513 end |
|
5514 function e:remove_disco_item(a,e) |
|
5515 local e=self.disco.items[e or false]; |
|
5516 for t=#e,1,-1 do |
|
5517 if e[t]==a then |
|
5518 table.remove(e,t); |
|
5519 end |
|
5520 end |
|
5521 end |
|
5522 function e:jid_has_identity(e,a,t) |
|
5523 local o=self.disco.cache[e]; |
|
5524 if not o then |
|
5525 return nil,"no-cache"; |
|
5526 end |
|
5527 local e=self.disco.cache[e].identities; |
|
5528 if t then |
|
5529 return e[a.."/"..t]or false; |
|
5530 end |
|
5531 for e in pairs(e)do |
|
5532 if e:match("^(.*)/")==a then |
|
5533 return true; |
|
5534 end |
|
5535 end |
|
5536 end |
|
5537 function e:jid_supports(e,t) |
|
5538 local e=self.disco.cache[e]; |
|
5539 if not e or not e.features then |
|
5540 return nil,"no-cache"; |
|
5541 end |
|
5542 return e.features[t]or false; |
|
5543 end |
|
5544 function e:get_local_services(o,a) |
|
5545 local e=self.disco.cache[self.host]; |
|
5546 if not(e)or not(e.items)then |
|
5547 return nil,"no-cache"; |
|
5548 end |
|
5549 local t={}; |
|
5550 for i,e in ipairs(e.items)do |
|
5551 if self:jid_has_identity(e.jid,o,a)then |
|
5552 table.insert(t,e.jid); |
|
5553 end |
|
5554 end |
|
5555 return t; |
|
5556 end |
|
5557 function e:disco_local_services(a) |
|
5558 self:disco_items(self.host,nil,function(t) |
|
5559 if not t then |
|
5560 return a({}); |
|
5561 end |
|
5562 local e=0; |
|
5563 local function o() |
|
5564 e=e-1; |
|
5565 if e==0 then |
|
5566 return a(t); |
|
5567 end |
|
5568 end |
|
5569 for a,t in ipairs(t)do |
|
5570 if t.jid then |
|
5571 e=e+1; |
|
5572 self:disco_info(t.jid,nil,o); |
|
5573 end |
|
5574 end |
|
5575 if e==0 then |
|
5576 return a(t); |
|
5577 end |
|
5578 end); |
|
5579 end |
|
5580 function e:disco_info(e,a,s) |
|
5581 local t=t.iq({to=e,type="get"}) |
|
5582 :tag("query",{xmlns=i,node=a}); |
|
5583 self:send_iq(t,function(n) |
|
5584 if n.attr.type=="error"then |
|
5585 return s(nil,n:get_error()); |
|
5586 end |
|
5587 local o,t={},{}; |
|
5588 for e in n:get_child("query",i):childtags()do |
|
5589 if e.name=="identity"then |
|
5590 o[e.attr.category.."/"..e.attr.type]=e.attr.name or true; |
|
5591 elseif e.name=="feature"then |
|
5592 t[e.attr.var]=true; |
|
5593 end |
|
5594 end |
|
5595 if not self.disco.cache[e]then |
|
5596 self.disco.cache[e]={nodes={}}; |
|
5597 end |
|
5598 if a then |
|
5599 if not self.disco.cache[e].nodes[a]then |
|
5600 self.disco.cache[e].nodes[a]={nodes={}}; |
|
5601 end |
|
5602 self.disco.cache[e].nodes[a].identities=o; |
|
5603 self.disco.cache[e].nodes[a].features=t; |
|
5604 else |
|
5605 self.disco.cache[e].identities=o; |
|
5606 self.disco.cache[e].features=t; |
|
5607 end |
|
5608 return s(self.disco.cache[e]); |
|
5609 end); |
|
5610 end |
|
5611 function e:disco_items(a,i,n) |
|
5612 local t=t.iq({to=a,type="get"}) |
|
5613 :tag("query",{xmlns=o,node=i}); |
|
5614 self:send_iq(t,function(e) |
|
5615 if e.attr.type=="error"then |
|
5616 return n(nil,e:get_error()); |
|
5617 end |
|
5618 local t={}; |
|
5619 for e in e:get_child("query",o):childtags()do |
|
5620 if e.name=="item"then |
|
5621 table.insert(t,{ |
|
5622 name=e.attr.name; |
|
5623 jid=e.attr.jid; |
|
5624 node=e.attr.node; |
|
5625 }); |
|
5626 end |
|
5627 end |
|
5628 if not self.disco.cache[a]then |
|
5629 self.disco.cache[a]={nodes={}}; |
|
5630 end |
|
5631 if i then |
|
5632 if not self.disco.cache[a].nodes[i]then |
|
5633 self.disco.cache[a].nodes[i]={nodes={}}; |
|
5634 end |
|
5635 self.disco.cache[a].nodes[i].items=t; |
|
5636 else |
|
5637 self.disco.cache[a].items=t; |
|
5638 end |
|
5639 return n(t); |
|
5640 end); |
|
5641 end |
|
5642 e:hook("iq/"..i,function(a) |
|
5643 local o=a.tags[1]; |
|
5644 if a.attr.type=='get'and o.name=="query"then |
|
5645 local o=h(o.attr.node); |
|
5646 local t=t.reply(a):add_child(o); |
|
5647 e:send(t); |
|
5648 return true |
|
5649 end |
|
5650 end); |
|
5651 e:hook("iq/"..o,function(i) |
|
5652 local a=i.tags[1]; |
|
5653 if i.attr.type=='get'and a.name=="query"then |
|
5654 local n=e.disco.items[a.attr.node or false]; |
|
5655 local t=t.reply(i):tag('query',{ |
|
5656 xmlns=o, |
|
5657 node=a.attr.node |
|
5658 }) |
|
5659 for a=1,#n do |
|
5660 t:tag('item',n[a]):up() |
|
5661 end |
|
5662 e:send(t); |
|
5663 return true |
|
5664 end |
|
5665 end); |
|
5666 local t; |
|
5667 e:hook("ready",function() |
|
5668 if t then return;end |
|
5669 t=true; |
|
5670 local function o(t) |
|
5671 local a=e.disco.cache[t]; |
|
5672 if a then |
|
5673 for a in pairs(a.identities)do |
|
5674 local o,a=a:match("^(.*)/(.*)$"); |
|
5675 print(t,o,a) |
|
5676 e:event("disco/service-discovered/"..o,{ |
|
5677 type=a,jid=t; |
|
5678 }); |
|
5679 end |
|
5680 end |
|
5681 end |
|
5682 e:disco_info(e.host,nil,function() |
|
5683 o(e.host); |
|
5684 end); |
|
5685 e:disco_local_services(function(t) |
|
5686 for a,t in ipairs(t)do |
|
5687 o(t.jid); |
|
5688 end |
|
5689 e:event("ready"); |
|
5690 end); |
|
5691 return true; |
|
5692 end,50); |
|
5693 e:hook("presence-out",function(t) |
|
5694 t:remove_children("c",n); |
|
5695 t:reset():add_child(e:caps()):reset(); |
|
5696 end,10); |
|
5697 end |
|
5698 end) |
|
5699 package.preload['verse.plugins.version']=(function(...) |
|
5700 local _ENV=_ENV; |
|
5701 local function e(t,...) |
|
5702 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
5703 package.loaded[t]=e; |
|
5704 for t=1,select("#",...)do |
|
5705 (select(t,...))(e); |
|
5706 end |
|
5707 _ENV=e; |
|
5708 _M=e; |
|
5709 return e; |
|
5710 end |
|
5711 local o=require"verse"; |
|
5712 local a="jabber:iq:version"; |
|
5713 local function i(t,e) |
|
5714 t.name=e.name; |
|
5715 t.version=e.version; |
|
5716 t.platform=e.platform; |
|
5717 end |
|
5718 function o.plugins.version(e) |
|
5719 e.version={set=i}; |
|
5720 e:hook("iq/"..a,function(t) |
|
5721 if t.attr.type~="get"then return;end |
|
5722 local t=o.reply(t) |
|
5723 :tag("query",{xmlns=a}); |
|
5724 if e.version.name then |
|
5725 t:tag("name"):text(tostring(e.version.name)):up(); |
|
5726 end |
|
5727 if e.version.version then |
|
5728 t:tag("version"):text(tostring(e.version.version)):up() |
|
5729 end |
|
5730 if e.version.platform then |
|
5731 t:tag("os"):text(e.version.platform); |
|
5732 end |
|
5733 e:send(t); |
|
5734 return true; |
|
5735 end); |
|
5736 function e:query_version(e,t) |
|
5737 t=t or function(e)return self:event("version/response",e);end |
|
5738 self:send_iq(o.iq({type="get",to=e}) |
|
5739 :tag("query",{xmlns=a}), |
|
5740 function(o) |
|
5741 if o.attr.type=="result"then |
|
5742 local e=o:get_child("query",a); |
|
5743 local o=e and e:get_child_text("name"); |
|
5744 local a=e and e:get_child_text("version"); |
|
5745 local e=e and e:get_child_text("os"); |
|
5746 t({ |
|
5747 name=o; |
|
5748 version=a; |
|
5749 platform=e; |
|
5750 }); |
|
5751 else |
|
5752 local o,a,e=o:get_error(); |
|
5753 t({ |
|
5754 error=true; |
|
5755 condition=a; |
|
5756 text=e; |
|
5757 type=o; |
|
5758 }); |
|
5759 end |
|
5760 end); |
|
5761 end |
|
5762 return true; |
|
5763 end |
|
5764 end) |
|
5765 package.preload['verse.plugins.ping']=(function(...) |
|
5766 local _ENV=_ENV; |
|
5767 local function e(t,...) |
|
5768 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
5769 package.loaded[t]=e; |
|
5770 for t=1,select("#",...)do |
|
5771 (select(t,...))(e); |
|
5772 end |
|
5773 _ENV=e; |
|
5774 _M=e; |
|
5775 return e; |
|
5776 end |
|
5777 local a=require"verse"; |
|
5778 local n=require"socket".gettime; |
|
5779 local i="urn:xmpp:ping"; |
|
5780 function a.plugins.ping(e) |
|
5781 function e:ping(t,o) |
|
5782 local s=n(); |
|
5783 e:send_iq(a.iq{to=t,type="get"}:tag("ping",{xmlns=i}), |
|
5784 function(e) |
|
5785 if e.attr.type=="error"then |
|
5786 local a,e,i=e:get_error(); |
|
5787 if e~="service-unavailable"and e~="feature-not-implemented"then |
|
5788 o(nil,t,{type=a,condition=e,text=i}); |
|
5789 return; |
|
5790 end |
|
5791 end |
|
5792 o(n()-s,t); |
|
5793 end); |
|
5794 end |
|
5795 e:hook("iq/"..i,function(t) |
|
5796 return e:send(a.reply(t)); |
|
5797 end); |
|
5798 return true; |
|
5799 end |
|
5800 end) |
|
5801 package.preload['verse.plugins.uptime']=(function(...) |
|
5802 local _ENV=_ENV; |
|
5803 local function e(t,...) |
|
5804 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
5805 package.loaded[t]=e; |
|
5806 for t=1,select("#",...)do |
|
5807 (select(t,...))(e); |
|
5808 end |
|
5809 _ENV=e; |
|
5810 _M=e; |
|
5811 return e; |
|
5812 end |
|
5813 local o=require"verse"; |
|
5814 local t="jabber:iq:last"; |
|
5815 local function a(e,t) |
|
5816 e.starttime=t.starttime; |
|
5817 end |
|
5818 function o.plugins.uptime(e) |
|
5819 e.uptime={set=a}; |
|
5820 e:hook("iq/"..t,function(a) |
|
5821 if a.attr.type~="get"then return;end |
|
5822 local t=o.reply(a) |
|
5823 :tag("query",{seconds=tostring(os.difftime(os.time(),e.uptime.starttime)),xmlns=t}); |
|
5824 e:send(t); |
|
5825 return true; |
|
5826 end); |
|
5827 function e:query_uptime(i,a) |
|
5828 a=a or function(t)return e:event("uptime/response",t);end |
|
5829 e:send_iq(o.iq({type="get",to=i}) |
|
5830 :tag("query",{xmlns=t}), |
|
5831 function(e) |
|
5832 local t=e:get_child("query",t); |
|
5833 if e.attr.type=="result"then |
|
5834 local e=tonumber(t.attr.seconds); |
|
5835 a({ |
|
5836 seconds=e or nil; |
|
5837 }); |
|
5838 else |
|
5839 local t,e,o=e:get_error(); |
|
5840 a({ |
|
5841 error=true; |
|
5842 condition=e; |
|
5843 text=o; |
|
5844 type=t; |
|
5845 }); |
|
5846 end |
|
5847 end); |
|
5848 end |
|
5849 return true; |
|
5850 end |
|
5851 end) |
|
5852 package.preload['verse.plugins.blocking']=(function(...) |
|
5853 local _ENV=_ENV; |
|
5854 local function e(t,...) |
|
5855 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
5856 package.loaded[t]=e; |
|
5857 for t=1,select("#",...)do |
|
5858 (select(t,...))(e); |
|
5859 end |
|
5860 _ENV=e; |
|
5861 _M=e; |
|
5862 return e; |
|
5863 end |
|
5864 local a=require"verse"; |
|
5865 local o="urn:xmpp:blocking"; |
|
5866 function a.plugins.blocking(e) |
|
5867 e.blocking={}; |
|
5868 function e.blocking:block_jid(i,t) |
|
5869 e:send_iq(a.iq{type="set"} |
|
5870 :tag("block",{xmlns=o}) |
|
5871 :tag("item",{jid=i}) |
|
5872 ,function()return t and t(true);end |
|
5873 ,function()return t and t(false);end |
|
5874 ); |
|
5875 end |
|
5876 function e.blocking:unblock_jid(i,t) |
|
5877 e:send_iq(a.iq{type="set"} |
|
5878 :tag("unblock",{xmlns=o}) |
|
5879 :tag("item",{jid=i}) |
|
5880 ,function()return t and t(true);end |
|
5881 ,function()return t and t(false);end |
|
5882 ); |
|
5883 end |
|
5884 function e.blocking:unblock_all_jids(t) |
|
5885 e:send_iq(a.iq{type="set"} |
|
5886 :tag("unblock",{xmlns=o}) |
|
5887 ,function()return t and t(true);end |
|
5888 ,function()return t and t(false);end |
|
5889 ); |
|
5890 end |
|
5891 function e.blocking:get_blocked_jids(t) |
|
5892 e:send_iq(a.iq{type="get"} |
|
5893 :tag("blocklist",{xmlns=o}) |
|
5894 ,function(e) |
|
5895 local a=e:get_child("blocklist",o); |
|
5896 if not a then return t and t(false);end |
|
5897 local e={}; |
|
5898 for t in a:childtags()do |
|
5899 e[#e+1]=t.attr.jid; |
|
5900 end |
|
5901 return t and t(e); |
|
5902 end |
|
5903 ,function(e)return t and t(false);end |
|
5904 ); |
|
5905 end |
|
5906 end |
|
5907 end) |
|
5908 package.preload['verse.plugins.jingle']=(function(...) |
|
5909 local _ENV=_ENV; |
|
5910 local function e(t,...) |
|
5911 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
5912 package.loaded[t]=e; |
|
5913 for t=1,select("#",...)do |
|
5914 (select(t,...))(e); |
|
5915 end |
|
5916 _ENV=e; |
|
5917 _M=e; |
|
5918 return e; |
|
5919 end |
|
5920 local o=require"verse"; |
|
5921 local e=require"util.timer"; |
|
5922 local n=require"util.uuid".generate; |
|
5923 local i="urn:xmpp:jingle:1"; |
|
5924 local h="urn:xmpp:jingle:errors:1"; |
|
5925 local t={}; |
|
5926 t.__index=t; |
|
5927 local e={}; |
|
5928 local e={}; |
|
5929 function o.plugins.jingle(e) |
|
5930 e:hook("ready",function() |
|
5931 e:add_disco_feature(i); |
|
5932 end,10); |
|
5933 function e:jingle(a) |
|
5934 return o.eventable(setmetatable(base or{ |
|
5935 role="initiator"; |
|
5936 peer=a; |
|
5937 sid=n(); |
|
5938 stream=e; |
|
5939 },t)); |
|
5940 end |
|
5941 function e:register_jingle_transport(e) |
|
5942 end |
|
5943 function e:register_jingle_content_type(e) |
|
5944 end |
|
5945 local function u(n) |
|
5946 local d=n:get_child("jingle",i); |
|
5947 local a=d.attr.sid; |
|
5948 local s=d.attr.action; |
|
5949 local a=e:event("jingle/"..a,n); |
|
5950 if a==true then |
|
5951 e:send(o.reply(n)); |
|
5952 return true; |
|
5953 end |
|
5954 if s~="session-initiate"then |
|
5955 local t=o.error_reply(n,"cancel","item-not-found") |
|
5956 :tag("unknown-session",{xmlns=h}):up(); |
|
5957 e:send(t); |
|
5958 return; |
|
5959 end |
|
5960 local l=d.attr.sid; |
|
5961 local a=o.eventable{ |
|
5962 role="receiver"; |
|
5963 peer=n.attr.from; |
|
5964 sid=l; |
|
5965 stream=e; |
|
5966 }; |
|
5967 setmetatable(a,t); |
|
5968 local r; |
|
5969 local h,s; |
|
5970 for t in d:childtags()do |
|
5971 if t.name=="content"and t.attr.xmlns==i then |
|
5972 local o=t:child_with_name("description"); |
|
5973 local i=o.attr.xmlns; |
|
5974 if i then |
|
5975 local e=e:event("jingle/content/"..i,a,o); |
|
5976 if e then |
|
5977 h=e; |
|
5978 end |
|
5979 end |
|
5980 local o=t:child_with_name("transport"); |
|
5981 local i=o.attr.xmlns; |
|
5982 s=e:event("jingle/transport/"..i,a,o); |
|
5983 if h and s then |
|
5984 r=t; |
|
5985 break; |
|
5986 end |
|
5987 end |
|
5988 end |
|
5989 if not h then |
|
5990 e:send(o.error_reply(n,"cancel","feature-not-implemented","The specified content is not supported")); |
|
5991 return true; |
|
5992 end |
|
5993 if not s then |
|
5994 e:send(o.error_reply(n,"cancel","feature-not-implemented","The specified transport is not supported")); |
|
5995 return true; |
|
5996 end |
|
5997 e:send(o.reply(n)); |
|
5998 a.content_tag=r; |
|
5999 a.creator,a.name=r.attr.creator,r.attr.name; |
|
6000 a.content,a.transport=h,s; |
|
6001 function a:decline() |
|
6002 end |
|
6003 e:hook("jingle/"..l,function(e) |
|
6004 if e.attr.from~=a.peer then |
|
6005 return false; |
|
6006 end |
|
6007 local e=e:get_child("jingle",i); |
|
6008 return a:handle_command(e); |
|
6009 end); |
|
6010 e:event("jingle",a); |
|
6011 return true; |
|
6012 end |
|
6013 function t:handle_command(a) |
|
6014 local t=a.attr.action; |
|
6015 e:debug("Handling Jingle command: %s",t); |
|
6016 if t=="session-terminate"then |
|
6017 self:destroy(); |
|
6018 elseif t=="session-accept"then |
|
6019 self:handle_accepted(a); |
|
6020 elseif t=="transport-info"then |
|
6021 e:debug("Handling transport-info"); |
|
6022 self.transport:info_received(a); |
|
6023 elseif t=="transport-replace"then |
|
6024 e:error("Peer wanted to swap transport, not implemented"); |
|
6025 else |
|
6026 e:warn("Unhandled Jingle command: %s",t); |
|
6027 return nil; |
|
6028 end |
|
6029 return true; |
|
6030 end |
|
6031 function t:send_command(e,a,t) |
|
6032 local e=o.iq({to=self.peer,type="set"}) |
|
6033 :tag("jingle",{ |
|
6034 xmlns=i, |
|
6035 sid=self.sid, |
|
6036 action=e, |
|
6037 initiator=self.role=="initiator"and self.stream.jid or nil, |
|
6038 responder=self.role=="responder"and self.jid or nil, |
|
6039 }):add_child(a); |
|
6040 if not t then |
|
6041 self.stream:send(e); |
|
6042 else |
|
6043 self.stream:send_iq(e,t); |
|
6044 end |
|
6045 end |
|
6046 function t:accept(a) |
|
6047 local t=o.iq({to=self.peer,type="set"}) |
|
6048 :tag("jingle",{ |
|
6049 xmlns=i, |
|
6050 sid=self.sid, |
|
6051 action="session-accept", |
|
6052 responder=e.jid, |
|
6053 }) |
|
6054 :tag("content",{creator=self.creator,name=self.name}); |
|
6055 local o=self.content:generate_accept(self.content_tag:child_with_name("description"),a); |
|
6056 t:add_child(o); |
|
6057 local a=self.transport:generate_accept(self.content_tag:child_with_name("transport"),a); |
|
6058 t:add_child(a); |
|
6059 local a=self; |
|
6060 e:send_iq(t,function(t) |
|
6061 if t.attr.type=="error"then |
|
6062 local a,t,a=t:get_error(); |
|
6063 e:error("session-accept rejected: %s",t); |
|
6064 return false; |
|
6065 end |
|
6066 a.transport:connect(function(t) |
|
6067 e:warn("CONNECTED (receiver)!!!"); |
|
6068 a.state="active"; |
|
6069 a:event("connected",t); |
|
6070 end); |
|
6071 end); |
|
6072 end |
|
6073 e:hook("iq/"..i,u); |
|
6074 return true; |
|
6075 end |
|
6076 function t:offer(t,a) |
|
6077 local e=o.iq({to=self.peer,type="set"}) |
|
6078 :tag("jingle",{xmlns=i,action="session-initiate", |
|
6079 initiator=self.stream.jid,sid=self.sid}); |
|
6080 e:tag("content",{creator=self.role,name=t}); |
|
6081 local t=self.stream:event("jingle/describe/"..t,a); |
|
6082 if not t then |
|
6083 return false,"Unknown content type"; |
|
6084 end |
|
6085 e:add_child(t); |
|
6086 local t=self.stream:event("jingle/transport/".."urn:xmpp:jingle:transports:s5b:1",self); |
|
6087 self.transport=t; |
|
6088 e:add_child(t:generate_initiate()); |
|
6089 self.stream:debug("Hooking %s","jingle/"..self.sid); |
|
6090 self.stream:hook("jingle/"..self.sid,function(e) |
|
6091 if e.attr.from~=self.peer then |
|
6092 return false; |
|
6093 end |
|
6094 local e=e:get_child("jingle",i); |
|
6095 return self:handle_command(e) |
|
6096 end); |
|
6097 self.stream:send_iq(e,function(e) |
|
6098 if e.attr.type=="error"then |
|
6099 self.state="terminated"; |
|
6100 local t,a,e=e:get_error(); |
|
6101 return self:event("error",{type=t,condition=a,text=e}); |
|
6102 end |
|
6103 end); |
|
6104 self.state="pending"; |
|
6105 end |
|
6106 function t:terminate(e) |
|
6107 local e=o.stanza("reason"):tag(e or"success"); |
|
6108 self:send_command("session-terminate",e,function(e) |
|
6109 self.state="terminated"; |
|
6110 self.transport:disconnect(); |
|
6111 self:destroy(); |
|
6112 end); |
|
6113 end |
|
6114 function t:destroy() |
|
6115 self:event("terminated"); |
|
6116 self.stream:unhook("jingle/"..self.sid,self.handle_command); |
|
6117 end |
|
6118 function t:handle_accepted(e) |
|
6119 local e=e:child_with_name("transport"); |
|
6120 self.transport:handle_accepted(e); |
|
6121 self.transport:connect(function(e) |
|
6122 self.stream:debug("CONNECTED (initiator)!") |
|
6123 self.state="active"; |
|
6124 self:event("connected",e); |
|
6125 end); |
|
6126 end |
|
6127 function t:set_source(a,o) |
|
6128 local function t() |
|
6129 local e,i=a(); |
|
6130 if e and e~=""then |
|
6131 self.transport.conn:send(e); |
|
6132 elseif e==""then |
|
6133 return t(); |
|
6134 elseif e==nil then |
|
6135 if o then |
|
6136 self:terminate(); |
|
6137 end |
|
6138 self.transport.conn:unhook("drained",t); |
|
6139 a=nil; |
|
6140 end |
|
6141 end |
|
6142 self.transport.conn:hook("drained",t); |
|
6143 t(); |
|
6144 end |
|
6145 function t:set_sink(t) |
|
6146 self.transport.conn:hook("incoming-raw",t); |
|
6147 self.transport.conn:hook("disconnected",function(e) |
|
6148 self.stream:debug("Closing sink..."); |
|
6149 local e=e.reason; |
|
6150 if e=="closed"then e=nil;end |
|
6151 t(nil,e); |
|
6152 end); |
|
6153 end |
|
6154 end) |
|
6155 package.preload['verse.plugins.jingle_ft']=(function(...) |
|
6156 local _ENV=_ENV; |
|
6157 local function e(t,...) |
|
6158 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
6159 package.loaded[t]=e; |
|
6160 for t=1,select("#",...)do |
|
6161 (select(t,...))(e); |
|
6162 end |
|
6163 _ENV=e; |
|
6164 _M=e; |
|
6165 return e; |
|
6166 end |
|
6167 local i=require"verse"; |
|
6168 local o=require"ltn12"; |
|
6169 local s=package.config:sub(1,1); |
|
6170 local t="urn:xmpp:jingle:apps:file-transfer:4"; |
|
6171 function i.plugins.jingle_ft(e) |
|
6172 e:hook("ready",function() |
|
6173 e:add_disco_feature(t); |
|
6174 end,10); |
|
6175 local a={type="file"}; |
|
6176 function a:generate_accept(t,e) |
|
6177 if e and e.save_file then |
|
6178 self.jingle:hook("connected",function() |
|
6179 local e=o.sink.file(io.open(e.save_file,"w+")); |
|
6180 self.jingle:set_sink(e); |
|
6181 end); |
|
6182 end |
|
6183 return t; |
|
6184 end |
|
6185 local a={__index=a}; |
|
6186 e:hook("jingle/content/"..t,function(t,e) |
|
6187 local e=e:get_child("file"); |
|
6188 local e={ |
|
6189 name=e:get_child_text("name"); |
|
6190 size=tonumber(e:get_child_text("size")); |
|
6191 desc=e:get_child_text("desc"); |
|
6192 date=e:get_child_text("date"); |
|
6193 }; |
|
6194 return setmetatable({jingle=t,file=e},a); |
|
6195 end); |
|
6196 e:hook("jingle/describe/file",function(e) |
|
6197 local a; |
|
6198 if e.timestamp then |
|
6199 a=os.date("!%Y-%m-%dT%H:%M:%SZ",e.timestamp); |
|
6200 end |
|
6201 return i.stanza("description",{xmlns=t}) |
|
6202 :tag("file") |
|
6203 :tag("name"):text(e.filename):up() |
|
6204 :tag("size"):text(tostring(e.size)):up() |
|
6205 :tag("date"):text(a):up() |
|
6206 :tag("desc"):text(e.description):up() |
|
6207 :up(); |
|
6208 end); |
|
6209 function e:send_file(n,t) |
|
6210 local e,a=io.open(t); |
|
6211 if not e then return e,a;end |
|
6212 local i=e:seek("end",0); |
|
6213 e:seek("set",0); |
|
6214 local a=o.source.file(e); |
|
6215 local e=self:jingle(n); |
|
6216 e:offer("file",{ |
|
6217 filename=t:match("[^"..s.."]+$"); |
|
6218 size=i; |
|
6219 }); |
|
6220 e:hook("connected",function() |
|
6221 e:set_source(a,true); |
|
6222 end); |
|
6223 return e; |
|
6224 end |
|
6225 end |
|
6226 end) |
|
6227 package.preload['verse.plugins.jingle_s5b']=(function(...) |
|
6228 local _ENV=_ENV; |
|
6229 local function e(t,...) |
|
6230 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
6231 package.loaded[t]=e; |
|
6232 for t=1,select("#",...)do |
|
6233 (select(t,...))(e); |
|
6234 end |
|
6235 _ENV=e; |
|
6236 _M=e; |
|
6237 return e; |
|
6238 end |
|
6239 local a=require"verse"; |
|
6240 local o="urn:xmpp:jingle:transports:s5b:1"; |
|
6241 local r="http://jabber.org/protocol/bytestreams"; |
|
6242 local h=require"util.hashes".sha1; |
|
6243 local s=require"util.uuid".generate; |
|
6244 local function d(e,n) |
|
6245 local function i() |
|
6246 e:unhook("connected",i); |
|
6247 return true; |
|
6248 end |
|
6249 local function o(t) |
|
6250 e:unhook("incoming-raw",o); |
|
6251 if t:sub(1,2)~="\005\000"then |
|
6252 return e:event("error","connection-failure"); |
|
6253 end |
|
6254 e:event("connected"); |
|
6255 return true; |
|
6256 end |
|
6257 local function a(t) |
|
6258 e:unhook("incoming-raw",a); |
|
6259 if t~="\005\000"then |
|
6260 local a="version-mismatch"; |
|
6261 if t:sub(1,1)=="\005"then |
|
6262 a="authentication-failure"; |
|
6263 end |
|
6264 return e:event("error",a); |
|
6265 end |
|
6266 e:send(string.char(5,1,0,3,#n)..n.."\0\0"); |
|
6267 e:hook("incoming-raw",o,100); |
|
6268 return true; |
|
6269 end |
|
6270 e:hook("connected",i,200); |
|
6271 e:hook("incoming-raw",a,100); |
|
6272 e:send("\005\001\000"); |
|
6273 end |
|
6274 local function n(o,e,i) |
|
6275 local e=a.new(nil,{ |
|
6276 streamhosts=e, |
|
6277 current_host=0; |
|
6278 }); |
|
6279 local function t(a) |
|
6280 if a then |
|
6281 return o(nil,a.reason); |
|
6282 end |
|
6283 if e.current_host<#e.streamhosts then |
|
6284 e.current_host=e.current_host+1; |
|
6285 e:debug("Attempting to connect to "..e.streamhosts[e.current_host].host..":"..e.streamhosts[e.current_host].port.."..."); |
|
6286 local a,t=e:connect( |
|
6287 e.streamhosts[e.current_host].host, |
|
6288 e.streamhosts[e.current_host].port |
|
6289 ); |
|
6290 if not a then |
|
6291 e:debug("Error connecting to proxy (%s:%s): %s", |
|
6292 e.streamhosts[e.current_host].host, |
|
6293 e.streamhosts[e.current_host].port, |
|
6294 t |
|
6295 ); |
|
6296 else |
|
6297 e:debug("Connecting..."); |
|
6298 end |
|
6299 d(e,i); |
|
6300 return true; |
|
6301 end |
|
6302 e:unhook("disconnected",t); |
|
6303 return o(nil); |
|
6304 end |
|
6305 e:hook("disconnected",t,100); |
|
6306 e:hook("connected",function() |
|
6307 e:unhook("disconnected",t); |
|
6308 o(e.streamhosts[e.current_host],e); |
|
6309 end,100); |
|
6310 t(); |
|
6311 return e; |
|
6312 end |
|
6313 function a.plugins.jingle_s5b(e) |
|
6314 e:hook("ready",function() |
|
6315 e:add_disco_feature(o); |
|
6316 end,10); |
|
6317 local t={}; |
|
6318 function t:generate_initiate() |
|
6319 self.s5b_sid=s(); |
|
6320 local i=a.stanza("transport",{xmlns=o, |
|
6321 mode="tcp",sid=self.s5b_sid}); |
|
6322 local t=0; |
|
6323 for a,o in pairs(e.proxy65.available_streamhosts)do |
|
6324 t=t+1; |
|
6325 i:tag("candidate",{jid=a,host=o.host, |
|
6326 port=o.port,cid=a,priority=t,type="proxy"}):up(); |
|
6327 end |
|
6328 e:debug("Have %d proxies",t) |
|
6329 return i; |
|
6330 end |
|
6331 function t:generate_accept(e) |
|
6332 local t={}; |
|
6333 self.s5b_peer_candidates=t; |
|
6334 self.s5b_mode=e.attr.mode or"tcp"; |
|
6335 self.s5b_sid=e.attr.sid or self.jingle.sid; |
|
6336 for e in e:childtags()do |
|
6337 t[e.attr.cid]={ |
|
6338 type=e.attr.type; |
|
6339 jid=e.attr.jid; |
|
6340 host=e.attr.host; |
|
6341 port=tonumber(e.attr.port)or 0; |
|
6342 priority=tonumber(e.attr.priority)or 0; |
|
6343 cid=e.attr.cid; |
|
6344 }; |
|
6345 end |
|
6346 local e=a.stanza("transport",{xmlns=o}); |
|
6347 return e; |
|
6348 end |
|
6349 function t:connect(i) |
|
6350 e:warn("Connecting!"); |
|
6351 local t={}; |
|
6352 for a,e in pairs(self.s5b_peer_candidates or{})do |
|
6353 t[#t+1]=e; |
|
6354 end |
|
6355 if#t>0 then |
|
6356 self.connecting_peer_candidates=true; |
|
6357 local function s(e,t) |
|
6358 self.jingle:send_command("transport-info",a.stanza("content",{creator=self.creator,name=self.name}) |
|
6359 :tag("transport",{xmlns=o,sid=self.s5b_sid}) |
|
6360 :tag("candidate-used",{cid=e.cid})); |
|
6361 self.onconnect_callback=i; |
|
6362 self.conn=t; |
|
6363 end |
|
6364 local e=h(self.s5b_sid..self.peer..e.jid,true); |
|
6365 n(s,t,e); |
|
6366 else |
|
6367 e:warn("Actually, I'm going to wait for my peer to tell me its streamhost..."); |
|
6368 self.onconnect_callback=i; |
|
6369 end |
|
6370 end |
|
6371 function t:info_received(t) |
|
6372 e:warn("Info received"); |
|
6373 local s=t:child_with_name("content"); |
|
6374 local i=s:child_with_name("transport"); |
|
6375 if i:get_child("candidate-used")and not self.connecting_peer_candidates then |
|
6376 local t=i:child_with_name("candidate-used"); |
|
6377 if t then |
|
6378 local function i(i,e) |
|
6379 if self.jingle.role=="initiator"then |
|
6380 self.jingle.stream:send_iq(a.iq({to=i.jid,type="set"}) |
|
6381 :tag("query",{xmlns=r,sid=self.s5b_sid}) |
|
6382 :tag("activate"):text(self.jingle.peer),function(i) |
|
6383 if i.attr.type=="result"then |
|
6384 self.jingle:send_command("transport-info",a.stanza("content",s.attr) |
|
6385 :tag("transport",{xmlns=o,sid=self.s5b_sid}) |
|
6386 :tag("activated",{cid=t.attr.cid})); |
|
6387 self.conn=e; |
|
6388 self.onconnect_callback(e); |
|
6389 else |
|
6390 self.jingle.stream:error("Failed to activate bytestream"); |
|
6391 end |
|
6392 end); |
|
6393 end |
|
6394 end |
|
6395 self.jingle.stream:debug("CID: %s",self.jingle.stream.proxy65.available_streamhosts[t.attr.cid]); |
|
6396 local t={ |
|
6397 self.jingle.stream.proxy65.available_streamhosts[t.attr.cid]; |
|
6398 }; |
|
6399 local e=h(self.s5b_sid..e.jid..self.peer,true); |
|
6400 n(i,t,e); |
|
6401 end |
|
6402 elseif i:get_child("activated")then |
|
6403 self.onconnect_callback(self.conn); |
|
6404 end |
|
6405 end |
|
6406 function t:disconnect() |
|
6407 if self.conn then |
|
6408 self.conn:close(); |
|
6409 end |
|
6410 end |
|
6411 function t:handle_accepted(e) |
|
6412 end |
|
6413 local t={__index=t}; |
|
6414 e:hook("jingle/transport/"..o,function(e) |
|
6415 return setmetatable({ |
|
6416 role=e.role, |
|
6417 peer=e.peer, |
|
6418 stream=e.stream, |
|
6419 jingle=e, |
|
6420 },t); |
|
6421 end); |
|
6422 end |
|
6423 end) |
|
6424 package.preload['verse.plugins.proxy65']=(function(...) |
|
6425 local _ENV=_ENV; |
|
6426 local function e(t,...) |
|
6427 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
6428 package.loaded[t]=e; |
|
6429 for t=1,select("#",...)do |
|
6430 (select(t,...))(e); |
|
6431 end |
|
6432 _ENV=e; |
|
6433 _M=e; |
|
6434 return e; |
|
6435 end |
|
6436 local a=require"verse"; |
|
6437 local r=require"util.uuid"; |
|
6438 local d=require"util.hashes".sha1; |
|
6439 local n={}; |
|
6440 n.__index=n; |
|
6441 local i="http://jabber.org/protocol/bytestreams"; |
|
6442 local s; |
|
6443 function a.plugins.proxy65(t) |
|
6444 t.proxy65=setmetatable({stream=t},n); |
|
6445 t.proxy65.available_streamhosts={}; |
|
6446 local e=0; |
|
6447 t:hook("disco/service-discovered/proxy",function(o) |
|
6448 if o.type=="bytestreams"then |
|
6449 e=e+1; |
|
6450 t:send_iq(a.iq({to=o.jid,type="get"}) |
|
6451 :tag("query",{xmlns=i}),function(a) |
|
6452 e=e-1; |
|
6453 if a.attr.type=="result"then |
|
6454 local e=a:get_child("query",i) |
|
6455 :get_child("streamhost").attr; |
|
6456 t.proxy65.available_streamhosts[e.jid]={ |
|
6457 jid=e.jid; |
|
6458 host=e.host; |
|
6459 port=tonumber(e.port); |
|
6460 }; |
|
6461 end |
|
6462 if e==0 then |
|
6463 t:event("proxy65/discovered-proxies",t.proxy65.available_streamhosts); |
|
6464 end |
|
6465 end); |
|
6466 end |
|
6467 end); |
|
6468 t:hook("iq/"..i,function(o) |
|
6469 local e=a.new(nil,{ |
|
6470 initiator_jid=o.attr.from, |
|
6471 streamhosts={}, |
|
6472 current_host=0; |
|
6473 }); |
|
6474 for t in o.tags[1]:childtags()do |
|
6475 if t.name=="streamhost"then |
|
6476 table.insert(e.streamhosts,t.attr); |
|
6477 end |
|
6478 end |
|
6479 local function i() |
|
6480 if e.current_host<#e.streamhosts then |
|
6481 e.current_host=e.current_host+1; |
|
6482 e:connect( |
|
6483 e.streamhosts[e.current_host].host, |
|
6484 e.streamhosts[e.current_host].port |
|
6485 ); |
|
6486 s(t,e,o.tags[1].attr.sid,o.attr.from,t.jid); |
|
6487 return true; |
|
6488 end |
|
6489 e:unhook("disconnected",i); |
|
6490 t:send(a.error_reply(o,"cancel","item-not-found")); |
|
6491 end |
|
6492 function e:accept() |
|
6493 e:hook("disconnected",i,100); |
|
6494 e:hook("connected",function() |
|
6495 e:unhook("disconnected",i); |
|
6496 local e=a.reply(o) |
|
6497 :tag("query",o.tags[1].attr) |
|
6498 :tag("streamhost-used",{jid=e.streamhosts[e.current_host].jid}); |
|
6499 t:send(e); |
|
6500 end,100); |
|
6501 i(); |
|
6502 end |
|
6503 function e:refuse() |
|
6504 end |
|
6505 t:event("proxy65/request",e); |
|
6506 end); |
|
6507 end |
|
6508 function n:new(t,h) |
|
6509 local e=a.new(nil,{ |
|
6510 target_jid=t; |
|
6511 bytestream_sid=r.generate(); |
|
6512 }); |
|
6513 local o=a.iq{type="set",to=t} |
|
6514 :tag("query",{xmlns=i,mode="tcp",sid=e.bytestream_sid}); |
|
6515 for t,e in ipairs(h or self.proxies)do |
|
6516 o:tag("streamhost",e):up(); |
|
6517 end |
|
6518 self.stream:send_iq(o,function(o) |
|
6519 if o.attr.type=="error"then |
|
6520 local t,o,a=o:get_error(); |
|
6521 e:event("connection-failed",{conn=e,type=t,condition=o,text=a}); |
|
6522 else |
|
6523 local o=o.tags[1]:get_child("streamhost-used"); |
|
6524 e.streamhost_jid=o.attr.jid; |
|
6525 local o,n; |
|
6526 for a,t in ipairs(h or self.proxies)do |
|
6527 if t.jid==e.streamhost_jid then |
|
6528 o,n=t.host,t.port; |
|
6529 break; |
|
6530 end |
|
6531 end |
|
6532 e:connect(o,n); |
|
6533 local function o() |
|
6534 e:unhook("connected",o); |
|
6535 local t=a.iq{to=e.streamhost_jid,type="set"} |
|
6536 :tag("query",{xmlns=i,sid=e.bytestream_sid}) |
|
6537 :tag("activate"):text(t); |
|
6538 self.stream:send_iq(t,function(t) |
|
6539 if t.attr.type=="result"then |
|
6540 e:event("connected",e); |
|
6541 end |
|
6542 end); |
|
6543 return true; |
|
6544 end |
|
6545 e:hook("connected",o,100); |
|
6546 s(self.stream,e,e.bytestream_sid,self.stream.jid,t); |
|
6547 end |
|
6548 end); |
|
6549 return e; |
|
6550 end |
|
6551 function s(i,e,a,t,o) |
|
6552 local t=d(a..t..o); |
|
6553 local function a() |
|
6554 e:unhook("connected",a); |
|
6555 return true; |
|
6556 end |
|
6557 local function o(t) |
|
6558 e:unhook("incoming-raw",o); |
|
6559 if t:sub(1,2)~="\005\000"then |
|
6560 return e:event("error","connection-failure"); |
|
6561 end |
|
6562 e:event("connected"); |
|
6563 return true; |
|
6564 end |
|
6565 local function i(a) |
|
6566 e:unhook("incoming-raw",i); |
|
6567 if a~="\005\000"then |
|
6568 local t="version-mismatch"; |
|
6569 if a:sub(1,1)=="\005"then |
|
6570 t="authentication-failure"; |
|
6571 end |
|
6572 return e:event("error",t); |
|
6573 end |
|
6574 e:send(string.char(5,1,0,3,#t)..t.."\0\0"); |
|
6575 e:hook("incoming-raw",o,100); |
|
6576 return true; |
|
6577 end |
|
6578 e:hook("connected",a,200); |
|
6579 e:hook("incoming-raw",i,100); |
|
6580 e:send("\005\001\000"); |
|
6581 end |
|
6582 end) |
|
6583 package.preload['verse.plugins.jingle_ibb']=(function(...) |
|
6584 local _ENV=_ENV; |
|
6585 local function e(t,...) |
|
6586 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
6587 package.loaded[t]=e; |
|
6588 for t=1,select("#",...)do |
|
6589 (select(t,...))(e); |
|
6590 end |
|
6591 _ENV=e; |
|
6592 _M=e; |
|
6593 return e; |
|
6594 end |
|
6595 local e=require"verse"; |
|
6596 local i=require"util.encodings".base64; |
|
6597 local s=require"util.uuid".generate; |
|
6598 local n="urn:xmpp:jingle:transports:ibb:1"; |
|
6599 local o="http://jabber.org/protocol/ibb"; |
|
6600 assert(i.encode("This is a test.")=="VGhpcyBpcyBhIHRlc3Qu","Base64 encoding failed"); |
|
6601 assert(i.decode("VGhpcyBpcyBhIHRlc3Qu")=="This is a test.","Base64 decoding failed"); |
|
6602 local t=table.concat |
|
6603 local a={}; |
|
6604 local t={__index=a}; |
|
6605 local function h(a) |
|
6606 local t=setmetatable({stream=a},t) |
|
6607 t=e.eventable(t); |
|
6608 return t; |
|
6609 end |
|
6610 function a:initiate(t,e,a) |
|
6611 self.block=2048; |
|
6612 self.stanza=a or'iq'; |
|
6613 self.peer=t; |
|
6614 self.sid=e or tostring(self):match("%x+$"); |
|
6615 self.iseq=0; |
|
6616 self.oseq=0; |
|
6617 local e=function(e) |
|
6618 return self:feed(e) |
|
6619 end |
|
6620 self.feeder=e; |
|
6621 print("Hooking incoming IQs"); |
|
6622 local t=self.stream; |
|
6623 t:hook("iq/"..o,e) |
|
6624 if a=="message"then |
|
6625 t:hook("message",e) |
|
6626 end |
|
6627 end |
|
6628 function a:open(t) |
|
6629 self.stream:send_iq(e.iq{to=self.peer,type="set"} |
|
6630 :tag("open",{ |
|
6631 xmlns=o, |
|
6632 ["block-size"]=self.block, |
|
6633 sid=self.sid, |
|
6634 stanza=self.stanza |
|
6635 }) |
|
6636 ,function(e) |
|
6637 if t then |
|
6638 if e.attr.type~="error"then |
|
6639 t(true) |
|
6640 else |
|
6641 t(false,e:get_error()) |
|
6642 end |
|
6643 end |
|
6644 end); |
|
6645 end |
|
6646 function a:send(n) |
|
6647 local a=self.stanza; |
|
6648 local t; |
|
6649 if a=="iq"then |
|
6650 t=e.iq{type="set",to=self.peer} |
|
6651 elseif a=="message"then |
|
6652 t=e.message{to=self.peer} |
|
6653 end |
|
6654 local e=self.oseq; |
|
6655 self.oseq=e+1; |
|
6656 t:tag("data",{xmlns=o,sid=self.sid,seq=e}) |
|
6657 :text(i.encode(n)); |
|
6658 if a=="iq"then |
|
6659 self.stream:send_iq(t,function(e) |
|
6660 self:event(e.attr.type=="result"and"drained"or"error"); |
|
6661 end) |
|
6662 else |
|
6663 stream:send(t) |
|
6664 self:event("drained"); |
|
6665 end |
|
6666 end |
|
6667 function a:feed(t) |
|
6668 if t.attr.from~=self.peer then return end |
|
6669 local a=t[1]; |
|
6670 if a.attr.sid~=self.sid then return end |
|
6671 local n; |
|
6672 if a.name=="open"then |
|
6673 self:event("connected"); |
|
6674 self.stream:send(e.reply(t)) |
|
6675 return true |
|
6676 elseif a.name=="data"then |
|
6677 local o=t:get_child_text("data",o); |
|
6678 local a=tonumber(a.attr.seq); |
|
6679 local n=self.iseq; |
|
6680 if o and a then |
|
6681 if a~=n then |
|
6682 self.stream:send(e.error_reply(t,"cancel","not-acceptable","Wrong sequence. Packet lost?")) |
|
6683 self:close(); |
|
6684 self:event("error"); |
|
6685 return true; |
|
6686 end |
|
6687 self.iseq=a+1; |
|
6688 local a=i.decode(o); |
|
6689 if self.stanza=="iq"then |
|
6690 self.stream:send(e.reply(t)) |
|
6691 end |
|
6692 self:event("incoming-raw",a); |
|
6693 return true; |
|
6694 end |
|
6695 elseif a.name=="close"then |
|
6696 self.stream:send(e.reply(t)) |
|
6697 self:close(); |
|
6698 return true |
|
6699 end |
|
6700 end |
|
6701 function a:close() |
|
6702 self.stream:unhook("iq/"..o,self.feeder) |
|
6703 self:event("disconnected"); |
|
6704 end |
|
6705 function e.plugins.jingle_ibb(a) |
|
6706 a:hook("ready",function() |
|
6707 a:add_disco_feature(n); |
|
6708 end,10); |
|
6709 local t={}; |
|
6710 function t:_setup() |
|
6711 local e=h(self.stream); |
|
6712 e.sid=self.sid or e.sid; |
|
6713 e.stanza=self.stanza or e.stanza; |
|
6714 e.block=self.block or e.block; |
|
6715 e:initiate(self.peer,self.sid,self.stanza); |
|
6716 self.conn=e; |
|
6717 end |
|
6718 function t:generate_initiate() |
|
6719 print("ibb:generate_initiate() as "..self.role); |
|
6720 local t=s(); |
|
6721 self.sid=t; |
|
6722 self.stanza='iq'; |
|
6723 self.block=2048; |
|
6724 local e=e.stanza("transport",{xmlns=n, |
|
6725 sid=self.sid,stanza=self.stanza,["block-size"]=self.block}); |
|
6726 return e; |
|
6727 end |
|
6728 function t:generate_accept(t) |
|
6729 print("ibb:generate_accept() as "..self.role); |
|
6730 local e=t.attr; |
|
6731 self.sid=e.sid or self.sid; |
|
6732 self.stanza=e.stanza or self.stanza; |
|
6733 self.block=e["block-size"]or self.block; |
|
6734 self:_setup(); |
|
6735 return t; |
|
6736 end |
|
6737 function t:connect(t) |
|
6738 if not self.conn then |
|
6739 self:_setup(); |
|
6740 end |
|
6741 local e=self.conn; |
|
6742 print("ibb:connect() as "..self.role); |
|
6743 if self.role=="initiator"then |
|
6744 e:open(function(a,...) |
|
6745 assert(a,table.concat({...},", ")); |
|
6746 t(e); |
|
6747 end); |
|
6748 else |
|
6749 t(e); |
|
6750 end |
|
6751 end |
|
6752 function t:info_received(e) |
|
6753 print("ibb:info_received()"); |
|
6754 end |
|
6755 function t:disconnect() |
|
6756 if self.conn then |
|
6757 self.conn:close() |
|
6758 end |
|
6759 end |
|
6760 function t:handle_accepted(e)end |
|
6761 local t={__index=t}; |
|
6762 a:hook("jingle/transport/"..n,function(e) |
|
6763 return setmetatable({ |
|
6764 role=e.role, |
|
6765 peer=e.peer, |
|
6766 stream=e.stream, |
|
6767 jingle=e, |
|
6768 },t); |
|
6769 end); |
|
6770 end |
|
6771 end) |
|
6772 package.preload['verse.plugins.pubsub']=(function(...) |
|
6773 local _ENV=_ENV; |
|
6774 local function e(t,...) |
|
6775 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
6776 package.loaded[t]=e; |
|
6777 for t=1,select("#",...)do |
|
6778 (select(t,...))(e); |
|
6779 end |
|
6780 _ENV=e; |
|
6781 _M=e; |
|
6782 return e; |
|
6783 end |
|
6784 local o=require"verse"; |
|
6785 local s=table.insert; |
|
6786 local i="http://jabber.org/protocol/pubsub"; |
|
6787 local h="http://jabber.org/protocol/pubsub#owner"; |
|
6788 local r="http://jabber.org/protocol/pubsub#event"; |
|
6789 local e={}; |
|
6790 local n={__index=e}; |
|
6791 function o.plugins.pubsub(e) |
|
6792 e.pubsub=setmetatable({stream=e},n); |
|
6793 e:hook("message",function(t) |
|
6794 local a=t.attr.from; |
|
6795 for t in t:childtags("event",r)do |
|
6796 local t=t:get_child("items"); |
|
6797 if t then |
|
6798 local o=t.attr.node; |
|
6799 for t in t:childtags("item")do |
|
6800 e:event("pubsub/event",{ |
|
6801 from=a; |
|
6802 node=o; |
|
6803 item=t; |
|
6804 }); |
|
6805 end |
|
6806 end |
|
6807 end |
|
6808 end); |
|
6809 return true; |
|
6810 end |
|
6811 function e:create(e,t,a) |
|
6812 return self:service(e):node(t):create(nil,a); |
|
6813 end |
|
6814 function e:subscribe(a,o,t,e) |
|
6815 return self:service(a):node(o):subscribe(t,nil,e); |
|
6816 end |
|
6817 function e:publish(i,o,a,t,e) |
|
6818 return self:service(i):node(o):publish(a,nil,t,e); |
|
6819 end |
|
6820 local a={}; |
|
6821 local t={__index=a}; |
|
6822 function e:service(e) |
|
6823 return setmetatable({stream=self.stream,service=e},t) |
|
6824 end |
|
6825 local function t(t,n,s,a,r,h,e) |
|
6826 local t=o.iq{type=t or"get",to=n} |
|
6827 :tag("pubsub",{xmlns=s or i}) |
|
6828 if a then t:tag(a,{node=r,jid=h});end |
|
6829 if e then t:tag("item",{id=e~=true and e or nil});end |
|
6830 return t; |
|
6831 end |
|
6832 function a:subscriptions(o) |
|
6833 self.stream:send_iq(t(nil,self.service,nil,"subscriptions") |
|
6834 ,o and function(a) |
|
6835 if a.attr.type=="result"then |
|
6836 local e=a:get_child("pubsub",i); |
|
6837 local e=e and e:get_child("subscriptions"); |
|
6838 local a={}; |
|
6839 if e then |
|
6840 for t in e:childtags("subscription")do |
|
6841 local e=self:node(t.attr.node) |
|
6842 e.subscription=t; |
|
6843 e.subscribed_jid=t.attr.jid; |
|
6844 s(a,e); |
|
6845 end |
|
6846 end |
|
6847 o(a); |
|
6848 else |
|
6849 o(false,a:get_error()); |
|
6850 end |
|
6851 end or nil); |
|
6852 end |
|
6853 function a:affiliations(e) |
|
6854 self.stream:send_iq(t(nil,self.service,nil,"affiliations") |
|
6855 ,e and function(t) |
|
6856 if t.attr.type=="result"then |
|
6857 local t=t:get_child("pubsub",i); |
|
6858 local a=t and t:get_child("affiliations")or{}; |
|
6859 local t={}; |
|
6860 if a then |
|
6861 for a in a:childtags("affiliation")do |
|
6862 local e=self:node(a.attr.node) |
|
6863 e.affiliation=a; |
|
6864 s(t,e); |
|
6865 end |
|
6866 end |
|
6867 e(t); |
|
6868 else |
|
6869 e(false,t:get_error()); |
|
6870 end |
|
6871 end or nil); |
|
6872 end |
|
6873 function a:nodes(a) |
|
6874 self.stream:disco_items(self.service,nil,function(e,...) |
|
6875 if e then |
|
6876 for t=1,#e do |
|
6877 e[t]=self:node(e[t].node); |
|
6878 end |
|
6879 end |
|
6880 a(e,...) |
|
6881 end); |
|
6882 end |
|
6883 local e={}; |
|
6884 local o={__index=e}; |
|
6885 function a:node(e) |
|
6886 return setmetatable({stream=self.stream,service=self.service,node=e},o) |
|
6887 end |
|
6888 function n:__call(t,e) |
|
6889 local t=self:service(t); |
|
6890 return e and t:node(e)or t; |
|
6891 end |
|
6892 function e:hook(a,o) |
|
6893 self._hooks=self._hooks or setmetatable({},{__mode='kv'}); |
|
6894 local function t(e) |
|
6895 if(not e.service or e.from==self.service)and e.node==self.node then |
|
6896 return a(e) |
|
6897 end |
|
6898 end |
|
6899 self._hooks[a]=t; |
|
6900 self.stream:hook("pubsub/event",t,o); |
|
6901 return t; |
|
6902 end |
|
6903 function e:unhook(e) |
|
6904 if e then |
|
6905 local e=self._hooks[e]; |
|
6906 self.stream:unhook("pubsub/event",e); |
|
6907 elseif self._hooks then |
|
6908 for e in pairs(self._hooks)do |
|
6909 self.stream:unhook("pubsub/event",e); |
|
6910 end |
|
6911 end |
|
6912 end |
|
6913 function e:create(a,e) |
|
6914 if a~=nil then |
|
6915 error("Not implemented yet."); |
|
6916 else |
|
6917 self.stream:send_iq(t("set",self.service,nil,"create",self.node),e); |
|
6918 end |
|
6919 end |
|
6920 function e:configure(e,a) |
|
6921 if e~=nil then |
|
6922 error("Not implemented yet."); |
|
6923 end |
|
6924 self.stream:send_iq(t("set",self.service,nil,e==nil and"default"or"configure",self.node),a); |
|
6925 end |
|
6926 function e:publish(i,a,o,e) |
|
6927 if a~=nil then |
|
6928 error("Node configuration is not implemented yet."); |
|
6929 end |
|
6930 self.stream:send_iq(t("set",self.service,nil,"publish",self.node,nil,i or true) |
|
6931 :add_child(o) |
|
6932 ,e); |
|
6933 end |
|
6934 function e:subscribe(e,a,o) |
|
6935 e=e or self.stream.jid; |
|
6936 if a~=nil then |
|
6937 error("Subscription configuration is not implemented yet."); |
|
6938 end |
|
6939 self.stream:send_iq(t("set",self.service,nil,"subscribe",self.node,e) |
|
6940 ,o); |
|
6941 end |
|
6942 function e:subscription(e) |
|
6943 error("Not implemented yet."); |
|
6944 end |
|
6945 function e:affiliation(e) |
|
6946 error("Not implemented yet."); |
|
6947 end |
|
6948 function e:unsubscribe(e,a) |
|
6949 e=e or self.subscribed_jid or self.stream.jid; |
|
6950 self.stream:send_iq(t("set",self.service,nil,"unsubscribe",self.node,e) |
|
6951 ,a); |
|
6952 end |
|
6953 function e:configure_subscription(e,e) |
|
6954 error("Not implemented yet."); |
|
6955 end |
|
6956 function e:items(a,e) |
|
6957 if a then |
|
6958 self.stream:send_iq(t("get",self.service,nil,"items",self.node) |
|
6959 ,e); |
|
6960 else |
|
6961 self.stream:disco_items(self.service,self.node,e); |
|
6962 end |
|
6963 end |
|
6964 function e:item(e,a) |
|
6965 self.stream:send_iq(t("get",self.service,nil,"items",self.node,nil,e) |
|
6966 ,a); |
|
6967 end |
|
6968 function e:retract(e,a) |
|
6969 self.stream:send_iq(t("set",self.service,nil,"retract",self.node,nil,e) |
|
6970 ,a); |
|
6971 end |
|
6972 function e:purge(a,e) |
|
6973 assert(not a,"Not implemented yet."); |
|
6974 self.stream:send_iq(t("set",self.service,h,"purge",self.node) |
|
6975 ,e); |
|
6976 end |
|
6977 function e:delete(a,e) |
|
6978 assert(not a,"Not implemented yet."); |
|
6979 self.stream:send_iq(t("set",self.service,h,"delete",self.node) |
|
6980 ,e); |
|
6981 end |
|
6982 end) |
|
6983 package.preload['verse.plugins.pep']=(function(...) |
|
6984 local _ENV=_ENV; |
|
6985 local function e(t,...) |
|
6986 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
6987 package.loaded[t]=e; |
|
6988 for t=1,select("#",...)do |
|
6989 (select(t,...))(e); |
|
6990 end |
|
6991 _ENV=e; |
|
6992 _M=e; |
|
6993 return e; |
|
6994 end |
|
6995 local e=require"verse"; |
|
6996 local t="http://jabber.org/protocol/pubsub"; |
|
6997 local t=t.."#event"; |
|
6998 function e.plugins.pep(e) |
|
6999 e:add_plugin("disco"); |
|
7000 e:add_plugin("pubsub"); |
|
7001 e.pep={}; |
|
7002 e:hook("pubsub/event",function(t) |
|
7003 return e:event("pep/"..t.node,{from=t.from,item=t.item.tags[1]}); |
|
7004 end); |
|
7005 function e:hook_pep(t,o,i) |
|
7006 local a=e.events._handlers["pep/"..t]; |
|
7007 if not(a)or#a==0 then |
|
7008 e:add_disco_feature(t.."+notify"); |
|
7009 end |
|
7010 e:hook("pep/"..t,o,i); |
|
7011 end |
|
7012 function e:unhook_pep(t,a) |
|
7013 e:unhook("pep/"..t,a); |
|
7014 local a=e.events._handlers["pep/"..t]; |
|
7015 if not(a)or#a==0 then |
|
7016 e:remove_disco_feature(t.."+notify"); |
|
7017 end |
|
7018 end |
|
7019 function e:publish_pep(t,a,o) |
|
7020 return e.pubsub:service(nil):node(a or t.attr.xmlns):publish(o or"current",nil,t) |
|
7021 end |
|
7022 end |
|
7023 end) |
|
7024 package.preload['verse.plugins.adhoc']=(function(...) |
|
7025 local _ENV=_ENV; |
|
7026 local function e(t,...) |
|
7027 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
7028 package.loaded[t]=e; |
|
7029 for t=1,select("#",...)do |
|
7030 (select(t,...))(e); |
|
7031 end |
|
7032 _ENV=e; |
|
7033 _M=e; |
|
7034 return e; |
|
7035 end |
|
7036 local o=require"verse"; |
|
7037 local n=require"lib.adhoc"; |
|
7038 local t="http://jabber.org/protocol/commands"; |
|
7039 local s="jabber:x:data"; |
|
7040 local a={}; |
|
7041 a.__index=a; |
|
7042 local i={}; |
|
7043 function o.plugins.adhoc(e) |
|
7044 e:add_plugin("disco"); |
|
7045 e:add_disco_feature(t); |
|
7046 function e:query_commands(a,o) |
|
7047 e:disco_items(a,t,function(a) |
|
7048 e:debug("adhoc list returned") |
|
7049 local t={}; |
|
7050 for o,a in ipairs(a)do |
|
7051 t[a.node]=a.name; |
|
7052 end |
|
7053 e:debug("adhoc calling callback") |
|
7054 return o(t); |
|
7055 end); |
|
7056 end |
|
7057 function e:execute_command(t,o,i) |
|
7058 local e=setmetatable({ |
|
7059 stream=e,jid=t, |
|
7060 command=o,callback=i |
|
7061 },a); |
|
7062 return e:execute(); |
|
7063 end |
|
7064 local function r(t,e) |
|
7065 if not(e)or e=="user"then return true;end |
|
7066 if type(e)=="function"then |
|
7067 return e(t); |
|
7068 end |
|
7069 end |
|
7070 function e:add_adhoc_command(o,a,s,h) |
|
7071 i[a]=n.new(o,a,s,h); |
|
7072 e:add_disco_item({jid=e.jid,node=a,name=o},t); |
|
7073 return i[a]; |
|
7074 end |
|
7075 local function s(a) |
|
7076 local t=a.tags[1]; |
|
7077 local t=t.attr.node; |
|
7078 local t=i[t]; |
|
7079 if not t then return;end |
|
7080 if not r(a.attr.from,t.permission)then |
|
7081 e:send(o.error_reply(a,"auth","forbidden","You don't have permission to execute this command"):up() |
|
7082 :add_child(t:cmdtag("canceled") |
|
7083 :tag("note",{type="error"}):text("You don't have permission to execute this command"))); |
|
7084 return true |
|
7085 end |
|
7086 return n.handle_cmd(t,{send=function(t)return e:send(t)end},a); |
|
7087 end |
|
7088 e:hook("iq/"..t,function(e) |
|
7089 local a=e.attr.type; |
|
7090 local t=e.tags[1].name; |
|
7091 if a=="set"and t=="command"then |
|
7092 return s(e); |
|
7093 end |
|
7094 end); |
|
7095 end |
|
7096 function a:_process_response(e) |
|
7097 if e.attr.type=="error"then |
|
7098 self.status="canceled"; |
|
7099 self.callback(self,{}); |
|
7100 return; |
|
7101 end |
|
7102 local e=e:get_child("command",t); |
|
7103 self.status=e.attr.status; |
|
7104 self.sessionid=e.attr.sessionid; |
|
7105 self.form=e:get_child("x",s); |
|
7106 self.note=e:get_child("note"); |
|
7107 self.callback(self); |
|
7108 end |
|
7109 function a:execute() |
|
7110 local e=o.iq({to=self.jid,type="set"}) |
|
7111 :tag("command",{xmlns=t,node=self.command}); |
|
7112 self.stream:send_iq(e,function(e) |
|
7113 self:_process_response(e); |
|
7114 end); |
|
7115 end |
|
7116 function a:next(a) |
|
7117 local e=o.iq({to=self.jid,type="set"}) |
|
7118 :tag("command",{ |
|
7119 xmlns=t, |
|
7120 node=self.command, |
|
7121 sessionid=self.sessionid |
|
7122 }); |
|
7123 if a then e:add_child(a);end |
|
7124 self.stream:send_iq(e,function(e) |
|
7125 self:_process_response(e); |
|
7126 end); |
|
7127 end |
|
7128 end) |
|
7129 package.preload['verse.plugins.presence']=(function(...) |
|
7130 local _ENV=_ENV; |
|
7131 local function e(t,...) |
|
7132 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
7133 package.loaded[t]=e; |
|
7134 for t=1,select("#",...)do |
|
7135 (select(t,...))(e); |
|
7136 end |
|
7137 _ENV=e; |
|
7138 _M=e; |
|
7139 return e; |
|
7140 end |
|
7141 local a=require"verse"; |
|
7142 function a.plugins.presence(t) |
|
7143 t.last_presence=nil; |
|
7144 t:hook("presence-out",function(e) |
|
7145 if not e.attr.to then |
|
7146 t.last_presence=e; |
|
7147 end |
|
7148 end,1); |
|
7149 function t:resend_presence() |
|
7150 if self.last_presence then |
|
7151 t:send(self.last_presence); |
|
7152 end |
|
7153 end |
|
7154 function t:set_status(e) |
|
7155 local a=a.presence(); |
|
7156 if type(e)=="table"then |
|
7157 if e.show then |
|
7158 a:tag("show"):text(e.show):up(); |
|
7159 end |
|
7160 if e.priority or e.prio then |
|
7161 a:tag("priority"):text(tostring(e.priority or e.prio)):up(); |
|
7162 end |
|
7163 if e.status or e.msg then |
|
7164 a:tag("status"):text(e.status or e.msg):up(); |
|
7165 end |
|
7166 elseif type(e)=="string"then |
|
7167 a:tag("status"):text(e):up(); |
|
7168 end |
|
7169 t:send(a); |
|
7170 end |
|
7171 end |
|
7172 end) |
|
7173 package.preload['verse.plugins.private']=(function(...) |
|
7174 local _ENV=_ENV; |
|
7175 local function e(t,...) |
|
7176 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
7177 package.loaded[t]=e; |
|
7178 for t=1,select("#",...)do |
|
7179 (select(t,...))(e); |
|
7180 end |
|
7181 _ENV=e; |
|
7182 _M=e; |
|
7183 return e; |
|
7184 end |
|
7185 local t=require"verse"; |
|
7186 local a="jabber:iq:private"; |
|
7187 function t.plugins.private(o) |
|
7188 function o:private_set(o,i,e,n) |
|
7189 local t=t.iq({type="set"}) |
|
7190 :tag("query",{xmlns=a}); |
|
7191 if e then |
|
7192 if e.name==o and e.attr and e.attr.xmlns==i then |
|
7193 t:add_child(e); |
|
7194 else |
|
7195 t:tag(o,{xmlns=i}) |
|
7196 :add_child(e); |
|
7197 end |
|
7198 end |
|
7199 self:send_iq(t,n); |
|
7200 end |
|
7201 function o:private_get(e,o,i) |
|
7202 self:send_iq(t.iq({type="get"}) |
|
7203 :tag("query",{xmlns=a}) |
|
7204 :tag(e,{xmlns=o}), |
|
7205 function(t) |
|
7206 if t.attr.type=="result"then |
|
7207 local t=t:get_child("query",a); |
|
7208 local e=t:get_child(e,o); |
|
7209 i(e); |
|
7210 end |
|
7211 end); |
|
7212 end |
|
7213 end |
|
7214 end) |
|
7215 package.preload['verse.plugins.roster']=(function(...) |
|
7216 local _ENV=_ENV; |
|
7217 local function e(t,...) |
|
7218 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
7219 package.loaded[t]=e; |
|
7220 for t=1,select("#",...)do |
|
7221 (select(t,...))(e); |
|
7222 end |
|
7223 _ENV=e; |
|
7224 _M=e; |
|
7225 return e; |
|
7226 end |
|
7227 local i=require"verse"; |
|
7228 local d=require"util.jid".bare; |
|
7229 local a="jabber:iq:roster"; |
|
7230 local o="urn:xmpp:features:rosterver"; |
|
7231 local n=table.insert; |
|
7232 function i.plugins.roster(t) |
|
7233 local s=false; |
|
7234 local e={ |
|
7235 items={}; |
|
7236 ver=""; |
|
7237 }; |
|
7238 t.roster=e; |
|
7239 t:hook("stream-features",function(e) |
|
7240 if e:get_child("ver",o)then |
|
7241 s=true; |
|
7242 end |
|
7243 end); |
|
7244 local function h(e) |
|
7245 local t=i.stanza("item",{xmlns=a}); |
|
7246 for a,e in pairs(e)do |
|
7247 if a~="groups"then |
|
7248 t.attr[a]=e; |
|
7249 else |
|
7250 for a=1,#e do |
|
7251 t:tag("group"):text(e[a]):up(); |
|
7252 end |
|
7253 end |
|
7254 end |
|
7255 return t; |
|
7256 end |
|
7257 local function r(o) |
|
7258 local e={}; |
|
7259 local a={}; |
|
7260 e.groups=a; |
|
7261 for t,a in pairs(o.attr)do |
|
7262 if t~="xmlns"then |
|
7263 e[t]=a |
|
7264 end |
|
7265 end |
|
7266 for e in o:childtags("group")do |
|
7267 n(a,e:get_text()) |
|
7268 end |
|
7269 return e; |
|
7270 end |
|
7271 function e:load(t) |
|
7272 e.ver,e.items=t.ver,t.items; |
|
7273 end |
|
7274 function e:dump() |
|
7275 return{ |
|
7276 ver=e.ver, |
|
7277 items=e.items, |
|
7278 }; |
|
7279 end |
|
7280 function e:add_contact(o,n,s,e) |
|
7281 local o={jid=o,name=n,groups=s}; |
|
7282 local a=i.iq({type="set"}) |
|
7283 :tag("query",{xmlns=a}) |
|
7284 :add_child(h(o)); |
|
7285 t:send_iq(a,function(t) |
|
7286 if not e then return end |
|
7287 if t.attr.type=="result"then |
|
7288 e(true); |
|
7289 else |
|
7290 e(nil,t); |
|
7291 end |
|
7292 end); |
|
7293 end |
|
7294 function e:delete_contact(o,n) |
|
7295 o=(type(o)=="table"and o.jid)or o; |
|
7296 local s={jid=o,subscription="remove"} |
|
7297 if not e.items[o]then return false,"item-not-found";end |
|
7298 t:send_iq(i.iq({type="set"}) |
|
7299 :tag("query",{xmlns=a}) |
|
7300 :add_child(h(s)), |
|
7301 function(e) |
|
7302 if not n then return end |
|
7303 if e.attr.type=="result"then |
|
7304 n(true); |
|
7305 else |
|
7306 n(nil,e); |
|
7307 end |
|
7308 end); |
|
7309 end |
|
7310 local function h(t) |
|
7311 local t=r(t); |
|
7312 e.items[t.jid]=t; |
|
7313 end |
|
7314 local function r(t) |
|
7315 local a=e.items[t]; |
|
7316 e.items[t]=nil; |
|
7317 return a; |
|
7318 end |
|
7319 function e:fetch(n) |
|
7320 t:send_iq(i.iq({type="get"}):tag("query",{xmlns=a,ver=s and e.ver or nil}), |
|
7321 function(o) |
|
7322 if o.attr.type=="result"then |
|
7323 local t=o:get_child("query",a); |
|
7324 if t then |
|
7325 e.items={}; |
|
7326 for t in t:childtags("item")do |
|
7327 h(t) |
|
7328 end |
|
7329 e.ver=t.attr.ver or""; |
|
7330 end |
|
7331 n(e); |
|
7332 else |
|
7333 n(nil,o); |
|
7334 end |
|
7335 end); |
|
7336 end |
|
7337 t:hook("iq/"..a,function(n) |
|
7338 local s,o=n.attr.type,n.attr.from; |
|
7339 if s=="set"and(not o or o==d(t.jid))then |
|
7340 local s=n:get_child("query",a); |
|
7341 local o=s and s:get_child("item"); |
|
7342 if o then |
|
7343 local i,a; |
|
7344 local n=o.attr.jid; |
|
7345 if o.attr.subscription=="remove"then |
|
7346 i="removed" |
|
7347 a=r(n); |
|
7348 else |
|
7349 i=e.items[n]and"changed"or"added"; |
|
7350 h(o) |
|
7351 a=e.items[n]; |
|
7352 end |
|
7353 e.ver=s.attr.ver; |
|
7354 if a then |
|
7355 t:event("roster/item-"..i,a); |
|
7356 end |
|
7357 end |
|
7358 t:send(i.reply(n)) |
|
7359 return true; |
|
7360 end |
|
7361 end); |
|
7362 end |
|
7363 end) |
|
7364 package.preload['verse.plugins.register']=(function(...) |
|
7365 local _ENV=_ENV; |
|
7366 local function e(t,...) |
|
7367 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
7368 package.loaded[t]=e; |
|
7369 for t=1,select("#",...)do |
|
7370 (select(t,...))(e); |
|
7371 end |
|
7372 _ENV=e; |
|
7373 _M=e; |
|
7374 return e; |
|
7375 end |
|
7376 local t=require"verse"; |
|
7377 local o="jabber:iq:register"; |
|
7378 function t.plugins.register(e) |
|
7379 local function a(i) |
|
7380 if i:get_child("register","http://jabber.org/features/iq-register")then |
|
7381 local t=t.iq({to=e.host_,type="set"}) |
|
7382 :tag("query",{xmlns=o}) |
|
7383 :tag("username"):text(e.username):up() |
|
7384 :tag("password"):text(e.password):up(); |
|
7385 if e.register_email then |
|
7386 t:tag("email"):text(e.register_email):up(); |
|
7387 end |
|
7388 e:send_iq(t,function(t) |
|
7389 if t.attr.type=="result"then |
|
7390 e:event("registration-success"); |
|
7391 else |
|
7392 local a,t,o=t:get_error(); |
|
7393 e:debug("Registration failed: %s",t); |
|
7394 e:event("registration-failure",{type=a,condition=t,text=o}); |
|
7395 end |
|
7396 end); |
|
7397 else |
|
7398 e:debug("In-band registration not offered by server"); |
|
7399 e:event("registration-failure",{condition="service-unavailable"}); |
|
7400 end |
|
7401 e:unhook("stream-features",a); |
|
7402 return true; |
|
7403 end |
|
7404 e:hook("stream-features",a,310); |
|
7405 end |
|
7406 end) |
|
7407 package.preload['verse.plugins.groupchat']=(function(...) |
|
7408 local _ENV=_ENV; |
|
7409 local function e(t,...) |
|
7410 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
7411 package.loaded[t]=e; |
|
7412 for t=1,select("#",...)do |
|
7413 (select(t,...))(e); |
|
7414 end |
|
7415 _ENV=e; |
|
7416 _M=e; |
|
7417 return e; |
|
7418 end |
|
7419 local i=require"verse"; |
|
7420 local e=require"util.events"; |
|
7421 local n=require"util.jid"; |
|
7422 local a={}; |
|
7423 a.__index=a; |
|
7424 local h="urn:xmpp:delay"; |
|
7425 local s="http://jabber.org/protocol/muc"; |
|
7426 function i.plugins.groupchat(o) |
|
7427 o:add_plugin("presence") |
|
7428 o.rooms={}; |
|
7429 o:hook("stanza",function(e) |
|
7430 local a=n.bare(e.attr.from); |
|
7431 if not a then return end |
|
7432 local t=o.rooms[a] |
|
7433 if not t and e.attr.to and a then |
|
7434 t=o.rooms[e.attr.to.." "..a] |
|
7435 end |
|
7436 if t and t.opts.source and e.attr.to~=t.opts.source then return end |
|
7437 if t then |
|
7438 local o=select(3,n.split(e.attr.from)); |
|
7439 local n=e:get_child_text("body"); |
|
7440 local i=e:get_child("delay",h); |
|
7441 local a={ |
|
7442 room_jid=a; |
|
7443 room=t; |
|
7444 sender=t.occupants[o]; |
|
7445 nick=o; |
|
7446 body=n; |
|
7447 stanza=e; |
|
7448 delay=(i and i.attr.stamp); |
|
7449 }; |
|
7450 local t=t:event(e.name,a); |
|
7451 return t or(e.name=="message")or nil; |
|
7452 end |
|
7453 end,500); |
|
7454 function o:join_room(n,h,t,r) |
|
7455 if not h then |
|
7456 return false,"no nickname supplied" |
|
7457 end |
|
7458 t=t or{}; |
|
7459 local e=setmetatable(i.eventable{ |
|
7460 stream=o,jid=n,nick=h, |
|
7461 subject=nil, |
|
7462 occupants={}, |
|
7463 opts=t, |
|
7464 },a); |
|
7465 if t.source then |
|
7466 self.rooms[t.source.." "..n]=e; |
|
7467 else |
|
7468 self.rooms[n]=e; |
|
7469 end |
|
7470 local a=e.occupants; |
|
7471 e:hook("presence",function(o) |
|
7472 local t=o.nick or h; |
|
7473 if not a[t]and o.stanza.attr.type~="unavailable"then |
|
7474 a[t]={ |
|
7475 nick=t; |
|
7476 jid=o.stanza.attr.from; |
|
7477 presence=o.stanza; |
|
7478 }; |
|
7479 local o=o.stanza:get_child("x",s.."#user"); |
|
7480 if o then |
|
7481 local e=o:get_child("item"); |
|
7482 if e and e.attr then |
|
7483 a[t].real_jid=e.attr.jid; |
|
7484 a[t].affiliation=e.attr.affiliation; |
|
7485 a[t].role=e.attr.role; |
|
7486 end |
|
7487 end |
|
7488 if t==e.nick then |
|
7489 e.stream:event("groupchat/joined",e); |
|
7490 else |
|
7491 e:event("occupant-joined",a[t]); |
|
7492 end |
|
7493 elseif a[t]and o.stanza.attr.type=="unavailable"then |
|
7494 if t==e.nick then |
|
7495 e.stream:event("groupchat/left",e); |
|
7496 if e.opts.source then |
|
7497 self.rooms[e.opts.source.." "..n]=nil; |
|
7498 else |
|
7499 self.rooms[n]=nil; |
|
7500 end |
|
7501 else |
|
7502 a[t].presence=o.stanza; |
|
7503 e:event("occupant-left",a[t]); |
|
7504 a[t]=nil; |
|
7505 end |
|
7506 end |
|
7507 end); |
|
7508 e:hook("message",function(a) |
|
7509 local t=a.stanza:get_child_text("subject"); |
|
7510 if not t then return end |
|
7511 t=#t>0 and t or nil; |
|
7512 if t~=e.subject then |
|
7513 local o=e.subject; |
|
7514 e.subject=t; |
|
7515 return e:event("subject-changed",{from=o,to=t,by=a.sender,event=a}); |
|
7516 end |
|
7517 end,2e3); |
|
7518 local t=i.presence():tag("x",{xmlns=s}):reset(); |
|
7519 if r then |
|
7520 t:get_child("x",s):tag("password"):text(r):reset(); |
|
7521 end |
|
7522 self:event("pre-groupchat/joining",t); |
|
7523 e:send(t) |
|
7524 self:event("groupchat/joining",e); |
|
7525 return e; |
|
7526 end |
|
7527 o:hook("presence-out",function(e) |
|
7528 if not e.attr.to then |
|
7529 for a,t in pairs(o.rooms)do |
|
7530 t:send(e); |
|
7531 end |
|
7532 e.attr.to=nil; |
|
7533 end |
|
7534 end); |
|
7535 end |
|
7536 function a:send(e) |
|
7537 if e.name=="message"and not e.attr.type then |
|
7538 e.attr.type="groupchat"; |
|
7539 end |
|
7540 if e.name=="presence"then |
|
7541 e.attr.to=self.jid.."/"..self.nick; |
|
7542 end |
|
7543 if e.attr.type=="groupchat"or not e.attr.to then |
|
7544 e.attr.to=self.jid; |
|
7545 end |
|
7546 if self.opts.source then |
|
7547 e.attr.from=self.opts.source |
|
7548 end |
|
7549 self.stream:send(e); |
|
7550 end |
|
7551 function a:send_message(e) |
|
7552 self:send(i.message():tag("body"):text(e)); |
|
7553 end |
|
7554 function a:set_subject(e) |
|
7555 self:send(i.message():tag("subject"):text(e)); |
|
7556 end |
|
7557 function a:leave(e) |
|
7558 self.stream:event("groupchat/leaving",self); |
|
7559 local t=i.presence({type="unavailable"}); |
|
7560 if e then |
|
7561 t:tag("status"):text(e); |
|
7562 end |
|
7563 self:send(t); |
|
7564 end |
|
7565 function a:admin_set(o,a,t,e) |
|
7566 self:send(i.iq({type="set"}) |
|
7567 :query(s.."#admin") |
|
7568 :tag("item",{nick=o,[a]=t}) |
|
7569 :tag("reason"):text(e or"")); |
|
7570 end |
|
7571 function a:set_role(e,a,t) |
|
7572 self:admin_set(e,"role",a,t); |
|
7573 end |
|
7574 function a:set_affiliation(a,t,e) |
|
7575 self:admin_set(a,"affiliation",t,e); |
|
7576 end |
|
7577 function a:kick(e,t) |
|
7578 self:set_role(e,"none",t); |
|
7579 end |
|
7580 function a:ban(e,t) |
|
7581 self:set_affiliation(e,"outcast",t); |
|
7582 end |
|
7583 end) |
|
7584 package.preload['verse.plugins.vcard']=(function(...) |
|
7585 local _ENV=_ENV; |
|
7586 local function e(t,...) |
|
7587 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
7588 package.loaded[t]=e; |
|
7589 for t=1,select("#",...)do |
|
7590 (select(t,...))(e); |
|
7591 end |
|
7592 _ENV=e; |
|
7593 _M=e; |
|
7594 return e; |
|
7595 end |
|
7596 local i=require"verse"; |
|
7597 local o=require"util.vcard"; |
|
7598 local e="vcard-temp"; |
|
7599 function i.plugins.vcard(a) |
|
7600 function a:get_vcard(n,t) |
|
7601 a:send_iq(i.iq({to=n,type="get"}) |
|
7602 :tag("vCard",{xmlns=e}),t and function(a) |
|
7603 local e=a:get_child("vCard",e); |
|
7604 if a.attr.type=="result"and e then |
|
7605 e=o.from_xep54(e) |
|
7606 t(e) |
|
7607 else |
|
7608 t(false) |
|
7609 end |
|
7610 end or nil); |
|
7611 end |
|
7612 function a:set_vcard(e,n) |
|
7613 local t; |
|
7614 if type(e)=="table"and e.name then |
|
7615 t=e; |
|
7616 elseif type(e)=="string"then |
|
7617 t=o.to_xep54(o.from_text(e)[1]); |
|
7618 elseif type(e)=="table"then |
|
7619 t=o.to_xep54(e); |
|
7620 error("Converting a table to vCard not implemented") |
|
7621 end |
|
7622 if not t then return false end |
|
7623 a:debug("setting vcard to %s",tostring(t)); |
|
7624 a:send_iq(i.iq({type="set"}) |
|
7625 :add_child(t),n); |
|
7626 end |
|
7627 end |
|
7628 end) |
|
7629 package.preload['verse.plugins.vcard_update']=(function(...) |
|
7630 local _ENV=_ENV; |
|
7631 local function e(t,...) |
|
7632 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
7633 package.loaded[t]=e; |
|
7634 for t=1,select("#",...)do |
|
7635 (select(t,...))(e); |
|
7636 end |
|
7637 _ENV=e; |
|
7638 _M=e; |
|
7639 return e; |
|
7640 end |
|
7641 local n=require"verse"; |
|
7642 local i="vcard-temp:x:update"; |
|
7643 local s=require("util.hashes").sha1; |
|
7644 local e,t=pcall(function() |
|
7645 local e=require("util.encodings").base64.decode; |
|
7646 assert(e("SGVsbG8=")=="Hello") |
|
7647 return e; |
|
7648 end); |
|
7649 if not e then |
|
7650 e,t=pcall(function()return require("mime").unb64;end); |
|
7651 if not e then |
|
7652 error("Could not find a base64 decoder") |
|
7653 end |
|
7654 end |
|
7655 local h=t; |
|
7656 function n.plugins.vcard_update(e) |
|
7657 e:add_plugin("vcard"); |
|
7658 e:add_plugin("presence"); |
|
7659 local t; |
|
7660 local function r(a) |
|
7661 local o; |
|
7662 for e=1,#a do |
|
7663 if a[e].name=="PHOTO"then |
|
7664 o=a[e][1]; |
|
7665 break |
|
7666 end |
|
7667 end |
|
7668 if o then |
|
7669 local a=s(h(o),true); |
|
7670 t=n.stanza("x",{xmlns=i}) |
|
7671 :tag("photo"):text(a); |
|
7672 e:resend_presence() |
|
7673 else |
|
7674 t=nil; |
|
7675 end |
|
7676 end |
|
7677 local a; |
|
7678 e:hook("ready",function() |
|
7679 if a then return;end |
|
7680 a=true; |
|
7681 e:get_vcard(nil,function(t) |
|
7682 if t then |
|
7683 r(t) |
|
7684 end |
|
7685 e:event("ready"); |
|
7686 end); |
|
7687 return true; |
|
7688 end,3); |
|
7689 e:hook("presence-out",function(e) |
|
7690 if t and not e:get_child("x",i)then |
|
7691 e:add_child(t); |
|
7692 end |
|
7693 end,10); |
|
7694 end |
|
7695 end) |
|
7696 package.preload['verse.plugins.carbons']=(function(...) |
|
7697 local _ENV=_ENV; |
|
7698 local function e(t,...) |
|
7699 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
7700 package.loaded[t]=e; |
|
7701 for t=1,select("#",...)do |
|
7702 (select(t,...))(e); |
|
7703 end |
|
7704 _ENV=e; |
|
7705 _M=e; |
|
7706 return e; |
|
7707 end |
|
7708 local a=require"verse"; |
|
7709 local o="urn:xmpp:carbons:2"; |
|
7710 local s="urn:xmpp:forward:0"; |
|
7711 local n=os.time; |
|
7712 local h=require"util.datetime".parse; |
|
7713 local r=require"util.jid".bare; |
|
7714 function a.plugins.carbons(e) |
|
7715 local t={}; |
|
7716 t.enabled=false; |
|
7717 e.carbons=t; |
|
7718 function t:enable(i) |
|
7719 e:send_iq(a.iq{type="set"} |
|
7720 :tag("enable",{xmlns=o}) |
|
7721 ,function(e) |
|
7722 local e=e.attr.type=="result"; |
|
7723 if e then |
|
7724 t.enabled=true; |
|
7725 end |
|
7726 if i then |
|
7727 i(e); |
|
7728 end |
|
7729 end or nil); |
|
7730 end |
|
7731 function t:disable(i) |
|
7732 e:send_iq(a.iq{type="set"} |
|
7733 :tag("disable",{xmlns=o}) |
|
7734 ,function(e) |
|
7735 local e=e.attr.type=="result"; |
|
7736 if e then |
|
7737 t.enabled=false; |
|
7738 end |
|
7739 if i then |
|
7740 i(e); |
|
7741 end |
|
7742 end or nil); |
|
7743 end |
|
7744 local i; |
|
7745 e:hook("bind-success",function() |
|
7746 i=r(e.jid); |
|
7747 end); |
|
7748 e:hook("message",function(a) |
|
7749 local t=a:get_child(nil,o); |
|
7750 if a.attr.from==i and t then |
|
7751 local o=t.name; |
|
7752 local t=t:get_child("forwarded",s); |
|
7753 local a=t and t:get_child("message","jabber:client"); |
|
7754 local t=t:get_child("delay","urn:xmpp:delay"); |
|
7755 local t=t and t.attr.stamp; |
|
7756 t=t and h(t); |
|
7757 if a then |
|
7758 return e:event("carbon",{ |
|
7759 dir=o, |
|
7760 stanza=a, |
|
7761 timestamp=t or n(), |
|
7762 }); |
|
7763 end |
|
7764 end |
|
7765 end,1); |
|
7766 end |
|
7767 end) |
|
7768 package.preload['verse.plugins.archive']=(function(...) |
|
7769 local _ENV=_ENV; |
|
7770 local function e(t,...) |
|
7771 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
7772 package.loaded[t]=e; |
|
7773 for t=1,select("#",...)do |
|
7774 (select(t,...))(e); |
|
7775 end |
|
7776 _ENV=e; |
|
7777 _M=e; |
|
7778 return e; |
|
7779 end |
|
7780 local o=require"verse"; |
|
7781 local t=require"util.stanza"; |
|
7782 local a="urn:xmpp:mam:2" |
|
7783 local l="urn:xmpp:forward:0"; |
|
7784 local d="urn:xmpp:delay"; |
|
7785 local i=require"util.uuid".generate; |
|
7786 local u=require"util.datetime".parse; |
|
7787 local h=require"util.datetime".datetime; |
|
7788 local e=require"util.dataforms".new; |
|
7789 local r=require"util.rsm"; |
|
7790 local c={}; |
|
7791 local m=e{ |
|
7792 {name="FORM_TYPE";type="hidden";value=a;}; |
|
7793 {name="with";type="jid-single";}; |
|
7794 {name="start";type="text-single"}; |
|
7795 {name="end";type="text-single";}; |
|
7796 }; |
|
7797 function o.plugins.archive(o) |
|
7798 function o:query_archive(o,e,n) |
|
7799 local i=i(); |
|
7800 local o=t.iq{type="set",to=o} |
|
7801 :tag("query",{xmlns=a,queryid=i}); |
|
7802 local t,s=tonumber(e["start"]),tonumber(e["end"]); |
|
7803 e["start"]=t and h(t); |
|
7804 e["end"]=s and h(s); |
|
7805 o:add_child(m:form(e,"submit")); |
|
7806 o:add_child(r.generate(e)); |
|
7807 local t={}; |
|
7808 local function s(e) |
|
7809 local e=e:get_child("result",a); |
|
7810 if e and e.attr.queryid==i then |
|
7811 local a=e:get_child("forwarded",l); |
|
7812 local o=e.attr.id; |
|
7813 local e=a:get_child("delay",d); |
|
7814 local e=e and u(e.attr.stamp)or nil; |
|
7815 local a=a:get_child("message","jabber:client") |
|
7816 t[#t+1]={id=o,stamp=e,message=a}; |
|
7817 return true |
|
7818 end |
|
7819 end |
|
7820 self:hook("message",s,1); |
|
7821 self:send_iq(o,function(e) |
|
7822 self:unhook("message",s); |
|
7823 if e.attr.type=="error"then |
|
7824 self:warn(table.concat({e:get_error()}," ")) |
|
7825 n(false,e:get_error()) |
|
7826 return true; |
|
7827 end |
|
7828 local e=e:get_child("fin",a) |
|
7829 if e then |
|
7830 local e=r.get(e); |
|
7831 for a,e in pairs(e or c)do t[a]=e;end |
|
7832 end |
|
7833 n(t); |
|
7834 return true |
|
7835 end); |
|
7836 end |
|
7837 local i={ |
|
7838 always=true,[true]="always", |
|
7839 never=false,[false]="never", |
|
7840 roster="roster", |
|
7841 } |
|
7842 local function s(t) |
|
7843 local e={}; |
|
7844 local a=t.attr.default; |
|
7845 if a then |
|
7846 e[false]=i[a]; |
|
7847 end |
|
7848 local a=t:get_child("always"); |
|
7849 if a then |
|
7850 for t in a:childtags("jid")do |
|
7851 local t=t:get_text(); |
|
7852 e[t]=true; |
|
7853 end |
|
7854 end |
|
7855 local t=t:get_child("never"); |
|
7856 if t then |
|
7857 for t in t:childtags("jid")do |
|
7858 local t=t:get_text(); |
|
7859 e[t]=false; |
|
7860 end |
|
7861 end |
|
7862 return e; |
|
7863 end |
|
7864 local function n(o) |
|
7865 local e |
|
7866 e,o[false]=o[false],nil; |
|
7867 if e~=nil then |
|
7868 e=i[e]; |
|
7869 end |
|
7870 local a=t.stanza("prefs",{xmlns=a,default=e}) |
|
7871 local e=t.stanza("always"); |
|
7872 local t=t.stanza("never"); |
|
7873 for o,a in pairs(o)do |
|
7874 (a and e or t):tag("jid"):text(o):up(); |
|
7875 end |
|
7876 return a:add_child(e):add_child(t); |
|
7877 end |
|
7878 function o:archive_prefs_get(o) |
|
7879 self:send_iq(t.iq{type="get"}:tag("prefs",{xmlns=a}), |
|
7880 function(e) |
|
7881 if e and e.attr.type=="result"and e.tags[1]then |
|
7882 local t=s(e.tags[1]); |
|
7883 o(t,e); |
|
7884 else |
|
7885 o(nil,e); |
|
7886 end |
|
7887 end); |
|
7888 end |
|
7889 function o:archive_prefs_set(e,a) |
|
7890 self:send_iq(t.iq{type="set"}:add_child(n(e)),a); |
|
7891 end |
|
7892 end |
|
7893 end) |
|
7894 package.preload['util.http']=(function(...) |
|
7895 local _ENV=_ENV; |
|
7896 local function e(t,...) |
|
7897 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
7898 package.loaded[t]=e; |
|
7899 for t=1,select("#",...)do |
|
7900 (select(t,...))(e); |
|
7901 end |
|
7902 _ENV=e; |
|
7903 _M=e; |
|
7904 return e; |
|
7905 end |
|
7906 local t,s=string.format,string.char; |
|
7907 local d,n,o=pairs,ipairs,tonumber; |
|
7908 local i,h=table.insert,table.concat; |
|
7909 local function r(e) |
|
7910 return e and(e:gsub("[^a-zA-Z0-9.~_-]",function(e)return t("%%%02x",e:byte());end)); |
|
7911 end |
|
7912 local function a(e) |
|
7913 return e and(e:gsub("%%(%x%x)",function(e)return s(o(e,16));end)); |
|
7914 end |
|
7915 local function e(e) |
|
7916 return e and(e:gsub("%W",function(e) |
|
7917 if e~=" "then |
|
7918 return t("%%%02x",e:byte()); |
|
7919 else |
|
7920 return"+"; |
|
7921 end |
|
7922 end)); |
|
7923 end |
|
7924 local function s(t) |
|
7925 local a={}; |
|
7926 if t[1]then |
|
7927 for o,t in n(t)do |
|
7928 i(a,e(t.name).."="..e(t.value)); |
|
7929 end |
|
7930 else |
|
7931 for o,t in d(t)do |
|
7932 i(a,e(o).."="..e(t)); |
|
7933 end |
|
7934 end |
|
7935 return h(a,"&"); |
|
7936 end |
|
7937 local function n(e) |
|
7938 if not e:match("=")then return a(e);end |
|
7939 local o={}; |
|
7940 for t,e in e:gmatch("([^=&]*)=([^&]*)")do |
|
7941 t,e=t:gsub("%+","%%20"),e:gsub("%+","%%20"); |
|
7942 t,e=a(t),a(e); |
|
7943 i(o,{name=t,value=e}); |
|
7944 o[t]=e; |
|
7945 end |
|
7946 return o; |
|
7947 end |
|
7948 local function t(e,t) |
|
7949 e=","..e:gsub("[ \t]",""):lower()..","; |
|
7950 return e:find(","..t:lower()..",",1,true)~=nil; |
|
7951 end |
|
7952 return{ |
|
7953 urlencode=r,urldecode=a; |
|
7954 formencode=s,formdecode=n; |
|
7955 contains_token=t; |
|
7956 }; |
|
7957 end) |
|
7958 package.preload['net.http.parser']=(function(...) |
|
7959 local _ENV=_ENV; |
|
7960 local function e(t,...) |
|
7961 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
7962 package.loaded[t]=e; |
|
7963 for t=1,select("#",...)do |
|
7964 (select(t,...))(e); |
|
7965 end |
|
7966 _ENV=e; |
|
7967 _M=e; |
|
7968 return e; |
|
7969 end |
|
7970 local w=tonumber; |
|
7971 local a=assert; |
|
7972 local b=require"socket.url".parse; |
|
7973 local t=require"util.http".urldecode; |
|
7974 local function g(e) |
|
7975 e=t((e:gsub("//+","/"))); |
|
7976 if e:sub(1,1)~="/"then |
|
7977 e="/"..e; |
|
7978 end |
|
7979 local t=0; |
|
7980 for e in e:gmatch("([^/]+)/")do |
|
7981 if e==".."then |
|
7982 t=t-1; |
|
7983 elseif e~="."then |
|
7984 t=t+1; |
|
7985 end |
|
7986 if t<0 then |
|
7987 return nil; |
|
7988 end |
|
7989 end |
|
7990 return e; |
|
7991 end |
|
7992 local y={}; |
|
7993 function y.new(u,h,e,p) |
|
7994 local d=true; |
|
7995 if not e or e=="server"then d=false;else a(e=="client","Invalid parser type");end |
|
7996 local e=""; |
|
7997 local y,a,r; |
|
7998 local s=nil; |
|
7999 local t; |
|
8000 local o; |
|
8001 local c; |
|
8002 local n; |
|
8003 return{ |
|
8004 feed=function(l,i) |
|
8005 if n then return nil,"parse has failed";end |
|
8006 if not i then |
|
8007 if s and d and not o then |
|
8008 t.body=e; |
|
8009 u(t); |
|
8010 elseif e~=""then |
|
8011 n=true;return h(); |
|
8012 end |
|
8013 return; |
|
8014 end |
|
8015 e=e..i; |
|
8016 while#e>0 do |
|
8017 if s==nil then |
|
8018 local m=e:find("\r\n\r\n",nil,true); |
|
8019 if not m then return;end |
|
8020 local u,r,l,i,v; |
|
8021 local f; |
|
8022 local a={}; |
|
8023 for t in e:sub(1,m+1):gmatch("([^\r\n]+)\r\n")do |
|
8024 if f then |
|
8025 local e,t=t:match("^([^%s:]+): *(.*)$"); |
|
8026 if not e then n=true;return h("invalid-header-line");end |
|
8027 e=e:lower(); |
|
8028 a[e]=a[e]and a[e]..","..t or t; |
|
8029 else |
|
8030 f=t; |
|
8031 if d then |
|
8032 l,i,v=t:match("^HTTP/(1%.[01]) (%d%d%d) (.*)$"); |
|
8033 i=w(i); |
|
8034 if not i then n=true;return h("invalid-status-line");end |
|
8035 c=not |
|
8036 ((p and p().method=="HEAD") |
|
8037 or(i==204 or i==304 or i==301) |
|
8038 or(i>=100 and i<200)); |
|
8039 else |
|
8040 u,r,l=t:match("^(%w+) (%S+) HTTP/(1%.[01])$"); |
|
8041 if not u then n=true;return h("invalid-status-line");end |
|
8042 end |
|
8043 end |
|
8044 end |
|
8045 if not f then n=true;return h("invalid-status-line");end |
|
8046 y=c and a["transfer-encoding"]=="chunked"; |
|
8047 o=w(a["content-length"]); |
|
8048 if d then |
|
8049 if not c then o=0;end |
|
8050 t={ |
|
8051 code=i; |
|
8052 httpversion=l; |
|
8053 headers=a; |
|
8054 body=c and""or nil; |
|
8055 responseversion=l; |
|
8056 responseheaders=a; |
|
8057 }; |
|
8058 else |
|
8059 local e; |
|
8060 if r:byte()==47 then |
|
8061 local a,t=r:match("([^?]*).?(.*)"); |
|
8062 if t==""then t=nil;end |
|
8063 e={path=a,query=t}; |
|
8064 else |
|
8065 e=b(r); |
|
8066 if not(e and e.path)then n=true;return h("invalid-url");end |
|
8067 end |
|
8068 r=g(e.path); |
|
8069 a.host=e.host or a.host; |
|
8070 o=o or 0; |
|
8071 t={ |
|
8072 method=u; |
|
8073 url=e; |
|
8074 path=r; |
|
8075 httpversion=l; |
|
8076 headers=a; |
|
8077 body=nil; |
|
8078 }; |
|
8079 end |
|
8080 e=e:sub(m+4); |
|
8081 s=true; |
|
8082 end |
|
8083 if s then |
|
8084 if d then |
|
8085 if y then |
|
8086 if not e:find("\r\n",nil,true)then |
|
8087 return; |
|
8088 end |
|
8089 if not a then |
|
8090 a,r=e:match("^(%x+)[^\r\n]*\r\n()"); |
|
8091 a=a and w(a,16); |
|
8092 if not a then n=true;return h("invalid-chunk-size");end |
|
8093 end |
|
8094 if a==0 and e:find("\r\n\r\n",r-2,true)then |
|
8095 s,a=nil,nil; |
|
8096 e=e:gsub("^.-\r\n\r\n",""); |
|
8097 u(t); |
|
8098 elseif#e-r-2>=a then |
|
8099 t.body=t.body..e:sub(r,r+(a-1)); |
|
8100 e=e:sub(r+a+2); |
|
8101 a,r=nil,nil; |
|
8102 else |
|
8103 break; |
|
8104 end |
|
8105 elseif o and#e>=o then |
|
8106 if t.code==101 then |
|
8107 t.body,e=e,""; |
|
8108 else |
|
8109 t.body,e=e:sub(1,o),e:sub(o+1); |
|
8110 end |
|
8111 s=nil;u(t); |
|
8112 else |
|
8113 break; |
|
8114 end |
|
8115 elseif#e>=o then |
|
8116 t.body,e=e:sub(1,o),e:sub(o+1); |
|
8117 s=nil;u(t); |
|
8118 else |
|
8119 break; |
|
8120 end |
|
8121 end |
|
8122 end |
|
8123 end; |
|
8124 }; |
|
8125 end |
|
8126 return y; |
|
8127 end) |
|
8128 package.preload['net.http']=(function(...) |
|
8129 local _ENV=_ENV; |
|
8130 local function a(t,...) |
|
8131 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
8132 package.loaded[t]=e; |
|
8133 for t=1,select("#",...)do |
|
8134 (select(t,...))(e); |
|
8135 end |
|
8136 _ENV=e; |
|
8137 _M=e; |
|
8138 return e; |
|
8139 end |
|
8140 local y=require"socket" |
|
8141 local q=require"util.encodings".base64.encode; |
|
8142 local r=require"socket.url" |
|
8143 local d=require"net.http.parser".new; |
|
8144 local h=require"util.http"; |
|
8145 local x=pcall(require,"ssl"); |
|
8146 local j=require"net.server" |
|
8147 local l,o=table.insert,table.concat; |
|
8148 local m=pairs; |
|
8149 local v,c,p,b,s= |
|
8150 tonumber,tostring,xpcall,select,debug.traceback; |
|
8151 local g,k=assert,error |
|
8152 local u=require"util.logger".init("http"); |
|
8153 a"http" |
|
8154 local i={}; |
|
8155 local n={default_port=80,default_mode="*a"}; |
|
8156 function n.onconnect(t) |
|
8157 local e=i[t]; |
|
8158 local a={e.method or"GET"," ",e.path," HTTP/1.1\r\n"}; |
|
8159 if e.query then |
|
8160 l(a,4,"?"..e.query); |
|
8161 end |
|
8162 t:write(o(a)); |
|
8163 local a={[2]=": ",[4]="\r\n"}; |
|
8164 for e,i in m(e.headers)do |
|
8165 a[1],a[3]=e,i; |
|
8166 t:write(o(a)); |
|
8167 end |
|
8168 t:write("\r\n"); |
|
8169 if e.body then |
|
8170 t:write(e.body); |
|
8171 end |
|
8172 end |
|
8173 function n.onincoming(a,t) |
|
8174 local e=i[a]; |
|
8175 if not e then |
|
8176 u("warn","Received response from connection %s with no request attached!",c(a)); |
|
8177 return; |
|
8178 end |
|
8179 if t and e.reader then |
|
8180 e:reader(t); |
|
8181 end |
|
8182 end |
|
8183 function n.ondisconnect(t,a) |
|
8184 local e=i[t]; |
|
8185 if e and e.conn then |
|
8186 e:reader(nil,a); |
|
8187 end |
|
8188 i[t]=nil; |
|
8189 end |
|
8190 function n.ondetach(e) |
|
8191 i[e]=nil; |
|
8192 end |
|
8193 local function f(e,o,t) |
|
8194 if not e.parser then |
|
8195 local function a(t) |
|
8196 if e.callback then |
|
8197 e.callback(t or"connection-closed",0,e); |
|
8198 e.callback=nil; |
|
8199 end |
|
8200 destroy_request(e); |
|
8201 end |
|
8202 if not o then |
|
8203 a(t); |
|
8204 return; |
|
8205 end |
|
8206 local function o(t) |
|
8207 if e.callback then |
|
8208 e.callback(t.body,t.code,t,e); |
|
8209 e.callback=nil; |
|
8210 end |
|
8211 destroy_request(e); |
|
8212 end |
|
8213 local function t() |
|
8214 return e; |
|
8215 end |
|
8216 e.parser=d(o,a,"client",t); |
|
8217 end |
|
8218 e.parser:feed(o); |
|
8219 end |
|
8220 local function w(e)u("error","Traceback[http]: %s",s(c(e),2));end |
|
8221 function request(e,t,l) |
|
8222 local e=r.parse(e); |
|
8223 if not(e and e.host)then |
|
8224 l(nil,0,e); |
|
8225 return nil,"invalid-url"; |
|
8226 end |
|
8227 if not e.path then |
|
8228 e.path="/"; |
|
8229 end |
|
8230 local d,o,s; |
|
8231 local r,a=e.host,e.port; |
|
8232 local h=r; |
|
8233 if(a=="80"and e.scheme=="http") |
|
8234 or(a=="443"and e.scheme=="https")then |
|
8235 a=nil; |
|
8236 elseif a then |
|
8237 h=h..":"..a; |
|
8238 end |
|
8239 o={ |
|
8240 ["Host"]=h; |
|
8241 ["User-Agent"]="Prosody XMPP Server"; |
|
8242 }; |
|
8243 if e.userinfo then |
|
8244 o["Authorization"]="Basic "..q(e.userinfo); |
|
8245 end |
|
8246 if t then |
|
8247 e.onlystatus=t.onlystatus; |
|
8248 s=t.body; |
|
8249 if s then |
|
8250 d="POST"; |
|
8251 o["Content-Length"]=c(#s); |
|
8252 o["Content-Type"]="application/x-www-form-urlencoded"; |
|
8253 end |
|
8254 if t.method then d=t.method;end |
|
8255 if t.headers then |
|
8256 for t,e in m(t.headers)do |
|
8257 o[t]=e; |
|
8258 end |
|
8259 end |
|
8260 end |
|
8261 e.method,e.headers,e.body=d,o,s; |
|
8262 local o=e.scheme=="https"; |
|
8263 if o and not x then |
|
8264 k("SSL not available, unable to contact https URL"); |
|
8265 end |
|
8266 local s=a and v(a)or(o and 443 or 80); |
|
8267 local a=y.tcp(); |
|
8268 a:settimeout(10); |
|
8269 local d,h=a:connect(r,s); |
|
8270 if not d and h~="timeout"then |
|
8271 l(nil,0,e); |
|
8272 return nil,h; |
|
8273 end |
|
8274 local h=false; |
|
8275 if o then |
|
8276 h=t and t.sslctx or{mode="client",protocol="sslv23",options={"no_sslv2","no_sslv3"}}; |
|
8277 end |
|
8278 e.handler,e.conn=g(j.wrapclient(a,r,s,n,"*a",h)); |
|
8279 e.write=function(...)return e.handler:write(...);end |
|
8280 e.callback=function(a,t,o,i)u("debug","Calling callback, status %s",t or"---");return b(2,p(function()return l(a,t,o,i)end,w));end |
|
8281 e.reader=f; |
|
8282 e.state="status"; |
|
8283 i[e.handler]=e; |
|
8284 return e; |
|
8285 end |
|
8286 function destroy_request(e) |
|
8287 if e.conn then |
|
8288 e.conn=nil; |
|
8289 e.handler:close() |
|
8290 end |
|
8291 end |
|
8292 local e,a=h.urlencode,h.urldecode; |
|
8293 local t,o=h.formencode,h.formdecode; |
|
8294 _M.urlencode,_M.urldecode=e,a; |
|
8295 _M.formencode,_M.formdecode=t,o; |
|
8296 return _M; |
|
8297 end) |
|
8298 package.preload['util.x509']=(function(...) |
|
8299 local _ENV=_ENV; |
|
8300 local function e(t,...) |
|
8301 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
8302 package.loaded[t]=e; |
|
8303 for t=1,select("#",...)do |
|
8304 (select(t,...))(e); |
|
8305 end |
|
8306 _ENV=e; |
|
8307 _M=e; |
|
8308 return e; |
|
8309 end |
|
8310 local i=require"util.encodings".stringprep.nameprep; |
|
8311 local l=require"util.encodings".idna.to_ascii; |
|
8312 local d=require"util.encodings".base64; |
|
8313 local e=require"util.logger".init("x509"); |
|
8314 local c=string.format; |
|
8315 local _ENV=nil; |
|
8316 local f="2.5.4.3"; |
|
8317 local r="2.5.29.17"; |
|
8318 local s="1.3.6.1.5.5.7.8.5"; |
|
8319 local h="1.3.6.1.5.5.7.8.7"; |
|
8320 local function n(a,o) |
|
8321 local t=l(a) |
|
8322 if t==nil then |
|
8323 e("info","Host %s failed IDNA ToASCII operation",a) |
|
8324 return false |
|
8325 end |
|
8326 t=t:lower() |
|
8327 local i=t:gsub("^[^.]+%.","") |
|
8328 for a=1,#o do |
|
8329 local a=o[a] |
|
8330 if t==a:lower()then |
|
8331 e("debug","Cert dNSName %s matched hostname",a); |
|
8332 return true |
|
8333 end |
|
8334 if a:match("^%*%.")then |
|
8335 local t=a:gsub("^[^.]+%.","") |
|
8336 if i==t:lower()then |
|
8337 e("debug","Cert dNSName %s matched hostname",a); |
|
8338 return true |
|
8339 end |
|
8340 end |
|
8341 end |
|
8342 return false |
|
8343 end |
|
8344 local function m(a,t) |
|
8345 local o=i(a) |
|
8346 for a=1,#t do |
|
8347 local t=t[a] |
|
8348 if t:match("[@/]")then |
|
8349 e("debug","Ignoring xmppAddr %s because it's not a bare domain",t) |
|
8350 else |
|
8351 local a=i(t) |
|
8352 if a==nil then |
|
8353 e("info","Ignoring xmppAddr %s, failed nameprep!",t) |
|
8354 else |
|
8355 if o==a then |
|
8356 e("debug","Cert xmppAddr %s matched hostname",t) |
|
8357 return true |
|
8358 end |
|
8359 end |
|
8360 end |
|
8361 end |
|
8362 return false |
|
8363 end |
|
8364 local function u(t,o,i) |
|
8365 local a=l(t) |
|
8366 if a==nil then |
|
8367 e("info","Host %s failed IDNA ToASCII operation",t); |
|
8368 return false |
|
8369 end |
|
8370 if o:match("^_")==nil then o="_"..o end |
|
8371 a=a:lower(); |
|
8372 local n=a:gsub("^[^.]+%.","") |
|
8373 for t=1,#i do |
|
8374 local i,t=i[t]:match("^(_[^.]+)%.(.*)"); |
|
8375 if o==i then |
|
8376 if a==t:lower()then |
|
8377 e("debug","Cert SRVName %s matched hostname",t); |
|
8378 return true; |
|
8379 end |
|
8380 if t:match("^%*%.")then |
|
8381 local a=t:gsub("^[^.]+%.","") |
|
8382 if n==a:lower()then |
|
8383 e("debug","Cert SRVName %s matched hostname",t) |
|
8384 return true |
|
8385 end |
|
8386 end |
|
8387 if a==t:lower()then |
|
8388 e("debug","Cert SRVName %s matched hostname",t); |
|
8389 return true |
|
8390 end |
|
8391 end |
|
8392 end |
|
8393 return false |
|
8394 end |
|
8395 local function l(a,i,o) |
|
8396 if o.setencode then |
|
8397 o:setencode("utf8"); |
|
8398 end |
|
8399 local t=o:extensions() |
|
8400 if t[r]then |
|
8401 local e=t[r]; |
|
8402 local t=false |
|
8403 if e[s]then |
|
8404 t=true |
|
8405 if i=="_xmpp-client"or i=="_xmpp-server"then |
|
8406 if m(a,e[s])then return true end |
|
8407 end |
|
8408 end |
|
8409 if e[h]then |
|
8410 t=true |
|
8411 if i and u(a,i,e[h])then return true end |
|
8412 end |
|
8413 if e["dNSName"]then |
|
8414 t=true |
|
8415 if n(a,e["dNSName"])then return true end |
|
8416 end |
|
8417 if e["uniformResourceIdentifier"]then |
|
8418 t=true |
|
8419 end |
|
8420 if t then return false end |
|
8421 end |
|
8422 local o=o:subject() |
|
8423 local t=nil |
|
8424 for a=1,#o do |
|
8425 local a=o[a] |
|
8426 if a["oid"]==f then |
|
8427 if t then |
|
8428 e("info","Certificate has multiple common names") |
|
8429 return false |
|
8430 end |
|
8431 t=a["value"]; |
|
8432 end |
|
8433 end |
|
8434 if t then |
|
8435 return n(a,{t}) |
|
8436 end |
|
8437 return false |
|
8438 end |
|
8439 local e="%-%-%-%-%-BEGIN ([A-Z ]+)%-%-%-%-%-\r?\n".. |
|
8440 "([0-9A-Za-z+/=\r\n]*)\r?\n%-%-%-%-%-END %1%-%-%-%-%-"; |
|
8441 local function a(t) |
|
8442 local t,e=t:match(e); |
|
8443 if t and e then |
|
8444 return d.decode(e),t; |
|
8445 end |
|
8446 end |
|
8447 local o=('.'):rep(64); |
|
8448 local n="-----BEGIN %s-----\n%s\n-----END %s-----\n" |
|
8449 local function i(t,e) |
|
8450 e=e and e:upper()or"CERTIFICATE"; |
|
8451 t=d.encode(t); |
|
8452 return c(n,e,t:gsub(o,'%0\n',(#t-1)/64),e); |
|
8453 end |
|
8454 return{ |
|
8455 verify_identity=l; |
|
8456 pem2der=a; |
|
8457 der2pem=i; |
|
8458 }; |
|
8459 end) |
|
8460 package.preload['verse.bosh']=(function(...) |
|
8461 local _ENV=_ENV; |
|
8462 local function e(t,...) |
|
8463 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
8464 package.loaded[t]=e; |
|
8465 for t=1,select("#",...)do |
|
8466 (select(t,...))(e); |
|
8467 end |
|
8468 _ENV=e; |
|
8469 _M=e; |
|
8470 return e; |
|
8471 end |
|
8472 local h=require"util.xmppstream".new; |
|
8473 local i=require"util.stanza"; |
|
8474 require"net.httpclient_listener"; |
|
8475 local t=require"net.http"; |
|
8476 local e=setmetatable({},{__index=verse.stream_mt}); |
|
8477 e.__index=e; |
|
8478 local s="http://etherx.jabber.org/streams"; |
|
8479 local n="http://jabber.org/protocol/httpbind"; |
|
8480 local o=5; |
|
8481 function verse.new_bosh(a,t) |
|
8482 local t={ |
|
8483 bosh_conn_pool={}; |
|
8484 bosh_waiting_requests={}; |
|
8485 bosh_rid=math.random(1,999999); |
|
8486 bosh_outgoing_buffer={}; |
|
8487 bosh_url=t; |
|
8488 conn={}; |
|
8489 }; |
|
8490 function t:reopen() |
|
8491 self.bosh_need_restart=true; |
|
8492 self:flush(); |
|
8493 end |
|
8494 local t=verse.new(a,t); |
|
8495 return setmetatable(t,e); |
|
8496 end |
|
8497 function e:connect() |
|
8498 self:_send_session_request(); |
|
8499 end |
|
8500 function e:send(e) |
|
8501 self:debug("Putting into BOSH send buffer: %s",tostring(e)); |
|
8502 self.bosh_outgoing_buffer[#self.bosh_outgoing_buffer+1]=i.clone(e); |
|
8503 self:flush(); |
|
8504 end |
|
8505 function e:flush() |
|
8506 if self.connected |
|
8507 and#self.bosh_waiting_requests<self.bosh_max_requests |
|
8508 and(#self.bosh_waiting_requests==0 |
|
8509 or#self.bosh_outgoing_buffer>0 |
|
8510 or self.bosh_need_restart)then |
|
8511 self:debug("Flushing..."); |
|
8512 local e=self:_make_body(); |
|
8513 local t=self.bosh_outgoing_buffer; |
|
8514 for o,a in ipairs(t)do |
|
8515 e:add_child(a); |
|
8516 t[o]=nil; |
|
8517 end |
|
8518 self:_make_request(e); |
|
8519 else |
|
8520 self:debug("Decided not to flush."); |
|
8521 end |
|
8522 end |
|
8523 function e:_make_request(a) |
|
8524 local e,t=t.request(self.bosh_url,{body=tostring(a)},function(i,e,t) |
|
8525 if e~=0 then |
|
8526 self.inactive_since=nil; |
|
8527 return self:_handle_response(i,e,t); |
|
8528 end |
|
8529 local e=os.time(); |
|
8530 if not self.inactive_since then |
|
8531 self.inactive_since=e; |
|
8532 elseif e-self.inactive_since>self.bosh_max_inactivity then |
|
8533 return self:_disconnected(); |
|
8534 else |
|
8535 self:debug("%d seconds left to reconnect, retrying in %d seconds...", |
|
8536 self.bosh_max_inactivity-(e-self.inactive_since),o); |
|
8537 end |
|
8538 timer.add_task(o,function() |
|
8539 self:debug("Retrying request..."); |
|
8540 for e,a in ipairs(self.bosh_waiting_requests)do |
|
8541 if a==t then |
|
8542 table.remove(self.bosh_waiting_requests,e); |
|
8543 break; |
|
8544 end |
|
8545 end |
|
8546 self:_make_request(a); |
|
8547 end); |
|
8548 end); |
|
8549 if e then |
|
8550 table.insert(self.bosh_waiting_requests,e); |
|
8551 else |
|
8552 self:warn("Request failed instantly: %s",t); |
|
8553 end |
|
8554 end |
|
8555 function e:_disconnected() |
|
8556 self.connected=nil; |
|
8557 self:event("disconnected"); |
|
8558 end |
|
8559 function e:_send_session_request() |
|
8560 local e=self:_make_body(); |
|
8561 e.attr.hold="1"; |
|
8562 e.attr.wait="60"; |
|
8563 e.attr["xml:lang"]="en"; |
|
8564 e.attr.ver="1.6"; |
|
8565 e.attr.from=self.jid; |
|
8566 e.attr.to=self.host; |
|
8567 e.attr.secure='true'; |
|
8568 t.request(self.bosh_url,{body=tostring(e)},function(t,e) |
|
8569 if e==0 then |
|
8570 return self:_disconnected(); |
|
8571 end |
|
8572 local e=self:_parse_response(t) |
|
8573 if not e then |
|
8574 self:warn("Invalid session creation response"); |
|
8575 self:_disconnected(); |
|
8576 return; |
|
8577 end |
|
8578 self.bosh_sid=e.attr.sid; |
|
8579 self.bosh_wait=tonumber(e.attr.wait); |
|
8580 self.bosh_hold=tonumber(e.attr.hold); |
|
8581 self.bosh_max_inactivity=tonumber(e.attr.inactivity); |
|
8582 self.bosh_max_requests=tonumber(e.attr.requests)or self.bosh_hold; |
|
8583 self.connected=true; |
|
8584 self:event("connected"); |
|
8585 self:_handle_response_payload(e); |
|
8586 end); |
|
8587 end |
|
8588 function e:_handle_response(t,a,e) |
|
8589 if self.bosh_waiting_requests[1]~=e then |
|
8590 self:warn("Server replied to request that wasn't the oldest"); |
|
8591 for t,a in ipairs(self.bosh_waiting_requests)do |
|
8592 if a==e then |
|
8593 self.bosh_waiting_requests[t]=nil; |
|
8594 break; |
|
8595 end |
|
8596 end |
|
8597 else |
|
8598 table.remove(self.bosh_waiting_requests,1); |
|
8599 end |
|
8600 local e=self:_parse_response(t); |
|
8601 if e then |
|
8602 self:_handle_response_payload(e); |
|
8603 end |
|
8604 self:flush(); |
|
8605 end |
|
8606 function e:_handle_response_payload(t) |
|
8607 local e=t.tags; |
|
8608 for t=1,#e do |
|
8609 local e=e[t]; |
|
8610 if e.attr.xmlns==s then |
|
8611 self:event("stream-"..e.name,e); |
|
8612 elseif e.attr.xmlns then |
|
8613 self:event("stream/"..e.attr.xmlns,e); |
|
8614 else |
|
8615 self:event("stanza",e); |
|
8616 end |
|
8617 end |
|
8618 if t.attr.type=="terminate"then |
|
8619 self:_disconnected({reason=t.attr.condition}); |
|
8620 end |
|
8621 end |
|
8622 local a={ |
|
8623 stream_ns="http://jabber.org/protocol/httpbind",stream_tag="body", |
|
8624 default_ns="jabber:client", |
|
8625 streamopened=function(e,t)e.notopen=nil;e.payload=verse.stanza("body",t);return true;end; |
|
8626 handlestanza=function(e,t)e.payload:add_child(t);end; |
|
8627 }; |
|
8628 function e:_parse_response(e) |
|
8629 self:debug("Parsing response: %s",e); |
|
8630 if e==nil then |
|
8631 self:debug("%s",debug.traceback()); |
|
8632 self:_disconnected(); |
|
8633 return; |
|
8634 end |
|
8635 local t={notopen=true,stream=self}; |
|
8636 local a=h(t,a); |
|
8637 a:feed(e); |
|
8638 return t.payload; |
|
8639 end |
|
8640 function e:_make_body() |
|
8641 self.bosh_rid=self.bosh_rid+1; |
|
8642 local e=verse.stanza("body",{ |
|
8643 xmlns=n; |
|
8644 content="text/xml; charset=utf-8"; |
|
8645 sid=self.bosh_sid; |
|
8646 rid=self.bosh_rid; |
|
8647 }); |
|
8648 if self.bosh_need_restart then |
|
8649 self.bosh_need_restart=nil; |
|
8650 e.attr.restart='true'; |
|
8651 end |
|
8652 return e; |
|
8653 end |
|
8654 end) |
|
8655 package.preload['verse.client']=(function(...) |
|
8656 local _ENV=_ENV; |
|
8657 local function e(t,...) |
|
8658 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
8659 package.loaded[t]=e; |
|
8660 for t=1,select("#",...)do |
|
8661 (select(t,...))(e); |
|
8662 end |
|
8663 _ENV=e; |
|
8664 _M=e; |
|
8665 return e; |
|
8666 end |
|
8667 local t=require"verse"; |
|
8668 local o=t.stream_mt; |
|
8669 local h=require"util.jid".split; |
|
8670 local s=require"net.adns"; |
|
8671 local a=require"util.stanza"; |
|
8672 t.message,t.presence,t.iq,t.stanza,t.reply,t.error_reply= |
|
8673 a.message,a.presence,a.iq,a.stanza,a.reply,a.error_reply; |
|
8674 local d=require"util.xmppstream".new; |
|
8675 local n="http://etherx.jabber.org/streams"; |
|
8676 local function r(t,e) |
|
8677 return t.priority<e.priority or(t.priority==e.priority and t.weight>e.weight); |
|
8678 end |
|
8679 local i={ |
|
8680 stream_ns=n, |
|
8681 stream_tag="stream", |
|
8682 default_ns="jabber:client"}; |
|
8683 function i.streamopened(e,t) |
|
8684 e.stream_id=t.id; |
|
8685 if not e:event("opened",t)then |
|
8686 e.notopen=nil; |
|
8687 end |
|
8688 return true; |
|
8689 end |
|
8690 function i.streamclosed(e) |
|
8691 e.notopen=true; |
|
8692 if not e.closed then |
|
8693 e:send("</stream:stream>"); |
|
8694 e.closed=true; |
|
8695 end |
|
8696 e:event("closed"); |
|
8697 return e:close("stream closed") |
|
8698 end |
|
8699 function i.handlestanza(t,e) |
|
8700 if e.attr.xmlns==n then |
|
8701 return t:event("stream-"..e.name,e); |
|
8702 elseif e.attr.xmlns then |
|
8703 return t:event("stream/"..e.attr.xmlns,e); |
|
8704 end |
|
8705 return t:event("stanza",e); |
|
8706 end |
|
8707 function i.error(a,t,e) |
|
8708 if a:event(t,e)==nil then |
|
8709 if e then |
|
8710 local t=e:get_child(nil,"urn:ietf:params:xml:ns:xmpp-streams"); |
|
8711 local e=e:get_child_text("text","urn:ietf:params:xml:ns:xmpp-streams"); |
|
8712 error(t.name..(e and": "..e or"")); |
|
8713 else |
|
8714 error(e and e.name or t or"unknown-error"); |
|
8715 end |
|
8716 end |
|
8717 end |
|
8718 function o:reset() |
|
8719 if self.stream then |
|
8720 self.stream:reset(); |
|
8721 else |
|
8722 self.stream=d(self,i); |
|
8723 end |
|
8724 self.notopen=true; |
|
8725 return true; |
|
8726 end |
|
8727 function o:connect_client(e,a) |
|
8728 self.jid,self.password=e,a; |
|
8729 self.username,self.host,self.resource=h(e); |
|
8730 self:add_plugin("tls"); |
|
8731 self:add_plugin("sasl"); |
|
8732 self:add_plugin("bind"); |
|
8733 self:add_plugin("session"); |
|
8734 function self.data(t,e) |
|
8735 local t,a=self.stream:feed(e); |
|
8736 if t then return;end |
|
8737 self:debug("Received invalid XML (%s) %d bytes: %s",tostring(a),#e,e:sub(1,300):gsub("[\r\n]+"," ")); |
|
8738 self:close("xml-not-well-formed"); |
|
8739 end |
|
8740 self:hook("connected",function()self:reopen();end); |
|
8741 self:hook("incoming-raw",function(e)return self.data(self.conn,e);end); |
|
8742 self.curr_id=0; |
|
8743 self.tracked_iqs={}; |
|
8744 self:hook("stanza",function(e) |
|
8745 local t,a=e.attr.id,e.attr.type; |
|
8746 if t and e.name=="iq"and(a=="result"or a=="error")and self.tracked_iqs[t]then |
|
8747 self.tracked_iqs[t](e); |
|
8748 self.tracked_iqs[t]=nil; |
|
8749 return true; |
|
8750 end |
|
8751 end); |
|
8752 self:hook("stanza",function(e) |
|
8753 local a; |
|
8754 if e.attr.xmlns==nil or e.attr.xmlns=="jabber:client"then |
|
8755 if e.name=="iq"and(e.attr.type=="get"or e.attr.type=="set")then |
|
8756 local o=e.tags[1]and e.tags[1].attr.xmlns; |
|
8757 if o then |
|
8758 a=self:event("iq/"..o,e); |
|
8759 if not a then |
|
8760 a=self:event("iq",e); |
|
8761 end |
|
8762 end |
|
8763 if a==nil then |
|
8764 self:send(t.error_reply(e,"cancel","service-unavailable")); |
|
8765 return true; |
|
8766 end |
|
8767 else |
|
8768 a=self:event(e.name,e); |
|
8769 end |
|
8770 end |
|
8771 return a; |
|
8772 end,-1); |
|
8773 self:hook("outgoing",function(e) |
|
8774 if e.name then |
|
8775 self:event("stanza-out",e); |
|
8776 end |
|
8777 end); |
|
8778 self:hook("stanza-out",function(e) |
|
8779 if not e.attr.xmlns then |
|
8780 self:event(e.name.."-out",e); |
|
8781 end |
|
8782 end); |
|
8783 local function e() |
|
8784 self:event("ready"); |
|
8785 end |
|
8786 self:hook("session-success",e,-1) |
|
8787 self:hook("bind-success",e,-1); |
|
8788 local e=self.close; |
|
8789 function self:close(t) |
|
8790 self.close=e; |
|
8791 if not self.closed then |
|
8792 self:send("</stream:stream>"); |
|
8793 self.closed=true; |
|
8794 else |
|
8795 return self:close(t); |
|
8796 end |
|
8797 end |
|
8798 local function t() |
|
8799 self:connect(self.connect_host or self.host,self.connect_port or 5222); |
|
8800 end |
|
8801 if not(self.connect_host or self.connect_port)then |
|
8802 s.lookup(function(a) |
|
8803 if a then |
|
8804 local e={}; |
|
8805 self.srv_hosts=e; |
|
8806 for a,t in ipairs(a)do |
|
8807 table.insert(e,t.srv); |
|
8808 end |
|
8809 table.sort(e,r); |
|
8810 local a=e[1]; |
|
8811 self.srv_choice=1; |
|
8812 if a then |
|
8813 self.connect_host,self.connect_port=a.target,a.port; |
|
8814 self:debug("Best record found, will connect to %s:%d",self.connect_host or self.host,self.connect_port or 5222); |
|
8815 end |
|
8816 self:hook("disconnected",function() |
|
8817 if self.srv_hosts and self.srv_choice<#self.srv_hosts then |
|
8818 self.srv_choice=self.srv_choice+1; |
|
8819 local e=e[self.srv_choice]; |
|
8820 self.connect_host,self.connect_port=e.target,e.port; |
|
8821 t(); |
|
8822 return true; |
|
8823 end |
|
8824 end,1e3); |
|
8825 self:hook("connected",function() |
|
8826 self.srv_hosts=nil; |
|
8827 end,1e3); |
|
8828 end |
|
8829 t(); |
|
8830 end,"_xmpp-client._tcp."..(self.host)..".","SRV"); |
|
8831 else |
|
8832 t(); |
|
8833 end |
|
8834 end |
|
8835 function o:reopen() |
|
8836 self:reset(); |
|
8837 self:send(a.stanza("stream:stream",{to=self.host,["xmlns:stream"]='http://etherx.jabber.org/streams', |
|
8838 xmlns="jabber:client",version="1.0"}):top_tag()); |
|
8839 end |
|
8840 function o:send_iq(e,a) |
|
8841 local t=self:new_id(); |
|
8842 self.tracked_iqs[t]=a; |
|
8843 e.attr.id=t; |
|
8844 self:send(e); |
|
8845 end |
|
8846 function o:new_id() |
|
8847 self.curr_id=self.curr_id+1; |
|
8848 return tostring(self.curr_id); |
|
8849 end |
|
8850 end) |
|
8851 package.preload['verse.component']=(function(...) |
|
8852 local _ENV=_ENV; |
|
8853 local function e(t,...) |
|
8854 local e=package.loaded[t]or _ENV[t]or{_NAME=t}; |
|
8855 package.loaded[t]=e; |
|
8856 for t=1,select("#",...)do |
|
8857 (select(t,...))(e); |
|
8858 end |
|
8859 _ENV=e; |
|
8860 _M=e; |
|
8861 return e; |
|
8862 end |
|
8863 local o=require"verse"; |
|
8864 local t=o.stream_mt; |
|
8865 local d=require"util.jid".split; |
|
8866 local e=require"lxp"; |
|
8867 local a=require"util.stanza"; |
|
8868 local h=require"util.hashes".sha1; |
|
8869 o.message,o.presence,o.iq,o.stanza,o.reply,o.error_reply= |
|
8870 a.message,a.presence,a.iq,a.stanza,a.reply,a.error_reply; |
|
8871 local r=require"util.xmppstream".new; |
|
8872 local s="http://etherx.jabber.org/streams"; |
|
8873 local i="jabber:component:accept"; |
|
8874 local n={ |
|
8875 stream_ns=s, |
|
8876 stream_tag="stream", |
|
8877 default_ns=i}; |
|
8878 function n.streamopened(e,t) |
|
8879 e.stream_id=t.id; |
|
8880 if not e:event("opened",t)then |
|
8881 e.notopen=nil; |
|
8882 end |
|
8883 return true; |
|
8884 end |
|
8885 function n.streamclosed(e) |
|
8886 return e:event("closed"); |
|
8887 end |
|
8888 function n.handlestanza(t,e) |
|
8889 if e.attr.xmlns==s then |
|
8890 return t:event("stream-"..e.name,e); |
|
8891 elseif e.attr.xmlns or e.name=="handshake"then |
|
8892 return t:event("stream/"..(e.attr.xmlns or i),e); |
|
8893 end |
|
8894 return t:event("stanza",e); |
|
8895 end |
|
8896 function t:reset() |
|
8897 if self.stream then |
|
8898 self.stream:reset(); |
|
8899 else |
|
8900 self.stream=r(self,n); |
|
8901 end |
|
8902 self.notopen=true; |
|
8903 return true; |
|
8904 end |
|
8905 function t:connect_component(e,n) |
|
8906 self.jid,self.password=e,n; |
|
8907 self.username,self.host,self.resource=d(e); |
|
8908 function self.data(a,e) |
|
8909 local o,a=self.stream:feed(e); |
|
8910 if o then return;end |
|
8911 t:debug("Received invalid XML (%s) %d bytes: %s",tostring(a),#e,e:sub(1,300):gsub("[\r\n]+"," ")); |
|
8912 t:close("xml-not-well-formed"); |
|
8913 end |
|
8914 self:hook("incoming-raw",function(e)return self.data(self.conn,e);end); |
|
8915 self.curr_id=0; |
|
8916 self.tracked_iqs={}; |
|
8917 self:hook("stanza",function(e) |
|
8918 local t,a=e.attr.id,e.attr.type; |
|
8919 if t and e.name=="iq"and(a=="result"or a=="error")and self.tracked_iqs[t]then |
|
8920 self.tracked_iqs[t](e); |
|
8921 self.tracked_iqs[t]=nil; |
|
8922 return true; |
|
8923 end |
|
8924 end); |
|
8925 self:hook("stanza",function(e) |
|
8926 local t; |
|
8927 if e.attr.xmlns==nil or e.attr.xmlns=="jabber:client"then |
|
8928 if e.name=="iq"and(e.attr.type=="get"or e.attr.type=="set")then |
|
8929 local a=e.tags[1]and e.tags[1].attr.xmlns; |
|
8930 if a then |
|
8931 t=self:event("iq/"..a,e); |
|
8932 if not t then |
|
8933 t=self:event("iq",e); |
|
8934 end |
|
8935 end |
|
8936 if t==nil then |
|
8937 self:send(o.error_reply(e,"cancel","service-unavailable")); |
|
8938 return true; |
|
8939 end |
|
8940 else |
|
8941 t=self:event(e.name,e); |
|
8942 end |
|
8943 end |
|
8944 return t; |
|
8945 end,-1); |
|
8946 self:hook("opened",function(e) |
|
8947 print(self.jid,self.stream_id,e.id); |
|
8948 local e=h(self.stream_id..n,true); |
|
8949 self:send(a.stanza("handshake",{xmlns=i}):text(e)); |
|
8950 self:hook("stream/"..i,function(e) |
|
8951 if e.name=="handshake"then |
|
8952 self:event("authentication-success"); |
|
8953 end |
|
8954 end); |
|
8955 end); |
|
8956 local function e() |
|
8957 self:event("ready"); |
|
8958 end |
|
8959 self:hook("authentication-success",e,-1); |
|
8960 self:connect(self.connect_host or self.host,self.connect_port or 5347); |
|
8961 self:reopen(); |
|
8962 end |
|
8963 function t:reopen() |
|
8964 self:reset(); |
|
8965 self:send(a.stanza("stream:stream",{to=self.jid,["xmlns:stream"]='http://etherx.jabber.org/streams', |
|
8966 xmlns=i,version="1.0"}):top_tag()); |
|
8967 end |
|
8968 function t:close(e) |
|
8969 if not self.notopen then |
|
8970 self:send("</stream:stream>"); |
|
8971 end |
|
8972 local t=self.conn.disconnect(); |
|
8973 self.conn:close(); |
|
8974 t(conn,e); |
|
8975 end |
|
8976 function t:send_iq(t,a) |
|
8977 local e=self:new_id(); |
|
8978 self.tracked_iqs[e]=a; |
|
8979 t.attr.id=e; |
|
8980 self:send(t); |
|
8981 end |
|
8982 function t:new_id() |
|
8983 self.curr_id=self.curr_id+1; |
|
8984 return tostring(self.curr_id); |
|
8985 end |
|
8986 end) |
|
8987 pcall(require,"luarocks.require"); |
|
8988 local n=require"socket"; |
|
8989 pcall(require,"ssl"); |
|
8990 local a=require"net.server"; |
|
8991 local s=require"util.events"; |
|
8992 local o=require"util.logger"; |
|
8993 local e={}; |
|
8994 e.server=a; |
|
8995 local t={}; |
|
8996 t.__index=t; |
|
8997 e.stream_mt=t; |
|
8998 e.plugins={}; |
|
8999 function e.init(...) |
|
9000 for e=1,select("#",...)do |
|
9001 local t,a=pcall(require,"verse."..select(e,...)); |
|
9002 if not t then |
|
9003 error("Verse connection module not found: verse."..select(e,...)..a); |
|
9004 end |
|
9005 end |
|
9006 return e; |
|
9007 end |
|
9008 local i=0; |
|
9009 function e.new(o,a) |
|
9010 local t=setmetatable(a or{},t); |
|
9011 i=i+1; |
|
9012 t.id=tostring(i); |
|
9013 t.logger=o or e.new_logger("stream"..t.id); |
|
9014 t.events=s.new(); |
|
9015 t.plugins={}; |
|
9016 t.verse=e; |
|
9017 return t; |
|
9018 end |
|
9019 e.add_task=require"util.timer".add_task; |
|
9020 e.logger=o.init; |
|
9021 e.new_logger=o.init; |
|
9022 e.log=e.logger("verse"); |
|
9023 local function i(t,...) |
|
9024 local e,a,o=0,{...},select('#',...); |
|
9025 return(t:gsub("%%(.)",function(t)if e<=o then e=e+1;return tostring(a[e]);end end)); |
|
9026 end |
|
9027 function e.set_log_handler(e,t) |
|
9028 t=t or{"debug","info","warn","error"}; |
|
9029 o.reset(); |
|
9030 if io.type(e)=="file"then |
|
9031 local t=e; |
|
9032 function e(e,a,o) |
|
9033 t:write(e,"\t",a,"\t",o,"\n"); |
|
9034 end |
|
9035 end |
|
9036 if e then |
|
9037 local function n(o,a,t,...) |
|
9038 return e(o,a,i(t,...)); |
|
9039 end |
|
9040 for t,e in ipairs(t)do |
|
9041 o.add_level_sink(e,n); |
|
9042 end |
|
9043 end |
|
9044 end |
|
9045 function e._default_log_handler(t,a,o) |
|
9046 return io.stderr:write(t,"\t",a,"\t",o,"\n"); |
|
9047 end |
|
9048 e.set_log_handler(e._default_log_handler,{"error"}); |
|
9049 local function o(t) |
|
9050 e.log("error","Error: %s",t); |
|
9051 e.log("error","Traceback: %s",debug.traceback()); |
|
9052 end |
|
9053 function e.set_error_handler(e) |
|
9054 o=e; |
|
9055 end |
|
9056 function e.loop() |
|
9057 return xpcall(a.loop,o); |
|
9058 end |
|
9059 function e.step() |
|
9060 return xpcall(a.step,o); |
|
9061 end |
|
9062 function e.quit() |
|
9063 return a.setquitting("once"); |
|
9064 end |
|
9065 function t:listen(o,t) |
|
9066 o=o or"localhost"; |
|
9067 t=t or 0; |
|
9068 local e,a=a.addserver(o,t,e.new_listener(self,"server"),"*a"); |
|
9069 if e then |
|
9070 self:debug("Bound to %s:%s",o,t); |
|
9071 self.server=e; |
|
9072 end |
|
9073 return e,a; |
|
9074 end |
|
9075 function t:connect(i,o) |
|
9076 i=i or"localhost"; |
|
9077 o=tonumber(o)or 5222; |
|
9078 local n=n.tcp() |
|
9079 n:settimeout(0); |
|
9080 n:setoption("keepalive",true); |
|
9081 local s,t=n:connect(i,o); |
|
9082 if not s and t~="timeout"then |
|
9083 self:warn("connect() to %s:%d failed: %s",i,o,t); |
|
9084 return self:event("disconnected",{reason=t})or false,t; |
|
9085 end |
|
9086 local e=a.wrapclient(n,i,o,e.new_listener(self),"*a"); |
|
9087 if not e then |
|
9088 self:warn("connection initialisation failed: %s",t); |
|
9089 return self:event("disconnected",{reason=t})or false,t; |
|
9090 end |
|
9091 self:set_conn(e); |
|
9092 return true; |
|
9093 end |
|
9094 function t:set_conn(t) |
|
9095 self.conn=t; |
|
9096 self.send=function(a,e) |
|
9097 self:event("outgoing",e); |
|
9098 e=tostring(e); |
|
9099 self:event("outgoing-raw",e); |
|
9100 return t:write(e); |
|
9101 end; |
|
9102 end |
|
9103 function t:close(t) |
|
9104 if not self.conn then |
|
9105 e.log("error","Attempt to close disconnected connection - possibly a bug"); |
|
9106 return; |
|
9107 end |
|
9108 local e=self.conn.disconnect(); |
|
9109 self.conn:close(); |
|
9110 e(self.conn,t); |
|
9111 end |
|
9112 function t:debug(...) |
|
9113 return self.logger("debug",...); |
|
9114 end |
|
9115 function t:info(...) |
|
9116 return self.logger("info",...); |
|
9117 end |
|
9118 function t:warn(...) |
|
9119 return self.logger("warn",...); |
|
9120 end |
|
9121 function t:error(...) |
|
9122 return self.logger("error",...); |
|
9123 end |
|
9124 function t:event(e,...) |
|
9125 self:debug("Firing event: "..tostring(e)); |
|
9126 return self.events.fire_event(e,...); |
|
9127 end |
|
9128 function t:hook(e,...) |
|
9129 return self.events.add_handler(e,...); |
|
9130 end |
|
9131 function t:unhook(e,t) |
|
9132 return self.events.remove_handler(e,t); |
|
9133 end |
|
9134 function e.eventable(e) |
|
9135 e.events=s.new(); |
|
9136 e.hook,e.unhook=t.hook,t.unhook; |
|
9137 local t=e.events.fire_event; |
|
9138 function e:event(e,...) |
|
9139 return t(e,...); |
|
9140 end |
|
9141 return e; |
|
9142 end |
|
9143 function t:add_plugin(t) |
|
9144 if self.plugins[t]then return true;end |
|
9145 if require("verse.plugins."..t)then |
|
9146 local e,a=e.plugins[t](self); |
|
9147 if e~=false then |
|
9148 self:debug("Loaded %s plugin",t); |
|
9149 self.plugins[t]=true; |
|
9150 else |
|
9151 self:warn("Failed to load %s plugin: %s",t,a); |
|
9152 end |
|
9153 end |
|
9154 return self; |
|
9155 end |
|
9156 function e.new_listener(t) |
|
9157 local a={}; |
|
9158 function a.onconnect(o) |
|
9159 if t.server then |
|
9160 local a=e.new(); |
|
9161 o:setlistener(e.new_listener(a)); |
|
9162 a:set_conn(o); |
|
9163 t:event("connected",{client=a}); |
|
9164 else |
|
9165 t.connected=true; |
|
9166 t:event("connected"); |
|
9167 end |
|
9168 end |
|
9169 function a.onincoming(a,e) |
|
9170 t:event("incoming-raw",e); |
|
9171 end |
|
9172 function a.ondisconnect(a,e) |
|
9173 if a~=t.conn then return end |
|
9174 t.connected=false; |
|
9175 t:event("disconnected",{reason=e}); |
|
9176 end |
|
9177 function a.ondrain(e) |
|
9178 t:event("drained"); |
|
9179 end |
|
9180 function a.onstatus(a,e) |
|
9181 t:event("status",e); |
|
9182 end |
|
9183 return a; |
|
9184 end |
|
9185 return e; |