# HG changeset patch # User Matthew Wild # Date 1679596042 0 # Node ID 249197af6c019e88525d73da988d0ba55aa77253 # Parent 8a9bf558aead772cc71d6a0fbcc5e28768923b79 Dockerfile, verse: Add support for sha1 via luaossl diff -r 8a9bf558aead -r 249197af6c01 Dockerfile --- a/Dockerfile Thu Mar 23 15:30:57 2023 +0000 +++ b/Dockerfile Thu Mar 23 18:27:22 2023 +0000 @@ -8,6 +8,7 @@ lua-cjson \ lua-expat \ lua-filesystem \ + lua-luaossl \ lua-sec \ lua-socket \ lua-unbound \ diff -r 8a9bf558aead -r 249197af6c01 verse.lua --- a/verse.lua Thu Mar 23 15:30:57 2023 +0000 +++ b/verse.lua Thu Mar 23 18:27:22 2023 +0000 @@ -23,7 +23,7 @@ }; return _M; end) -package.preload['util.sha1']=(function(...) +package.preload['util.hashes']=(function(...) local _ENV=_ENV; local function e(t,...) local e=package.loaded[t]or _ENV[t]or{_NAME=t}; @@ -35,126 +35,70 @@ _M=e; return e; end -local m=string.len -local o=string.char -local k=string.byte -local q=string.sub -local c=math.floor -local t=require"bit" -local j=t.bnot -local e=t.band -local y=t.bor -local n=t.bxor -local a=t.lshift -local i=t.rshift -local u,r,l,d,h -local function p(t,e) -return a(t,e)+i(t,32-e) -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=c(i/16) -end -return t -end -local function g(t) -local i,a -local n="" -i=m(t)*8 -t=t..o(128) -a=56-e(m(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=c(i/256) -end -return t..n -end -local function b(w) -local m,t,o,a,f,s,c,v -local i,i -local i={} -while(w~="")do -for e=0,15 do -i[e]=0 -for t=1,4 do -i[e]=i[e]*256+k(w,e*4+t) -end -end -for e=16,79 do -i[e]=p(n(n(i[e-3],i[e-8]),n(i[e-14],i[e-16])),1) -end -m=u -t=r -o=l -a=d -f=h -for h=0,79 do -if(h<20)then -s=y(e(t,o),e(j(t),a)) -c=1518500249 -elseif(h<40)then -s=n(n(t,o),a) -c=1859775393 -elseif(h<60)then -s=y(y(e(t,o),e(t,a)),e(o,a)) -c=2400959708 -else -s=n(n(t,o),a) -c=3395469782 -end -v=p(m,5)+s+f+c+i[h] -f=a -a=o -o=p(t,30) -t=m -m=v -end -u=e(u+m,4294967295) -r=e(r+t,4294967295) -l=e(l+o,4294967295) -d=e(d+a,4294967295) -h=e(h+f,4294967295) -w=q(w,65) -end -end -local function a(e,t) -e=g(e) -u=1732584193 -r=4023233417 -l=2562383102 -d=271733878 -h=3285377520 -b(e) -local e=s(u)..s(r)..s(l) -..s(d)..s(h); -if t then -return e; -else -return(e:gsub("..",function(e) -return string.char(tonumber(e,16)); +local function t(t,e) +error("Hash method "..e.." not available",2); +end +local e=setmetatable({},{__index=t}); +local function t(t,o) +local e,a; +if t=="util.sha1"then +e,a=true,require(t) +else +e,a=pcall(require,t); +end +if e then o(a);end +end +local function i(e) +return(e:gsub(".",function(e) +return("%02x"):format(e:byte()); end)); end -end -_G.sha1={sha1=a}; -return _G.sha1; +t("util.sha1",function(t) +e.sha1=t.sha1; +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(a,o,e)return t.pbkdf2(a,o,e,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); +t("openssl.digest",function(o) +local function a(t) +return function(e,a) +local e=o.new(t):final(e); +if a then +return i(e); +end +return e; +end; +end +e.sha1=a("sha1"); +end); +return e; end) package.preload['lib.adhoc']=(function(...) local _ENV=_ENV; -local function d(t,...) +local function r(t,...) local e=package.loaded[t]or _ENV[t]or{_NAME=t}; package.loaded[t]=e; for t=1,select("#",...)do @@ -164,71 +108,71 @@ _M=e; return e; end -local s,l=require"util.stanza",require"util.id".short; -local r="http://jabber.org/protocol/commands"; +local s,i=require"util.stanza",require"util.id".short; +local e="http://jabber.org/protocol/commands"; local n={} local h={}; -local function i(o,e,t,a) -local e=s.stanza("command",{xmlns=r,node=o.node,status=e}); +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(e,o,a,t) -return{name=e,node=o,handler=a,cmdtag=i,permission=(t or"user")}; -end -function h.handle_cmd(o,h,t) -local e=t.tags[1].attr.sessionid or l(); +function h.new(e,a,i,t) +return{name=e,node=a,handler=i,cmdtag=o,permission=(t or"user")}; +end +function h.handle_cmd(o,h,e) +local t=e.tags[1].attr.sessionid or i(); 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,i=o:handler(a,n[e]); -n[e]=i; -local i=s.reply(t); -local t; +a.to=e.attr.to; +a.from=e.attr.from; +a.action=e.tags[1].attr.action or"execute"; +a.form=e.tags[1]:child_with_ns("jabber:x:data"); +local a,i=o:handler(a,n[t]); +n[t]=i; +local i=s.reply(e); +local e; if a.status=="completed"then -n[e]=nil; -t=o:cmdtag("completed",e); +n[t]=nil; +e=o:cmdtag("completed",t); elseif a.status=="canceled"then -n[e]=nil; -t=o:cmdtag("canceled",e); +n[t]=nil; +e=o:cmdtag("canceled",t); elseif a.status=="error"then -n[e]=nil; +n[t]=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); -end -for a,e in pairs(a)do +e=o:cmdtag("executing",t); +end +for a,t in pairs(a)do if a=="info"then -t:tag("note",{type="info"}):text(e):up(); +e:tag("note",{type="info"}):text(t):up(); elseif a=="warn"then -t:tag("note",{type="warn"}):text(e):up(); +e:tag("note",{type="warn"}):text(t):up(); elseif a=="error"then -t:tag("note",{type="error"}):text(e.message):up(); +e:tag("note",{type="error"}):text(t.message):up(); elseif a=="actions"then local a=s.stanza("actions"); -for i,e in ipairs(e)do -if(e=="prev")or(e=="next")or(e=="complete")then -a:tag(e):up(); -else -d:log("error",'Command "'..o.name.. -'" at node "'..o.node..'" provided an invalid action "'..e..'"'); -end -end -t:add_child(a); +for i,t in ipairs(t)do +if(t=="prev")or(t=="next")or(t=="complete")then +a:tag(t):up(); +else +r:log("error",'Command "'..o.name.. +'" at node "'..o.node..'" provided an invalid action "'..t..'"'); +end +end +e:add_child(a); elseif a=="form"then -t:add_child((e.layout or e):form(e.values)); +e:add_child((t.layout or t):form(t.values)); elseif a=="result"then -t:add_child((e.layout or e):form(e.values,"result")); +e:add_child((t.layout or t):form(t.values,"result")); elseif a=="other"then -t:add_child(e); -end -end -i:add_child(t); +e:add_child(t); +end +end +i:add_child(e); h.send(i); return true; end @@ -246,7 +190,293 @@ _M=e; return e; end -return{pack=function(...)return{n=select("#",...);...}end;create=function()return{}end} +return{ +pack=function(...)return{n=select("#",...);...}end; +create=function()return{}end; +move=function(o,t,i,a,e) +e=e or o; +if i>=t then +local n=(i-t)+1; +if a>i or a<=t or o~=e then +for i=0,n-1 do +e[a+i]=o[t+i]; +end +else +for i=n-1,0,-1 do +e[a+i]=o[t+i]; +end +end +end +return e; +end; +} +end) +package.preload['util.sha1']=(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 m=string.len +local a=string.char +local j=string.byte +local k=string.sub +local c=math.floor +local t=require"util.bit" +local q=t.bnot +local e=t.band +local y=t.bor +local n=t.bxor +local i=t.lshift +local o=t.rshift +local l,u,d,h,s +local function p(t,e) +return i(t,e)+o(t,32-e) +end +local function r(i) +local t,o +local t="" +for n=1,8 do +o=e(i,15) +if(o<10)then +t=a(o+48)..t +else +t=a(o+87)..t +end +i=c(i/16) +end +return t +end +local function b(t) +local i,o +local n="" +i=m(t)*8 +t=t..a(128) +o=56-e(m(t),63) +if(o<0)then +o=o+64 +end +for e=1,o do +t=t..a(0) +end +for t=1,8 do +n=a(e(i,255))..n +i=c(i/256) +end +return t..n +end +local function g(f) +local m,t,o,a,w,r,c,v +local i,i +local i={} +while(f~="")do +for e=0,15 do +i[e]=0 +for t=1,4 do +i[e]=i[e]*256+j(f,e*4+t) +end +end +for e=16,79 do +i[e]=p(n(n(i[e-3],i[e-8]),n(i[e-14],i[e-16])),1) +end +m=l +t=u +o=d +a=h +w=s +for s=0,79 do +if(s<20)then +r=y(e(t,o),e(q(t),a)) +c=1518500249 +elseif(s<40)then +r=n(n(t,o),a) +c=1859775393 +elseif(s<60)then +r=y(y(e(t,o),e(t,a)),e(o,a)) +c=2400959708 +else +r=n(n(t,o),a) +c=3395469782 +end +v=p(m,5)+r+w+c+i[s] +w=a +a=o +o=p(t,30) +t=m +m=v +end +l=e(l+m,4294967295) +u=e(u+t,4294967295) +d=e(d+o,4294967295) +h=e(h+a,4294967295) +s=e(s+w,4294967295) +f=k(f,65) +end +end +local function t(e,t) +e=b(e) +l=1732584193 +u=4023233417 +d=2562383102 +h=271733878 +s=3285377520 +g(e) +local e=r(l)..r(u)..r(d) +..r(h)..r(s); +if t then +return e; +else +return(e:gsub("..",function(e) +return string.char(tonumber(e,16)); +end)); +end +end +return{ +sha1=t; +}; +end) +package.preload['util.bit']=(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=type; +local h=tonumber; +local n=setmetatable; +local u=error; +local l=tostring; +local c={[0]=0;[1]=1;[2]=2;[3]=3;[4]=4;[5]=5;[6]=6;[7]=7;[8]=8;[9]=9;[10]=10;[11]=11;[12]=12;[13]=13;[14]=14;[15]=15;[16]=1;[17]=0;[18]=3;[19]=2;[20]=5;[21]=4;[22]=7;[23]=6;[24]=9;[25]=8;[26]=11;[27]=10;[28]=13;[29]=12;[30]=15;[31]=14;[32]=2;[33]=3;[34]=0;[35]=1;[36]=6;[37]=7;[38]=4;[39]=5;[40]=10;[41]=11;[42]=8;[43]=9;[44]=14;[45]=15;[46]=12;[47]=13;[48]=3;[49]=2;[50]=1;[51]=0;[52]=7;[53]=6;[54]=5;[55]=4;[56]=11;[57]=10;[58]=9;[59]=8;[60]=15;[61]=14;[62]=13;[63]=12;[64]=4;[65]=5;[66]=6;[67]=7;[68]=0;[69]=1;[70]=2;[71]=3;[72]=12;[73]=13;[74]=14;[75]=15;[76]=8;[77]=9;[78]=10;[79]=11;[80]=5;[81]=4;[82]=7;[83]=6;[84]=1;[85]=0;[86]=3;[87]=2;[88]=13;[89]=12;[90]=15;[91]=14;[92]=9;[93]=8;[94]=11;[95]=10;[96]=6;[97]=7;[98]=4;[99]=5;[100]=2;[101]=3;[102]=0;[103]=1;[104]=14;[105]=15;[106]=12;[107]=13;[108]=10;[109]=11;[110]=8;[111]=9;[112]=7;[113]=6;[114]=5;[115]=4;[116]=3;[117]=2;[118]=1;[119]=0;[120]=15;[121]=14;[122]=13;[123]=12;[124]=11;[125]=10;[126]=9;[127]=8;[128]=8;[129]=9;[130]=10;[131]=11;[132]=12;[133]=13;[134]=14;[135]=15;[136]=0;[137]=1;[138]=2;[139]=3;[140]=4;[141]=5;[142]=6;[143]=7;[144]=9;[145]=8;[146]=11;[147]=10;[148]=13;[149]=12;[150]=15;[151]=14;[152]=1;[153]=0;[154]=3;[155]=2;[156]=5;[157]=4;[158]=7;[159]=6;[160]=10;[161]=11;[162]=8;[163]=9;[164]=14;[165]=15;[166]=12;[167]=13;[168]=2;[169]=3;[170]=0;[171]=1;[172]=6;[173]=7;[174]=4;[175]=5;[176]=11;[177]=10;[178]=9;[179]=8;[180]=15;[181]=14;[182]=13;[183]=12;[184]=3;[185]=2;[186]=1;[187]=0;[188]=7;[189]=6;[190]=5;[191]=4;[192]=12;[193]=13;[194]=14;[195]=15;[196]=8;[197]=9;[198]=10;[199]=11;[200]=4;[201]=5;[202]=6;[203]=7;[204]=0;[205]=1;[206]=2;[207]=3;[208]=13;[209]=12;[210]=15;[211]=14;[212]=9;[213]=8;[214]=11;[215]=10;[216]=5;[217]=4;[218]=7;[219]=6;[220]=1;[221]=0;[222]=3;[223]=2;[224]=14;[225]=15;[226]=12;[227]=13;[228]=10;[229]=11;[230]=8;[231]=9;[232]=6;[233]=7;[234]=4;[235]=5;[236]=2;[237]=3;[238]=0;[239]=1;[240]=15;[241]=14;[242]=13;[243]=12;[244]=11;[245]=10;[246]=9;[247]=8;[248]=7;[249]=6;[250]=5;[251]=4;[252]=3;[253]=2;[254]=1;[255]=0;}; +local w={[0]=0;[1]=1;[2]=2;[3]=3;[4]=4;[5]=5;[6]=6;[7]=7;[8]=8;[9]=9;[10]=10;[11]=11;[12]=12;[13]=13;[14]=14;[15]=15;[16]=1;[17]=1;[18]=3;[19]=3;[20]=5;[21]=5;[22]=7;[23]=7;[24]=9;[25]=9;[26]=11;[27]=11;[28]=13;[29]=13;[30]=15;[31]=15;[32]=2;[33]=3;[34]=2;[35]=3;[36]=6;[37]=7;[38]=6;[39]=7;[40]=10;[41]=11;[42]=10;[43]=11;[44]=14;[45]=15;[46]=14;[47]=15;[48]=3;[49]=3;[50]=3;[51]=3;[52]=7;[53]=7;[54]=7;[55]=7;[56]=11;[57]=11;[58]=11;[59]=11;[60]=15;[61]=15;[62]=15;[63]=15;[64]=4;[65]=5;[66]=6;[67]=7;[68]=4;[69]=5;[70]=6;[71]=7;[72]=12;[73]=13;[74]=14;[75]=15;[76]=12;[77]=13;[78]=14;[79]=15;[80]=5;[81]=5;[82]=7;[83]=7;[84]=5;[85]=5;[86]=7;[87]=7;[88]=13;[89]=13;[90]=15;[91]=15;[92]=13;[93]=13;[94]=15;[95]=15;[96]=6;[97]=7;[98]=6;[99]=7;[100]=6;[101]=7;[102]=6;[103]=7;[104]=14;[105]=15;[106]=14;[107]=15;[108]=14;[109]=15;[110]=14;[111]=15;[112]=7;[113]=7;[114]=7;[115]=7;[116]=7;[117]=7;[118]=7;[119]=7;[120]=15;[121]=15;[122]=15;[123]=15;[124]=15;[125]=15;[126]=15;[127]=15;[128]=8;[129]=9;[130]=10;[131]=11;[132]=12;[133]=13;[134]=14;[135]=15;[136]=8;[137]=9;[138]=10;[139]=11;[140]=12;[141]=13;[142]=14;[143]=15;[144]=9;[145]=9;[146]=11;[147]=11;[148]=13;[149]=13;[150]=15;[151]=15;[152]=9;[153]=9;[154]=11;[155]=11;[156]=13;[157]=13;[158]=15;[159]=15;[160]=10;[161]=11;[162]=10;[163]=11;[164]=14;[165]=15;[166]=14;[167]=15;[168]=10;[169]=11;[170]=10;[171]=11;[172]=14;[173]=15;[174]=14;[175]=15;[176]=11;[177]=11;[178]=11;[179]=11;[180]=15;[181]=15;[182]=15;[183]=15;[184]=11;[185]=11;[186]=11;[187]=11;[188]=15;[189]=15;[190]=15;[191]=15;[192]=12;[193]=13;[194]=14;[195]=15;[196]=12;[197]=13;[198]=14;[199]=15;[200]=12;[201]=13;[202]=14;[203]=15;[204]=12;[205]=13;[206]=14;[207]=15;[208]=13;[209]=13;[210]=15;[211]=15;[212]=13;[213]=13;[214]=15;[215]=15;[216]=13;[217]=13;[218]=15;[219]=15;[220]=13;[221]=13;[222]=15;[223]=15;[224]=14;[225]=15;[226]=14;[227]=15;[228]=14;[229]=15;[230]=14;[231]=15;[232]=14;[233]=15;[234]=14;[235]=15;[236]=14;[237]=15;[238]=14;[239]=15;[240]=15;[241]=15;[242]=15;[243]=15;[244]=15;[245]=15;[246]=15;[247]=15;[248]=15;[249]=15;[250]=15;[251]=15;[252]=15;[253]=15;[254]=15;[255]=15;}; +local p={[0]=0;[1]=0;[2]=0;[3]=0;[4]=0;[5]=0;[6]=0;[7]=0;[8]=0;[9]=0;[10]=0;[11]=0;[12]=0;[13]=0;[14]=0;[15]=0;[16]=0;[17]=1;[18]=0;[19]=1;[20]=0;[21]=1;[22]=0;[23]=1;[24]=0;[25]=1;[26]=0;[27]=1;[28]=0;[29]=1;[30]=0;[31]=1;[32]=0;[33]=0;[34]=2;[35]=2;[36]=0;[37]=0;[38]=2;[39]=2;[40]=0;[41]=0;[42]=2;[43]=2;[44]=0;[45]=0;[46]=2;[47]=2;[48]=0;[49]=1;[50]=2;[51]=3;[52]=0;[53]=1;[54]=2;[55]=3;[56]=0;[57]=1;[58]=2;[59]=3;[60]=0;[61]=1;[62]=2;[63]=3;[64]=0;[65]=0;[66]=0;[67]=0;[68]=4;[69]=4;[70]=4;[71]=4;[72]=0;[73]=0;[74]=0;[75]=0;[76]=4;[77]=4;[78]=4;[79]=4;[80]=0;[81]=1;[82]=0;[83]=1;[84]=4;[85]=5;[86]=4;[87]=5;[88]=0;[89]=1;[90]=0;[91]=1;[92]=4;[93]=5;[94]=4;[95]=5;[96]=0;[97]=0;[98]=2;[99]=2;[100]=4;[101]=4;[102]=6;[103]=6;[104]=0;[105]=0;[106]=2;[107]=2;[108]=4;[109]=4;[110]=6;[111]=6;[112]=0;[113]=1;[114]=2;[115]=3;[116]=4;[117]=5;[118]=6;[119]=7;[120]=0;[121]=1;[122]=2;[123]=3;[124]=4;[125]=5;[126]=6;[127]=7;[128]=0;[129]=0;[130]=0;[131]=0;[132]=0;[133]=0;[134]=0;[135]=0;[136]=8;[137]=8;[138]=8;[139]=8;[140]=8;[141]=8;[142]=8;[143]=8;[144]=0;[145]=1;[146]=0;[147]=1;[148]=0;[149]=1;[150]=0;[151]=1;[152]=8;[153]=9;[154]=8;[155]=9;[156]=8;[157]=9;[158]=8;[159]=9;[160]=0;[161]=0;[162]=2;[163]=2;[164]=0;[165]=0;[166]=2;[167]=2;[168]=8;[169]=8;[170]=10;[171]=10;[172]=8;[173]=8;[174]=10;[175]=10;[176]=0;[177]=1;[178]=2;[179]=3;[180]=0;[181]=1;[182]=2;[183]=3;[184]=8;[185]=9;[186]=10;[187]=11;[188]=8;[189]=9;[190]=10;[191]=11;[192]=0;[193]=0;[194]=0;[195]=0;[196]=4;[197]=4;[198]=4;[199]=4;[200]=8;[201]=8;[202]=8;[203]=8;[204]=12;[205]=12;[206]=12;[207]=12;[208]=0;[209]=1;[210]=0;[211]=1;[212]=4;[213]=5;[214]=4;[215]=5;[216]=8;[217]=9;[218]=8;[219]=9;[220]=12;[221]=13;[222]=12;[223]=13;[224]=0;[225]=0;[226]=2;[227]=2;[228]=4;[229]=4;[230]=6;[231]=6;[232]=8;[233]=8;[234]=10;[235]=10;[236]=12;[237]=12;[238]=14;[239]=14;[240]=0;[241]=1;[242]=2;[243]=3;[244]=4;[245]=5;[246]=6;[247]=7;[248]=8;[249]=9;[250]=10;[251]=11;[252]=12;[253]=13;[254]=14;[255]=15;} +local y={[0]=15;[1]=14;[2]=13;[3]=12;[4]=11;[5]=10;[6]=9;[7]=8;[8]=7;[9]=6;[10]=5;[11]=4;[12]=3;[13]=2;[14]=1;[15]=0;}; +local d={[0]=0;[1]=0;[2]=1;[3]=1;[4]=2;[5]=2;[6]=3;[7]=3;[8]=4;[9]=4;[10]=5;[11]=5;[12]=6;[13]=6;[14]=7;[15]=7;}; +local r={[0]=0;[1]=8;[2]=0;[3]=8;[4]=0;[5]=8;[6]=0;[7]=8;[8]=0;[9]=8;[10]=0;[11]=8;[12]=0;[13]=8;[14]=0;[15]=8;}; +local b={[0]=0;[1]=2;[2]=4;[3]=6;[4]=8;[5]=10;[6]=12;[7]=14;[8]=0;[9]=2;[10]=4;[11]=6;[12]=8;[13]=10;[14]=12;[15]=14;}; +local v={[0]=0;[1]=0;[2]=0;[3]=0;[4]=0;[5]=0;[6]=0;[7]=0;[8]=1;[9]=1;[10]=1;[11]=1;[12]=1;[13]=1;[14]=1;[15]=1;}; +local m={[0]=0;[1]=0;[2]=0;[3]=0;[4]=0;[5]=0;[6]=0;[7]=0;[8]=8;[9]=8;[10]=8;[11]=8;[12]=8;[13]=8;[14]=8;[15]=8;}; +local i={__tostring=function(e)return("%x%x%x%x%x%x%x%x"):format(e[1],e[2],e[3],e[4],e[5],e[6],e[7],e[8]);end}; +local function s(a,t,e) +return n({ +e[a[1]*16+t[1]]; +e[a[2]*16+t[2]]; +e[a[3]*16+t[3]]; +e[a[4]*16+t[4]]; +e[a[5]*16+t[5]]; +e[a[6]*16+t[6]]; +e[a[7]*16+t[7]]; +e[a[8]*16+t[8]]; +},i); +end +local function a(e,t) +return n({ +t[e[1]]; +t[e[2]]; +t[e[3]]; +t[e[4]]; +t[e[5]]; +t[e[6]]; +t[e[7]]; +t[e[8]]; +},i); +end +local function f(t,e)return s(t,e,c);end +local function c(e,t)return s(e,t,w);end +local function w(e,t)return s(e,t,p);end +local function p(e)return a(e,y);end +local function s(t) +local a=0; +for e=1,8 do +local o=d[t[e]]+a; +a=r[t[e]]; +t[e]=o; +end +end +local function y(e,t) +local e={e[1],e[2],e[3],e[4],e[5],e[6],e[7],e[8]}; +for t=1,t do s(e);end +return n(e,i); +end +local function s(e) +local a=m[e[1]]; +for t=1,8 do +local o=d[e[t]]+a; +a=r[e[t]]; +e[t]=o; +end +end +local function r(e,t) +local e={e[1],e[2],e[3],e[4],e[5],e[6],e[7],e[8]}; +for t=1,t do s(e);end +return n(e,i); +end +local function s(t) +local a=0; +for e=8,1,-1 do +local o=b[t[e]]+a; +a=v[t[e]]; +t[e]=o; +end +end +local function d(e,t) +local e={e[1],e[2],e[3],e[4],e[5],e[6],e[7],e[8]}; +for t=1,t do s(e);end +return n(e,i); +end +local function a(e) +if o(e)=="number"then e=("%x"):format(e); +elseif o(e)=="table"then return e; +elseif o(e)~="string"then u("string expected, got "..o(e),2);end +local a={0,0,0,0,0,0,0,0}; +e="00000000"..e; +e=e:sub(-8); +for t=1,8 do +a[t]=h(e:sub(t,t),16)or u("Number format error",2); +end +return n(a,i); +end +local function t(t) +return function(e,...) +if o(e)~="table"then e=a(e);end +e=t(e,...); +e=h(l(e),16); +if e>2147483647 then e=e-1-4294967295;end +return e; +end; +end +local function i(i) +return function(e,t,...) +if o(e)~="table"then e=a(e);end +if o(t)~="table"then t=a(t);end +e=i(e,t,...); +e=h(l(e),16); +if e>2147483647 then e=e-1-4294967295;end +return e; +end; +end +return{ +bits=32; +bxor=i(f); +bor=i(c); +band=i(w); +bnot=t(p); +lshift=t(d); +rshift=t(y); +arshift=t(r); +cast=t(a); +}; end) package.preload['util.stanza']=(function(...) local _ENV=_ENV; @@ -263,70 +493,70 @@ local a=error; local o=table.insert; local l=table.remove; -local m=table.concat; +local y=table.concat; local d=string.match; -local f=tostring; -local u=setmetatable; -local x=getmetatable; +local p=tostring; +local m=setmetatable; +local q=getmetatable; local h=pairs; local s=ipairs; local t=type; -local j=string.gsub; -local y=string.sub; +local x=string.gsub; +local u=string.sub; local r=string.find; local c=table.move or require"util.table".move; -local b=require"util.table".create; -local v=require"util.encodings".utf8.valid; -local q,p=pcall(require,"util.termcolours"); -local g="urn:ietf:params:xml:ns:xmpp-stanzas"; -local k={xmlns=g}; +local w=require"util.table".create; +local i=require"util.encodings".utf8.valid; +local j,f=pcall(require,"util.termcolours"); +local b="urn:ietf:params:xml:ns:xmpp-stanzas"; +local v={xmlns=b}; local _ENV=nil; local e={__name="stanza"}; e.__index=e; -local function i(t,e) -return not r(t,e and"[^\1\9\10\13\20-\255]"or"[^\9\10\13\20-\255]"); -end -local function n(o,e) +local function n(e,t) +return not r(e,t and"[^\1\9\10\13\20-\255]"or"[^\9\10\13\20-\255]"); +end +local function k(o,e) if t(o)~="string"then a("invalid "..e.." name: expected string, got "..t(o)); elseif#o==0 then a("invalid "..e.." name: empty string"); elseif r(o,"[<>& '\"]")then a("invalid "..e.." name: contains invalid characters"); -elseif not i(o,e=="attribute")then +elseif not n(o,e=="attribute")then a("invalid "..e.." name: contains control characters"); -elseif not v(o)then +elseif not i(o)then a("invalid "..e.." name: contains invalid utf8"); end end -local function w(e,o) +local function g(e,o) if t(e)~="string"then a("invalid "..o.." value: expected string, got "..t(e)); -elseif not i(e,false)then +elseif not n(e,false)then a("invalid "..o.." value: contains control characters"); -elseif not v(e)then +elseif not i(e)then a("invalid "..o.." value: contains invalid utf8"); end end -local function v(e) +local function n(e) if e~=nil then if t(e)~="table"then a("invalid attributes: expected table, got "..t(e)); end -for t,e in h(e)do -n(t,"attribute"); -w(e,"attribute"); +for e,t in h(e)do +k(e,"attribute"); +g(t,"attribute"); end end end local function i(t,a,o) -n(t,"tag"); -v(a); +k(t,"tag"); +n(a); local t={name=t,attr=a or{},namespaces=o,tags={}}; -return u(t,e); +return m(t,e); end local function n(t) -return x(t)==e; +return q(t)==e; end function e:query(e) return self:tag("query",{xmlns=e}); @@ -334,21 +564,21 @@ function e:body(t,e) return self:text_tag("body",t,e); end -function e:text_tag(e,t,o,a) -return self:tag(e,o,a):text(t):up(); -end -function e:tag(t,e,a) -local t=i(t,e,a); +function e:text_tag(a,o,t,e) +return self:tag(a,t,e):text(o):up(); +end +function e:tag(e,t,a) +local t=i(e,t,a); local e=self.last_add; if not e then e={};self.last_add=e;end (e[#e]or self):add_direct_child(t); o(e,t); return self; end -function e:text(t) -if t~=nil and t~=""then -local e=self.last_add; -(e and e[#e]or self):add_direct_child(t); +function e:text(e) +if e~=nil and e~=""then +local t=self.last_add; +(t and t[#t]or self):add_direct_child(e); end return self; end @@ -369,7 +599,7 @@ o(self.tags,e); o(self,e); else -w(e,"text"); +g(e,"text"); o(self,e); end end @@ -378,34 +608,34 @@ (e and e[#e]or self):add_direct_child(t); return self; end -function e:remove_children(a,e) -e=e or self.attr.xmlns; -return self:maptags(function(t) -if(not a or t.name==a)and t.attr.xmlns==e then +function e:remove_children(a,t) +t=t or self.attr.xmlns; +return self:maptags(function(e) +if(not a or e.name==a)and e.attr.xmlns==t then return nil; end -return t; -end); -end -function e:get_child(a,t) +return e; +end); +end +function e:get_child(t,a) for o,e in s(self.tags)do -if(not a or e.name==a) -and((not t and self.attr.xmlns==e.attr.xmlns) -or e.attr.xmlns==t)then +if(not t or e.name==t) +and((not a and self.attr.xmlns==e.attr.xmlns) +or e.attr.xmlns==a)then return e; end end return nil; end -function e:get_child_text(e,t) -local e=self:get_child(e,t); +function e:get_child_text(t,e) +local e=self:get_child(t,e); if e then return e:get_text(); end return nil; end -function e:get_child_attr(e,a,t) -local e=self:get_child(e,a); +function e:get_child_attr(a,e,t) +local e=self:get_child(a,e); if e then return e.attr[t]; end @@ -423,9 +653,9 @@ end return nil; end -function e:get_child_with_attr(e,i,t,o,a) -for e in self:childtags(e,i)do -if(a and a(e.attr[t])or e.attr[t])==o then +function e:get_child_with_attr(e,o,a,i,t) +for e in self:childtags(e,o)do +if(t and t(e.attr[a])or e.attr[a])==i then return e; end end @@ -438,39 +668,39 @@ return t[e]; end,self,e; end -function e:childtags(o,a) +function e:childtags(t,a) local e=self.tags; -local i,t=1,#e; +local i,o=1,#e; return function() -for t=i,t do -local e=e[t]; -if(not o or e.name==o) +for o=i,o do +local e=e[o]; +if(not t or e.name==t) and((not a and self.attr.xmlns==e.attr.xmlns) or e.attr.xmlns==a)then -i=t+1; +i=o+1; return e; end end end; end function e:maptags(h) -local o,t=self.tags,1; -local n,i=#self,#o; +local i,t=self.tags,1; +local n,o=#self,#i; local s=n+1; local e=1; -while t<=i and i>0 do -if self[e]==o[t]then +while t<=o and o>0 do +if self[e]==i[t]then local a=h(self[e]); if a==nil then l(self,e); -l(o,t); +l(i,t); n=n-1; -i=i-1; +o=o-1; e=e-1; t=t-1; else self[e]=a; -o[t]=a; +i[t]=a; end t=t+1; end @@ -486,9 +716,9 @@ local s=#a+1; repeat local o,t,i; -local n=y(a,e,e); +local n=u(a,e,e); if n=="@"then -return self.attr[y(a,e+1)]; +return self.attr[u(a,e+1)]; elseif n=="{"then o,e=d(a,"^([^}]+)}()",e+1); end @@ -503,7 +733,7 @@ self=self:get_child(t,o); until not self end -local function l(t,s) +local function u(t,s) local n={}; for t,e in h(t.attr)do n[t]=e;end local a,i=t.namespaces; @@ -516,33 +746,33 @@ o={}; a={name=t.name,attr=n,namespaces=i,tags=o}; else -o=b(#t.tags,0); -a=b(#t,4); +o=w(#t.tags,0); +a=w(#t,4); a.name=t.name; a.attr=n; a.namespaces=i; a.tags=o; end -u(a,e); +m(a,e); if not s then c(t,1,#t,1,a); c(t.tags,1,#t.tags,1,o); -a:maptags(l); +a:maptags(u); end return a; end -local function u(e,o) +local function l(e,o) if not n(e)then a("bad argument to clone: expected stanza, got "..t(e)); end -return l(e,o); -end -local l={["'"]="'",["\""]=""",["<"]="<",[">"]=">",["&"]="&"}; -local function c(e)return(j(e,"['&<>\"]",l));end -local function l(a,e,s,t,u) +return u(e,o); +end +local u={["'"]="'",["\""]=""",["<"]="<",[">"]=">",["&"]="&"}; +local function m(e)return(x(e,"['&<>\"]",u));end +local function u(a,e,l,t,u) local i=0; -local l=a.name -o(e,"<"..l); +local s=a.name +o(e,"<"..s); for a,n in h(a.attr)do if r(a,"\1",1,true)then local s,a=d(a,"^([^\1]*)\1?(.*)$"); @@ -560,26 +790,26 @@ for i=1,i do local i=a[i]; if i.name then -s(i,e,s,t,a.attr.xmlns); +l(i,e,l,t,a.attr.xmlns); else o(e,t(i)); end end -o(e,""); +o(e,""); end end function e.__tostring(t) local e={}; -l(t,e,l,c,nil); -return m(e); +u(t,e,u,m,nil); +return y(e); end function e.top_tag(e) -local e=u(e,true); -return f(e):sub(1,-3)..">"; +local e=l(e,true); +return p(e):sub(1,-3)..">"; end function e.get_text(e) if#e.tags==0 then -return m(e); +return y(e); end return nil; end @@ -591,7 +821,7 @@ end i=e.attr.type; for i,e in s(e.tags)do -if e.attr.xmlns==g then +if e.attr.xmlns==b then if not a and e.name=="text"then a=e:get_text(); elseif not t then @@ -619,12 +849,12 @@ i=nil; end o:tag("error",{type=a,by=i}) -:tag(s,k); +:tag(s,v); if e and s=="gone"and t(e.uri)=="string"then o:text(e.uri); end o:up(); -if h then o:text_tag("text",h,k);end +if h then o:text_tag("text",h,v);end if e and n(e.tag)then o:add_child(e.tag); elseif e and e.namespace and e.condition then @@ -632,19 +862,19 @@ end return o:up(); end -local function l(a) -local i={name=a.name,attr=a.attr}; -for a,e in s(a)do +local function u(i) +local a={name=i.name,attr=i.attr}; +for i,e in s(i)do if t(e)=="table"then -o(i,l(e)); -else -o(i,e); -end -end -return i; -end -e.__freeze=l; -local function m(a) +o(a,u(e)); +else +o(a,e); +end +end +return a; +end +e.__freeze=u; +local function c(a) if a then local e=a.attr; local o={}; @@ -661,7 +891,7 @@ local o=i(a.name,o); for a,e in s(a)do if t(e)=="table"then -o:add_direct_child(m(e)); +o:add_direct_child(c(e)); elseif t(e)=="string"then o:add_direct_child(e); end @@ -669,14 +899,14 @@ return o; end end -local function y(e,t) -if not t then -return i("message",e); -else -return i("message",e):text_tag("body",t); -end -end -local function v(e) +local function v(t,e) +if not e then +return i("message",t); +else +return i("message",t):text_tag("body",e); +end +end +local function w(e) if not e then a("iq stanzas require id and type attributes"); end @@ -688,7 +918,7 @@ end return i("iq",e); end -local function r(e) +local function h(e) if not n(e)then a("bad argument to reply: expected stanza, got "..t(e)); end @@ -700,15 +930,15 @@ type=((e.name=="iq"and"result")or e.attr.type) }); end -local function w(e,s,h,i,o) +local function y(e,r,o,i,s) if not n(e)then a("bad argument to error_reply: expected stanza, got "..t(e)); elseif e.attr.type=="error"then a("bad argument to error_reply: got stanza of type error which must not be replied to"); end -local e=r(e); +local e=h(e); e.attr.type="error"; -e:add_error(s,h,i,o); +e:add_error(r,o,i,s); e.last_add={e[1]}; return e; end @@ -716,36 +946,36 @@ return i("presence",e); end local s; -if q then -local a,t=p.getstyle,p.getstring; -local n=a("1b3967"); +if j then +local a,t=f.getstyle,f.getstring; +local h=a("1b3967"); local r=a("13b5ea"); local o=a("439639"); -local i=a("a0ce67"); -local h=a("d9541e"); +local n=a("a0ce67"); +local i=a("d9541e"); local a=a("e96d1f"); -local h=( -t(i,"%1").. +local a=( +t(n,"%1").. t(o,"%2").. -t(h,"%3").. +t(i,"%3").. t(a,"%4").. -t(h,"%5") +t(i,"%5") ); -local d=( +local o=( t(o,"%1").. -t(i,"%2").. +t(n,"%2").. t(o,"%3") ); function s(e) -return(e:gsub("(<[?/]?)([^ >/?]*)(.-)([?/]?>)([^<]*)",function(o,e,a,i,s) -return t(n,o)..t(r,e).. -a:gsub("([^=]+)(=)([\"'])(.-)([\"'])",h).. -t(n,i).. -s:gsub("(&#?)(%w+)(;)",d); +return(e:gsub("(<[?/]?)([^ >/?]*)(.-)([?/]?>)([^<]*)",function(e,i,s,n,d) +return t(h,e)..t(r,i).. +s:gsub("([^=]+)(=)([\"'])(.-)([\"'])",a).. +t(h,n).. +d:gsub("(&#?)(%w+)(;)",o); end,100)); end function e.pretty_print(e) -return s(f(e)); +return s(p(e)); end function e.pretty_top_tag(e) return s(e:top_tag()); @@ -754,40 +984,40 @@ e.pretty_print=e.__tostring; e.pretty_top_tag=e.top_tag; end -function e.indent(i,o,a) +function e.indent(i,e,a) if#i==0 or(#i==1 and t(i[1])=="string")then return i; end a=a or"\t"; -o=o or 1; -local e=u(i,true); +e=e or 1; +local o=l(i,true); for i in i:children()do if t(i)=="string"then if i:find("%S")then -e:text("\n"..a:rep(o)); -e:text(i); +o:text("\n"..a:rep(e)); +o:text(i); end elseif n(i)then -e:text("\n"..a:rep(o)); -e:add_direct_child(i:indent(o+1,a)); -end -end -e:text("\n"..a:rep((o-1))); -return e; +o:text("\n"..a:rep(e)); +o:add_direct_child(i:indent(e+1,a)); +end +end +o:text("\n"..a:rep((e-1))); +return o; end return{ stanza_mt=e; stanza=i; is_stanza=n; -preserialize=l; -deserialize=m; -clone=u; -message=y; -iq=v; -reply=r; -error_reply=w; +preserialize=u; +deserialize=c; +clone=l; +message=v; +iq=w; +reply=h; +error_reply=y; presence=d; -xml_escape=c; +xml_escape=m; pretty_print=s; }; end) @@ -807,44 +1037,44 @@ local t=require"util.logger".init("timer"); local e=require"net.server"; local d=require"util.time".now -local l=type; -local h=debug.traceback; -local i=tostring; -local c=require"util.xpcall".xpcall; -local f=math.max; -local m=pairs; +local m=type; +local i=debug.traceback; +local r=tostring; +local f=require"util.xpcall".xpcall; +local c=math.max; +local u=pairs; if e.timer then return e.timer; end local _ENV=nil; -local r=e.add_task; +local h=e.add_task; local o; local s=0; local a=a.create(); local n={}; local e=nil; -local function u(e)t("error","Traceback[timer]: %s",h(i(e),2));end -local function h(i) +local function l(e)t("error","Traceback[timer]: %s",i(r(e),2));end +local function r(o) local t; -local o; +local i; while true do t=a:peek(); -if t==nil or t>i then break;end -local t,a,e=a:pop(); +if t==nil or t>o then break;end +local a,t,e=a:pop(); local s=n[e]; n[e]=nil; -local h,t=c(a,u,i,e,s); -if h and l(t)=="number"then -if o then -o[e]={a,t+i}; -else -o={[e]={a,t+i}}; +local h,a=f(t,l,o,e,s); +if h and m(a)=="number"then +if i then +i[e]={t,a+o}; +else +i={[e]={t,a+o}}; end n[e]=s; end end -if o then -for o,e in m(o)do +if i then +for o,e in u(i)do a:insert(e[1],e[2],o); end t=a:peek(); @@ -855,15 +1085,15 @@ e=t; end if t then -return t-i; +return t-o; end s=s-1; end -local function u(t,u,l) +local function l(t,l,u) local i=d(); local t=i+t; -local a=a:insert(u,t); -n[a]=l; +local a=a:insert(l,t); +n[a]=u; if e==nil or t";end local e={}; for t in t:gmatch("[^;]+")do -h(e,y[o(t)]); -end -return""; +h(e,f[o(t)]); +end +return""; end local function t(e) return e:gsub("\027%[(.-)m",a); end return{ getstring=p; -getstyle=r; +getstyle=s; setstyle=i; tohtml=t; }; @@ -1056,23 +1286,23 @@ _M=e; return e; end -local a=require"util.random"; -local t=a.bytes; -local i=require"util.hex".encode; -local o=math.ceil; +local t=require"util.random"; +local a=t.bytes; +local o=require"util.hex".encode; +local i=math.ceil; local function e(e) -return i(t(o(e/2))):sub(1,e); +return o(a(i(e/2))):sub(1,e); end local function o() -return("%x"):format(t(1):byte()%4+8); -end -local function t() +return("%x"):format(a(1):byte()%4+8); +end +local function a() return e(8).."-"..e(4).."-4"..e(3).."-"..(o())..e(3).."-"..e(12); end return{ get_nibbles=e; -generate=t; -seed=a.seed; +generate=a; +seed=t.seed; }; end) package.preload['util.time']=(function(...) @@ -1087,14 +1317,14 @@ _M=e; return e; end -local o=require"socket".gettime; +local a=require"socket".gettime; local e; -local t,a=pcall(require,"system"); +local t,o=pcall(require,"system"); if t then -e=a.monotime; +e=o.monotime; end return{ -now=o; +now=a; monotonic=e; } end) @@ -1111,18 +1341,18 @@ return e; end local t=load; -local i=io.open; +local n=io.open; local function s(o,a,e) return t(o,a,nil,e); end -local function h(a,o) -local e,i,n=i(a); -if not e then return e,i,n;end -local a,t=t(e:lines(2048),"@"..a,nil,o); +local function i(a,i) +local e,n,o=n(a); +if not e then return e,n,o;end +local a,t=t(e:lines(2048),"@"..a,nil,i); e:close(); return a,t; end -return{envload=s,envloadfile=h}; +return{envload=s,envloadfile=i}; end) package.preload['util.id']=(function(...) local _ENV=_ENV; @@ -1136,12 +1366,12 @@ _M=e; return e; end -local t=string.gsub; -local o=require"util.random".bytes; +local o=string.gsub; +local t=require"util.random".bytes; local a=require"util.encodings".base64.encode; local i={["+"]="-",["/"]="_",["="]=""}; local function e(e) -return(t(a(o(e)),"[+/=]",i)); +return(o(a(t(e)),"[+/=]",i)); end return{ tiny=function()return e(3);end; @@ -1165,30 +1395,30 @@ _M=e; return e; end -local _=getmetatable; -local t,a=next,type; +local u=getmetatable; +local e,o=next,type; local n=string.format; -local z=string.gsub; -local c=string.rep; -local o=string.char; -local k=string.match; -local q=table.concat; -local g=require"util.hex".to; -local p=pcall; +local p=string.gsub; +local y=string.rep; +local a=string.char; +local g=string.match; +local H=table.concat; +local S=require"util.hex".to; +local N=pcall; local v=require"util.envload".envload; if not math.type then require"util.mathcompat" end -local b,j=math.huge,-math.huge; -local x=math.type; -local function h(e) -return t,e,nil; -end -local function s(t,e) -error("Can't serialize "..a(t)..(e and": "..e or"")); -end -local function t(e,t) -return n("{__type=%q,__error=%q}",a(e),t or"fail"); +local z,A=math.huge,-math.huge; +local j=math.type; +local function l(t) +return e,t,nil; +end +local function h(t,e) +error("Can't serialize "..o(t)..(e and": "..e or"")); +end +local function t(t,e) +return n("{__type=%q,__error=%q}",o(t),e or"fail"); end local r={ ['\a']=[[\a]];['\b']=[[\b]]; @@ -1198,12 +1428,12 @@ ['\"']=[[\"]];['\'']=[[\']]; } for t=0,255 do -local e=o(t); +local e=a(t); if not r[e]then r[e]=n("\\%03d",t); end end -local o={ +local a={ ["do"]=true;["and"]=true;["else"]=true;["break"]=true; ["if"]=true;["end"]=true;["goto"]=true;["false"]=true; ["in"]=true;["for"]=true;["then"]=true;["local"]=true; @@ -1211,8 +1441,8 @@ ["elseif"]=true;["function"]=true;["not"]=true; ["repeat"]=true;["return"]=true;["while"]=true; }; -local function u(e) -if a(e)~="table"then +local function s(e) +if o(e)~="table"then e={preset=e}; end local i={ @@ -1241,122 +1471,122 @@ e.equals=e.equals or"="; e.unquoted=true; end -local s=e.fallback or e.fatal==false and t or s; -local function l(e) -return(i[a(e)]or s)(e); -end -local p=e.keywords or o; -local y=e.indentwith or"\t"; -local v=e.itemstart or"\n"; -local I=e.itemsep or";"; -local N=e.itemlast or";\n"; -local O=e.tstart or"{"; -local E=e.tend or"}"; -local T=e.kstart or"["; -local A=e.kend or"]"; -local f=e.equals or" = "; -local w=e.unquoted==true and"^[%a_][%w_]*$"or e.unquoted; +local s=e.fallback or e.fatal==false and t or h; +local function h(e) +return(i[o(e)]or s)(e); +end +local q=e.keywords or a; +local f=e.indentwith or"\t"; +local b=e.itemstart or"\n"; +local v=e.itemsep or";"; +local I=e.itemlast or";\n"; +local w=e.tstart or"{"; +local N=e.tend or"}"; +local k=e.kstart or"["; +local x=e.kend or"]"; +local c=e.equals or" = "; +local m=e.unquoted==true and"^[%a_][%w_]*$"or e.unquoted; local d=e.hex; -local S=e.freeze; -local m=e.maxdepth or 127; -local H=e.multiref; -local R=e.table_iterator or h; -local function u(o,t,e,i) -if t[o]then -t[e],e=s(o,"table has multiple references"),e+1; -return e; -elseif i>m then -t[e],e=s(o,"max table depth reached"),e+1; -return e; -end -local m=o; -t[o]=true; -t[m]=true; -if S==true then -local i=_(o); -if a(i)=="table"then +local T=e.freeze; +local E=e.maxdepth or 127; +local _=e.multiref; +local O=e.table_iterator or l; +local function l(a,t,e,i) +if t[a]then +t[e],e=s(a,"table has multiple references"),e+1; +return e; +elseif i>E then +t[e],e=s(a,"max table depth reached"),e+1; +return e; +end +local d=a; +t[a]=true; +t[d]=true; +if T==true then +local i=u(a); +if o(i)=="table"then local n=i.__name; local i=i.__freeze; -if a(i)=="function"then -o=i(o); -if a(o)=="string"then -t[e],e=o,e+1; -return e; -end -if a(n)=="string"then +if o(i)=="function"then +a=i(a); +if o(a)=="string"then +t[e],e=a,e+1; +return e; +end +if o(n)=="string"then t[e],e=n,e+1; end end end end -t[e],e=O,e+1; -local b=c(y,i); -local s=1; -local h,r; -local d=false; -for o,n in R(o)do -d=true; -t[e],e=v,e+1; +t[e],e=w,e+1; +local p=y(f,i); +local r=1; +local n,u; +local w=false; +for a,s in O(a)do +w=true; t[e],e=b,e+1; -h,r=a(o),a(n); -if o==s then -s=s+1; -elseif w and h=="string"and -not p[o]and k(o,w)then -t[e],e=o,e+1; -t[e],e=f,e+1; -else -t[e],e=T,e+1; -if h=="table"then -e=u(o,t,e,i+1); -else -t[e],e=l(o),e+1; -end -t[e],t[e+1],e=A,f,e+2; -end -if r=="table"then -e=u(n,t,e,i+1); -else -t[e],e=l(n),e+1; -end -t[e],e=I,e+1; -end -if d then -t[e-1]=N; -t[e],e=c(y,i-1),e+1; -end -t[e],e=E,e+1; -if H then -t[o]=nil; -t[m]=nil; +t[e],e=p,e+1; +n,u=o(a),o(s); +if a==r then +r=r+1; +elseif m and n=="string"and +not q[a]and g(a,m)then +t[e],e=a,e+1; +t[e],e=c,e+1; +else +t[e],e=k,e+1; +if n=="table"then +e=l(a,t,e,i+1); +else +t[e],e=h(a),e+1; +end +t[e],t[e+1],e=x,c,e+2; +end +if u=="table"then +e=l(s,t,e,i+1); +else +t[e],e=h(s),e+1; +end +t[e],e=v,e+1; +end +if w then +t[e-1]=I; +t[e],e=y(f,i-1),e+1; +end +t[e],e=N,e+1; +if _ then +t[a]=nil; +t[d]=nil; end return e; end function i.table(t) local e={}; -u(t,e,1,1); -return q(e); -end -local function t(e) -return'"'..z(e,"[%z\1-\31\"\'\\\127-\255]",r)..'"'; -end -if a(d)=="string"then +l(t,e,1,1); +return H(e); +end +local function a(e) +return'"'..p(e,"[%z\1-\31\"\'\\\127-\255]",r)..'"'; +end +if o(d)=="string"then function i.string(e) -local t=t(e); +local t=a(e); if#t>(#e*2+2+#d)then -return d..'"'..g(e)..'"'; +return d..'"'..S(e)..'"'; end return t; end else -i.string=t; +i.string=a; end function i.number(e) -if x(e)=="integer"then +if j(e)=="integer"then return n("%d",e); -elseif e==b then +elseif e==z then return"(1/0)"; -elseif e==j then +elseif e==A then return"(-1/0)"; elseif e~=e then return"(0/0)"; @@ -1369,28 +1599,28 @@ function i.boolean(e) return e and"true"or"false"; end -return l; -end -local function o(e) -if a(e)~="string"then return nil;end +return h; +end +local function i(e) +if o(e)~="string"then return nil;end e="return "..e; local e,t=v(e,"=serialized data",{}); if not e then return nil,t;end -local t,e=p(e); +local t,e=N(e); if not t then return nil,e;end return e; end -local a=u(); +local a=s(); return{ -new=u; +new=s; serialize=function(e,t) if t==nil then return a(e); else -return u(t)(e); +return s(t)(e); end end; -deserialize=o; +deserialize=i; }; end) package.preload['util.indexedbheap']=(function(...) @@ -1406,36 +1636,36 @@ return e; end local d=setmetatable; -local r=math.floor; +local h=math.floor; local i=table.remove; -local function l(t,s,o,n,i) +local function l(t,i,o,n,s) local e=#t+1; while true do -local a=r(e/2); -if a==0 or s>t[a]then break;end +local a=h(e/2); +if a==0 or i>t[a]then break;end t[e]=t[a]; o[e]=o[a]; -i[o[e]]=e; +s[o[e]]=e; e=a; end -t[e]=s; +t[e]=i; o[e]=n; -i[n]=e; -end -local function h(a,e,t,i) -local n=a[e]; -local s=t[e]; +s[n]=e; +end +local function r(t,e,a,n) +local i=t[e]; +local s=a[e]; while e~=1 do -local o=r(e/2); -if n>=a[o]then break;end -a[e]=a[o]; +local o=h(e/2); +if i>=t[o]then break;end t[e]=t[o]; -i[t[e]]=e; +a[e]=a[o]; +n[a[e]]=e; e=o; end -a[e]=n; -t[e]=s; -i[s]=e; +t[e]=i; +a[e]=s; +n[s]=e; return e; end local function n(a,e,o,h) @@ -1462,35 +1692,35 @@ h[n]=e; return e; end -local function r(e,t,o) +local function u(e,t,a) local h=#e; if h==0 then return nil;end local s=e[1]; -local a=t[1]; -o[a]=nil; +local o=t[1]; +a[o]=nil; if h==1 then e[1]=nil; t[1]=nil; -return s,a; +return s,o; end e[1]=i(e); t[1]=i(t); -o[t[1]]=1; -n(e,1,t,o); -return s,a; +a[t[1]]=1; +n(e,1,t,a); +return s,o; end local t={}; -function t:insert(t,a,e) +function t:insert(a,t,e) if e==nil then e=self.current_id; self.current_id=e+1; end -self.items[e]=t; -l(self.priorities,a,self.ids,e,self.index); +self.items[e]=a; +l(self.priorities,t,self.ids,e,self.index); return e; end function t:pop() -local a,e=r(self.priorities,self.ids,self.index); +local a,e=u(self.priorities,self.ids,self.index); if e then local t=self.items[e]; self.items[e]=nil; @@ -1504,7 +1734,7 @@ local e=self.index[e]; if e==nil then return;end self.priorities[e]=t; -e=h(self.priorities,e,self.ids,self.index); +e=r(self.priorities,e,self.ids,self.index); n(self.priorities,e,self.ids,self.index); end function t:remove_index(e) @@ -1521,7 +1751,7 @@ self.index[t]=nil; self.items[t]=nil; if a>e then -e=h(self.priorities,e,self.ids,self.index); +e=r(self.priorities,e,self.ids,self.index); n(self.priorities,e,self.ids,self.index); end return o,s,t; @@ -1575,16 +1805,16 @@ _M=e; return e; end -local r,l,u,f +local d,l,u,m =table.insert,table.sort,table.remove,table.concat; -local h=require"util.table".move; -local s=setmetatable; +local s=require"util.table".move; +local h=setmetatable; local a=getmetatable; -local d=math.random; -local c=math.floor; -local y,p=pairs,ipairs; -local w=tostring; -local m=type; +local r=math.random; +local y=math.floor; +local p,w=pairs,ipairs; +local f=tostring; +local c=type; local i={}; local t={}; local e={}; @@ -1594,15 +1824,15 @@ __tostring=function(e)return"{"..e:concat(", ").."}";end; }; function o:__freeze()return self;end -local function n(i,e,a,t) -if m(e)=="function"then -e=i.collect(e,a,t); -end -return s(e or{},o); -end -function o.__add(t,a) -local e=n(); -return e:append(t):append(a); +local function n(t,e,a,i) +if c(e)=="function"then +e=t.collect(e,a,i); +end +return h(e or{},o); +end +function o.__add(a,e) +local t=n(); +return t:append(a):append(e); end function o.__eq(e,t) if a(e)~=o or a(t)~=o then @@ -1619,76 +1849,76 @@ end return true; end -function o.__div(t,o) -local a=n(); +function o.__div(a,i) +local t=n(); local e=0; -for i=1,#t do -local t=o(t[i]); -if t~=nil then +for o=1,#a do +local a=i(a[o]); +if a~=nil then e=e+1; -a[e]=t; -end -end -return a; -end -s(i,{__call=n}); +t[e]=a; +end +end +return t; +end +h(i,{__call=n}); function e:random() -return self[d(1,#self)]; +return self[r(1,#self)]; end function e:random_other(t) local e=#self; return self[((math.random(1,e-1)+(t-1))%e)+1]; end -function t.map(e,t,a) -for t,o in p(t)do -e[t]=a(o); -end -return e; -end -function t.filter(t,o,n) -local i,a=o==t,#o; +function t.map(e,t,o) +for t,a in w(t)do +e[t]=o(a); +end +return e; +end +function t.filter(t,a,n) +local i,o=a==t,#a; local e=1; -for a=1,a do -local a=o[a]; +for o=1,o do +local a=a[o]; if n(a)then t[e]=a; e=e+1; end end -if i and e<=a then -for e=e,a do +if i and e<=o then +for e=e,o do t[e]=nil; end end return t; end -function t.slice(a,t,o,e) +function t.slice(o,t,a,e) if e==nil then e=-1; end if e<0 then e=#t+(e+1); end -if o<0 then -o=#t+(o+1); -end -if o<1 then -o=1; +if a<0 then +a=#t+(a+1); +end +if a<1 then +a=1; end if e>#t then e=#t; end -if o>e then -for e=1,#a do -a[e]=nil; -end -return a; -end -h(t,o,e,1,a); -if t==a then -h(t,#a+1,#a*2,2+e-o,t); -end -return a; +if a>e then +for e=1,#o do +o[e]=nil; +end +return o; +end +s(t,a,e,1,o); +if t==o then +s(t,#o+1,#o*2,2+e-a,t); +end +return o; end function t.sort(e,t,...) if t~=e then @@ -1697,31 +1927,31 @@ l(e,...); return e; end -function t.unique(o,a) -local e={}; -return t.filter(o,a,function(t) -if e[t]then +function t.unique(o,e) +local a={}; +return t.filter(o,e,function(e) +if a[e]then return false; else -e[t]=true; +a[e]=true; return true; end end); end -function t.pluck(a,e,o,i) -for t=1,#e do -local e=e[t][o]; +function t.pluck(t,e,i,o) +for a=1,#e do +local e=e[a][i]; if e==nil then -e=i; -end -a[t]=e; -end -return a; +e=o; +end +t[a]=e; +end +return t; end function t.reverse(e,i) local t=#i; if i==e then -local a=c(t/2); +local a=y(t/2); t=t+1; local o; for a=1,a do @@ -1739,22 +1969,22 @@ function e:shuffle() local t=#self; for e=1,#self do -local t=d(e,t); +local t=r(e,t); self[e],self[t]=self[t],self[e]; end return self; end function e:append(e) -h(e,1,#e,#self+1,self); +s(e,1,#e,#self+1,self); return self; end function e:push(t) -r(self,t); +d(self,t); return self; end e.pop=u; function e:concat(e) -return f(i.map(self,w),e); +return m(i.map(self,f),e); end function e:length() return#self; @@ -1764,15 +1994,15 @@ while true do e=i(a,e); if e==nil then break;end -r(t,e); -end -return s(t,o); -end -for t,a in y(t)do +d(t,e); +end +return h(t,o); +end +for t,a in p(t)do local a=a; -i[t]=function(t,...) -local o=n(); -return a(o,t,...); +i[t]=function(o,...) +local t=n(); +return a(t,o,...); end e[t]=function(e,...) return a(e,e,...); @@ -1793,15 +2023,15 @@ return e; end local n=tostring; -local m=table.unpack; +local p=table.unpack; local e=table.pack; -local c=require"util.encodings".utf8.valid; +local y=require"util.encodings".utf8.valid; local i=type; -local l=require"util.serialization".new("debug"); -local r=math.type; +local w=require"util.serialization".new("debug"); +local d=math.type; local u={c=true,d=true,i=true,o=true,u=true,X=true,x=true,}; -local f={o=true;u=true;x=true;X=true}; -local d={ +local l={o=true;u=true;x=true;X=true}; +local r={ ["\000"]="\226\144\128",["\001"]="\226\144\129",["\002"]="\226\144\130", ["\003"]="\226\144\131",["\004"]="\226\144\132",["\005"]="\226\144\133", ["\006"]="\226\144\134",["\007"]="\226\144\135",["\008"]="\226\144\136", @@ -1814,10 +2044,10 @@ ["\027"]="\226\144\155",["\028"]="\226\144\156",["\029"]="\226\144\157", ["\030"]="\226\144\158",["\031"]="\226\144\159",["\127"]="\226\144\161", }; -local y=pcall(string.format,"%p",""); -local function w(h,...) +local c=pcall(string.format,"%p",""); +local function f(h,...) local o=e(...); -local w=o.n; +local m=o.n; local a=0; h=h:gsub("%%[^cdiouxXaAeEfgGpqs%%]*[cdiouxXaAeEfgGpqs%%]",function(s) if s=="%%"then return end @@ -1832,7 +2062,7 @@ if t=="s"and i=="string"and not e:find("[%z\1-\31\128-\255]")then return elseif i=="number"then -if t=="g"or(t=="d"and r(e)=="integer")then return end +if t=="g"or(t=="d"and d(e)=="integer")then return end elseif t=="s"and i~="string"then e=n(e); i="string"; @@ -1843,32 +2073,32 @@ t="s"; s="[%s]"; i="string"; -elseif u[t]and r(e)~="integer"then +elseif u[t]and d(e)~="integer"then o[a]=n(e); return"[%s]"; -elseif f[t]and e<0 then +elseif l[t]and e<0 then o[a]=n(e); return"[%s]"; else return end end -if t=="p"and not y then +if t=="p"and not c then e=n(e); t="s"; s="[%s]"; i="string"; end if i=="string"and t~="p"then -if not c(e)then +if not y(e)then t="q"; elseif t~="q"then -o[a]=e:gsub("[%z\1-\8\11-\31\127]",d):gsub("\n\t?","\n\t"); +o[a]=e:gsub("[%z\1-\8\11-\31\127]",r):gsub("\n\t?","\n\t"); return s; end end if t=="q"then -o[a]=l(e); +o[a]=w(e); return"%s"; end if t=="p"and(i=="boolean"or i=="number")then @@ -1876,20 +2106,20 @@ return"[%s]"; end end); -while a=d; -return s(h,"."),t; +a=o(i,t)or 0; +n(r,h(i,t+1,t+a)); +t=t+a+1; +until a==0 or t>=d; +return s(r,"."),t; end e.CNAME=a; e.NS=a e.PTR=a; -local x={ +local p={ __tostring=function(e) return i("%s %s %d %d %d %d %d",e.mname,e.rname,e.serial,e.refresh,e.retry,e.expire,e.minimum); end; }; function e.SOA(n) -local s,h,i; -s,i=a(n,1); -h,i=a(n,i); +local h,s,i; +h,i=a(n,1); +s,i=a(n,i); local -j,q,g,k, -b,l,r,d, -n,a,o,i, -u,w,c,p, -v,y,m,f +m,f,w,y, +v,g,b,j, +x,q,k,c, +u,i,n,a, +o,r,l,d =o(n,i,i+19); return t({ -mname=s; -rname=h; -serial=j*16777216+q*65536+g*256+k; -refresh=b*16777216+l*65536+r*256+d; -retry=n*16777216+a*65536+o*256+i; -expire=u*16777216+w*65536+c*256+p; -minimum=v*16777216+y*65536+m*256+f; -},x); -end -e.A=d; -e.AAAA=d; -local d={ +mname=h; +rname=s; +serial=m*16777216+f*65536+w*256+y; +refresh=v*16777216+g*65536+b*256+j; +retry=x*16777216+q*65536+k*256+c; +expire=u*16777216+i*65536+n*256+a; +minimum=o*16777216+r*65536+l*256+d; +},p); +end +e.A=r; +e.AAAA=r; +local r={ __tostring=function(e) return i("%d %s",e.pref,e.mx) end @@ -2371,43 +2601,43 @@ return t({ pref=a*256+e; mx=i; -},d); -end -local d={ +},r); +end +local r={ __tostring=function(e) return i("%d %d %d %s",e.priority,e.weight,e.port,e.target); end }; function e.SRV(e) -local i=a(e,7); -local e,a,o,n,h,s=o(e,1,6); +local a=a(e,7); +local e,o,h,n,i,s=o(e,1,6); return t({ -priority=e*256+a; -weight=o*256+n; -port=h*256+s; -target=i; -},d); +priority=e*256+o; +weight=h*256+n; +port=i*256+s; +target=a; +},r); end local d={__tostring=s}; function e.TXT(s) local l=#s; -local h,a,i={},1; +local r,a,i={},1; repeat i=o(s,a)or 0; -n(h,r(s,a+1,a+i)); +n(r,h(s,a+1,a+i)); a=a+i+1; until a>=l; -return t(h,d); +return t(r,d); end e.SPF=e.TXT; -local d={ +local r={ [0]="PKIX-CA"; [1]="PKIX-EE"; [2]="DANE-TA"; [3]="DANE-EE"; [255]="PrivCert"; }; -local u={ +local d={ [0]="Cert", [1]="SPKI", [255]="PrivSel", @@ -2418,17 +2648,17 @@ [2]="SHA2-512", [255]="PrivMatch", }; -local m={ +local u={ __tostring=function(e) return i("%s %s %s %s", -d[e.use]or e.use, -u[e.select]or e.select, +r[e.use]or e.use, +d[e.select]or e.select, l[e.match]or e.match, -c(e.data)); +m(e.data)); end; __index={ -getUsage=function(e)return d[e.use]end; -getSelector=function(e)return u[e.select]end; +getUsage=function(e)return r[e.use]end; +getSelector=function(e)return d[e.select]end; getMatchType=function(e)return l[e.match]end; } }; @@ -2438,12 +2668,12 @@ use=i; select=o; match=a; -data=r(e,4); -},m); +data=h(e,4); +},u); end local o={"alpn";"no-default-alpn";"port";"ipv4hint";"ech";"ipv6hint"}; t(o,{__index=function(t,e)return"key"..tostring(e);end}); -local m={ +local f={ __tostring=function(e) local t={}; for a=1,#e.fields do @@ -2452,55 +2682,55 @@ return i("%d %s %s",e.prio,e.name,s(t," ")); end; }; -local r={__tostring=function(e)return s(e,", ");end} +local u={__tostring=function(e)return s(e,", ");end} function e.SVCB(i) local o,s=i:byte(1,2); -local u=o*256+s; -local l,o=a(i,3); -local d={}; +local l=o*256+s; +local d,o=a(i,3); +local r={}; while#i>o do -local s,l=i:byte(o+0,o+1); -local h,a=i:byte(o+2,o+3); -local s=s*256+l; -local h=h*256+a; +local a,s=i:byte(o+0,o+1); +local h,d=i:byte(o+2,o+3); +local s=a*256+s; +local h=h*256+d; local a=i:sub(o+4,o+4-1+h) if s==1 then -a=t(e.TXT(a),r); +a=t(e.TXT(a),u); elseif s==3 then -local e,t=a:byte(1,2); -local e=e*256+t; +local t,e=a:byte(1,2); +local e=t*256+e; a=e; elseif s==4 then local o={}; for t=1,#a,4 do n(o,e.A(a:sub(t,t+3))); end -a=t(o,r); +a=t(o,u); elseif s==6 then local o={}; for t=1,#a,16 do n(o,e.AAAA(a:sub(t,t+15))); end -a=t(o,r); -end -n(d,{key=s,value=a,len=h}); +a=t(o,u); +end +n(r,{key=s,value=a,len=h}); o=o+h+4; end return t({ -prio=u,name=l,fields=d, -},m); +prio=l,name=d,fields=r, +},f); end e.HTTPS=e.SVCB; local o={ TLSA={ -use=d; -select=u; +use=r; +select=d; match=l; }; }; local a={ __tostring=function(e) -return i([[\# %d %s]],#e.raw,c(e.raw)); +return i([[\# %d %s]],#e.raw,m(e.raw)); end; }; local function i(e) @@ -2509,9 +2739,9 @@ t(e,{__index=function()return i end}); return{ parsers=e; -classes=h.classes; -types=h.types; -errors=h.errors; +classes=c.classes; +types=c.types; +errors=c.errors; params=o; }; end) @@ -2527,116 +2757,116 @@ _M=e; return e; end -local f=function(e) +local w=function(e) return _G[e] end -local V,e=require("util.logger").init("socket"),table.concat; -local n=function(...)return V("debug",e{...});end -local j=function(...)return V("warn",e{...});end +local W,e=require("util.logger").init("socket"),table.concat; +local n=function(...)return W("debug",e{...});end +local q=function(...)return W("warn",e{...});end local ie=1 -local w=f"type" -local q=f"pairs" -local oe=f"ipairs" -local b=f"tonumber" -local u=f"tostring" -local t=f"table" -local a=f"string" -local e=f"coroutine" -local W=math.min -local te=math.huge -local ye=t.concat -local ae=t.insert -local be=a.sub -local pe=e.wrap -local ke=e.yield -local x=f"socket"or require"socket" -local P=x.gettime +local f=w"type" +local j=w"pairs" +local ne=w"ipairs" +local p=w"tonumber" +local u=w"tostring" +local e=w"table" +local a=w"string" +local t=w"coroutine" +local V=math.min +local se=math.huge +local ye=e.concat +local he=e.insert +local pe=a.sub +local ve=t.wrap +local be=t.yield +local T=w"socket"or require"socket" +local P=T.gettime local e=require"util.net"; -local ge=e.pton; -local ve=require"util.sslconfig"; -local Y,fe=pcall(require,"net.tls_luasec"); -local ue=x.bind -local we=x.select -local U +local ke=e.pton; +local ge=require"util.sslconfig"; +local Y,je=pcall(require,"net.tls_luasec"); +local me=T.bind +local xe=T.select +local H local Z local ce -local me +local qe local ee -local l -local de -local J -local K -local le +local d +local we +local te +local ae local re -local ne -local Q -local h -local se -local G -local he -local p +local de +local ue +local oe +local r +local le +local B +local fe +local v local i local F -local r +local h local s local R -local v +local b local y -local k -local T +local g +local z local a local o -local g +local k +local M local C -local M +local U +local E local D -local _ -local H -local B -local d +local X +local l +local L local S local I local O local N -local L -local z -local E +local _ +local x local A -p={} +v={} i={} -r={} +h={} F={} s={} -v={} +b={} y={} R={} -k={} +g={} a=0 o=0 -g=0 -C=0 +k=0 M=0 -D=1 -_=128 -H=10 -S=51e3*1024 -I=25e3*1024 -O=30 -N=6e4 -L=14*60 +C=0 +U=1 +E=128 +D=10 +L=51e3*1024 +S=25e3*1024 +I=30 +O=6e4 +N=14*60 local e=package.config:sub(1,1)=="\\" -E=(e and math.huge)or x._SETSIZE or 1024 -z=x._SETSIZE or 1024 +x=(e and math.huge)or T._SETSIZE or 1024 +_=T._SETSIZE or 1024 A=30 -re=function(w,t,m,c,q,y,v) -if t:getfd()>=E then -j("server.lua: Disallowed FD number: "..t:getfd()) +de=function(w,t,m,c,j,y,p) +if t:getfd()>=x then +q("server.lua: Disallowed FD number: "..t:getfd()) t:close() return nil,"fd-too-large" end local f=0 local b,e=w.onconnect,w.ondisconnect -local g=t.accept +local k=t.accept local e={} e.shutdown=function()end e.ssl=function() @@ -2654,9 +2884,9 @@ end e.close=function() t:close() -o=h(r,t,o) -a=h(i,t,a) -p[m..":"..c]=nil; +o=r(h,t,o) +a=r(i,t,a) +v[m..":"..c]=nil; s[t]=nil e=nil t=nil @@ -2664,7 +2894,7 @@ end e.pause=function(o) if not e.paused then -a=h(i,t,a) +a=r(i,t,a) if o then s[t]=nil t:close() @@ -2677,12 +2907,12 @@ e.resume=function() if e.paused then if not t then -t=ue(m,c,_); +t=me(m,c,E); t:settimeout(0) end -a=l(i,t,a) +a=d(i,t,a) s[t]=e -k[e]=nil +g[e]=nil e.paused=false; n("server.lua: server [",m,"]:",c," resumed") end @@ -2697,105 +2927,105 @@ return t end e.readbuffer=function() -if a>=z or o>=z then +if a>=_ or o>=_ then e.pause() -k[e]=d +g[e]=l n("server.lua: refused new client connection: server full") return false end -local t,o=g(t) +local t,i=k(t) if t then local a,o=t:getpeername() -local e,i,t=G(e,w,t,a,c,o,q,y,v) -if t then +local t,i,e=B(e,w,t,a,c,o,j,y,p) +if e then return false end f=f+1 n("server.lua: accepted new client connection from ",u(a),":",u(o)," to ",u(c)) -if b and not v then -return b(e); +if b and not p then +return b(t); end return; -elseif o then -n("server.lua: error with new client connection: ",u(o)) +elseif i then +n("server.lua: error with new client connection: ",u(i)) e.pause() -k[e]=d +g[e]=l return false end end return e end -G=function(q,c,t,H,ee,L,D,w,te,P) -if t:getfd()>=E then -j("server.lua: Disallowed FD number: "..t:getfd()) +B=function(k,c,t,N,te,I,D,p,Z,Q) +if t:getfd()>=x then +q("server.lua: Disallowed FD number: "..t:getfd()) t:close() -if q then -k[q]=d -q.pause() +if k then +g[k]=l +k.pause() end return nil,nil,"fd-too-large" end t:settimeout(0) -local b -local N -local z -local B -local x +local v +local E +local _ +local J +local j local K=c.onincoming local G=c.onstatus -local k=c.ondisconnect -local J=c.onpredrain -local X=c.ondrain -local ae=c.onreadtimeout; -local Q=c.ondetach +local x=c.ondisconnect +local P=c.onpredrain +local W=c.ondrain +local ee=c.onreadtimeout; +local U=c.ondetach local g={} local m=0 -local Z -local V +local X +local F local f=0 -local p=false -local E=false -local W,F=0,0 -local _=S -local O=I +local w=false +local T=false +local V,B=0,0 +local O=L +local S=S local e=g -e.extra=P -if P then -e.servername=P.servername +e.extra=Q +if Q then +e.servername=Q.servername end e.dispatch=function() return K end e.disconnect=function() -return k -end -e.onreadtimeout=ae; +return x +end +e.onreadtimeout=ee; e.setlistener=function(a,t,o) -if Q then -Q(a) +if U then +U(a) end K=t.onincoming -k=t.ondisconnect +x=t.ondisconnect G=t.onstatus -J=t.onpredrain -X=t.ondrain +P=t.onpredrain +W=t.ondrain e.onreadtimeout=t.onreadtimeout -Q=t.ondetach +U=t.ondetach if t.onattach then t.onattach(a,o) end end e._setpending=function() -x=true +j=true end e.getstats=function() -return F,W +return B,V end e.ssl=function() -return B +return J end e.sslctx=function() -return w +return p end e.ssl_info=function() return t.info and t:info() @@ -2812,46 +3042,46 @@ if not t.getpeerfinished then return nil,"not-implemented";end return t:getpeerfinished(); end -e.send=function(n,i,a,o) -return b(t,i,a,o) -end -e.receive=function(o,a) -return N(t,o,a) +e.send=function(n,i,o,a) +return v(t,i,o,a) +end +e.receive=function(a,o) +return E(t,a,o) end e.shutdown=function(a) -return z(t,a) -end -e.setoption=function(i,o,a) +return _(t,a) +end +e.setoption=function(i,a,o) if t.setoption then -return t:setoption(o,a); +return t:setoption(a,o); end return false,"setoption not implemented"; end -e.force_close=function(t,a) +e.force_close=function(a,t) if m~=0 then -n("server.lua: discarding unwritten data for ",u(H),":",u(L)) +n("server.lua: discarding unwritten data for ",u(N),":",u(I)) m=0; end -return t:close(a); +return a:close(t); end e.close=function(l,d) if not e then return true;end -a=h(i,t,a) -v[e]=nil +a=r(i,t,a) +b[e]=nil if m~=0 then e:sendbuffer() if m~=0 then if e then e.write=nil end -Z=true +X=true return false end end if t then -T=z and z(t) +z=_ and _(t) t:close() -o=h(r,t,o) +o=r(h,t,o) s[t]=nil t=nil else @@ -2862,43 +3092,43 @@ R[e]=nil local t=e; e=nil +if x then +x(t,d or false); +x=nil +end +end if k then -k(t,d or false); -k=nil -end -end -if q then -q.remove() +k.remove() end n"server.lua: closed client handler and removed socket from list" return true end e.server=function() -return q +return k end e.ip=function() -return H +return N end e.serverport=function() -return ee +return te end e.clientport=function() -return L +return I end e.port=e.clientport local k=function(i,a) if not e then return false end f=f+#a -if f>_ then +if f>O then R[e]="send buffer exceeded" return false -elseif not E and t and not r[t]then -o=l(r,t,o) +elseif not T and t and not h[t]then +o=d(h,t,o) end m=m+1 g[m]=a if e then -y[e]=y[e]or d +y[e]=y[e]or l end return true end @@ -2914,176 +3144,176 @@ return D end e.set_send=function(a,t) -b=t or b -return b -end -e.bufferlen=function(o,a,t) -_=t or _ +v=t or v +return v +end +e.bufferlen=function(o,t,a) O=a or O -return f,O,_ -end -e.lock_read=function(a,t) -j("server.lua, lock_read() is deprecated, use pause() and resume()") -if t==true then -return a:pause() -elseif t==false then -return a:resume() -end -return p +S=t or S +return f,S,O +end +e.lock_read=function(t,a) +q("server.lua, lock_read() is deprecated, use pause() and resume()") +if a==true then +return t:pause() +elseif a==false then +return t:resume() +end +return w end e.pause=function(o) local o=a -a=h(i,t,a) -v[e]=nil +a=r(i,t,a) +b[e]=nil if a~=o then -p=true -end -return p; +w=true +end +return w; end e.resume=function(o) -if p then -p=false -a=l(i,t,a) -v[e]=d -end -return p; +if w then +w=false +a=d(i,t,a) +b[e]=l +end +return w; end e.lock=function(t,a) -j("server.lua, lock() is deprecated") +q("server.lua, lock() is deprecated") e.lock_read(t,a) if a==true then e.pause_writes(t) elseif a==false then e.resume_writes(t) end -return p,E +return w,T end e.pause_writes=function(a) local a=o -o=h(r,t,o) +o=r(h,t,o) y[e]=nil -E=true +T=true end e.resume_writes=function(e) -E=false +T=false if f>0 and t then -o=l(r,t,o) -end -end -local v=function() -local o,t,a=N(t,D) +o=d(h,t,o) +end +end +local b=function() +local o,t,a=E(t,D) if not t or(t=="wantread"or t=="timeout")then local a=o or a or"" local o=#a -if o>O then +if o>S then e:close("receive buffer exceeded") return false end local o=o*ie -F=F+o -M=M+o -v[e]=d -if x then -x=nil +B=B+o +C=C+o +b[e]=l +if j then +j=nil if c.onconnect then c.onconnect(e) end end return K(e,a,t) else -n("server.lua: client ",u(H),":",u(L)," read error: ",u(t)) -T=e and e:force_close(t) +n("server.lua: client ",u(N),":",u(I)," read error: ",u(t)) +z=e and e:force_close(t) return false end end -local p=function() -local w,a,i,s,l; +local w=function() +local w,a,i,s,d; if t then -if x then -x=nil +if j then +j=nil if c.onconnect then c.onconnect(e); end end -if J then -J(e); +if P then +P(e); end s=ye(g,"",1,m) -w,a,i=b(t,s,1,f) -l=(w or i or 0)*ie -W=W+l -C=C+l +w,a,i=v(t,s,1,f) +d=(w or i or 0)*ie +V=V+d +M=M+d for e=m,1,-1 do g[e]=nil end else -w,a,l=false,"unexpected close",0; +w,a,d=false,"unexpected close",0; end if w then m=0 f=0 -o=h(r,t,o) +o=r(h,t,o) y[e]=nil -if X then -X(e) -end -T=V and e:starttls(nil) -T=Z and e:force_close() +if W then +W(e) +end +z=F and e:starttls(nil) +z=X and e:force_close() return true elseif i and(a=="timeout"or a=="wantwrite")then -s=be(s,i+1,f) +s=pe(s,i+1,f) g[1]=s m=1 f=f-i -y[e]=d +y[e]=l return true else -n("server.lua: client ",u(H),":",u(L)," write error: ",u(a)) -T=e and e:force_close(a) +n("server.lua: client ",u(N),":",u(I)," write error: ",u(a)) +z=e and e:force_close(a) return false end end -local d; +local l; function e.set_sslctx(y,t) -w=t; +p=t; local u,f -d=pe(function(s) +l=ve(function(s) local t -for d=1,A do -o=(f and h(r,s,o))or o -a=(u and h(i,s,a))or a +for l=1,A do +o=(f and r(h,s,o))or o +a=(u and r(i,s,a))or a u,f=nil,nil -d,t=s:dohandshake() +l,t=s:dohandshake() if not t then n("server.lua: ssl handshake done") -e.readbuffer=v -e.sendbuffer=p -d=G and G(e,"ssl-handshake-complete") +e.readbuffer=b +e.sendbuffer=w +l=G and G(e,"ssl-handshake-complete") if y.autostart_ssl and c.onconnect then c.onconnect(y); if m~=0 then -o=l(r,s,o) -end -end -a=l(i,s,a) +o=d(h,s,o) +end +end +a=d(i,s,a) return true else if t=="wantwrite"then -o=l(r,s,o) +o=d(h,s,o) f=true elseif t=="wantread"then -a=l(i,s,a) +a=d(i,s,a) u=true else break; end t=nil; -ke() +be() end end t=(t or"handshake too long"); n("server.lua: ",t); -T=e and e:force_close(t) +z=e and e:force_close(t) return false,t end ) @@ -3095,71 +3325,71 @@ end if m>0 then n"server.lua: we need to do tls, but delaying until send buffer empty" -V=true +F=true return end n("server.lua: attempting to start tls on "..u(t)) -local m,c=t -t,c=w:wrap(t) +local c,m=t +t,m=p:wrap(t) if not t then -n("server.lua: error while starting tls on client: ",u(c or"unknown error")) -return nil,c +n("server.lua: error while starting tls on client: ",u(m or"unknown error")) +return nil,m end if t.sni then if f.servername then t:sni(f.servername); -elseif next(w._sni_contexts)~=nil then -t:sni(w._sni_contexts,true); +elseif next(p._sni_contexts)~=nil then +t:sni(p._sni_contexts,true); end end t:settimeout(0) -b=t.send -N=t.receive -z=U +v=t.send +E=t.receive +_=H s[t]=e -a=l(i,t,a) -a=h(i,m,a) -o=h(r,m,o) -s[m]=nil +a=d(i,t,a) +a=r(i,c,a) +o=r(h,c,o) +s[c]=nil e.starttls=nil -V=nil -B=true -e.readbuffer=d -e.sendbuffer=d -return d(t) -end -end -e.readbuffer=v -e.sendbuffer=p -b=t.send -N=t.receive -z=(B and U)or t.shutdown +F=nil +J=true +e.readbuffer=l +e.sendbuffer=l +return l(t) +end +end +e.readbuffer=b +e.sendbuffer=w +v=t.send +E=t.receive +_=(J and H)or t.shutdown s[t]=e -a=l(i,t,a) -if w and te and Y then +a=d(i,t,a) +if p and Z and Y then n"server.lua: auto-starting ssl negotiation..." e.autostart_ssl=true; -local t,e=e:starttls(w); -if t==false then -return nil,nil,e +local e,t=e:starttls(p); +if e==false then +return nil,nil,t end end return e,t end -U=function() -end -me=function() +H=function() +end +qe=function() return false end -l=function(a,t,e) -if not a[t]then +d=function(t,a,e) +if not t[a]then e=e+1 -a[e]=t -a[t]=e -end -return e; -end -h=function(e,i,t) +t[e]=a +t[a]=e +end +return e; +end +r=function(e,i,t) local o=e[i] if o then e[i]=nil @@ -3173,13 +3403,13 @@ end return t end -Q=function(e) -o=h(r,e,o) -a=h(i,e,a) +oe=function(e) +o=r(h,e,o) +a=r(i,e,a) s[e]=nil e:close() end -local function c(e,t,o) +local function m(e,t,o) local a; local i=t.sendbuffer; function t.sendbuffer() @@ -3199,259 +3429,259 @@ end e:set_mode("*a"); end -J=function(e,t,d,h) -e=e or"*" +te=function(t,e,l,h) +t=t or"*" h=h or{} local o local r=h.tls_ctx; local c=h.tls_direct; local u=h.read_size; -if w(d)~="table"then +if f(l)~="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 p[e..":"..t]then -o="listeners on '["..e.."]:"..t.."' already exist" +elseif v[t..":"..e]then +o="listeners on '["..t.."]:"..e.."' already exist" elseif r and not Y then o="luasec not found" end if o then -j("server.lua, [",e,"]:",t,": ",o) +q("server.lua, [",t,"]:",e,": ",o) return nil,o end -local o,h=ue(e,t,_) +local o,h=me(t,e,E) if h then -j("server.lua, [",e,"]:",t,": ",h) +q("server.lua, [",t,"]:",e,": ",h) return nil,h end -local h,d=re(d,o,e,t,u,r,c) +local h,l=de(l,o,t,e,u,r,c) if not h then o:close() -return nil,d +return nil,l end o:settimeout(0) -a=l(i,o,a) -p[e..":"..t]=h +a=d(i,o,a) +v[t..":"..e]=h s[o]=h -n("server.lua: new "..(r and"ssl "or"").."server listener on '[",e,"]:",t,"'") +n("server.lua: new "..(r and"ssl "or"").."server listener on '[",t,"]:",e,"'") return h end -de=function(i,o,t,a,e) -return J(i,o,t,{ -read_size=a; +we=function(i,o,a,t,e) +return te(i,o,a,{ +read_size=t; tls_ctx=e; tls_direct=e and true or false; }); end +re=function(t,e) +return v[t..":"..e]; +end le=function(e,t) -return p[e..":"..t]; -end -se=function(e,t) -local a=p[e..":"..t] +local a=v[e..":"..t] if not a then return nil,"no server found on '["..e.."]:"..u(t).."'" end a:close() -p[e..":"..t]=nil +v[e..":"..t]=nil return true end ee=function() -for t,e in q(s)do -e:close() -s[t]=nil +for e,t in j(s)do +t:close() +s[e]=nil end a=0 o=0 -g=0 -p={} +k=0 +v={} i={} -r={} +h={} F={} s={} end -ne=function() +ue=function() return{ -select_timeout=D; -tcp_backlog=_; -max_send_buffer_size=S; -max_receive_buffer_size=I; -select_idle_check_interval=O; -send_timeout=N; -read_timeout=L; -max_connections=z; +select_timeout=U; +tcp_backlog=E; +max_send_buffer_size=L; +max_receive_buffer_size=S; +select_idle_check_interval=I; +send_timeout=O; +read_timeout=N; +max_connections=_; max_ssl_handshake_roundtrips=A; -highest_allowed_fd=E; -accept_retry_interval=H; +highest_allowed_fd=x; +accept_retry_interval=D; } end -he=function(e) -if w(e)~="table"then +fe=function(e) +if f(e)~="table"then return nil,"invalid settings table" end -D=b(e.select_timeout)or D -S=b(e.max_send_buffer_size)or S -I=b(e.max_receive_buffer_size)or I -O=b(e.select_idle_check_interval)or O -_=b(e.tcp_backlog)or _ -N=b(e.send_timeout)or N -L=b(e.read_timeout)or L -H=b(e.accept_retry_interval)or H -z=e.max_connections or z +U=p(e.select_timeout)or U +L=p(e.max_send_buffer_size)or L +S=p(e.max_receive_buffer_size)or S +I=p(e.select_idle_check_interval)or I +E=p(e.tcp_backlog)or E +O=p(e.send_timeout)or O +N=p(e.read_timeout)or N +D=p(e.accept_retry_interval)or D +_=e.max_connections or _ A=e.max_ssl_handshake_roundtrips or A -E=e.highest_allowed_fd or E +x=e.highest_allowed_fd or x return true end -K=function(e) -if w(e)~="function"then +ae=function(e) +if f(e)~="function"then return nil,"invalid listener function" end -g=g+1 -F[g]=e +k=k+1 +F[k]=e return true end local u do -local a={}; +local i={}; local t={}; -function u(e,a) -local o=P(); -e=e+o; -if e>=o then -ae(t,{e,a}); -else -local e=a(o); -if e and w(e)=="number"then -return u(e,a); -end -end -end -K(function(o) +function u(e,o) +local a=P(); +e=e+a; +if e>=a then +he(t,{e,o}); +else +local e=o(a); +if e and f(e)=="number"then +return u(e,o); +end +end +end +ae(function(a) if#t>0 then -for o,e in q(t)do -ae(a,e); +for a,e in j(t)do +he(i,e); end t={}; end -local e=te; -for s,t in q(a)do -local n,i=t[1],t[2]; -if n<=o then -a[s]=nil; -local t=i(o); -if w(t)=="number"then -u(t,i); -e=W(e,t); -end -else -e=W(e,n-o); +local e=se; +for s,t in j(i)do +local n,o=t[1],t[2]; +if n<=a then +i[s]=nil; +local t=o(a); +if f(t)=="number"then +u(t,o); +e=V(e,t); +end +else +e=V(e,n-a); end end return e; end); end ce=function() -return M,C,a,o,g -end -local e; -local function b(t) -e=t; -end -Z=function(t) -if e then return"quitting";end -if t then e="once";end -d=P() +return C,M,a,o,k +end +local t; +local function c(e) +t=e; +end +Z=function(e) +if t then return"quitting";end +if e then t="once";end +l=P() repeat -local t=te; -for e=1,g do -local e=F[e](d) -if e then t=W(t,e);end -end -local t,a,o=we(i,r,W(D,t)) -for t,e in oe(t)do +local e=se; +for t=1,k do +local t=F[t](l) +if t then e=V(e,t);end +end +local e,a,o=xe(i,h,V(U,e)) +for t,e in ne(e)do local t=s[e] if t then t:readbuffer() else -Q(e) +oe(e) n"server.lua: found no handler and closed socket (readlist)" end end -for e,t in oe(a)do +for e,t in ne(a)do local e=s[t] if e then e:sendbuffer() else -Q(t) +oe(t) n"server.lua: found no handler and closed socket (writelist)" end end -for e,t in q(R)do +for e,t in j(R)do e.disconnect()(e,t) e:force_close() R[e]=nil; end -d=P() -if d-B>O then -B=d -for e,t in q(y)do -if d-t>N then +l=P() +if l-X>I then +X=l +for e,t in j(y)do +if l-t>O then e.disconnect()(e,"send timeout") e:force_close() end end -for e,t in q(v)do -if d-t>L then +for e,t in j(b)do +if l-t>N then if not(e.onreadtimeout)or e:onreadtimeout()~=true then e.disconnect()(e,"read timeout") e:close() else -v[e]=d -end -end -end -end -for e,t in q(k)do -if d-t>H then -k[e]=nil; +b[e]=l +end +end +end +end +for e,t in j(g)do +if l-t>D then +g[e]=nil; e.resume(); end end -until e; -if e=="once"then e=nil;return;end +until t; +if t=="once"then t=nil;return;end ee(); return"quitting" end -local function p() +local function g() return Z(true); end -local function m() +local function k() return"select"; end -local d=function(e,t,h,d,c,n,u) -local t,e,h=G(nil,d,e,t,h,"clientport",c,n,n,u) -if not t then return nil,h end -s[e]=t +local n=function(c,u,l,t,e,n,r) +local e,t,r=B(nil,t,c,u,l,"clientport",e,n,n,r) +if not e then return nil,r end +s[t]=e if not n then -t._setpending() -a=l(i,e,a) -o=l(r,e,o) -end -return t,e -end -local g=function(o,t,i,r,n,a,s) +e._setpending() +a=d(i,t,a) +o=d(h,t,o) +end +return e,t +end +local v=function(o,t,i,h,s,a,d) local e -if w(i)~="table"then +if f(i)~="table"then e="invalid listener table" -elseif w(o)~="string"then +elseif f(o)~="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 Y then +elseif s and not Y then e="luasec not found" end if not a then -local e=ge(o); +local e=ke(o); if not e then return nil,"invalid-ip";end if#e==16 then a="tcp6"; @@ -3459,12 +3689,12 @@ a="tcp4"; end end -local a=x[a]; -if w(a)~="function"then +local a=T[a]; +if f(a)~="function"then e="invalid socket type" end if e then -j("server.lua, addclient: ",e) +q("server.lua, addclient: ",e) return nil,e end local e,a=a() @@ -3472,85 +3702,85 @@ return nil,a end e:settimeout(0) -local h,a=e:setpeername(o,t) -if h or a=="timeout"or a=="Operation already in progress"then -return d(e,o,t,i,r,n,s) +local r,a=e:setpeername(o,t) +if r or a=="timeout"or a=="Operation already in progress"then +return n(e,o,t,i,h,s,d) else return nil,a end end -local k=function(e) +local p=function(e) local e=e.conn; -o=h(r,e,o) -a=h(i,e,a) +o=r(h,e,o) +a=r(i,e,a) s[e]=nil end; -local i=function(d,n,t) -local e=d.conn -s[e]=d -if n~=nil then -if n then -a=l(i,e,a) -else -o=h(r,e,o) -end -end +local a=function(n,t,l) +local e=n.conn +s[e]=n if t~=nil then if t then -o=l(r,e,o) -else -a=h(i,e,a) -end -end -end -local t=function(e,o,a) +a=d(i,e,a) +else +o=r(h,e,o) +end +end +if l~=nil then +if l then +o=d(h,e,o) +else +a=r(i,e,a) +end +end +end +local a=function(e,i,o) local t=e -if w(e)=="number"then +if f(e)=="number"then t={getfd=function()return e;end} end local e={ conn=t; -readbuffer=o or U; -sendbuffer=a or U; -close=k; -setflags=i; -}; -i(e,o,a) +readbuffer=i or H; +sendbuffer=o or H; +close=p; +setflags=a; +}; +a(e,i,o) return e end -f"setmetatable"(s,{__mode="k"}) -f"setmetatable"(v,{__mode="k"}) -f"setmetatable"(y,{__mode="k"}) -B=P() -local function a(e) -local t=V; +w"setmetatable"(s,{__mode="k"}) +w"setmetatable"(b,{__mode="k"}) +w"setmetatable"(y,{__mode="k"}) +X=P() +local function o(e) +local t=W; if e then -V=e; +W=e; end return t; end return{ -_addtimer=K, +_addtimer=ae, add_task=u; -addclient=g, -wrapclient=d, -watchfd=t, +addclient=v, +wrapclient=n, +watchfd=a, loop=Z, -link=c, -step=p, +link=m, +step=g, stats=ce, closeall=ee, -addserver=de, -listen=J, -getserver=le, -setlogger=a, -getsettings=ne, -setquitting=b, -removeserver=se, -get_backend=m, -changesettings=he, +addserver=we, +listen=te, +getserver=re, +setlogger=o, +getsettings=ue, +setquitting=c, +removeserver=le, +get_backend=k, +changesettings=fe, tls_builder=function(e) -return ve._new(fe.new_context,e) +return ge._new(je.new_context,e) end, } end) @@ -3567,21 +3797,21 @@ return e; end local e=require"lxp"; -local g=require"util.stanza"; -local y=g.stanza_mt; +local x=require"util.stanza"; +local k=x.stanza_mt; local w=error; local t=tostring; local d=table.insert; -local b=table.concat; -local E=table.remove; -local p=setmetatable; +local g=table.concat; +local z=table.remove; +local b=setmetatable; local T=pcall(e.new,{StartDoctypeDecl=false}); -local _=pcall(e.new,{XmlDecl=false}); +local A=pcall(e.new,{XmlDecl=false}); local a=not not e.new({}).getcurrentbytecount; -local x=1024*1024*1; +local _=1024*1024*1; local _ENV=nil; -local v=e.new; -local j={ +local j=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"; @@ -3589,47 +3819,47 @@ }; local h="http://etherx.jabber.org/streams"; local r="\1"; -local k="^([^"..r.."]*)"..r.."?(.*)$"; +local q="^([^"..r.."]*)"..r.."?(.*)$"; local function o()end -local function q(n,e,s) +local function v(n,e,s) local i={}; -local g=e.streamopened; -local v=e.streamclosed; -local l=e.error or +local p=e.streamopened; +local y=e.streamclosed; +local u=e.error or function(o,a,e) w("XML stream error: "..t(a)..(e and": "..t(e)or""),2); end; -local x=e.handlestanza; +local v=e.handlestanza; s=s or o; local t=e.stream_ns or h; -local m=e.stream_tag or"stream"; +local c=e.stream_tag or"stream"; if t~=""then -m=t..r..m; -end -local z=t..r..(e.error_tag or"error"); -local q=e.default_ns; -local f="en"; -local u={}; +c=t..r..c; +end +local x=t..r..(e.error_tag or"error"); +local j=e.default_ns; +local m="en"; +local l={}; local h,e={}; local t=0; local r=0; -function i:StartElement(c,o) +function i:StartElement(f,o) if e and#h>0 then -d(e,b(h)); +d(e,g(h)); h={}; end -local h,i=c:match(k); +local h,i=f:match(q); if i==""then h,i="",h; end -if h~=q or r>0 then +if h~=j or r>0 then o.xmlns=h; r=r+1; end for t=1,#o do local e=o[t]; o[t]=nil; -local t=j[e]; +local t=E[e]; if t then o[t]=o[e]; o[e]=nil; @@ -3640,32 +3870,32 @@ t=self:getcurrentbytecount(); end if n.notopen then -if c==m then +if f==c then r=0; -f=o["xml:lang"]or f; -if g then +m=o["xml:lang"]or m; +if p then if a then s(t); t=0; end -g(n,o); -end -else -l(n,"no-stream",c); +p(n,o); +end +else +u(n,"no-stream",f); end return; end if h=="jabber:client"and i~="iq"and i~="presence"and i~="message"then -l(n,"invalid-top-level-element"); -end -e=p({name=i,attr=o,tags={}},y); +u(n,"invalid-top-level-element"); +end +e=b({name=i,attr=o,tags={}},k); else if a then t=t+self:getcurrentbytecount(); end -d(u,e); +d(l,e); local t=e; -e=p({name=i,attr=o,tags={}},y); +e=b({name=i,attr=o,tags={}},k); d(t,e); d(t.tags,e); end @@ -3707,42 +3937,42 @@ end if e then if#h>0 then -d(e,b(h)); +d(e,g(h)); h={}; end -if#u==0 then +if#l==0 then if a then s(t); end t=0; if e.attr["xml:lang"]==nil then -e.attr["xml:lang"]=f; -end -if o~=z then -x(n,e); -else -l(n,"stream-error",e); +e.attr["xml:lang"]=m; +end +if o~=x then +v(n,e); +else +u(n,"stream-error",e); end e=nil; else -e=E(u); +e=z(l); end else if a then s(t); end -if v then -v(n); +if y then +y(n); end end end local function o(e) -l(n,"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 w("Failed to abort parsing"); end end -if _ then +if A then function i:XmlDecl(e,t,i) if a then s(self:getcurrentbytecount()); @@ -3761,56 +3991,56 @@ i.ProcessingInstruction=o; local function a() e,h,t=nil,{},0; -u={}; -end -local function e(t,e) +l={}; +end +local function t(t,e) n=e; end -return i,{reset=a,set_session=e}; -end -local function l(e,h,o) +return i,{reset=a,set_session=t}; +end +local function u(l,d,o) local t=0; -local i; +local e; if a then -function i(e) +function e(e) t=t-e; end -o=o or x; +o=o or _; elseif o then w("Stanza size limits are not supported on this version of LuaExpat") end -local n,d=q(e,h,i); -local i=v(n,r,false); -local s=i.parse; -function e.open_stream(e,o,a) +local n,s=v(l,d,e); +local i=j(n,r,false); +local h=i.parse; +function l.open_stream(e,t,a) local i=e.sends2s or e.send; -local t={ +local o={ ["xmlns:stream"]="http://etherx.jabber.org/streams", ["xml:lang"]="en", -xmlns=h.default_ns, +xmlns=d.default_ns, version=e.version and(e.version>0 and"1.0"or nil), id=e.streamid or"", -from=o or e.host,to=a, +from=t or e.host,to=a, }; if e.stream_attrs then -e:stream_attrs(o,a,t) -end -i(""..g.stanza("stream:stream",t):top_tag()); +e:stream_attrs(t,a,o) +end +i(""..x.stanza("stream:stream",o):top_tag()); return true; end return{ reset=function() -i=v(n,r,false); -s=i.parse; +i=j(n,r,false); +h=i.parse; t=0; -d.reset(); +s.reset(); end, feed=function(e,n) if a then t=t+#n; end local e=i; -local n,s=s(e,n); +local n,s=h(e,n); if a and t>o then return nil,"stanza-too-large"; end @@ -3820,7 +4050,7 @@ end return n,s; end, -set_session=d.set_session; +set_session=s.set_session; set_stanza_size_limit=function(t,e) o=e; end; @@ -3828,9 +4058,9 @@ end return{ ns_separator=r; -ns_pattern=k; -new_sax_handlers=q; -new=l; +ns_pattern=q; +new_sax_handlers=v; +new=u; }; end) package.preload['util.jid']=(function(...) @@ -3845,23 +4075,23 @@ _M=e; return e; end -local i=select; -local a,h=string.match,string.sub; -local u=require"util.encodings".stringprep.nodeprep; +local o=select; +local a,n=string.match,string.sub; +local d=require"util.encodings".stringprep.nodeprep; local l=require"util.encodings".stringprep.nameprep; -local d=require"util.encodings".stringprep.resourceprep; -local o={ +local u=require"util.encodings".stringprep.resourceprep; +local i={ [" "]="\\20";['"']="\\22"; ["&"]="\\26";["'"]="\\27"; ["/"]="\\2f";[":"]="\\3a"; ["<"]="\\3c";[">"]="\\3e"; ["@"]="\\40";["\\"]="\\5c"; }; -local n={}; local s={}; -for t,e in pairs(o)do -n[e]=t; -s[e]=e:gsub("\\",o) +local h={}; +for t,e in pairs(i)do +s[e]=t; +h[e]=e:gsub("\\",i) end local _ENV=nil; local function t(e) @@ -3880,25 +4110,25 @@ return e; end local function r(e,o) -local a,e,t=t(e); +local t,e,a=t(e); if e~=nil and e~="."then -if h(e,-1,-1)=="."then -e=h(e,1,-2); +if n(e,-1,-1)=="."then +e=n(e,1,-2); end e=l(e,o); if e==nil then return;end +if t~=nil then +t=d(t,o); +if t==nil then return;end +end if a~=nil then a=u(a,o); if a==nil then return;end end -if t~=nil then -t=d(t,o); -if t==nil then return;end -end -return a,e,t; -end -end -local function h(t,e,a) +return t,e,a; +end +end +local function n(t,e,a) if e==nil then return end if t~=nil and a~=nil then return t.."@"..e.."/"..a; @@ -3909,43 +4139,43 @@ end return e; end -local function c(e,t) -local e,a,t=r(e,t); -return h(e,a,t); -end -local function f(a,e) -local i,n,o=t(a); -local a,t,e=t(e); -if(a==nil or a==i)and +local function l(t,e) +local a,t,e=r(t,e); +return n(a,t,e); +end +local function d(e,a) +local o,n,i=t(e); +local e,t,a=t(a); +if(e==nil or e==o)and (t==nil or t==n)and -(e==nil or e==o)then +(a==nil or a==i)then return true end return false end +local function c(e) +return(o(1,t(e))); +end +local function a(e) +return(o(2,t(e))); +end local function u(e) -return(i(1,t(e))); -end -local function l(e) -return(i(2,t(e))); -end -local function d(e) -return(i(3,t(e))); -end -local function a(e)return e and(e:gsub("\\%x%x",s):gsub("[\"&'/:<>@ ]",o));end -local function o(e)return e and(e:gsub("\\%x%x",n));end +return(o(3,t(e))); +end +local function o(e)return e and(e:gsub("\\%x%x",h):gsub("[\"&'/:<>@ ]",i));end +local function i(e)return e and(e:gsub("\\%x%x",s));end return{ split=t; bare=m; prepped_split=r; -join=h; -prep=c; -compare=f; -node=u; -host=l; -resource=d; -escape=a; -unescape=o; +join=n; +prep=l; +compare=d; +node=c; +host=a; +resource=u; +escape=o; +unescape=i; }; end) package.preload['util.events']=(function(...) @@ -3961,98 +4191,98 @@ return e; end local a=pairs; -local d=table.insert; -local w=table.remove; -local u=table.sort; -local l=setmetatable; +local l=table.insert; +local m=table.remove; +local r=table.sort; +local d=setmetatable; local h=next; local _ENV=nil; local function f() -local o={}; +local i={}; local t; local n={}; -local i={}; +local o={}; local s=nil; -local function r(n,o) -local e=i[o]; +local function u(n,i) +local e=o[i]; if not e or h(e)==nil then return;end local t={}; for e in a(e)do -d(t,e); -end -u(t,function(a,t)return e[a]>e[t];end); -n[o]=t; +l(t,e); +end +r(t,function(t,a)return e[t]>e[a];end); +n[i]=t; return t; end; -l(o,{__index=r}); -local function l(t,n,a) -local e=i[t]; +d(i,{__index=u}); +local function d(t,n,a) +local e=o[t]; if e then e[n]=a or 0; else e={[n]=a or 0}; -i[t]=e; -end -o[t]=nil; +o[t]=e; +end +i[t]=nil; end; -local function d(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 r(t,a) +local e=o[t]; +if e then +e[a]=nil; +i[t]=nil; +if h(e)==nil then +o[t]=nil; end end end; -local function c(e) -return o[e]; +local function f(e) +return i[e]; end; -local function u(e) -for e,t in a(e)do -l(e,t); -end -end; -local function m(e) +local function w(e) for t,e in a(e)do d(t,e); end end; -local function r(a,t) -local e=o[a]; +local function u(e) +for t,e in a(e)do +r(t,e); +end +end; +local function h(t,a) +local e=i[t]; if e and not s then -for a=1,#e do -local e=e[a](t); +for t=1,#e do +local e=e[t](a); if e~=nil then return e;end end elseif e and s then for o=1,#e do -local e=s(e[o],a,t); +local e=s(e[o],t,a); if e~=nil then return e;end end end end; -local function f(s,h) -local e=n[s]or t; -if e then -local a=#e; -local function i(o,n) -a=a-1; -if a==0 then -if t==nil or e==t then -return r(o,n); -end -e,a=t,#t; -return e[a](i,o,n); -else -return e[a](i,o,n); -end -end -return e[a](i,s,h); -end -return r(s,h); -end -local function r(a,o) +local function c(s,r) +local a=n[s]or t; +if a then +local e=#a; +local function n(o,i) +e=e-1; +if e==0 then +if t==nil or a==t then +return h(o,i); +end +a,e=t,#t; +return a[e](n,o,i); +else +return a[e](n,o,i); +end +end +return a[e](n,s,r); +end +return h(s,r); +end +local function l(a,o) local e; if a==false then e=t; @@ -4079,7 +4309,7 @@ if not e then return;end for t=#e,1,-1 do if e[t]==o then -w(e,t); +m(e,t); end end if#e==0 then @@ -4090,27 +4320,27 @@ end end end -local function a(t) -local e=s; -s=t; -return e; +local function e(e) +local t=s; +s=e; +return t; end return{ +add_handler=d; +remove_handler=r; +add_handlers=w; +remove_handlers=u; +get_handlers=f; +wrappers={ add_handler=l; -remove_handler=d; -add_handlers=u; -remove_handlers=m; -get_handlers=c; -wrappers={ -add_handler=r; remove_handler=h; }; -add_wrapper=r; +add_wrapper=l; remove_wrapper=h; -set_debug_hook=a; -fire_event=f; -_handlers=o; -_event_map=i; +set_debug_hook=e; +fire_event=c; +_handlers=i; +_event_map=o; }; end return{ @@ -4132,20 +4362,20 @@ local e=setmetatable; local n=ipairs; local s,p=type,next; -local u=tonumber; -local r=tostring; -local l=table.concat; -local c=require"util.stanza"; -local m=require"util.jid".prep; +local h=tonumber; +local l=tostring; +local d=table.concat; +local f=require"util.stanza"; +local u=require"util.jid".prep; local _ENV=nil; local y='jabber:x:data'; -local f='http://jabber.org/protocol/xdata-validate'; -local d={}; -local t={__index=d}; -local function w(a) -return e(a,t); -end -local function v(e) +local m='http://jabber.org/protocol/xdata-validate'; +local r={}; +local a={__index=r}; +local function c(t) +return e(t,a); +end +local function w(e) local o={ title=e:get_child_text("title"); instructions=e:get_child_text("instructions"); @@ -4173,27 +4403,27 @@ a[#a+1]=e.attr.label and{label=e.attr.label,value=e:get_text()}or e:get_text(); end if e.type=="text-multi"then -e.value=l(a,"\n"); +e.value=d(a,"\n"); else e.value=a; end end end -local t=t:get_child("validate",f); +local t=t:get_child("validate",m); if t then e.datatype=datatype.attr.datatype; local t=t:get_child("range"); if t then -e.range_min=u(t.attr.min); -e.range_max=u(t.attr.max); -end -end -end -return w(o); -end -function d.form(t,h,i) +e.range_min=h(t.attr.min); +e.range_max=h(t.attr.max); +end +end +end +return c(o); +end +function r.form(t,h,i) if not i then i="form"end -local e=c.stanza("x",{xmlns=y,type=i}); +local e=f.stanza("x",{xmlns=y,type=i}); if i=="cancel"then return e; end @@ -4214,11 +4444,11 @@ end end if i=="form"and a.datatype then -e:tag("validate",{xmlns=f,datatype=a.datatype}); +e:tag("validate",{xmlns=m,datatype=a.datatype}); if a.range_min or a.range_max then e:tag("range",{ -min=a.range_min and r(a.range_min), -max=a.range_max and r(a.range_max), +min=a.range_min and l(a.range_min), +max=a.range_max and l(a.range_max), }):up(); end e:up(); @@ -4304,14 +4534,14 @@ return e; end local t={}; -local h={}; -function d.data(e,r,i) +local l={}; +function r.data(e,h,i) local o={}; local a={}; local s={}; for n,e in n(e)do local n; -for t in r:childtags("field")do +for t in h:childtags("field")do if(e.var or e.name)==t.attr.var then n=t; break; @@ -4328,7 +4558,7 @@ local t=t[e.type]; if t then local t,i=t(n,e.required); -local n=e.datatype and h[e.datatype]; +local n=e.datatype and l[e.datatype]; if t~=nil and n then local o,a=n(t,e); if o then @@ -4359,7 +4589,7 @@ function(o,a) local e,a=e(o,a); if not e then return e,a;end -local a=m(e); +local a=u(e); if not a then return nil,"Invalid JID: "..e; end @@ -4371,14 +4601,14 @@ local e={}; for t in o:childtags("value")do local t=t:get_text(); -local o=m(t); +local o=u(t); a[#a+1]=o; if t and not o then e[#e+1]=("Invalid JID: "..t); end end if#a>0 then -return a,(#e>0 and l(e,"\n")or nil); +return a,(#e>0 and d(e,"\n")or nil); elseif i then return nil,"Required value missing"; end @@ -4399,20 +4629,20 @@ function(a,e) local e,a=t["list-multi"](a,e); if e then -e=l(e,"\n"); +e=d(e,"\n"); end return e,a; end t["list-single"]=e; -local a={ +local o={ ["1"]=true,["true"]=true, ["0"]=false,["false"]=false, }; t["boolean"]= -function(o,i) -local e,o=e(o,i); -if not e then return e,o;end -local a=a[e]; +function(i,a) +local e,a=e(i,a); +if not e then return e,a;end +local a=o[e]; if a==nil then return nil,"Invalid boolean representation:"..e; end @@ -4422,9 +4652,9 @@ function(e) return e:get_child_text("value"); end -h["xs:integer"]= +l["xs:integer"]= function(e,t) -local e=u(e); +local e=h(e); if not e then return false,"not a number"; elseif e%1~=0 then @@ -4438,7 +4668,7 @@ return true,e; end local function t(e) -if not c.is_stanza(e)then +if not f.is_stanza(e)then return nil,"not a stanza object"; elseif e.attr.xmlns~="jabber:x:data"or e.name~="x"then return nil,"not a dataform element"; @@ -4451,8 +4681,8 @@ return""; end return{ -new=w; -from_stanza=v; +new=c; +from_stanza=w; get_type=t; }; end) @@ -4468,18 +4698,18 @@ _M=e; return e; end -local l=require"util.encodings".base64.encode; +local d=require"util.encodings".base64.encode; local u=require"util.hashes".sha1; -local n,s,h=table.insert,table.sort,table.concat; +local n,h,s=table.insert,table.sort,table.concat; local r=ipairs; local _ENV=nil; -local function d(e) -local i,o,a={},{},{}; +local function l(e) +local o,a,i={},{},{}; for t,e in r(e)do if e.name=="identity"then -n(i,(e.attr.category or"").."\0"..(e.attr.type or"").."\0"..(e.attr["xml:lang"]or"").."\0"..(e.attr.name or"")); +n(o,(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(o,e.attr.var or""); +n(a,e.attr.var or""); elseif e.name=="x"and e.attr.xmlns=="jabber:x:data"then local t={}; local o; @@ -4490,34 +4720,34 @@ e=#e.tags==0 and e:get_text(); if e then n(a,e);end end -s(a); +h(a); if e.attr.var=="FORM_TYPE"then o=a[1]; elseif#a>0 then -n(t,e.attr.var.."\0"..h(a,"<")); +n(t,e.attr.var.."\0"..s(a,"<")); else n(t,e.attr.var); end end end -s(t); -t=h(t,"<"); +h(t); +t=s(t,"<"); if o then t=o.."\0"..t;end -n(a,t); -end -end -s(i); -s(o); -s(a); -if#i>0 then i=h(i,"<"):gsub("%z","/").."<";else i="";end -if#o>0 then o=h(o,"<").."<";else o="";end -if#a>0 then a=h(a,"<"):gsub("%z","<").."<";else a="";end -local e=i..o..a; -local t=l(u(e)); +n(i,t); +end +end +h(o); +h(a); +h(i); +if#o>0 then o=s(o,"<"):gsub("%z","/").."<";else o="";end +if#a>0 then a=s(a,"<").."<";else a="";end +if#i>0 then i=s(i,"<"):gsub("%z","<").."<";else i="";end +local e=o..a..i; +local t=d(u(e)); return t,e; end return{ -calculate_hash=d; +calculate_hash=l; }; end) package.preload['util.vcard']=(function(...) @@ -4532,23 +4762,23 @@ _M=e; return e; end -local o=require"util.stanza"; -local a,c=table.insert,table.concat; -local h=type; -local e,s,m=next,pairs,ipairs; -local u,l,d,r; +local i=require"util.stanza"; +local a,u=table.insert,table.concat; +local n=type; +local e,s,c=next,pairs,ipairs; +local r,l,d,h; local f="\n"; -local i; +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 y(e) +local function p(e) return e:gsub("\\?[\\nt:;,]",{ ["\\\\"]="\\", ["\\n"]="\n", @@ -4562,104 +4792,104 @@ [","]="\31", }); end -local function p(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 n(t)=="table"then +if t.types and e.TYPE then +if n(e.TYPE)=="table"then +for o,t in s(t.types)do +for o,e in s(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 s(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 n(t) -local e=o.stanza("vCard",{xmlns="vcard-temp"}); +local function m(t) +local e=i.stanza("vCard",{xmlns="vcard-temp"}); for a=1,#t do -e:add_child(p(t[a])); -end -return e; -end -function r(e) +e:add_child(w(t[a])); +end +return e; +end +function h(e) if not e[1]or e[1].name then -return n(e) -else -local t=o.stanza("xCard",{xmlns="vcard-temp"}); +return m(e) +else +local t=i.stanza("xCard",{xmlns="vcard-temp"}); for a=1,#e do -t:add_child(n(e[a])); +t:add_child(m(e[a])); end return t; end end -function u(t) +function r(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=y(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,i,n in t:gmatch("\30([^=]+)(=?)([^\30]*)")do +a=a:upper(); +local e={}; +for t in n:gmatch("[^\31]+")do +e[#e+1]=t +e[t]=true; +end +if i=="="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 @@ -4668,12 +4898,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 @@ -4681,9 +4911,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 @@ -4691,111 +4921,111 @@ e=s; end end -return h; -end -local function n(t) +return s; +end +local function i(t) local e={}; for a=1,#t do -e[a]=w(t[a]); -end -e=c(e,";"); +e[a]=y(t[a]); +end +e=u(e,";"); local a=""; -for t,e in s(t)do -if h(t)=="string"and t~="name"then -a=a..(";%s=%s"):format(t,h(e)=="table"and c(e,",")or e); +for e,t in s(t)do +if n(e)=="string"and e~="name"then +a=a..(";%s=%s"):format(e,n(t)=="table"and u(t,",")or t); end end return("%s%s:%s"):format(t.name,a,e) end -local function o(t) +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 c(e,f); +return u(e,f); end function l(e) if e[1]and e[1].name then -return o(e) -else -local t={}; +return t(e) +else +local a={}; +for o=1,#e do +a[o]=t(e[o]); +end +return u(a,f); +end +end +local function u(i) +local t=i.name; +local e=o[t]; +local t={name=t}; +if e=="text"then +t[1]=i:get_text(); +elseif n(e)=="table"then +if e.value then +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,#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 -t[a]=o(e[a]); -end -return c(t,f); -end -end -local function n(o) -local e=o.name; -local t=i[e]; -local e={name=e}; -if t=="text"then -e[1]=o:get_text(); -elseif h(t)=="table"then -if t.value then -e[1]=o:get_child_text(t.value)or""; -elseif t.values then -local t=t.values; -if t.behaviour=="repeat-last"then -for t=1,#o.tags do -a(e,o.tags[t]:get_text()or""); -end -else -for i=1,#t do -a(e,o:get_child_text(t[i])or""); -end -end -elseif t.names then -local t=t.names; -for a=1,#t do -if o:get_child(t[a])then -e[1]=t[a]; +if i:get_child(e[a])then +t[1]=e[a]; break; end end end -if t.props_verbatim then -for a,t in s(t.props_verbatim)do -e[a]=t; -end -end -if t.types then -local t=t.types; -e.TYPE={}; -for i=1,#t do -if o:get_child(t[i])then -a(e.TYPE,t[i]:lower()); -end -end -if#e.TYPE==0 then -e.TYPE=nil; -end -end -if t.props then -local t=t.props; -for i=1,#t do -local t=t[i] -local o=o:get_child_text(t); +if e.props_verbatim then +for e,a in s(e.props_verbatim)do +t[e]=a; +end +end +if e.types then +local e=e.types; +t.TYPE={}; +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 +t.TYPE=nil; +end +end +if e.props then +local e=e.props; +for o=1,#e do +local e=e[o] +local o=i:get_child_text(e); if o then -e[t]=e[t]or{}; -a(e[t],o); +t[e]=t[e]or{}; +a(t[e],o); end end end else return nil end -return e; -end -local function o(e) -local e=e.tags; -local t={}; -for o=1,#e do -a(t,n(e[o])); -end -return t +return t; +end +local function i(e) +local t=e.tags; +local e={}; +for o=1,#t do +a(e,u(t[o])); +end +return e end function d(e) if e.attr.xmlns~="vcard-temp"then @@ -4803,16 +5033,16 @@ end if e.name=="xCard"then local a={}; -local t=e.tags; -for e=1,#t do -a[e]=o(t[e]); +local e=e.tags; +for t=1,#e do +a[t]=i(e[t]); end return a elseif e.name=="vCard"then -return o(e) -end -end -i={ +return i(e) +end +end +o={ VERSION="text", FN="text", N={ @@ -4934,17 +5164,17 @@ }, DESC="text", }; -i.LOGO=i.PHOTO; -i.SOUND=i.PHOTO; +o.LOGO=o.PHOTO; +o.SOUND=o.PHOTO; return{ -from_text=u; +from_text=r; to_text=l; from_xep54=d; -to_xep54=r; +to_xep54=h; lua_to_text=l; -lua_to_xep54=r; -text_to_lua=u; -text_to_xep54=function(...)return r(u(...));end; +lua_to_xep54=h; +text_to_lua=r; +text_to_xep54=function(...)return h(r(...));end; xep54_to_lua=d; xep54_to_text=function(...)return l(d(...))end; }; @@ -4961,27 +5191,27 @@ _M=e; return e; end -local o=pairs; -local c=ipairs; -local u=require; -local l=table.remove; +local i=pairs; +local r=ipairs; +local h=require; +local s=table.remove; local _ENV=nil; local e={}; local t; -local function h(e) +local function n(e) local a=t(e,"debug"); -local o=t(e,"info"); +local n=t(e,"info"); local i=t(e,"warn"); -local n=t(e,"error"); +local o=t(e,"error"); return function(t,e,...) if t=="debug"then return a(e,...); elseif t=="info"then -return o(e,...); +return n(e,...); elseif t=="warn"then return i(e,...); elseif t=="error"then -return n(e,...); +return o(e,...); end end end @@ -4991,43 +5221,43 @@ t={}; e[a]=t; end -local e=function(e,...) -for i=1,#t do -t[i](o,a,e,...); +local e=function(i,...) +for e=1,#t do +t[e](o,a,i,...); end end return e; end local function d() -for t,e in o(e)do +for t,e in i(e)do for t=1,#e do e[t]=nil; end end end -local function i(t,a) +local function o(t,a) if not e[t]then e[t]={a}; else e[t][#e[t]+1]=a; end end -local function r(s,n) -local a=u"util.format".format; -local function e(o,t,e,...) -return s(o,t,a(e,...)); -end -for a,t in c(n or{"debug","info","warn","error"})do -i(t,e); -end -return e; -end -local function n(i) +local function l(i,s) +local n=h"util.format".format; +local function e(t,a,e,...) +return i(t,a,n(e,...)); +end +for a,t in r(s or{"debug","info","warn","error"})do +o(t,e); +end +return e; +end +local function h(o) local a; -for t,e in o(e)do +for t,e in i(e)do for t=#e,1,-1 do -if e[t]==i then -l(e,t); +if e[t]==o then +s(e,t); a=true; end end @@ -5035,13 +5265,13 @@ return a; end return{ -init=h; +init=n; make_logger=t; reset=d; -add_level_sink=i; -add_simple_sink=r; +add_level_sink=o; +add_simple_sink=l; new=t; -remove_sink=n; +remove_sink=h; }; end) package.preload['util.datetime']=(function(...) @@ -5058,14 +5288,14 @@ end local e=os.date; local i=os.time; -local r=os.difftime; +local l=os.difftime; local t=math.floor; local s=tonumber; local _ENV=nil; local function d(a) return e("!%Y-%m-%d",a and t(a)or nil); end -local function l(a) +local function r(a) if a==nil or a%1==0 then return e("!%Y-%m-%dT%H:%M:%SZ",a); end @@ -5073,7 +5303,7 @@ local a=t(a); return e("!%Y-%m-%dT%H:%M:%S.%%06dZ",a):format(t(o*1e6)); end -local function c(a) +local function u(a) if a==nil or a%1==0 then return e("!%H:%M:%S",a); end @@ -5081,15 +5311,15 @@ local a=t(a); return e("!%H:%M:%S.%%06d",a):format(t(o*1e6)); end -local function u(a) +local function m(a) return e("!%Y%m%dT%H:%M:%S",a and t(a)or nil); end -local function m(a) +local function c(a) if a then -local h,l,d,u,c,a,n=a:match("^(%d%d%d%d)%-?(%d%d)%-?(%d%d)T(%d%d):(%d%d):(%d%d%.?%d*)([Z+%-]?.*)$"); +local h,r,d,c,u,a,n=a:match("^(%d%d%d%d)%-?(%d%d)%-?(%d%d)T(%d%d):(%d%d):(%d%d%.?%d*)([Z+%-]?.*)$"); if h then local o=i(); -local r=r(i(e("*t",o)),i(e("!*t",o))); +local l=l(i(e("*t",o)),i(e("!*t",o))); local o=0; if n~=""and n~="Z"then local a,t,e=n:match("([+%-])(%d%d):?(%d*)"); @@ -5100,17 +5330,17 @@ if a=="-"then o=-o;end end local e=a%1; -a=t(a+r)-o; -return i({year=h,month=l,day=d,hour=u,min=c,sec=a,isdst=false})+e; +a=t(a+l)-o; +return i({year=h,month=r,day=d,hour=c,min=u,sec=a,isdst=false})+e; end end end return{ date=d; -datetime=l; -time=c; -legacy=u; -parse=m; +datetime=r; +time=u; +legacy=m; +parse=c; }; end) package.preload['util.json']=(function(...) @@ -5125,37 +5355,37 @@ _M=e; return e; end -local p=type; -local t,y,c=table.insert,table.concat,table.remove; -local n=string.char; -local z,d=tostring,tonumber; -local u,r,j=pairs,ipairs,require"util.iterators".sorted_pairs; +local u=type; +local t,w,y=table.insert,table.concat,table.remove; +local s=string.char; +local x,d=tostring,tonumber; +local p,l,z=pairs,ipairs,require"util.iterators".sorted_pairs; local i=next; -local b,m=getmetatable,setmetatable; -local l=print; +local b,f=getmetatable,setmetatable; +local r=print; local a,e=pcall(require,"util.array"); local v=a and b(e())or{}; local a={}; -local h=m({},{__tostring=function()return"null";end;}); -a.null=h; -local f={ +local n=f({},{__tostring=function()return"null";end;}); +a.null=n; +local m={ ["\""]="\\\"",["\\"]="\\\\",["\b"]="\\b", ["\f"]="\\f",["\n"]="\\n",["\r"]="\\r",["\t"]="\\t"}; -for t=0,31 do -local e=n(t); -if not f[e]then f[e]=("\\u%.4X"):format(t);end -end -local function q(e) -if e<128 then return n(e);end +for e=0,31 do +local t=s(e); +if not m[t]then m[t]=("\\u%.4X"):format(e);end +end +local function j(e) +if e<128 then return s(e);end local t=e%64; if e<2048 then local e=(e-t)/64; -return n(128+64+e,128+t); +return s(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 s(128+64+32+e,128+o,128+t); end local k={ number=true, @@ -5163,87 +5393,87 @@ table=true, boolean=true }; -local x={ +local q={ __array=true; __hash=true; }; -local o,g,s,w; -function w(a,e) -t(e,"\""..(a:gsub(".",f)).."\""); -end -function s(a,e) +local o,g,h,c; +function c(a,e) +t(e,"\""..(a:gsub(".",m)).."\""); +end +function h(a,e) t(e,"["); if i(a)then -for i,a in r(a)do +for i,a in l(a)do o(a,e); t(e,","); end -c(e); +y(e); end t(e,"]"); end -function g(l,e) +function g(d,e) local a={}; -local n={}; -local d={}; -for e,t in r(l)do -a[e]=t; -end -for e,t in u(l)do -local o,i=p(e),p(t); -if k[i]or t==h then -if o=="string"and not x[e]then -d[e]=t; -elseif(k[o]or e==h)and a[e]==nil then -n[e]=t; -end -end -end -if i(n)~=nil or i(d)~=nil or i(a)==nil then +local s={}; +local r={}; +for t,e in l(d)do +a[t]=e; +end +for e,t in p(d)do +local o,i=u(e),u(t); +if k[i]or t==n then +if o=="string"and not q[e]then +r[e]=t; +elseif(k[o]or e==n)and a[e]==nil then +s[e]=t; +end +end +end +if i(s)~=nil or i(r)~=nil or i(a)==nil then t(e,"{"); -local r=#e; -local h=e.ordered and j or u; -for a,i in h(d)do -w(a,e); +local n=#e; +local d=e.ordered and z or p; +for a,i in d(r)do +c(a,e); t(e,":"); o(i,e); t(e,","); end -if i(n)~=nil then +if i(s)~=nil then t(e,"\"__hash\":["); -for a,i in u(n)do +for a,i in p(s)do o(a,e); t(e,","); o(i,e); t(e,","); end -c(e); +y(e); t(e,"]"); t(e,","); end if i(a)then t(e,"\"__array\":"); -s(a,e); +h(a,e); t(e,","); end -if r~=#e then c(e);end +if n~=#e then y(e);end t(e,"}"); else -s(a,e); +h(a,e); end end function o(e,a) -local o=p(e); -if e==h then +local o=u(e); +if e==n then t(a,"null"); elseif o=="number"then -t(a,z(e)); +t(a,x(e)); elseif o=="string"then -w(e,a); +c(e,a); elseif o=="table"then local t=b(e); if t==v then -s(e,a); +h(e,a); else g(e,a); end @@ -5256,26 +5486,26 @@ function a.encode(t) local e={}; o(t,e); -return y(e); +return w(e); end function a.encode_ordered(t) local e={ordered=true}; o(t,e); -return y(e); +return w(e); end function a.encode_array(t) local e={}; -s(t,e); -return y(e); +h(t,e); +return w(e); end local function o(t,e) return t:find("[^ \t\r\n]",e)or e; end -local function c(e) +local function u(e) local a=e.__array; if a then e.__array=nil; -for o,a in r(a)do +for o,a in l(a)do t(e,a); end end @@ -5283,7 +5513,7 @@ if a then e.__hash=nil; local t; -for o,a in r(a)do +for o,a in l(a)do if t~=nil then e[t]=a;t=nil; else @@ -5293,127 +5523,127 @@ end return e; end -local s,r; -local function u(t,e) -local i={}; +local i,h; +local function c(t,e) +local n={}; while true do -local n,a; +local s,a; e=o(t,e+1); if t:byte(e)~=34 then -if t:byte(e)==125 then return i,e+1;end +if t:byte(e)==125 then return n,e+1;end return nil,"key expected"; end -n,e=r(t,e); -if n==nil then return nil,e;end +s,e=h(t,e); +if s==nil then return nil,e;end e=o(t,e); if t:byte(e)~=58 then return nil,"colon expected";end -a,e=s(t,e+1); +a,e=i(t,e+1); if a==nil then return nil,e;end -i[n]=a; +n[s]=a; e=o(t,e); local t=t:byte(e); -if t==125 then return c(i),e+1;end +if t==125 then return u(n),e+1;end if t~=44 then return nil,"object eof";end end end -local function c(n,e) -local i={}; +local function u(s,e) +local n={}; while true do local a,h; -a,e,h=s(n,e+1,93); +a,e,h=i(s,e+1,93); if a==nil then if h then -if#i~=0 then +if#n~=0 then return nil,"value expected"; end -a,e=m(i,v),e+1; +a,e=f(n,v),e+1; end return a,e; end -t(i,a); -e=o(n,e); -local t=n:byte(e); -if t==93 then return m(i,v),e+1;end +t(n,a); +e=o(s,e); +local t=s:byte(e); +if t==93 then return f(n,v),e+1;end if t~=44 then return nil,"array eof";end end end local t; -local function i(e) +local function l(e) local t,e=d(e:sub(3,6),16),d(e:sub(9,12),16); local e=t*1024+e-56613888; local o=e%64; e=(e-o)/64; -local t=e%64; -e=(e-t)/64; local a=e%64; e=(e-a)/64; -return n(240+e,128+a,128+t,128+o); -end -local function n(e) +local t=e%64; +e=(e-t)/64; +return s(240+e,128+t,128+a,128+o); +end +local function s(e) e=e:match("%x%x%x%x",3); if e then local e=d(e,16) if e>=55296 and e<=57343 then t=true;end -return q(e); +return j(e); end t=true; end -function r(o,e) +function h(o,e) e=e+1; local a=o:find("\"",e,true); if a then local e=o:sub(e,a-1); t=nil; -e=e:gsub("\\u[dD][89abAB]%x%x\\u[dD][cdefCDEF]%x%x",i); -e=e:gsub("\\u.?.?.?.?",n); +e=e:gsub("\\u[dD][89abAB]%x%x\\u[dD][cdefCDEF]%x%x",l); +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 i(e,t) +local function s(e,t) local e=e:match("[0-9%.%-eE%+]+",t); return d(e),t+#e; end local function d(t,e) -local o,a,t=t:byte(e+1,e+3); -if o==117 and a==108 and t==108 then -return h,e+4; +local t,a,o=t:byte(e+1,e+3); +if t==117 and a==108 and o==108 then +return n,e+4; end return nil,"null parse failed"; end -local function n(t,e) +local function l(t,e) local o,t,a=t:byte(e+1,e+3); if o==114 and t==117 and a==101 then return true,e+4; end return nil,"true parse failed"; end -local function h(t,e) -local o,a,t,i=t:byte(e+1,e+4); -if o==97 and a==108 and t==115 and i==101 then +local function n(t,e) +local o,i,a,t=t:byte(e+1,e+4); +if o==97 and i==108 and a==115 and t==101 then return false,e+5; end return nil,"false parse failed"; end -function s(a,e,s) +function i(a,e,i) e=o(a,e); local t=a:byte(e); if t==123 then -return u(a,e); +return c(a,e); elseif t==91 then -return c(a,e); +return u(a,e); elseif t==34 then -return r(a,e); +return h(a,e); elseif t~=nil and t>=48 and t<=57 or t==45 then -return i(a,e); +return s(a,e); elseif t==110 then return d(a,e); elseif t==116 then -return n(a,e); +return l(a,e); elseif t==102 then -return h(a,e); -elseif t==s then +return n(a,e); +elseif t==i then return nil,e,true; else return nil,"value expected"; @@ -5432,7 +5662,7 @@ }; function a.decode(e) e=e:gsub("\\.",t) -local t,a=s(e,1); +local t,a=i(e,1); if t==nil then return t,a;end if e:find("[^ \t\r\n]",a)then return nil,"garbage at eof";end return t; @@ -5442,11 +5672,11 @@ local t=a.decode(e); local t=a.encode(t); if e~=t then -l("FAILED"); -l("encoded:",e); -l("recoded:",t); -else -l(e); +r("FAILED"); +r("encoded:",e); +r("recoded:",t); +else +r(e); end return e==t; end @@ -5465,38 +5695,38 @@ return e; end local t=require"util.stanza"; -local u=require"lxp"; -local i=table.insert; -local r=table.remove; -local c=error; +local d=require"lxp"; +local r=table.insert; +local h=table.remove; +local l=error; local _ENV=nil; local e=(function() -local d={ +local c={ ["http://www.w3.org/XML/1998/namespace"]="xml"; }; local n="\1"; -local h="^([^"..n.."]*)"..n.."?(.*)$"; -return function(l,o) +local s="^([^"..n.."]*)"..n.."?(.*)$"; +return function(u,o) local e={}; local a=t.stanza("root"); local t={}; -local s={}; +local i={}; function e:StartNamespaceDecl(e,a) if e~=nil then -i(t,a); -i(s,e); +r(t,a); +r(i,e); end end function e:EndNamespaceDecl(e) if e~=nil then -r(t); -r(s); +h(t); +h(i); end end function e:StartElement(o,e) -local o,i=o:match(h); -if i==""then -o,i="",o; +local o,n=o:match(s); +if n==""then +o,n="",o; end if o~=""then e.xmlns=o; @@ -5504,9 +5734,9 @@ for t=1,#e do local a=e[t]; e[t]=nil; -local t,o=a:match(h); +local t,o=a:match(s); if o~=""then -t=d[t]; +t=c[t]; if t then e[t..":"..o]=e[a]; e[a]=nil; @@ -5515,9 +5745,9 @@ end local o={} for e=1,#t do -o[s[e]]=t[e]; -end -a:tag(i,e,o); +o[i[e]]=t[e]; +end +a:tag(n,e,o); end function e:CharacterData(e) a:text(e); @@ -5527,7 +5757,7 @@ end local function t(t) if not t.stop or not t:stop()then -c("Failed to abort parsing"); +l("Failed to abort parsing"); end end e.StartDoctypeDecl=t; @@ -5537,13 +5767,13 @@ if not o or not o.allow_processing_instructions then e.ProcessingInstruction=t; end -local t=u.new(e,n); -local e,i,o,n=t:parse(l); -if e then e,i,o,n=t:parse();end +local t=d.new(e,n); +local e,o,n,i=t:parse(u); +if e then e,o,n,i=t:parse();end if e then return a.tags[1]; else -return e,("%s (line %d, col %d))"):format(i,o,n); +return e,("%s (line %d, col %d))"):format(o,n,i); end end; end)(); @@ -5563,16 +5793,16 @@ _M=e; return e; end -local s=require"util.stanza".stanza; -local t,o=tostring,tonumber; -local h=type; -local n=pairs; -local i='http://jabber.org/protocol/rsm'; +local h=require"util.stanza".stanza; +local o,i=tostring,tonumber; +local s=type; +local r=pairs; +local n='http://jabber.org/protocol/rsm'; local a={}; do local e=a; local function t(e) -return o((e:get_text())); +return i((e:get_text())); end local function a(t) return t:get_text(); @@ -5585,34 +5815,34 @@ e.max=t; e.index=t; e.first=function(e) -return{index=o(e.attr.index);e:get_text()}; +return{index=i(e.attr.index);e:get_text()}; end; e.last=a; e.count=t; end -local h=setmetatable({ -first=function(a,e) -if h(e)=="table"then -a:tag("first",{index=e.index}):text(e[1]):up(); -else -a:tag("first"):text(t(e)):up(); +local s=setmetatable({ +first=function(t,e) +if s(e)=="table"then +t:tag("first",{index=e.index}):text(e[1]):up(); +else +t:tag("first"):text(o(e)):up(); end end; -before=function(a,e) +before=function(t,e) if e==true then -a:tag("before"):up(); -else -a:tag("before"):text(t(e)):up(); +t:tag("before"):up(); +else +t:tag("before"):text(o(e)):up(); end end },{ -__index=function(a,e) -return function(a,o) -a:tag(e):text(t(o)):up(); +__index=function(t,e) +return function(a,t) +a:tag(e):text(o(t)):up(); end end; }); -local function t(e) +local function o(e) local o={}; for t in e:childtags()do local e=t.name; @@ -5623,22 +5853,22 @@ end return o; end -local function o(t) -local e=s("set",{xmlns=i}); -for t,o in n(t)do +local function i(t) +local e=h("set",{xmlns=n}); +for t,o in r(t)do if a[t]then -h[t](e,o); -end -end -return e; -end -local function a(e) -local e=e:get_child("set",i); +s[t](e,o); +end +end +return e; +end +local function t(e) +local e=e:get_child("set",n); if e and#e.tags>0 then -return t(e); -end -end -return{parse=t,generate=o,get=a}; +return o(e); +end +end +return{parse=o,generate=i,get=t}; end) package.preload['util.random']=(function(...) local _ENV=_ENV; @@ -5678,20 +5908,20 @@ local n=require"util.hex"; local a={}; local o={ -__index=function(o,t) -local e=a[t]; -if not e then return nil;end -local e=e(o); -o[t]=e; -return e; +__index=function(e,t) +local a=a[t]; +if not a then return nil;end +local a=a(e); +e[t]=a; +return a; end, __tostring=function(e)return e.addr;end, }; -o.__eq=function(t,e) -if getmetatable(t)~=o or getmetatable(e)~=o then +o.__eq=function(e,t) +if getmetatable(e)~=o or getmetatable(t)~=o then return false; end -return t.packed==e.packed; +return e.packed==t.packed; end local h={ ["0"]="0000",["1"]="0001",["2"]="0010",["3"]="0011", @@ -5736,7 +5966,7 @@ return e.bits; end local e; -local function v(t,a) +local function y(t,a) t,a=t.bits_full,a.bits_full; for e=1,128 do if t:sub(e,e)~=a:sub(e,e)then @@ -5745,77 +5975,77 @@ end return 128; end -local n=t("::1"); -local w=t("127.0.0.0"); -local h=t("2002::"); -local d=t("2001::"); -local p=t("fe80::"); -local m=t("169.254.0.0"); -local r=t("fc00::"); -local i=t("fec0::"); -local l=t("3ffe::"); -local u=t("::"); -local f=t("ff00::"); -local c=t("::ffff:0:0"); -local function y(t) -if e(t,w,8)then +local i=t("::1"); +local m=t("127.0.0.0"); +local u=t("2002::"); +local h=t("2001::"); +local f=t("fe80::"); +local w=t("169.254.0.0"); +local c=t("fc00::"); +local n=t("fec0::"); +local r=t("3ffe::"); +local d=t("::"); +local v=t("ff00::"); +local l=t("::ffff:0:0"); +local function p(t) +if e(t,m,8)then return 2; -elseif e(t,m,16)then +elseif e(t,w,16)then return 2; else return 14; end end local function w(t) -if t==n then +if t==i then return 2; -elseif e(t,p,10)then +elseif e(t,f,10)then return 2; -elseif e(t,i,10)then +elseif e(t,n,10)then return 5; -elseif e(t,f,10)then +elseif e(t,v,10)then return t.packed:byte(2)%16; else return 14; end end local function m(t) -if t==n then +if t==i then return 0; -elseif e(t,h,16)then +elseif e(t,u,16)then return 2; -elseif e(t,d,32)then +elseif e(t,h,32)then return 5; -elseif e(t,r,7)then +elseif e(t,c,7)then return 13; -elseif e(t,i,10)then +elseif e(t,n,10)then return 11; -elseif e(t,l,16)then +elseif e(t,r,16)then return 12; -elseif e(t,u,96)then +elseif e(t,d,96)then return 3; -elseif e(t,c,96)then +elseif e(t,l,96)then return 4; else return 1; end end local function f(t) -if t==n then +if t==i then return 50; -elseif e(t,h,16)then +elseif e(t,u,16)then return 30; -elseif e(t,d,32)then +elseif e(t,h,32)then return 5; -elseif e(t,r,7)then +elseif e(t,c,7)then return 3; -elseif e(t,i,10)then +elseif e(t,n,10)then return 1; -elseif e(t,l,16)then +elseif e(t,r,16)then return 1; -elseif e(t,u,96)then +elseif e(t,d,96)then return 1; -elseif e(t,c,96)then +elseif e(t,l,96)then return 35; else return 40; @@ -5842,19 +6072,19 @@ end function a:scope() if self.proto=="IPv4"then -return y(self); +return p(self); else return w(self); end end -local r=t("10.0.0.0"); -local h=t("172.16.0.0"); -local i=t("192.168.0.0"); -local n=t("100.64.0.0"); +local n=t("10.0.0.0"); +local i=t("172.16.0.0"); +local r=t("192.168.0.0"); +local h=t("100.64.0.0"); function a:private() local t=self.scope~=14; if not t and self.proto=="IPv4"then -return e(self,r,8)or e(self,h,12)or e(self,i,16)or e(self,n,10); +return e(self,n,8)or e(self,i,12)or e(self,r,16)or e(self,h,10); end return t; end @@ -5898,7 +6128,7 @@ end return{ new_ip=t, -commonPrefixLength=v, +commonPrefixLength=y, parse_cidr=n, match=e, is_ip=i; @@ -5917,25 +6147,25 @@ _M=e; return e; end -local h=string.char; +local n=string.char; local s=string.format; -local o=string.gsub; -local n=string.lower; -local a={}; +local a=string.gsub; +local h=string.lower; +local o={}; local i={}; do -local e,t; -for o=0,255 do -e,t=h(o),s("%02x",o); -a[e]=t; -i[t]=e; +local t,e; +for a=0,255 do +t,e=n(a),s("%02x",a); +o[t]=e; +i[e]=t; end end local function t(e) -return(o(e,".",a)); +return(a(e,".",o)); end local function e(e) -return(o(n(e),"%X*(%x%x)%X*",i)); +return(a(h(e),"%X*(%x%x)%X*",i)); end return{ encode=t,decode=e; @@ -5976,53 +6206,53 @@ _M=e; return e; end -local n=type; -local o=pairs; +local i=type; +local a=pairs; local t=rawset; local r=rawget; -local c=error; -local d=table.concat; -local l=table.insert; -local u=setmetatable; -local m=require"util.paths".resolve_relative_path; +local f=error; +local m=table.concat; +local u=table.insert; +local c=setmetatable; +local l=require"util.paths".resolve_relative_path; local _ENV=nil; -local i={}; +local n={}; local e={}; -local f=function(e)return e end -function i.options(h,s,e) -local a=h[s]or{}; -if n(e)~="table"then e={e}end -for o,e in o(e)do +local d=function(e)return e end +function n.options(h,s,e) +local o=h[s]or{}; +if i(e)~="table"then e={e}end +for a,e in a(e)do if e==true or e==false then -a[o]=e; -else -a[e]=true; -end -end -t(h,s,a) -end -i.verifyext=i.options; -function e.options(a) +o[a]=e; +else +o[e]=true; +end +end +t(h,s,o) +end +n.verifyext=n.options; +function e.options(o) local t={}; -for e,a in o(a)do -if a then -t[#t+1]=e; +for a,e in a(o)do +if e then +t[#t+1]=a; end end return t; end e.verifyext=e.options; function e.ciphers(t) -if n(t)=="table"then -return d(t,":"); +if i(t)=="table"then +return m(t,":"); end return t; end e.curveslist=e.ciphers; e.ciphersuites=e.ciphers; function e.key(t,a) -if n(t)=="string"then -return m(a._basedir,t); +if i(t)=="string"then +return l(a._basedir,t); else return nil end @@ -6031,39 +6261,39 @@ e.cafile=e.key; e.capath=e.key; e.dhparam=e.key; -local a={"sslv2","sslv3","tlsv1","tlsv1_1","tlsv1_2","tlsv1_3"}; -for e=1,#a do a[a[e].."+"]=e-1;end +local o={"sslv2","sslv3","tlsv1","tlsv1_1","tlsv1_2","tlsv1_3"}; +for e=1,#o do o[o[e].."+"]=e-1;end local function h(e) -local t=a[e.protocol]; +local t=o[e.protocol]; if t then e.protocol="sslv23"; for t=1,t do -l(e.options,"no_"..a[t]); -end -end -end -local function s(e,a) -t(e,"_cache",nil); -if n(a)=="table"then -for a,o in o(a)do -if a:sub(1,1)~="_"then -(i[a]or t)(e,a,o); -end -end -end -return e -end -local function n(i) -local a={}; -for t,o in o(i)do +u(e.options,"no_"..o[t]); +end +end +end +local function s(o,e) +t(o,"_cache",nil); +if i(e)=="table"then +for e,a in a(e)do +if e:sub(1,1)~="_"then +(n[e]or t)(o,e,a); +end +end +end +return o +end +local function i(i) +local o={}; +for t,a in a(i)do if t:sub(1,1)~="_"then -a[t]=(e[t]or f)(o,i); -end -end -h(a); -return a; -end -local function i(e) +o[t]=(e[t]or d)(a,i); +end +end +h(o); +return o; +end +local function n(e) local a=r(e,"_cache"); if a then return a,nil @@ -6077,32 +6307,32 @@ local e={ __index={ apply=s; -final=n; -build=i; +final=i; +build=n; }; __newindex=function() -c("SSL config objects cannot be modified directly. Use :apply()") +f("SSL config objects cannot be modified directly. Use :apply()") end; }; -local function a(t,a) -return u({ +local function n(t,a) +return c({ _context_factory=t, _basedir=a, options={}, },e); end local function h(i) -local a=a(); -for e,o in o(i)do -t(a,e,o); -end -return a +local o=n(); +for e,a in a(i)do +t(o,e,a); +end +return o end e.__index.clone=h; return{ apply=s; -final=n; -_new=a; +final=i; +_new=n; }; end) package.preload['util.paths']=(function(...) @@ -6118,23 +6348,23 @@ return e; end local i=table.concat; -local t=package.config:sub(1,1); +local e=package.config:sub(1,1); local a={} -function a.resolve_relative_path(a,e) -if e then -a=a:gsub("%"..t.."+$",""); -e=e:gsub("^%.%"..t.."+",""); -local o; -if t=="/"and e:sub(1,1)~="/"then -o=true; -elseif t=="\\"and(e:sub(1,1)~="/"and(e:sub(2,3)~=":\\"and e:sub(2,3)~=":/"))then -o=true; -end -if o then -return a..t..e; -end -end -return e; +function a.resolve_relative_path(o,t) +if t then +o=o:gsub("%"..e.."+$",""); +t=t:gsub("^%.%"..e.."+",""); +local a; +if e=="/"and t:sub(1,1)~="/"then +a=true; +elseif e=="\\"and(t:sub(1,1)~="/"and(t:sub(2,3)~=":\\"and t:sub(2,3)~=":/"))then +a=true; +end +if a then +return o..e..t; +end +end +return t; end function a.glob_to_pattern(e) return"^"..e:gsub("[%p*?]",function(e) @@ -6147,29 +6377,29 @@ end end).."$"; end -function a.join(a,e,o,...) -if e then +function a.join(t,a,o,...) +if a then if o then if...then -return i({a,e,o,...},t); -end -return a..t..e..t..o; -end -return a..t..e; -end -return a; +return i({t,a,o,...},e); +end +return t..e..a..e..o; +end +return t..e..a; +end +return t; end function a.complement_lua_path(t) -local a=_VERSION:match(" (.+)$"); -local o=package.config:sub(3,3); +local o=_VERSION:match(" (.+)$"); +local a=package.config:sub(3,3); local e=package.config:sub(1,1); -local a=e.."lua"..e..a..e; +local o=e.."lua"..e..o..e; if not string.find(package.path,t,1,true)then -package.path=package.path..o..t..e.."share"..a.."?.lua"; -package.path=package.path..o..t..e.."share"..a.."?"..e.."init.lua"; +package.path=package.path..a..t..e.."share"..o.."?.lua"; +package.path=package.path..a..t..e.."share"..o.."?"..e.."init.lua"; end if not string.find(package.path,t,1,true)then -package.cpath=package.cpath..o..t..e.."lib"..a.."?.so"; +package.cpath=package.cpath..a..t..e.."lib"..o.."?.so"; end end return a; @@ -6342,11 +6572,11 @@ return e; end local t=require"ssl"; -local h=t.newcontext; +local o=t.newcontext; local s=t.context or require"ssl.context"; -local o=io.open; +local n=io.open; local e={}; -local n={__index=e}; +local h={__index=e}; function e:set_sni_host(a,t,e) local e,t=self._builder:clone():apply({ certificate=t, @@ -6370,13 +6600,13 @@ end local function i(e,i) if type(e.dhparam)=="string"then -local t,a=o(e.dhparam); +local t,a=n(e.dhparam); if not t then return nil,"Could not open DH parameters: "..a end local a=t:read("*a"); t:close(); e.dhparam=function()return a;end end -local t,a=h(e); +local t,a=o(e); if not t then return nil,a end @@ -6391,7 +6621,7 @@ _inner=t, _builder=i, _sni_contexts={}, -},n),nil +},h),nil end return{ new_context=i, @@ -6409,20 +6639,20 @@ _M=e; return e; end -local n,m=require"mime".b64,require"mime".unb64; +local s,h=require"mime".b64,require"mime".unb64; local t=require"util.hashes"; -local a=require"bit"; -local d=require"util.random"; -local p=tonumber; -local s,e=string.char,string.byte; -local i=string.gsub; -local h=a.bxor; -local function r(a,t) -return(i(a,"()(.)",function(a,o) -return s(h(e(o),e(t,a))) +local i=require"bit"; +local l=require"util.random"; +local c=tonumber; +local a,e=string.char,string.byte; +local o=string.gsub; +local i=i.bxor; +local function r(n,t) +return(o(n,"()(.)",function(n,o) +return a(i(e(o),e(t,n))) end)); end -local f,t=t.sha1,t.hmac_sha1; +local y,t=t.sha1,t.hmac_sha1; local function w(o,e,i) local e=t(o,e.."\0\0\0\1"); local a=e; @@ -6432,13 +6662,13 @@ end return a; end -local function y(e) +local function f(e) return e; end local function a(e) -return(i(e,"[,=]",{[","]="=2C",["="]="=3D"})); -end -local function s(e) +return(o(e,"[,=]",{[","]="=2C",["="]="=3D"})); +end +local function n(e) if e:ssl()then local e=e:socket(); if e.info and e:info().protocol=="TLSv1.3"then @@ -6450,61 +6680,61 @@ end end end -local function h(e,o) +local function d(e,i) local a="n="..a(e.username); -local i=n(d.bytes(15)); -local h="r="..i; -local l=a..","..h; +local o=s(l.bytes(15)); +local u="r="..o; +local l=a..","..u; local d=""; local a="n"; -if o=="SCRAM-SHA-1-PLUS"then -a,d=s(e.conn); -elseif s(e.conn)then +if i=="SCRAM-SHA-1-PLUS"then +a,d=n(e.conn); +elseif n(e.conn)then a="y"; end -local s=a..",,"; -local a=s..l; -local a,u=coroutine.yield(a); +local n=a..",,"; +local a=n..l; +local a,m=coroutine.yield(a); if a~="challenge"then return false end -local a,o,c=u:match("(r=[^,]+),s=([^,]*),i=(%d+)"); -local c=p(c); -o=m(o); -if not a or not o or not c then +local a,i,p=m:match("(r=[^,]+),s=([^,]*),i=(%d+)"); +local c=c(p); +i=h(i); +if not a or not i or not c then return false,"Could not parse server_first_message"; -elseif a:find(i,3,true)~=3 then +elseif a:find(o,3,true)~=3 then return false,"nonce sent by server does not match our nonce"; -elseif a==h then +elseif a==u then return false,"server did not append s-nonce to nonce"; end -local i=s..d; -local i="c="..n(i); -local h=i..","..a; -local i; +local o=n..d; +local o="c="..s(o); +local d=o..","..a; local a; -local s; +local o; +local n; if e.client_key and e.server_key then -a=e.client_key; -s=e.server_key; +o=e.client_key; +n=e.server_key; else if e.salted_password then -i=e.salted_password; +a=e.salted_password; elseif e.password then -i=w(y(e.password),o,c); -end -s=t(i,"Server Key"); -a=t(i,"Client Key"); -end -local o=f(a); -local e=l..","..u..","..h; -local o=t(o,e); -local a=r(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 m(e)~=t then +a=w(f(e.password),i,c); +end +n=t(a,"Server Key"); +o=t(a,"Client Key"); +end +local a=y(o); +local e=l..","..m..","..d; +local a=t(a,e); +local o=r(o,a); +local a=t(n,e); +local e="p="..s(o); +local e=d..","..e; +local t,e=coroutine.yield(e); +if t~="success"then return false,"success-expected"end +local e=e:match("v=([^,]+)"); +if h(e)~=a then return false,"server signature did not match"; end return true; @@ -6512,10 +6742,10 @@ 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 h,99; +return d,99; elseif t=="SCRAM-SHA-1-PLUS"then -if s(e.conn)then -return h,100; +if n(e.conn)then +return d,100; end end end @@ -6573,8 +6803,8 @@ _M=e; return e; end -return function(a,e) -if e=="OAUTHBEARER"and a.username then +return function(t,e) +if e=="OAUTHBEARER"and t.username then return function(e) local t=e.bearer_token and("Bearer "..e.bearer_token)or""; local t,a=coroutine.yield("n,a="..e.username.."@"..e.host..",\001auth="..t.."\001"); @@ -6589,7 +6819,7 @@ end return false; end -end,a.bearer_token and 6 or 4; +end,t.bearer_token and 6 or 4; end end end) @@ -6654,28 +6884,28 @@ _M=e; return e; end -local i=require"verse"; -local h,r=require"mime".b64,require"mime".unb64; +local n=require"verse"; +local s,r=require"mime".b64,require"mime".unb64; local o="urn:ietf:params:xml:ns:xmpp-sasl"; -function i.plugins.sasl(e) +function n.plugins.sasl(e) local function d(t) if e.authenticated then return;end e:debug("Authenticating with SASL..."); local t=t:get_child("mechanisms",o); if not t then return end local a={}; -local n={}; -local s={}; +local i={}; +local h={}; for t in t:childtags("mechanism")do t=t:get_text(); e:debug("Server offers %s",t); -s[t]=true; +h[t]=true; if not a[t]then -local i=t:match("[^-]+"); -local s,o=pcall(require,"util.sasl."..i:lower()); +local n=t:match("[^-]+"); +local s,o=pcall(require,"util.sasl."..n:lower()); if s then -e:debug("Loaded SASL %s module",i); -a[t],n[t]=o(e,t); +e:debug("Loaded SASL %s module",n); +a[t],i[t]=o(e,t); elseif not tostring(o):match("not found")then e:debug("Loading failed: %s",tostring(o)); end @@ -6686,18 +6916,18 @@ table.insert(t,e); end if not t[1]then -e:event("authentication-failure",{condition="no-supported-sasl-mechanisms",mechanisms=s}); +e:event("authentication-failure",{condition="no-supported-sasl-mechanisms",mechanisms=h}); e:close(); return; end -table.sort(t,function(t,e)return n[t]>n[e];end); -local t,n=t[1]; +table.sort(t,function(t,e)return i[t]>i[e];end); +local t,i=t[1]; e:debug("Selecting %s mechanism...",t); e.sasl_mechanism=coroutine.wrap(a[t]); -n=e:sasl_mechanism(t); -local t=i.stanza("auth",{xmlns=o,mechanism=t}); -if n then -t:text(h(n)); +i=e:sasl_mechanism(t); +local t=n.stanza("auth",{xmlns=o,mechanism=t}); +if i then +t:text(s(i)); end e:send(t); return true; @@ -6720,7 +6950,7 @@ e.authenticated=true e:reopen(); else -e:send(i.stanza("response",{xmlns=o}):text(h(t))); +e:send(n.stanza("response",{xmlns=o}):text(s(t))); end return true; end @@ -6742,10 +6972,10 @@ return e; end local t=require"verse"; -local i=require"util.jid"; +local o=require"util.jid"; local a="urn:ietf:params:xml:ns:xmpp-bind"; function t.plugins.bind(e) -local function o(o) +local function i(i) if e.bound then return;end e:debug("Binding resource..."); e:send_iq(t.iq({id="bind",type="set"}):tag("bind",{xmlns=a}):tag("resource"):text(e.resource), @@ -6754,17 +6984,17 @@ local t=t :get_child("bind",a) :get_child_text("jid"); -e.username,e.host,e.resource=i.split(t); +e.username,e.host,e.resource=o.split(t); e.jid,e.bound=t,true; e:event("bind-success",{jid=t}); elseif t.attr.type=="error"then local a=t:child_with_name("error"); -local t,a,o=t:get_error(); -e:event("bind-failure",{error=a,text=o,type=t}); -end -end); -end -e:hook("stream-features",o,200); +local o,t,a=t:get_error(); +e:event("bind-failure",{error=t,text=a,type=o}); +end +end); +end +e:hook("stream-features",i,200); return true; end end) @@ -6781,38 +7011,38 @@ return e; end local n=require"verse"; -local r=require"socket".gettime; +local h=require"socket".gettime; local s="urn:xmpp:sm:3"; function n.plugins.smacks(e) local t=nil; local a=nil; -local h=nil; -local o; -local i=nil; -local function m(t) -if i and(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 c(a) +local r=nil; +local i; +local o=nil; +local function l(t) +if o and(t.attr.xmlns=="jabber:client"or not t.attr.xmlns)then +o=o+1; +e:debug("Increasing handled stanzas to %d for %s",o,t:top_tag()); +end +end +local function d(a) if t and(a.name and not a.attr.xmlns)then t[#t+1]=tostring(a); -h=r(); -if not o then -o=true; +r=h(); +if not i then +i=true; e:debug("Waiting to send ack request..."); n.add_task(1,function() if#t==0 then -o=false; +i=false; return; end -local a=r()-h; +local a=h()-r; if a<1 and#t<10 then return 1-a; end e:debug("Time up, sending ..."); -o=false; +i=false; e:send(n.stanza("r",{xmlns=s})); end); end @@ -6830,15 +7060,15 @@ return true; end end -local function d() +local function c() e.resumption_token=nil; end -local function l(o) -if o.name=="r"then -e:debug("Ack requested... acking %d handled stanzas",i); -e:send(n.stanza("a",{xmlns=s,h=tostring(i)})); -elseif o.name=="a"then -local o=tonumber(o.attr.h); +local function m(i) +if i.name=="r"then +e:debug("Ack requested... acking %d handled stanzas",o); +e:send(n.stanza("a",{xmlns=s,h=tostring(o)})); +elseif i.name=="a"then +local o=tonumber(i.attr.h); if o>a then local i=#t; for a=a+1,o do @@ -6849,15 +7079,15 @@ elseif oa then local i=#t; for a=a+1,o do @@ -6872,25 +7102,25 @@ t={}; e:debug("Resumed successfully"); e:event("resumed"); -elseif o.name=="failed"then +elseif i.name=="failed"then e.bound=nil e.smacks=nil a=nil -i=nil +o=nil t={}; local t=e.pre_smacks_features; e.pre_smacks_features=nil; e:event("stream-features",t); else -e:warn("Don't know how to handle "..s.."/"..o.name); -end -end -local function o() +e:warn("Don't know how to handle "..s.."/"..i.name); +end +end +local function i() if e.stream_management_supported and not e.smacks then e:debug("smacks: sending enable"); t={}; a=0; -h=r(); +r=h(); e:send(n.stanza("enable",{xmlns=s,resume="true"})); e.smacks=true; end @@ -6900,20 +7130,20 @@ e.pre_smacks_features=t; e.stream_management_supported=true; if e.smacks and e.bound then -e:debug("Resuming stream with %d handled stanzas",i); +e:debug("Resuming stream with %d handled stanzas",o); e:send(n.stanza("resume",{xmlns=s, -h=tostring(i),previd=e.resumption_token})); +h=tostring(o),previd=e.resumption_token})); return true; else end end end e:hook("stream-features",a,250); -e:hook("stream/"..s,l); -e:hook("bind-success",o,1); -e:hook("stanza",m); -e:hook("outgoing",c); -e:hook("closed",d,100); +e:hook("stream/"..s,m); +e:hook("bind-success",i,1); +e:hook("stanza",l); +e:hook("outgoing",d); +e:hook("closed",c,100); e:hook("disconnected",u,100); end end) @@ -6953,24 +7183,24 @@ local t=require"verse"; local e=require("mime").b64; local e=require("util.hashes").sha1; -local s=require"util.caps".calculate_hash; -local h="http://jabber.org/protocol/caps"; +local r=require"util.caps".calculate_hash; +local n="http://jabber.org/protocol/caps"; local e="http://jabber.org/protocol/disco"; local o=e.."#info"; local i=e.."#items"; function t.plugins.disco(e) e:add_plugin("presence"); -local a={ -__index=function(t,e) -local a={identities={},features={}}; +local s={ +__index=function(a,e) +local t={identities={},features={}}; if e=="identities"or e=="features"then -return t[false][e] -end -t[e]=a; -return a; +return a[false][e] +end +a[e]=t; +return t; end, }; -local n={ +local a={ __index=function(t,a) local e={}; t[a]=e; @@ -6985,17 +7215,17 @@ {category='client',type='pc',name='Verse'}, }, features={ -[h]=true, +[n]=true, [o]=true, [i]=true, }, }, -},a); -items=setmetatable({[false]={}},n); +},s); +items=setmetatable({[false]={}},a); }; e.caps={} e.caps.node='http://code.matthewwild.co.uk/verse/' -local function r(a) +local function h(a) local i=e.disco.info[a or false]; if a and a==e.caps.node.."#"..e.caps.hash then i=e.disco.info[false]; @@ -7015,30 +7245,34 @@ end setmetatable(e.caps,{ __call=function(...) -local a=s(r()) +local a=r(h()) e.caps.hash=a; return t.stanza('c',{ -xmlns=h, +xmlns=n, hash='sha-1', node=e.caps.node, ver=a }) end }) -function e:set_identity(e,t) -self.disco.info[t or false].identities={e}; -end -function e:add_identity(t,e) -local e=self.disco.info[e or false].identities; -e[#e+1]=t; -end -function e:add_disco_feature(e,t) -local e=e.var or e; -self.disco.info[t or false].features[e]=true; -end -function e:remove_disco_feature(e,t) -local e=e.var or e; -self.disco.info[t or false].features[e]=nil; +function e:set_identity(a,t) +self.disco.info[t or false].identities={a}; +e:event("disco-info-changed"); +end +function e:add_identity(a,t) +local t=self.disco.info[t or false].identities; +t[#t+1]=a; +e:event("disco-info-changed"); +end +function e:add_disco_feature(t,a) +local t=t.var or t; +self.disco.info[a or false].features[t]=true; +e:event("disco-info-changed"); +end +function e:remove_disco_feature(t,a) +local t=t.var or t; +self.disco.info[a or false].features[t]=nil; +e:event("disco-info-changed"); end function e:add_disco_item(t,e) local e=self.disco.items[e or false]; @@ -7052,17 +7286,17 @@ end end end -function e:jid_has_identity(t,e,a) -local o=self.disco.cache[t]; +function e:jid_has_identity(e,a,t) +local o=self.disco.cache[e]; if not o then return nil,"no-cache"; end -local t=self.disco.cache[t].identities; -if a then -return t[e.."/"..a]or false; -end -for t in pairs(t)do -if t:match("^(.*)/")==e then +local e=self.disco.cache[e].identities; +if t then +return e[a.."/"..t]or false; +end +for e in pairs(e)do +if e:match("^(.*)/")==a then return true; end end @@ -7074,14 +7308,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 @@ -7117,22 +7351,19 @@ if t.attr.type=="error"then return h(nil,t:get_error()); end -local i,s,n={},{},{}; +local n,s,i={},{},{}; for e in t:get_child("query",o):childtags()do -self:debug("DISCO {%s}%s",e.attr.xmlns or"",e.name); if e.name=="identity"then -i[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 s[e.attr.var]=true; end end -for e in t:get_child("query",o):childtags("x","jabber:x:data")do -self:debug("DISCO {%s}%s",e.attr.xmlns or"",e.name); -local t=e:get_child_with_attr("field",nil,"var","FORM_TYPE"); -local a=t and t:get_child_text("value"); -self:debug("FORM: %s (%s)",a,t); -if a then -n[a]=e; +for t in t:get_child("query",o):childtags("x","jabber:x:data")do +local e=t:get_child_with_attr("field",nil,"var","FORM_TYPE"); +local e=e and e:get_child_text("value"); +if e then +i[e]=t; end end if not self.disco.cache[e]then @@ -7142,13 +7373,13 @@ if not self.disco.cache[e].nodes[a]then self.disco.cache[e].nodes[a]={nodes={}}; end -self.disco.cache[e].nodes[a].identities=i; +self.disco.cache[e].nodes[a].identities=n; self.disco.cache[e].nodes[a].features=s; -self.disco.cache[e].nodes[a].extended=n; -else -self.disco.cache[e].identities=i; +self.disco.cache[e].nodes[a].extended=i; +else +self.disco.cache[e].identities=n; self.disco.cache[e].features=s; -self.disco.cache[e].extended=n; +self.disco.cache[e].extended=i; end return h(self.disco.cache[e]); end); @@ -7156,17 +7387,17 @@ function e:disco_items(a,o,n) local t=t.iq({to=a,type="get"}) :tag("query",{xmlns=i,node=o}); -self:send_iq(t,function(t) -if t.attr.type=="error"then -return n(nil,t:get_error()); -end -local e={}; -for t in t:get_child("query",i):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(t,function(e) +if e.attr.type=="error"then +return n(nil,e:get_error()); +end +local t={}; +for e in e:get_child("query",i):childtags()do +if e.name=="item"then +table.insert(t,{ +name=e.attr.name; +jid=e.attr.jid; +node=e.attr.node; }); end end @@ -7177,29 +7408,29 @@ if not self.disco.cache[a].nodes[o]then self.disco.cache[a].nodes[o]={nodes={}}; end -self.disco.cache[a].nodes[o].items=e; -else -self.disco.cache[a].items=e; -end -return n(e); +self.disco.cache[a].nodes[o].items=t; +else +self.disco.cache[a].items=t; +end +return n(t); end); end e:hook("iq/"..o,function(a) local o=a.tags[1]; if a.attr.type=='get'and o.name=="query"then -local o=r(o.attr.node); +local o=h(o.attr.node); local t=t.reply(a):add_child(o); e:send(t); return true end end); -e:hook("iq/"..i,function(a) -local o=a.tags[1]; -if a.attr.type=='get'and o.name=="query"then -local n=e.disco.items[o.attr.node or false]; -local t=t.reply(a):tag('query',{ +e:hook("iq/"..i,function(o) +local a=o.tags[1]; +if o.attr.type=='get'and a.name=="query"then +local n=e.disco.items[a.attr.node or false]; +local t=t.reply(o):tag('query',{ xmlns=i, -node=o.attr.node +node=a.attr.node }) for a=1,#n do t:tag('item',n[a]):up() @@ -7212,33 +7443,35 @@ e:hook("ready",function() if t then return;end t=true; -local function o(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; +local function a(a) +local t=e.disco.cache[a]; +if t then +for t in pairs(t.identities)do +local t,o=t:match("^(.*)/(.*)$"); +e:event("disco/service-discovered/"..t,{ +type=o,jid=a; }); end end end e:disco_info(e.host,nil,function() -o(e.host); +a(e.host); end); e:disco_local_services(function(t) -for a,t in ipairs(t)do -o(t.jid); +for o,t in ipairs(t)do +a(t.jid); end e:event("ready"); end); return true; end,50); e:hook("presence-out",function(t) -t:remove_children("c",h); +t:remove_children("c",n); t:reset():add_child(e:caps()):reset(); end,10); +e:hook("disco-info-changed",function() +e:resend_presence(); +end); end end) package.preload['verse.plugins.version']=(function(...) @@ -7254,18 +7487,18 @@ return e; end local o=require"verse"; -local t="jabber:iq:version"; -local function a(t,e) +local a="jabber:iq:version"; +local function i(t,e) t.name=e.name; t.version=e.version; t.platform=e.platform; end function o.plugins.version(e) -e.version={set=a}; -e:hook("iq/"..t,function(a) -if a.attr.type~="get"then return;end -local t=o.reply(a) -:tag("query",{xmlns=t}); +e.version={set=i}; +e:hook("iq/"..a,function(t) +if t.attr.type~="get"then return;end +local t=o.reply(t) +:tag("query",{xmlns=a}); if e.version.name then t:tag("name"):text(tostring(e.version.name)):up(); end @@ -7278,28 +7511,28 @@ e:send(t); return true; end); -function e:query_version(i,a) -a=a or function(e)return self:event("version/response",e);end +function e:query_version(i,t) +t=t or function(e)return self:event("version/response",e);end self:send_iq(o.iq({type="get",to=i}) -:tag("query",{xmlns=t}), +:tag("query",{xmlns=a}), function(o) if o.attr.type=="result"then -local e=o:get_child("query",t); -local t=e and e:get_child_text("name"); +local e=o:get_child("query",a); +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"); -a({ -name=t; +t({ +name=a; version=o; platform=e; }); else -local o,e,t=o:get_error(); -a({ +local e,a,o=o:get_error(); +t({ error=true; -condition=e; -text=t; -type=o; +condition=a; +text=o; +type=e; }); end end); @@ -7319,30 +7552,30 @@ _M=e; return e; end -local a=require"verse"; -local s=require"socket".gettime; -local o=require"util.id".short; -local i="urn:xmpp:ping"; -function a.plugins.ping(e) -function e:ping(t,n) -local h=s(); -local o=o(); -local a=a.iq{id=o,to=t,type="get"}:tag("ping",{xmlns=i}); -e:send_iq(a, +local t=require"verse"; +local o=require"socket".gettime; +local s=require"util.id".short; +local n="urn:xmpp:ping"; +function t.plugins.ping(e) +function e:ping(a,i) +local h=o(); +local s=s(); +local t=t.iq{id=s,to=a,type="get"}:tag("ping",{xmlns=n}); +e:send_iq(t, function(e) if e.attr.type=="error"then -local o,e,a=e:get_error(); +local o,e,t=e:get_error(); if e~="service-unavailable"and e~="feature-not-implemented"then -n(nil,t,{type=o,condition=e,text=a}); +i(nil,a,{type=o,condition=e,text=t}); return; end end -n(s()-h,t); -end); -return o; -end -e:hook("iq/"..i,function(t) -return e:send(a.reply(t)); +i(o()-h,a); +end); +return s; +end +e:hook("iq/"..n,function(a) +return e:send(t.reply(a)); end); return true; end @@ -7385,11 +7618,11 @@ seconds=e or nil; }); else -local o,e,t=e:get_error(); +local o,t,e=e:get_error(); a({ error=true; -condition=e; -text=t; +condition=t; +text=e; type=o; }); end @@ -7430,12 +7663,12 @@ end t(e); else -local o,a,e=a:get_error(); +local e,a,o=a:get_error(); t({ error=true; condition=a; -text=e; -type=o; +text=o; +type=e; }); end end); @@ -7455,38 +7688,38 @@ _M=e; return e; end -local a=require"verse"; -local o="urn:xmpp:blocking"; -function a.plugins.blocking(e) +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 @@ -7513,9 +7746,9 @@ end local a=require"verse"; local e=require"util.timer"; -local n=require"util.id".short; +local o=require"util.id".short; local i="urn:xmpp:jingle:1"; -local r="urn:xmpp:jingle:errors:1"; +local h="urn:xmpp:jingle:errors:1"; local t={}; t.__index=t; local e={}; @@ -7524,11 +7757,11 @@ e:hook("ready",function() e:add_disco_feature(i); end,10); -function e:jingle(o) +function e:jingle(i) return a.eventable(setmetatable(base or{ role="initiator"; -peer=o; -sid=n(); +peer=i; +sid=o(); stream=e; },t)); end @@ -7538,16 +7771,16 @@ end local function u(n) local s=n:get_child("jingle",i); -local h=s.attr.sid; -local o=s.attr.action; -local h=e:event("jingle/"..h,n); -if h==true then +local o=s.attr.sid; +local r=s.attr.action; +local o=e:event("jingle/"..o,n); +if o==true then e:send(a.reply(n)); return true; end -if o~="session-initiate"then +if r~="session-initiate"then local t=a.error_reply(n,"cancel","item-not-found") -:tag("unknown-session",{xmlns=r}):up(); +:tag("unknown-session",{xmlns=h}):up(); e:send(t); return; end @@ -7691,8 +7924,8 @@ self.stream:send_iq(e,function(e) if e.attr.type=="error"then self.state="terminated"; -local e,t,a=e:get_error(); -return self:event("error",{type=e,condition=t,text=a}); +local t,a,e=e:get_error(); +return self:event("error",{type=t,condition=a,text=e}); end end); self.state="pending"; @@ -7758,26 +7991,26 @@ _M=e; return e; end -local i=require"verse"; -local n=require"ltn12"; -local s=package.config:sub(1,1); -local a="urn:xmpp:jingle:apps:file-transfer:4"; -function i.plugins.jingle_ft(t) -t:hook("ready",function() -t:add_disco_feature(a); +local o=require"verse"; +local a=require"ltn12"; +local n=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); end,10); -local o={type="file"}; -function o:generate_accept(t,e) +local i={type="file"}; +function i:generate_accept(t,e) if e and e.save_file then self.jingle:hook("connected",function() -local e=n.sink.file(io.open(e.save_file,"w+")); +local e=a.sink.file(io.open(e.save_file,"w+")); self.jingle:set_sink(e); end); end return t; end -local o={__index=o}; -t:hook("jingle/content/"..a,function(t,e) +local i={__index=i}; +e:hook("jingle/content/"..t,function(t,e) local e=e:get_child("file"); local e={ name=e:get_child_text("name"); @@ -7785,30 +8018,30 @@ desc=e:get_child_text("desc"); date=e:get_child_text("date"); }; -return setmetatable({jingle=t,file=e},o); -end); -t:hook("jingle/describe/file",function(e) -local t; +return setmetatable({jingle=t,file=e},i); +end); +e:hook("jingle/describe/file",function(e) +local a; if e.timestamp then -t=os.date("!%Y-%m-%dT%H:%M:%SZ",e.timestamp); -end -return i.stanza("description",{xmlns=a}) +a=os.date("!%Y-%m-%dT%H:%M:%SZ",e.timestamp); +end +return o.stanza("description",{xmlns=t}) :tag("file") :tag("name"):text(e.filename):up() :tag("size"):text(tostring(e.size)):up() -:tag("date"):text(t):up() +:tag("date"):text(a):up() :tag("desc"):text(e.description):up() :up(); end); -function t:send_file(i,t) -local e,a=io.open(t); -if not e then return e,a;end +function e:send_file(i,t) +local e,o=io.open(t); +if not e then return e,o;end local o=e:seek("end",0); e:seek("set",0); -local a=n.source.file(e); +local a=a.source.file(e); local e=self:jingle(i); e:offer("file",{ -filename=t:match("[^"..s.."]+$"); +filename=t:match("[^"..n.."]+$"); size=o; }); e:hook("connected",function() @@ -7830,49 +8063,49 @@ _M=e; return e; end -local a=require"verse"; +local t=require"verse"; local o="urn:xmpp:jingle:transports:s5b:1"; -local d="http://jabber.org/protocol/bytestreams"; +local l="http://jabber.org/protocol/bytestreams"; local h=require"util.hashes".sha1; -local l=require"util.id".short; +local d=require"util.id".short; local function r(e,s) local function n() e:unhook("connected",n); return true; end -local function i(t) -e:unhook("incoming-raw",i); +local function o(t) +e:unhook("incoming-raw",o); if t:sub(1,2)~="\005\000"then return e:event("error","connection-failure"); end e:event("connected"); return true; end -local function o(t) -e:unhook("incoming-raw",o); -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); +local function i(a) +e:unhook("incoming-raw",i); +if a~="\005\000"then +local t="version-mismatch"; +if a:sub(1,1)=="\005"then +t="authentication-failure"; +end +return e:event("error",t); end e:send(string.char(5,1,0,3,#s)..s.."\0\0"); -e:hook("incoming-raw",i,100); +e:hook("incoming-raw",o,100); return true; end e:hook("connected",n,200); -e:hook("incoming-raw",o,100); +e:hook("incoming-raw",i,100); e:send("\005\001\000"); end -local function s(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; @@ -7894,41 +8127,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() -self.s5b_sid=l(); -local i=a.stanza("transport",{xmlns=o, +local a={}; +function a:generate_initiate() +self.s5b_sid=d(); +local a=t.stanza("transport",{xmlns=o, mode="tcp",sid=self.s5b_sid}); local t=0; -for a,o in pairs(e.proxy65.available_streamhosts)do +for o,i in pairs(e.proxy65.available_streamhosts)do t=t+1; -i:tag("candidate",{jid=a,host=o.host, -port=o.port,cid=a,priority=t,type="proxy"}):up(); +a:tag("candidate",{jid=o,host=i.host, +port=i.port,cid=o,priority=t,type="proxy"}):up(); end e:debug("Have %d proxies",t) -return i; -end -function t:generate_accept(e) -local t={}; -self.s5b_peer_candidates=t; +return a; +end +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; @@ -7937,47 +8170,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 n(e,t) -self.jingle:send_command("transport-info",a.stanza("content",{creator=self.creator,name=self.name}) +local function s(a,e) +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=e.cid})); +:tag("candidate-used",{cid=a.cid})); self.onconnect_callback=i; -self.conn=t; +self.conn=e; end local e=h(self.s5b_sid..self.peer..e.jid,true); -s(n,t,e); +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 n=t:child_with_name("content"); -local i=n:child_with_name("transport"); +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 r(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"}) -:tag("query",{xmlns=d,sid=self.s5b_sid}) +self.jingle.stream:send_iq(t.iq({to=i.jid,type="set"}) +:tag("query",{xmlns=l,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",n.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 @@ -7986,25 +8219,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=h(self.s5b_sid..e.jid..self.peer,true); -s(r,t,e); +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, @@ -8111,19 +8344,19 @@ 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 o,t,a=o:get_error(); +e:event("connection-failed",{conn=e,type=o,condition=t,text=a}); else local o=o.tags[1]:get_child("streamhost-used"); e.streamhost_jid=o.attr.jid; -local h,o; +local o,h; for a,t in ipairs(n or self.proxies)do if t.jid==e.streamhost_jid then -h,o=t.host,t.port; +o,h=t.host,t.port; break; end end -e:connect(h,o); +e:connect(o,h); local function o() e:unhook("connected",o); local t=a.iq{to=e.streamhost_jid,type="set"} @@ -8143,34 +8376,34 @@ return e; end function s(i,e,t,a,o) -local t=r(t..a..o); -local function a() -e:unhook("connected",a); +local i=r(t..a..o); +local function s() +e:unhook("connected",s); return true; end -local function o(t) -e:unhook("incoming-raw",o); +local function n(t) +e:unhook("incoming-raw",n); 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); -if a~="\005\000"then +local function a(o) +e:unhook("incoming-raw",a); +if o~="\005\000"then local t="version-mismatch"; -if a:sub(1,1)=="\005"then +if o: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"); -e:hook("incoming-raw",o,100); +e:send(string.char(5,1,0,3,#i)..i.."\0\0"); +e:hook("incoming-raw",n,100); return true; end -e:hook("connected",a,200); -e:hook("incoming-raw",i,100); +e:hook("connected",s,200); +e:hook("incoming-raw",a,100); e:send("\005\001\000"); end end) @@ -8188,15 +8421,15 @@ end local e=require"verse"; local i=require"util.encodings".base64; -local h=require"util.id".short; +local s=require"util.id".short; local n="urn:xmpp:jingle:transports:ibb:1"; local o="http://jabber.org/protocol/ibb"; assert(i.encode("This is a test.")=="VGhpcyBpcyBhIHRlc3Qu","Base64 encoding failed"); assert(i.decode("VGhpcyBpcyBhIHRlc3Qu")=="This is a test.","Base64 decoding failed"); local a={}; -local t={__index=a}; -local function s(a) -local t=setmetatable({stream=a},t) +local h={__index=a}; +local function r(t) +local t=setmetatable({stream=t},h) t=e.eventable(t); return t; end @@ -8301,7 +8534,7 @@ end,10); local t={}; function t:_setup() -local e=s(self.stream); +local e=r(self.stream); e.sid=self.sid or e.sid; e.stanza=self.stanza or e.stanza; e.block=self.block or e.block; @@ -8310,7 +8543,7 @@ end function t:generate_initiate() print("ibb:generate_initiate() as "..self.role); -local t=h(); +local t=s(); self.sid=t; self.stanza='iq'; self.block=2048; @@ -8375,31 +8608,31 @@ 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 r="http://jabber.org/protocol/pubsub#event"; -local e={}; -local n={__index=e}; +local h="http://jabber.org/protocol/pubsub#owner"; +local a="http://jabber.org/protocol/pubsub#event"; +local t={}; +local s={__index=t}; function i.plugins.pubsub(e) -e.pubsub=setmetatable({stream=e},n); +e.pubsub=setmetatable({stream=e},s); e:hook("message",function(t) -local a=t.attr.from; -for t in t:childtags("event",r)do +local o=t.attr.from; +for t in t:childtags("event",a)do local t=t:get_child("items"); if t then -local o=t.attr.node; +local a=t.attr.node; for t in t:childtags("item")do e:event("pubsub/event",{ -from=a; -node=o; +from=o; +node=a; item=t; }); end for t in t:childtags("retract")do e:event("pubsub/retraction",{ -from=a; -node=o; +from=o; +node=a; item=t; }); end @@ -8408,53 +8641,53 @@ end); return true; end -function e:create(a,e,t) -return self:service(a):node(e):create(nil,t); -end -function e:subscribe(o,t,a,e) -return self:service(o):node(t):subscribe(a,nil,e); -end -function e:publish(e,t,o,a,i) -return self:service(e):node(t):publish(o,nil,a,i); +function t:create(a,t,e) +return self:service(a):node(t):create(nil,e); +end +function t:subscribe(e,t,o,a) +return self:service(e):node(t):subscribe(o,nil,a); +end +function t:publish(i,o,t,a,e) +return self:service(i):node(o):publish(t,nil,a,e); end local a={}; -local t={__index=a}; -function e:service(e) -return setmetatable({stream=self.stream,service=e},t) -end -local function t(d,r,e,n,h,s,t,a) -local e=i.iq{type=d or"get",to=r} -:tag("pubsub",{xmlns=e or o}) -local o={node=h,jid=s}; -if a then -for t,e in pairs(a)do +local r={__index=a}; +function t:service(e) +return setmetatable({stream=self.stream,service=e},r) +end +local function t(t,r,s,a,d,h,e,n) +local t=i.iq{type=t or"get",to=r} +:tag("pubsub",{xmlns=s or o}) +local o={node=d,jid=h}; +if n then +for t,e in pairs(n)do o[t]=e; end end -if n then e:tag(n,o);end -if t then -e:tag("item",{id=t~=true and t or nil}); -end -return e; -end -function a:subscriptions(a) +if a then t:tag(a,o);end +if e then +t:tag("item",{id=e~=true and e or nil}); +end +return t; +end +function a:subscriptions(e) self.stream:send_iq(t(nil,self.service,nil,"subscriptions") -,a and function(e) -if e.attr.type=="result"then -local e=e:get_child("pubsub",o); -local e=e and e:get_child("subscriptions"); -local o={}; -if e then -for e in e:childtags("subscription")do +,e and function(a) +if a.attr.type=="result"then +local t=a:get_child("pubsub",o); +local t=t and t:get_child("subscriptions"); +local a={}; +if t then +for e in t:childtags("subscription")do local t=self:node(e.attr.node) t.subscription=e; t.subscribed_jid=e.attr.jid; -h(o,t); -end -end -a(o); -else -a(false,e:get_error()); +n(a,t); +end +end +e(a); +else +e(false,a:get_error()); end end or nil); end @@ -8466,10 +8699,10 @@ local e=e and e:get_child("affiliations")or{}; local o={}; if e then -for e in e:childtags("affiliation")do -local t=self:node(e.attr.node) -t.affiliation=e; -h(o,t); +for t in e:childtags("affiliation")do +local e=self:node(t.attr.node) +e.affiliation=t; +n(o,e); end end a(o); @@ -8493,7 +8726,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 @@ -8518,11 +8751,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) @@ -8531,21 +8764,21 @@ 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) +function e:publish(e,a,o,i) if a~=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); -end -function e:subscribe(e,a,o) +self.stream:send_iq(t("set",self.service,nil,"publish",self.node,nil,e or true) +:add_child(o) +,i); +end +function e:subscribe(e,o,a) e=e or self.stream.jid; -if a~=nil then +if o~=nil then error("Subscription configuration is not implemented yet."); end self.stream:send_iq(t("set",self.service,nil,"subscribe",self.node,e) -,o); +,a); end function e:subscription(e) error("Not implemented yet."); @@ -8568,9 +8801,9 @@ self.stream:disco_items(self.service,self.node,e); end end -function e:item(e,a) -self.stream:send_iq(t("get",self.service,nil,"items",self.node,nil,e) -,a); +function e:item(a,e) +self.stream:send_iq(t("get",self.service,nil,"items",self.node,nil,a) +,e); end function e:retract(o,e,a) if type(e)=="function"then @@ -8595,7 +8828,7 @@ t( "set", self.service, -s, +h, "purge", self.node, nil, @@ -8605,10 +8838,10 @@ a ); end -function e:delete(e,a) -assert(not e,"Not implemented yet."); -self.stream:send_iq(t("set",self.service,s,"delete",self.node) -,a); +function e:delete(a,e) +assert(not a,"Not implemented yet."); +self.stream:send_iq(t("set",self.service,h,"delete",self.node) +,e); end end) package.preload['verse.plugins.pep']=(function(...) @@ -8633,12 +8866,12 @@ e:hook("pubsub/event",function(t) return e:event("pep/"..t.node,{from=t.from,id=t.item.attr.id,item=t.item.tags[1]}); end); -function e:hook_pep(t,i,o) +function e:hook_pep(t,o,i) local a=e.events._handlers["pep/"..t]; if not(a)or#a==0 then e:add_disco_feature(t.."+notify"); end -e:hook("pep/"..t,i,o); +e:hook("pep/"..t,o,i); end function e:unhook_pep(t,a) e:unhook("pep/"..t,a); @@ -8685,14 +8918,14 @@ return o(t); end); end -function e:execute_command(o,i,t) +function e:execute_command(i,o,t) local e=setmetatable({ -stream=e,jid=o, -command=i,callback=t +stream=e,jid=i, +command=o,callback=t },a); return e:execute(); end -local function s(t,e) +local function r(t,e) if not(e)or e=="user"then return true;end if type(e)=="function"then return e(t); @@ -8703,12 +8936,12 @@ e:add_disco_item({jid=e.jid,node=a,name=o},t); return i[a]; end -local function h(t) +local function s(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 +if not r(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") :tag("note",{type="error"}):text("You don't have permission to execute this command"))); @@ -8717,10 +8950,10 @@ return n.handle_cmd(a,{send=function(t)return e:send(t)end},t); 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 @@ -8744,15 +8977,15 @@ self:_process_response(e); end); end -function a:next(e) -local t=o.iq({to=self.jid,type="set"}) +function a:next(a) +local e=o.iq({to=self.jid,type="set"}) :tag("command",{ xmlns=t, node=self.command, sessionid=self.sessionid }); -if e then t:add_child(e);end -self.stream:send_iq(t,function(e) +if a then e:add_child(a);end +self.stream:send_iq(e,function(e) self:_process_response(e); end); end @@ -8814,29 +9047,29 @@ _M=e; return e; end -local t=require"verse"; -local a="jabber:iq:private"; -function t.plugins.private(o) -function o:private_set(i,o,e,n) -local t=t.iq({type="set"}) -:tag("query",{xmlns=a}); +local a=require"verse"; +local t="jabber:iq:private"; +function a.plugins.private(n) +function n:private_set(o,i,e,n) +local t=a.iq({type="set"}) +:tag("query",{xmlns=t}); if e then -if e.name==i and e.attr and e.attr.xmlns==o then +if e.name==o and e.attr and e.attr.xmlns==i then t:add_child(e); else -t:tag(i,{xmlns=o}) +t:tag(o,{xmlns=i}) :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}) +function n:private_get(e,o,i) +self:send_iq(a.iq({type="get"}) +:tag("query",{xmlns=t}) :tag(e,{xmlns=o}), -function(t) -if t.attr.type=="result"then -local t=t:get_child("query",a); +function(a) +if a.attr.type=="result"then +local t=a:get_child("query",t); local e=t:get_child(e,o); i(e); end @@ -8857,36 +9090,36 @@ return e; end local i=require"verse"; -local l=require"util.jid".bare; +local d=require"util.jid".bare; local a="jabber:iq:roster"; -local o="urn:xmpp:features:rosterver"; -local n=table.insert; +local n="urn:xmpp:features:rosterver"; +local o=table.insert; function i.plugins.roster(t) -local h=false; +local s=false; local e={ items={}; ver=""; }; t.roster=e; t:hook("stream-features",function(e) -if e:get_child("ver",o)then -h=true; -end -end); -local function s(e) -local t=i.stanza("item",{xmlns=a}); -for a,e in pairs(e)do +if e:get_child("ver",n)then +s=true; +end +end); +local function h(t) +local e=i.stanza("item",{xmlns=a}); +for a,t in pairs(t)do if a~="groups"then -t.attr[a]=e; -else -for a=1,#e do -t:tag("group"):text(e[a]):up(); -end -end -end -return t; -end -local function d(a) +e.attr[a]=t; +else +for a=1,#t do +e:tag("group"):text(t[a]):up(); +end +end +end +return e; +end +local function r(a) local e={}; local t={}; e.groups=t; @@ -8896,7 +9129,7 @@ end end for e in a:childtags("group")do -n(t,e:get_text()) +o(t,e:get_text()) end return e; end @@ -8909,11 +9142,11 @@ items=e.items, }; end -function e:add_contact(h,o,n,e) -local o={jid=h,name=o,groups=n}; +function e:add_contact(o,n,s,e) +local o={jid=o,name=n,groups=s}; local a=i.iq({type="set"}) :tag("query",{xmlns=a}) -:add_child(s(o)); +:add_child(h(o)); t:send_iq(a,function(t) if not e then return end if t.attr.type=="result"then @@ -8925,11 +9158,11 @@ end function e:delete_contact(o,n) o=(type(o)=="table"and o.jid)or o; -local h={jid=o,subscription="remove"} +local s={jid=o,subscription="remove"} if not e.items[o]then return false,"item-not-found";end t:send_iq(i.iq({type="set"}) :tag("query",{xmlns=a}) -:add_child(s(h)), +:add_child(h(s)), function(e) if not n then return end if e.attr.type=="result"then @@ -8939,55 +9172,55 @@ end end); end -local function r(t) -local t=d(t); +local function h(t) +local t=r(t); e.items[t.jid]=t; end -local function d(t) +local function r(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=h and e.ver or nil}), -function(t) -if t.attr.type=="result"then -local t=t:get_child("query",a); +function e:fetch(n) +t:send_iq(i.iq({type="get"}):tag("query",{xmlns=a,ver=s and e.ver or nil}), +function(o) +if o.attr.type=="result"then +local t=o:get_child("query",a); if t then e.items={}; for t in t:childtags("item")do -r(t) +h(t) end e.ver=t.attr.ver or""; end -o(e); -else -o(nil,t); -end -end); -end -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 s=o:get_child("query",a); -local n=s and s:get_child("item"); -if n then -local o,a; -local i=n.attr.jid; -if n.attr.subscription=="remove"then -o="removed" -a=d(i); -else -o=e.items[i]and"changed"or"added"; -r(n) -a=e.items[i]; +n(e); +else +n(nil,o); +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 a=s and s:get_child("item"); +if a then +local n,o; +local i=a.attr.jid; +if a.attr.subscription=="remove"then +n="removed" +o=r(i); +else +n=e.items[i]and"changed"or"added"; +h(a) +o=e.items[i]; end e.ver=s.attr.ver; -if a then -t:event("roster/item-"..o,a); -end -end -t:send(i.reply(o)) +if o then +t:event("roster/item-"..n,o); +end +end +t:send(i.reply(n)) return true; end end); @@ -9067,17 +9300,17 @@ end if t and t.opts.source and e.attr.to~=t.opts.source then return end if t then -local o=select(3,n.split(e.attr.from)); +local i=select(3,n.split(e.attr.from)); local n=e:get_child_text("body"); -local i=e:get_child("delay",h); +local o=e:get_child("delay",h); local a={ room_jid=a; room=t; -sender=t.occupants[o]; -nick=o; +sender=t.occupants[i]; +nick=i; body=n; stanza=e; -delay=(i and i.attr.stamp); +delay=(o and o.attr.stamp); }; local t=t:event(e.name,a); return t or(e.name=="message")or nil; @@ -9186,31 +9419,31 @@ function a:set_subject(e) self:send(i.message():tag("subject"):text(e)); end -function a:leave(t) +function a:leave(e) self.stream:event("groupchat/leaving",self); -local e=i.presence({type="unavailable"}); -if t then -e:tag("status"):text(t); -end -self:send(e); -end -function a:admin_set(e,t,a,o) +local t=i.presence({type="unavailable"}); +if e then +t:tag("status"):text(e); +end +self:send(t); +end +function a:admin_set(t,o,a,e) self:send(i.iq({type="set"}) :query(s.."#admin") -:tag("item",{nick=e,[t]=a}) -:tag("reason"):text(o or"")); -end -function a:set_role(a,e,t) -self:admin_set(a,"role",e,t); -end -function a:set_affiliation(t,a,e) -self:admin_set(t,"affiliation",a,e); +:tag("item",{nick=t,[o]=a}) +: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(e,t,a) +self:admin_set(e,"affiliation",t,a); end function a:kick(t,e) self:set_role(t,"none",e); end -function a:ban(e,t) -self:set_affiliation(e,"outcast",t); +function a:ban(t,e) +self:set_affiliation(t,"outcast",e); end end) package.preload['verse.plugins.vcard']=(function(...) @@ -9270,9 +9503,9 @@ _M=e; return e; end -local n=require"verse"; -local i="vcard-temp:x:update"; -local r=require("util.hashes").sha1; +local i=require"verse"; +local n="vcard-temp:x:update"; +local s=require("util.hashes").sha1; local e,t=pcall(function() local e=require("util.encodings").base64.decode; assert(e("SGVsbG8=")=="Hello") @@ -9285,11 +9518,11 @@ end end local h=t; -function n.plugins.vcard_update(e) +function i.plugins.vcard_update(e) e:add_plugin("vcard"); e:add_plugin("presence"); local t; -local function s(a) +local function r(a) local o; for e=1,#a do if a[e].name=="PHOTO"then @@ -9298,8 +9531,8 @@ end end if o then -local a=r(h(o),true); -t=n.stanza("x",{xmlns=i}) +local a=s(h(o),true); +t=i.stanza("x",{xmlns=n}) :tag("photo"):text(a); e:resend_presence() else @@ -9312,14 +9545,14 @@ a=true; e:get_vcard(nil,function(t) if t then -s(t) +r(t) end e:event("ready"); end); return true; end,3); e:hook("presence-out",function(e) -if t and not e:get_child("x",i)then +if t and not e:get_child("x",n)then e:add_child(t); end end,10); @@ -9337,19 +9570,19 @@ _M=e; return e; end -local o=require"verse"; -local a="urn:xmpp:carbons:2"; -local n="urn:xmpp:forward:0"; -local h=os.time; -local s=require"util.datetime".parse; -local r=require"util.jid".bare; -function o.plugins.carbons(e) +local a=require"verse"; +local o="urn:xmpp:carbons:2"; +local r="urn:xmpp:forward:0"; +local s=os.time; +local h=require"util.datetime".parse; +local n=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 @@ -9361,8 +9594,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 @@ -9373,24 +9606,24 @@ end end or nil); end -local i; +local a; e:hook("bind-success",function() -i=r(e.jid); -end); -e:hook("message",function(o) -local t=o:get_child(nil,a); -if o.attr.from==i and t then +a=n(e.jid); +end); +e:hook("message",function(i) +local t=i:get_child(nil,o); +if i.attr.from==a and t then local o=t.name; -local t=t:get_child("forwarded",n); +local t=t:get_child("forwarded",r); 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 h(t); if a then return e:event("carbon",{ dir=o, stanza=a, -timestamp=t or h(), +timestamp=t or s(), }); end end @@ -9412,71 +9645,71 @@ local a=require"verse"; local t=require"util.stanza"; local e="urn:xmpp:mam:2" -local c="urn:xmpp:forward:0"; -local u="urn:xmpp:delay"; -local i=require"util.id".short; -local m=require"util.datetime".parse; -local r=require"util.datetime".datetime; +local l="urn:xmpp:forward:0"; +local d="urn:xmpp:delay"; +local r=require"util.id".short; +local c=require"util.datetime".parse; +local s=require"util.datetime".datetime; local o=require"util.dataforms".new; -local h=require"util.rsm"; -local d={}; -local l=o{ +local n=require"util.rsm"; +local u={}; +local m=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(o) -function o:query_archive(o,a,n) -local i=i(); -local o=t.iq{id=i,type="set",to=o} -:tag("query",{xmlns=e,queryid=i}); -local t,s=tonumber(a["start"]),tonumber(a["end"]); -a["start"]=t and r(t); -a["end"]=s and r(s); -o:add_child(l:form(a,"submit")); -o:add_child(h.generate(a)); +function a.plugins.archive(i) +function i:query_archive(i,a,h) +local o=r(); +local i=t.iq{id=o,type="set",to=i} +:tag("query",{xmlns=e,queryid=o}); +local t,r=tonumber(a["start"]),tonumber(a["end"]); +a["start"]=t and s(t); +a["end"]=r and s(r); +i:add_child(m:form(a,"submit")); +i:add_child(n.generate(a)); local t={}; local function s(a) local e=a:get_child("result",e); -if e and e.attr.queryid==i then -local a=e:get_child("forwarded",c); +if e and e.attr.queryid==o then +local a=e:get_child("forwarded",l); local i=e.attr.id; -local e=a:get_child("delay",u); -local o=e and m(e.attr.stamp)or nil; +local e=a:get_child("delay",d); +local o=e and c(e.attr.stamp)or nil; local e=a:get_child("message","jabber:client") t[#t+1]={id=i,stamp=o,message=e}; return true end end self:hook("message",s,1); -self:send_iq(o,function(a) +self:send_iq(i,function(a) self:unhook("message",s); if a.attr.type=="error"then self:warn(table.concat({a:get_error()}," ")) -n(false,a:get_error()) +h(false,a:get_error()) return true; end local e=a:get_child("fin",e) if e then t.complete=e.attr.complete=="true"or e.attr.complete=="1"; -local e=h.get(e); -for e,a in pairs(e or d)do t[e]=a;end -end -n(t); +local e=n.get(e); +for a,e in pairs(e or u)do t[a]=e;end +end +h(t); return true end); end -local i={ +local n={ always=true,[true]="always", never=false,[false]="never", roster="roster", } -local function n(t) +local function h(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 @@ -9498,28 +9731,28 @@ local a a,o[false]=o[false],nil; if a~=nil then -a=i[a]; -end -local i=t.stanza("prefs",{xmlns=e,default=a}) -local a=t.stanza("always"); -local e=t.stanza("never"); -for t,o in pairs(o)do -(o and a or e):tag("jid"):text(t):up(); -end -return i:add_child(a):add_child(e); -end -function o:archive_prefs_get(a) +a=n[a]; +end +local a=t.stanza("prefs",{xmlns=e,default=a}) +local e=t.stanza("always"); +local t=t.stanza("never"); +for o,a in pairs(o)do +(a and e or t):tag("jid"):text(o):up(); +end +return a:add_child(e):add_child(t); +end +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=n(e.tags[1]); +local t=h(e.tags[1]); a(t,e); else a(nil,e); end end); end -function o:archive_prefs_set(e,a) +function i:archive_prefs_set(e,a) self:send_iq(t.iq{type="set"}:add_child(s(e)),a); end end @@ -9545,8 +9778,8 @@ t={uri=t}; end local a=a.stanza("page",{xmlns=o}) -for e,t in pairs(t)do -a:tag(e):text(t):up(); +for t,e in pairs(t)do +a:tag(t):text(e):up(); end return e:publish_pep(a,i); end @@ -9574,13 +9807,13 @@ _M=e; return e; end -local n,t=string.format,string.char; -local r,h=pairs,ipairs; -local i,o=table.insert,table.concat; +local i,t=string.format,string.char; +local h,r=pairs,ipairs; +local o,s=table.insert,table.concat; local e={}; for a=0,255 do local t=t(a); -local a=n("%%%02x",a); +local a=i("%%%02x",a); e[t]=a; e[a]=t; e[a:upper()]=t; @@ -9594,35 +9827,35 @@ local function e(e) return e and(n(e):gsub("%%20","+")); end -local function s(a) -local t={}; -if a[1]then -for o,a in h(a)do -i(t,e(a.name).."="..e(a.value)); -end -else -for a,o in r(a)do -i(t,e(a).."="..e(o)); -end -end -return o(t,"&"); -end -local function h(e) +local function d(t) +local a={}; +if t[1]then +for i,t in r(t)do +o(a,e(t.name).."="..e(t.value)); +end +else +for i,t in h(t)do +o(a,e(i).."="..e(t)); +end +end +return s(a,"&"); +end +local function s(e) if not e:match("=")then return a(e);end -local o={}; -for t,e in e:gmatch("([^=&]*)=([^&]*)")do -t,e=t:gsub("%+","%%20"),e:gsub("%+","%%20"); -t,e=a(t),a(e); -i(o,{name=t,value=e}); -o[t]=e; -end -return o; -end -local function i(e,t) +local i={}; +for e,t in e:gmatch("([^=&]*)=([^&]*)")do +e,t=e:gsub("%+","%%20"),t:gsub("%+","%%20"); +e,t=a(e),a(t); +o(i,{name=e,value=t}); +i[e]=t; +end +return i; +end +local function o(e,t) e=","..e:gsub("[ \t]",""):lower()..","; return e:find(","..t:lower()..",",1,true)~=nil; end -local function o(e,t) +local function t(e,t) if t then if e:sub(-1,-1)~="/"then e=e.."/";end else @@ -9633,9 +9866,9 @@ end return{ urlencode=n,urldecode=a; -formencode=s,formdecode=h; -contains_token=i; -normalize_path=o; +formencode=d,formdecode=s; +contains_token=o; +normalize_path=t; }; end) package.preload['net.http.parser']=(function(...) @@ -9650,12 +9883,12 @@ _M=e; return e; end -local u=tonumber; -local g=assert; -local z=require"socket.url".parse; +local l=tonumber; +local b=assert; +local q=require"socket.url".parse; local t=require"util.http".urldecode; -local j=require"util.dbuffer"; -local function x(e) +local g=require"util.dbuffer"; +local function j(e) e=t((e:gsub("//+","/"))); if e:sub(1,1)~="/"then e="/"..e; @@ -9673,129 +9906,129 @@ end return e; end -local q={}; -function q.new(l,s,e,h) +local k={}; +function k.new(c,n,e,r) local f=true; -if not e or e=="server"then f=false;else g(e=="client","Invalid parser type");end -local v=u(h and h().body_size_limit)or 10*1024*1024; -local n=u(h and h().head_size_limit)or 10*1024; -local k=u(h and h().buffer_size_limit)or v*2; -local a=j.new(k); +if not e or e=="server"then f=false;else b(e=="client","Invalid parser type");end +local w=l(r and r().body_size_limit)or 10*1024*1024; +local s=l(r and r().head_size_limit)or 10*1024; +local k=l(r and r().buffer_size_limit)or w*2; +local a=g.new(k); local d; -local r=nil; +local h=nil; local e; local t; -local w; +local y; local o; return{ -feed=function(c,i) +feed=function(u,i) if o then return nil,"parse has failed";end if not i then -if r and f and not t then +if h and f and not t then a:collapse(); e.body=a:read_chunk()or""; e.partial=nil; -l(e); -r=nil; +c(e); +h=nil; elseif a:length()~=0 then -o=true;return s("unexpected-eof"); +o=true;return n("unexpected-eof"); end return; end -if not a:write(i)then o=true;return s("max-buffer-size-exceeded");end +if not a:write(i)then o=true;return n("max-buffer-size-exceeded");end while a:length()>0 do -if r==nil then -local b=a:sub(1,n):find("\r\n\r\n",nil,true); +if h==nil then +local b=a:sub(1,s):find("\r\n\r\n",nil,true); if not b then return;end -local p,c,m,i,g; -local y; -local n={}; +local p,u,m,s,x; +local v; +local i={}; for t in a:read(b+3):gmatch("([^\r\n]+)\r\n")do -if y then +if v then local e,t=t:match("^([^%s:]+): *(.*)$"); -if not e then o=true;return s("invalid-header-line");end +if not e then o=true;return n("invalid-header-line");end e=e:lower(); -n[e]=n[e]and n[e]..","..t or t; -else -y=t; +i[e]=i[e]and i[e]..","..t or t; +else +v=t; if f then -m,i,g=t:match("^HTTP/(1%.[01]) (%d%d%d) (.*)$"); -i=u(i); -if not i then o=true;return s("invalid-status-line");end -w=not -((h and h().method=="HEAD") -or(i==204 or i==304 or i==301) -or(i>=100 and i<200)); -else -p,c,m=t:match("^(%w+) (%S+) HTTP/(1%.[01])$"); -if not p then o=true;return s("invalid-status-line");end -end -end -end -if not y then o=true;return s("invalid-status-line");end -d=w and n["transfer-encoding"]=="chunked"; -t=u(n["content-length"]); +m,s,x=t:match("^HTTP/(1%.[01]) (%d%d%d) (.*)$"); +s=l(s); +if not s then o=true;return n("invalid-status-line");end +y=not +((r and r().method=="HEAD") +or(s==204 or s==304 or s==301) +or(s>=100 and s<200)); +else +p,u,m=t:match("^(%w+) (%S+) HTTP/(1%.[01])$"); +if not p then o=true;return n("invalid-status-line");end +end +end +end +if not v then o=true;return n("invalid-status-line");end +d=y and i["transfer-encoding"]=="chunked"; +t=l(i["content-length"]); if f then -if not w then t=0;end +if not y then t=0;end e={ -code=i; +code=s; httpversion=m; -headers=n; +headers=i; body=false; body_length=t; chunked=d; partial=true; responseversion=m; -responseheaders=n; +responseheaders=i; }; else local a; -if c:byte()==47 then -local t,e=c:match("([^?]*).?(.*)"); +if u:byte()==47 then +local t,e=u:match("([^?]*).?(.*)"); if e==""then e=nil;end a={path=t,query=e}; else -a=z(c); -if not(a and a.path)then o=true;return s("invalid-url");end -end -c=x(a.path); -n.host=a.host or n.host; +a=q(u); +if not(a and a.path)then o=true;return n("invalid-url");end +end +u=j(a.path); +i.host=a.host or i.host; t=t or 0; e={ method=p; url=a; -path=c; +path=u; httpversion=m; -headers=n; +headers=i; body=false; body_sink=nil; chunked=d; partial=true; }; end -if not t or t>v then -l(e); -if not e.body_sink and(t and t>v)then +if not t or t>w then +c(e); +if not e.body_sink and(t and t>w)then o=true; -return s("content-length-limit-exceeded"); +return n("content-length-limit-exceeded"); end end if d and not e.body_sink then -l(e); +c(e); if not e.body_sink then -e.body_buffer=j.new(k); -end -end -r=true; -end -if r then +e.body_buffer=g.new(k); +end +end +h=true; +end +if h then if d then -local n=a:sub(1,512); -local t,i=n:match("^(%x+)[^\r\n]*\r\n()"); +local s=a:sub(1,512); +local t,i=s:match("^(%x+)[^\r\n]*\r\n()"); if not t then return;end -t=t and u(t,16); -if not t then o=true;return s("invalid-chunk-size");end -if t==0 and n:find("\r\n\r\n",i-2,true)then +t=t and l(t,16); +if not t then o=true;return n("invalid-chunk-size");end +if t==0 and s:find("\r\n\r\n",i-2,true)then local t=e.body_buffer; if t then e.body_buffer=nil; @@ -9806,9 +10039,9 @@ local t=a:read_chunk(); t=t:gsub("^.-\r\n\r\n",""); a:write(t); -r,d=nil,nil; +h,d=nil,nil; e.partial=nil; -l(e); +c(e); elseif a:length()-i-1>=t then a:discard(i-1); (e.body_sink or e.body_buffer):write(a:read(t)); @@ -9826,20 +10059,20 @@ i=a:read_chunk(t); else o=true; -return s("body-sink-write-failure"); +return n("body-sink-write-failure"); end end if t==0 then -r=nil; +h=nil; e.partial=nil; -l(e); +c(e); end elseif not t or a:length()>=t then -g(not d) +b(not d) e.body=t and a:read(t)or a:read_chunk()or""; -r=nil; +h=nil; e.partial=nil; -l(e); +c(e); else break; end @@ -9850,7 +10083,7 @@ end; }; end -return q; +return k; end) package.preload['net.http']=(function(...) local _ENV=_ENV; @@ -9864,35 +10097,35 @@ _M=e; return e; end -local O=require"util.encodings".base64.encode; -local A=require"socket.url" -local E=require"net.http.parser".new; +local z=require"util.encodings".base64.encode; +local T=require"socket.url" +local _=require"net.http.parser".new; local d=require"util.http"; -local T=require"util.events"; -local _=require"util.x509".verify_identity; -local k=require"util.promise"; -local g=require"net.http.errors"; -local b=require"net.resolvers.basic"; -local v=require"net.connect".connect; -local y=pcall(require,"ssl"); -local s,f=table.insert,table.concat; +local O=require"util.events"; +local A=require"util.x509".verify_identity; +local E=require"util.promise"; +local j=require"net.http.errors"; +local x=require"net.resolvers.basic"; +local q=require"net.connect".connect; +local v=pcall(require,"ssl"); +local s,p=table.insert,table.concat; local l=pairs; -local p,c,t= +local y,c,t= tonumber,tostring,debug.traceback; -local q=os.time; -local z=require"util.xpcall".xpcall; -local w=error +local w=os.time; +local b=require"util.xpcall".xpcall; +local f=error local o=require"util.logger".init("http"); local _ENV=nil; local a={}; -local function x(e)return(c(e):match("%x+$"));end -local i={default_port=80,default_mode="*a"}; -local function j(e)o("error","Traceback[http]: %s",t(c(e),2));return e;end -local function h(e,t,...) +local function g(e)return(c(e):match("%x+$"));end +local n={default_port=80,default_mode="*a"}; +local function k(e)o("error","Traceback[http]: %s",t(c(e),2));return e;end +local function m(e,t,...) if not t then o("error","Request '%s': error in callback: %s",e.id,(...)); if not e.suppress_errors then -w(...); +f(...); end end return...; @@ -9904,7 +10137,7 @@ t:close() end end -local function m(e,t) +local function u(e,t) if e.callback then e.callback(t or"cancelled",0,e); e.callback=nil; @@ -9913,7 +10146,7 @@ r(e); end end -local function u(e,n,t) +local function h(e,n,a) if not e.parser then local function i(t) if e.callback then @@ -9923,7 +10156,7 @@ r(e); end if not n then -i(t); +i(a); return; end local a; @@ -9952,26 +10185,26 @@ local function t() return e; end -e.parser=E(n,i,"client",t); +e.parser=_(n,i,"client",t); end e.parser:feed(n); end -function i.onconnect(t) +function n.onconnect(t) local e=a[t]; e.write=function(...)return e.conn:write(...);end local r=e.callback; -e.callback=function(i,a,n,s) +e.callback=function(n,a,i,s) do -local t={http=e.http,url=e.url,request=e,response=n,content=i,code=a,callback=e.callback}; +local t={http=e.http,url=e.url,request=e,response=i,content=n,code=a,callback=e.callback}; e.http.events.fire_event("response",t); -i,a,n=t.content,t.code,t.response; +n,a,i=t.content,t.code,t.response; end o("debug","Request '%s': Calling callback, status %s",e.id,a or"---"); -return h(e.id,z(r,j,i,a,n,s)); -end -e.reader=u; +return m(e.id,b(r,k,n,a,i,s)); +end +e.reader=h; e.state="status"; -e.cancel=m; +e.cancel=u; a[e.conn]=e; if not e.insecure and t:ssl()then local a=t:socket(); @@ -9983,7 +10216,7 @@ return; end local a=a.getpeercertificate and a:getpeercertificate(); -if not a or not _(e.host,false,a)then +if not a or not A(e.host,false,a)then e.callback("certificate-verify-failed",0,e); e.callback=nil; t:close(); @@ -9998,142 +10231,142 @@ s(a,e..": "..t.."\r\n"); end s(a,"\r\n") -t:write(f(a)); +t:write(p(a)); if e.body then t:write(e.body); end end -function i.onincoming(t,i) -local e=a[t]; +function n.onincoming(i,t) +local e=a[i]; if not e then -o("warn","Received response from connection %s with no request attached!",t); +o("warn","Received response from connection %s with no request attached!",i); return; end -if i and e.reader then -e:reader(i); -end -end -function i.ondisconnect(t,o) +if t and e.reader then +e:reader(t); +end +end +function n.ondisconnect(t,o) local e=a[t]; if e and e.conn then e:reader(nil,o or"closed"); end a[t]=nil; end -function i.onattach(e,t) +function n.onattach(e,t) a[e]=t; t.conn=e; end -function i.ondetach(e) +function n.ondetach(e) a[e]=nil; end -function i.onfail(e,t) +function n.onfail(e,t) e.http.events.fire_event("request-connection-error",{http=e.http,request=e,url=e.url,err=t}); e.callback(t or"connection failed",0,e); end -local function f(a,s,t,n) -local e=A.parse(s); +local function m(a,h,t,i) +local e=T.parse(h); if not(e and e.host)then -n("invalid-url",0,e); +i("invalid-url",0,e); return nil,"invalid-url"; end -e.url=s; +e.url=h; e.http=a; -e.time=q(); +e.time=w(); if not e.path then e.path="/"; end -e.id=t and t.id or x(e); +e.id=t and t.id or g(e); do -local o={http=a,url=s,request=e,options=t,callback=n}; +local o={http=a,url=h,request=e,options=t,callback=i}; local a=a.events.fire_event("pre-request",o); if a then return a; end -e,s,t,e.callback=o.request,o.url,o.options,o.callback; -end -local d,h,u; -local m,n=e.host,e.port; +e,h,t,e.callback=o.request,o.url,o.options,o.callback; +end +local u,s,d; +local m,i=e.host,e.port; local r=m; -if(n=="80"and e.scheme=="http") -or(n=="443"and e.scheme=="https")then -n=nil; -elseif n then -r=r..":"..n; -end -h={ +if(i=="80"and e.scheme=="http") +or(i=="443"and e.scheme=="https")then +i=nil; +elseif i then +r=r..":"..i; +end +s={ ["Host"]=r; ["User-Agent"]="Prosody XMPP Server"; }; if e.userinfo then -h["Authorization"]="Basic "..O(e.userinfo); +s["Authorization"]="Basic "..z(e.userinfo); end if t then e.onlystatus=t.onlystatus; -u=t.body; -if u then -d="POST"; -h["Content-Length"]=c(#u); -h["Content-Type"]="application/x-www-form-urlencoded"; -end -if t.method then d=t.method;end +d=t.body; +if d then +u="POST"; +s["Content-Length"]=c(#d); +s["Content-Type"]="application/x-www-form-urlencoded"; +end +if t.method then u=t.method;end if t.headers then -for t,e in l(t.headers)do -h[t]=e; +for e,t in l(t.headers)do +s[e]=t; end end e.insecure=t.insecure; e.suppress_errors=t.suppress_errors; e.streaming_handler=t.streaming_handler; end -o("debug","Making %s %s request '%s' to %s",e.scheme:upper(),d or"GET",e.id,(t and t.suppress_url and r)or s); -e.method,e.headers,e.body=d,h,u; +o("debug","Making %s %s request '%s' to %s",e.scheme:upper(),u or"GET",e.id,(t and t.suppress_url and r)or h); +e.method,e.headers,e.body=u,s,d; local o=e.scheme=="https"; -if o and not y then -w("SSL not available, unable to contact https URL"); -end -local r=n and p(n)or(o and 443 or 80); -local n=a.options and a.options.use_dane; -local h=false; +if o and not v then +f("SSL not available, unable to contact https URL"); +end +local r=i and y(i)or(o and 443 or 80); +local s=a.options and a.options.use_dane; +local i=false; if o then -h=t and t.sslctx or a.options and a.options.sslctx; +i=t and t.sslctx or a.options and a.options.sslctx; if t and t.use_dane~=nil then -n=t.use_dane; -end -end -local t=b.new(m,r,"tcp",{servername=e.host;use_dane=n}); -v(t,i,{sslctx=h},e); -a.events.fire_event("request",{http=a,request=e,url=s}); -return e; -end -local function e(t) +s=t.use_dane; +end +end +local t=x.new(m,r,"tcp",{servername=e.host;use_dane=s}); +q(t,n,{sslctx=i},e); +a.events.fire_event("request",{http=a,request=e,url=h}); +return e; +end +local function e(a) local e={ -options=t; -request=function(o,a,t,e) -if e~=nil then -return f(o,a,t,e); -else -return k.new(function(i,n) -f(o,a,t,function(t,a,e,o) +options=a; +request=function(a,t,e,o) +if o~=nil then +return m(a,t,e,o); +else +return E.new(function(n,o) +m(a,t,e,function(i,a,e,t) if a==0 then -n(g.new(t,{request=e})); -else -e.request=o; -i(e); +o(j.new(i,{request=e})); +else +e.request=t; +n(e); end end); end); end end; -new=t and function(o) -local a={}; -for e,t in l(t)do a[e]=t;end +new=a and function(o) +local t={}; +for e,a in l(a)do t[e]=a;end if o then -for t,e in l(o)do a[t]=e;end -end -return e(a); +for a,e in l(o)do t[a]=e;end +end +return e(t); end or e; -events=T.new(); +events=O.new(); }; return e; end @@ -10142,8 +10375,8 @@ suppress_errors=true; }); return{ -request=function(e,a,o) -return t:request(e,a,o); +request=function(o,a,e) +return t:request(o,a,e); end; default=t; new=e; @@ -10172,16 +10405,16 @@ end local o=require"util.encodings".stringprep.nameprep; local r=require"util.encodings".idna.to_ascii; -local y=require"util.encodings".idna.to_unicode; +local f=require"util.encodings".idna.to_unicode; local c=require"util.encodings".base64; local e=require"util.logger".init("x509"); -local p=require"util.multitable"; -local v=string.format; +local y=require"util.multitable"; +local p=string.format; local d=ipairs; local _ENV=nil; local u="2.5.4.3"; local h="2.5.29.17"; -local s="1.3.6.1.5.5.7.8.5"; +local i="1.3.6.1.5.5.7.8.5"; local n="1.3.6.1.5.5.7.8.7"; local function l(o,a) local t=r(o) @@ -10190,16 +10423,16 @@ return false end t=t:lower() -local o=t:gsub("^[^.]+%.","") -for i=1,#a do -local a=a[i] +local i=t:gsub("^[^.]+%.","") +for o=1,#a do +local a=a[o] if t==a:lower()then e("debug","Cert dNSName %s matched hostname",a); return true end if a:match("^%*%.")then local t=a:gsub("^[^.]+%.","") -if o==t:lower()then +if i==t:lower()then e("debug","Cert dNSName %s matched hostname",a); return true end @@ -10227,7 +10460,7 @@ end return false end -local function f(i,o,t) +local function m(i,o,t) local a=r(i) if a==nil then e("info","Host %s failed IDNA ToASCII operation",i); @@ -10258,37 +10491,37 @@ end return false end -local function m(o,a,i) -if i.setencode then -i:setencode("utf8"); -end -local t=i:extensions() +local function v(a,o,s) +if s.setencode then +s:setencode("utf8"); +end +local t=s:extensions() if t[h]then local e=t[h]; local t=false -if e[s]then +if e[i]then t=true -if a=="_xmpp-client"or a=="_xmpp-server"then -if w(o,e[s])then return true end +if o=="_xmpp-client"or o=="_xmpp-server"then +if w(a,e[i])then return true end end end if e[n]then t=true -if a and f(o,a,e[n])then return true end +if o and m(a,o,e[n])then return true end end if e["dNSName"]then t=true -if l(o,e["dNSName"])then return true end +if l(a,e["dNSName"])then return true end end if e["uniformResourceIdentifier"]then t=true end if t then return false end end -local a=i:subject() +local o=s:subject() local t=nil -for o=1,#a do -local a=a[o] +for a=1,#o do +local a=o[a] if a["oid"]==u then if t then e("info","Certificate has multiple common names") @@ -10298,31 +10531,31 @@ end end if t then -return l(o,{t}) +return l(a,{t}) end return false end -local function l(i) -if i.setencode then -i:setencode("utf8"); -end -local a=p.new(); -local e=i:extensions(); +local function l(s) +if s.setencode then +s:setencode("utf8"); +end +local a=y.new(); +local e=s:extensions(); local t=e[h]; if t then if t["dNSName"]then for t,e in d(t["dNSName"])do local t=e:sub(1,2)=="*."; if t then e=e:sub(3);end -e=y(o(e)); +e=f(o(e)); if e then if t then e="*."..e;end a:set(e,"*",true); end end end -if t[s]then -for t,e in d(t[s])do +if t[i]then +for t,e in d(t[i])do e=o(e); if e then a:set(e,"xmpp-client",true); @@ -10342,7 +10575,7 @@ end end end -local e=i:subject(); +local e=s:subject(); for t=1,#e do local e=e[t]; if e.oid==u then @@ -10357,23 +10590,23 @@ local t="%-%-%-%-%-BEGIN ([A-Z ]+)%-%-%-%-%-\r?\n".. "([0-9A-Za-z+/=\r\n]*)\r?\n%-%-%-%-%-END %1%-%-%-%-%-"; local function a(e) -local e,t=e:match(t); -if e and t then -return c.decode(t),e; -end -end -local n=('.'):rep(64); -local i="-----BEGIN %s-----\n%s\n-----END %s-----\n" -local function o(t,e) +local t,e=e:match(t); +if t and e then +return c.decode(e),t; +end +end +local i=('.'):rep(64); +local o="-----BEGIN %s-----\n%s\n-----END %s-----\n" +local function n(t,e) e=e and e:upper()or"CERTIFICATE"; t=c.encode(t); -return v(i,e,t:gsub(n,'%0\n',(#t-1)/64),e); +return p(o,e,t:gsub(i,'%0\n',(#t-1)/64),e); end return{ -verify_identity=m; +verify_identity=v; get_identities=l; pem2der=a; -der2pem=o; +der2pem=n; }; end) package.preload['verse.bosh']=(function(...) @@ -10388,15 +10621,15 @@ _M=e; return e; end -local n=require"util.xmppstream".new; -local o=require"util.stanza"; +local h=require"util.xmppstream".new; +local i=require"util.stanza"; require"net.httpclient_listener"; -local a=require"net.http"; +local o=require"net.http"; local e=setmetatable({},{__index=verse.stream_mt}); e.__index=e; -local h="http://etherx.jabber.org/streams"; -local s="http://jabber.org/protocol/httpbind"; -local t=5; +local s="http://etherx.jabber.org/streams"; +local n="http://jabber.org/protocol/httpbind"; +local a=5; function verse.new_bosh(a,t) local t={ bosh_conn_pool={}; @@ -10418,7 +10651,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]=o.clone(e); +self.bosh_outgoing_buffer[#self.bosh_outgoing_buffer+1]=i.clone(e); self:flush(); end function e:flush() @@ -10428,22 +10661,22 @@ or#self.bosh_outgoing_buffer>0 or self.bosh_need_restart)then 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; -end -self:_make_request(e); +local t=self:_make_body(); +local e=self.bosh_outgoing_buffer; +for o,a in ipairs(e)do +t:add_child(a); +e[o]=nil; +end +self:_make_request(t); else self:debug("Decided not to flush."); end end -function e:_make_request(o) -local e,t=a.request(self.bosh_url,{body=tostring(o)},function(i,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(i,e,a); +return self:_handle_response(o,e,t); end local e=os.time(); if not self.inactive_since then @@ -10452,17 +10685,17 @@ return self:_disconnected(); else self:debug("%d seconds left to reconnect, retrying in %d seconds...", -self.bosh_max_inactivity-(e-self.inactive_since),t); -end -timer.add_task(t,function() +self.bosh_max_inactivity-(e-self.inactive_since),a); +end +timer.add_task(a,function() self:debug("Retrying request..."); -for t,e in ipairs(self.bosh_waiting_requests)do -if e==a then -table.remove(self.bosh_waiting_requests,t); +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(o); +self:_make_request(i); end); end); if e then @@ -10484,7 +10717,7 @@ e.attr.from=self.jid; e.attr.to=self.host; e.attr.secure='true'; -a.request(self.bosh_url,{body=tostring(e)},function(e,t) +o.request(self.bosh_url,{body=tostring(e)},function(e,t) if t==0 then return self:_disconnected(); end @@ -10504,19 +10737,19 @@ self:_handle_response_payload(e); end); end -function e:_handle_response(a,t,e) +function e:_handle_response(t,a,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(a); +local e=self:_parse_response(t); if e then self:_handle_response_payload(e); end @@ -10526,7 +10759,7 @@ local e=t.tags; for t=1,#e do local e=e[t]; -if e.attr.xmlns==h then +if e.attr.xmlns==s then self:event("stream-"..e.name,e); elseif e.attr.xmlns then self:event("stream/"..e.attr.xmlns,e); @@ -10542,7 +10775,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(e,t)e.payload:add_child(t);end; +handlestanza=function(t,e)t.payload:add_child(e);end; }; function e:_parse_response(e) self:debug("Parsing response: %s",e); @@ -10552,14 +10785,14 @@ return; end local t={notopen=true,stream=self}; -local a=n(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=s; +xmlns=n; content="text/xml; charset=utf-8"; sid=self.bosh_sid; rid=self.bosh_rid; @@ -10585,8 +10818,8 @@ end local t=require"verse"; local i=t.stream_mt; -local d=require"util.jid".split; -local r=require"net.adns"; +local s=require"util.jid".split; +local h=require"net.adns"; local a=require"util.stanza"; local o=require"util.id".short; math.randomseed((require"socket".gettime()*1e6)%2147483648); @@ -10598,9 +10831,9 @@ end return a.iq(e); end -local s=require"util.xmppstream".new; +local r=require"util.xmppstream".new; local n="http://etherx.jabber.org/streams"; -local function h(e,t) +local function d(e,t) if e.priority==t.priority then if not e.weight_r then e.weight_r=math.random(); @@ -10655,22 +10888,22 @@ if self.stream then self.stream:reset(); else -self.stream=s(self,o); +self.stream=r(self,o); end self.notopen=true; return true; end -function i:connect_client(e,i,a,o) -self.jid,self.password=e,i; -self.client_key,self.server_key=a,o; -self.username,self.host,self.resource=d(e); +function i:connect_client(e,a,i,o) +self.jid,self.password=e,a; +self.client_key,self.server_key=i,o; +self.username,self.host,self.resource=s(e); self:add_plugin("tls"); self:add_plugin("sasl"); self:add_plugin("bind"); function self.data(t,e) -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]+"," ")); +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]+"," ")); self:close("xml-not-well-formed"); end self:hook("connected",function()self:reopen();end); @@ -10722,32 +10955,32 @@ end self:hook("session-success",e,-1) self:hook("bind-success",e,-1); -local e=self.close; -function self:close(t) -self.close=e; +local t=self.close; +function self:close(e) +self.close=t; if not self.closed then self:send(""); self.closed=true; else -return self:close(t); -end -end -local function a() +return self:close(e); +end +end +local function t() self:connect(self.connect_host or self.host,self.connect_port or 5222); end if not(self.connect_host or self.connect_port)then -r.lookup(function(t) -if t then +h.lookup(function(a) +if a then local e={}; self.srv_hosts=e; -for a,t in ipairs(t)do +for a,t in ipairs(a)do table.insert(e,t.srv); end -table.sort(e,h); -local t=e[1]; +table.sort(e,d); +local a=e[1]; self.srv_choice=1; -if t then -self.connect_host,self.connect_port=t.target,t.port; +if a then +self.connect_host,self.connect_port=a.target,a.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() @@ -10755,7 +10988,7 @@ self.srv_choice=self.srv_choice+1; local e=e[self.srv_choice]; self.connect_host,self.connect_port=e.target,e.port; -a(); +t(); return true; end end,1e3); @@ -10763,10 +10996,10 @@ self.srv_hosts=nil; end,1e3); end -a(); +t(); end,"_xmpp-client._tcp."..(self.host)..".","SRV"); else -a(); +t(); end end function i:reopen() @@ -10793,94 +11026,116 @@ _M=e; return e; end -local a=require"verse"; -local t=a.stream_mt; -local d=require"util.jid".split; -local e=require"lxp"; -local o=require"util.stanza"; -local r=require"util.hashes".sha1; -a.message,a.presence,a.iq,a.stanza,a.reply,a.error_reply= -o.message,o.presence,o.iq,o.stanza,o.reply,o.error_reply; -local h=require"util.xmppstream".new; -local s="http://etherx.jabber.org/streams"; -local i="jabber:component:accept"; -local n={ -stream_ns=s, +local t=require"verse"; +local s=t.stream_mt; +local r=require"util.jid".split; +local a=require"util.stanza"; +local h=require"util.hashes".sha1; +t.message,t.presence,t.iq,t.stanza,t.reply,t.error_reply= +a.message,a.presence,a.iq,a.stanza,a.reply,a.error_reply; +local d=require"util.xmppstream".new; +local n="http://etherx.jabber.org/streams"; +local o="jabber:component:accept"; +local i={ +stream_ns=n, stream_tag="stream", -default_ns=i}; -function n.streamopened(e,t) +default_ns=o}; +function i.streamopened(e,t) e.stream_id=t.id; if not e:event("opened",t)then e.notopen=nil; end return true; end -function n.streamclosed(e) +function i.streamclosed(e) return e:event("closed"); end -function n.handlestanza(t,e) -if e.attr.xmlns==s then +function i.handlestanza(t,e) +if e.attr.xmlns==n then return t:event("stream-"..e.name,e); elseif e.attr.xmlns or e.name=="handshake"then -return t:event("stream/"..(e.attr.xmlns or i),e); +return t:event("stream/"..(e.attr.xmlns or o),e); end return t:event("stanza",e); end -function t:reset() +function s:connect_component(e,n) +self.jid,self.password=e,n; +self.username,self.host,self.resource=r(e); +function self:reset() if self.stream then self.stream:reset(); else -self.stream=h(self,n); +self.stream=d(self,i); end self.notopen=true; return true; end -function t:connect_component(e,n) -self.jid,self.password=e,n; -self.username,self.host,self.resource=d(e); -function self.data(a,e) -local a,o=self.stream:feed(e); +function self:reopen() +self:reset(); +self:send(a.stanza("stream:stream",{to=self.jid,["xmlns:stream"]='http://etherx.jabber.org/streams', +xmlns=o,version="1.0"}):top_tag()); +end +function self:close(e) +if not self.notopen then +self:send(""); +end +local t=self.conn.disconnect(); +self.conn:close(); +t(conn,e); +end +function self:send_iq(t,a) +local e=self:new_id(); +self.tracked_iqs[e]=a; +t.attr.id=e; +self:send(t); +end +function self:new_id() +self.curr_id=self.curr_id+1; +return tostring(self.curr_id); +end +function self.data(t,e) +local a,t=self.stream:feed(e); if a then return;end -t:debug("Received invalid XML (%s) %d bytes: %s",tostring(o),#e,e:sub(1,300):gsub("[\r\n]+"," ")); -t:close("xml-not-well-formed"); +stream:debug("Received invalid XML (%s) %d bytes: %s",tostring(t),#e,e:sub(1,300):gsub("[\r\n]+"," ")); +stream:close("xml-not-well-formed"); end self:hook("incoming-raw",function(e)return self.data(self.conn,e);end); self.curr_id=0; self.tracked_iqs={}; -self:hook("stanza",function(t) -local e,a=t.attr.id,t.attr.type; -if e and t.name=="iq"and(a=="result"or a=="error")and self.tracked_iqs[e]then -self.tracked_iqs[e](t); -self.tracked_iqs[e]=nil; +self:hook("stanza",function(e) +local t,a=e.attr.id,e.attr.type; +if t and e.name=="iq"and(a=="result"or a=="error")and self.tracked_iqs[t]then +self.tracked_iqs[t](e); +self.tracked_iqs[t]=nil; return true; 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(o.stanza("handshake",{xmlns=i}):text(e)); -self:hook("stream/"..i,function(e) +local e=h(self.stream_id..n,true); +self:send(a.stanza("handshake",{xmlns=o}):text(e)); +self:hook("stream/"..o,function(e) if e.name=="handshake"then self:event("authentication-success"); end @@ -10893,29 +11148,6 @@ self:connect(self.connect_host or self.host,self.connect_port or 5347); self:reopen(); end -function t:reopen() -self:reset(); -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 t:close(t) -if not self.notopen then -self:send(""); -end -local e=self.conn.disconnect(); -self.conn:close(); -e(conn,t); -end -function t:send_iq(e,a) -local t=self:new_id(); -self.tracked_iqs[t]=a; -e.attr.id=t; -self:send(e); -end -function t:new_id() -self.curr_id=self.curr_id+1; -return tostring(self.curr_id); -end end) pcall(require,"luarocks.require"); local h=require"socket"; @@ -10940,11 +11172,11 @@ return e; end local i=0; -function e.new(o,a) -local t=setmetatable(a or{},t); +function e.new(a,o) +local t=setmetatable(o or{},t); i=i+1; t.id=tostring(i); -t.logger=o or e.new_logger("stream"..t.id); +t.logger=a or e.new_logger("stream"..t.id); t.events=s.new(); t.plugins={}; t.verse=e; @@ -10964,16 +11196,16 @@ end end if e then -local function a(t,a,o,...) -return e(t,a,n(o,...)); +local function i(o,a,t,...) +return e(o,a,n(t,...)); end for t,e in ipairs(t)do -o.add_level_sink(e,a); -end -end -end -function e._default_log_handler(a,o,t) -return io.stderr:write(a,"\t",o,"\t",t,"\n"); +o.add_level_sink(e,i); +end +end +end +function e._default_log_handler(o,t,a) +return io.stderr:write(o,"\t",t,"\t",a,"\n"); end e.set_log_handler(e._default_log_handler,{"error"}); local function o(t) @@ -11062,8 +11294,8 @@ function t:hook(e,...) return self.events.add_handler(e,...); end -function t:unhook(e,t) -return self.events.remove_handler(e,t); +function t:unhook(t,e) +return self.events.remove_handler(t,e); end function e.eventable(e) e.events=s.new();