verse.lua

changeset 103
9e0e56393978
parent 88
98b4cf14960b
child 177
3c19b67a1f0f
--- a/verse.lua	Mon Sep 10 09:50:42 2018 +0100
+++ b/verse.lua	Mon Sep 10 09:51:01 2018 +0100
@@ -1,217 +1,118 @@
 package.preload['util.encodings']=(function(...)
+local _ENV=_ENV;
+local function a(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local function e()
 error("Function not implemented");
 end
 local e=require"mime";
-return{
+a"encodings"
 stringprep={};
 base64={encode=e.b64,decode=e.unb64};
-};
+return _M;
 end)
 package.preload['util.hashes']=(function(...)
-local t,e=pcall(require,"crypto");
-if t then
-local t={};
-local o=e.digest;
-local function s(e)
-return function(t,a)
-return o(e,t,not a);
-end
-end
-local e=e.hmac.digest;
-local function n(o)
-return function(i,a,t)
-return e(o,a,i,not t);
-end
-end
-local e={"md5","sha1","sha256","sha512"};
-for a,e in ipairs(e)do
-t[e]=s(e);
-t["hmac_"..e]=n(e);
-end
-return t;
-else
-local t=require"util.sha1".sha1;
-local s=require"bit".bxor;
-local a=string.rep;
-local n=string.char;
-local d=string.byte;
-local i=table.concat;
-local function r(e,h,r)
-if#e>64 then
-e=t(e);
-elseif#e<64 then
-e=e..a("\0",64-#e);
-end
-local o,a={},{}
-for t=1,64 do
-local e=d(e,t)
-o[t]=n(s(e,92));
-a[t]=n(s(e,54));
-end
-o=i(o);
-a=i(a);
-return t(o..t(a..h),r);
-end
-return{
-sha1=t;
-hmac_sha1=r;
-};
-end
-end)
-package.preload['util.sha1']=(function(...)
-local r=string.len
-local o=string.char
-local j=string.byte
-local q=string.sub
-local h=math.floor
-local t=require"bit"
-local g=t.bnot
-local e=t.band
-local y=t.bor
-local n=t.bxor
-local a=t.lshift
-local i=t.rshift
-local m,d,c,l,u
-local function p(e,t)
-return a(e,t)+i(e,32-t)
-end
-local function s(i)
-local t,a
-local t=""
-for n=1,8 do
-a=e(i,15)
-if(a<10)then
-t=o(a+48)..t
-else
-t=o(a+87)..t
-end
-i=h(i/16)
-end
-return t
-end
-local function k(t)
-local i,a
-local n=""
-i=r(t)*8
-t=t..o(128)
-a=56-e(r(t),63)
-if(a<0)then
-a=a+64
-end
-for e=1,a do
-t=t..o(0)
-end
-for t=1,8 do
-n=o(e(i,255))..n
-i=h(i/256)
-end
-return t..n
-end
-local function b(f)
-local s,t,i,o,w,h,r,v
-local a,a
-local a={}
-while(f~="")do
-for e=0,15 do
-a[e]=0
-for t=1,4 do
-a[e]=a[e]*256+j(f,e*4+t)
-end
-end
-for e=16,79 do
-a[e]=p(n(n(a[e-3],a[e-8]),n(a[e-14],a[e-16])),1)
-end
-s=m
-t=d
-i=c
-o=l
-w=u
-for d=0,79 do
-if(d<20)then
-h=y(e(t,i),e(g(t),o))
-r=1518500249
-elseif(d<40)then
-h=n(n(t,i),o)
-r=1859775393
-elseif(d<60)then
-h=y(y(e(t,i),e(t,o)),e(i,o))
-r=2400959708
-else
-h=n(n(t,i),o)
-r=3395469782
-end
-v=p(s,5)+h+w+r+a[d]
-w=o
-o=i
-i=p(t,30)
-t=s
-s=v
-end
-m=e(m+s,4294967295)
-d=e(d+t,4294967295)
-c=e(c+i,4294967295)
-l=e(l+o,4294967295)
-u=e(u+w,4294967295)
-f=q(f,65)
-end
-end
-local function t(e,t)
-e=k(e)
-m=1732584193
-d=4023233417
-c=2562383102
-l=271733878
-u=3285377520
-b(e)
-local e=s(m)..s(d)..s(c)
-..s(l)..s(u);
-if t then
-return e;
-else
-return(e:gsub("..",function(e)
-return string.char(tonumber(e,16));
-end));
-end
-end
-_G.sha1={sha1=t};
-return _G.sha1;
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local function t(t,e)
+error("Hash method "..e.." not available",2);
+end
+local e=setmetatable({},{__index=t});
+local function t(e,o)
+local e,a=pcall(require,e);
+if e then o(a);end
+end
+t("bgcrypto.md5",function(t)
+e.md5=t.digest;
+e.hmac_md5=t.hmac.digest;
+end);
+t("bgcrypto.sha1",function(t)
+e.sha1=t.digest;
+e.hmac_sha1=t.hmac.digest;
+e.scram_Hi_sha1=function(e,a,o)return t.pbkdf2(e,a,o,20);end;
+end);
+t("bgcrypto.sha256",function(t)
+e.sha256=t.digest;
+e.hmac_sha256=t.hmac.digest;
+end);
+t("bgcrypto.sha512",function(t)
+e.sha512=t.digest;
+e.hmac_sha512=t.hmac.digest;
+end);
+t("sha1",function(t)
+e.sha1=function(e,a)
+if a then
+return t.sha1(e);
+else
+return(t.binary(e));
+end
+end;
+end);
+return e;
 end)
 package.preload['lib.adhoc']=(function(...)
-local s,r=require"util.stanza",require"util.uuid";
+local _ENV=_ENV;
+local function r(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local s,i=require"util.stanza",require"util.uuid";
 local e="http://jabber.org/protocol/commands";
-local i={}
+local n={}
 local h={};
-local function n(o,i,t,a)
-local e=s.stanza("command",{xmlns=e,node=o.node,status=i});
+local function o(i,o,t,a)
+local e=s.stanza("command",{xmlns=e,node=i.node,status=o});
 if t then e.attr.sessionid=t;end
 if a then e.attr.action=a;end
 return e;
 end
-function h.new(o,a,t,e)
-return{name=o,node=a,handler=t,cmdtag=n,permission=(e or"user")};
+function h.new(a,i,e,t)
+return{name=a,node=i,handler=e,cmdtag=o,permission=(t or"user")};
 end
 function h.handle_cmd(o,h,t)
-local e=t.tags[1].attr.sessionid or r.generate();
+local e=t.tags[1].attr.sessionid or i.generate();
 local a={};
 a.to=t.attr.to;
 a.from=t.attr.from;
 a.action=t.tags[1].attr.action or"execute";
 a.form=t.tags[1]:child_with_ns("jabber:x:data");
-local a,n=o:handler(a,i[e]);
-i[e]=n;
-local n=s.reply(t);
+local a,i=o:handler(a,n[e]);
+n[e]=i;
+local i=s.reply(t);
 local t;
 if a.status=="completed"then
-i[e]=nil;
+n[e]=nil;
 t=o:cmdtag("completed",e);
 elseif a.status=="canceled"then
-i[e]=nil;
+n[e]=nil;
 t=o:cmdtag("canceled",e);
 elseif a.status=="error"then
-i[e]=nil;
-n=s.error_reply(n,a.error.type,a.error.condition,a.error.message);
-h.send(n);
+n[e]=nil;
+i=s.error_reply(i,a.error.type,a.error.condition,a.error.message);
+h.send(i);
 return true;
 else
 t=o:cmdtag("executing",e);
@@ -229,7 +130,7 @@
 if(e=="prev")or(e=="next")or(e=="complete")then
 a:tag(e):up();
 else
-module:log("error",'Command "'..o.name..
+r:log("error",'Command "'..o.name..
 '" at node "'..o.node..'" provided an invalid action "'..e..'"');
 end
 end
@@ -242,57 +143,66 @@
 t:add_child(e);
 end
 end
-n:add_child(t);
-h.send(n);
+i:add_child(t);
+h.send(i);
 return true;
 end
 return h;
 end)
 package.preload['util.stanza']=(function(...)
+local _ENV=_ENV;
+local function h(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local t=table.insert;
-local d=table.remove;
-local y=table.concat;
-local h=string.format;
-local l=string.match;
-local f=tostring;
+local s=table.remove;
+local p=table.concat;
+local r=string.format;
+local u=string.match;
+local w=tostring;
 local m=setmetatable;
-local p=getmetatable;
 local n=pairs;
-local o=ipairs;
-local i=type;
-local b=string.gsub;
-local w=string.sub;
-local c=string.find;
+local i=ipairs;
+local o=type;
+local y=string.gsub;
+local l=string.sub;
+local f=string.find;
 local e=os;
-local u=not e.getenv("WINDIR");
-local r,a;
-if u then
+local c=not e.getenv("WINDIR");
+local d,a;
+if c then
 local t,e=pcall(require,"util.termcolours");
 if t then
-r,a=e.getstyle,e.getstring;
-else
-u=nil;
+d,a=e.getstyle,e.getstring;
+else
+c=nil;
 end
 end
 local v="urn:ietf:params:xml:ns:xmpp-stanzas";
-local e=nil;
-local e={__type="stanza"};
-e.__index=e;
-local function s(t,a)
-local t={name=t,attr=a or{},tags={}};
+h"stanza"
+stanza_mt={__type="stanza"};
+stanza_mt.__index=stanza_mt;
+local e=stanza_mt;
+function stanza(a,t)
+local t={name=a,attr=t or{},tags={}};
 return m(t,e);
 end
-local function k(t)
-return p(t)==e;
-end
+local h=stanza;
 function e:query(e)
 return self:tag("query",{xmlns=e});
 end
 function e:body(t,e)
 return self:tag("body",e):text(t);
 end
-function e:tag(e,a)
-local a=s(e,a);
+function e:tag(a,e)
+local a=h(a,e);
 local e=self.last_add;
 if not e then e={};self.last_add=e;end
 (e[#e]or self):add_direct_child(a);
@@ -306,7 +216,7 @@
 end
 function e:up()
 local e=self.last_add;
-if e then d(e);end
+if e then s(e);end
 return self;
 end
 function e:reset()
@@ -314,7 +224,7 @@
 return self;
 end
 function e:add_direct_child(e)
-if i(e)=="table"then
+if o(e)=="table"then
 t(self.tags,e);
 end
 t(self,e);
@@ -325,7 +235,7 @@
 return self;
 end
 function e:get_child(t,a)
-for o,e in o(self.tags)do
+for o,e in i(self.tags)do
 if(not t or e.name==t)
 and((not a and self.attr.xmlns==e.attr.xmlns)
 or e.attr.xmlns==a)then
@@ -333,20 +243,20 @@
 end
 end
 end
-function e:get_child_text(t,e)
-local e=self:get_child(t,e);
+function e:get_child_text(e,t)
+local e=self:get_child(e,t);
 if e then
 return e:get_text();
 end
 return nil;
 end
 function e:child_with_name(t)
-for a,e in o(self.tags)do
+for a,e in i(self.tags)do
 if e.name==t then return e;end
 end
 end
 function e:child_with_ns(t)
-for a,e in o(self.tags)do
+for a,e in i(self.tags)do
 if e.attr.xmlns==t then return e;end
 end
 end
@@ -357,15 +267,15 @@
 return t[e];
 end,self,e;
 end
-function e:childtags(o,i)
+function e:childtags(i,o)
 local e=self.tags;
 local a,t=1,#e;
 return function()
 for t=a,t do
 local e=e[t];
-if(not o or e.name==o)
-and((not i and self.attr.xmlns==e.attr.xmlns)
-or e.attr.xmlns==i)then
+if(not i or e.name==i)
+and((not o and self.attr.xmlns==e.attr.xmlns)
+or e.attr.xmlns==o)then
 a=t+1;
 return e;
 end
@@ -373,27 +283,27 @@
 end;
 end
 function e:maptags(i)
-local o,e=self.tags,1;
+local o,t=self.tags,1;
 local n,a=#self,#o;
-local t=1;
-while e<=a and a>0 do
-if self[t]==o[e]then
-local i=i(self[t]);
+local e=1;
+while t<=a and a>0 do
+if self[e]==o[t]then
+local i=i(self[e]);
 if i==nil then
-d(self,t);
-d(o,e);
+s(self,e);
+s(o,t);
 n=n-1;
 a=a-1;
+e=e-1;
 t=t-1;
-e=e-1;
-else
-self[t]=i;
-o[e]=i;
+else
+self[e]=i;
+o[t]=i;
+end
+t=t+1;
 end
 e=e+1;
 end
-t=t+1;
-end
 return self;
 end
 function e:find(a)
@@ -401,13 +311,13 @@
 local s=#a+1;
 repeat
 local o,t,n;
-local i=w(a,e,e);
+local i=l(a,e,e);
 if i=="@"then
-return self.attr[w(a,e+1)];
+return self.attr[l(a,e+1)];
 elseif i=="{"then
-o,e=l(a,"^([^}]+)}()",e+1);
-end
-t,n,e=l(a,"^([^@/#]*)([/#]?)()",e);
+o,e=u(a,"^([^}]+)}()",e+1);
+end
+t,n,e=u(a,"^([^@/#]*)([/#]?)()",e);
 t=t~=""and t or nil;
 if e==s then
 if n=="#"then
@@ -418,17 +328,21 @@
 self=self:get_child(t,o);
 until not self
 end
-local w={["'"]="&apos;",["\""]="&quot;",["<"]="&lt;",[">"]="&gt;",["&"]="&amp;"};
-local function d(e)return(b(e,"['&<>\"]",w));end
-local function w(o,e,h,a,r)
+local l
+do
+local e={["'"]="&apos;",["\""]="&quot;",["<"]="&lt;",[">"]="&gt;",["&"]="&amp;"};
+function l(t)return(y(t,"['&<>\"]",e));end
+_M.xml_escape=l;
+end
+local function y(o,e,h,a,r)
 local i=0;
 local s=o.name
 t(e,"<"..s);
 for o,n in n(o.attr)do
-if c(o,"\1",1,true)then
-local o,s=l(o,"^([^\1]*)\1?(.*)$");
+if f(o,"\1",1,true)then
+local s,o=u(o,"^([^\1]*)\1?(.*)$");
 i=i+1;
-t(e," xmlns:ns"..i.."='"..a(o).."' ".."ns"..i..":"..s.."='"..a(n).."'");
+t(e," xmlns:ns"..i.."='"..a(s).."' ".."ns"..i..":"..o.."='"..a(n).."'");
 elseif not(o=="xmlns"and n==r)then
 t(e," "..o.."='"..a(n).."'");
 end
@@ -451,280 +365,288 @@
 end
 function e.__tostring(t)
 local e={};
-w(t,e,w,d,nil);
-return y(e);
-end
-function e.top_tag(e)
-local t="";
-if e.attr then
-for e,a in n(e.attr)do if i(e)=="string"then t=t..h(" %s='%s'",e,d(f(a)));end end
-end
-return h("<%s%s>",e.name,t);
+y(t,e,y,l,nil);
+return p(e);
+end
+function e.top_tag(t)
+local e="";
+if t.attr then
+for t,a in n(t.attr)do if o(t)=="string"then e=e..r(" %s='%s'",t,l(w(a)));end end
+end
+return r("<%s%s>",t.name,e);
 end
 function e.get_text(e)
 if#e.tags==0 then
-return y(e);
+return p(e);
 end
 end
 function e.get_error(e)
-local i,t,a;
+local o,a,t;
 local e=e:get_child("error");
 if not e then
 return nil,nil,nil;
 end
-i=e.attr.type;
-for o,e in o(e.tags)do
+o=e.attr.type;
+for o,e in i(e.tags)do
 if e.attr.xmlns==v then
-if not a and e.name=="text"then
-a=e:get_text();
-elseif not t then
-t=e.name;
-end
-if t and a then
+if not t and e.name=="text"then
+t=e:get_text();
+elseif not a then
+a=e.name;
+end
+if a and t then
 break;
 end
 end
 end
-return i,t or"undefined-condition",a;
-end
-local w=0;
-local function y()
-w=w+1;
-return"lx"..w;
-end
-local function w(e)
+return o,a or"undefined-condition",t;
+end
+do
+local e=0;
+function new_id()
+e=e+1;
+return"lx"..e;
+end
+end
+function preserialize(e)
 local a={name=e.name,attr=e.attr};
-for o,e in o(e)do
-if i(e)=="table"then
-t(a,w(e));
+for i,e in i(e)do
+if o(e)=="table"then
+t(a,preserialize(e));
 else
 t(a,e);
 end
 end
 return a;
 end
-local function p(a)
+function deserialize(a)
 if a then
 local s=a.attr;
 for e=1,#s do s[e]=nil;end
 local h={};
 for e in n(s)do
-if c(e,"|",1,true)and not c(e,"\1",1,true)then
-local a,t=l(e,"^([^|]+)|(.+)$");
-h[a.."\1"..t]=s[e];
+if f(e,"|",1,true)and not f(e,"\1",1,true)then
+local t,a=u(e,"^([^|]+)|(.+)$");
+h[t.."\1"..a]=s[e];
 s[e]=nil;
 end
 end
-for e,t in n(h)do
-s[e]=t;
+for t,e in n(h)do
+s[t]=e;
 end
 m(a,e);
-for t,e in o(a)do
-if i(e)=="table"then
-p(e);
+for t,e in i(a)do
+if o(e)=="table"then
+deserialize(e);
 end
 end
 if not a.tags then
-local e={};
-for n,o in o(a)do
-if i(o)=="table"then
-t(e,o);
-end
-end
-a.tags=e;
+local n={};
+for i,e in i(a)do
+if o(e)=="table"then
+t(n,e);
+end
+end
+a.tags=n;
 end
 end
 return a;
 end
-local function l(a)
-local o,i={},{};
-for t,e in n(a.attr)do o[t]=e;end
-local o={name=a.name,attr=o,tags=i};
+local function s(a)
+local i,o={},{};
+for t,e in n(a.attr)do i[t]=e;end
+local i={name=a.name,attr=i,tags=o};
 for e=1,#a do
 local e=a[e];
 if e.name then
-e=l(e);
-t(i,e);
-end
+e=s(e);
 t(o,e);
 end
-return m(o,e);
-end
-local function b(t,e)
+t(i,e);
+end
+return m(i,e);
+end
+clone=s;
+function message(t,e)
 if not e then
-return s("message",t);
-else
-return s("message",t):tag("body"):text(e):up();
-end
-end
-local function g(e)
-if e and not e.id then e.id=y();end
-return s("iq",e or{id=y()});
-end
-local function m(e)
-return s(e.name,e.attr and{to=e.attr.from,from=e.attr.to,id=e.attr.id,type=((e.name=="iq"and"result")or e.attr.type)});
-end
-local c={xmlns=v};
-local function v(e,o,a,t)
-local e=m(e);
+return h("message",t);
+else
+return h("message",t):tag("body"):text(e):up();
+end
+end
+function iq(e)
+if e and not e.id then e.id=new_id();end
+return h("iq",e or{id=new_id()});
+end
+function reply(e)
+return h(e.name,e.attr and{to=e.attr.from,from=e.attr.to,id=e.attr.id,type=((e.name=="iq"and"result")or e.attr.type)});
+end
+do
+local t={xmlns=v};
+function error_reply(e,o,i,a)
+local e=reply(e);
 e.attr.type="error";
 e:tag("error",{type=o})
-:tag(a,c):up();
-if t then e:tag("text",c):text(t):up();end
-return e;
-end
-local function c(e)
-return s("presence",e);
-end
-if u then
-local s=r("yellow");
-local u=r("red");
-local l=r("red");
-local t=r("magenta");
-local r=" "..a(s,"%s")..a(t,"=")..a(u,"'%s'");
-local s=a(t,"<")..a(l,"%s").."%s"..a(t,">");
-local l=s.."%s"..a(t,"</")..a(l,"%s")..a(t,">");
-function e.pretty_print(t)
-local e="";
-for a,t in o(t)do
-if i(t)=="string"then
-e=e..d(t);
-else
-e=e..t:pretty_print();
+:tag(i,t):up();
+if(a)then e:tag("text",t):text(a):up();end
+return e;
+end
+end
+function presence(e)
+return h("presence",e);
+end
+if c then
+local s=d("yellow");
+local h=d("red");
+local u=d("red");
+local t=d("magenta");
+local h=" "..a(s,"%s")..a(t,"=")..a(h,"'%s'");
+local s=a(t,"<")..a(u,"%s").."%s"..a(t,">");
+local d=s.."%s"..a(t,"</")..a(u,"%s")..a(t,">");
+function e.pretty_print(e)
+local t="";
+for a,e in i(e)do
+if o(e)=="string"then
+t=t..l(e);
+else
+t=t..e:pretty_print();
 end
 end
 local a="";
-if t.attr then
-for e,t in n(t.attr)do if i(e)=="string"then a=a..h(r,e,f(t));end end
-end
-return h(l,t.name,a,e,t.name);
-end
-function e.pretty_top_tag(t)
-local e="";
-if t.attr then
-for t,a in n(t.attr)do if i(t)=="string"then e=e..h(r,t,f(a));end end
-end
-return h(s,t.name,e);
+if e.attr then
+for e,t in n(e.attr)do if o(e)=="string"then a=a..r(h,e,w(t));end end
+end
+return r(d,e.name,a,t,e.name);
+end
+function e.pretty_top_tag(e)
+local t="";
+if e.attr then
+for e,a in n(e.attr)do if o(e)=="string"then t=t..r(h,e,w(a));end end
+end
+return r(s,e.name,t);
 end
 else
 e.pretty_print=e.__tostring;
 e.pretty_top_tag=e.top_tag;
 end
-return{
-stanza_mt=e;
-stanza=s;
-is_stanza=k;
-new_id=y;
-preserialize=w;
-deserialize=p;
-clone=l;
-message=b;
-iq=g;
-reply=m;
-error_reply=v;
-presence=c;
-xml_escape=d;
-};
+return _M;
 end)
 package.preload['util.timer']=(function(...)
+local _ENV=_ENV;
+local function o(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local a=require"net.server";
-local s=math.min
-local l=math.huge
-local n=require"util.time".now
-local h=table.insert;
-local r=pairs;
-local d=type;
-local i={};
+local h=math.min
+local u=math.huge
+local i=require"socket".gettime;
+local d=table.insert;
+local l=pairs;
+local r=type;
+local s={};
 local e={};
-local t=nil;
+o"timer"
 local t;
 if not a.event then
-function t(o,i)
-local n=n();
-o=o+n;
-if o>=n then
-h(e,{o,i});
-else
-local e=i(n);
-if e and d(e)=="number"then
-return t(e,i);
+function t(o,n)
+local i=i();
+o=o+i;
+if o>=i then
+d(e,{o,n});
+else
+local e=n(i);
+if e and r(e)=="number"then
+return t(e,n);
 end
 end
 end
 a._addtimer(function()
-local a=n();
+local a=i();
 if#e>0 then
-for a,t in r(e)do
-h(i,t);
+for a,t in l(e)do
+d(s,t);
 end
 e={};
 end
-local e=l;
-for h,o in r(i)do
-local o,n=o[1],o[2];
+local e=u;
+for n,o in l(s)do
+local o,i=o[1],o[2];
 if o<=a then
-i[h]=nil;
-local a=n(a);
-if d(a)=="number"then
-t(a,n);
-e=s(e,a);
-end
-else
-e=s(e,o-a);
+s[n]=nil;
+local a=i(a);
+if r(a)=="number"then
+t(a,i);
+e=h(e,a);
+end
+else
+e=h(e,o-a);
 end
 end
 return e;
 end);
 else
 local e=a.event;
-local o=a.event_base;
-local i=(e.core and e.core.LEAVE)or-1;
-function t(a,e)
+local n=a.event_base;
+local a=(e.core and e.core.LEAVE)or-1;
+function t(o,e)
 local t;
-t=o:addevent(nil,0,function()
-local e=e(n());
+t=n:addevent(nil,0,function()
+local e=e(i());
 if e then
 return 0,e;
 elseif t then
-return i;
-end
-end
-,a);
-end
-end
-return{
+return a;
+end
+end
+,o);
+end
+end
 add_task=t;
-};
+return _M;
 end)
 package.preload['util.termcolours']=(function(...)
-local h,s=table.concat,table.insert;
-local a,r=string.char,string.format;
-local o=tonumber;
-local d=ipairs;
+local _ENV=_ENV;
+local function a(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local n,i=table.concat,table.insert;
+local t,s=string.char,string.format;
+local h=tonumber;
+local c=ipairs;
 local l=io.write;
-local i=math.floor;
-local u=type;
-local m=setmetatable;
-local f=pairs;
-local t;
+local e;
 if os.getenv("WINDIR")then
-t=require"util.windows";
-end
-local n=t and t.get_consolecolor and t.get_consolecolor();
-local e=nil;
-local e={
+e=require"util.windows";
+end
+local o=e and e.get_consolecolor and e.get_consolecolor();
+a"termcolours"
+local u={
 reset=0;bright=1,dim=2,underscore=4,blink=5,reverse=7,hidden=8;
 black=30;red=31;green=32;yellow=33;blue=34;magenta=35;cyan=36;white=37;
 ["black background"]=40;["red background"]=41;["green background"]=42;["yellow background"]=43;["blue background"]=44;["magenta background"]=45;["cyan background"]=46;["white background"]=47;
 bold=1,dark=2,underline=4,underlined=4,normal=0;
 }
-local c={
-["0"]=n,
+local d={
+["0"]=o,
 ["1"]=7+8,
 ["1;33"]=2+4+8,
 ["1;31"]=4+8
 }
-local p={
+local r={
 [1]="font-weight: bold",[2]="opacity: 0.5",[4]="text-decoration: underline",[8]="visibility: hidden",
 [30]="color:black",[31]="color:red",[32]="color:green",[33]="color:#FFD700",
 [34]="color:blue",[35]="color: magenta",[36]="color:cyan",[37]="color: white",
@@ -732,127 +654,123 @@
 [43]="background-color:yellow",[44]="background-color:blue",[45]="background-color: magenta",
 [46]="background-color:cyan",[47]="background-color: white";
 };
-local a=a(27).."[%sm%s"..a(27).."[0m";
-local function y(e,t)
+local a=t(27).."[%sm%s"..t(27).."[0m";
+function getstring(e,t)
 if e then
-return r(a,e,t);
+return s(a,e,t);
 else
 return t;
 end
 end
-local function w(e)
-return i(e*3/32)+232;
-end
-local function r(e,t,a)
-if e==t and t==a then
-return w(e);
-end
-e=i(e*3/128);
-t=i(t*3/128);
-a=i(a*3/128);
-return 16+(e*36)+(t*6)+(a);
-end
-local function a(e)
-local t=o(e:sub(1,2),16);
-local a=o(e:sub(3,4),16);
-local e=o(e:sub(5,6),16);
-return t,a,e;
-end
-m(e,{__index=function(t,e)
-if u(e)=="string"and e:find("%x%x%x%x%x%x")==1 then
-local t=e:sub(7)==" background"and"48;5;"or"38;5;";
-return t..r(a(e));
-end
-end});
-local a={
-red="ff0000";fuchsia="ff00ff";green="008000";white="ffffff";
-lime="00ff00";yellow="ffff00";purple="800080";blue="0000ff";
-aqua="00ffff";olive="808000";black="000000";navy="000080";
-teal="008080";silver="c0c0c0";maroon="800000";gray="808080";
-}
-for t,a in f(a)do
-e[t]=e[t]or e[a];
-t,a=t.." background",a.." background"
-e[t]=e[t]or e[a];
-end
-local function r(...)
-local t,a={...},{};
-for o,t in d(t)do
-t=e[t];
-if t then
-s(a,t);
-end
-end
-return h(a,";");
+function getstyle(...)
+local e,t={...},{};
+for a,e in c(e)do
+e=u[e];
+if e then
+i(t,e);
+end
+end
+return n(t,";");
 end
 local a="0";
-local function i(e)
+function setstyle(e)
 e=e or"0";
 if e~=a then
 l("\27["..e.."m");
 a=e;
 end
 end
-if t then
-function i(e)
-e=e or"0";
-if e~=a then
-t.set_consolecolor(c[e]or n);
-a=e;
-end
-end
-if not n then
-function i()end
-end
-end
-local function a(t)
-if t=="0"then return"</span>";end
-local e={};
-for t in t:gmatch("[^;]+")do
-s(e,p[o(t)]);
-end
-return"</span><span style='"..h(e,";").."'>";
-end
-local function e(e)
+if e then
+function setstyle(t)
+t=t or"0";
+if t~=a then
+e.set_consolecolor(d[t]or o);
+a=t;
+end
+end
+if not o then
+function setstyle(e)end
+end
+end
+local function a(e)
+if e=="0"then return"</span>";end
+local t={};
+for e in e:gmatch("[^;]+")do
+i(t,r[h(e)]);
+end
+return"</span><span style='"..n(t,";").."'>";
+end
+function tohtml(e)
 return e:gsub("\027%[(.-)m",a);
 end
-return{
-getstring=y;
-getstyle=r;
-setstyle=i;
-tohtml=e;
-};
+return _M;
 end)
 package.preload['util.uuid']=(function(...)
-local a=require"util.random";
-local t=a.bytes;
-local o=require"util.hex".to;
-local i=math.ceil;
-local function e(e)
-return o(t(i(e/2))):sub(1,e);
-end
+local _ENV=_ENV;
+local function o(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local n=tostring;
+local e=os.time;
+local a=os.clock;
+local i=require"util.hashes".sha1;
+o"uuid"
+local t=0;
 local function o()
+local e=e();
+if t>=e then e=t+1;end
+t=e;
+return e;
+end
+local function t(e)
+return i(e..a()..n({}),true);
+end
+local e=t(o());
+local function a(a)
+e=t(e..a);
+end
+local function t(t)
+if#e<t then a(o());end
+local a=e:sub(0,t);
+e=e:sub(t+1);
+return a;
+end
+local function e()
 return("%x"):format(t(1):byte()%4+8);
 end
-local function t()
-return e(8).."-"..e(4).."-4"..e(3).."-"..(o())..e(3).."-"..e(12);
-end
-return{
-get_nibbles=e;
-generate=t;
-seed=a.seed;
-};
+function generate()
+return t(8).."-"..t(4).."-4"..t(3).."-"..(e())..t(3).."-"..t(12);
+end
+seed=a;
+return _M;
 end)
 package.preload['net.dns']=(function(...)
-local i=require"socket";
+local _ENV=_ENV;
+local function c(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local s=require"socket";
 local k=require"util.timer";
-local z=require"util.ip".new_ip;
-local e,w=pcall(require,"util.windows");
-local E=(e and w)or os.getenv("WINDIR");
-local l,_,v,a,n=
+local e,b=pcall(require,"util.windows");
+local _=(e and b)or os.getenv("WINDIR");
+local u,E,v,a,i=
 coroutine,io,math,string,table;
-local c,s,o,m,u,b,x,q,e,T=
-ipairs,next,pairs,print,setmetatable,tostring,assert,error,select,type;
+local m,h,o,f,r,p,x,q,t,e,z=
+ipairs,next,pairs,print,setmetatable,tostring,assert,error,unpack,select,type;
 local e={
 get=function(t,...)
 local a=e('#',...);
@@ -863,40 +781,40 @@
 return t;
 end;
 set=function(a,...)
-local i=e('#',...);
-local h,o=e(i-1,...);
-local t,n;
-for i=1,i-2 do
-local i=e(i,...)
-local e=a[i]
+local n=e('#',...);
+local s,o=e(n-1,...);
+local t,i;
+for n=1,n-2 do
+local n=e(n,...)
+local e=a[n]
 if o==nil then
 if e==nil then
 return;
-elseif s(e,s(e))then
-t=nil;n=nil;
+elseif h(e,h(e))then
+t=nil;i=nil;
 elseif t==nil then
-t=a;n=i;
+t=a;i=n;
 end
 elseif e==nil then
 e={};
-a[i]=e;
+a[n]=e;
 end
 a=e
 end
 if o==nil and t then
-t[n]=nil;
-else
-a[h]=o;
+t[i]=nil;
+else
+a[s]=o;
 return o;
 end
 end;
 };
-local r,d=e.get,e.set;
+local d,l=e.get,e.set;
 local j=15;
-local e=nil;
-local t={};
-local h=n.insert
-local function f(e)
+c('dns')
+local t=_M;
+local n=i.insert
+local function c(e)
 return(e-(e%256))/256;
 end
 local function y(e)
@@ -908,10 +826,10 @@
 end
 return t;
 end
-local function p(i)
+local function w(i)
 local e={};
 for o,i in o(i)do
-local t=a.char(f(o),o%256);
+local t=a.char(c(o),o%256);
 e[o]=t;
 e[i]=t;
 e[a.lower(i)]=t;
@@ -926,27 +844,27 @@
 t.classes={'IN','CS','CH','HS',[255]='*'};
 t.type=y(t.types);
 t.class=y(t.classes);
-t.typecode=p(t.types);
-t.classcode=p(t.classes);
-local function g(e,o,i)
+t.typecode=w(t.types);
+t.classcode=w(t.classes);
+local function g(e,i,o)
 if a.byte(e,-1)~=46 then e=e..'.';end
 e=a.lower(e);
-return e,t.type[o or'A'],t.class[i or'IN'];
-end
-local function p(t,a,s)
-a=a or i.gettime();
-for o,e in c(t)do
+return e,t.type[i or'A'],t.class[o or'IN'];
+end
+local function y(t,a,n)
+a=a or s.gettime();
+for o,e in m(t)do
 if e.tod then
 e.ttl=v.floor(e.tod-a);
 if e.ttl<=0 then
 t[e[e.type:lower()]]=nil;
-n.remove(t,o);
-return p(t,a,s);
-end
-elseif s=='soft'then
+i.remove(t,o);
+return y(t,a,n);
+end
+elseif n=='soft'then
 x(e.ttl==0);
 t[e[e.type:lower()]]=nil;
-n.remove(t,o);
+i.remove(t,o);
 end
 end
 end
@@ -955,12 +873,12 @@
 e.timeout=j;
 local function j(e)
 local e=e.type and e[e.type:lower()];
-if T(e)~="string"then
+if z(e)~="string"then
 return"<UNKNOWN RDATA TYPE>";
 end
 return e;
 end
-local y={
+local w={
 LOC=e.LOC_tostring;
 MX=function(e)
 return a.format('%2i %s',e.pref,e.mx);
@@ -972,33 +890,40 @@
 };
 local x={};
 function x.__tostring(e)
-local t=(y[e.type]or j)(e);
+local t=(w[e.type]or j)(e);
 return a.format('%2s %-5s %6i %-28s %s',e.class,e.type,e.ttl,e.name,t);
 end
 local j={};
 function j.__tostring(t)
 local e={};
-for a,t in c(t)do
-h(e,b(t)..'\n');
-end
-return n.concat(e);
-end
-local y={};
-function y.__tostring(e)
-local a=i.gettime();
+for a,t in m(t)do
+n(e,p(t)..'\n');
+end
+return i.concat(e);
+end
+local w={};
+function w.__tostring(e)
+local a=s.gettime();
 local t={};
 for i,e in o(e)do
 for i,e in o(e)do
 for o,e in o(e)do
-p(e,a);
-h(t,b(e));
-end
-end
-end
-return n.concat(t);
+y(e,a);
+n(t,p(e));
+end
+end
+end
+return i.concat(t);
+end
+function e:new()
+local t={active={},cache={},unsorted={}};
+r(t,e);
+r(t.cache,w);
+r(t.unsorted,{__mode='kv'});
+return t;
 end
 function t.random(...)
-v.randomseed(v.floor(1e4*i.gettime())%2147483648);
+v.randomseed(v.floor(1e4*s.gettime())%2147483648);
 t.random=v.random;
 return t.random(...);
 end
@@ -1018,27 +943,27 @@
 e.nscount=e.nscount or 0;
 e.arcount=e.arcount or 0;
 local t=a.char(
-f(e.id),e.id%256,
+c(e.id),e.id%256,
 e.rd+2*e.tc+4*e.aa+8*e.opcode+128*e.qr,
 e.rcode+16*e.z+128*e.ra,
-f(e.qdcount),e.qdcount%256,
-f(e.ancount),e.ancount%256,
-f(e.nscount),e.nscount%256,
-f(e.arcount),e.arcount%256
+c(e.qdcount),e.qdcount%256,
+c(e.ancount),e.ancount%256,
+c(e.nscount),e.nscount%256,
+c(e.arcount),e.arcount%256
 );
 return t,e.id;
 end
-local function f(t)
+local function c(t)
 local e={};
 for t in a.gmatch(t,'[^.]+')do
-h(e,a.char(a.len(t)));
-h(e,t);
-end
-h(e,a.char(0));
-return n.concat(e);
-end
-local function T(o,a,e)
-o=f(o);
+n(e,a.char(a.len(t)));
+n(e,t);
+end
+n(e,a.char(0));
+return i.concat(e);
+end
+local function z(o,a,e)
+o=c(o);
 a=t.typecode[a or'a'];
 e=t.classcode[e or'in'];
 return o..a..e;
@@ -1058,8 +983,8 @@
 return 256*t+e;
 end
 function e:dword()
-local e,t,o,a=self:byte(4);
-return 16777216*e+65536*t+256*o+a;
+local o,t,a,e=self:byte(4);
+return 16777216*o+65536*t+256*a+e;
 end
 function e:sub(e)
 e=e or 1;
@@ -1088,24 +1013,24 @@
 return e;
 end
 function e:name()
-local t,a=nil,0;
+local a,t=nil,0;
 local e=self:byte();
 local o={};
 if e==0 then return"."end
 while e>0 do
 if e>=192 then
-a=a+1;
-if a>=20 then q('dns error: 20 pointers');end;
+t=t+1;
+if t>=20 then q('dns error: 20 pointers');end;
 local e=((e-192)*256)+self:byte();
-t=t or self.offset;
+a=a or self.offset;
 self.offset=e+1;
 else
-h(o,self:sub(e)..'.');
+n(o,self:sub(e)..'.');
 end
 e=self:byte();
 end
-self.offset=t or self.offset;
-return n.concat(o);
+self.offset=a or self.offset;
+return i.concat(o);
 end
 function e:question()
 local e={};
@@ -1114,26 +1039,26 @@
 e.class=t.class[self:word()];
 return e;
 end
-function e:A(n)
-local i,o,e,t=self:byte(4);
-n.a=a.format('%i.%i.%i.%i',i,o,e,t);
+function e:A(e)
+local o,t,n,i=self:byte(4);
+e.a=a.format('%i.%i.%i.%i',o,t,n,i);
 end
 function e:AAAA(a)
 local e={};
 for t=1,a.rdlength,2 do
 local t,a=self:byte(2);
-n.insert(e,("%02x%02x"):format(t,a));
-end
-e=n.concat(e,":"):gsub("%f[%x]0+(%x)","%1");
+i.insert(e,("%02x%02x"):format(t,a));
+end
+e=i.concat(e,":"):gsub("%f[%x]0+(%x)","%1");
 local t={};
 for e in e:gmatch(":[0:]+:")do
-n.insert(t,e)
+i.insert(t,e)
 end
 if#t==0 then
 a.aaaa=e;
 return
 elseif#t>1 then
-n.sort(t,function(e,t)return#e>#t end);
+i.sort(t,function(t,e)return#t>#e end);
 end
 a.aaaa=e:gsub(t[1],"::",1):gsub("^0::","::"):gsub("::0$","::");
 end
@@ -1160,28 +1085,28 @@
 e.loc.altitude=self:dword();
 end
 end
-local function f(e,i,t)
+local function c(e,i,t)
 e=e-2147483648;
 if e<0 then i=t;e=-e;end
-local n,t,o;
-o=e%6e4;
-e=(e-o)/6e4;
-t=e%60;
-n=(e-t)/60;
-return a.format('%3d %2d %2.3f %s',n,t,o/1e3,i);
+local n,o,t;
+t=e%6e4;
+e=(e-t)/6e4;
+o=e%60;
+n=(e-o)/60;
+return a.format('%3d %2d %2.3f %s',n,o,t/1e3,i);
 end
 function e.LOC_tostring(e)
 local t={};
-h(t,a.format(
+n(t,a.format(
 '%s    %s    %.2fm %.2fm %.2fm %.2fm',
-f(e.loc.latitude,'N','S'),
-f(e.loc.longitude,'E','W'),
+c(e.loc.latitude,'N','S'),
+c(e.loc.longitude,'E','W'),
 (e.loc.altitude-1e7)/100,
 e.loc.size/100,
 e.loc.horiz_pre/100,
 e.loc.vert_pre/100
 ));
-return n.concat(t);
+return i.concat(t);
 end
 function e:NS(e)
 e.ns=self:name();
@@ -1203,7 +1128,7 @@
 end
 function e:rr()
 local e={};
-u(e,x);
+r(e,x);
 e.name=self:name(self);
 e.type=t.type[self:word()]or e.type;
 e.class=t.class[self:word()]or e.class;
@@ -1223,7 +1148,7 @@
 end
 function e:rrs(t)
 local e={};
-for t=1,t do h(e,self:rr());end
+for t=1,t do n(e,self:rr());end
 return e;
 end
 function e:decode(t,o)
@@ -1234,7 +1159,7 @@
 t.question={};
 local i=self.offset;
 for e=1,t.header.qdcount do
-h(t.question,self:question());
+n(t.question,self:question());
 end
 t.question.raw=a.sub(self.packet,i,self.offset-1);
 if not o then
@@ -1251,16 +1176,16 @@
 e.delays={1,3};
 function e:addnameserver(e)
 self.server=self.server or{};
-h(self.server,e);
+n(self.server,e);
 end
 function e:setnameserver(e)
 self.server={};
 self:addnameserver(e);
 end
 function e:adddefaultnameservers()
-if E then
-if w and w.get_nameservers then
-for t,e in c(w.get_nameservers())do
+if _ then
+if b and b.get_nameservers then
+for t,e in m(b.get_nameservers())do
 self:addnameserver(e);
 end
 end
@@ -1269,16 +1194,15 @@
 self:addnameserver("208.67.220.220");
 end
 else
-local e=_.open("/etc/resolv.conf");
+local e=E.open("/etc/resolv.conf");
 if e then
 for e in e:lines()do
 e=e:gsub("#.*$","")
-:match('^%s*nameserver%s+([%x:%.]*%%?%S*)%s*$');
+:match('^%s*nameserver%s+(.*)%s*$');
 if e then
-local e=z(e);
-if e then
-self:addnameserver(e.addr);
-end
+e:gsub("%f[%d.](%d+%.%d+%.%d+%.%d+)%f[^%d.]",function(e)
+self:addnameserver(e)
+end);
 end
 end
 end
@@ -1287,29 +1211,24 @@
 end
 end
 end
-function e:getsocket(a)
+function e:getsocket(o)
 self.socket=self.socket or{};
 self.socketset=self.socketset or{};
-local e=self.socket[a];
+local e=self.socket[o];
 if e then return e;end
-local o,t;
-local n=self.server[a];
-if n:find(":")then
-e,t=i.udp6();
-else
-e,t=(i.udp4 or i.udp)();
-end
+local a,t;
+e,t=s.udp();
 if e and self.socket_wrapper then e,t=self.socket_wrapper(e,self);end
 if not e then
 return nil,t;
 end
 e:settimeout(0);
-self.socket[a]=e;
-self.socketset[e]=a;
-o,t=e:setsockname('*',0);
-if not o then return self:servfail(e,t);end
-o,t=e:setpeername(n,53);
-if not o then return self:servfail(e,t);end
+self.socket[o]=e;
+self.socketset[e]=o;
+a,t=e:setsockname('*',0);
+if not a then return self:servfail(e,t);end
+a,t=e:setpeername(self.server[o],53);
+if not a then return self:servfail(e,t);end
 return e;
 end
 function e:voidsocket(e)
@@ -1326,100 +1245,100 @@
 self.socket_wrapper=e;
 end
 function e:closeall()
-for t,e in c(self.socket)do
+for t,e in m(self.socket)do
 self.socket[t]=nil;
 self.socketset[e]=nil;
 e:close();
 end
 end
 function e:remember(e,t)
-local i,o,a=g(e.name,e.type,e.class);
+local a,o,i=g(e.name,e.type,e.class);
 if t~='*'then
 t=o;
-local t=r(self.cache,a,'*',i);
-if t then h(t,e);end
-end
-self.cache=self.cache or u({},y);
-local a=r(self.cache,a,t,i)or
-d(self.cache,a,t,i,u({},j));
+local t=d(self.cache,i,'*',a);
+if t then n(t,e);end
+end
+self.cache=self.cache or r({},w);
+local a=d(self.cache,i,t,a)or
+l(self.cache,i,t,a,r({},j));
 if not a[e[o:lower()]]then
 a[e[o:lower()]]=true;
-h(a,e);
+n(a,e);
 end
 if t=='MX'then self.unsorted[a]=true;end
 end
-local function f(t,e)
-return(t.pref==e.pref)and(t.mx<e.mx)or(t.pref<e.pref);
-end
-function e:peek(o,a,t,h)
+local function c(e,t)
+return(e.pref==t.pref)and(e.mx<t.mx)or(e.pref<t.pref);
+end
+function e:peek(o,a,t,n)
 o,a,t=g(o,a,t);
-local e=r(self.cache,t,a,o);
+local e=d(self.cache,t,a,o);
 if not e then
-if h then if h<=0 then return end else h=3 end
-e=r(self.cache,t,"CNAME",o);
+if n then if n<=0 then return end else n=3 end
+e=d(self.cache,t,"CNAME",o);
 if not(e and e[1])then return end
-return self:peek(e[1].cname,a,t,h-1);
-end
-if p(e,i.gettime())and a=='*'or not s(e)then
-d(self.cache,t,a,o,nil);
+return self:peek(e[1].cname,a,t,n-1);
+end
+if y(e,s.gettime())and a=='*'or not h(e)then
+l(self.cache,t,a,o,nil);
 return nil;
 end
-if self.unsorted[e]then n.sort(e,f);self.unsorted[e]=nil;end
+if self.unsorted[e]then i.sort(e,c);self.unsorted[e]=nil;end
 return e;
 end
 function e:purge(e)
 if e=='soft'then
-self.time=i.gettime();
+self.time=s.gettime();
 for t,e in o(self.cache or{})do
 for t,e in o(e)do
 for t,e in o(e)do
-p(e,self.time,'soft')
-end
-end
-end
-else self.cache=u({},y);end
+y(e,self.time,'soft')
+end
+end
+end
+else self.cache=r({},w);end
 end
 function e:query(e,a,t)
 e,a,t=g(e,a,t)
-local n=l.running();
-local o=r(self.wanted,t,a,e);
+local n=u.running();
+local o=d(self.wanted,t,a,e);
 if n and o then
-d(self.wanted,t,a,e,n,true);
+l(self.wanted,t,a,e,n,true);
 return true;
 end
 if not self.server then self:adddefaultnameservers();end
-local s=T(e,a,t);
+local h=z(e,a,t);
 local o=self:peek(e,a,t);
 if o then return o;end
-local h,o=v();
-local i={
-packet=h..s,
+local o,i=v();
+local o={
+packet=o..h,
 server=self.best_server,
 delay=1,
-retry=i.gettime()+self.delays[1]
+retry=s.gettime()+self.delays[1]
 };
-self.active[o]=self.active[o]or{};
-self.active[o][s]=i;
-local o,h=self:getsocket(i.server)
-if not o then
+self.active[i]=self.active[i]or{};
+self.active[i][h]=o;
+if n then
+l(self.wanted,t,a,e,n,true);
+end
+local i,h=self:getsocket(o.server)
+if not i then
 return nil,h;
 end
-o:send(i.packet)
-if n then
-d(self.wanted,t,a,e,n,true);
-end
+i:send(o.packet)
 if k and self.timeout then
-local d=#self.server;
+local r=#self.server;
 local s=1;
 k.add_task(self.timeout,function()
-if r(self.wanted,t,a,e,n)then
-if s<d then
+if d(self.wanted,t,a,e,n)then
+if s<r then
 s=s+1;
-self:servfail(o);
-i.server=self.best_server;
-o,h=self:getsocket(i.server);
-if o then
-o:send(i.packet);
+self:servfail(i);
+o.server=self.best_server;
+i,h=self:getsocket(o.server);
+if i then
+i:send(o.packet);
 return self.timeout;
 end
 end
@@ -1429,13 +1348,13 @@
 end
 return true;
 end
-function e:servfail(t,n)
-local h=self.socketset[t]
+function e:servfail(t,i)
+local n=self.socketset[t]
 t=self:voidsocket(t);
-self.time=i.gettime();
-for i,a in o(self.active)do
+self.time=s.gettime();
+for s,a in o(self.active)do
 for o,e in o(a)do
-if e.server==h then
+if e.server==n then
 e.server=e.server+1
 if e.server>#self.server then
 e.server=1;
@@ -1444,28 +1363,28 @@
 if e.retries>=#self.server then
 a[o]=nil;
 else
-t,n=self:getsocket(e.server);
+t,i=self:getsocket(e.server);
 if t then t:send(e.packet);end
 end
 end
 end
-if s(a)==nil then
-self.active[i]=nil;
-end
-end
-if h==self.best_server then
+if h(a)==nil then
+self.active[s]=nil;
+end
+end
+if n==self.best_server then
 self.best_server=self.best_server+1;
 if self.best_server>#self.server then
 self.best_server=1;
 end
 end
-return t,n;
+return t,i;
 end
 function e:settimeout(e)
 self.timeout=e;
 end
 function e:receive(t)
-self.time=i.gettime();
+self.time=s.gettime();
 t=t or self.socket;
 local e;
 for a,t in o(t)do
@@ -1476,31 +1395,29 @@
 if e and self.active[e.header.id]
 and self.active[e.header.id][e.question.raw]then
 for a,t in o(e.answer)do
-if t.name:sub(-#e.question[1].name,-1)==e.question[1].name then
 self:remember(t,e.question[1].type)
 end
-end
 local t=self.active[e.header.id];
 t[e.question.raw]=nil;
-if not s(t)then self.active[e.header.id]=nil;end
-if not s(self.active)then self:closeall();end
+if not h(t)then self.active[e.header.id]=nil;end
+if not h(self.active)then self:closeall();end
 local e=e.question[1];
-local t=r(self.wanted,e.class,e.type,e.name);
+local t=d(self.wanted,e.class,e.type,e.name);
 if t then
 for e in o(t)do
-if l.status(e)=="suspended"then l.resume(e);end
-end
-d(self.wanted,e.class,e.type,e.name,nil);
-end
-end
-end
-end
-end
-return e;
-end
-function e:feed(a,e,t)
-self.time=i.gettime();
-local e=self:decode(e,t);
+if u.status(e)=="suspended"then u.resume(e);end
+end
+l(self.wanted,e.class,e.type,e.name,nil);
+end
+end
+end
+end
+end
+return e;
+end
+function e:feed(a,t,e)
+self.time=s.gettime();
+local e=self:decode(t,e);
 if e and self.active[e.header.id]
 and self.active[e.header.id][e.question.raw]then
 for a,t in o(e.answer)do
@@ -1508,34 +1425,34 @@
 end
 local t=self.active[e.header.id];
 t[e.question.raw]=nil;
-if not s(t)then self.active[e.header.id]=nil;end
-if not s(self.active)then self:closeall();end
+if not h(t)then self.active[e.header.id]=nil;end
+if not h(self.active)then self:closeall();end
 local e=e.question[1];
 if e then
-local t=r(self.wanted,e.class,e.type,e.name);
+local t=d(self.wanted,e.class,e.type,e.name);
 if t then
 for e in o(t)do
-if l.status(e)=="suspended"then l.resume(e);end
-end
-d(self.wanted,e.class,e.type,e.name,nil);
+if u.status(e)=="suspended"then u.resume(e);end
+end
+l(self.wanted,e.class,e.type,e.name,nil);
 end
 end
 end
 return e;
 end
 function e:cancel(t,a,i)
-local e=r(self.wanted,t,a,i);
+local e=d(self.wanted,t,a,i);
 if e then
 for e in o(e)do
-if l.status(e)=="suspended"then l.resume(e);end
-end
-d(self.wanted,t,a,i,nil);
+if u.status(e)=="suspended"then u.resume(e);end
+end
+l(self.wanted,t,a,i,nil);
 end
 end
 function e:pulse()
 while self:receive()do end
-if not s(self.active)then return nil;end
-self.time=i.gettime();
+if not h(self.active)then return nil;end
+self.time=s.gettime();
 for a,t in o(self.active)do
 for o,e in o(t)do
 if self.time>=e.retry then
@@ -1546,8 +1463,8 @@
 end
 if e.delay>#self.delays then
 t[o]=nil;
-if not s(t)then self.active[a]=nil;end
-if not s(self.active)then return nil;end
+if not h(t)then self.active[a]=nil;end
+if not h(self.active)then return nil;end
 else
 local t=self.socket[e.server];
 if t then t:send(e.packet);end
@@ -1556,22 +1473,22 @@
 end
 end
 end
-if s(self.active)then return true;end
+if h(self.active)then return true;end
 return nil;
 end
-function e:lookup(o,a,t)
-self:query(o,a,t)
+function e:lookup(a,e,t)
+self:query(a,e,t)
 while self:pulse()do
 local e={}
-for t,a in c(self.socket)do
+for t,a in m(self.socket)do
 e[t]=a
 end
-i.select(e,nil,4)
-end
-return self:peek(o,a,t);
-end
-function e:lookupex(o,t,e,a)
-return self:peek(t,e,a)or self:query(t,e,a);
+s.select(e,nil,4)
+end
+return self:peek(a,e,t);
+end
+function e:lookupex(o,a,t,e)
+return self:peek(a,t,e)or self:query(a,t,e);
 end
 function e:tohostname(e)
 return t.lookup(e:gsub("(%d+)%.(%d+)%.(%d+)%.(%d+)","%4.%3.%2.%1.in-addr.arpa."),"PTR");
@@ -1588,31 +1505,31 @@
 type=t.type,
 class=t.class
 };
-local function n(t,e)
+local function s(t,e)
 return(i[e]and i[e][t[e]])or'';
 end
-function e.print(e)
-for o,t in o{'id','qr','opcode','aa','tc','rd','ra','z',
+function e.print(t)
+for o,e in o{'id','qr','opcode','aa','tc','rd','ra','z',
 'rcode','qdcount','ancount','nscount','arcount'}do
-m(a.format('%-30s','header.'..t),e.header[t],n(e.header,t));
-end
-for e,t in c(e.question)do
-m(a.format('question[%i].name         ',e),t.name);
-m(a.format('question[%i].type         ',e),t.type);
-m(a.format('question[%i].class        ',e),t.class);
-end
-local h={name=1,type=1,class=1,ttl=1,rdlength=1,rdata=1};
-local t;
-for s,i in o({'answer','authority','additional'})do
-for s,e in o(e[i])do
-for h,o in o({'name','type','class','ttl','rdlength'})do
-t=a.format('%s[%i].%s',i,s,o);
-m(a.format('%-30s',t),e[o],n(e,o));
-end
-for e,o in o(e)do
-if not h[e]then
-t=a.format('%s[%i].%s',i,s,e);
-m(a.format('%-30s  %s',b(t),b(o)));
+f(a.format('%-30s','header.'..e),t.header[e],s(t.header,e));
+end
+for e,t in m(t.question)do
+f(a.format('question[%i].name         ',e),t.name);
+f(a.format('question[%i].type         ',e),t.type);
+f(a.format('question[%i].class        ',e),t.class);
+end
+local r={name=1,type=1,class=1,ttl=1,rdlength=1,rdata=1};
+local e;
+for n,i in o({'answer','authority','additional'})do
+for h,n in o(t[i])do
+for o,t in o({'name','type','class','ttl','rdlength'})do
+e=a.format('%s[%i].%s',i,h,t);
+f(a.format('%-30s',e),n[t],s(n,t));
+end
+for t,o in o(n)do
+if not r[t]then
+e=a.format('%s[%i].%s',i,h,t);
+f(a.format('%-30s  %s',p(e),p(o)));
 end
 end
 end
@@ -1620,9 +1537,9 @@
 end
 function t.resolver()
 local t={active={},cache={},unsorted={},wanted={},best_server=1};
-u(t,e);
-u(t.cache,y);
-u(t.unsorted,{__mode='kv'});
+r(t,e);
+r(t.cache,w);
+r(t.unsorted,{__mode='kv'});
 return t;
 end
 local e=t.resolver();
@@ -1660,192 +1577,208 @@
 return t;
 end)
 package.preload['net.adns']=(function(...)
+local _ENV=_ENV;
+local function o(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local c=require"net.server";
 local a=require"net.dns";
-local e=require"util.logger".init("adns");
-local o,r,l=coroutine,tostring,pcall;
-local function m(a,a,t,e)return(e-t)+1;end
-local t=nil;
-local function u(d,t,s,h)
-return o.wrap(function(i)
-if i then
-e("debug","Records for %s already cached, using those...",t);
-d(i);
+local t=require"util.logger".init("adns");
+local e,e=table.insert,table.remove;
+local n,h,l=coroutine,tostring,pcall;
+local function u(a,a,t,e)return(e-t)+1;end
+o"adns"
+function lookup(d,e,s,r)
+return n.wrap(function(o)
+if o then
+t("debug","Records for %s already cached, using those...",e);
+d(o);
 return;
 end
-e("debug","Records for %s not in cache, sending query (%s)...",t,r(o.running()));
-local n,i=a.query(t,s,h);
-if n then
-o.yield({h or"IN",s or"A",t,o.running()});
-e("debug","Reply for %s (%s)",t,r(o.running()));
-end
-if n then
-n,i=l(d,a.peek(t,s,h));
-else
-e("error","Error sending DNS query: %s",i);
-n,i=l(d,nil,i);
-end
-if not n then
-e("error","Error in DNS response handler: %s",r(i));
-end
-end)(a.peek(t,s,h));
-end
-local function d(t,o,i)
-e("warn","Cancelling DNS lookup for %s",r(t[3]));
-a.cancel(t[1],t[2],t[3],t[4],o);
-end
-local function r(o,i)
+t("debug","Records for %s not in cache, sending query (%s)...",e,h(n.running()));
+local i,o=a.query(e,s,r);
+if i then
+n.yield({r or"IN",s or"A",e,n.running()});
+t("debug","Reply for %s (%s)",e,h(n.running()));
+end
+if i then
+i,o=l(d,a.peek(e,s,r));
+else
+t("error","Error sending DNS query: %s",o);
+i,o=l(d,nil,o);
+end
+if not i then
+t("error","Error in DNS response handler: %s",h(o));
+end
+end)(a.peek(e,s,r));
+end
+function cancel(e,o,i)
+t("warn","Cancelling DNS lookup for %s",h(e[3]));
+a.cancel(e[1],e[2],e[3],e[4],o);
+end
+function new_async_socket(i,o)
 local n="<unknown>";
 local s={};
-local t={};
+local e={};
 local h;
-function s.onincoming(o,e)
-if e then
-a.feed(t,e);
-end
-end
-function s.ondisconnect(o,a)
-if a then
-e("warn","DNS socket for %s disconnected: %s",n,a);
-local t=i.server;
-if i.socketset[o]==i.best_server and i.best_server==#t then
-e("error","Exhausted all %d configured DNS servers, next lookup will try %s again",#t,t[1]);
-end
-i:servfail(o);
-end
-end
-t,h=c.wrapclient(o,"dns",53,s);
-if not t then
+function s.onincoming(o,t)
+if t then
+a.feed(e,t);
+end
+end
+function s.ondisconnect(a,i)
+if i then
+t("warn","DNS socket for %s disconnected: %s",n,i);
+local e=o.server;
+if o.socketset[a]==o.best_server and o.best_server==#e then
+t("error","Exhausted all %d configured DNS servers, next lookup will try %s again",#e,e[1]);
+end
+o:servfail(a);
+end
+end
+e,h=c.wrapclient(i,"dns",53,s);
+if not e then
 return nil,h;
 end
-t.settimeout=function()end
-t.setsockname=function(e,...)return o:setsockname(...);end
-t.setpeername=function(e,...)n=(...);local a,o=o:setpeername(...);e:set_send(m);return a,o;end
-t.connect=function(e,...)return o:connect(...)end
-t.send=function(a,t)
-e("debug","Sending DNS query to %s",n);
-return o:send(t);
-end
-return t;
-end
-a.socket_wrapper_set(r);
-return{
-lookup=u;
-cancel=d;
-new_async_socket=r;
-};
+e.settimeout=function()end
+e.setsockname=function(t,...)return i:setsockname(...);end
+e.setpeername=function(o,...)n=(...);local a,t=i:setpeername(...);o:set_send(u);return a,t;end
+e.connect=function(t,...)return i:connect(...)end
+e.send=function(a,e)
+t("debug","Sending DNS query to %s",n);
+return i:send(e);
+end
+return e;
+end
+a.socket_wrapper_set(new_async_socket);
+return _M;
 end)
 package.preload['net.server']=(function(...)
-local c=function(e)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local m=function(e)
 return _G[e]
 end
-local Y,e=require("util.logger").init("socket"),table.concat;
-local i=function(...)return Y("debug",e{...});end
-local L=function(...)return Y("warn",e{...});end
-local he=1
-local w=c"type"
-local D=c"pairs"
-local ee=c"ipairs"
-local f=c"tonumber"
-local r=c"tostring"
-local a=c"table"
-local t=c"string"
-local e=c"coroutine"
-local Z=math.min
-local ue=math.huge
-local we=a.concat
-local fe=t.sub
-local me=e.wrap
-local ye=e.yield
-local U,e=pcall(require,"ssl")
-local p=c"socket"or require"socket"
-local X=p.gettime
-local pe=p.dns.getaddrinfo
-local be=(U and e.wrap)
-local de=p.bind
-local ve=p.sleep
-local ce=p.select
-local V
+local W,e=require("util.logger").init("socket"),table.concat;
+local n=function(...)return W("debug",e{...});end
+local E=function(...)return W("warn",e{...});end
+local ce=1
+local f=m"type"
+local b=m"pairs"
+local ue=m"ipairs"
+local y=m"tonumber"
+local l=m"tostring"
+local t=m"table"
+local a=m"string"
+local e=m"coroutine"
+local Y=math.min
+local re=math.huge
+local pe=t.concat
+local he=t.insert
+local we=a.sub
+local fe=e.wrap
+local me=e.yield
+local O,e=pcall(require,"ssl")
+local g=m"socket"or require"socket"
+local F=g.gettime
+local ee=g.dns.getaddrinfo
+local ye=(O and e.wrap)
+local te=g.bind
+local ve=g.select
+local I
+local B
+local ae
+local G
+local J
+local u
+local ie
+local X
+local se
+local ne
+local oe
+local Q
+local s
+local le
+local Z
+local de
+local p
+local i
 local P
-local le
-local B
-local K
-local m
-local re
-local oe
-local ae
-local te
-local ie
-local G
-local d
-local se
-local Q
-local ne
+local r
+local h
+local T
 local v
-local h
-local F
-local l
-local s
-local _
-local b
-local y
+local w
 local k
 local x
 local a
 local o
-local g
-local W
+local q
+local C
 local M
-local I
-local O
+local A
 local j
-local A
-local J
-local n
-local E
-local T
 local N
+local K
+local d
 local H
 local S
-local C
-local q
+local R
+local D
+local L
 local z
-local R
-v={}
+local _
+local U
+p={}
+i={}
+r={}
+P={}
 h={}
-l={}
-F={}
-s={}
-b={}
-y={}
-_={}
+v={}
+w={}
+T={}
 k={}
 a=0
 o=0
-g=0
-W=0
+q=0
+C=0
 M=0
-I=1
-O=0
+A=1
 j=128
-A=10
-E=51e3*1024
-T=25e3*1024
-N=30
-H=6e4
-S=6*60*60
+N=10
+H=51e3*1024
+S=25e3*1024
+R=30
+D=6e4
+L=14*60
 local e=package.config:sub(1,1)=="\\"
-z=(e and math.huge)or p._SETSIZE or 1024
-q=p._SETSIZE or 1024
-R=30
-te=function(y,t,c,u,g,w)
-if t:getfd()>=z then
-L("server.lua: Disallowed FD number: "..t:getfd())
+_=(e and math.huge)or g._SETSIZE or 1024
+z=g._SETSIZE or 1024
+U=30
+ne=function(y,t,m,c,g,w)
+if t:getfd()>=_ then
+E("server.lua: Disallowed FD number: "..t:getfd())
 t:close()
 return nil,"fd-too-large"
 end
 local f=0
-local p,e=y.onconnect,y.ondisconnect
+local v,e=y.onconnect,y.ondisconnect
 local b=t.accept
 local e={}
 e.shutdown=function()end
@@ -1863,110 +1796,109 @@
 end
 e.close=function()
 t:close()
-o=d(l,t,o)
-a=d(h,t,a)
-v[c..":"..u]=nil;
-s[t]=nil
+o=s(r,t,o)
+a=s(i,t,a)
+p[m..":"..c]=nil;
+h[t]=nil
 e=nil
 t=nil
-i"server.lua: closed server handler and removed sockets from list"
+n"server.lua: closed server handler and removed sockets from list"
 end
 e.pause=function(o)
 if not e.paused then
-a=d(h,t,a)
+a=s(i,t,a)
 if o then
-s[t]=nil
+h[t]=nil
 t:close()
 t=nil;
 end
 e.paused=true;
-i("server.lua: server [",c,"]:",u," paused")
+n("server.lua: server [",m,"]:",c," paused")
 end
 end
 e.resume=function()
 if e.paused then
 if not t then
-t=de(c,u,j);
+t=te(m,c,j);
 t:settimeout(0)
 end
-a=m(h,t,a)
-s[t]=e
+a=u(i,t,a)
+h[t]=e
 k[e]=nil
 e.paused=false;
-i("server.lua: server [",c,"]:",u," resumed")
+n("server.lua: server [",m,"]:",c," resumed")
 end
 end
 e.ip=function()
-return c
+return m
 end
 e.serverport=function()
-return u
+return c
 end
 e.socket=function()
 return t
 end
 e.readbuffer=function()
-if a>=q or o>=q then
+if a>=z or o>=z then
 e.pause()
-k[e]=n
-i("server.lua: refused new client connection: server full")
+k[e]=d
+n("server.lua: refused new client connection: server full")
 return false
 end
-local t,s=b(t)
+local t,o=b(t)
 if t then
 local o,a=t:getpeername()
-local e,n,t=Q(e,y,t,o,u,a,g,w)
-if t then
+local t,i,e=Z(e,y,t,o,c,a,g,w)
+if e then
 return false
 end
 f=f+1
-i("server.lua: accepted new client connection from ",r(o),":",r(a)," to ",r(u))
-if p and not w then
-return p(e);
+n("server.lua: accepted new client connection from ",l(o),":",l(a)," to ",l(c))
+if v and not w then
+return v(t);
 end
 return;
-elseif s then
-i("server.lua: error with new client connection: ",r(s))
+elseif o then
+n("server.lua: error with new client connection: ",l(o))
 e.pause()
-k[e]=n
+k[e]=d
 return false
 end
 end
 return e
 end
-Q=function(v,f,t,O,J,I,N,g)
-if t:getfd()>=z then
-L("server.lua: Disallowed FD number: "..t:getfd())
+Z=function(p,f,t,z,K,A,N,g)
+if t:getfd()>=_ then
+E("server.lua: Disallowed FD number: "..t:getfd())
 t:close()
-if v then
-k[v]=n
-v.pause()
+if p then
+k[p]=d
+p.pause()
 end
 return nil,nil,"fd-too-large"
 end
 t:settimeout(0)
-local w
-local z
+local y
+local _
 local q
-local Y
+local V
 local P=f.onincoming
-local F=f.onstatus
+local Y=f.onstatus
 local k=f.ondisconnect
-local L=f.ondrain
+local D=f.ondrain
 local Q=f.onreadtimeout;
-local C=f.ondetach
-local p={}
-local u=0
-local G
-local K
-local D
+local R=f.ondetach
+local b={}
 local c=0
+local B
+local L
+local m=0
 local j=false
-local A=false
-local S,H=0,0
-local E=E
-local T=T
-local e=p
+local E=false
+local W,F=0,0
+local H=H
+local S=S
+local e=b
 e.dispatch=function()
 return P
 end
@@ -1975,30 +1907,30 @@
 end
 e.onreadtimeout=Q;
 e.setlistener=function(a,t)
-if C then
-C(a)
+if R then
+R(a)
 end
 P=t.onincoming
 k=t.ondisconnect
-F=t.onstatus
-L=t.ondrain
+Y=t.onstatus
+D=t.ondrain
 e.onreadtimeout=t.onreadtimeout
-C=t.ondetach
+R=t.ondetach
 end
 e.getstats=function()
-return H,S
+return F,W
 end
 e.ssl=function()
-return Y
+return V
 end
 e.sslctx=function()
 return g
 end
-e.send=function(n,o,i,a)
-return w(t,o,i,a)
+e.send=function(n,o,a,i)
+return y(t,o,a,i)
 end
 e.receive=function(o,a)
-return z(t,o,a)
+return _(t,o,a)
 end
 e.shutdown=function(a)
 return q(t,a)
@@ -2009,85 +1941,85 @@
 end
 return false,"setoption not implemented";
 end
-e.force_close=function(a,t)
-if u~=0 then
-i("server.lua: discarding unwritten data for ",r(O),":",r(I))
-u=0;
-end
-return a:close(t);
-end
-e.close=function(r,n)
+e.force_close=function(t,a)
+if c~=0 then
+n("server.lua: discarding unwritten data for ",l(z),":",l(A))
+c=0;
+end
+return t:close(a);
+end
+e.close=function(l,d)
 if not e then return true;end
-a=d(h,t,a)
-b[e]=nil
-if u~=0 then
+a=s(i,t,a)
+v[e]=nil
+if c~=0 then
 e.sendbuffer()
-if u~=0 then
+if c~=0 then
 if e then
 e.write=nil
 end
-G=true
+B=true
 return false
 end
 end
 if t then
 x=q and q(t)
 t:close()
-o=d(l,t,o)
-s[t]=nil
+o=s(r,t,o)
+h[t]=nil
 t=nil
 else
-i"server.lua: socket already closed"
+n"server.lua: socket already closed"
 end
 if e then
-y[e]=nil
-_[e]=nil
+w[e]=nil
+T[e]=nil
 local t=e;
 e=nil
 if k then
-k(t,n or false);
+k(t,d or false);
 k=nil
 end
 end
-if v then
-v.remove()
-end
-i"server.lua: closed client handler and removed socket from list"
+if p then
+p.remove()
+end
+n"server.lua: closed client handler and removed socket from list"
 return true
 end
 e.server=function()
-return v
+return p
 end
 e.ip=function()
-return O
+return z
 end
 e.serverport=function()
-return J
+return K
 end
 e.clientport=function()
-return I
+return A
 end
 e.port=e.clientport
-local v=function(i,a)
+local p=function(i,a)
 if not e then return false end
-c=c+#a
-if c>E then
-_[e]="send buffer exceeded"
-e.write=B
+m=m+#a
+if m>H then
+T[e]="send buffer exceeded"
+e.write=G
 return false
-elseif t and not l[t]then
-o=m(l,t,o)
-end
-u=u+1
-p[u]=a
+elseif t and not r[t]then
+o=u(r,t,o)
+end
+c=c+1
+b[c]=a
 if e then
-y[e]=y[e]or n
+w[e]=w[e]or d
 end
 return true
 end
-e.write=v
+e.write=p
 e.bufferqueue=function(t)
-return p
+return b
 end
 e.socket=function(a)
 return t
@@ -2097,27 +2029,27 @@
 return N
 end
 e.set_send=function(a,t)
-w=t or w
-return w
-end
-e.bufferlen=function(o,t,a)
-E=a or E
-T=t or T
-return c,T,E
-end
-e.lock_read=function(i,o)
+y=t or y
+return y
+end
+e.bufferlen=function(o,a,t)
+H=t or H
+S=a or S
+return m,S,H
+end
+e.lock_read=function(n,o)
 if o==true then
 local o=a
-a=d(h,t,a)
-b[e]=nil
+a=s(i,t,a)
+v[e]=nil
 if a~=o then
 j=true
 end
 elseif o==false then
 if j then
 j=false
-a=m(h,t,a)
-b[e]=n
+a=u(i,t,a)
+v[e]=d
 end
 end
 return j
@@ -2131,209 +2063,207 @@
 e.lock=function(i,a)
 e.lock_read(a)
 if a==true then
-e.write=B
+e.write=G
 local a=o
-o=d(l,t,o)
-y[e]=nil
+o=s(r,t,o)
+w[e]=nil
 if o~=a then
-A=true
+E=true
 end
 elseif a==false then
-e.write=v
-if A then
-A=false
-v("")
-end
-end
-return j,A
-end
-local v=function()
-local a,t,o=z(t,N)
+e.write=p
+if E then
+E=false
+p("")
+end
+end
+return j,E
+end
+local p=function()
+local a,t,o=_(t,N)
 if not t or(t=="wantread"or t=="timeout")then
-local a=a or o or""
-local o=#a
-if o>T then
+local o=a or o or""
+local a=#o
+if a>S then
 e:close("receive buffer exceeded")
 return false
 end
-local o=o*he
-H=H+o
-M=M+o
-b[e]=n
-return P(e,a,t)
-else
-i("server.lua: client ",r(O),":",r(I)," read error: ",r(t))
-K=true
+local a=a*ce
+F=F+a
+M=M+a
+v[e]=d
+return P(e,o,t)
+else
+n("server.lua: client ",l(z),":",l(A)," read error: ",l(t))
 x=e and e:force_close(t)
 return false
 end
 end
-local y=function()
-local f,a,s,h,m;
+local v=function()
+local f,a,h,i,u;
 if t then
-h=we(p,"",1,u)
-f,a,s=w(t,h,1,c)
-m=(f or s or 0)*he
-S=S+m
-W=W+m
-for e=u,1,-1 do
-p[e]=nil
-end
-else
-f,a,m=false,"unexpected close",0;
+i=pe(b,"",1,c)
+f,a,h=y(t,i,1,m)
+u=(f or h or 0)*ce
+W=W+u
+C=C+u
+for e=c,1,-1 do
+b[e]=nil
+end
+else
+f,a,u=false,"unexpected close",0;
 end
 if f then
-u=0
 c=0
-o=d(l,t,o)
-y[e]=nil
-if L then
-L(e)
-end
-x=D and e:starttls(nil)
-x=G and e:force_close()
+m=0
+o=s(r,t,o)
+w[e]=nil
+if D then
+D(e)
+end
+x=L and e:starttls(nil)
+x=B and e:force_close()
 return true
-elseif s and(a=="timeout"or a=="wantwrite")then
-h=fe(h,s+1,c)
-p[1]=h
-u=1
-c=c-s
-y[e]=n
+elseif h and(a=="timeout"or a=="wantwrite")then
+i=we(i,h+1,m)
+b[1]=i
+c=1
+m=m-h
+w[e]=d
 return true
 else
-i("server.lua: client ",r(O),":",r(I)," write error: ",r(a))
-K=true
+n("server.lua: client ",l(z),":",l(A)," write error: ",l(a))
 x=e and e:force_close(a)
 return false
 end
 end
-local c;
+local d;
 function e.set_sslctx(w,t)
 g=t;
-local s,r
-c=me(function(n)
+local m,l
+d=fe(function(h)
 local t
-for c=1,R do
-o=(r and d(l,n,o))or o
-a=(s and d(h,n,a))or a
-s,r=nil,nil
-c,t=n:dohandshake()
+for d=1,U do
+o=(l and s(r,h,o))or o
+a=(m and s(i,h,a))or a
+m,l=nil,nil
+d,t=h:dohandshake()
 if not t then
-i("server.lua: ssl handshake done")
-e.readbuffer=v
-e.sendbuffer=y
-c=F and F(e,"ssl-handshake-complete")
+n("server.lua: ssl handshake done")
+e.readbuffer=p
+e.sendbuffer=v
+d=Y and Y(e,"ssl-handshake-complete")
 if w.autostart_ssl and f.onconnect then
 f.onconnect(w);
-if u~=0 then
-o=m(l,n,o)
-end
-end
-a=m(h,n,a)
+if c~=0 then
+o=u(r,h,o)
+end
+end
+a=u(i,h,a)
 return true
 else
 if t=="wantwrite"then
-o=m(l,n,o)
-r=true
+o=u(r,h,o)
+l=true
 elseif t=="wantread"then
-a=m(h,n,a)
-s=true
+a=u(i,h,a)
+m=true
 else
 break;
 end
 t=nil;
-ye()
+me()
 end
 end
 t="ssl handshake error: "..(t or"handshake too long");
-i("server.lua: ",t);
+n("server.lua: ",t);
 x=e and e:force_close(t)
 return false,t
 end
 )
 end
-if U then
-e.starttls=function(f,n)
-if n then
-e:set_sslctx(n);
-end
-if u>0 then
-i"server.lua: we need to do tls, but delaying until send buffer empty"
-D=true
+if O then
+e.starttls=function(f,m)
+if m then
+e:set_sslctx(m);
+end
+if c>0 then
+n"server.lua: we need to do tls, but delaying until send buffer empty"
+L=true
 return
 end
-i("server.lua: attempting to start tls on "..r(t))
-local n,u=t
-t,u=be(t,g)
+n("server.lua: attempting to start tls on "..l(t))
+local c,m=t
+t,m=ye(t,g)
 if not t then
-i("server.lua: error while starting tls on client: ",r(u or"unknown error"))
-return nil,u
+n("server.lua: error while starting tls on client: ",l(m or"unknown error"))
+return nil,m
 end
 t:settimeout(0)
-w=t.send
-z=t.receive
-q=V
-s[t]=e
-a=m(h,t,a)
-a=d(h,n,a)
-o=d(l,n,o)
-s[n]=nil
+y=t.send
+_=t.receive
+q=I
+h[t]=e
+a=u(i,t,a)
+a=s(i,c,a)
+o=s(r,c,o)
+h[c]=nil
 e.starttls=nil
-D=nil
-Y=true
-e.readbuffer=c
-e.sendbuffer=c
-return c(t)
-end
-end
-e.readbuffer=v
-e.sendbuffer=y
-w=t.send
-z=t.receive
-q=(Y and V)or t.shutdown
-s[t]=e
-a=m(h,t,a)
-if g and U then
-i"server.lua: auto-starting ssl negotiation..."
+L=nil
+V=true
+e.readbuffer=d
+e.sendbuffer=d
+return d(t)
+end
+end
+e.readbuffer=p
+e.sendbuffer=v
+y=t.send
+_=t.receive
+q=(V and I)or t.shutdown
+h[t]=e
+a=u(i,t,a)
+if g and O then
+n"server.lua: auto-starting ssl negotiation..."
 e.autostart_ssl=true;
-local e,t=e:starttls(g);
-if e==false then
-return nil,nil,t
+local t,e=e:starttls(g);
+if t==false then
+return nil,nil,e
 end
 end
 return e,t
 end
-V=function()
-end
-B=function()
+I=function()
+end
+G=function()
 return false
 end
-m=function(a,t,e)
-if not a[t]then
+u=function(t,a,e)
+if not t[a]then
 e=e+1
-a[e]=t
-a[t]=e
-end
-return e;
-end
-d=function(e,a,t)
-local i=e[a]
-if i then
-e[a]=nil
+t[e]=a
+t[a]=e
+end
+return e;
+end
+s=function(e,i,t)
+local a=e[i]
+if a then
+e[i]=nil
 local o=e[t]
 e[t]=nil
-if o~=a then
-e[o]=i
-e[i]=o
+if o~=i then
+e[o]=a
+e[a]=o
 end
 return t-1
 end
 return t
 end
-G=function(e)
-o=d(l,e,o)
-a=d(h,e,a)
-s[e]=nil
+Q=function(e)
+o=s(r,e,o)
+a=s(i,e,a)
+h[e]=nil
 e:close()
 end
 local function x(e,t,o)
@@ -2356,342 +2286,425 @@
 end
 e:set_mode("*a");
 end
-re=function(e,t,d,l,r)
-e=e or"*"
+ie=function(t,e,d,l,r)
+t=t or"*"
 local o
-if w(d)~="table"then
+if f(d)~="table"then
 o="invalid listener table"
-elseif w(e)~="string"then
+elseif f(t)~="string"then
 o="invalid address"
-elseif w(t)~="number"or not(t>=0 and t<=65535)then
+elseif f(e)~="number"or not(e>=0 and e<=65535)then
 o="invalid port"
-elseif v[e..":"..t]then
-o="listeners on '["..e.."]:"..t.."' already exist"
-elseif r and not U then
+elseif p[t..":"..e]then
+o="listeners on '["..t.."]:"..e.."' already exist"
+elseif r and not O then
 o="luasec not found"
 end
 if o then
-L("server.lua, [",e,"]:",t,": ",o)
+E("server.lua, [",t,"]:",e,": ",o)
 return nil,o
 end
-local o,n=de(e,t,j)
-if n then
-L("server.lua, [",e,"]:",t,": ",n)
-return nil,n
-end
-local n,d=te(d,o,e,t,l,r)
-if not n then
+local o,s=te(t,e,j)
+if s then
+E("server.lua, [",t,"]:",e,": ",s)
+return nil,s
+end
+local s,d=ne(d,o,t,e,l,r)
+if not s then
 o:close()
 return nil,d
 end
 o:settimeout(0)
-a=m(h,o,a)
-v[e..":"..t]=n
-s[o]=n
-i("server.lua: new "..(r and"ssl "or"").."server listener on '[",e,"]:",t,"'")
-return n
-end
-ae=function(t,e)
-return v[t..":"..e];
+a=u(i,o,a)
+p[t..":"..e]=s
+h[o]=s
+n("server.lua: new "..(r and"ssl "or"").."server listener on '[",t,"]:",e,"'")
+return s
 end
 se=function(t,e)
-local a=v[t..":"..e]
+return p[t..":"..e];
+end
+le=function(t,e)
+local a=p[t..":"..e]
 if not a then
-return nil,"no server found on '["..t.."]:"..r(e).."'"
+return nil,"no server found on '["..t.."]:"..l(e).."'"
 end
 a:close()
-v[t..":"..e]=nil
+p[t..":"..e]=nil
 return true
 end
-K=function()
-for t,e in D(s)do
-e:close()
-s[t]=nil
+J=function()
+for e,t in b(h)do
+t:close()
+h[e]=nil
 end
 a=0
 o=0
-g=0
-v={}
+q=0
+p={}
+i={}
+r={}
+P={}
 h={}
-l={}
-F={}
-s={}
-end
-ie=function()
+end
+oe=function()
 return{
-select_timeout=I;
-select_sleep_time=O;
+select_timeout=A;
 tcp_backlog=j;
-max_send_buffer_size=E;
-max_receive_buffer_size=T;
-select_idle_check_interval=N;
-send_timeout=H;
-read_timeout=S;
-max_connections=q;
-max_ssl_handshake_roundtrips=R;
-highest_allowed_fd=z;
-accept_retry_interval=A;
+max_send_buffer_size=H;
+max_receive_buffer_size=S;
+select_idle_check_interval=R;
+send_timeout=D;
+read_timeout=L;
+max_connections=z;
+max_ssl_handshake_roundtrips=U;
+highest_allowed_fd=_;
+accept_retry_interval=N;
 }
 end
-ne=function(e)
-if w(e)~="table"then
+de=function(e)
+if f(e)~="table"then
 return nil,"invalid settings table"
 end
-I=f(e.select_timeout)or I
-O=f(e.select_sleep_time)or O
-E=f(e.max_send_buffer_size)or E
-T=f(e.max_receive_buffer_size)or T
-N=f(e.select_idle_check_interval)or N
-j=f(e.tcp_backlog)or j
-H=f(e.send_timeout)or H
-S=f(e.read_timeout)or S
-A=f(e.accept_retry_interval)or A
-q=e.max_connections or q
-R=e.max_ssl_handshake_roundtrips or R
-z=e.highest_allowed_fd or z
+A=y(e.select_timeout)or A
+H=y(e.max_send_buffer_size)or H
+S=y(e.max_receive_buffer_size)or S
+R=y(e.select_idle_check_interval)or R
+j=y(e.tcp_backlog)or j
+D=y(e.send_timeout)or D
+L=y(e.read_timeout)or L
+N=y(e.accept_retry_interval)or N
+z=e.max_connections or z
+U=e.max_ssl_handshake_roundtrips or U
+_=e.highest_allowed_fd or _
+return true
+end
+X=function(e)
+if f(e)~="function"then
+return nil,"invalid listener function"
+end
+q=q+1
+P[q]=e
 return true
 end
-oe=function(e)
-if w(e)~="function"then
-return nil,"invalid listener function"
-end
-g=g+1
-F[g]=e
-return true
-end
-le=function()
-return M,W,a,o,g
-end
-local t;
-local function f(e)
-t=not not e;
-end
-P=function(a)
-if t then return"quitting";end
-if a then t="once";end
-local e=ue;
+local l do
+local a={};
+local e={};
+function l(t,a)
+local o=F();
+t=t+o;
+if t>=o then
+he(e,{t,a});
+else
+local e=a(o);
+if e and f(e)=="number"then
+return l(e,a);
+end
+end
+end
+X(function(t)
+if#e>0 then
+for o,t in b(e)do
+he(a,t);
+end
+e={};
+end
+local e=re;
+for n,o in b(a)do
+local i,o=o[1],o[2];
+if i<=t then
+a[n]=nil;
+local t=o(t);
+if f(t)=="number"then
+l(t,o);
+e=Y(e,t);
+end
+else
+e=Y(e,i-t);
+end
+end
+return e;
+end);
+end
+ae=function()
+return M,C,a,o,q
+end
+local e;
+local function p(t)
+e=t;
+end
+B=function(t)
+if e then return"quitting";end
+if t then e="once";end
+d=F()
 repeat
-local o,a,h=ce(h,l,Z(I,e))
-for e,t in ee(a)do
-local e=s[t]
-if e then
-e.sendbuffer()
-else
-G(t)
-i"server.lua: found no handler and closed socket (writelist)"
-end
-end
-for e,t in ee(o)do
-local e=s[t]
-if e then
-e.readbuffer()
-else
-G(t)
-i"server.lua: found no handler and closed socket (readlist)"
-end
-end
-for e,t in D(_)do
+local t=re;
+for e=1,q do
+local e=P[e](d)
+if e then t=Y(t,e);end
+end
+local t,a,o=ve(i,r,Y(A,t))
+for t,e in ue(t)do
+local t=h[e]
+if t then
+t.readbuffer()
+else
+Q(e)
+n"server.lua: found no handler and closed socket (readlist)"
+end
+end
+for t,e in ue(a)do
+local t=h[e]
+if t then
+t.sendbuffer()
+else
+Q(e)
+n"server.lua: found no handler and closed socket (writelist)"
+end
+end
+for e,t in b(T)do
 e.disconnect()(e,t)
 e:force_close()
-_[e]=nil;
-end
-n=X()
-if n-J>N then
-J=n
-for e,t in D(y)do
-if n-t>H then
+T[e]=nil;
+end
+d=F()
+if d-K>R then
+K=d
+for e,t in b(w)do
+if d-t>D then
 e.disconnect()(e,"send timeout")
 e:force_close()
 end
 end
-for e,t in D(b)do
-if n-t>S then
+for e,t in b(v)do
+if d-t>L then
 if not(e.onreadtimeout)or e:onreadtimeout()~=true then
 e.disconnect()(e,"read timeout")
 e:close()
 else
-b[e]=n
-end
-end
-end
-end
-if n-C>=Z(e,1)then
-e=ue;
-for t=1,g do
-local t=F[t](n)
-if t then e=Z(e,t);end
-end
-C=n
-else
-e=e-(n-C);
-end
-for e,t in D(k)do
-if n-t>A then
+v[e]=d
+end
+end
+end
+end
+for e,t in b(k)do
+if d-t>N then
 k[e]=nil;
 e.resume();
 end
 end
-ve(O)
-until t;
-if a and t=="once"then t=nil;return;end
-K();
+until e;
+if e=="once"then e=nil;return;end
+J();
 return"quitting"
 end
-local function u()
-return P(true);
-end
-local function d()
+local function k()
+return B(true);
+end
+local function y()
 return"select";
 end
-local i=function(e,a,h,t,n,i)
-local e,a,n=Q(nil,t,e,a,h,"clientport",n,i)
-if not e then return nil,n end
-s[a]=e
-if not i then
-o=m(l,a,o)
-if t.onconnect then
-local a=e.sendbuffer;
+local c=function(l,e,t,n,d,s)
+local e,t,d=Z(nil,n,l,e,t,"clientport",d,s)
+if not e then return nil,d end
+h[t]=e
+if not s then
+a=u(i,t,a)
+o=u(r,t,o)
+if n.onconnect then
+local t=e.sendbuffer;
 e.sendbuffer=function()
-e.sendbuffer=a;
-t.onconnect(e);
-return a();
-end
-end
-end
-return e,a
-end
-local o=function(o,t,s,r,n,a)
+e.sendbuffer=t;
+n.onconnect(e);
+return t();
+end
+end
+end
+return e,t
+end
+local b=function(a,t,n,s,i,o)
 local e
-if w(s)~="table"then
+if f(n)~="table"then
 e="invalid listener table"
-elseif w(o)~="string"then
+elseif f(a)~="string"then
 e="invalid address"
-elseif w(t)~="number"or not(t>=0 and t<=65535)then
+elseif f(t)~="number"or not(t>=0 and t<=65535)then
 e="invalid port"
-elseif n and not U then
+elseif i and not O then
 e="luasec not found"
 end
-if not a then
-local e,t=pe(o)
+if ee and not o then
+local e,t=ee(a)
 if not e then return nil,t end
 if e[1]and e[1].family=="inet6"then
-a="tcp6"
-else
-a="tcp"
-end
-end
-local a=p[a]
-if w(a)~="function"then
+o="tcp6"
+end
+end
+local o=g[o or"tcp"]
+if f(o)~="function"then
 e="invalid socket type"
 end
 if e then
-L("server.lua, addclient: ",e)
+E("server.lua, addclient: ",e)
 return nil,e
 end
-local e,a=a()
-if a then
-return nil,a
+local e,o=o()
+if o then
+return nil,o
 end
 e:settimeout(0)
-local h,a=e:connect(o,t)
-if h or a=="timeout"then
-return i(e,o,t,s,r,n)
-else
-return nil,a
-end
-end
-c"setmetatable"(s,{__mode="k"})
-c"setmetatable"(b,{__mode="k"})
-c"setmetatable"(y,{__mode="k"})
-C=X()
-J=X()
+local h,o=e:connect(a,t)
+if h or o=="timeout"or o=="Operation already in progress"then
+return c(e,a,t,n,s,i)
+else
+return nil,o
+end
+end
+local g=function(e)
+local e=e.conn;
+o=s(r,e,o)
+a=s(i,e,a)
+h[e]=nil
+end;
+local t=function(n,t,d)
+local e=n.conn
+h[e]=n
+if t~=nil then
+if t then
+a=u(i,e,a)
+else
+o=s(r,e,o)
+end
+end
+if d~=nil then
+if d then
+o=u(r,e,o)
+else
+a=s(i,e,a)
+end
+end
+end
+local t=function(e,o,a)
+local i=e
+if f(e)=="number"then
+i={getfd=function()return e;end}
+end
+local e={
+conn=i;
+readbuffer=o or I;
+sendbuffer=a or I;
+close=g;
+setflags=t;
+};
+t(e,o,a)
+return e
+end
+m"setmetatable"(h,{__mode="k"})
+m"setmetatable"(v,{__mode="k"})
+m"setmetatable"(w,{__mode="k"})
+K=F()
 local function a(e)
-local t=Y;
+local t=W;
 if e then
-Y=e;
+W=e;
 end
 return t;
 end
 return{
-_addtimer=oe,
-addclient=o,
-wrapclient=i,
-loop=P,
+_addtimer=X,
+add_task=l;
+addclient=b,
+wrapclient=c,
+watchfd=t,
+loop=B,
 link=x,
-step=u,
-stats=le,
-closeall=K,
-addserver=re,
-getserver=ae,
+step=k,
+stats=ae,
+closeall=J,
+addserver=ie,
+getserver=se,
 setlogger=a,
-getsettings=ie,
-setquitting=f,
-removeserver=se,
-get_backend=d,
-changesettings=ne,
+getsettings=oe,
+setquitting=p,
+removeserver=le,
+get_backend=y,
+changesettings=de,
 }
 end)
 package.preload['util.xmppstream']=(function(...)
+local _ENV=_ENV;
+local function o(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local e=require"lxp";
-local b=require"util.stanza";
-local k=b.stanza_mt;
-local m=error;
+local t=require"util.stanza";
+local p=t.stanza_mt;
+local f=error;
 local t=tostring;
-local d=table.insert;
-local p=table.concat;
-local x=table.remove;
-local v=setmetatable;
-local q=pcall(e.new,{StartDoctypeDecl=false});
-local j=pcall(e.new,{XmlDecl=false});
+local l=table.insert;
+local w=table.concat;
+local T=table.remove;
+local y=setmetatable;
+local x=pcall(e.new,{StartDoctypeDecl=false});
+local z=pcall(e.new,{XmlDecl=false});
 local a=not not e.new({}).getcurrentbytecount;
-local z=1024*1024*10;
-local o=nil;
-local y=e.new;
-local _={
+local _=1024*1024*10;
+o"xmppstream"
+local k=e.new;
+local E={
 ["http://www.w3.org/XML/1998/namespace\1lang"]="xml:lang";
 ["http://www.w3.org/XML/1998/namespace\1space"]="xml:space";
 ["http://www.w3.org/XML/1998/namespace\1base"]="xml:base";
 ["http://www.w3.org/XML/1998/namespace\1id"]="xml:id";
 };
-local s="http://etherx.jabber.org/streams";
-local r="\1";
-local g="^([^"..r.."]*)"..r.."?(.*)$";
-local function h()end
-local function w(i,e,n)
-local o={};
-local w=e.streamopened;
-local f=e.streamclosed;
-local l=e.error or function(o,a,e)m("XML stream error: "..t(a)..(e and": "..t(e)or""),2);end;
-local y=e.handlestanza;
-n=n or h;
-local t=e.stream_ns or s;
-local c=e.stream_tag or"stream";
+local o="http://etherx.jabber.org/streams";
+local d="\1";
+local b="^([^"..d.."]*)"..d.."?(.*)$";
+_M.ns_separator=d;
+_M.ns_pattern=b;
+local function s()end
+function new_sax_handlers(n,e,h)
+local i={};
+local g=e.streamopened;
+local v=e.streamclosed;
+local u=e.error or function(o,a,e)f("XML stream error: "..t(a)..(e and": "..t(e)or""),2);end;
+local k=e.handlestanza;
+h=h or s;
+local t=e.stream_ns or o;
+local m=e.stream_tag or"stream";
 if t~=""then
-c=t..r..c;
-end
-local b=t..r..(e.error_tag or"error");
-local z=e.default_ns;
-local u={};
+m=t..d..m;
+end
+local q=t..d..(e.error_tag or"error");
+local j=e.default_ns;
+local d={};
 local s,e={};
 local t=0;
-local h=0;
-function o:StartElement(m,o)
+local r=0;
+function i:StartElement(c,o)
 if e and#s>0 then
-d(e,p(s));
+l(e,w(s));
 s={};
 end
-local r,s=m:match(g);
-if s==""then
-r,s="",r;
-end
-if r~=z or h>0 then
-o.xmlns=r;
-h=h+1;
+local s,i=c:match(b);
+if i==""then
+s,i="",s;
+end
+if s~=j or r>0 then
+o.xmlns=s;
+r=r+1;
 end
 for t=1,#o do
 local e=o[t];
 o[t]=nil;
-local t=_[e];
+local t=E[e];
 if t then
 o[t]=o[e];
 o[e]=nil;
@@ -2701,481 +2714,408 @@
 if a then
 t=self:getcurrentbytecount();
 end
-if i.notopen then
-if m==c then
-h=0;
-if w then
+if n.notopen then
+if c==m then
+r=0;
+if g then
 if a then
-n(t);
+h(t);
 t=0;
 end
-w(i,o);
-end
-else
-l(i,"no-stream",m);
+g(n,o);
+end
+else
+u(n,"no-stream",c);
 end
 return;
 end
-if r=="jabber:client"and s~="iq"and s~="presence"and s~="message"then
-l(i,"invalid-top-level-element");
-end
-e=v({name=s,attr=o,tags={}},k);
+if s=="jabber:client"and i~="iq"and i~="presence"and i~="message"then
+u(n,"invalid-top-level-element");
+end
+e=y({name=i,attr=o,tags={}},p);
 else
 if a then
 t=t+self:getcurrentbytecount();
 end
-d(u,e);
+l(d,e);
 local t=e;
-e=v({name=s,attr=o,tags={}},k);
-d(t,e);
-d(t.tags,e);
-end
-end
-if j then
-function o:XmlDecl(e,e,e)
+e=y({name=i,attr=o,tags={}},p);
+l(t,e);
+l(t.tags,e);
+end
+end
+if z then
+function i:XmlDecl(e,e,e)
 if a then
-n(self:getcurrentbytecount());
-end
-end
-end
-function o:StartCdataSection()
+h(self:getcurrentbytecount());
+end
+end
+end
+function i:StartCdataSection()
 if a then
 if e then
 t=t+self:getcurrentbytecount();
 else
-n(self:getcurrentbytecount());
-end
-end
-end
-function o:EndCdataSection()
+h(self:getcurrentbytecount());
+end
+end
+end
+function i:EndCdataSection()
 if a then
 if e then
 t=t+self:getcurrentbytecount();
 else
-n(self:getcurrentbytecount());
-end
-end
-end
-function o:CharacterData(o)
+h(self:getcurrentbytecount());
+end
+end
+end
+function i:CharacterData(o)
 if e then
 if a then
 t=t+self:getcurrentbytecount();
 end
-d(s,o);
+l(s,o);
 elseif a then
-n(self:getcurrentbytecount());
-end
-end
-function o:EndElement(o)
+h(self:getcurrentbytecount());
+end
+end
+function i:EndElement(o)
 if a then
 t=t+self:getcurrentbytecount()
 end
-if h>0 then
-h=h-1;
+if r>0 then
+r=r-1;
 end
 if e then
 if#s>0 then
-d(e,p(s));
+l(e,w(s));
 s={};
 end
-if#u==0 then
+if#d==0 then
 if a then
-n(t);
+h(t);
 end
 t=0;
-if o~=b then
-y(i,e);
-else
-l(i,"stream-error",e);
+if o~=q then
+k(n,e);
+else
+u(n,"stream-error",e);
 end
 e=nil;
 else
-e=x(u);
-end
-else
-if f then
-f(i);
+e=T(d);
+end
+else
+if v then
+v(n);
 end
 end
 end
 local function a(e)
-l(i,"parse-error","restricted-xml","Restricted XML, see RFC 6120 section 11.1.");
+u(n,"parse-error","restricted-xml","Restricted XML, see RFC 6120 section 11.1.");
 if not e.stop or not e:stop()then
-m("Failed to abort parsing");
-end
-end
-if q then
-o.StartDoctypeDecl=a;
-end
-o.Comment=a;
-o.ProcessingInstruction=a;
+f("Failed to abort parsing");
+end
+end
+if x then
+i.StartDoctypeDecl=a;
+end
+i.Comment=a;
+i.ProcessingInstruction=a;
 local function a()
 e,s,t=nil,{},0;
-u={};
-end
-local function t(t,e)
-i=e;
-end
-return o,{reset=a,set_session=t};
-end
-local function u(d,l,o)
-local t=0;
-local e;
+d={};
+end
+local function e(t,e)
+n=e;
+end
+return i,{reset=a,set_session=e};
+end
+function new(n,i,o)
+local e=0;
+local t;
 if a then
-function e(e)
-t=t-e;
-end
-o=o or z;
+function t(t)
+e=e-t;
+end
+o=o or _;
 elseif o then
-m("Stanza size limits are not supported on this version of LuaExpat")
-end
-local n,s=w(d,l,e);
-local i=y(n,r,false);
-local h=i.parse;
-function d.open_stream(e,a,i)
-local o=e.sends2s or e.send;
-local t={
-["xmlns:stream"]="http://etherx.jabber.org/streams",
-["xml:lang"]="en",
-xmlns=l.default_ns,
-version=e.version and(e.version>0 and"1.0"or nil),
-id=e.streamid,
-from=a or e.host,to=i,
-};
-if e.stream_attrs then
-e:stream_attrs(a,i,t)
-end
-o("<?xml version='1.0'?>");
-o(b.stanza("stream:stream",t):top_tag());
-return true;
-end
+f("Stanza size limits are not supported on this version of LuaExpat")
+end
+local i,n=new_sax_handlers(n,i,t);
+local t=k(i,d,false);
+local s=t.parse;
 return{
 reset=function()
-i=y(n,r,false);
-h=i.parse;
-t=0;
-s.reset();
+t=k(i,d,false);
+s=t.parse;
+e=0;
+n.reset();
 end,
-feed=function(n,e)
+feed=function(n,i)
 if a then
-t=t+#e;
-end
-local i,e=h(i,e);
-if a and t>o then
+e=e+#i;
+end
+local i,t=s(t,i);
+if a and e>o then
 return nil,"stanza-too-large";
 end
-return i,e;
+return i,t;
 end,
-set_session=s.set_session;
+set_session=n.set_session;
 };
 end
-return{
-ns_separator=r;
-ns_pattern=g;
-new_sax_handlers=w;
-new=u;
-};
+return _M;
 end)
 package.preload['util.jid']=(function(...)
-local o=select;
-local a,i=string.match,string.sub;
+local _ENV=_ENV;
+local function a(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local t,s=string.match,string.sub;
 local l=require"util.encodings".stringprep.nodeprep;
-local r=require"util.encodings".stringprep.nameprep;
-local d=require"util.encodings".stringprep.resourceprep;
-local h={
+local d=require"util.encodings".stringprep.nameprep;
+local r=require"util.encodings".stringprep.resourceprep;
+local n={
 [" "]="\\20";['"']="\\22";
 ["&"]="\\26";["'"]="\\27";
 ["/"]="\\2f";[":"]="\\3a";
 ["<"]="\\3c";[">"]="\\3e";
 ["@"]="\\40";["\\"]="\\5c";
 };
-local s={};
-for e,t in pairs(h)do s[t]=e;end
-local e=nil;
-local function t(e)
+local i={};
+for e,t in pairs(n)do i[t]=e;end
+a"jid"
+local function o(e)
 if not e then return;end
-local i,t=a(e,"^([^@/]+)@()");
-local t,o=a(e,"^([^@/]+)()",t)
-if i and not t then return nil,nil,nil;end
-local a=a(e,"^/(.+)$",o);
-if(not t)or((not a)and#e>=o)then return nil,nil,nil;end
-return i,t,a;
-end
-local function m(e)
-local t,e=t(e);
+local i,a=t(e,"^([^@/]+)@()");
+local a,o=t(e,"^([^@/]+)()",a)
+if i and not a then return nil,nil,nil;end
+local t=t(e,"^/(.+)$",o);
+if(not a)or((not t)and#e>=o)then return nil,nil,nil;end
+return i,a,t;
+end
+split=o;
+function bare(e)
+local t,e=o(e);
 if t and e then
 return t.."@"..e;
 end
 return e;
 end
-local function n(e)
-local t,e,a=t(e);
-if e and e~="."then
-if i(e,-1,-1)=="."then
-e=i(e,1,-2);
-end
-e=r(e);
+local function h(e)
+local a,e,t=o(e);
+if e then
+if s(e,-1,-1)=="."then
+e=s(e,1,-2);
+end
+e=d(e);
 if not e then return;end
-if t then
-t=l(t);
-if not t then return;end
-end
 if a then
-a=d(a);
+a=l(a);
 if not a then return;end
 end
-return t,e,a;
-end
-end
-local function i(a,e,t)
-if not e then return end
-if a and t then
+if t then
+t=r(t);
+if not t then return;end
+end
+return a,e,t;
+end
+end
+prepped_split=h;
+function prep(e)
+local a,e,t=h(e);
+if e then
+if a then
+e=a.."@"..e;
+end
+if t then
+e=e.."/"..t;
+end
+end
+return e;
+end
+function join(a,e,t)
+if a and e and t then
 return a.."@"..e.."/"..t;
-elseif a then
+elseif a and e then
 return a.."@"..e;
-elseif t then
+elseif e and t then
 return e.."/"..t;
-end
-return e;
-end
-local function c(e)
-local a,t,e=n(e);
-return i(a,t,e);
-end
-local function u(e,a)
-local o,n,i=t(e);
-local e,t,a=t(a);
-if((e~=nil and e==o)or e==nil)and
-((t~=nil and t==n)or t==nil)and
-((a~=nil and a==i)or a==nil)then
+elseif e then
+return e;
+end
+return nil;
+end
+function compare(t,e)
+local n,i,s=o(t);
+local a,t,e=o(e);
+if((a~=nil and a==n)or a==nil)and
+((t~=nil and t==i)or t==nil)and
+((e~=nil and e==s)or e==nil)then
 return true
 end
 return false
 end
-local function l(e)
-return(o(1,t(e)));
-end
-local function d(e)
-return(o(2,t(e)));
-end
-local function r(e)
-return(o(3,t(e)));
-end
-local function a(e)return e and(e:gsub(".",h));end
-local function o(e)return e and(e:gsub("\\%x%x",s));end
-return{
-split=t;
-bare=m;
-prepped_split=n;
-join=i;
-prep=c;
-compare=u;
-node=l;
-host=d;
-resource=r;
-escape=a;
-unescape=o;
-};
+function escape(e)return e and(e:gsub(".",n));end
+function unescape(e)return e and(e:gsub("\\%x%x",i));end
+return _M;
 end)
 package.preload['util.events']=(function(...)
-local a=pairs;
-local s=table.insert;
-local l=table.remove;
-local r=table.sort;
-local d=setmetatable;
-local h=next;
-local e=nil;
-local function u()
-local o={};
-local t;
-local n={};
-local i={};
-local function u(n,o)
-local e=i[o];
-if not e or h(e)==nil then return;end
+local _ENV=_ENV;
+local function a(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local i=pairs;
+local r=table.insert;
+local s=table.sort;
+local h=setmetatable;
+local n=next;
+a"events"
+function new()
 local t={};
-for e in a(e)do
-s(t,e);
-end
-r(t,function(a,t)return e[a]>e[t];end);
-n[o]=t;
+local e={};
+local function o(o,a)
+local e=e[a];
+if not e or n(e)==nil then return;end
+local t={};
+for e in i(e)do
+r(t,e);
+end
+s(t,function(a,t)return e[a]>e[t];end);
+o[a]=t;
 return t;
 end;
-d(o,{__index=u});
-local function s(t,n,a)
-local e=i[t];
-if e then
-e[n]=a or 0;
-else
-e={[n]=a or 0};
-i[t]=e;
-end
-o[t]=nil;
+h(t,{__index=o});
+local function h(o,i,n)
+local a=e[o];
+if a then
+a[i]=n or 0;
+else
+a={[i]=n or 0};
+e[o]=a;
+end
+t[o]=nil;
 end;
-local function r(e,a)
-local t=i[e];
-if t then
-t[a]=nil;
-o[e]=nil;
-if h(t)==nil then
-i[e]=nil;
+local function s(o,i)
+local a=e[o];
+if a then
+a[i]=nil;
+t[o]=nil;
+if n(a)==nil then
+e[o]=nil;
 end
 end
 end;
-local function m(e)
-return o[e];
-end;
-local function f(e)
-for e,t in a(e)do
-s(e,t);
+local function n(e)
+for t,e in i(e)do
+h(t,e);
 end
 end;
-local function c(e)
-for t,e in a(e)do
-r(t,e);
+local function a(e)
+for t,e in i(e)do
+s(t,e);
 end
 end;
-local function h(e,t)
-local e=o[e];
+local function o(e,...)
+local e=t[e];
 if e then
-for a=1,#e do
-local e=e[a](t);
+for t=1,#e do
+local e=e[t](...);
 if e~=nil then return e;end
 end
 end
 end;
-local function u(i,s)
-local a=n[i]or t;
-if a then
-local e=#a;
-local function n(i,o)
-e=e-1;
-if e==0 then
-if t==nil or a==t then
-return h(i,o);
-end
-a,e=t,#t;
-return a[e](n,i,o);
-else
-return a[e](n,i,o);
-end
-end
-return a[e](n,i,s);
-end
-return h(i,s);
-end
-local function d(a,o)
-local e;
-if a==false then
-e=t;
-if not e then
-e={};
-t=e;
-end
-else
-e=n[a];
-if not e then
-e={};
-n[a]=e;
-end
-end
-e[#e+1]=o;
-end
-local function h(a,o)
-local e;
-if a==false then
-e=t;
-else
-e=n[a];
-end
-if not e then return;end
-for t=#e,1 do
-if e[t]==o then
-l(e,t);
-end
-end
-if#e==0 then
-if a==false then
-t=nil;
-else
-n[a]=nil;
-end
-end
-end
 return{
-add_handler=s;
-remove_handler=r;
-add_handlers=f;
-remove_handlers=c;
-get_handlers=m;
-wrappers={
-add_handler=d;
-remove_handler=h;
+add_handler=h;
+remove_handler=s;
+add_handlers=n;
+remove_handlers=a;
+fire_event=o;
+_handlers=t;
+_event_map=e;
 };
-add_wrapper=d;
-remove_wrapper=h;
-fire_event=u;
-_handlers=o;
-_event_map=i;
-};
-end
-return{
-new=u;
-};
+end
+return _M;
 end)
 package.preload['util.dataforms']=(function(...)
-local e=setmetatable;
-local t,i=pairs,ipairs;
-local d,r,u=tostring,type,next;
-local h=table.concat;
-local m=require"util.stanza";
-local l=require"util.jid".prep;
+local _ENV=_ENV;
+local function o(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local a=setmetatable;
+local e,i=pairs,ipairs;
+local h,r,c=tostring,type,next;
+local s=table.concat;
+local u=require"util.stanza";
+local d=require"util.jid".prep;
+o"dataforms"
+local l='jabber:x:data';
 local n={};
-local c='jabber:x:data';
-local s={};
-local a={__index=s};
-function n.new(t)
-return e(t,a);
-end
-function n.from_stanza(e)
+local e={__index=n};
+function new(t)
+return a(t,e);
+end
+function from_stanza(e)
 local o={
 title=e:get_child_text("title");
 instructions=e:get_child_text("instructions");
 };
-for e in e:childtags("field")do
+for t in e:childtags("field")do
 local a={
-name=e.attr.var;
-label=e.attr.label;
-type=e.attr.type;
-required=e:get_child("required")and true or nil;
-value=e:get_child_text("value");
+name=t.attr.var;
+label=t.attr.label;
+type=t.attr.type;
+required=t:get_child("required")and true or nil;
+value=t:get_child_text("value");
 };
 o[#o+1]=a;
 if a.type then
-local t={};
+local e={};
 if a.type:match"list%-"then
-for e in e:childtags("option")do
-t[#t+1]={label=e.attr.label,value=e:get_child_text("value")};
-end
-for e in e:childtags("value")do
-t[#t+1]={label=e.attr.label,value=e:get_text(),default=true};
+for t in t:childtags("option")do
+e[#e+1]={label=t.attr.label,value=t:get_child_text("value")};
+end
+for t in t:childtags("value")do
+e[#e+1]={label=t.attr.label,value=t:get_text(),default=true};
 end
 elseif a.type:match"%-multi"then
-for e in e:childtags("value")do
-t[#t+1]=e.attr.label and{label=e.attr.label,value=e:get_text()}or e:get_text();
+for t in t:childtags("value")do
+e[#e+1]=t.attr.label and{label=t.attr.label,value=t:get_text()}or t:get_text();
 end
 if a.type=="text-multi"then
-a.value=h(t,"\n");
-else
-a.value=t;
+a.value=s(e,"\n");
+else
+a.value=e;
 end
 end
 end
 end
 return new(o);
 end
-function s.form(t,n,e)
-local e=m.stanza("x",{xmlns=c,type=e or"form"});
+function n.form(t,n,e)
+local e=u.stanza("x",{xmlns=l,type=e or"form"});
 if t.title then
 e:tag("title"):text(t.title):up();
 end
@@ -3193,7 +3133,7 @@
 :add_child(t)
 :up();
 else
-e:tag("value"):text(d(t)):up();
+e:tag("value"):text(h(t)):up();
 end
 elseif a=="boolean"then
 e:tag("value"):text((t and"1")or"0"):up();
@@ -3220,7 +3160,7 @@
 a=true;
 end
 else
-e:tag("option",{label=t}):tag("value"):text(d(t)):up():up();
+e:tag("option",{label=t}):tag("value"):text(h(t)):up():up();
 end
 end
 elseif a=="list-multi"then
@@ -3231,7 +3171,7 @@
 e:tag("value"):text(t.value):up();
 end
 else
-e:tag("option",{label=t}):tag("value"):text(d(t)):up():up();
+e:tag("option",{label=t}):tag("value"):text(h(t)):up():up();
 end
 end
 end
@@ -3244,7 +3184,7 @@
 return e;
 end
 local e={};
-function s.data(t,n)
+function n.data(t,n)
 local o={};
 local a={};
 for i,t in i(t)do
@@ -3266,7 +3206,7 @@
 end
 end
 end
-if u(a)then
+if c(a)then
 return o,a;
 end
 return o;
@@ -3285,7 +3225,7 @@
 e["jid-single"]=
 function(t,o)
 local t=t:get_child_text("value")
-local a=l(t);
+local a=d(t);
 if a and#a>0 then
 return a
 elseif t then
@@ -3300,14 +3240,14 @@
 local t={};
 for e in o:childtags("value")do
 local e=e:get_text();
-local o=l(e);
+local o=d(e);
 a[#a+1]=o;
 if e and not o then
 t[#t+1]=("Invalid JID: "..e);
 end
 end
 if#a>0 then
-return a,(#t>0 and h(t,"\n")or nil);
+return a,(#t>0 and s(t,"\n")or nil);
 elseif i then
 return nil,"Required value missing";
 end
@@ -3324,7 +3264,7 @@
 function(t,a)
 local t,a=e["list-multi"](t,a);
 if t then
-t=h(t,"\n");
+t=s(t,"\n");
 end
 return t,a;
 end
@@ -3350,24 +3290,35 @@
 function(e)
 return e:get_child_text("value");
 end
-return n;
+return _M;
 end)
 package.preload['util.caps']=(function(...)
-local d=require"util.encodings".base64.encode;
-local l=require"util.hashes".sha1;
+local _ENV=_ENV;
+local function a(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local l=require"util.encodings".base64.encode;
+local d=require"util.hashes".sha1;
 local n,s,h=table.insert,table.sort,table.concat;
 local r=ipairs;
-local e=nil;
-local function u(e)
-local a,i,o={},{},{};
+a"caps"
+function calculate_hash(e)
+local a,o,i={},{},{};
 for t,e in r(e)do
 if e.name=="identity"then
 n(a,(e.attr.category or"").."\0"..(e.attr.type or"").."\0"..(e.attr["xml:lang"]or"").."\0"..(e.attr.name or""));
 elseif e.name=="feature"then
-n(i,e.attr.var or"");
+n(o,e.attr.var or"");
 elseif e.name=="x"and e.attr.xmlns=="jabber:x:data"then
 local t={};
-local i;
+local o;
 for a,e in r(e.tags)do
 if e.name=="field"and e.attr.var then
 local a={};
@@ -3377,7 +3328,7 @@
 end
 s(a);
 if e.attr.var=="FORM_TYPE"then
-i=a[1];
+o=a[1];
 elseif#a>0 then
 n(t,e.attr.var.."\0"..h(a,"<"));
 else
@@ -3387,42 +3338,52 @@
 end
 s(t);
 t=h(t,"<");
-if i then t=i.."\0"..t;end
-n(o,t);
+if o then t=o.."\0"..t;end
+n(i,t);
 end
 end
 s(a);
+s(o);
 s(i);
-s(o);
 if#a>0 then a=h(a,"<"):gsub("%z","/").."<";else a="";end
-if#i>0 then i=h(i,"<").."<";else i="";end
-if#o>0 then o=h(o,"<"):gsub("%z","<").."<";else o="";end
-local e=a..i..o;
-local t=d(l(e));
+if#o>0 then o=h(o,"<").."<";else o="";end
+if#i>0 then i=h(i,"<"):gsub("%z","<").."<";else i="";end
+local e=a..o..i;
+local t=l(d(e));
+print(("CAPS %q %q"):format(t,e));
 return t,e;
 end
-return{
-calculate_hash=u;
-};
+return _M;
 end)
 package.preload['util.vcard']=(function(...)
-local o=require"util.stanza";
-local a,u=table.insert,table.concat;
-local h=type;
-local e,s,m=next,pairs,ipairs;
-local c,d,l,r;
-local f="\n";
-local i;
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local i=require"util.stanza";
+local a,h=table.insert,table.concat;
+local s=type;
+local e,n,c=next,pairs,ipairs;
+local d,r,l,u;
+local m="\n";
+local o;
 local function e()
 error"Not implemented"
 end
 local function e()
 error"Not implemented"
 end
-local function w(e)
+local function y(e)
 return e:gsub("[,:;\\]","\\%1"):gsub("\n","\\n");
 end
-local function n(e)
+local function p(e)
 return e:gsub("\\?[\\nt:;,]",{
 ["\\\\"]="\\",
 ["\\n"]="\n",
@@ -3436,104 +3397,104 @@
 [","]="\31",
 });
 end
-local function y(t)
-local a=o.stanza(t.name,{xmlns="vcard-temp"});
-local e=i[t.name];
-if e=="text"then
-a:text(t[1]);
-elseif h(e)=="table"then
-if e.types and t.TYPE then
-if h(t.TYPE)=="table"then
-for o,e in s(e.types)do
-for o,t in s(t.TYPE)do
-if t:upper()==e then
-a:tag(e):up();
+local function w(e)
+local a=i.stanza(e.name,{xmlns="vcard-temp"});
+local t=o[e.name];
+if t=="text"then
+a:text(e[1]);
+elseif s(t)=="table"then
+if t.types and e.TYPE then
+if s(e.TYPE)=="table"then
+for o,t in n(t.types)do
+for o,e in n(e.TYPE)do
+if e:upper()==t then
+a:tag(t):up();
 break;
 end
 end
 end
 else
-a:tag(t.TYPE:upper()):up();
-end
-end
-if e.props then
-for o,e in s(e.props)do
-if t[e]then
-a:tag(e):up();
-end
-end
-end
-if e.value then
-a:tag(e.value):text(t[1]):up();
-elseif e.values then
-local o=e.values;
+a:tag(e.TYPE:upper()):up();
+end
+end
+if t.props then
+for o,t in n(t.props)do
+if e[t]then
+a:tag(t):up();
+end
+end
+end
+if t.value then
+a:tag(t.value):text(e[1]):up();
+elseif t.values then
+local o=t.values;
 local i=o.behaviour=="repeat-last"and o[#o];
-for o=1,#t do
-a:tag(e.values[o]or i):text(t[o]):up();
+for o=1,#e do
+a:tag(t.values[o]or i):text(e[o]):up();
 end
 end
 end
 return a;
 end
-local function t(e)
-local t=o.stanza("vCard",{xmlns="vcard-temp"});
+local function f(t)
+local e=i.stanza("vCard",{xmlns="vcard-temp"});
+for a=1,#t do
+e:add_child(w(t[a]));
+end
+return e;
+end
+function u(e)
+if not e[1]or e[1].name then
+return f(e)
+else
+local t=i.stanza("xCard",{xmlns="vcard-temp"});
 for a=1,#e do
-t:add_child(y(e[a]));
+t:add_child(f(e[a]));
 end
 return t;
 end
-function r(e)
-if not e[1]or e[1].name then
-return t(e)
-else
-local a=o.stanza("xCard",{xmlns="vcard-temp"});
-for o=1,#e do
-a:add_child(t(e[o]));
-end
-return a;
-end
-end
-function c(t)
+end
+function d(t)
 t=t
 :gsub("\r\n","\n")
 :gsub("\n ","")
 :gsub("\n\n+","\n");
-local h={};
+local s={};
 local e;
 for t in t:gmatch("[^\n]+")do
-local t=n(t);
-local s,t,n=t:match("^([-%a]+)(\30?[^\29]*)\29(.*)$");
-n=n:gsub("\29",":");
+local t=p(t);
+local n,t,i=t:match("^([-%a]+)(\30?[^\29]*)\29(.*)$");
+i=i:gsub("\29",":");
 if#t>0 then
-local a={};
-for e,o,i in t:gmatch("\30([^=]+)(=?)([^\30]*)")do
-e=e:upper();
-local t={};
-for e in i:gmatch("[^\31]+")do
-t[#t+1]=e
-t[e]=true;
-end
-if o=="="then
-a[e]=t;
-else
-a[e]=true;
-end
-end
-t=a;
-end
-if s=="BEGIN"and n=="VCARD"then
+local o={};
+for a,n,i in t:gmatch("\30([^=]+)(=?)([^\30]*)")do
+a=a:upper();
+local e={};
+for t in i:gmatch("[^\31]+")do
+e[#e+1]=t
+e[t]=true;
+end
+if n=="="then
+o[a]=e;
+else
+o[a]=true;
+end
+end
+t=o;
+end
+if n=="BEGIN"and i=="VCARD"then
 e={};
-h[#h+1]=e;
-elseif s=="END"and n=="VCARD"then
+s[#s+1]=e;
+elseif n=="END"and i=="VCARD"then
 e=nil;
-elseif e and i[s]then
-local o=i[s];
-local i={name=s};
-e[#e+1]=i;
+elseif e and o[n]then
+local o=o[n];
+local n={name=n};
+e[#e+1]=n;
 local s=e;
-e=i;
+e=n;
 if o.types then
-for o,a in m(o.types)do
+for o,a in c(o.types)do
 local a=a:lower();
 if(t.TYPE and t.TYPE[a]==true)
 or t[a]==true then
@@ -3542,12 +3503,12 @@
 end
 end
 if o.props then
-for o,a in m(o.props)do
+for o,a in c(o.props)do
 if t[a]then
 if t[a]==true then
 e[a]=true;
 else
-for o,t in m(t[a])do
+for o,t in c(t[a])do
 e[a]=t;
 end
 end
@@ -3555,9 +3516,9 @@
 end
 end
 if o=="text"or o.value then
-a(e,n);
+a(e,i);
 elseif o.values then
-local t="\30"..n;
+local t="\30"..i;
 for t in t:gmatch("\30([^\30]*)")do
 a(e,t);
 end
@@ -3565,82 +3526,82 @@
 e=s;
 end
 end
-return h;
-end
-local function n(e)
-local t={};
-for a=1,#e do
-t[a]=w(e[a]);
-end
-t=u(t,";");
+return s;
+end
+local function i(t)
+local e={};
+for a=1,#t do
+e[a]=y(t[a]);
+end
+e=h(e,";");
 local a="";
-for e,t in s(e)do
-if h(e)=="string"and e~="name"then
-a=a..(";%s=%s"):format(e,h(t)=="table"and u(t,",")or t);
-end
-end
-return("%s%s:%s"):format(e.name,a,t)
-end
-local function o(t)
+for t,e in n(t)do
+if s(t)=="string"and t~="name"then
+a=a..(";%s=%s"):format(t,s(e)=="table"and h(e,",")or e);
+end
+end
+return("%s%s:%s"):format(t.name,a,e)
+end
+local function t(t)
 local e={};
 a(e,"BEGIN:VCARD")
 for o=1,#t do
-a(e,n(t[o]));
+a(e,i(t[o]));
 end
 a(e,"END:VCARD")
-return u(e,f);
-end
-function d(e)
+return h(e,m);
+end
+function r(e)
 if e[1]and e[1].name then
-return o(e)
-else
-local a={};
-for t=1,#e do
-a[t]=o(e[t]);
-end
-return u(a,f);
-end
-end
-local function n(o)
-local t=o.name;
-local e=i[t];
+return t(e)
+else
+local o={};
+for a=1,#e do
+o[a]=t(e[a]);
+end
+return h(o,m);
+end
+end
+local function h(i)
+local t=i.name;
+local e=o[t];
 local t={name=t};
 if e=="text"then
-t[1]=o:get_text();
-elseif h(e)=="table"then
+t[1]=i:get_text();
+elseif s(e)=="table"then
 if e.value then
-t[1]=o:get_child_text(e.value)or"";
+t[1]=i:get_child_text(e.value)or"";
 elseif e.values then
 local e=e.values;
 if e.behaviour=="repeat-last"then
-for e=1,#o.tags do
-a(t,o.tags[e]:get_text()or"");
-end
-else
-for i=1,#e do
-a(t,o:get_child_text(e[i])or"");
+for e=1,#i.tags do
+a(t,i.tags[e]:get_text()or"");
+end
+else
+for o=1,#e do
+a(t,i:get_child_text(e[o])or"");
 end
 end
 elseif e.names then
 local e=e.names;
 for a=1,#e do
-if o:get_child(e[a])then
+if i:get_child(e[a])then
 t[1]=e[a];
 break;
 end
 end
 end
 if e.props_verbatim then
-for e,a in s(e.props_verbatim)do
-t[e]=a;
+for a,e in n(e.props_verbatim)do
+t[a]=e;
 end
 end
 if e.types then
 local e=e.types;
 t.TYPE={};
-for i=1,#e do
-if o:get_child(e[i])then
-a(t.TYPE,e[i]:lower());
+for o=1,#e do
+if i:get_child(e[o])then
+a(t.TYPE,e[o]:lower());
 end
 end
 if#t.TYPE==0 then
@@ -3649,9 +3610,9 @@
 end
 if e.props then
 local e=e.props;
-for i=1,#e do
-local e=e[i]
-local o=o:get_child_text(e);
+for o=1,#e do
+local e=e[o]
+local o=i:get_child_text(e);
 if o then
 t[e]=t[e]or{};
 a(t[e],o);
@@ -3663,11 +3624,11 @@
 end
 return t;
 end
-local function t(e)
+local function i(e)
 local e=e.tags;
 local t={};
 for o=1,#e do
-a(t,n(e[o]));
+a(t,h(e[o]));
 end
 return t
 end
@@ -3677,16 +3638,16 @@
 end
 if e.name=="xCard"then
 local a={};
-local e=e.tags;
-for o=1,#e do
-a[o]=t(e[o]);
+local t=e.tags;
+for e=1,#t do
+a[e]=i(t[e]);
 end
 return a
 elseif e.name=="vCard"then
-return t(e)
-end
-end
-i={
+return i(e)
+end
+end
+o={
 VERSION="text",
 FN="text",
 N={
@@ -3808,159 +3769,188 @@
 },
 DESC="text",
 };
-i.LOGO=i.PHOTO;
-i.SOUND=i.PHOTO;
+o.LOGO=o.PHOTO;
+o.SOUND=o.PHOTO;
 return{
-from_text=c;
-to_text=d;
+from_text=d;
+to_text=r;
 from_xep54=l;
-to_xep54=r;
-lua_to_text=d;
-lua_to_xep54=r;
-text_to_lua=c;
-text_to_xep54=function(...)return r(c(...));end;
+to_xep54=u;
+lua_to_text=r;
+lua_to_xep54=u;
+text_to_lua=d;
+text_to_xep54=function(...)return u(d(...));end;
 xep54_to_lua=l;
-xep54_to_text=function(...)return d(l(...))end;
+xep54_to_text=function(...)return r(l(...))end;
 };
 end)
 package.preload['util.logger']=(function(...)
-local o=pairs;
-local e=nil;
-local t={};
-local e;
-local function i(t)
-local a=e(t,"debug");
-local n=e(t,"info");
-local i=e(t,"warn");
-local o=e(t,"error");
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local e=pcall;
+local e=string.find;
+local e,o,e=ipairs,pairs,setmetatable;
+local a={};
+local e={};
+local t;
+function a.init(e)
+local a=t(e,"debug");
+local o=t(e,"info");
+local i=t(e,"warn");
+local n=t(e,"error");
 return function(t,e,...)
 if t=="debug"then
 return a(e,...);
 elseif t=="info"then
-return n(e,...);
+return o(e,...);
 elseif t=="warn"then
 return i(e,...);
 elseif t=="error"then
-return o(e,...);
-end
-end
-end
-function e(o,a)
-local e=t[a];
-if not e then
-e={};
-t[a]=e;
-end
-local e=function(i,...)
-for t=1,#e do
-e[t](o,a,i,...);
-end
-end
-return e;
-end
-local function n()
-for t,e in o(t)do
+return n(e,...);
+end
+end
+end
+function t(o,a)
+local t=e[a];
+if not t then
+t={};
+e[a]=t;
+end
+local e=function(e,...)
+for i=1,#t do
+t[i](o,a,e,...);
+end
+end
+return e;
+end
+function a.reset()
+for t,e in o(e)do
 for t=1,#e do
 e[t]=nil;
 end
 end
 end
-local function o(e,a)
-if not t[e]then
-t[e]={a};
-else
-t[e][#t[e]+1]=a;
-end
-end
-return{
-init=i;
-make_logger=e;
-reset=n;
-add_level_sink=o;
-new=e;
-};
+function a.add_level_sink(t,o)
+if not e[t]then
+e[t]={o};
+else
+e[t][#e[t]+1]=o;
+end
+end
+a.new=t;
+return a;
 end)
 package.preload['util.datetime']=(function(...)
+local _ENV=_ENV;
+local function a(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local e=os.date;
 local i=os.time;
-local w=os.difftime;
-local l=tonumber;
-local t=nil;
-local function c(t)
+local u=os.difftime;
+local t=error;
+local s=tonumber;
+a"datetime"
+function date(t)
 return e("!%Y-%m-%d",t);
 end
-local function u(t)
+function datetime(t)
 return e("!%Y-%m-%dT%H:%M:%SZ",t);
 end
-local function m(t)
+function time(t)
 return e("!%H:%M:%S",t);
 end
-local function f(t)
+function legacy(t)
 return e("!%Y%m%dT%H:%M:%S",t);
 end
-local function y(t)
-if t then
-local n,d,h,s,r,o,a;
-n,d,h,s,r,o,a=t:match("^(%d%d%d%d)%-?(%d%d)%-?(%d%d)T(%d%d):(%d%d):(%d%d)%.?%d*([Z+%-]?.*)$");
+function parse(o)
+if o then
+local n,h,l,d,r,t,a;
+n,h,l,d,r,t,a=o:match("^(%d%d%d%d)%-?(%d%d)%-?(%d%d)T(%d%d):(%d%d):(%d%d)%.?%d*([Z+%-]?.*)$");
 if n then
-local u=w(i(e("*t")),i(e("!*t")));
-local t=0;
+local u=u(i(e("*t")),i(e("!*t")));
+local o=0;
 if a~=""and a~="Z"then
-local o,a,e=a:match("([+%-])(%d%d):?(%d*)");
-if not o then return;end
+local a,t,e=a:match("([+%-])(%d%d):?(%d*)");
+if not a then return;end
 if#e~=2 then e="0";end
-a,e=l(a),l(e);
-t=a*60*60+e*60;
-if o=="-"then t=-t;end
-end
-o=(o+u)-t;
-return i({year=n,month=d,day=h,hour=s,min=r,sec=o,isdst=false});
-end
-end
-end
-return{
-date=c;
-datetime=u;
-time=m;
-legacy=f;
-parse=y;
-};
+t,e=s(t),s(e);
+o=t*60*60+e*60;
+if a=="-"then o=-o;end
+end
+t=(t+u)-o;
+return i({year=n,month=h,day=l,hour=d,min=r,sec=t,isdst=false});
+end
+end
+end
+return _M;
 end)
 package.preload['util.json']=(function(...)
-local v=type;
-local t,p,y,j=table.insert,table.concat,table.remove,table.sort;
-local n=string.char;
-local q,l=tostring,tonumber;
-local c,s=pairs,ipairs;
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local w=type;
+local t,v,p,q=table.insert,table.concat,table.remove,table.sort;
+local h=string.char;
+local j,l=tostring,tonumber;
+local u,s=pairs,ipairs;
 local i=next;
-local b,w=getmetatable,setmetatable;
-local m=print;
-local a,e=pcall(require,"util.array");
-local f=a and b(e())or{};
+local e=error;
+local e,r,b=newproxy,getmetatable,setmetatable;
+local c=print;
+local a,o=pcall(require,"util.array");
+local f=a and r(o())or{};
 local a={};
-local r=w({},{__tostring=function()return"null";end;});
-a.null=r;
-local d={
+local n=e and e(true)or{};
+if r and r(n)then
+r(n).__tostring=function()return"null";end;
+end
+a.null=n;
+local y={
 ["\""]="\\\"",["\\"]="\\\\",["\b"]="\\b",
 ["\f"]="\\f",["\n"]="\\n",["\r"]="\\r",["\t"]="\\t"};
 local e={
 ["\""]="\"",["\\"]="\\",["/"]="/",
 b="\b",f="\f",n="\n",r="\r",t="\t"};
-for t=0,31 do
-local e=n(t);
-if not d[e]then d[e]=("\\u%.4X"):format(t);end
+for e=0,31 do
+local t=h(e);
+if not y[t]then y[t]=("\\u%.4X"):format(e);end
 end
 local function x(e)
-if e<128 then return n(e);end
+if e<128 then return h(e);end
 local t=e%64;
 if e<2048 then
 local e=(e-t)/64;
-return n(128+64+e,128+t);
+return h(128+64+e,128+t);
 end
 local a=e%4096;
 local o=(a-t)/64;
 local e=(e-a)/4096;
-return n(128+64+32+e,128+o,128+t);
+return h(128+64+32+e,128+o,128+t);
 end
 local g={
 number=true,
@@ -3972,96 +3962,94 @@
 __array=true;
 __hash=true;
 };
-local o,k,h,u;
-function u(a,e)
-t(e,"\""..(a:gsub(".",d)).."\"");
-end
-function h(a,e)
+local o,k,d,m;
+function m(a,e)
+t(e,"\""..(a:gsub(".",y)).."\"");
+end
+function d(a,e)
 t(e,"[");
 if i(a)then
 for i,a in s(a)do
 o(a,e);
 t(e,",");
 end
-y(e);
+p(e);
 end
 t(e,"]");
 end
 function k(l,e)
 local a={};
-local d={};
-local n={};
-for e,t in s(l)do
-a[e]=t;
-end
-for e,t in c(l)do
-local o,i=v(e),v(t);
-if g[i]or t==r then
+local r={};
+local h={};
+for t,e in s(l)do
+a[t]=e;
+end
+for e,t in u(l)do
+local o,i=w(e),w(t);
+if g[i]or t==n then
 if o=="string"and not z[e]then
-n[e]=t;
-elseif(g[o]or e==r)and a[e]==nil then
-d[e]=t;
-end
-end
-end
-if i(d)~=nil or i(n)~=nil or i(a)==nil then
+h[e]=t;
+elseif(g[o]or e==n)and a[e]==nil then
+r[e]=t;
+end
+end
+end
+if i(r)~=nil or i(h)~=nil or i(a)==nil then
 t(e,"{");
-local r=#e;
+local n=#e;
 if e.ordered then
 local a={};
-for e in c(n)do
+for e in u(h)do
 t(a,e);
 end
-j(a);
+q(a);
 for i,a in s(a)do
-u(a,e);
+m(a,e);
 t(e,":");
-o(n[a],e);
+o(h[a],e);
 t(e,",");
 end
 else
-for a,i in c(n)do
-u(a,e);
+for a,i in u(h)do
+m(a,e);
 t(e,":");
 o(i,e);
 t(e,",");
 end
 end
-if i(d)~=nil then
+if i(r)~=nil then
 t(e,"\"__hash\":[");
-for i,a in c(d)do
+for i,a in u(r)do
 o(i,e);
 t(e,",");
 o(a,e);
 t(e,",");
 end
-y(e);
+p(e);
 t(e,"]");
 t(e,",");
 end
 if i(a)then
 t(e,"\"__array\":");
-h(a,e);
+d(a,e);
 t(e,",");
 end
-if r~=#e then y(e);end
+if n~=#e then p(e);end
 t(e,"}");
 else
-h(a,e);
+d(a,e);
 end
 end
 function o(e,a)
-local o=v(e);
-if e==r then
-t(a,"null");
-elseif o=="number"then
-t(a,q(e));
+local o=w(e);
+if o=="number"then
+t(a,j(e));
 elseif o=="string"then
-u(e,a);
+m(e,a);
 elseif o=="table"then
-local t=b(e);
+local t=r(e);
 if t==f then
-h(e,a);
+d(e,a);
 else
 k(e,a);
 end
@@ -4074,17 +4062,17 @@
 function a.encode(t)
 local e={};
 o(t,e);
-return p(e);
+return v(e);
 end
 function a.encode_ordered(t)
 local e={ordered=true};
 o(t,e);
-return p(e);
+return v(e);
 end
 function a.encode_array(t)
 local e={};
-h(t,e);
-return p(e);
+d(t,e);
+return v(e);
 end
 local function o(t,e)
 return t:find("[^ \t\r\n]",e)or e;
@@ -4111,119 +4099,119 @@
 end
 return e;
 end
-local i,h;
-local function u(t,e)
-local a={};
+local i,r;
+local function m(t,e)
+local s={};
 while true do
-local n,s;
+local n,a;
 e=o(t,e+1);
 if t:byte(e)~=34 then
-if t:byte(e)==125 then return a,e+1;end
+if t:byte(e)==125 then return s,e+1;end
 return nil,"key expected";
 end
-n,e=h(t,e);
+n,e=r(t,e);
 if n==nil then return nil,e;end
 e=o(t,e);
 if t:byte(e)~=58 then return nil,"colon expected";end
-s,e=i(t,e+1);
-if s==nil then return nil,e;end
-a[n]=s;
+a,e=i(t,e+1);
+if a==nil then return nil,e;end
+s[n]=a;
 e=o(t,e);
 local t=t:byte(e);
-if t==125 then return d(a),e+1;end
+if t==125 then return d(s),e+1;end
 if t~=44 then return nil,"object eof";end
 end
 end
-local function c(a,e)
+local function u(n,e)
 local s={};
 local h=e;
 while true do
-local n;
-n,e=i(a,e+1);
-if n==nil then
-if a:byte(h+1)==93 then return w(s,f),h+2;end
-return n,e;
-end
-t(s,n);
-e=o(a,e);
-local t=a:byte(e);
-if t==93 then return w(s,f),e+1;end
+local a;
+a,e=i(n,e+1);
+if a==nil then
+if n:byte(h+1)==93 then return b(s,f),h+2;end
+return a,e;
+end
+t(s,a);
+e=o(n,e);
+local t=n:byte(e);
+if t==93 then return b(s,f),e+1;end
 if t~=44 then return nil,"array eof";end
 end
 end
-local s;
+local t;
 local function e(e)
-local t,e=l(e:sub(3,6),16),l(e:sub(9,12),16);
-local e=t*1024+e-56613888;
-local o=e%64;
-e=(e-o)/64;
+local e,t=l(e:sub(3,6),16),l(e:sub(9,12),16);
+local e=e*1024+t-56613888;
 local a=e%64;
 e=(e-a)/64;
 local t=e%64;
 e=(e-t)/64;
-return n(240+e,128+t,128+a,128+o);
-end
-local function n(e)
+local o=e%64;
+e=(e-o)/64;
+return h(240+e,128+o,128+t,128+a);
+end
+local function s(e)
 e=e:match("%x%x%x%x",3);
 if e then
 return x(l(e,16));
 end
-s=true;
-end
-function h(a,e)
+t=true;
+end
+function r(o,e)
 e=e+1;
-local t=a:find("\"",e,true);
-if t then
-local e=a:sub(e,t-1);
-s=nil;
-e=e:gsub("\\u.?.?.?.?",n);
-if s then return nil,"invalid escape";end
-return e,t+1;
+local a=o:find("\"",e,true);
+if a then
+local e=o:sub(e,a-1);
+t=nil;
+e=e:gsub("\\u.?.?.?.?",s);
+if t then return nil,"invalid escape";end
+return e,a+1;
 end
 return nil,"string eof";
 end
-local function d(e,t)
-local e=e:match("[0-9%.%-eE%+]+",t);
-return l(e),t+#e;
-end
-local function l(t,e)
-local t,o,a=t:byte(e+1,e+3);
-if t==117 and o==108 and a==108 then
-return r,e+4;
-end
-return nil,"null parse failed";
+local function d(t,e)
+local t=t:match("[0-9%.%-eE%+]+",e);
+return l(t),e+#t;
 end
 local function s(t,e)
 local o,a,t=t:byte(e+1,e+3);
-if o==114 and a==117 and t==101 then
+if o==117 and a==108 and t==108 then
+return n,e+4;
+end
+return nil,"null parse failed";
+end
+local function n(t,e)
+local a,t,o=t:byte(e+1,e+3);
+if a==114 and t==117 and o==101 then
 return true,e+4;
 end
 return nil,"true parse failed";
 end
-local function n(t,e)
-local t,o,a,i=t:byte(e+1,e+4);
-if t==97 and o==108 and a==115 and i==101 then
+local function h(t,e)
+local t,a,o,i=t:byte(e+1,e+4);
+if t==97 and a==108 and o==115 and i==101 then
 return false,e+5;
 end
 return nil,"false parse failed";
 end
-function i(a,e)
-e=o(a,e);
-local t=a:byte(e);
-if t==123 then
-return u(a,e);
-elseif t==91 then
-return c(a,e);
-elseif t==34 then
-return h(a,e);
-elseif t~=nil and t>=48 and t<=57 or t==45 then
-return d(a,e);
-elseif t==110 then
-return l(a,e);
-elseif t==116 then
-return s(a,e);
-elseif t==102 then
-return n(a,e);
+function i(a,t)
+t=o(a,t);
+local e=a:byte(t);
+if e==123 then
+return m(a,t);
+elseif e==91 then
+return u(a,t);
+elseif e==34 then
+return r(a,t);
+elseif e~=nil and e>=48 and e<=57 or e==45 then
+return d(a,t);
+elseif e==110 then
+return s(a,t);
+elseif e==116 then
+return n(a,t);
+elseif e==102 then
+return h(a,t);
 else
 return nil,"value expected";
 end
@@ -4251,20 +4239,31 @@
 local t=a.decode(e);
 local t=a.encode(t);
 if e~=t then
-m("FAILED");
-m("encoded:",e);
-m("recoded:",t);
-else
-m(e);
+c("FAILED");
+c("encoded:",e);
+c("recoded:",t);
+else
+c(e);
 end
 return e==t;
 end
 return a;
 end)
 package.preload['util.xml']=(function(...)
+local _ENV=_ENV;
+local function a(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local t=require"util.stanza";
 local h=require"lxp";
-local e=nil;
+a("xml")
 local e=(function()
 local n={
 ["http://www.w3.org/XML/1998/namespace"]="xml";
@@ -4299,34 +4298,44 @@
 function o:CharacterData(e)
 a:text(e);
 end
-function o:EndElement()
+function o:EndElement(e)
 a:up();
 end
-local t=h.new(o,"\1");
-local e,n,i,o=t:parse(s);
-if e then e,n,i,o=t:parse();end
+local n=h.new(o,"\1");
+local e,i,t,o=n:parse(s);
+if e then e,i,t,o=n:parse();end
 if e then
 return a.tags[1];
 else
-return e,n.." (line "..i..", col "..o..")";
+return e,i.." (line "..t..", col "..o..")";
 end
 end;
 end)();
-return{
 parse=e;
-};
+return _M;
 end)
 package.preload['util.rsm']=(function(...)
-local s=require"util.stanza".stanza;
-local a,i=tostring,tonumber;
-local h=type;
-local r=pairs;
-local n='http://jabber.org/protocol/rsm';
-local o={};
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local h=require"util.stanza".stanza;
+local t,o=tostring,tonumber;
+local n=type;
+local s=pairs;
+local i='http://jabber.org/protocol/rsm';
+local a={};
 do
-local e=o;
+local e=a;
 local function t(e)
-return i((e:get_text()));
+return o((e:get_text()));
 end
 local function a(t)
 return t:get_text();
@@ -4339,62 +4348,73 @@
 e.max=t;
 e.index=t;
 e.first=function(e)
-return{index=i(e.attr.index);e:get_text()};
+return{index=o(e.attr.index);e:get_text()};
 end;
 e.last=a;
 e.count=t;
 end
-local h=setmetatable({
-first=function(t,e)
-if h(e)=="table"then
-t:tag("first",{index=e.index}):text(e[1]):up();
-else
-t:tag("first"):text(a(e)):up();
+local r=setmetatable({
+first=function(a,e)
+if n(e)=="table"then
+a:tag("first",{index=e.index}):text(e[1]):up();
+else
+a:tag("first"):text(t(e)):up();
 end
 end;
-before=function(e,t)
-if t==true then
+before=function(e,a)
+if a==true then
 e:tag("before"):up();
 else
-e:tag("before"):text(a(t)):up();
+e:tag("before"):text(t(a)):up();
 end
 end
 },{
-__index=function(t,e)
-return function(o,t)
-o:tag(e):text(a(t)):up();
+__index=function(e,o)
+return function(e,a)
+e:tag(o):text(t(a)):up();
 end
 end;
 });
+local function t(e)
+local t={};
+for o in e:childtags()do
+local e=o.name;
+local a=e and a[e];
+if a then
+t[e]=a(o);
+end
+end
+return t;
+end
+local function n(t)
+local e=h("set",{xmlns=i});
+for t,o in s(t)do
+if a[t]then
+r[t](e,o);
+end
+end
+return e;
+end
 local function a(e)
-local i={};
-for a in e:childtags()do
-local e=a.name;
-local t=e and o[e];
-if t then
-i[e]=t(a);
-end
-end
-return i;
-end
-local function i(t)
-local e=s("set",{xmlns=n});
-for t,a in r(t)do
-if o[t]then
-h[t](e,a);
-end
-end
-return e;
-end
-local function t(e)
-local e=e:get_child("set",n);
+local e=e:get_child("set",i);
 if e and#e.tags>0 then
-return a(e);
-end
-end
-return{parse=a,generate=i,get=t};
+return t(e);
+end
+end
+return{parse=t,generate=n,get=a};
 end)
 package.preload['util.random']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local e=io.open("/dev/urandom","r");
 if e then
 return{
@@ -4406,10 +4426,21 @@
 return e.rand;
 end)
 package.preload['util.ip']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local o={};
 local i={__index=function(t,e)return(o[e])(t);end,
 __tostring=function(e)return e.addr;end,
-__eq=function(e,t)return e.addr==t.addr;end};
+__eq=function(t,e)return t.addr==e.addr;end};
 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"};
 local function e(e,t)
 if not t then
@@ -4431,37 +4462,37 @@
 end
 if t=="IPv6"and e:find('.',1,true)then
 local t;
-e,t=e:gsub(":(%d+)%.(%d+)%.(%d+)%.(%d+)$",function(e,a,t,o)
-return(":%04X:%04X"):format(e*256+a,t*256+o);
+e,t=e:gsub(":(%d+)%.(%d+)%.(%d+)%.(%d+)$",function(t,e,a,o)
+return(":%04X:%04X"):format(t*256+e,a*256+o);
 end);
 if t~=1 then return nil,"invalid-address";end
 end
 return setmetatable({addr=e,proto=t,zone=a},i);
 end
-local function i(t)
-local e="";
-local a={};
-if t.proto=="IPv4"then
-t=t.toV4mapped;
-end
-t=(t.addr):upper();
-t:gsub("([^:]*):?",function(e)a[#a+1]=e end);
-if not t:match(":$")then a[#a]=nil;end
-for o,t in ipairs(a)do
-if t:len()==0 and o~=1 and o~=#a then
-for t=1,16*(9-#a)do
-e=e.."0";
-end
-else
-for t=1,4-t:len()do
-e=e.."0000";
-end
-for a=1,t:len()do
-e=e..n[t:sub(a,a)];
-end
-end
-end
-return e;
+local function i(a)
+local t="";
+local e={};
+if a.proto=="IPv4"then
+a=a.toV4mapped;
+end
+a=(a.addr):upper();
+a:gsub("([^:]*):?",function(t)e[#e+1]=t end);
+if not a:match(":$")then e[#e]=nil;end
+for o,a in ipairs(e)do
+if a:len()==0 and o~=1 and o~=#e then
+for e=1,16*(9-#e)do
+t=t.."0";
+end
+else
+for e=1,4-a:len()do
+t=t.."0000";
+end
+for e=1,a:len()do
+t=t..n[a:sub(e,e)];
+end
+end
+end
+return t;
 end
 local function t(a,t)
 a,t=i(a),i(t);
@@ -4472,7 +4503,7 @@
 end
 return 128;
 end
-local function s(t)
+local function h(t)
 local e={};
 t:gsub("([^.]*).?",function(t)e[#e+1]=tonumber(t)end);
 if e[1]==127 then
@@ -4496,7 +4527,7 @@
 return 14;
 end
 end
-local function n(a)
+local function i(a)
 if t(a,e("::1","IPv6"))==128 then
 return 0;
 elseif t(a,e("2002::","IPv6"))>=16 then
@@ -4517,7 +4548,7 @@
 return 1;
 end
 end
-local function i(a)
+local function n(a)
 if t(a,e("::1","IPv6"))==128 then
 return 50;
 elseif t(a,e("2002::","IPv6"))>=16 then
@@ -4538,7 +4569,7 @@
 return 40;
 end
 end
-local function h(o)
+local function s(o)
 local a={};
 local t="::ffff:";
 o:gsub("([^.]*).?",function(e)a[#a+1]=tonumber(e)end);
@@ -4551,16 +4582,16 @@
 end
 function o:toV4mapped()
 if self.proto~="IPv4"then return nil,"No IPv4 address"end
-local e=h(self.addr);
+local e=s(self.addr);
 self.toV4mapped=e;
 return e;
 end
 function o:label()
 local e;
 if self.proto=="IPv4"then
-e=n(self.toV4mapped);
-else
-e=n(self);
+e=i(self.toV4mapped);
+else
+e=i(self);
 end
 self.label=e;
 return e;
@@ -4568,9 +4599,9 @@
 function o:precedence()
 local e;
 if self.proto=="IPv4"then
-e=i(self.toV4mapped);
-else
-e=i(self);
+e=n(self.toV4mapped);
+else
+e=n(self);
 end
 self.precedence=e;
 return e;
@@ -4578,126 +4609,111 @@
 function o:scope()
 local e;
 if self.proto=="IPv4"then
-e=s(self.addr);
+e=h(self.addr);
 else
 e=r(self.addr);
 end
 self.scope=e;
 return e;
 end
-function o:private()
-local t=self.scope~=14;
-if not t and self.proto=="IPv4"then
-local a=self.addr;
-local e={};
-a:gsub("([^.]*).?",function(t)e[#e+1]=tonumber(t)end);
-if e[1]==127 or e[1]==10 or(e[1]==192 and e[2]==168)
-or(e[1]==172 and(e[2]>=16 or e[2]<=32))then
-t=true;
-end
-end
-self.private=t;
-return t;
-end
-local function i(t)
-local o;
-local a=t:find("/",1,true);
-if a then
-o=tonumber(t:sub(a+1,-1));
-t=t:sub(1,a-1);
-end
-return e(t),o;
-end
-local function n(e,a,o)
-local e=t(e,a);
-if o and a.proto=="IPv4"then
-e=e-96;
-end
-return e>=(o or 128);
-end
 return{new_ip=e,
-commonPrefixLength=t,
-parse_cidr=i,
-match=n};
-end)
-package.preload['util.time']=(function(...)
-local e=require"socket".gettime;
-return{
-now=e;
-}
+commonPrefixLength=t};
 end)
 package.preload['util.sasl.scram']=(function(...)
-local i,l=require"mime".b64,require"mime".unb64;
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local n,u=require"mime".b64,require"mime".unb64;
 local e=require"util.hashes";
 local a=require"bit";
-local r=require"util.random";
-local p=tonumber;
-local d,t=string.char,string.byte;
-local s=string.gsub;
-local h=a.bxor;
-local function n(e,o)
-return(s(e,"()(.)",function(e,a)
-return d(h(t(a),t(o,e)))
+local s=require"util.random";
+local d=tonumber;
+local h,t=string.char,string.byte;
+local i=string.gsub;
+local r=a.bxor;
+local function l(e,o)
+return(i(e,"()(.)",function(a,e)
+return h(r(t(e),t(o,a)))
 end));
 end
-local y,e=e.sha1,e.hmac_sha1;
-local function f(o,t,i)
-local t=e(o,t.."\0\0\0\1");
-local a=t;
+local y,t=e.sha1,e.hmac_sha1;
+local function w(o,e,i)
+local e=t(o,e.."\0\0\0\1");
+local a=e;
 for i=2,i do
-t=e(o,t);
-a=n(a,t);
+e=t(o,e);
+a=l(a,e);
 end
 return a;
 end
-local function w(e)
-return e;
-end
-local function t(e)
-return(s(e,"[,=]",{[","]="=2C",["="]="=3D"}));
-end
-local function u(o,a)
-local t="n="..t(o.username);
-local d=i(r.bytes(15));
-local r="r="..d;
-local h=t..","..r;
-local s="";
-local t=o.conn:ssl()and"y"or"n";
-if a=="SCRAM-SHA-1-PLUS"then
-s=o.conn:socket():getfinished();
-t="p=tls-unique";
-end
-local u=t..",,";
-local t=u..h;
-local t,m=coroutine.yield(t);
-if t~="challenge"then return false end
-local a,t,c=m:match("(r=[^,]+),s=([^,]*),i=(%d+)");
-local c=p(c);
-t=l(t);
-if not a or not t or not c then
+local function p(e)
+return e;
+end
+local function a(e)
+return(i(e,"[,=]",{[","]="=2C",["="]="=3D"}));
+end
+local function f(e,i)
+local a="n="..a(e.username);
+local h=n(s.bytes(15));
+local c="r="..h;
+local m=a..","..c;
+local o="";
+local a=e.conn:ssl()and"y"or"n";
+if i=="SCRAM-SHA-1-PLUS"then
+o=e.conn:socket():getfinished();
+a="p=tls-unique";
+end
+local s=a..",,";
+local a=s..m;
+local a,r=coroutine.yield(a);
+if a~="challenge"then return false end
+local a,i,f=r:match("(r=[^,]+),s=([^,]*),i=(%d+)");
+local d=d(f);
+i=u(i);
+if not a or not i or not d then
 return false,"Could not parse server_first_message";
-elseif a:find(d,3,true)~=3 then
+elseif a:find(h,3,true)~=3 then
 return false,"nonce sent by server does not match our nonce";
-elseif a==r then
+elseif a==c then
 return false,"server did not append s-nonce to nonce";
 end
-local s=u..s;
-local s="c="..i(s);
-local s=s..","..a;
-local o=f(w(o.password),t,c);
-local t=e(o,"Client Key");
-local r=y(t);
-local a=h..","..m..","..s;
-local h=e(r,a);
-local n=n(t,h);
-local t=e(o,"Server Key");
-local t=e(t,a);
-local e="p="..i(n);
-local e=s..","..e;
+local o=s..o;
+local o="c="..n(o);
+local h=o..","..a;
+local o;
+local a;
+local s;
+if e.client_key and e.server_key then
+a=e.client_key;
+s=e.server_key;
+else
+if e.salted_password then
+o=e.salted_password;
+elseif e.password then
+o=w(p(e.password),i,d);
+end
+s=t(o,"Server Key");
+a=t(o,"Client Key");
+end
+local o=y(a);
+local e=m..","..r..","..h;
+local o=t(o,e);
+local a=l(a,o);
+local t=t(s,e);
+local e="p="..n(a);
+local e=h..","..e;
 local e,a=coroutine.yield(e);
 if e~="success"then return false,"success-expected"end
 local e=a:match("v=([^,]+)");
-if l(e)~=t then
+if u(e)~=t then
 return false,"server signature did not match";
 end
 return true;
@@ -4705,17 +4721,28 @@
 return function(e,t)
 if e.username and(e.password or(e.client_key or e.server_key))then
 if t=="SCRAM-SHA-1"then
-return u,99;
+return f,99;
 elseif t=="SCRAM-SHA-1-PLUS"then
 local e=e.conn:ssl()and e.conn:socket();
 if e and e.getfinished then
-return u,100;
+return f,100;
 end
 end
 end
 end
 end)
 package.preload['util.sasl.plain']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 return function(e,t)
 if t=="PLAIN"and e.username and e.password then
 return function(e)
@@ -4725,6 +4752,17 @@
 end
 end)
 package.preload['util.sasl.anonymous']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 return function(t,e)
 if e=="ANONYMOUS"then
 return function()
@@ -4734,6 +4772,17 @@
 end
 end)
 package.preload['verse.plugins.tls']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local a=require"verse";
 local t="urn:ietf:params:xml:ns:xmpp-tls";
 function a.plugins.tls(e)
@@ -4769,26 +4818,37 @@
 end
 end)
 package.preload['verse.plugins.sasl']=(function(...)
-local n=require"verse";
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local i=require"verse";
 local s,h=require"mime".b64,require"mime".unb64;
 local a="urn:ietf:params:xml:ns:xmpp-sasl";
-function n.plugins.sasl(e)
+function i.plugins.sasl(e)
 local function r(t)
 if e.authenticated then return;end
 e:debug("Authenticating with SASL...");
 local t=t:get_child("mechanisms",a);
 if not t then return end
 local o={};
-local i={};
+local n={};
 for t in t:childtags("mechanism")do
 t=t:get_text();
 e:debug("Server offers %s",t);
 if not o[t]then
-local n=t:match("[^-]+");
-local s,a=pcall(require,"util.sasl."..n:lower());
+local i=t:match("[^-]+");
+local s,a=pcall(require,"util.sasl."..i:lower());
 if s then
-e:debug("Loaded SASL %s module",n);
-o[t],i[t]=a(e,t);
+e:debug("Loaded SASL %s module",i);
+o[t],n[t]=a(e,t);
 elseif not tostring(a):match("not found")then
 e:debug("Loading failed: %s",tostring(a));
 end
@@ -4803,14 +4863,14 @@
 e:close();
 return;
 end
-table.sort(t,function(t,e)return i[t]>i[e];end);
-local t,i=t[1];
+table.sort(t,function(t,e)return n[t]>n[e];end);
+local t,n=t[1];
 e:debug("Selecting %s mechanism...",t);
 e.sasl_mechanism=coroutine.wrap(o[t]);
-i=e:sasl_mechanism(t);
-local t=n.stanza("auth",{xmlns=a,mechanism=t});
-if i then
-t:text(s(i));
+n=e:sasl_mechanism(t);
+local t=i.stanza("auth",{xmlns=a,mechanism=t});
+if n then
+t:text(s(n));
 end
 e:send(t);
 return true;
@@ -4833,7 +4893,7 @@
 e.authenticated=true
 e:reopen();
 else
-e:send(n.stanza("response",{xmlns=a}):text(s(t)));
+e:send(i.stanza("response",{xmlns=a}):text(s(t)));
 end
 return true;
 end
@@ -4843,11 +4903,22 @@
 end
 end)
 package.preload['verse.plugins.bind']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local t=require"verse";
-local o=require"util.jid";
+local i=require"util.jid";
 local a="urn:ietf:params:xml:ns:xmpp-bind";
 function t.plugins.bind(e)
-local function i(i)
+local function o(o)
 if e.bound then return;end
 e:debug("Binding resource...");
 e:send_iq(t.iq({type="set"}):tag("bind",{xmlns=a}):tag("resource"):text(e.resource),
@@ -4856,7 +4927,7 @@
 local t=t
 :get_child("bind",a)
 :get_child_text("jid");
-e.username,e.host,e.resource=o.split(t);
+e.username,e.host,e.resource=i.split(t);
 e.jid,e.bound=t,true;
 e:event("bind-success",{jid=t});
 elseif t.attr.type=="error"then
@@ -4866,44 +4937,66 @@
 end
 end);
 end
-e:hook("stream-features",i,200);
+e:hook("stream-features",o,200);
 return true;
 end
 end)
 package.preload['verse.plugins.session']=(function(...)
-local t=require"verse";
-local a="urn:ietf:params:xml:ns:xmpp-session";
-function t.plugins.session(e)
-local function i(o)
-local o=o:get_child("session",a);
-if o and not o:get_child("optional")then
-local function o(o)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local a=require"verse";
+local o="urn:ietf:params:xml:ns:xmpp-session";
+function a.plugins.session(e)
+local function n(t)
+local t=t:get_child("session",o);
+if t and not t:get_child("optional")then
+local function i(t)
 e:debug("Establishing Session...");
-e:send_iq(t.iq({type="set"}):tag("session",{xmlns=a}),
+e:send_iq(a.iq({type="set"}):tag("session",{xmlns=o}),
 function(t)
 if t.attr.type=="result"then
 e:event("session-success");
 elseif t.attr.type=="error"then
-local t,o,a=t:get_error();
-e:event("session-failure",{error=o,text=a,type=t});
+local t,a,o=t:get_error();
+e:event("session-failure",{error=a,text=o,type=t});
 end
 end);
 return true;
 end
-e:hook("bind-success",o);
-end
-end
-e:hook("stream-features",i);
+e:hook("bind-success",i);
+end
+end
+e:hook("stream-features",n);
 return true;
 end
 end)
 package.preload['verse.plugins.legacy']=(function(...)
-local i=require"verse";
-local s=require"util.uuid".generate;
-local o="jabber:iq:auth";
-function i.plugins.legacy(e)
-local function n(t)
-local a=t:get_child("query",o);
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local o=require"verse";
+local n=require"util.uuid".generate;
+local i="jabber:iq:auth";
+function o.plugins.legacy(e)
+local function s(t)
+local a=t:get_child("query",i);
 if t.attr.type~="result"or not a then
 local o,a,t=t:get_error();
 e:debug("warn","%s %s: %s",o,a,t);
@@ -4911,11 +5004,11 @@
 local t={
 username=e.username;
 password=e.password;
-resource=e.resource or s();
+resource=e.resource or n();
 digest=false,sequence=false,token=false;
 };
-local o=i.iq({to=e.host,type="set"})
-:tag("query",{xmlns=o});
+local o=o.iq({to=e.host,type="set"})
+:tag("query",{xmlns=i});
 if#a>0 then
 for a in a:childtags()do
 local a=a.name;
@@ -4947,52 +5040,63 @@
 end
 end);
 end
-local function t(t)
+local function a(t)
 if not t.version then
-e:send_iq(i.iq({type="get"})
+e:send_iq(o.iq({type="get"})
 :tag("query",{xmlns="jabber:iq:auth"})
 :tag("username"):text(e.username),
-n);
-end
-end
-e:hook("opened",t);
+s);
+end
+end
+e:hook("opened",a);
 end
 end)
 package.preload['verse.plugins.compression']=(function(...)
-local a=require"verse";
-local i=require"zlib";
-local e="http://jabber.org/features/compress"
-local t="http://jabber.org/protocol/compress"
-local e="http://etherx.jabber.org/streams";
-local e=9;
-local function h(o)
-local i,e=pcall(i.deflate,e);
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local t=require"verse";
+local e=require"zlib";
+local a="http://jabber.org/features/compress"
+local a="http://jabber.org/protocol/compress"
+local o="http://etherx.jabber.org/streams";
+local n=9;
+local function i(o)
+local i,e=pcall(e.deflate,n);
 if i==false then
-local t=a.stanza("failure",{xmlns=t}):tag("setup-failed");
+local t=t.stanza("failure",{xmlns=a}):tag("setup-failed");
 o:send(t);
 o:error("Failed to create zlib.deflate filter: %s",tostring(e));
 return
 end
 return e
 end
-local function d(o)
-local i,e=pcall(i.inflate);
+local function s(o)
+local i,e=pcall(e.inflate);
 if i==false then
-local t=a.stanza("failure",{xmlns=t}):tag("setup-failed");
+local t=t.stanza("failure",{xmlns=a}):tag("setup-failed");
 o:send(t);
 o:error("Failed to create zlib.inflate filter: %s",tostring(e));
 return
 end
 return e
 end
-local function l(e,o)
+local function h(e,o)
 function e:send(i)
 local i,o,n=pcall(o,tostring(i),'sync');
 if i==false then
 e:close({
 condition="undefined-condition";
 text=o;
-extra=a.stanza("failure",{xmlns=t}):tag("processing-failed");
+extra=t.stanza("failure",{xmlns=a}):tag("processing-failed");
 });
 e:warn("Compressed send failed: %s",tostring(o));
 return;
@@ -5009,7 +5113,7 @@
 e:close({
 condition="undefined-condition";
 text=o;
-extra=a.stanza("failure",{xmlns=t}):tag("processing-failed");
+extra=t.stanza("failure",{xmlns=a}):tag("processing-failed");
 });
 stream:warn("%s",tostring(o));
 return;
@@ -5017,15 +5121,15 @@
 return s(n,o);
 end;
 end
-function a.plugins.compression(e)
-local function i(o)
+function t.plugins.compression(e)
+local function n(o)
 if not e.compressed then
 local o=o:child_with_name("compression");
 if o then
 for o in o:children()do
 local o=o[1]
 if o=="zlib"then
-e:send(a.stanza("compress",{xmlns=t}):tag("method"):text("zlib"))
+e:send(t.stanza("compress",{xmlns=a}):tag("method"):text("zlib"))
 e:debug("Enabled compression using zlib.")
 return true;
 end
@@ -5034,49 +5138,60 @@
 end
 end
 end
-local function o(t)
-if t.name=="compressed"then
+local function o(a)
+if a.name=="compressed"then
 e:debug("Activating compression...")
-local t=h(e);
+local a=i(e);
+if not a then return end
+local t=s(e);
 if not t then return end
-local a=d(e);
-if not a then return end
-l(e,t);
-r(e,a);
+h(e,a);
+r(e,t);
 e.compressed=true;
 e:reopen();
-elseif t.name=="failure"then
+elseif a.name=="failure"then
 e:warn("Failed to establish compression");
 end
 end
-e:hook("stream-features",i,250);
-e:hook("stream/"..t,o);
+e:hook("stream-features",n,250);
+e:hook("stream/"..a,o);
 end
 end)
 package.preload['verse.plugins.smacks']=(function(...)
-local s=require"verse";
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local i=require"verse";
 local h=require"socket".gettime;
-local n="urn:xmpp:sm:2";
-function s.plugins.smacks(e)
+local s="urn:xmpp:sm:3";
+function i.plugins.smacks(e)
 local t={};
 local a=0;
 local r=h();
 local o;
-local i=0;
-local function l(t)
+local n=0;
+local function d(t)
 if t.attr.xmlns=="jabber:client"or not t.attr.xmlns then
-i=i+1;
-e:debug("Increasing handled stanzas to %d for %s",i,t:top_tag());
-end
-end
-local function d(a)
+n=n+1;
+e:debug("Increasing handled stanzas to %d for %s",n,t:top_tag());
+end
+end
+local function l(a)
 if a.name and not a.attr.xmlns then
 t[#t+1]=tostring(a);
 r=h();
 if not o then
 o=true;
 e:debug("Waiting to send ack request...");
-s.add_task(1,function()
+i.add_task(1,function()
 if#t==0 then
 o=false;
 return;
@@ -5087,7 +5202,7 @@
 end
 e:debug("Time up, sending <r>...");
 o=false;
-e:send(s.stanza("r",{xmlns=n}));
+e:send(i.stanza("r",{xmlns=s}));
 end);
 end
 end
@@ -5098,20 +5213,20 @@
 if e.resumption_token then
 e:debug("smacks: have resumption token, reconnecting in 1s...");
 e.authenticated=nil;
-s.add_task(1,function()
+i.add_task(1,function()
 e:connect(e.connect_host or e.host,e.connect_port or 5222);
 end);
 return true;
 end
 end
-local function r()
+local function u()
 e.resumption_token=nil;
 e:unhook("disconnected",h);
 end
-local function u(o)
+local function r(o)
 if o.name=="r"then
-e:debug("Ack requested... acking %d handled stanzas",i);
-e:send(s.stanza("a",{xmlns=n,h=tostring(i)}));
+e:debug("Ack requested... acking %d handled stanzas",n);
+e:send(i.stanza("a",{xmlns=s,h=tostring(n)}));
 elseif o.name=="a"then
 local o=tonumber(o.attr.h);
 if o>a then
@@ -5127,7 +5242,7 @@
 elseif o.name=="enabled"then
 if o.attr.id then
 e.resumption_token=o.attr.id;
-e:hook("closed",r,100);
+e:hook("closed",u,100);
 e:hook("disconnected",h,100);
 end
 elseif o.name=="resumed"then
@@ -5147,36 +5262,47 @@
 e:debug("Resumed successfully");
 e:event("resumed");
 else
-e:warn("Don't know how to handle "..n.."/"..o.name);
-end
-end
-local function o()
+e:warn("Don't know how to handle "..s.."/"..o.name);
+end
+end
+local function t()
 if not e.smacks then
 e:debug("smacks: sending enable");
-e:send(s.stanza("enable",{xmlns=n,resume="true"}));
+e:send(i.stanza("enable",{xmlns=s,resume="true"}));
 e.smacks=true;
-e:hook("stanza",l);
-e:hook("outgoing",d);
-end
-end
-local function a(t)
-if t:get_child("sm",n)then
+e:hook("stanza",d);
+e:hook("outgoing",l);
+end
+end
+local function a(a)
+if a:get_child("sm",s)then
 e.stream_management_supported=true;
 if e.smacks and e.bound then
-e:debug("Resuming stream with %d handled stanzas",i);
-e:send(s.stanza("resume",{xmlns=n,
-h=i,previd=e.resumption_token}));
+e:debug("Resuming stream with %d handled stanzas",n);
+e:send(i.stanza("resume",{xmlns=s,
+h=n,previd=e.resumption_token}));
 return true;
 else
-e:hook("bind-success",o,1);
+e:hook("bind-success",t,1);
 end
 end
 end
 e:hook("stream-features",a,250);
-e:hook("stream/"..n,u);
+e:hook("stream/"..s,r);
 end
 end)
 package.preload['verse.plugins.keepalive']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local t=require"verse";
 function t.plugins.keepalive(e)
 e.keepalive_timeout=e.keepalive_timeout or 300;
@@ -5187,16 +5313,28 @@
 end
 end)
 package.preload['verse.plugins.disco']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local a=require"verse";
-local r=require("mime").b64;
-local h=require("util.hashes").sha1;
+local e=require("mime").b64;
+local e=require("util.hashes").sha1;
+local r=require"util.caps".calculate_hash;
 local s="http://jabber.org/protocol/caps";
 local e="http://jabber.org/protocol/disco";
 local i=e.."#info";
 local o=e.."#items";
 function a.plugins.disco(e)
 e:add_plugin("presence");
-local t={
+local n={
 __index=function(t,e)
 local a={identities={},features={}};
 if e=="identities"or e=="features"then
@@ -5206,10 +5344,10 @@
 return a;
 end,
 };
-local n={
-__index=function(t,a)
+local t={
+__index=function(a,t)
 local e={};
-t[a]=e;
+a[t]=e;
 return e;
 end,
 };
@@ -5226,56 +5364,32 @@
 [o]=true,
 },
 },
-},t);
-items=setmetatable({[false]={}},n);
+},n);
+items=setmetatable({[false]={}},t);
 };
 e.caps={}
 e.caps.node='http://code.matthewwild.co.uk/verse/'
-local function n(t,e)
-if t.category<e.category then
-return true;
-elseif e.category<t.category then
-return false;
-end
-if t.type<e.type then
-return true;
-elseif e.type<t.type then
-return false;
-end
-if(not t['xml:lang']and e['xml:lang'])or
-(e['xml:lang']and t['xml:lang']<e['xml:lang'])then
-return true
-end
-return false
-end
-local function d(e,t)
-return e.var<t.var
-end
-local function l(o)
-local t=e.disco.info[o or false].identities;
-table.sort(t,n)
-local a={};
-for e in pairs(e.disco.info[o or false].features)do
-a[#a+1]={var=e};
-end
-table.sort(a,d)
-local e={};
-for a,t in pairs(t)do
-e[#e+1]=table.concat({
-t.category,t.type or'',
-t['xml:lang']or'',t.name or''
-},'/');
-end
-for a,t in pairs(a)do
-e[#e+1]=t.var
-end
-e[#e+1]='';
-e=table.concat(e,'<');
-return(r(h(e)))
+local function h(t)
+local o=e.disco.info[t or false];
+if t and t==e.caps.node.."#"..e.caps.hash then
+o=e.disco.info[false];
+end
+local n,o=o.identities,o.features
+local e=a.stanza("query",{
+xmlns=i,
+node=t,
+});
+for a,t in pairs(n)do
+e:tag('identity',t):up()
+end
+for t in pairs(o)do
+e:tag('feature',{var=t}):up()
+end
+return e;
 end
 setmetatable(e.caps,{
 __call=function(...)
-local t=l()
+local t=r(h())
 e.caps.hash=t;
 return a.stanza('c',{
 xmlns=s,
@@ -5285,8 +5399,8 @@
 })
 end
 })
-function e:set_identity(t,a)
-self.disco.info[a or false].identities={t};
+function e:set_identity(a,t)
+self.disco.info[t or false].identities={a};
 e:resend_presence();
 end
 function e:add_identity(a,t)
@@ -5316,17 +5430,17 @@
 end
 end
 end
-function e:jid_has_identity(e,t,a)
-local o=self.disco.cache[e];
+function e:jid_has_identity(t,a,e)
+local o=self.disco.cache[t];
 if not o then
 return nil,"no-cache";
 end
-local e=self.disco.cache[e].identities;
-if a then
-return e[t.."/"..a]or false;
-end
-for e in pairs(e)do
-if e:match("^(.*)/")==t then
+local t=self.disco.cache[t].identities;
+if e then
+return t[a.."/"..e]or false;
+end
+for e in pairs(t)do
+if e:match("^(.*)/")==a then
 return true;
 end
 end
@@ -5338,14 +5452,14 @@
 end
 return e.features[t]or false;
 end
-function e:get_local_services(o,a)
+function e:get_local_services(a,o)
 local e=self.disco.cache[self.host];
 if not(e)or not(e.items)then
 return nil,"no-cache";
 end
 local t={};
 for i,e in ipairs(e.items)do
-if self:jid_has_identity(e.jid,o,a)then
+if self:jid_has_identity(e.jid,a,o)then
 table.insert(t,e.jid);
 end
 end
@@ -5377,14 +5491,14 @@
 function e:disco_info(e,t,s)
 local a=a.iq({to=e,type="get"})
 :tag("query",{xmlns=i,node=t});
-self:send_iq(a,function(n)
-if n.attr.type=="error"then
-return s(nil,n:get_error());
-end
-local o,a={},{};
-for e in n:get_child("query",i):childtags()do
+self:send_iq(a,function(o)
+if o.attr.type=="error"then
+return s(nil,o:get_error());
+end
+local n,a={},{};
+for e in o:get_child("query",i):childtags()do
 if e.name=="identity"then
-o[e.attr.category.."/"..e.attr.type]=e.attr.name or true;
+n[e.attr.category.."/"..e.attr.type]=e.attr.name or true;
 elseif e.name=="feature"then
 a[e.attr.var]=true;
 end
@@ -5396,10 +5510,10 @@
 if not self.disco.cache[e].nodes[t]then
 self.disco.cache[e].nodes[t]={nodes={}};
 end
-self.disco.cache[e].nodes[t].identities=o;
+self.disco.cache[e].nodes[t].identities=n;
 self.disco.cache[e].nodes[t].features=a;
 else
-self.disco.cache[e].identities=o;
+self.disco.cache[e].identities=n;
 self.disco.cache[e].features=a;
 end
 return s(self.disco.cache[e]);
@@ -5408,17 +5522,17 @@
 function e:disco_items(t,i,n)
 local a=a.iq({to=t,type="get"})
 :tag("query",{xmlns=o,node=i});
-self:send_iq(a,function(a)
-if a.attr.type=="error"then
-return n(nil,a:get_error());
-end
-local e={};
-for t in a:get_child("query",o):childtags()do
-if t.name=="item"then
-table.insert(e,{
-name=t.attr.name;
-jid=t.attr.jid;
-node=t.attr.node;
+self:send_iq(a,function(e)
+if e.attr.type=="error"then
+return n(nil,e:get_error());
+end
+local a={};
+for e in e:get_child("query",o):childtags()do
+if e.name=="item"then
+table.insert(a,{
+name=e.attr.name;
+jid=e.attr.jid;
+node=e.attr.node;
 });
 end
 end
@@ -5429,32 +5543,18 @@
 if not self.disco.cache[t].nodes[i]then
 self.disco.cache[t].nodes[i]={nodes={}};
 end
-self.disco.cache[t].nodes[i].items=e;
-else
-self.disco.cache[t].items=e;
-end
-return n(e);
+self.disco.cache[t].nodes[i].items=a;
+else
+self.disco.cache[t].items=a;
+end
+return n(a);
 end);
 end
-e:hook("iq/"..i,function(o)
-local t=o.tags[1];
-if o.attr.type=='get'and t.name=="query"then
-local t=t.attr.node;
-local n=e.disco.info[t or false];
-if t and t==e.caps.node.."#"..e.caps.hash then
-n=e.disco.info[false];
-end
-local n,s=n.identities,n.features
-local t=a.reply(o):tag("query",{
-xmlns=i,
-node=t,
-});
-for a,e in pairs(n)do
-t:tag('identity',e):up()
-end
-for a in pairs(s)do
-t:tag('feature',{var=a}):up()
-end
+e:hook("iq/"..i,function(t)
+local o=t.tags[1];
+if t.attr.type=='get'and o.name=="query"then
+local o=h(o.attr.node);
+local t=a.reply(t):add_child(o);
 e:send(t);
 return true
 end
@@ -5478,17 +5578,24 @@
 e:hook("ready",function()
 if t then return;end
 t=true;
+local function i(t)
+local a=e.disco.cache[t];
+if a then
+for a in pairs(a.identities)do
+local o,a=a:match("^(.*)/(.*)$");
+print(t,o,a)
+e:event("disco/service-discovered/"..o,{
+type=a,jid=t;
+});
+end
+end
+end
+e:disco_info(e.host,nil,function()
+i(e.host);
+end);
 e:disco_local_services(function(t)
-for t,a in ipairs(t)do
-local t=e.disco.cache[a.jid];
-if t then
-for t in pairs(t.identities)do
-local o,t=t:match("^(.*)/(.*)$");
-e:event("disco/service-discovered/"..o,{
-type=t,jid=a.jid;
-});
-end
-end
+for a,t in ipairs(t)do
+i(t.jid);
 end
 e:event("ready");
 end);
@@ -5502,6 +5609,17 @@
 end
 end)
 package.preload['verse.plugins.version']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local o=require"verse";
 local a="jabber:iq:version";
 local function i(e,t)
@@ -5534,21 +5652,21 @@
 function(o)
 if o.attr.type=="result"then
 local e=o:get_child("query",a);
-local o=e and e:get_child_text("name");
-local a=e and e:get_child_text("version");
+local a=e and e:get_child_text("name");
+local o=e and e:get_child_text("version");
 local e=e and e:get_child_text("os");
 t({
-name=o;
-version=a;
+name=a;
+version=o;
 platform=e;
 });
 else
-local e,o,a=o:get_error();
+local a,e,o=o:get_error();
 t({
 error=true;
-condition=o;
-text=a;
-type=e;
+condition=e;
+text=o;
+type=a;
 });
 end
 end);
@@ -5557,35 +5675,57 @@
 end
 end)
 package.preload['verse.plugins.ping']=(function(...)
-local t=require"verse";
-local i=require"socket".gettime;
-local n="urn:xmpp:ping";
-function t.plugins.ping(e)
-function e:ping(a,o)
-local s=i();
-e:send_iq(t.iq{to=a,type="get"}:tag("ping",{xmlns=n}),
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local a=require"verse";
+local n=require"socket".gettime;
+local i="urn:xmpp:ping";
+function a.plugins.ping(e)
+function e:ping(t,o)
+local s=n();
+e:send_iq(a.iq{to=t,type="get"}:tag("ping",{xmlns=i}),
 function(e)
 if e.attr.type=="error"then
-local t,e,i=e:get_error();
+local i,e,a=e:get_error();
 if e~="service-unavailable"and e~="feature-not-implemented"then
-o(nil,a,{type=t,condition=e,text=i});
+o(nil,t,{type=i,condition=e,text=a});
 return;
 end
 end
-o(i()-s,a);
+o(n()-s,t);
 end);
 end
-e:hook("iq/"..n,function(a)
-return e:send(t.reply(a));
+e:hook("iq/"..i,function(t)
+return e:send(a.reply(t));
 end);
 return true;
 end
 end)
 package.preload['verse.plugins.uptime']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local o=require"verse";
 local t="jabber:iq:last";
-local function a(t,e)
-t.starttime=e.starttime;
+local function a(e,t)
+e.starttime=t.starttime;
 end
 function o.plugins.uptime(e)
 e.uptime={set=a};
@@ -5608,12 +5748,12 @@
 seconds=e or nil;
 });
 else
-local e,o,t=e:get_error();
+local o,t,e=e:get_error();
 a({
 error=true;
-condition=o;
-text=t;
-type=e;
+condition=t;
+text=e;
+type=o;
 });
 end
 end);
@@ -5622,38 +5762,49 @@
 end
 end)
 package.preload['verse.plugins.blocking']=(function(...)
-local a=require"verse";
-local o="urn:xmpp:blocking";
-function a.plugins.blocking(e)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local o=require"verse";
+local a="urn:xmpp:blocking";
+function o.plugins.blocking(e)
 e.blocking={};
 function e.blocking:block_jid(i,t)
-e:send_iq(a.iq{type="set"}
-:tag("block",{xmlns=o})
+e:send_iq(o.iq{type="set"}
+:tag("block",{xmlns=a})
 :tag("item",{jid=i})
 ,function()return t and t(true);end
 ,function()return t and t(false);end
 );
 end
 function e.blocking:unblock_jid(i,t)
-e:send_iq(a.iq{type="set"}
-:tag("unblock",{xmlns=o})
+e:send_iq(o.iq{type="set"}
+:tag("unblock",{xmlns=a})
 :tag("item",{jid=i})
 ,function()return t and t(true);end
 ,function()return t and t(false);end
 );
 end
 function e.blocking:unblock_all_jids(t)
-e:send_iq(a.iq{type="set"}
-:tag("unblock",{xmlns=o})
+e:send_iq(o.iq{type="set"}
+:tag("unblock",{xmlns=a})
 ,function()return t and t(true);end
 ,function()return t and t(false);end
 );
 end
 function e.blocking:get_blocked_jids(t)
-e:send_iq(a.iq{type="get"}
-:tag("blocklist",{xmlns=o})
+e:send_iq(o.iq{type="get"}
+:tag("blocklist",{xmlns=a})
 ,function(e)
-local a=e:get_child("blocklist",o);
+local a=e:get_child("blocklist",a);
 if not a then return t and t(false);end
 local e={};
 for t in a:childtags()do
@@ -5667,24 +5818,35 @@
 end
 end)
 package.preload['verse.plugins.jingle']=(function(...)
-local a=require"verse";
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local o=require"verse";
 local e=require"util.timer";
-local o=require"util.uuid".generate;
+local n=require"util.uuid".generate;
 local i="urn:xmpp:jingle:1";
-local h="urn:xmpp:jingle:errors:1";
+local r="urn:xmpp:jingle:errors:1";
 local t={};
 t.__index=t;
 local e={};
 local e={};
-function a.plugins.jingle(e)
+function o.plugins.jingle(e)
 e:hook("ready",function()
 e:add_disco_feature(i);
 end,10);
-function e:jingle(i)
-return a.eventable(setmetatable(base or{
+function e:jingle(a)
+return o.eventable(setmetatable(base or{
 role="initiator";
-peer=i;
-sid=o();
+peer=a;
+sid=n();
 stream=e;
 },t));
 end
@@ -5693,71 +5855,71 @@
 function e:register_jingle_content_type(e)
 end
 local function u(n)
-local r=n:get_child("jingle",i);
-local s=r.attr.sid;
-local o=r.attr.action;
-local s=e:event("jingle/"..s,n);
-if s==true then
-e:send(a.reply(n));
+local s=n:get_child("jingle",i);
+local a=s.attr.sid;
+local h=s.attr.action;
+local a=e:event("jingle/"..a,n);
+if a==true then
+e:send(o.reply(n));
 return true;
 end
-if o~="session-initiate"then
-local t=a.error_reply(n,"cancel","item-not-found")
-:tag("unknown-session",{xmlns=h}):up();
+if h~="session-initiate"then
+local t=o.error_reply(n,"cancel","item-not-found")
+:tag("unknown-session",{xmlns=r}):up();
 e:send(t);
 return;
 end
-local l=r.attr.sid;
-local o=a.eventable{
+local l=s.attr.sid;
+local a=o.eventable{
 role="receiver";
 peer=n.attr.from;
 sid=l;
 stream=e;
 };
-setmetatable(o,t);
-local s;
-local h,d;
-for t in r:childtags()do
+setmetatable(a,t);
+local h;
+local d,r;
+for t in s:childtags()do
 if t.name=="content"and t.attr.xmlns==i then
-local i=t:child_with_name("description");
-local a=i.attr.xmlns;
-if a then
-local e=e:event("jingle/content/"..a,o,i);
+local o=t:child_with_name("description");
+local i=o.attr.xmlns;
+if i then
+local e=e:event("jingle/content/"..i,a,o);
 if e then
-h=e;
-end
-end
-local a=t:child_with_name("transport");
-local i=a.attr.xmlns;
-d=e:event("jingle/transport/"..i,o,a);
-if h and d then
-s=t;
+d=e;
+end
+end
+local o=t:child_with_name("transport");
+local i=o.attr.xmlns;
+r=e:event("jingle/transport/"..i,a,o);
+if d and r then
+h=t;
 break;
 end
 end
 end
-if not h then
-e:send(a.error_reply(n,"cancel","feature-not-implemented","The specified content is not supported"));
-return true;
-end
 if not d then
-e:send(a.error_reply(n,"cancel","feature-not-implemented","The specified transport is not supported"));
+e:send(o.error_reply(n,"cancel","feature-not-implemented","The specified content is not supported"));
+return true;
+end
+if not r then
+e:send(o.error_reply(n,"cancel","feature-not-implemented","The specified transport is not supported"));
 return true;
 end
-e:send(a.reply(n));
-o.content_tag=s;
-o.creator,o.name=s.attr.creator,s.attr.name;
-o.content,o.transport=h,d;
-function o:decline()
+e:send(o.reply(n));
+a.content_tag=h;
+a.creator,a.name=h.attr.creator,h.attr.name;
+a.content,a.transport=d,r;
+function a:decline()
 end
 e:hook("jingle/"..l,function(e)
-if e.attr.from~=o.peer then
+if e.attr.from~=a.peer then
 return false;
 end
 local e=e:get_child("jingle",i);
-return o:handle_command(e);
+return a:handle_command(e);
 end);
-e:event("jingle",o);
+e:event("jingle",a);
 return true;
 end
 function t:handle_command(a)
@@ -5778,12 +5940,12 @@
 end
 return true;
 end
-function t:send_command(o,t,e)
-local t=a.iq({to=self.peer,type="set"})
+function t:send_command(a,t,e)
+local t=o.iq({to=self.peer,type="set"})
 :tag("jingle",{
 xmlns=i,
 sid=self.sid,
-action=o,
+action=a,
 initiator=self.role=="initiator"and self.stream.jid or nil,
 responder=self.role=="responder"and self.jid or nil,
 }):add_child(t);
@@ -5793,8 +5955,8 @@
 self.stream:send_iq(t,e);
 end
 end
-function t:accept(o)
-local t=a.iq({to=self.peer,type="set"})
+function t:accept(a)
+local t=o.iq({to=self.peer,type="set"})
 :tag("jingle",{
 xmlns=i,
 sid=self.sid,
@@ -5802,9 +5964,9 @@
 responder=e.jid,
 })
 :tag("content",{creator=self.creator,name=self.name});
-local a=self.content:generate_accept(self.content_tag:child_with_name("description"),o);
-t:add_child(a);
-local a=self.transport:generate_accept(self.content_tag:child_with_name("transport"),o);
+local o=self.content:generate_accept(self.content_tag:child_with_name("description"),a);
+t:add_child(o);
+local a=self.transport:generate_accept(self.content_tag:child_with_name("transport"),a);
 t:add_child(a);
 local a=self;
 e:send_iq(t,function(t)
@@ -5823,12 +5985,12 @@
 e:hook("iq/"..i,u);
 return true;
 end
-function t:offer(t,o)
-local e=a.iq({to=self.peer,type="set"})
+function t:offer(t,a)
+local e=o.iq({to=self.peer,type="set"})
 :tag("jingle",{xmlns=i,action="session-initiate",
 initiator=self.stream.jid,sid=self.sid});
 e:tag("content",{creator=self.role,name=t});
-local t=self.stream:event("jingle/describe/"..t,o);
+local t=self.stream:event("jingle/describe/"..t,a);
 if not t then
 return false,"Unknown content type";
 end
@@ -5847,14 +6009,14 @@
 self.stream:send_iq(e,function(e)
 if e.attr.type=="error"then
 self.state="terminated";
-local e,a,t=e:get_error();
-return self:event("error",{type=e,condition=a,text=t});
+local e,t,a=e:get_error();
+return self:event("error",{type=e,condition=t,text=a});
 end
 end);
 self.state="pending";
 end
 function t:terminate(e)
-local e=a.stanza("reason"):tag(e or"success");
+local e=o.stanza("reason"):tag(e or"success");
 self:send_command("session-terminate",e,function(e)
 self.state="terminated";
 self.transport:disconnect();
@@ -5903,26 +6065,37 @@
 end
 end)
 package.preload['verse.plugins.jingle_ft']=(function(...)
-local o=require"verse";
-local i=require"ltn12";
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local i=require"verse";
+local o=require"ltn12";
 local s=package.config:sub(1,1);
-local t="urn:xmpp:jingle:apps:file-transfer:4";
-function o.plugins.jingle_ft(e)
-e:hook("ready",function()
-e:add_disco_feature(t);
+local a="urn:xmpp:jingle:apps:file-transfer:4";
+function i.plugins.jingle_ft(t)
+t:hook("ready",function()
+t:add_disco_feature(a);
 end,10);
-local a={type="file"};
-function a:generate_accept(t,e)
+local n={type="file"};
+function n:generate_accept(t,e)
 if e and e.save_file then
 self.jingle:hook("connected",function()
-local e=i.sink.file(io.open(e.save_file,"w+"));
+local e=o.sink.file(io.open(e.save_file,"w+"));
 self.jingle:set_sink(e);
 end);
 end
 return t;
 end
-local a={__index=a};
-e:hook("jingle/content/"..t,function(t,e)
+local n={__index=n};
+t:hook("jingle/content/"..a,function(t,e)
 local e=e:get_child("file");
 local e={
 name=e:get_child_text("name");
@@ -5930,60 +6103,71 @@
 desc=e:get_child_text("desc");
 date=e:get_child_text("date");
 };
-return setmetatable({jingle=t,file=e},a);
+return setmetatable({jingle=t,file=e},n);
 end);
-e:hook("jingle/describe/file",function(e)
-local a;
+t:hook("jingle/describe/file",function(e)
+local t;
 if e.timestamp then
-a=os.date("!%Y-%m-%dT%H:%M:%SZ",e.timestamp);
-end
-return o.stanza("description",{xmlns=t})
+t=os.date("!%Y-%m-%dT%H:%M:%SZ",e.timestamp);
+end
+return i.stanza("description",{xmlns=a})
 :tag("file")
 :tag("name"):text(e.filename):up()
 :tag("size"):text(tostring(e.size)):up()
-:tag("date"):text(a):up()
+:tag("date"):text(t):up()
 :tag("desc"):text(e.description):up()
 :up();
 end);
-function e:send_file(n,t)
+function t:send_file(i,t)
 local e,a=io.open(t);
 if not e then return e,a;end
-local o=e:seek("end",0);
+local a=e:seek("end",0);
 e:seek("set",0);
-local a=i.source.file(e);
-local e=self:jingle(n);
+local o=o.source.file(e);
+local e=self:jingle(i);
 e:offer("file",{
 filename=t:match("[^"..s.."]+$");
-size=o;
+size=a;
 });
 e:hook("connected",function()
-e:set_source(a,true);
+e:set_source(o,true);
 end);
 return e;
 end
 end
 end)
 package.preload['verse.plugins.jingle_s5b']=(function(...)
-local a=require"verse";
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local t=require"verse";
 local o="urn:xmpp:jingle:transports:s5b:1";
 local r="http://jabber.org/protocol/bytestreams";
-local n=require"util.hashes".sha1;
+local h=require"util.hashes".sha1;
 local s=require"util.uuid".generate;
 local function d(e,t)
 local function a()
 e:unhook("connected",a);
 return true;
 end
-local function o(t)
-e:unhook("incoming-raw",o);
+local function i(t)
+e:unhook("incoming-raw",i);
 if t:sub(1,2)~="\005\000"then
 return e:event("error","connection-failure");
 end
 e:event("connected");
 return true;
 end
-local function i(a)
-e:unhook("incoming-raw",i);
+local function o(a)
+e:unhook("incoming-raw",o);
 if a~="\005\000"then
 local t="version-mismatch";
 if a:sub(1,1)=="\005"then
@@ -5992,21 +6176,21 @@
 return e:event("error",t);
 end
 e:send(string.char(5,1,0,3,#t)..t.."\0\0");
-e:hook("incoming-raw",o,100);
+e:hook("incoming-raw",i,100);
 return true;
 end
 e:hook("connected",a,200);
-e:hook("incoming-raw",i,100);
+e:hook("incoming-raw",o,100);
 e:send("\005\001\000");
 end
-local function h(o,e,i)
-local e=a.new(nil,{
+local function n(a,e,i)
+local e=t.new(nil,{
 streamhosts=e,
 current_host=0;
 });
-local function t(a)
-if a then
-return o(nil,a.reason);
+local function t(o)
+if o then
+return a(nil,o.reason);
 end
 if e.current_host<#e.streamhosts then
 e.current_host=e.current_host+1;
@@ -6028,41 +6212,41 @@
 return true;
 end
 e:unhook("disconnected",t);
-return o(nil);
+return a(nil);
 end
 e:hook("disconnected",t,100);
 e:hook("connected",function()
 e:unhook("disconnected",t);
-o(e.streamhosts[e.current_host],e);
+a(e.streamhosts[e.current_host],e);
 end,100);
 t();
 return e;
 end
-function a.plugins.jingle_s5b(e)
+function t.plugins.jingle_s5b(e)
 e:hook("ready",function()
 e:add_disco_feature(o);
 end,10);
-local t={};
-function t:generate_initiate()
+local a={};
+function a:generate_initiate()
 self.s5b_sid=s();
-local a=a.stanza("transport",{xmlns=o,
+local a=t.stanza("transport",{xmlns=o,
 mode="tcp",sid=self.s5b_sid});
 local t=0;
-for o,i in pairs(e.proxy65.available_streamhosts)do
+for i,o in pairs(e.proxy65.available_streamhosts)do
 t=t+1;
-a:tag("candidate",{jid=o,host=i.host,
-port=i.port,cid=o,priority=t,type="proxy"}):up();
+a:tag("candidate",{jid=i,host=o.host,
+port=o.port,cid=i,priority=t,type="proxy"}):up();
 end
 e:debug("Have %d proxies",t)
 return a;
 end
-function t:generate_accept(e)
-local t={};
-self.s5b_peer_candidates=t;
+function a:generate_accept(e)
+local a={};
+self.s5b_peer_candidates=a;
 self.s5b_mode=e.attr.mode or"tcp";
 self.s5b_sid=e.attr.sid or self.jingle.sid;
 for e in e:childtags()do
-t[e.attr.cid]={
+a[e.attr.cid]={
 type=e.attr.type;
 jid=e.attr.jid;
 host=e.attr.host;
@@ -6071,47 +6255,47 @@
 cid=e.attr.cid;
 };
 end
-local e=a.stanza("transport",{xmlns=o});
-return e;
-end
-function t:connect(i)
+local e=t.stanza("transport",{xmlns=o});
+return e;
+end
+function a:connect(i)
 e:warn("Connecting!");
-local t={};
-for a,e in pairs(self.s5b_peer_candidates or{})do
-t[#t+1]=e;
-end
-if#t>0 then
+local a={};
+for t,e in pairs(self.s5b_peer_candidates or{})do
+a[#a+1]=e;
+end
+if#a>0 then
 self.connecting_peer_candidates=true;
-local function s(t,e)
-self.jingle:send_command("transport-info",a.stanza("content",{creator=self.creator,name=self.name})
+local function s(e,a)
+self.jingle:send_command("transport-info",t.stanza("content",{creator=self.creator,name=self.name})
 :tag("transport",{xmlns=o,sid=self.s5b_sid})
-:tag("candidate-used",{cid=t.cid}));
+:tag("candidate-used",{cid=e.cid}));
 self.onconnect_callback=i;
-self.conn=e;
-end
-local e=n(self.s5b_sid..self.peer..e.jid,true);
-h(s,t,e);
+self.conn=a;
+end
+local e=h(self.s5b_sid..self.peer..e.jid,true);
+n(s,a,e);
 else
 e:warn("Actually, I'm going to wait for my peer to tell me its streamhost...");
 self.onconnect_callback=i;
 end
 end
-function t:info_received(t)
+function a:info_received(a)
 e:warn("Info received");
-local s=t:child_with_name("content");
+local s=a:child_with_name("content");
 local i=s:child_with_name("transport");
 if i:get_child("candidate-used")and not self.connecting_peer_candidates then
-local t=i:child_with_name("candidate-used");
-if t then
-local function d(i,e)
+local a=i:child_with_name("candidate-used");
+if a then
+local function i(i,e)
 if self.jingle.role=="initiator"then
-self.jingle.stream:send_iq(a.iq({to=i.jid,type="set"})
+self.jingle.stream:send_iq(t.iq({to=i.jid,type="set"})
 :tag("query",{xmlns=r,sid=self.s5b_sid})
 :tag("activate"):text(self.jingle.peer),function(i)
 if i.attr.type=="result"then
-self.jingle:send_command("transport-info",a.stanza("content",s.attr)
+self.jingle:send_command("transport-info",t.stanza("content",s.attr)
 :tag("transport",{xmlns=o,sid=self.s5b_sid})
-:tag("activated",{cid=t.attr.cid}));
+:tag("activated",{cid=a.attr.cid}));
 self.conn=e;
 self.onconnect_callback(e);
 else
@@ -6120,25 +6304,25 @@
 end);
 end
 end
-self.jingle.stream:debug("CID: %s",self.jingle.stream.proxy65.available_streamhosts[t.attr.cid]);
+self.jingle.stream:debug("CID: %s",self.jingle.stream.proxy65.available_streamhosts[a.attr.cid]);
 local t={
-self.jingle.stream.proxy65.available_streamhosts[t.attr.cid];
+self.jingle.stream.proxy65.available_streamhosts[a.attr.cid];
 };
-local e=n(self.s5b_sid..e.jid..self.peer,true);
-h(d,t,e);
+local e=h(self.s5b_sid..e.jid..self.peer,true);
+n(i,t,e);
 end
 elseif i:get_child("activated")then
 self.onconnect_callback(self.conn);
 end
 end
-function t:disconnect()
+function a:disconnect()
 if self.conn then
 self.conn:close();
 end
 end
-function t:handle_accepted(e)
-end
-local t={__index=t};
+function a:handle_accepted(e)
+end
+local t={__index=a};
 e:hook("jingle/transport/"..o,function(e)
 return setmetatable({
 role=e.role,
@@ -6150,8 +6334,19 @@
 end
 end)
 package.preload['verse.plugins.proxy65']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local a=require"verse";
-local h=require"util.uuid";
+local d=require"util.uuid";
 local r=require"util.hashes".sha1;
 local n={};
 n.__index=n;
@@ -6222,31 +6417,31 @@
 t:event("proxy65/request",e);
 end);
 end
-function n:new(t,n)
+function n:new(t,h)
 local e=a.new(nil,{
 target_jid=t;
-bytestream_sid=h.generate();
+bytestream_sid=d.generate();
 });
 local o=a.iq{type="set",to=t}
 :tag("query",{xmlns=i,mode="tcp",sid=e.bytestream_sid});
-for t,e in ipairs(n or self.proxies)do
+for t,e in ipairs(h or self.proxies)do
 o:tag("streamhost",e):up();
 end
 self.stream:send_iq(o,function(o)
 if o.attr.type=="error"then
-local t,a,o=o:get_error();
-e:event("connection-failed",{conn=e,type=t,condition=a,text=o});
+local a,t,o=o:get_error();
+e:event("connection-failed",{conn=e,type=a,condition=t,text=o});
 else
 local o=o.tags[1]:get_child("streamhost-used");
 e.streamhost_jid=o.attr.jid;
-local o,h;
-for a,t in ipairs(n or self.proxies)do
+local n,o;
+for a,t in ipairs(h or self.proxies)do
 if t.jid==e.streamhost_jid then
-o,h=t.host,t.port;
+n,o=t.host,t.port;
 break;
 end
 end
-e:connect(o,h);
+e:connect(n,o);
 local function o()
 e:unhook("connected",o);
 local t=a.iq{to=e.streamhost_jid,type="set"}
@@ -6265,10 +6460,10 @@
 end);
 return e;
 end
-function s(i,e,t,o,a)
-local t=r(t..o..a);
-local function i()
-e:unhook("connected",i);
+function s(i,e,a,t,o)
+local a=r(a..t..o);
+local function t()
+e:unhook("connected",t);
 return true;
 end
 local function o(t)
@@ -6279,25 +6474,36 @@
 e:event("connected");
 return true;
 end
-local function a(i)
-e:unhook("incoming-raw",a);
-if i~="\005\000"then
-local t="version-mismatch";
-if i:sub(1,1)=="\005"then
-t="authentication-failure";
-end
-return e:event("error",t);
-end
-e:send(string.char(5,1,0,3,#t)..t.."\0\0");
+local function i(t)
+e:unhook("incoming-raw",i);
+if t~="\005\000"then
+local a="version-mismatch";
+if t:sub(1,1)=="\005"then
+a="authentication-failure";
+end
+return e:event("error",a);
+end
+e:send(string.char(5,1,0,3,#a)..a.."\0\0");
 e:hook("incoming-raw",o,100);
 return true;
 end
-e:hook("connected",i,200);
-e:hook("incoming-raw",a,100);
+e:hook("connected",t,200);
+e:hook("incoming-raw",i,100);
 e:send("\005\001\000");
 end
 end)
 package.preload['verse.plugins.jingle_ibb']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local e=require"verse";
 local i=require"util.encodings".base64;
 local s=require"util.uuid".generate;
@@ -6313,11 +6519,11 @@
 t=e.eventable(t);
 return t;
 end
-function a:initiate(a,e,t)
+function a:initiate(e,t,a)
 self.block=2048;
-self.stanza=t or'iq';
-self.peer=a;
-self.sid=e or tostring(self):match("%x+$");
+self.stanza=a or'iq';
+self.peer=e;
+self.sid=t or tostring(self):match("%x+$");
 self.iseq=0;
 self.oseq=0;
 local e=function(e)
@@ -6325,10 +6531,10 @@
 end
 self.feeder=e;
 print("Hooking incomming IQs");
-local a=self.stream;
-a:hook("iq/"..o,e)
-if t=="message"then
-a:hook("message",e)
+local t=self.stream;
+t:hook("iq/"..o,e)
+if a=="message"then
+t:hook("message",e)
 end
 end
 function a:open(t)
@@ -6476,15 +6682,26 @@
 end
 end)
 package.preload['verse.plugins.pubsub']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local i=require"verse";
-local h=table.insert;
+local n=table.insert;
 local o="http://jabber.org/protocol/pubsub";
-local s="http://jabber.org/protocol/pubsub#owner";
+local h="http://jabber.org/protocol/pubsub#owner";
 local a="http://jabber.org/protocol/pubsub#event";
 local e={};
-local n={__index=e};
+local s={__index=e};
 function i.plugins.pubsub(e)
-e.pubsub=setmetatable({stream=e},n);
+e.pubsub=setmetatable({stream=e},s);
 e:hook("message",function(t)
 local o=t.attr.from;
 for t in t:childtags("event",a)do
@@ -6503,32 +6720,32 @@
 end);
 return true;
 end
-function e:create(e,t,a)
-return self:service(e):node(t):create(nil,a);
-end
-function e:subscribe(e,t,a,o)
-return self:service(e):node(t):subscribe(a,nil,o);
-end
-function e:publish(i,o,t,e,a)
-return self:service(i):node(o):publish(t,nil,e,a);
+function e:create(e,a,t)
+return self:service(e):node(a):create(nil,t);
+end
+function e:subscribe(a,e,o,t)
+return self:service(a):node(e):subscribe(o,nil,t);
+end
+function e:publish(e,a,o,i,t)
+return self:service(e):node(a):publish(o,nil,i,t);
 end
 local a={};
 local t={__index=a};
 function e:service(e)
 return setmetatable({stream=self.stream,service=e},t)
 end
-local function t(r,h,e,a,n,s,t)
-local e=i.iq{type=r or"get",to=h}
-:tag("pubsub",{xmlns=e or o})
-if a then e:tag(a,{node=n,jid=s});end
+local function t(h,e,r,a,s,n,t)
+local e=i.iq{type=h or"get",to=e}
+:tag("pubsub",{xmlns=r or o})
+if a then e:tag(a,{node=s,jid=n});end
 if t then e:tag("item",{id=t~=true and t or nil});end
 return e;
 end
 function a:subscriptions(a)
 self.stream:send_iq(t(nil,self.service,nil,"subscriptions")
-,a and function(i)
-if i.attr.type=="result"then
-local e=i:get_child("pubsub",o);
+,a and function(t)
+if t.attr.type=="result"then
+local e=t:get_child("pubsub",o);
 local e=e and e:get_child("subscriptions");
 local o={};
 if e then
@@ -6536,32 +6753,32 @@
 local e=self:node(t.attr.node)
 e.subscription=t;
 e.subscribed_jid=t.attr.jid;
-h(o,e);
+n(o,e);
 end
 end
 a(o);
 else
-a(false,i:get_error());
+a(false,t:get_error());
 end
 end or nil);
 end
-function a:affiliations(e)
+function a:affiliations(a)
 self.stream:send_iq(t(nil,self.service,nil,"affiliations")
-,e and function(t)
-if t.attr.type=="result"then
-local t=t:get_child("pubsub",o);
-local t=t and t:get_child("affiliations")or{};
-local a={};
-if t then
-for t in t:childtags("affiliation")do
-local e=self:node(t.attr.node)
-e.affiliation=t;
-h(a,e);
-end
-end
-e(a);
-else
-e(false,t:get_error());
+,a and function(e)
+if e.attr.type=="result"then
+local e=e:get_child("pubsub",o);
+local e=e and e:get_child("affiliations")or{};
+local t={};
+if e then
+for e in e:childtags("affiliation")do
+local a=self:node(e.attr.node)
+a.affiliation=e;
+n(t,a);
+end
+end
+a(t);
+else
+a(false,e:get_error());
 end
 end or nil);
 end
@@ -6580,7 +6797,7 @@
 function a:node(e)
 return setmetatable({stream=self.stream,service=self.service,node=e},o)
 end
-function n:__call(t,e)
+function s:__call(t,e)
 local t=self:service(t);
 return e and t:node(e)or t;
 end
@@ -6605,11 +6822,11 @@
 end
 end
 end
-function e:create(e,a)
-if e~=nil then
+function e:create(a,e)
+if a~=nil then
 error("Not implemented yet.");
 else
-self.stream:send_iq(t("set",self.service,nil,"create",self.node),a);
+self.stream:send_iq(t("set",self.service,nil,"create",self.node),e);
 end
 end
 function e:configure(e,a)
@@ -6618,13 +6835,13 @@
 end
 self.stream:send_iq(t("set",self.service,nil,e==nil and"default"or"configure",self.node),a);
 end
-function e:publish(i,a,e,o)
-if a~=nil then
+function e:publish(a,e,o,i)
+if e~=nil then
 error("Node configuration is not implemented yet.");
 end
-self.stream:send_iq(t("set",self.service,nil,"publish",self.node,nil,i or true)
-:add_child(e)
-,o);
+self.stream:send_iq(t("set",self.service,nil,"publish",self.node,nil,a or true)
+:add_child(o)
+,i);
 end
 function e:subscribe(e,o,a)
 e=e or self.stream.jid;
@@ -6660,22 +6877,33 @@
 self.stream:send_iq(t("get",self.service,nil,"items",self.node,nil,e)
 ,a);
 end
-function e:retract(e,a)
-self.stream:send_iq(t("set",self.service,nil,"retract",self.node,nil,e)
-,a);
+function e:retract(a,e)
+self.stream:send_iq(t("set",self.service,nil,"retract",self.node,nil,a)
+,e);
 end
 function e:purge(a,e)
 assert(not a,"Not implemented yet.");
-self.stream:send_iq(t("set",self.service,s,"purge",self.node)
+self.stream:send_iq(t("set",self.service,h,"purge",self.node)
 ,e);
 end
 function e:delete(a,e)
 assert(not a,"Not implemented yet.");
-self.stream:send_iq(t("set",self.service,s,"delete",self.node)
+self.stream:send_iq(t("set",self.service,h,"delete",self.node)
 ,e);
 end
 end)
 package.preload['verse.plugins.pep']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local e=require"verse";
 local t="http://jabber.org/protocol/pubsub";
 local t=t.."#event";
@@ -6700,12 +6928,23 @@
 e:remove_disco_feature(t.."+notify");
 end
 end
-function e:publish_pep(t,a)
-return e.pubsub:service(nil):node(a or t.attr.xmlns):publish(nil,nil,t)
+function e:publish_pep(t,a,o)
+return e.pubsub:service(nil):node(a or t.attr.xmlns):publish(o or"current",nil,t)
 end
 end
 end)
 package.preload['verse.plugins.adhoc']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local o=require"verse";
 local n=require"lib.adhoc";
 local t="http://jabber.org/protocol/commands";
@@ -6717,24 +6956,24 @@
 e:add_plugin("disco");
 e:add_disco_feature(t);
 function e:query_commands(a,o)
-e:disco_items(a,t,function(t)
+e:disco_items(a,t,function(a)
 e:debug("adhoc list returned")
-local a={};
-for o,t in ipairs(t)do
-a[t.node]=t.name;
+local t={};
+for o,a in ipairs(a)do
+t[a.node]=a.name;
 end
 e:debug("adhoc calling callback")
-return o(a);
+return o(t);
 end);
 end
-function e:execute_command(i,o,t)
+function e:execute_command(t,i,o)
 local e=setmetatable({
-stream=e,jid=i,
-command=o,callback=t
+stream=e,jid=t,
+command=i,callback=o
 },a);
 return e:execute();
 end
-local function s(t,e)
+local function h(t,e)
 if not(e)or e=="user"then return true;end
 if type(e)=="function"then
 return e(t);
@@ -6745,24 +6984,24 @@
 e:add_disco_item({jid=e.jid,node=a,name=o},t);
 return i[a];
 end
-local function h(t)
-local a=t.tags[1];
-local a=a.attr.node;
-local a=i[a];
-if not a then return;end
-if not s(t.attr.from,a.permission)then
-e:send(o.error_reply(t,"auth","forbidden","You don't have permission to execute this command"):up()
-:add_child(a:cmdtag("canceled")
+local function s(a)
+local t=a.tags[1];
+local t=t.attr.node;
+local t=i[t];
+if not t then return;end
+if not h(a.attr.from,t.permission)then
+e:send(o.error_reply(a,"auth","forbidden","You don't have permission to execute this command"):up()
+:add_child(t:cmdtag("canceled")
 :tag("note",{type="error"}):text("You don't have permission to execute this command")));
 return true
 end
-return n.handle_cmd(a,{send=function(t)return e:send(t)end},t);
+return n.handle_cmd(t,{send=function(t)return e:send(t)end},a);
 end
 e:hook("iq/"..t,function(e)
-local t=e.attr.type;
-local a=e.tags[1].name;
-if t=="set"and a=="command"then
-return h(e);
+local a=e.attr.type;
+local t=e.tags[1].name;
+if a=="set"and t=="command"then
+return s(e);
 end
 end);
 end
@@ -6786,20 +7025,31 @@
 self:_process_response(e);
 end);
 end
-function a:next(a)
-local e=o.iq({to=self.jid,type="set"})
+function a:next(e)
+local t=o.iq({to=self.jid,type="set"})
 :tag("command",{
 xmlns=t,
 node=self.command,
 sessionid=self.sessionid
 });
-if a then e:add_child(a);end
-self.stream:send_iq(e,function(e)
+if e then t:add_child(e);end
+self.stream:send_iq(t,function(e)
 self:_process_response(e);
 end);
 end
 end)
 package.preload['verse.plugins.presence']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local a=require"verse";
 function a.plugins.presence(t)
 t.last_presence=nil;
@@ -6809,8 +7059,8 @@
 end
 end,1);
 function t:resend_presence()
-if last_presence then
-t:send(last_presence);
+if self.last_presence then
+t:send(self.last_presence);
 end
 end
 function t:set_status(e)
@@ -6819,42 +7069,55 @@
 if e.show then
 a:tag("show"):text(e.show):up();
 end
-if e.prio then
-a:tag("priority"):text(tostring(e.prio)):up();
-end
-if e.msg then
-a:tag("status"):text(e.msg):up();
-end
+if e.priority or e.prio then
+a:tag("priority"):text(tostring(e.priority or e.prio)):up();
+end
+if e.status or e.msg then
+a:tag("status"):text(e.status or e.msg):up();
+end
+elseif type(e)=="string"then
+a:tag("status"):text(e):up();
 end
 t:send(a);
 end
 end
 end)
 package.preload['verse.plugins.private']=(function(...)
-local t=require"verse";
-local a="jabber:iq:private";
-function t.plugins.private(o)
-function o:private_set(o,i,e,n)
-local t=t.iq({type="set"})
-:tag("query",{xmlns=a});
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local a=require"verse";
+local t="jabber:iq:private";
+function a.plugins.private(o)
+function o:private_set(i,o,e,n)
+local t=a.iq({type="set"})
+:tag("query",{xmlns=t});
 if e then
-if e.name==o and e.attr and e.attr.xmlns==i then
+if e.name==i and e.attr and e.attr.xmlns==o then
 t:add_child(e);
 else
-t:tag(o,{xmlns=i})
+t:tag(i,{xmlns=o})
 :add_child(e);
 end
 end
 self:send_iq(t,n);
 end
-function o:private_get(e,o,i)
-self:send_iq(t.iq({type="get"})
-:tag("query",{xmlns=a})
-:tag(e,{xmlns=o}),
-function(t)
-if t.attr.type=="result"then
-local t=t:get_child("query",a);
-local e=t:get_child(e,o);
+function o:private_get(o,e,i)
+self:send_iq(a.iq({type="get"})
+:tag("query",{xmlns=t})
+:tag(o,{xmlns=e}),
+function(a)
+if a.attr.type=="result"then
+local t=a:get_child("query",t);
+local e=t:get_child(o,e);
 i(e);
 end
 end);
@@ -6862,13 +7125,24 @@
 end
 end)
 package.preload['verse.plugins.roster']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local i=require"verse";
-local d=require"util.jid".bare;
+local l=require"util.jid".bare;
 local a="jabber:iq:roster";
 local o="urn:xmpp:features:rosterver";
 local n=table.insert;
 function i.plugins.roster(t)
-local r=false;
+local h=false;
 local e={
 items={};
 ver="";
@@ -6876,7 +7150,7 @@
 t.roster=e;
 t:hook("stream-features",function(e)
 if e:get_child("ver",o)then
-r=true;
+h=true;
 end
 end);
 local function s(t)
@@ -6892,17 +7166,17 @@
 end
 return e;
 end
-local function l(o)
+local function d(a)
 local e={};
-local a={};
-e.groups=a;
-for t,a in pairs(o.attr)do
+local t={};
+e.groups=t;
+for t,a in pairs(a.attr)do
 if t~="xmlns"then
 e[t]=a
 end
 end
-for e in o:childtags("group")do
-n(a,e:get_text())
+for e in a:childtags("group")do
+n(t,e:get_text())
 end
 return e;
 end
@@ -6915,8 +7189,8 @@
 items=e.items,
 };
 end
-function e:add_contact(o,n,h,e)
-local o={jid=o,name=n,groups=h};
+function e:add_contact(n,o,h,e)
+local o={jid=n,name=o,groups=h};
 local a=i.iq({type="set"})
 :tag("query",{xmlns=a})
 :add_child(s(o));
@@ -6945,24 +7219,24 @@
 end
 end);
 end
-local function h(t)
-local t=l(t);
+local function r(t)
+local t=d(t);
 e.items[t.jid]=t;
 end
-local function l(t)
+local function d(t)
 local a=e.items[t];
 e.items[t]=nil;
 return a;
 end
 function e:fetch(o)
-t:send_iq(i.iq({type="get"}):tag("query",{xmlns=a,ver=r and e.ver or nil}),
+t:send_iq(i.iq({type="get"}):tag("query",{xmlns=a,ver=h and e.ver or nil}),
 function(t)
 if t.attr.type=="result"then
 local t=t:get_child("query",a);
 if t then
 e.items={};
 for t in t:childtags("item")do
-h(t)
+r(t)
 end
 e.ver=t.attr.ver or"";
 end
@@ -6972,41 +7246,52 @@
 end
 end);
 end
-t:hook("iq/"..a,function(n)
-local s,o=n.attr.type,n.attr.from;
-if s=="set"and(not o or o==d(t.jid))then
-local s=n:get_child("query",a);
-local o=s and s:get_child("item");
+t:hook("iq/"..a,function(o)
+local s,n=o.attr.type,o.attr.from;
+if s=="set"and(not n or n==l(t.jid))then
+local n=o:get_child("query",a);
+local a=n and n:get_child("item");
+if a then
+local i,o;
+local s=a.attr.jid;
+if a.attr.subscription=="remove"then
+i="removed"
+o=d(s);
+else
+i=e.items[s]and"changed"or"added";
+r(a)
+o=e.items[s];
+end
+e.ver=n.attr.ver;
 if o then
-local n,a;
-local i=o.attr.jid;
-if o.attr.subscription=="remove"then
-n="removed"
-a=l(i);
-else
-n=e.items[i]and"changed"or"added";
-h(o)
-a=e.items[i];
-end
-e.ver=s.attr.ver;
-if a then
-t:event("roster/item-"..n,a);
-end
-end
-t:send(i.reply(n))
+t:event("roster/item-"..i,o);
+end
+end
+t:send(i.reply(o))
 return true;
 end
 end);
 end
 end)
 package.preload['verse.plugins.register']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local t=require"verse";
-local o="jabber:iq:register";
+local i="jabber:iq:register";
 function t.plugins.register(e)
-local function a(i)
-if i:get_child("register","http://jabber.org/features/iq-register")then
+local function a(o)
+if o:get_child("register","http://jabber.org/features/iq-register")then
 local t=t.iq({to=e.host_,type="set"})
-:tag("query",{xmlns=o})
+:tag("query",{xmlns=i})
 :tag("username"):text(e.username):up()
 :tag("password"):text(e.password):up();
 if e.register_email then
@@ -7032,8 +7317,19 @@
 end
 end)
 package.preload['verse.plugins.groupchat']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local i=require"verse";
-local e=require"events";
+local e=require"util.events";
 local n=require"util.jid";
 local a={};
 a.__index=a;
@@ -7051,17 +7347,17 @@
 end
 if t and t.opts.source and e.attr.to~=t.opts.source then return end
 if t then
-local i=select(3,n.split(e.attr.from));
+local o=select(3,n.split(e.attr.from));
 local n=e:get_child_text("body");
-local o=e:get_child("delay",h);
+local i=e:get_child("delay",h);
 local a={
 room_jid=a;
 room=t;
-sender=t.occupants[i];
-nick=i;
+sender=t.occupants[o];
+nick=o;
 body=n;
 stanza=e;
-delay=(o and o.attr.stamp);
+delay=(i and i.attr.stamp);
 };
 local t=t:event(e.name,a);
 return t or(e.name=="message")or nil;
@@ -7175,17 +7471,17 @@
 end
 self:send(e);
 end
-function a:admin_set(e,a,t,o)
+function a:admin_set(a,t,o,e)
 self:send(i.iq({type="set"})
 :query(s.."#admin")
-:tag("item",{nick=e,[a]=t})
-:tag("reason"):text(o or""));
-end
-function a:set_role(e,a,t)
-self:admin_set(e,"role",a,t);
-end
-function a:set_affiliation(e,t,a)
-self:admin_set(e,"affiliation",t,a);
+:tag("item",{nick=a,[t]=o})
+:tag("reason"):text(e or""));
+end
+function a:set_role(t,e,a)
+self:admin_set(t,"role",e,a);
+end
+function a:set_affiliation(a,e,t)
+self:admin_set(a,"affiliation",e,t);
 end
 function a:kick(e,t)
 self:set_role(e,"none",t);
@@ -7195,6 +7491,17 @@
 end
 end)
 package.preload['verse.plugins.vcard']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local i=require"verse";
 local o=require"util.vcard";
 local e="vcard-temp";
@@ -7229,6 +7536,17 @@
 end
 end)
 package.preload['verse.plugins.vcard_update']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local n=require"verse";
 local i="vcard-temp:x:update";
 local s=require("util.hashes").sha1;
@@ -7248,16 +7566,16 @@
 e:add_plugin("vcard");
 e:add_plugin("presence");
 local t;
-local function r(o)
-local a;
-for e=1,#o do
-if o[e].name=="PHOTO"then
-a=o[e][1];
+local function r(a)
+local o;
+for e=1,#a do
+if a[e].name=="PHOTO"then
+o=a[e][1];
 break
 end
 end
-if a then
-local a=s(h(a),true);
+if o then
+local a=s(h(o),true);
 t=n.stanza("x",{xmlns=i})
 :tag("photo"):text(a);
 e:resend_presence()
@@ -7285,19 +7603,30 @@
 end
 end)
 package.preload['verse.plugins.carbons']=(function(...)
-local o=require"verse";
-local a="urn:xmpp:carbons:2";
-local r="urn:xmpp:forward:0";
-local h=os.time;
-local s=require"util.datetime".parse;
-local n=require"util.jid".bare;
-function o.plugins.carbons(e)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local a=require"verse";
+local o="urn:xmpp:carbons:2";
+local n="urn:xmpp:forward:0";
+local s=os.time;
+local r=require"util.datetime".parse;
+local h=require"util.jid".bare;
+function a.plugins.carbons(e)
 local t={};
 t.enabled=false;
 e.carbons=t;
 function t:enable(i)
-e:send_iq(o.iq{type="set"}
-:tag("enable",{xmlns=a})
+e:send_iq(a.iq{type="set"}
+:tag("enable",{xmlns=o})
 ,function(e)
 local e=e.attr.type=="result";
 if e then
@@ -7309,8 +7638,8 @@
 end or nil);
 end
 function t:disable(i)
-e:send_iq(o.iq{type="set"}
-:tag("disable",{xmlns=a})
+e:send_iq(a.iq{type="set"}
+:tag("disable",{xmlns=o})
 ,function(e)
 local e=e.attr.type=="result";
 if e then
@@ -7321,24 +7650,24 @@
 end
 end or nil);
 end
-local o;
+local i;
 e:hook("bind-success",function()
-o=n(e.jid);
+i=h(e.jid);
 end);
-e:hook("message",function(i)
-local t=i:get_child(nil,a);
-if i.attr.from==o and t then
+e:hook("message",function(a)
+local t=a:get_child(nil,o);
+if a.attr.from==i and t then
 local o=t.name;
-local t=t:get_child("forwarded",r);
+local t=t:get_child("forwarded",n);
 local a=t and t:get_child("message","jabber:client");
 local t=t:get_child("delay","urn:xmpp:delay");
 local t=t and t.attr.stamp;
-t=t and s(t);
+t=t and r(t);
 if a then
 return e:event("carbon",{
 dir=o,
 stanza=a,
-timestamp=t or h(),
+timestamp=t or s(),
 });
 end
 end
@@ -7346,75 +7675,85 @@
 end
 end)
 package.preload['verse.plugins.archive']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local a=require"verse";
 local t=require"util.stanza";
-local e="urn:xmpp:mam:0"
-local h="urn:xmpp:forward:0";
-local l="urn:xmpp:delay";
-local o=require"util.uuid".generate;
-local u=require"util.datetime".parse;
-local n=require"util.datetime".datetime;
-local i=require"util.dataforms".new;
-local r=require"util.rsm";
-local c={};
-local m=i{
+local e="urn:xmpp:mam:2"
+local n="urn:xmpp:forward:0";
+local c="urn:xmpp:delay";
+local d=require"util.uuid".generate;
+local m=require"util.datetime".parse;
+local s=require"util.datetime".datetime;
+local o=require"util.dataforms".new;
+local h=require"util.rsm";
+local l={};
+local u=o{
 {name="FORM_TYPE";type="hidden";value=e;};
 {name="with";type="jid-single";};
 {name="start";type="text-single"};
 {name="end";type="text-single";};
 };
-function a.plugins.archive(s)
-function s:query_archive(d,a,s)
-local i=o();
-local o=t.iq{type="set",to=d}
-:tag("query",{xmlns=e,queryid=i});
-local t,d=tonumber(a["start"]),tonumber(a["end"]);
-a["start"]=t and n(t);
-a["end"]=d and n(d);
-o:add_child(m:form(a,"submit"));
-o:add_child(r.generate(a));
-local a={};
-local function n(o)
-local t=o:get_child("fin",e)
-if t and t.attr.queryid==i then
-local e=r.get(t);
-for t,e in pairs(e or c)do a[t]=e;end
-self:unhook("message",n);
-s(a);
+function a.plugins.archive(i)
+function i:query_archive(o,a,r)
+local d=d();
+local o=t.iq{type="set",to=o}
+:tag("query",{xmlns=e,queryid=d});
+local i,t=tonumber(a["start"]),tonumber(a["end"]);
+a["start"]=i and s(i);
+a["end"]=t and s(t);
+o:add_child(u:form(a,"submit"));
+o:add_child(h.generate(a));
+local t={};
+local function i(o)
+local a=o:get_child("result",e);
+if a and a.attr.queryid==d then
+local e=a:get_child("forwarded",n);
+e=e or o:get_child("forwarded",n);
+local o=a.attr.id;
+local a=e:get_child("delay",c);
+local a=a and m(a.attr.stamp)or nil;
+local e=e:get_child("message","jabber:client")
+t[#t+1]={id=o,stamp=a,message=e};
 return true
 end
-local e=o:get_child("result",e);
-if e and e.attr.queryid==i then
-local t=e:get_child("forwarded",h);
-t=t or o:get_child("forwarded",h);
-local o=e.attr.id;
-local e=t:get_child("delay",l);
-local e=e and u(e.attr.stamp)or nil;
-local t=t:get_child("message","jabber:client")
-a[#a+1]={id=o,stamp=e,message=t};
-return true
-end
-end
-self:hook("message",n,1);
-self:send_iq(o,function(e)
-if e.attr.type=="error"then
-self:warn(table.concat({e:get_error()}," "))
-self:unhook("message",n);
-s(false,e:get_error())
-end
+end
+self:hook("message",i,1);
+self:send_iq(o,function(a)
+self:unhook("message",i);
+if a.attr.type=="error"then
+self:warn(table.concat({a:get_error()}," "))
+r(false,a:get_error())
+return true;
+end
+local e=a:get_child("fin",e)
+if e then
+local e=h.get(e);
+for a,e in pairs(e or l)do t[a]=e;end
+end
+r(t);
 return true
 end);
 end
-local i={
+local n={
 always=true,[true]="always",
 never=false,[false]="never",
 roster="roster",
 }
-local function h(t)
+local function s(t)
 local e={};
 local a=t.attr.default;
 if a then
-e[false]=i[a];
+e[false]=n[a];
 end
 local a=t:get_child("always");
 if a then
@@ -7432,11 +7771,11 @@
 end
 return e;
 end
-local function n(o)
+local function h(o)
 local a
 a,o[false]=o[false],nil;
 if a~=nil then
-a=i[a];
+a=n[a];
 end
 local i=t.stanza("prefs",{xmlns=e,default=a})
 local a=t.stanza("always");
@@ -7446,31 +7785,42 @@
 end
 return i:add_child(a):add_child(e);
 end
-function s:archive_prefs_get(a)
+function i:archive_prefs_get(a)
 self:send_iq(t.iq{type="get"}:tag("prefs",{xmlns=e}),
 function(e)
 if e and e.attr.type=="result"and e.tags[1]then
-local t=h(e.tags[1]);
+local t=s(e.tags[1]);
 a(t,e);
 else
 a(nil,e);
 end
 end);
 end
-function s:archive_prefs_set(a,e)
-self:send_iq(t.iq{type="set"}:add_child(n(a)),e);
+function i:archive_prefs_set(e,a)
+self:send_iq(t.iq{type="set"}:add_child(h(e)),a);
 end
 end
 end)
 package.preload['util.http']=(function(...)
-local t,h=string.format,string.char;
-local r,s,i=pairs,ipairs,tonumber;
-local o,d=table.insert,table.concat;
-local function n(e)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local t,n=string.format,string.char;
+local o,s,h=pairs,ipairs,tonumber;
+local i,d=table.insert,table.concat;
+local function r(e)
 return e and(e:gsub("[^a-zA-Z0-9.~_-]",function(e)return t("%%%02x",e:byte());end));
 end
 local function a(e)
-return e and(e:gsub("%%(%x%x)",function(e)return h(i(e,16));end));
+return e and(e:gsub("%%(%x%x)",function(e)return n(h(e,16));end));
 end
 local function e(e)
 return e and(e:gsub("%W",function(e)
@@ -7481,47 +7831,57 @@
 end
 end));
 end
-local function h(t)
+local function n(t)
 local a={};
 if t[1]then
-for i,t in s(t)do
-o(a,e(t.name).."="..e(t.value));
-end
-else
-for t,i in r(t)do
-o(a,e(t).."="..e(i));
+for o,t in s(t)do
+i(a,e(t.name).."="..e(t.value));
+end
+else
+for o,t in o(t)do
+i(a,e(o).."="..e(t));
 end
 end
 return d(a,"&");
 end
 local function s(e)
 if not e:match("=")then return a(e);end
-local i={};
-for t,e in e:gmatch("([^=&]*)=([^&]*)")do
-t,e=t:gsub("%+","%%20"),e:gsub("%+","%%20");
-t,e=a(t),a(e);
-o(i,{name=t,value=e});
-i[t]=e;
-end
-return i;
-end
-local function t(e,t)
+local o={};
+for e,t in e:gmatch("([^=&]*)=([^&]*)")do
+e,t=e:gsub("%+","%%20"),t:gsub("%+","%%20");
+e,t=a(e),a(t);
+i(o,{name=e,value=t});
+o[e]=t;
+end
+return o;
+end
+local function o(e,t)
 e=","..e:gsub("[ \t]",""):lower()..",";
 return e:find(","..t:lower()..",",1,true)~=nil;
 end
 return{
-urlencode=n,urldecode=a;
-formencode=h,formdecode=s;
-contains_token=t;
+urlencode=r,urldecode=a;
+formencode=n,formdecode=s;
+contains_token=o;
 };
 end)
 package.preload['net.http.parser']=(function(...)
-local c=tonumber;
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local m=tonumber;
 local a=assert;
-local g,u=table.insert,table.concat;
-local q=require"socket.url".parse;
+local v=require"socket.url".parse;
 local t=require"util.http".urldecode;
-local function k(e)
+local function b(e)
 e=t((e:gsub("//+","/")));
 if e:sub(1,1)~="/"then
 e="/"..e;
@@ -7539,154 +7899,132 @@
 end
 return e;
 end
-local v={};
-function v.new(f,r,e,l)
-local m=true;
-if not e or e=="server"then m=false;else a(e=="client","Invalid parser type");end
-local e,o,i={},0,true;
-local v=c(l and l().body_size_limit)or 10*1024*1024;
-local p=c(l and l().buffer_size_limit)or v*2;
-local b,a,h;
-local d=nil;
-local n;
+local y={};
+function y.new(c,h,e,y)
+local d=true;
+if not e or e=="server"then d=false;else a(e=="client","Invalid parser type");end
+local e="";
+local p,o,r;
+local s=nil;
 local t;
-local y;
-local s;
+local a;
+local u;
+local n;
 return{
-feed=function(j,w)
-if s then return nil,"parse has failed";end
-if not w then
-if i then e,i=u(e),false;end
-if d and m and not t then
-n.body=e;
-f(n);
+feed=function(l,i)
+if n then return nil,"parse has failed";end
+if not i then
+if s and d and not a then
+t.body=e;
+c(t);
 elseif e~=""then
-s=true;return r("unexpected-eof");
+n=true;return h();
 end
 return;
 end
-if i then
-g(e,w);
-else
-e={e,w};
-i=true;
-end
-o=o+#w;
-if o>p then s=true;return r("max-buffer-size-exceeded");end
-while o>0 do
-if d==nil then
-if i then e,i=u(e),false;end
+e=e..i;
+while#e>0 do
+if s==nil then
 local f=e:find("\r\n\r\n",nil,true);
 if not f then return;end
-local w,h,u,i,g;
-local p;
-local a={};
+local w,r,l,i,g;
+local c;
+local o={};
 for t in e:sub(1,f+1):gmatch("([^\r\n]+)\r\n")do
-if p then
+if c then
 local e,t=t:match("^([^%s:]+): *(.*)$");
-if not e then s=true;return r("invalid-header-line");end
+if not e then n=true;return h("invalid-header-line");end
 e=e:lower();
-a[e]=a[e]and a[e]..","..t or t;
-else
-p=t;
-if m then
-u,i,g=t:match("^HTTP/(1%.[01]) (%d%d%d) (.*)$");
-i=c(i);
-if not i then s=true;return r("invalid-status-line");end
-y=not
-((l and l().method=="HEAD")
+o[e]=o[e]and o[e]..","..t or t;
+else
+c=t;
+if d then
+l,i,g=t:match("^HTTP/(1%.[01]) (%d%d%d) (.*)$");
+i=m(i);
+if not i then n=true;return h("invalid-status-line");end
+u=not
+((y and y().method=="HEAD")
 or(i==204 or i==304 or i==301)
 or(i>=100 and i<200));
 else
-w,h,u=t:match("^(%w+) (%S+) HTTP/(1%.[01])$");
-if not w then s=true;return r("invalid-status-line");end
-end
-end
-end
-if not p then s=true;return r("invalid-status-line");end
-b=y and a["transfer-encoding"]=="chunked";
-t=c(a["content-length"]);
-if t and t>v then s=true;return r("content-length-limit-exceeded");end
-if m then
-if not y then t=0;end
-n={
+w,r,l=t:match("^(%w+) (%S+) HTTP/(1%.[01])$");
+if not w then n=true;return h("invalid-status-line");end
+end
+end
+end
+if not c then n=true;return h("invalid-status-line");end
+p=u and o["transfer-encoding"]=="chunked";
+a=m(o["content-length"]);
+if d then
+if not u then a=0;end
+t={
 code=i;
-httpversion=u;
-headers=a;
-body=y and""or nil;
-responseversion=u;
-responseheaders=a;
+httpversion=l;
+headers=o;
+body=u and""or nil;
+responseversion=l;
+responseheaders=o;
 };
 else
 local e;
-if h:byte()==47 then
-local a,t=h:match("([^?]*).?(.*)");
+if r:byte()==47 then
+local a,t=r:match("([^?]*).?(.*)");
 if t==""then t=nil;end
 e={path=a,query=t};
 else
-e=q(h);
-if not(e and e.path)then s=true;return r("invalid-url");end
-end
-h=k(e.path);
-a.host=e.host or a.host;
-t=t or 0;
-n={
+e=v(r);
+if not(e and e.path)then n=true;return h("invalid-url");end
+end
+r=b(e.path);
+o.host=e.host or o.host;
+a=a or 0;
+t={
 method=w;
 url=e;
-path=h;
-httpversion=u;
-headers=a;
+path=r;
+httpversion=l;
+headers=o;
 body=nil;
 };
 end
 e=e:sub(f+4);
-o=#e;
-d=true;
-end
+s=true;
+end
+if s then
 if d then
-if m then
-if b then
-if h and o-h-2<a then
-return;
-end
-if i then e,i=u(e),false;end
+if p then
 if not e:find("\r\n",nil,true)then
 return;
 end
-if not a then
-a,h=e:match("^(%x+)[^\r\n]*\r\n()");
-a=a and c(a,16);
-if not a then s=true;return r("invalid-chunk-size");end
-end
-if a==0 and e:find("\r\n\r\n",h-2,true)then
-d,a=nil,nil;
+if not o then
+o,r=e:match("^(%x+)[^\r\n]*\r\n()");
+o=o and m(o,16);
+if not o then n=true;return h("invalid-chunk-size");end
+end
+if o==0 and e:find("\r\n\r\n",r-2,true)then
+s,o=nil,nil;
 e=e:gsub("^.-\r\n\r\n","");
-f(n);
-elseif o-h-2>=a then
-n.body=n.body..e:sub(h,h+(a-1));
-e=e:sub(h+a+2);
-o=o-(h+a+2-1);
-a,h=nil,nil;
+c(t);
+elseif#e-r-2>=o then
+t.body=t.body..e:sub(r,r+(o-1));
+e=e:sub(r+o+2);
+o,r=nil,nil;
 else
 break;
 end
-elseif t and o>=t then
-if i then e,i=u(e),false;end
-if n.code==101 then
-n.body,e,o,i=e,{},0,true;
-else
-n.body,e=e:sub(1,t),e:sub(t+1);
-o=#e;
-end
-d=nil;f(n);
+elseif a and#e>=a then
+if t.code==101 then
+t.body,e=e,"";
+else
+t.body,e=e:sub(1,a),e:sub(a+1);
+end
+s=nil;c(t);
 else
 break;
 end
-elseif o>=t then
-if i then e,i=u(e),false;end
-n.body,e=e:sub(1,t),e:sub(t+1);
-o=#e;
-d=nil;f(n);
+elseif#e>=a then
+t.body,e=e:sub(1,a),e:sub(a+1);
+s=nil;c(t);
 else
 break;
 end
@@ -7695,35 +8033,45 @@
 end;
 };
 end
-return v;
+return y;
 end)
 package.preload['net.http']=(function(...)
-local z=require"util.encodings".base64.encode;
-local m=require"socket.url"
-local h=require"net.http.parser".new;
-local u=require"util.http";
-local g=require"util.events";
-local b=pcall(require,"ssl");
-local k=require"net.server"
-local i,o=table.insert,table.concat;
-local w=pairs;
-local v,l,p,s=
-tonumber,tostring,xpcall,debug.traceback;
-local y=error
-local d=require"util.logger".init("http");
-local e=nil;
-local n={};
-local function c(e)return(l(e):match("%x+$"));end
-local r={default_port=80,default_mode="*a"};
-function r.onconnect(t)
-local e=n[t];
+local _ENV=_ENV;
+local function a(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local g=require"socket"
+local b=require"util.encodings".base64.encode;
+local l=require"socket.url"
+local u=require"net.http.parser".new;
+local s=require"util.http";
+local k=pcall(require,"ssl");
+local q=require"net.server"
+local d,o=table.insert,table.concat;
+local m=pairs;
+local y,h,w,f,r=
+tonumber,tostring,xpcall,select,debug.traceback;
+local p,v=assert,error
+local c=require"util.logger".init("http");
+a"http"
+local i={};
+local n={default_port=80,default_mode="*a"};
+function n.onconnect(t)
+local e=i[t];
 local a={e.method or"GET"," ",e.path," HTTP/1.1\r\n"};
 if e.query then
-i(a,4,"?"..e.query);
+d(a,4,"?"..e.query);
 end
 t:write(o(a));
 local a={[2]=": ",[4]="\r\n"};
-for e,i in w(e.headers)do
+for e,i in m(e.headers)do
 a[1],a[3]=e,i;
 t:write(o(a));
 end
@@ -7732,185 +8080,152 @@
 t:write(e.body);
 end
 end
-function r.onincoming(t,a)
-local e=n[t];
+function n.onincoming(a,t)
+local e=i[a];
 if not e then
-d("warn","Received response from connection %s with no request attached!",l(t));
+c("warn","Received response from connection %s with no request attached!",h(a));
 return;
 end
-if a and e.reader then
-e:reader(a);
-end
-end
-function r.ondisconnect(t,a)
-local e=n[t];
+if t and e.reader then
+e:reader(t);
+end
+end
+function n.ondisconnect(t,a)
+local e=i[t];
 if e and e.conn then
-e:reader(nil,a or"closed");
-end
-n[t]=nil;
-end
-function r.ondetach(e)
-n[e]=nil;
-end
-local function o(e)
-if e.conn then
-e.conn=nil;
-e.handler:close()
-end
-end
-local function x(e,i,n)
+e:reader(nil,a);
+end
+i[t]=nil;
+end
+function n.ondetach(e)
+i[e]=nil;
+end
+local function x(e,a,i)
 if not e.parser then
-local function a(t)
+local function o(t)
 if e.callback then
 e.callback(t or"connection-closed",0,e);
 e.callback=nil;
 end
-o(e);
-end
-if not i then
-a(n);
+destroy_request(e);
+end
+if not a then
+o(i);
 return;
 end
-local function i(t)
+local function a(t)
 if e.callback then
 e.callback(t.body,t.code,t,e);
 e.callback=nil;
 end
-o(e);
+destroy_request(e);
 end
 local function t()
 return e;
 end
-e.parser=h(i,a,"client",t);
-end
-e.parser:feed(i);
-end
-local function q(e)d("error","Traceback[http]: %s",s(l(e),2));end
-local function j(e,t,...)
-if not t then
-d("error","Request '%s': error in callback: %s",e,l((...)));
-end
-return...;
-end
-local function f(o,a,t,h)
-local e=m.parse(a);
-e.url=a;
+e.parser=u(a,o,"client",t);
+end
+e.parser:feed(a);
+end
+local function j(e)c("error","Traceback[http]: %s",r(h(e),2));end
+function request(e,t,r)
+local e=l.parse(e);
 if not(e and e.host)then
-h("invalid-url",0,e);
+r(nil,0,e);
 return nil,"invalid-url";
 end
 if not e.path then
 e.path="/";
 end
-e.id=t and t.id or c(e);
-do
-local i={http=o,url=a,request=e,options=t,callback=h};
-local o=o.events.fire_event("pre-request",i);
-if o then
-return o;
-end
-e,a,t,h=i.request,i.url,i.options,i.callback;
-end
-local m,s,c;
-local f,i=e.host,e.port;
-local u=f;
-if(i=="80"and e.scheme=="http")
-or(i=="443"and e.scheme=="https")then
-i=nil;
-elseif i then
-u=u..":"..i;
-end
-s={
-["Host"]=u;
+local l,o,s;
+local u,a=e.host,e.port;
+local d=u;
+if(a=="80"and e.scheme=="http")
+or(a=="443"and e.scheme=="https")then
+a=nil;
+elseif a then
+d=d..":"..a;
+end
+o={
+["Host"]=d;
 ["User-Agent"]="Prosody XMPP Server";
 };
 if e.userinfo then
-s["Authorization"]="Basic "..z(e.userinfo);
+o["Authorization"]="Basic "..b(e.userinfo);
 end
 if t then
 e.onlystatus=t.onlystatus;
-c=t.body;
-if c then
-m="POST";
-s["Content-Length"]=l(#c);
-s["Content-Type"]="application/x-www-form-urlencoded";
-end
-if t.method then m=t.method;end
+s=t.body;
+if s then
+l="POST";
+o["Content-Length"]=h(#s);
+o["Content-Type"]="application/x-www-form-urlencoded";
+end
+if t.method then l=t.method;end
 if t.headers then
-for e,t in w(t.headers)do
-s[e]=t;
-end
-end
-end
-d("debug","Making %s %s request '%s' to %s",e.scheme:upper(),m or"GET",e.id,(t and t.suppress_url and u)or a);
-e.method,e.headers,e.body=m,s,c;
-local s=e.scheme=="https";
-if s and not b then
-y("SSL not available, unable to contact https URL");
-end
-local l=i and v(i)or(s and 443 or 80);
-local i=false;
-if s then
-i=t and t.sslctx or{mode="client",protocol="sslv23",options={"no_sslv2","no_sslv3"}};
-end
-local i,t=k.addclient(f,l,r,"*a",i)
-if not i then
-o.events.fire_event("request-connection-error",{http=o,request=e,url=a,err=t});
-h(t,0,e);
-return nil,t;
-end
-e.handler,e.conn=i,t
+for e,t in m(t.headers)do
+o[e]=t;
+end
+end
+end
+e.method,e.headers,e.body=l,o,s;
+local o=e.scheme=="https";
+if o and not k then
+v("SSL not available, unable to contact https URL");
+end
+local h=a and y(a)or(o and 443 or 80);
+local a=g.tcp();
+a:settimeout(10);
+local d,s=a:connect(u,h);
+if not d and s~="timeout"then
+r(nil,0,e);
+return nil,s;
+end
+local s=false;
+if o then
+s=t and t.sslctx or{mode="client",protocol="sslv23",options={"no_sslv2","no_sslv3"}};
+end
+e.handler,e.conn=p(q.wrapclient(a,u,h,n,"*a",s));
 e.write=function(...)return e.handler:write(...);end
-e.callback=function(i,t,n,s)
-do
-local e={http=o,url=a,request=e,response=n,content=i,code=t,callback=h};
-o.events.fire_event("response",e);
-i,t,n=e.content,e.code,e.response;
-end
-d("debug","Request '%s': Calling callback, status %s",e.id,t or"---");
-return j(e.id,p(function()return h(i,t,s,n)end,q));
-end
+e.callback=function(i,t,o,a)c("debug","Calling callback, status %s",t or"---");return f(2,w(function()return r(i,t,o,a)end,j));end
 e.reader=x;
 e.state="status";
-n[e.handler]=e;
-o.events.fire_event("request",{http=o,request=e,url=a});
-return e;
-end
-local function e(t)
-local e={
-options=t;
-request=f;
-new=t and function(a)
-return e(setmetatable(a,{__index=t}));
-end or e;
-events=g.new();
-request=f;
-};
-return e;
-end
-local t=e();
-return{
-request=function(e,a,o)
-return t:request(e,a,o);
-end;
-new=e;
-events=t.events;
-urlencode=u.urlencode;
-urldecode=u.urldecode;
-formencode=u.formencode;
-formdecode=u.formdecode;
-};
+i[e.handler]=e;
+return e;
+end
+function destroy_request(e)
+if e.conn then
+e.conn=nil;
+e.handler:close()
+end
+end
+local e,t=s.urlencode,s.urldecode;
+local o,a=s.formencode,s.formdecode;
+_M.urlencode,_M.urldecode=e,t;
+_M.formencode,_M.formdecode=o,a;
+return _M;
 end)
 package.preload['verse.bosh']=(function(...)
-local r=require"util.xmppstream".new;
-local h=require"util.stanza";
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local h=require"util.xmppstream".new;
+local i=require"util.stanza";
 require"net.httpclient_listener";
 local o=require"net.http";
 local e=setmetatable({},{__index=verse.stream_mt});
 e.__index=e;
-local s="http://etherx.jabber.org/streams";
-local n="http://jabber.org/protocol/httpbind";
-local i=5;
+local n="http://etherx.jabber.org/streams";
+local s="http://jabber.org/protocol/httpbind";
+local a=5;
 function verse.new_bosh(a,t)
 local t={
 bosh_conn_pool={};
@@ -7932,7 +8247,7 @@
 end
 function e:send(e)
 self:debug("Putting into BOSH send buffer: %s",tostring(e));
-self.bosh_outgoing_buffer[#self.bosh_outgoing_buffer+1]=h.clone(e);
+self.bosh_outgoing_buffer[#self.bosh_outgoing_buffer+1]=i.clone(e);
 self:flush();
 end
 function e:flush()
@@ -7944,20 +8259,20 @@
 self:debug("Flushing...");
 local e=self:_make_body();
 local t=self.bosh_outgoing_buffer;
-for o,a in ipairs(t)do
-e:add_child(a);
-t[o]=nil;
+for a,o in ipairs(t)do
+e:add_child(o);
+t[a]=nil;
 end
 self:_make_request(e);
 else
 self:debug("Decided not to flush.");
 end
 end
-function e:_make_request(t)
-local e,t=o.request(self.bosh_url,{body=tostring(t)},function(o,e,a)
+function e:_make_request(i)
+local e,t=o.request(self.bosh_url,{body=tostring(i)},function(o,e,t)
 if e~=0 then
 self.inactive_since=nil;
-return self:_handle_response(o,e,a);
+return self:_handle_response(o,e,t);
 end
 local e=os.time();
 if not self.inactive_since then
@@ -7966,17 +8281,17 @@
 return self:_disconnected();
 else
 self:debug("%d seconds left to reconnect, retrying in %d seconds...",
-self.bosh_max_inactivity-(e-self.inactive_since),i);
-end
-timer.add_task(i,function()
+self.bosh_max_inactivity-(e-self.inactive_since),a);
+end
+timer.add_task(a,function()
 self:debug("Retrying request...");
-for e,t in ipairs(self.bosh_waiting_requests)do
-if t==a then
+for e,a in ipairs(self.bosh_waiting_requests)do
+if a==t then
 table.remove(self.bosh_waiting_requests,e);
 break;
 end
 end
-self:_make_request(t);
+self:_make_request(i);
 end);
 end);
 if e then
@@ -8018,19 +8333,19 @@
 self:_handle_response_payload(e);
 end);
 end
-function e:_handle_response(t,a,e)
+function e:_handle_response(o,t,e)
 if self.bosh_waiting_requests[1]~=e then
 self:warn("Server replied to request that wasn't the oldest");
-for t,a in ipairs(self.bosh_waiting_requests)do
-if a==e then
-self.bosh_waiting_requests[t]=nil;
+for a,t in ipairs(self.bosh_waiting_requests)do
+if t==e then
+self.bosh_waiting_requests[a]=nil;
 break;
 end
 end
 else
 table.remove(self.bosh_waiting_requests,1);
 end
-local e=self:_parse_response(t);
+local e=self:_parse_response(o);
 if e then
 self:_handle_response_payload(e);
 end
@@ -8040,7 +8355,7 @@
 local e=t.tags;
 for t=1,#e do
 local e=e[t];
-if e.attr.xmlns==s then
+if e.attr.xmlns==n then
 self:event("stream-"..e.name,e);
 elseif e.attr.xmlns then
 self:event("stream/"..e.attr.xmlns,e);
@@ -8056,7 +8371,7 @@
 stream_ns="http://jabber.org/protocol/httpbind",stream_tag="body",
 default_ns="jabber:client",
 streamopened=function(e,t)e.notopen=nil;e.payload=verse.stanza("body",t);return true;end;
-handlestanza=function(t,e)t.payload:add_child(e);end;
+handlestanza=function(e,t)e.payload:add_child(t);end;
 };
 function e:_parse_response(e)
 self:debug("Parsing response: %s",e);
@@ -8066,14 +8381,14 @@
 return;
 end
 local t={notopen=true,stream=self};
-local a=r(t,a);
+local a=h(t,a);
 a:feed(e);
 return t.payload;
 end
 function e:_make_body()
 self.bosh_rid=self.bosh_rid+1;
 local e=verse.stanza("body",{
-xmlns=n;
+xmlns=s;
 content="text/xml; charset=utf-8";
 sid=self.bosh_sid;
 rid=self.bosh_rid;
@@ -8086,10 +8401,21 @@
 end
 end)
 package.preload['verse.client']=(function(...)
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
 local t=require"verse";
 local o=t.stream_mt;
-local h=require"util.jid".split;
-local d=require"net.adns";
+local d=require"util.jid".split;
+local h=require"net.adns";
 local e=require"lxp";
 local a=require"util.stanza";
 t.message,t.presence,t.iq,t.stanza,t.reply,t.error_reply=
@@ -8149,15 +8475,15 @@
 end
 function o:connect_client(e,a)
 self.jid,self.password=e,a;
-self.username,self.host,self.resource=h(e);
+self.username,self.host,self.resource=d(e);
 self:add_plugin("tls");
 self:add_plugin("sasl");
 self:add_plugin("bind");
 self:add_plugin("session");
 function self.data(t,e)
-local a,t=self.stream:feed(e);
-if a then return;end
-self:debug("Received invalid XML (%s) %d bytes: %s",tostring(t),#e,e:sub(1,300):gsub("[\r\n]+"," "));
+local t,a=self.stream:feed(e);
+if t then return;end
+self:debug("Received invalid XML (%s) %d bytes: %s",tostring(a),#e,e:sub(1,300):gsub("[\r\n]+"," "));
 self:close("xml-not-well-formed");
 end
 self:hook("connected",function()self:reopen();end);
@@ -8218,22 +8544,22 @@
 return self:close(e);
 end
 end
-local function t()
+local function a()
 self:connect(self.connect_host or self.host,self.connect_port or 5222);
 end
 if not(self.connect_host or self.connect_port)then
-d.lookup(function(a)
-if a then
+h.lookup(function(t)
+if t then
 local e={};
 self.srv_hosts=e;
-for a,t in ipairs(a)do
+for a,t in ipairs(t)do
 table.insert(e,t.srv);
 end
 table.sort(e,s);
-local a=e[1];
+local t=e[1];
 self.srv_choice=1;
-if a then
-self.connect_host,self.connect_port=a.target,a.port;
+if t then
+self.connect_host,self.connect_port=t.target,t.port;
 self:debug("Best record found, will connect to %s:%d",self.connect_host or self.host,self.connect_port or 5222);
 end
 self:hook("disconnected",function()
@@ -8241,7 +8567,7 @@
 self.srv_choice=self.srv_choice+1;
 local e=e[self.srv_choice];
 self.connect_host,self.connect_port=e.target,e.port;
-t();
+a();
 return true;
 end
 end,1e3);
@@ -8249,10 +8575,10 @@
 self.srv_hosts=nil;
 end,1e3);
 end
-t();
+a();
 end,"_xmpp-client._tcp."..(self.host)..".","SRV");
 else
-t();
+a();
 end
 end
 function o:reopen()
@@ -8260,11 +8586,11 @@
 self:send(a.stanza("stream:stream",{to=self.host,["xmlns:stream"]='http://etherx.jabber.org/streams',
 xmlns="jabber:client",version="1.0"}):top_tag());
 end
-function o:send_iq(e,a)
-local t=self:new_id();
-self.tracked_iqs[t]=a;
-e.attr.id=t;
-self:send(e);
+function o:send_iq(t,a)
+local e=self:new_id();
+self.tracked_iqs[e]=a;
+t.attr.id=e;
+self:send(t);
 end
 function o:new_id()
 self.curr_id=self.curr_id+1;
@@ -8272,15 +8598,26 @@
 end
 end)
 package.preload['verse.component']=(function(...)
-local a=require"verse";
-local o=a.stream_mt;
-local d=require"util.jid".split;
+local _ENV=_ENV;
+local function e(t,...)
+local e=package.loaded[t]or _ENV[t]or{_NAME=t};
+package.loaded[t]=e;
+for t=1,select("#",...)do
+(select(t,...))(e);
+end
+_ENV=e;
+_M=e;
+return e;
+end
+local t=require"verse";
+local a=t.stream_mt;
+local h=require"util.jid".split;
 local e=require"lxp";
-local t=require"util.stanza";
-local r=require"util.sha1".sha1;
-a.message,a.presence,a.iq,a.stanza,a.reply,a.error_reply=
-t.message,t.presence,t.iq,t.stanza,t.reply,t.error_reply;
-local h=require"util.xmppstream".new;
+local o=require"util.stanza";
+local d=require"util.hashes".sha1;
+t.message,t.presence,t.iq,t.stanza,t.reply,t.error_reply=
+o.message,o.presence,o.iq,o.stanza,o.reply,o.error_reply;
+local r=require"util.xmppstream".new;
 local s="http://etherx.jabber.org/streams";
 local i="jabber:component:accept";
 local n={
@@ -8305,23 +8642,23 @@
 end
 return t:event("stanza",e);
 end
-function o:reset()
+function a:reset()
 if self.stream then
 self.stream:reset();
 else
-self.stream=h(self,n);
+self.stream=r(self,n);
 end
 self.notopen=true;
 return true;
 end
-function o:connect_component(e,n)
+function a:connect_component(e,n)
 self.jid,self.password=e,n;
-self.username,self.host,self.resource=d(e);
+self.username,self.host,self.resource=h(e);
 function self.data(t,e)
-local t,a=self.stream:feed(e);
+local t,o=self.stream:feed(e);
 if t then return;end
-o:debug("Received invalid XML (%s) %d bytes: %s",tostring(a),#e,e:sub(1,300):gsub("[\r\n]+"," "));
-o:close("xml-not-well-formed");
+a:debug("Received invalid XML (%s) %d bytes: %s",tostring(o),#e,e:sub(1,300):gsub("[\r\n]+"," "));
+a:close("xml-not-well-formed");
 end
 self:hook("incoming-raw",function(e)return self.data(self.conn,e);end);
 self.curr_id=0;
@@ -8335,30 +8672,30 @@
 end
 end);
 self:hook("stanza",function(e)
-local t;
+local a;
 if e.attr.xmlns==nil or e.attr.xmlns=="jabber:client"then
 if e.name=="iq"and(e.attr.type=="get"or e.attr.type=="set")then
 local o=e.tags[1]and e.tags[1].attr.xmlns;
 if o then
-t=self:event("iq/"..o,e);
-if not t then
-t=self:event("iq",e);
-end
-end
-if t==nil then
-self:send(a.error_reply(e,"cancel","service-unavailable"));
+a=self:event("iq/"..o,e);
+if not a then
+a=self:event("iq",e);
+end
+end
+if a==nil then
+self:send(t.error_reply(e,"cancel","service-unavailable"));
 return true;
 end
 else
-t=self:event(e.name,e);
-end
-end
-return t;
+a=self:event(e.name,e);
+end
+end
+return a;
 end,-1);
 self:hook("opened",function(e)
 print(self.jid,self.stream_id,e.id);
-local e=r(self.stream_id..n,true);
-self:send(t.stanza("handshake",{xmlns=i}):text(e));
+local e=d(self.stream_id..n,true);
+self:send(o.stanza("handshake",{xmlns=i}):text(e));
 self:hook("stream/"..i,function(e)
 if e.name=="handshake"then
 self:event("authentication-success");
@@ -8372,26 +8709,26 @@
 self:connect(self.connect_host or self.host,self.connect_port or 5347);
 self:reopen();
 end
-function o:reopen()
+function a:reopen()
 self:reset();
-self:send(t.stanza("stream:stream",{to=self.jid,["xmlns:stream"]='http://etherx.jabber.org/streams',
+self:send(o.stanza("stream:stream",{to=self.jid,["xmlns:stream"]='http://etherx.jabber.org/streams',
 xmlns=i,version="1.0"}):top_tag());
 end
-function o:close(e)
+function a:close(t)
 if not self.notopen then
 self:send("</stream:stream>");
 end
-local t=self.conn.disconnect();
+local e=self.conn.disconnect();
 self.conn:close();
-t(conn,e);
-end
-function o:send_iq(t,a)
+e(conn,t);
+end
+function a:send_iq(t,a)
 local e=self:new_id();
 self.tracked_iqs[e]=a;
 t.attr.id=e;
 self:send(t);
 end
-function o:new_id()
+function a:new_id()
 self.curr_id=self.curr_id+1;
 return tostring(self.curr_id);
 end
@@ -8402,18 +8739,17 @@
 local a=require"net.server";
 local s=require"util.events";
 local o=require"util.logger";
-local t={};
-local e=t;
-t.server=a;
+local e={};
+e.server=a;
 local t={};
 t.__index=t;
 e.stream_mt=t;
 e.plugins={};
 function e.init(...)
 for e=1,select("#",...)do
-local a,t=pcall(require,"verse."..select(e,...));
-if not a then
-error("Verse connection module not found: verse."..select(e,...)..t);
+local t,a=pcall(require,"verse."..select(e,...));
+if not t then
+error("Verse connection module not found: verse."..select(e,...)..a);
 end
 end
 return e;
@@ -8433,9 +8769,9 @@
 e.logger=o.init;
 e.new_logger=o.init;
 e.log=e.logger("verse");
-local function n(a,...)
-local e,t,o=0,{...},select('#',...);
-return(a:gsub("%%(.)",function(a)if e<=o then e=e+1;return tostring(t[e]);end end));
+local function n(t,...)
+local e,a,o=0,{...},select('#',...);
+return(t:gsub("%%(.)",function(t)if e<=o then e=e+1;return tostring(a[e]);end end));
 end
 function e.set_log_handler(e,t)
 t=t or{"debug","info","warn","error"};
@@ -8455,8 +8791,8 @@
 end
 end
 end
-function e._default_log_handler(o,a,t)
-return io.stderr:write(o,"\t",a,"\t",t,"\n");
+function e._default_log_handler(a,t,o)
+return io.stderr:write(a,"\t",t,"\t",o,"\n");
 end
 e.set_log_handler(e._default_log_handler,{"error"});
 local function o(t)
@@ -8473,7 +8809,7 @@
 return xpcall(a.step,o);
 end
 function e.quit()
-return a.setquitting(true);
+return a.setquitting("once");
 end
 function t:listen(t,o)
 t=t or"localhost";
@@ -8485,18 +8821,18 @@
 end
 return e,a;
 end
-function t:connect(o,i)
-o=o or"localhost";
-i=tonumber(i)or 5222;
+function t:connect(i,o)
+i=i or"localhost";
+o=tonumber(o)or 5222;
 local n=h.tcp()
 n:settimeout(0);
 n:setoption("keepalive",true);
-local s,t=n:connect(o,i);
+local s,t=n:connect(i,o);
 if not s and t~="timeout"then
-self:warn("connect() to %s:%d failed: %s",o,i,t);
+self:warn("connect() to %s:%d failed: %s",i,o,t);
 return self:event("disconnected",{reason=t})or false,t;
 end
-local e=a.wrapclient(n,o,i,e.new_listener(self),"*a");
+local e=a.wrapclient(n,i,o,e.new_listener(self),"*a");
 if not e then
 self:warn("connection initialisation failed: %s",t);
 return self:event("disconnected",{reason=t})or false,t;
@@ -8541,8 +8877,8 @@
 function t:hook(e,...)
 return self.events.add_handler(e,...);
 end
-function t:unhook(t,e)
-return self.events.remove_handler(t,e);
+function t:unhook(e,t)
+return self.events.remove_handler(e,t);
 end
 function e.eventable(e)
 e.events=s.new();
@@ -8582,10 +8918,10 @@
 function a.onincoming(a,e)
 t:event("incoming-raw",e);
 end
-function a.ondisconnect(e,a)
-if e~=t.conn then return end
+function a.ondisconnect(a,e)
+if a~=t.conn then return end
 t.connected=false;
-t:event("disconnected",{reason=a});
+t:event("disconnected",{reason=e});
 end
 function a.ondrain(e)
 t:event("drained");

mercurial