verse.lua

changeset 0
550f506de75a
equal deleted inserted replaced
-1:000000000000 0:550f506de75a
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={["'"]="&apos;",["\""]="&quot;",["<"]="&lt;",[">"]="&gt;",["&"]="&amp;"};
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;

mercurial