spamscanner 7.0.9 → 7.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/arf.cjs.map +1 -1
- package/dist/cjs/index.cjs +1338 -179
- package/dist/cjs/index.cjs.map +4 -4
- package/dist/esm/arf.js.map +1 -1
- package/dist/esm/cli.js +1266 -123
- package/dist/esm/cli.js.map +4 -4
- package/dist/esm/index.js +1306 -163
- package/dist/esm/index.js.map +4 -4
- package/dist/types/attachments.d.ts +1 -0
- package/dist/types/entities.d.ts +2 -0
- package/dist/types/html.d.ts +2 -2
- package/dist/types/index.d.ts +26 -6
- package/dist/types/links.d.ts +24 -0
- package/dist/types/parse.d.ts +1 -1
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -1624,6 +1624,286 @@ var init_homograph = __esm({
|
|
|
1624
1624
|
}
|
|
1625
1625
|
});
|
|
1626
1626
|
|
|
1627
|
+
// src/entities.js
|
|
1628
|
+
var NAMED, NAMED_REFERENCES;
|
|
1629
|
+
var init_entities = __esm({
|
|
1630
|
+
"src/entities.js"() {
|
|
1631
|
+
NAMED = [
|
|
1632
|
+
"AElig=c6,AMP=26,Aacute=c1,Abreve=102,Acirc=c2,Acy=410,Afr=1d504,Agrave=c0,Alpha=391,Amacr=100,And=2a",
|
|
1633
|
+
"53,Aogon=104,Aopf=1d538,ApplyFunction=2061,Aring=c5,Ascr=1d49c,Assign=2254,Atilde=c3,Auml=c4,Backsla",
|
|
1634
|
+
"sh=2216,Barv=2ae7,Barwed=2306,Bcy=411,Because=2235,Bernoullis=212c,Beta=392,Bfr=1d505,Bopf=1d539,Bre",
|
|
1635
|
+
"ve=2d8,Bscr=212c,Bumpeq=224e,CHcy=427,COPY=a9,Cacute=106,Cap=22d2,CapitalDifferentialD=2145,Cayleys=",
|
|
1636
|
+
"212d,Ccaron=10c,Ccedil=c7,Ccirc=108,Cconint=2230,Cdot=10a,Cedilla=b8,CenterDot=b7,Cfr=212d,Chi=3a7,C",
|
|
1637
|
+
"ircleDot=2299,CircleMinus=2296,CirclePlus=2295,CircleTimes=2297,ClockwiseContourIntegral=2232,CloseC",
|
|
1638
|
+
"urlyDoubleQuote=201d,CloseCurlyQuote=2019,Colon=2237,Colone=2a74,Congruent=2261,Conint=222f,ContourI",
|
|
1639
|
+
"ntegral=222e,Copf=2102,Coproduct=2210,CounterClockwiseContourIntegral=2233,Cross=2a2f,Cscr=1d49e,Cup",
|
|
1640
|
+
"=22d3,CupCap=224d,DD=2145,DDotrahd=2911,DJcy=402,DScy=405,DZcy=40f,Dagger=2021,Darr=21a1,Dashv=2ae4,",
|
|
1641
|
+
"Dcaron=10e,Dcy=414,Del=2207,Delta=394,Dfr=1d507,DiacriticalAcute=b4,DiacriticalDot=2d9,DiacriticalDo",
|
|
1642
|
+
"ubleAcute=2dd,DiacriticalGrave=60,DiacriticalTilde=2dc,Diamond=22c4,DifferentialD=2146,Dopf=1d53b,Do",
|
|
1643
|
+
"t=a8,DotDot=20dc,DotEqual=2250,DoubleContourIntegral=222f,DoubleDot=a8,DoubleDownArrow=21d3,DoubleLe",
|
|
1644
|
+
"ftArrow=21d0,DoubleLeftRightArrow=21d4,DoubleLeftTee=2ae4,DoubleLongLeftArrow=27f8,DoubleLongLeftRig",
|
|
1645
|
+
"htArrow=27fa,DoubleLongRightArrow=27f9,DoubleRightArrow=21d2,DoubleRightTee=22a8,DoubleUpArrow=21d1,",
|
|
1646
|
+
"DoubleUpDownArrow=21d5,DoubleVerticalBar=2225,DownArrow=2193,DownArrowBar=2913,DownArrowUpArrow=21f5",
|
|
1647
|
+
",DownBreve=311,DownLeftRightVector=2950,DownLeftTeeVector=295e,DownLeftVector=21bd,DownLeftVectorBar",
|
|
1648
|
+
"=2956,DownRightTeeVector=295f,DownRightVector=21c1,DownRightVectorBar=2957,DownTee=22a4,DownTeeArrow",
|
|
1649
|
+
"=21a7,Downarrow=21d3,Dscr=1d49f,Dstrok=110,ENG=14a,ETH=d0,Eacute=c9,Ecaron=11a,Ecirc=ca,Ecy=42d,Edot",
|
|
1650
|
+
"=116,Efr=1d508,Egrave=c8,Element=2208,Emacr=112,EmptySmallSquare=25fb,EmptyVerySmallSquare=25ab,Eogo",
|
|
1651
|
+
"n=118,Eopf=1d53c,Epsilon=395,Equal=2a75,EqualTilde=2242,Equilibrium=21cc,Escr=2130,Esim=2a73,Eta=397",
|
|
1652
|
+
",Euml=cb,Exists=2203,ExponentialE=2147,Fcy=424,Ffr=1d509,FilledSmallSquare=25fc,FilledVerySmallSquar",
|
|
1653
|
+
"e=25aa,Fopf=1d53d,ForAll=2200,Fouriertrf=2131,Fscr=2131,GJcy=403,GT=3e,Gamma=393,Gammad=3dc,Gbreve=1",
|
|
1654
|
+
"1e,Gcedil=122,Gcirc=11c,Gcy=413,Gdot=120,Gfr=1d50a,Gg=22d9,Gopf=1d53e,GreaterEqual=2265,GreaterEqual",
|
|
1655
|
+
"Less=22db,GreaterFullEqual=2267,GreaterGreater=2aa2,GreaterLess=2277,GreaterSlantEqual=2a7e,GreaterT",
|
|
1656
|
+
"ilde=2273,Gscr=1d4a2,Gt=226b,HARDcy=42a,Hacek=2c7,Hat=5e,Hcirc=124,Hfr=210c,HilbertSpace=210b,Hopf=2",
|
|
1657
|
+
"10d,HorizontalLine=2500,Hscr=210b,Hstrok=126,HumpDownHump=224e,HumpEqual=224f,IEcy=415,IJlig=132,IOc",
|
|
1658
|
+
"y=401,Iacute=cd,Icirc=ce,Icy=418,Idot=130,Ifr=2111,Igrave=cc,Im=2111,Imacr=12a,ImaginaryI=2148,Impli",
|
|
1659
|
+
"es=21d2,Int=222c,Integral=222b,Intersection=22c2,InvisibleComma=2063,InvisibleTimes=2062,Iogon=12e,I",
|
|
1660
|
+
"opf=1d540,Iota=399,Iscr=2110,Itilde=128,Iukcy=406,Iuml=cf,Jcirc=134,Jcy=419,Jfr=1d50d,Jopf=1d541,Jsc",
|
|
1661
|
+
"r=1d4a5,Jsercy=408,Jukcy=404,KHcy=425,KJcy=40c,Kappa=39a,Kcedil=136,Kcy=41a,Kfr=1d50e,Kopf=1d542,Ksc",
|
|
1662
|
+
"r=1d4a6,LJcy=409,LT=3c,Lacute=139,Lambda=39b,Lang=27ea,Laplacetrf=2112,Larr=219e,Lcaron=13d,Lcedil=1",
|
|
1663
|
+
"3b,Lcy=41b,LeftAngleBracket=27e8,LeftArrow=2190,LeftArrowBar=21e4,LeftArrowRightArrow=21c6,LeftCeili",
|
|
1664
|
+
"ng=2308,LeftDoubleBracket=27e6,LeftDownTeeVector=2961,LeftDownVector=21c3,LeftDownVectorBar=2959,Lef",
|
|
1665
|
+
"tFloor=230a,LeftRightArrow=2194,LeftRightVector=294e,LeftTee=22a3,LeftTeeArrow=21a4,LeftTeeVector=29",
|
|
1666
|
+
"5a,LeftTriangle=22b2,LeftTriangleBar=29cf,LeftTriangleEqual=22b4,LeftUpDownVector=2951,LeftUpTeeVect",
|
|
1667
|
+
"or=2960,LeftUpVector=21bf,LeftUpVectorBar=2958,LeftVector=21bc,LeftVectorBar=2952,Leftarrow=21d0,Lef",
|
|
1668
|
+
"trightarrow=21d4,LessEqualGreater=22da,LessFullEqual=2266,LessGreater=2276,LessLess=2aa1,LessSlantEq",
|
|
1669
|
+
"ual=2a7d,LessTilde=2272,Lfr=1d50f,Ll=22d8,Lleftarrow=21da,Lmidot=13f,LongLeftArrow=27f5,LongLeftRigh",
|
|
1670
|
+
"tArrow=27f7,LongRightArrow=27f6,Longleftarrow=27f8,Longleftrightarrow=27fa,Longrightarrow=27f9,Lopf=",
|
|
1671
|
+
"1d543,LowerLeftArrow=2199,LowerRightArrow=2198,Lscr=2112,Lsh=21b0,Lstrok=141,Lt=226a,Map=2905,Mcy=41",
|
|
1672
|
+
"c,MediumSpace=205f,Mellintrf=2133,Mfr=1d510,MinusPlus=2213,Mopf=1d544,Mscr=2133,Mu=39c,NJcy=40a,Nacu",
|
|
1673
|
+
"te=143,Ncaron=147,Ncedil=145,Ncy=41d,NegativeMediumSpace=200b,NegativeThickSpace=200b,NegativeThinSp",
|
|
1674
|
+
"ace=200b,NegativeVeryThinSpace=200b,NestedGreaterGreater=226b,NestedLessLess=226a,NewLine=a,Nfr=1d51",
|
|
1675
|
+
"1,NoBreak=2060,NonBreakingSpace=a0,Nopf=2115,Not=2aec,NotCongruent=2262,NotCupCap=226d,NotDoubleVert",
|
|
1676
|
+
"icalBar=2226,NotElement=2209,NotEqual=2260,NotEqualTilde=2242.338,NotExists=2204,NotGreater=226f,Not",
|
|
1677
|
+
"GreaterEqual=2271,NotGreaterFullEqual=2267.338,NotGreaterGreater=226b.338,NotGreaterLess=2279,NotGre",
|
|
1678
|
+
"aterSlantEqual=2a7e.338,NotGreaterTilde=2275,NotHumpDownHump=224e.338,NotHumpEqual=224f.338,NotLeftT",
|
|
1679
|
+
"riangle=22ea,NotLeftTriangleBar=29cf.338,NotLeftTriangleEqual=22ec,NotLess=226e,NotLessEqual=2270,No",
|
|
1680
|
+
"tLessGreater=2278,NotLessLess=226a.338,NotLessSlantEqual=2a7d.338,NotLessTilde=2274,NotNestedGreater",
|
|
1681
|
+
"Greater=2aa2.338,NotNestedLessLess=2aa1.338,NotPrecedes=2280,NotPrecedesEqual=2aaf.338,NotPrecedesSl",
|
|
1682
|
+
"antEqual=22e0,NotReverseElement=220c,NotRightTriangle=22eb,NotRightTriangleBar=29d0.338,NotRightTria",
|
|
1683
|
+
"ngleEqual=22ed,NotSquareSubset=228f.338,NotSquareSubsetEqual=22e2,NotSquareSuperset=2290.338,NotSqua",
|
|
1684
|
+
"reSupersetEqual=22e3,NotSubset=2282.20d2,NotSubsetEqual=2288,NotSucceeds=2281,NotSucceedsEqual=2ab0.",
|
|
1685
|
+
"338,NotSucceedsSlantEqual=22e1,NotSucceedsTilde=227f.338,NotSuperset=2283.20d2,NotSupersetEqual=2289",
|
|
1686
|
+
",NotTilde=2241,NotTildeEqual=2244,NotTildeFullEqual=2247,NotTildeTilde=2249,NotVerticalBar=2224,Nscr",
|
|
1687
|
+
"=1d4a9,Ntilde=d1,Nu=39d,OElig=152,Oacute=d3,Ocirc=d4,Ocy=41e,Odblac=150,Ofr=1d512,Ograve=d2,Omacr=14",
|
|
1688
|
+
"c,Omega=3a9,Omicron=39f,Oopf=1d546,OpenCurlyDoubleQuote=201c,OpenCurlyQuote=2018,Or=2a54,Oscr=1d4aa,",
|
|
1689
|
+
"Oslash=d8,Otilde=d5,Otimes=2a37,Ouml=d6,OverBar=203e,OverBrace=23de,OverBracket=23b4,OverParenthesis",
|
|
1690
|
+
"=23dc,PartialD=2202,Pcy=41f,Pfr=1d513,Phi=3a6,Pi=3a0,PlusMinus=b1,Poincareplane=210c,Popf=2119,Pr=2a",
|
|
1691
|
+
"bb,Precedes=227a,PrecedesEqual=2aaf,PrecedesSlantEqual=227c,PrecedesTilde=227e,Prime=2033,Product=22",
|
|
1692
|
+
"0f,Proportion=2237,Proportional=221d,Pscr=1d4ab,Psi=3a8,QUOT=22,Qfr=1d514,Qopf=211a,Qscr=1d4ac,RBarr",
|
|
1693
|
+
"=2910,REG=ae,Racute=154,Rang=27eb,Rarr=21a0,Rarrtl=2916,Rcaron=158,Rcedil=156,Rcy=420,Re=211c,Revers",
|
|
1694
|
+
"eElement=220b,ReverseEquilibrium=21cb,ReverseUpEquilibrium=296f,Rfr=211c,Rho=3a1,RightAngleBracket=2",
|
|
1695
|
+
"7e9,RightArrow=2192,RightArrowBar=21e5,RightArrowLeftArrow=21c4,RightCeiling=2309,RightDoubleBracket",
|
|
1696
|
+
"=27e7,RightDownTeeVector=295d,RightDownVector=21c2,RightDownVectorBar=2955,RightFloor=230b,RightTee=",
|
|
1697
|
+
"22a2,RightTeeArrow=21a6,RightTeeVector=295b,RightTriangle=22b3,RightTriangleBar=29d0,RightTriangleEq",
|
|
1698
|
+
"ual=22b5,RightUpDownVector=294f,RightUpTeeVector=295c,RightUpVector=21be,RightUpVectorBar=2954,Right",
|
|
1699
|
+
"Vector=21c0,RightVectorBar=2953,Rightarrow=21d2,Ropf=211d,RoundImplies=2970,Rrightarrow=21db,Rscr=21",
|
|
1700
|
+
"1b,Rsh=21b1,RuleDelayed=29f4,SHCHcy=429,SHcy=428,SOFTcy=42c,Sacute=15a,Sc=2abc,Scaron=160,Scedil=15e",
|
|
1701
|
+
",Scirc=15c,Scy=421,Sfr=1d516,ShortDownArrow=2193,ShortLeftArrow=2190,ShortRightArrow=2192,ShortUpArr",
|
|
1702
|
+
"ow=2191,Sigma=3a3,SmallCircle=2218,Sopf=1d54a,Sqrt=221a,Square=25a1,SquareIntersection=2293,SquareSu",
|
|
1703
|
+
"bset=228f,SquareSubsetEqual=2291,SquareSuperset=2290,SquareSupersetEqual=2292,SquareUnion=2294,Sscr=",
|
|
1704
|
+
"1d4ae,Star=22c6,Sub=22d0,Subset=22d0,SubsetEqual=2286,Succeeds=227b,SucceedsEqual=2ab0,SucceedsSlant",
|
|
1705
|
+
"Equal=227d,SucceedsTilde=227f,SuchThat=220b,Sum=2211,Sup=22d1,Superset=2283,SupersetEqual=2287,Supse",
|
|
1706
|
+
"t=22d1,THORN=de,TRADE=2122,TSHcy=40b,TScy=426,Tab=9,Tau=3a4,Tcaron=164,Tcedil=162,Tcy=422,Tfr=1d517,",
|
|
1707
|
+
"Therefore=2234,Theta=398,ThickSpace=205f.200a,ThinSpace=2009,Tilde=223c,TildeEqual=2243,TildeFullEqu",
|
|
1708
|
+
"al=2245,TildeTilde=2248,Topf=1d54b,TripleDot=20db,Tscr=1d4af,Tstrok=166,Uacute=da,Uarr=219f,Uarrocir",
|
|
1709
|
+
"=2949,Ubrcy=40e,Ubreve=16c,Ucirc=db,Ucy=423,Udblac=170,Ufr=1d518,Ugrave=d9,Umacr=16a,UnderBar=5f,Und",
|
|
1710
|
+
"erBrace=23df,UnderBracket=23b5,UnderParenthesis=23dd,Union=22c3,UnionPlus=228e,Uogon=172,Uopf=1d54c,",
|
|
1711
|
+
"UpArrow=2191,UpArrowBar=2912,UpArrowDownArrow=21c5,UpDownArrow=2195,UpEquilibrium=296e,UpTee=22a5,Up",
|
|
1712
|
+
"TeeArrow=21a5,Uparrow=21d1,Updownarrow=21d5,UpperLeftArrow=2196,UpperRightArrow=2197,Upsi=3d2,Upsilo",
|
|
1713
|
+
"n=3a5,Uring=16e,Uscr=1d4b0,Utilde=168,Uuml=dc,VDash=22ab,Vbar=2aeb,Vcy=412,Vdash=22a9,Vdashl=2ae6,Ve",
|
|
1714
|
+
"e=22c1,Verbar=2016,Vert=2016,VerticalBar=2223,VerticalLine=7c,VerticalSeparator=2758,VerticalTilde=2",
|
|
1715
|
+
"240,VeryThinSpace=200a,Vfr=1d519,Vopf=1d54d,Vscr=1d4b1,Vvdash=22aa,Wcirc=174,Wedge=22c0,Wfr=1d51a,Wo",
|
|
1716
|
+
"pf=1d54e,Wscr=1d4b2,Xfr=1d51b,Xi=39e,Xopf=1d54f,Xscr=1d4b3,YAcy=42f,YIcy=407,YUcy=42e,Yacute=dd,Ycir",
|
|
1717
|
+
"c=176,Ycy=42b,Yfr=1d51c,Yopf=1d550,Yscr=1d4b4,Yuml=178,ZHcy=416,Zacute=179,Zcaron=17d,Zcy=417,Zdot=1",
|
|
1718
|
+
"7b,ZeroWidthSpace=200b,Zeta=396,Zfr=2128,Zopf=2124,Zscr=1d4b5,aacute=e1,abreve=103,ac=223e,acE=223e.",
|
|
1719
|
+
"333,acd=223f,acirc=e2,acute=b4,acy=430,aelig=e6,af=2061,afr=1d51e,agrave=e0,alefsym=2135,aleph=2135,",
|
|
1720
|
+
"alpha=3b1,amacr=101,amalg=2a3f,amp=26,and=2227,andand=2a55,andd=2a5c,andslope=2a58,andv=2a5a,ang=222",
|
|
1721
|
+
"0,ange=29a4,angle=2220,angmsd=2221,angmsdaa=29a8,angmsdab=29a9,angmsdac=29aa,angmsdad=29ab,angmsdae=",
|
|
1722
|
+
"29ac,angmsdaf=29ad,angmsdag=29ae,angmsdah=29af,angrt=221f,angrtvb=22be,angrtvbd=299d,angsph=2222,ang",
|
|
1723
|
+
"st=c5,angzarr=237c,aogon=105,aopf=1d552,ap=2248,apE=2a70,apacir=2a6f,ape=224a,apid=224b,apos=27,appr",
|
|
1724
|
+
"ox=2248,approxeq=224a,aring=e5,ascr=1d4b6,ast=2a,asymp=2248,asympeq=224d,atilde=e3,auml=e4,awconint=",
|
|
1725
|
+
"2233,awint=2a11,bNot=2aed,backcong=224c,backepsilon=3f6,backprime=2035,backsim=223d,backsimeq=22cd,b",
|
|
1726
|
+
"arvee=22bd,barwed=2305,barwedge=2305,bbrk=23b5,bbrktbrk=23b6,bcong=224c,bcy=431,bdquo=201e,becaus=22",
|
|
1727
|
+
"35,because=2235,bemptyv=29b0,bepsi=3f6,bernou=212c,beta=3b2,beth=2136,between=226c,bfr=1d51f,bigcap=",
|
|
1728
|
+
"22c2,bigcirc=25ef,bigcup=22c3,bigodot=2a00,bigoplus=2a01,bigotimes=2a02,bigsqcup=2a06,bigstar=2605,b",
|
|
1729
|
+
"igtriangledown=25bd,bigtriangleup=25b3,biguplus=2a04,bigvee=22c1,bigwedge=22c0,bkarow=290d,blackloze",
|
|
1730
|
+
"nge=29eb,blacksquare=25aa,blacktriangle=25b4,blacktriangledown=25be,blacktriangleleft=25c2,blacktria",
|
|
1731
|
+
"ngleright=25b8,blank=2423,blk12=2592,blk14=2591,blk34=2593,block=2588,bne=3d.20e5,bnequiv=2261.20e5,",
|
|
1732
|
+
"bnot=2310,bopf=1d553,bot=22a5,bottom=22a5,bowtie=22c8,boxDL=2557,boxDR=2554,boxDl=2556,boxDr=2553,bo",
|
|
1733
|
+
"xH=2550,boxHD=2566,boxHU=2569,boxHd=2564,boxHu=2567,boxUL=255d,boxUR=255a,boxUl=255c,boxUr=2559,boxV",
|
|
1734
|
+
"=2551,boxVH=256c,boxVL=2563,boxVR=2560,boxVh=256b,boxVl=2562,boxVr=255f,boxbox=29c9,boxdL=2555,boxdR",
|
|
1735
|
+
"=2552,boxdl=2510,boxdr=250c,boxh=2500,boxhD=2565,boxhU=2568,boxhd=252c,boxhu=2534,boxminus=229f,boxp",
|
|
1736
|
+
"lus=229e,boxtimes=22a0,boxuL=255b,boxuR=2558,boxul=2518,boxur=2514,boxv=2502,boxvH=256a,boxvL=2561,b",
|
|
1737
|
+
"oxvR=255e,boxvh=253c,boxvl=2524,boxvr=251c,bprime=2035,breve=2d8,brvbar=a6,bscr=1d4b7,bsemi=204f,bsi",
|
|
1738
|
+
"m=223d,bsime=22cd,bsol=5c,bsolb=29c5,bsolhsub=27c8,bull=2022,bullet=2022,bump=224e,bumpE=2aae,bumpe=",
|
|
1739
|
+
"224f,bumpeq=224f,cacute=107,cap=2229,capand=2a44,capbrcup=2a49,capcap=2a4b,capcup=2a47,capdot=2a40,c",
|
|
1740
|
+
"aps=2229.fe00,caret=2041,caron=2c7,ccaps=2a4d,ccaron=10d,ccedil=e7,ccirc=109,ccups=2a4c,ccupssm=2a50",
|
|
1741
|
+
",cdot=10b,cedil=b8,cemptyv=29b2,cent=a2,centerdot=b7,cfr=1d520,chcy=447,check=2713,checkmark=2713,ch",
|
|
1742
|
+
"i=3c7,cir=25cb,cirE=29c3,circ=2c6,circeq=2257,circlearrowleft=21ba,circlearrowright=21bb,circledR=ae",
|
|
1743
|
+
",circledS=24c8,circledast=229b,circledcirc=229a,circleddash=229d,cire=2257,cirfnint=2a10,cirmid=2aef",
|
|
1744
|
+
",cirscir=29c2,clubs=2663,clubsuit=2663,colon=3a,colone=2254,coloneq=2254,comma=2c,commat=40,comp=220",
|
|
1745
|
+
"1,compfn=2218,complement=2201,complexes=2102,cong=2245,congdot=2a6d,conint=222e,copf=1d554,coprod=22",
|
|
1746
|
+
"10,copy=a9,copysr=2117,crarr=21b5,cross=2717,cscr=1d4b8,csub=2acf,csube=2ad1,csup=2ad0,csupe=2ad2,ct",
|
|
1747
|
+
"dot=22ef,cudarrl=2938,cudarrr=2935,cuepr=22de,cuesc=22df,cularr=21b6,cularrp=293d,cup=222a,cupbrcap=",
|
|
1748
|
+
"2a48,cupcap=2a46,cupcup=2a4a,cupdot=228d,cupor=2a45,cups=222a.fe00,curarr=21b7,curarrm=293c,curlyeqp",
|
|
1749
|
+
"rec=22de,curlyeqsucc=22df,curlyvee=22ce,curlywedge=22cf,curren=a4,curvearrowleft=21b6,curvearrowrigh",
|
|
1750
|
+
"t=21b7,cuvee=22ce,cuwed=22cf,cwconint=2232,cwint=2231,cylcty=232d,dArr=21d3,dHar=2965,dagger=2020,da",
|
|
1751
|
+
"leth=2138,darr=2193,dash=2010,dashv=22a3,dbkarow=290f,dblac=2dd,dcaron=10f,dcy=434,dd=2146,ddagger=2",
|
|
1752
|
+
"021,ddarr=21ca,ddotseq=2a77,deg=b0,delta=3b4,demptyv=29b1,dfisht=297f,dfr=1d521,dharl=21c3,dharr=21c",
|
|
1753
|
+
"2,diam=22c4,diamond=22c4,diamondsuit=2666,diams=2666,die=a8,digamma=3dd,disin=22f2,div=f7,divide=f7,",
|
|
1754
|
+
"divideontimes=22c7,divonx=22c7,djcy=452,dlcorn=231e,dlcrop=230d,dollar=24,dopf=1d555,dot=2d9,doteq=2",
|
|
1755
|
+
"250,doteqdot=2251,dotminus=2238,dotplus=2214,dotsquare=22a1,doublebarwedge=2306,downarrow=2193,downd",
|
|
1756
|
+
"ownarrows=21ca,downharpoonleft=21c3,downharpoonright=21c2,drbkarow=2910,drcorn=231f,drcrop=230c,dscr",
|
|
1757
|
+
"=1d4b9,dscy=455,dsol=29f6,dstrok=111,dtdot=22f1,dtri=25bf,dtrif=25be,duarr=21f5,duhar=296f,dwangle=2",
|
|
1758
|
+
"9a6,dzcy=45f,dzigrarr=27ff,eDDot=2a77,eDot=2251,eacute=e9,easter=2a6e,ecaron=11b,ecir=2256,ecirc=ea,",
|
|
1759
|
+
"ecolon=2255,ecy=44d,edot=117,ee=2147,efDot=2252,efr=1d522,eg=2a9a,egrave=e8,egs=2a96,egsdot=2a98,el=",
|
|
1760
|
+
"2a99,elinters=23e7,ell=2113,els=2a95,elsdot=2a97,emacr=113,empty=2205,emptyset=2205,emptyv=2205,emsp",
|
|
1761
|
+
"=2003,emsp13=2004,emsp14=2005,eng=14b,ensp=2002,eogon=119,eopf=1d556,epar=22d5,eparsl=29e3,eplus=2a7",
|
|
1762
|
+
"1,epsi=3b5,epsilon=3b5,epsiv=3f5,eqcirc=2256,eqcolon=2255,eqsim=2242,eqslantgtr=2a96,eqslantless=2a9",
|
|
1763
|
+
"5,equals=3d,equest=225f,equiv=2261,equivDD=2a78,eqvparsl=29e5,erDot=2253,erarr=2971,escr=212f,esdot=",
|
|
1764
|
+
"2250,esim=2242,eta=3b7,eth=f0,euml=eb,euro=20ac,excl=21,exist=2203,expectation=2130,exponentiale=214",
|
|
1765
|
+
"7,fallingdotseq=2252,fcy=444,female=2640,ffilig=fb03,fflig=fb00,ffllig=fb04,ffr=1d523,filig=fb01,fjl",
|
|
1766
|
+
"ig=66.6a,flat=266d,fllig=fb02,fltns=25b1,fnof=192,fopf=1d557,forall=2200,fork=22d4,forkv=2ad9,fparti",
|
|
1767
|
+
"nt=2a0d,frac12=bd,frac13=2153,frac14=bc,frac15=2155,frac16=2159,frac18=215b,frac23=2154,frac25=2156,",
|
|
1768
|
+
"frac34=be,frac35=2157,frac38=215c,frac45=2158,frac56=215a,frac58=215d,frac78=215e,frasl=2044,frown=2",
|
|
1769
|
+
"322,fscr=1d4bb,gE=2267,gEl=2a8c,gacute=1f5,gamma=3b3,gammad=3dd,gap=2a86,gbreve=11f,gcirc=11d,gcy=43",
|
|
1770
|
+
"3,gdot=121,ge=2265,gel=22db,geq=2265,geqq=2267,geqslant=2a7e,ges=2a7e,gescc=2aa9,gesdot=2a80,gesdoto",
|
|
1771
|
+
"=2a82,gesdotol=2a84,gesl=22db.fe00,gesles=2a94,gfr=1d524,gg=226b,ggg=22d9,gimel=2137,gjcy=453,gl=227",
|
|
1772
|
+
"7,glE=2a92,gla=2aa5,glj=2aa4,gnE=2269,gnap=2a8a,gnapprox=2a8a,gne=2a88,gneq=2a88,gneqq=2269,gnsim=22",
|
|
1773
|
+
"e7,gopf=1d558,grave=60,gscr=210a,gsim=2273,gsime=2a8e,gsiml=2a90,gt=3e,gtcc=2aa7,gtcir=2a7a,gtdot=22",
|
|
1774
|
+
"d7,gtlPar=2995,gtquest=2a7c,gtrapprox=2a86,gtrarr=2978,gtrdot=22d7,gtreqless=22db,gtreqqless=2a8c,gt",
|
|
1775
|
+
"rless=2277,gtrsim=2273,gvertneqq=2269.fe00,gvnE=2269.fe00,hArr=21d4,hairsp=200a,half=bd,hamilt=210b,",
|
|
1776
|
+
"hardcy=44a,harr=2194,harrcir=2948,harrw=21ad,hbar=210f,hcirc=125,hearts=2665,heartsuit=2665,hellip=2",
|
|
1777
|
+
"026,hercon=22b9,hfr=1d525,hksearow=2925,hkswarow=2926,hoarr=21ff,homtht=223b,hookleftarrow=21a9,hook",
|
|
1778
|
+
"rightarrow=21aa,hopf=1d559,horbar=2015,hscr=1d4bd,hslash=210f,hstrok=127,hybull=2043,hyphen=2010,iac",
|
|
1779
|
+
"ute=ed,ic=2063,icirc=ee,icy=438,iecy=435,iexcl=a1,iff=21d4,ifr=1d526,igrave=ec,ii=2148,iiiint=2a0c,i",
|
|
1780
|
+
"iint=222d,iinfin=29dc,iiota=2129,ijlig=133,imacr=12b,image=2111,imagline=2110,imagpart=2111,imath=13",
|
|
1781
|
+
"1,imof=22b7,imped=1b5,in=2208,incare=2105,infin=221e,infintie=29dd,inodot=131,int=222b,intcal=22ba,i",
|
|
1782
|
+
"ntegers=2124,intercal=22ba,intlarhk=2a17,intprod=2a3c,iocy=451,iogon=12f,iopf=1d55a,iota=3b9,iprod=2",
|
|
1783
|
+
"a3c,iquest=bf,iscr=1d4be,isin=2208,isinE=22f9,isindot=22f5,isins=22f4,isinsv=22f3,isinv=2208,it=2062",
|
|
1784
|
+
",itilde=129,iukcy=456,iuml=ef,jcirc=135,jcy=439,jfr=1d527,jmath=237,jopf=1d55b,jscr=1d4bf,jsercy=458",
|
|
1785
|
+
",jukcy=454,kappa=3ba,kappav=3f0,kcedil=137,kcy=43a,kfr=1d528,kgreen=138,khcy=445,kjcy=45c,kopf=1d55c",
|
|
1786
|
+
",kscr=1d4c0,lAarr=21da,lArr=21d0,lAtail=291b,lBarr=290e,lE=2266,lEg=2a8b,lHar=2962,lacute=13a,laempt",
|
|
1787
|
+
"yv=29b4,lagran=2112,lambda=3bb,lang=2329,langd=2991,langle=27e8,lap=2a85,laquo=ab,larr=2190,larrb=21",
|
|
1788
|
+
"e4,larrbfs=291f,larrfs=291d,larrhk=21a9,larrlp=21ab,larrpl=2939,larrsim=2973,larrtl=21a2,lat=2aab,la",
|
|
1789
|
+
"tail=2919,late=2aad,lates=2aad.fe00,lbarr=290c,lbbrk=2772,lbrace=7b,lbrack=5b,lbrke=298b,lbrksld=298",
|
|
1790
|
+
"f,lbrkslu=298d,lcaron=13e,lcedil=13c,lceil=2308,lcub=7b,lcy=43b,ldca=2936,ldquo=201c,ldquor=201e,ldr",
|
|
1791
|
+
"dhar=2967,ldrushar=294b,ldsh=21b2,le=2264,leftarrow=2190,leftarrowtail=21a2,leftharpoondown=21bd,lef",
|
|
1792
|
+
"tharpoonup=21bc,leftleftarrows=21c7,leftrightarrow=2194,leftrightarrows=21c6,leftrightharpoons=21cb,",
|
|
1793
|
+
"leftrightsquigarrow=21ad,leftthreetimes=22cb,leg=22da,leq=2264,leqq=2266,leqslant=2a7d,les=2a7d,lesc",
|
|
1794
|
+
"c=2aa8,lesdot=2a7f,lesdoto=2a81,lesdotor=2a83,lesg=22da.fe00,lesges=2a93,lessapprox=2a85,lessdot=22d",
|
|
1795
|
+
"6,lesseqgtr=22da,lesseqqgtr=2a8b,lessgtr=2276,lesssim=2272,lfisht=297c,lfloor=230a,lfr=1d529,lg=2276",
|
|
1796
|
+
",lgE=2a91,lhard=21bd,lharu=21bc,lharul=296a,lhblk=2584,ljcy=459,ll=226a,llarr=21c7,llcorner=231e,llh",
|
|
1797
|
+
"ard=296b,lltri=25fa,lmidot=140,lmoust=23b0,lmoustache=23b0,lnE=2268,lnap=2a89,lnapprox=2a89,lne=2a87",
|
|
1798
|
+
",lneq=2a87,lneqq=2268,lnsim=22e6,loang=27ec,loarr=21fd,lobrk=27e6,longleftarrow=27f5,longleftrightar",
|
|
1799
|
+
"row=27f7,longmapsto=27fc,longrightarrow=27f6,looparrowleft=21ab,looparrowright=21ac,lopar=2985,lopf=",
|
|
1800
|
+
"1d55d,loplus=2a2d,lotimes=2a34,lowast=2217,lowbar=5f,loz=25ca,lozenge=25ca,lozf=29eb,lpar=28,lparlt=",
|
|
1801
|
+
"2993,lrarr=21c6,lrcorner=231f,lrhar=21cb,lrhard=296d,lrm=200e,lrtri=22bf,lsaquo=2039,lscr=1d4c1,lsh=",
|
|
1802
|
+
"21b0,lsim=2272,lsime=2a8d,lsimg=2a8f,lsqb=5b,lsquo=2018,lsquor=201a,lstrok=142,lt=3c,ltcc=2aa6,ltcir",
|
|
1803
|
+
"=2a79,ltdot=22d6,lthree=22cb,ltimes=22c9,ltlarr=2976,ltquest=2a7b,ltrPar=2996,ltri=25c3,ltrie=22b4,l",
|
|
1804
|
+
"trif=25c2,lurdshar=294a,luruhar=2966,lvertneqq=2268.fe00,lvnE=2268.fe00,mDDot=223a,macr=af,male=2642",
|
|
1805
|
+
",malt=2720,maltese=2720,map=21a6,mapsto=21a6,mapstodown=21a7,mapstoleft=21a4,mapstoup=21a5,marker=25",
|
|
1806
|
+
"ae,mcomma=2a29,mcy=43c,mdash=2014,measuredangle=2221,mfr=1d52a,mho=2127,micro=b5,mid=2223,midast=2a,",
|
|
1807
|
+
"midcir=2af0,middot=b7,minus=2212,minusb=229f,minusd=2238,minusdu=2a2a,mlcp=2adb,mldr=2026,mnplus=221",
|
|
1808
|
+
"3,models=22a7,mopf=1d55e,mp=2213,mscr=1d4c2,mstpos=223e,mu=3bc,multimap=22b8,mumap=22b8,nGg=22d9.338",
|
|
1809
|
+
",nGt=226b.20d2,nGtv=226b.338,nLeftarrow=21cd,nLeftrightarrow=21ce,nLl=22d8.338,nLt=226a.20d2,nLtv=22",
|
|
1810
|
+
"6a.338,nRightarrow=21cf,nVDash=22af,nVdash=22ae,nabla=2207,nacute=144,nang=2220.20d2,nap=2249,napE=2",
|
|
1811
|
+
"a70.338,napid=224b.338,napos=149,napprox=2249,natur=266e,natural=266e,naturals=2115,nbsp=a0,nbump=22",
|
|
1812
|
+
"4e.338,nbumpe=224f.338,ncap=2a43,ncaron=148,ncedil=146,ncong=2247,ncongdot=2a6d.338,ncup=2a42,ncy=43",
|
|
1813
|
+
"d,ndash=2013,ne=2260,neArr=21d7,nearhk=2924,nearr=2197,nearrow=2197,nedot=2250.338,nequiv=2262,nesea",
|
|
1814
|
+
"r=2928,nesim=2242.338,nexist=2204,nexists=2204,nfr=1d52b,ngE=2267.338,nge=2271,ngeq=2271,ngeqq=2267.",
|
|
1815
|
+
"338,ngeqslant=2a7e.338,nges=2a7e.338,ngsim=2275,ngt=226f,ngtr=226f,nhArr=21ce,nharr=21ae,nhpar=2af2,",
|
|
1816
|
+
"ni=220b,nis=22fc,nisd=22fa,niv=220b,njcy=45a,nlArr=21cd,nlE=2266.338,nlarr=219a,nldr=2025,nle=2270,n",
|
|
1817
|
+
"leftarrow=219a,nleftrightarrow=21ae,nleq=2270,nleqq=2266.338,nleqslant=2a7d.338,nles=2a7d.338,nless=",
|
|
1818
|
+
"226e,nlsim=2274,nlt=226e,nltri=22ea,nltrie=22ec,nmid=2224,nopf=1d55f,not=ac,notin=2209,notinE=22f9.3",
|
|
1819
|
+
"38,notindot=22f5.338,notinva=2209,notinvb=22f7,notinvc=22f6,notni=220c,notniva=220c,notnivb=22fe,not",
|
|
1820
|
+
"nivc=22fd,npar=2226,nparallel=2226,nparsl=2afd.20e5,npart=2202.338,npolint=2a14,npr=2280,nprcue=22e0",
|
|
1821
|
+
",npre=2aaf.338,nprec=2280,npreceq=2aaf.338,nrArr=21cf,nrarr=219b,nrarrc=2933.338,nrarrw=219d.338,nri",
|
|
1822
|
+
"ghtarrow=219b,nrtri=22eb,nrtrie=22ed,nsc=2281,nsccue=22e1,nsce=2ab0.338,nscr=1d4c3,nshortmid=2224,ns",
|
|
1823
|
+
"hortparallel=2226,nsim=2241,nsime=2244,nsimeq=2244,nsmid=2224,nspar=2226,nsqsube=22e2,nsqsupe=22e3,n",
|
|
1824
|
+
"sub=2284,nsubE=2ac5.338,nsube=2288,nsubset=2282.20d2,nsubseteq=2288,nsubseteqq=2ac5.338,nsucc=2281,n",
|
|
1825
|
+
"succeq=2ab0.338,nsup=2285,nsupE=2ac6.338,nsupe=2289,nsupset=2283.20d2,nsupseteq=2289,nsupseteqq=2ac6",
|
|
1826
|
+
".338,ntgl=2279,ntilde=f1,ntlg=2278,ntriangleleft=22ea,ntrianglelefteq=22ec,ntriangleright=22eb,ntria",
|
|
1827
|
+
"nglerighteq=22ed,nu=3bd,num=23,numero=2116,numsp=2007,nvDash=22ad,nvHarr=2904,nvap=224d.20d2,nvdash=",
|
|
1828
|
+
"22ac,nvge=2265.20d2,nvgt=3e.20d2,nvinfin=29de,nvlArr=2902,nvle=2264.20d2,nvlt=3c.20d2,nvltrie=22b4.2",
|
|
1829
|
+
"0d2,nvrArr=2903,nvrtrie=22b5.20d2,nvsim=223c.20d2,nwArr=21d6,nwarhk=2923,nwarr=2196,nwarrow=2196,nwn",
|
|
1830
|
+
"ear=2927,oS=24c8,oacute=f3,oast=229b,ocir=229a,ocirc=f4,ocy=43e,odash=229d,odblac=151,odiv=2a38,odot",
|
|
1831
|
+
"=2299,odsold=29bc,oelig=153,ofcir=29bf,ofr=1d52c,ogon=2db,ograve=f2,ogt=29c1,ohbar=29b5,ohm=3a9,oint",
|
|
1832
|
+
"=222e,olarr=21ba,olcir=29be,olcross=29bb,oline=203e,olt=29c0,omacr=14d,omega=3c9,omicron=3bf,omid=29",
|
|
1833
|
+
"b6,ominus=2296,oopf=1d560,opar=29b7,operp=29b9,oplus=2295,or=2228,orarr=21bb,ord=2a5d,order=2134,ord",
|
|
1834
|
+
"erof=2134,ordf=aa,ordm=ba,origof=22b6,oror=2a56,orslope=2a57,orv=2a5b,oscr=2134,oslash=f8,osol=2298,",
|
|
1835
|
+
"otilde=f5,otimes=2297,otimesas=2a36,ouml=f6,ovbar=233d,par=2225,para=b6,parallel=2225,parsim=2af3,pa",
|
|
1836
|
+
"rsl=2afd,part=2202,pcy=43f,percnt=25,period=2e,permil=2030,perp=22a5,pertenk=2031,pfr=1d52d,phi=3c6,",
|
|
1837
|
+
"phiv=3d5,phmmat=2133,phone=260e,pi=3c0,pitchfork=22d4,piv=3d6,planck=210f,planckh=210e,plankv=210f,p",
|
|
1838
|
+
"lus=2b,plusacir=2a23,plusb=229e,pluscir=2a22,plusdo=2214,plusdu=2a25,pluse=2a72,plusmn=b1,plussim=2a",
|
|
1839
|
+
"26,plustwo=2a27,pm=b1,pointint=2a15,popf=1d561,pound=a3,pr=227a,prE=2ab3,prap=2ab7,prcue=227c,pre=2a",
|
|
1840
|
+
"af,prec=227a,precapprox=2ab7,preccurlyeq=227c,preceq=2aaf,precnapprox=2ab9,precneqq=2ab5,precnsim=22",
|
|
1841
|
+
"e8,precsim=227e,prime=2032,primes=2119,prnE=2ab5,prnap=2ab9,prnsim=22e8,prod=220f,profalar=232e,prof",
|
|
1842
|
+
"line=2312,profsurf=2313,prop=221d,propto=221d,prsim=227e,prurel=22b0,pscr=1d4c5,psi=3c8,puncsp=2008,",
|
|
1843
|
+
"qfr=1d52e,qint=2a0c,qopf=1d562,qprime=2057,qscr=1d4c6,quaternions=210d,quatint=2a16,quest=3f,questeq",
|
|
1844
|
+
"=225f,quot=22,rAarr=21db,rArr=21d2,rAtail=291c,rBarr=290f,rHar=2964,race=223d.331,racute=155,radic=2",
|
|
1845
|
+
"21a,raemptyv=29b3,rang=232a,rangd=2992,range=29a5,rangle=27e9,raquo=bb,rarr=2192,rarrap=2975,rarrb=2",
|
|
1846
|
+
"1e5,rarrbfs=2920,rarrc=2933,rarrfs=291e,rarrhk=21aa,rarrlp=21ac,rarrpl=2945,rarrsim=2974,rarrtl=21a3",
|
|
1847
|
+
",rarrw=219d,ratail=291a,ratio=2236,rationals=211a,rbarr=290d,rbbrk=2773,rbrace=7d,rbrack=5d,rbrke=29",
|
|
1848
|
+
"8c,rbrksld=298e,rbrkslu=2990,rcaron=159,rcedil=157,rceil=2309,rcub=7d,rcy=440,rdca=2937,rdldhar=2969",
|
|
1849
|
+
",rdquo=201d,rdquor=201d,rdsh=21b3,real=211c,realine=211b,realpart=211c,reals=211d,rect=25ad,reg=ae,r",
|
|
1850
|
+
"fisht=297d,rfloor=230b,rfr=1d52f,rhard=21c1,rharu=21c0,rharul=296c,rho=3c1,rhov=3f1,rightarrow=2192,",
|
|
1851
|
+
"rightarrowtail=21a3,rightharpoondown=21c1,rightharpoonup=21c0,rightleftarrows=21c4,rightleftharpoons",
|
|
1852
|
+
"=21cc,rightrightarrows=21c9,rightsquigarrow=219d,rightthreetimes=22cc,ring=2da,risingdotseq=2253,rla",
|
|
1853
|
+
"rr=21c4,rlhar=21cc,rlm=200f,rmoust=23b1,rmoustache=23b1,rnmid=2aee,roang=27ed,roarr=21fe,robrk=27e7,",
|
|
1854
|
+
"ropar=2986,ropf=1d563,roplus=2a2e,rotimes=2a35,rpar=29,rpargt=2994,rppolint=2a12,rrarr=21c9,rsaquo=2",
|
|
1855
|
+
"03a,rscr=1d4c7,rsh=21b1,rsqb=5d,rsquo=2019,rsquor=2019,rthree=22cc,rtimes=22ca,rtri=25b9,rtrie=22b5,",
|
|
1856
|
+
"rtrif=25b8,rtriltri=29ce,ruluhar=2968,rx=211e,sacute=15b,sbquo=201a,sc=227b,scE=2ab4,scap=2ab8,scaro",
|
|
1857
|
+
"n=161,sccue=227d,sce=2ab0,scedil=15f,scirc=15d,scnE=2ab6,scnap=2aba,scnsim=22e9,scpolint=2a13,scsim=",
|
|
1858
|
+
"227f,scy=441,sdot=22c5,sdotb=22a1,sdote=2a66,seArr=21d8,searhk=2925,searr=2198,searrow=2198,sect=a7,",
|
|
1859
|
+
"semi=3b,seswar=2929,setminus=2216,setmn=2216,sext=2736,sfr=1d530,sfrown=2322,sharp=266f,shchcy=449,s",
|
|
1860
|
+
"hcy=448,shortmid=2223,shortparallel=2225,shy=ad,sigma=3c3,sigmaf=3c2,sigmav=3c2,sim=223c,simdot=2a6a",
|
|
1861
|
+
",sime=2243,simeq=2243,simg=2a9e,simgE=2aa0,siml=2a9d,simlE=2a9f,simne=2246,simplus=2a24,simrarr=2972",
|
|
1862
|
+
",slarr=2190,smallsetminus=2216,smashp=2a33,smeparsl=29e4,smid=2223,smile=2323,smt=2aaa,smte=2aac,smt",
|
|
1863
|
+
"es=2aac.fe00,softcy=44c,sol=2f,solb=29c4,solbar=233f,sopf=1d564,spades=2660,spadesuit=2660,spar=2225",
|
|
1864
|
+
",sqcap=2293,sqcaps=2293.fe00,sqcup=2294,sqcups=2294.fe00,sqsub=228f,sqsube=2291,sqsubset=228f,sqsubs",
|
|
1865
|
+
"eteq=2291,sqsup=2290,sqsupe=2292,sqsupset=2290,sqsupseteq=2292,squ=25a1,square=25a1,squarf=25aa,squf",
|
|
1866
|
+
"=25aa,srarr=2192,sscr=1d4c8,ssetmn=2216,ssmile=2323,sstarf=22c6,star=2606,starf=2605,straightepsilon",
|
|
1867
|
+
"=3f5,straightphi=3d5,strns=af,sub=2282,subE=2ac5,subdot=2abd,sube=2286,subedot=2ac3,submult=2ac1,sub",
|
|
1868
|
+
"nE=2acb,subne=228a,subplus=2abf,subrarr=2979,subset=2282,subseteq=2286,subseteqq=2ac5,subsetneq=228a",
|
|
1869
|
+
",subsetneqq=2acb,subsim=2ac7,subsub=2ad5,subsup=2ad3,succ=227b,succapprox=2ab8,succcurlyeq=227d,succ",
|
|
1870
|
+
"eq=2ab0,succnapprox=2aba,succneqq=2ab6,succnsim=22e9,succsim=227f,sum=2211,sung=266a,sup=2283,sup1=b",
|
|
1871
|
+
"9,sup2=b2,sup3=b3,supE=2ac6,supdot=2abe,supdsub=2ad8,supe=2287,supedot=2ac4,suphsol=27c9,suphsub=2ad",
|
|
1872
|
+
"7,suplarr=297b,supmult=2ac2,supnE=2acc,supne=228b,supplus=2ac0,supset=2283,supseteq=2287,supseteqq=2",
|
|
1873
|
+
"ac6,supsetneq=228b,supsetneqq=2acc,supsim=2ac8,supsub=2ad4,supsup=2ad6,swArr=21d9,swarhk=2926,swarr=",
|
|
1874
|
+
"2199,swarrow=2199,swnwar=292a,szlig=df,target=2316,tau=3c4,tbrk=23b4,tcaron=165,tcedil=163,tcy=442,t",
|
|
1875
|
+
"dot=20db,telrec=2315,tfr=1d531,there4=2234,therefore=2234,theta=3b8,thetasym=3d1,thetav=3d1,thickapp",
|
|
1876
|
+
"rox=2248,thicksim=223c,thinsp=2009,thkap=2248,thksim=223c,thorn=fe,tilde=2dc,times=d7,timesb=22a0,ti",
|
|
1877
|
+
"mesbar=2a31,timesd=2a30,tint=222d,toea=2928,top=22a4,topbot=2336,topcir=2af1,topf=1d565,topfork=2ada",
|
|
1878
|
+
",tosa=2929,tprime=2034,trade=2122,triangle=25b5,triangledown=25bf,triangleleft=25c3,trianglelefteq=2",
|
|
1879
|
+
"2b4,triangleq=225c,triangleright=25b9,trianglerighteq=22b5,tridot=25ec,trie=225c,triminus=2a3a,tripl",
|
|
1880
|
+
"us=2a39,trisb=29cd,tritime=2a3b,trpezium=23e2,tscr=1d4c9,tscy=446,tshcy=45b,tstrok=167,twixt=226c,tw",
|
|
1881
|
+
"oheadleftarrow=219e,twoheadrightarrow=21a0,uArr=21d1,uHar=2963,uacute=fa,uarr=2191,ubrcy=45e,ubreve=",
|
|
1882
|
+
"16d,ucirc=fb,ucy=443,udarr=21c5,udblac=171,udhar=296e,ufisht=297e,ufr=1d532,ugrave=f9,uharl=21bf,uha",
|
|
1883
|
+
"rr=21be,uhblk=2580,ulcorn=231c,ulcorner=231c,ulcrop=230f,ultri=25f8,umacr=16b,uml=a8,uogon=173,uopf=",
|
|
1884
|
+
"1d566,uparrow=2191,updownarrow=2195,upharpoonleft=21bf,upharpoonright=21be,uplus=228e,upsi=3c5,upsih",
|
|
1885
|
+
"=3d2,upsilon=3c5,upuparrows=21c8,urcorn=231d,urcorner=231d,urcrop=230e,uring=16f,urtri=25f9,uscr=1d4",
|
|
1886
|
+
"ca,utdot=22f0,utilde=169,utri=25b5,utrif=25b4,uuarr=21c8,uuml=fc,uwangle=29a7,vArr=21d5,vBar=2ae8,vB",
|
|
1887
|
+
"arv=2ae9,vDash=22a8,vangrt=299c,varepsilon=3f5,varkappa=3f0,varnothing=2205,varphi=3d5,varpi=3d6,var",
|
|
1888
|
+
"propto=221d,varr=2195,varrho=3f1,varsigma=3c2,varsubsetneq=228a.fe00,varsubsetneqq=2acb.fe00,varsups",
|
|
1889
|
+
"etneq=228b.fe00,varsupsetneqq=2acc.fe00,vartheta=3d1,vartriangleleft=22b2,vartriangleright=22b3,vcy=",
|
|
1890
|
+
"432,vdash=22a2,vee=2228,veebar=22bb,veeeq=225a,vellip=22ee,verbar=7c,vert=7c,vfr=1d533,vltri=22b2,vn",
|
|
1891
|
+
"sub=2282.20d2,vnsup=2283.20d2,vopf=1d567,vprop=221d,vrtri=22b3,vscr=1d4cb,vsubnE=2acb.fe00,vsubne=22",
|
|
1892
|
+
"8a.fe00,vsupnE=2acc.fe00,vsupne=228b.fe00,vzigzag=299a,wcirc=175,wedbar=2a5f,wedge=2227,wedgeq=2259,",
|
|
1893
|
+
"weierp=2118,wfr=1d534,wopf=1d568,wp=2118,wr=2240,wreath=2240,wscr=1d4cc,xcap=22c2,xcirc=25ef,xcup=22",
|
|
1894
|
+
"c3,xdtri=25bd,xfr=1d535,xhArr=27fa,xharr=27f7,xi=3be,xlArr=27f8,xlarr=27f5,xmap=27fc,xnis=22fb,xodot",
|
|
1895
|
+
"=2a00,xopf=1d569,xoplus=2a01,xotime=2a02,xrArr=27f9,xrarr=27f6,xscr=1d4cd,xsqcup=2a06,xuplus=2a04,xu",
|
|
1896
|
+
"tri=25b3,xvee=22c1,xwedge=22c0,yacute=fd,yacy=44f,ycirc=177,ycy=44b,yen=a5,yfr=1d536,yicy=457,yopf=1",
|
|
1897
|
+
"d56a,yscr=1d4ce,yucy=44e,yuml=ff,zacute=17a,zcaron=17e,zcy=437,zdot=17c,zeetrf=2128,zeta=3b6,zfr=1d5",
|
|
1898
|
+
"37,zhcy=436,zigrarr=21dd,zopf=1d56b,zscr=1d4cf,zwj=200d,zwnj=200c"
|
|
1899
|
+
].join("");
|
|
1900
|
+
NAMED_REFERENCES = new Map(NAMED.split(",").map((entry) => {
|
|
1901
|
+
const [name, codes] = entry.split("=");
|
|
1902
|
+
return [name, String.fromCodePoint(...codes.split(".").map((code) => Number.parseInt(code, 16)))];
|
|
1903
|
+
}));
|
|
1904
|
+
}
|
|
1905
|
+
});
|
|
1906
|
+
|
|
1627
1907
|
// src/html.js
|
|
1628
1908
|
function fromCode(code) {
|
|
1629
1909
|
if (code === 0 || code > 1114111 || code >= 55296 && code <= 57343) {
|
|
@@ -1640,8 +1920,8 @@ function decodeEntities(value, { attribute = false } = {}) {
|
|
|
1640
1920
|
if (hex !== void 0 || decimal !== void 0) {
|
|
1641
1921
|
return fromCode(hex === void 0 ? Number.parseInt(decimal, 10) : Number.parseInt(hex, 16));
|
|
1642
1922
|
}
|
|
1643
|
-
if (semicolon &&
|
|
1644
|
-
return
|
|
1923
|
+
if (semicolon && NAMED_REFERENCES.has(name)) {
|
|
1924
|
+
return NAMED_REFERENCES.get(name);
|
|
1645
1925
|
}
|
|
1646
1926
|
let legacy;
|
|
1647
1927
|
for (let length = Math.min(name.length, LEGACY_LONGEST); length >= 2 && legacy === void 0; length--) {
|
|
@@ -1655,7 +1935,7 @@ function decodeEntities(value, { attribute = false } = {}) {
|
|
|
1655
1935
|
if (attribute && /[\da-zA-Z=]/.test(next)) {
|
|
1656
1936
|
return match;
|
|
1657
1937
|
}
|
|
1658
|
-
return
|
|
1938
|
+
return NAMED_REFERENCES.get(legacy) + rest;
|
|
1659
1939
|
});
|
|
1660
1940
|
}
|
|
1661
1941
|
function readTag(html2, start) {
|
|
@@ -2296,106 +2576,14 @@ function visibleText(html2) {
|
|
|
2296
2576
|
}
|
|
2297
2577
|
return { text: parts.join(""), hidden };
|
|
2298
2578
|
}
|
|
2299
|
-
var LATIN1,
|
|
2579
|
+
var LATIN1, LEGACY, LEGACY_LONGEST, WINDOWS_1252, REFERENCE, UNSHOWN, RAW_SHOWN, RAW_END, BREAKS, SPECIAL, SCOPE, FORMATTING, LINE, OWN_PLACE, VOID, CLOSES_PARAGRAPH, PARAGRAPH, IMPLIED, TABLE_PARTS, TABLE_BOXES, HEADINGS, IMPLIED_END, PARTS_OF_TABLE, TABLE_STRUCTURE, IN_TABLE, MAX_FORMATTING, MARKERS, FOSTERED_MARKERS, NOT_REOPENING, LEAVES_FOREIGN, HOLDS_HTML, SVG_UNSHOWN, MAX_OPEN, MAX_ATTRIBUTES, MAX_STYLE, COMMENT_END, WHITESPACE2, NO_WORD_ATTRIBUTES, FIELDS, FIELD_HELP, HINTS, MAX_HELP, LABEL_END, isHelp, MAX_VALUE, LENGTH, UNITS, SIZE_KEYWORDS, ZERO_NUMBER, DISPLAY_INLINE, DISPLAY_BLOCK, isZero, declarationCache, ROOT, DOCTYPE, QUIRKS_PUBLIC, QUIRKS_IF_NO_SYSTEM;
|
|
2300
2580
|
var init_html = __esm({
|
|
2301
2581
|
"src/html.js"() {
|
|
2582
|
+
init_entities();
|
|
2302
2583
|
init_linear();
|
|
2303
2584
|
LATIN1 = "nbsp iexcl cent pound curren yen brvbar sect uml copy ordf laquo not shy reg macr deg plusmn sup2 sup3 acute micro para middot cedil sup1 ordm raquo frac14 frac12 frac34 iquest Agrave Aacute Acirc Atilde Auml Aring AElig Ccedil Egrave Eacute Ecirc Euml Igrave Iacute Icirc Iuml ETH Ntilde Ograve Oacute Ocirc Otilde Ouml times Oslash Ugrave Uacute Ucirc Uuml Yacute THORN szlig agrave aacute acirc atilde auml aring aelig ccedil egrave eacute ecirc euml igrave iacute icirc iuml eth ntilde ograve oacute ocirc otilde ouml divide oslash ugrave uacute ucirc uuml yacute thorn yuml".split(" ");
|
|
2304
|
-
ENTITIES = new Map([
|
|
2305
|
-
...LATIN1.map((name, index) => [name, String.fromCodePoint(160 + index)]),
|
|
2306
|
-
["amp", "&"],
|
|
2307
|
-
["lt", "<"],
|
|
2308
|
-
["gt", ">"],
|
|
2309
|
-
["quot", '"'],
|
|
2310
|
-
["apos", "'"],
|
|
2311
|
-
["AMP", "&"],
|
|
2312
|
-
["LT", "<"],
|
|
2313
|
-
["GT", ">"],
|
|
2314
|
-
["QUOT", '"'],
|
|
2315
|
-
["COPY", "\xA9"],
|
|
2316
|
-
["REG", "\xAE"],
|
|
2317
|
-
["OElig", "\u0152"],
|
|
2318
|
-
["oelig", "\u0153"],
|
|
2319
|
-
["Scaron", "\u0160"],
|
|
2320
|
-
["scaron", "\u0161"],
|
|
2321
|
-
["Yuml", "\u0178"],
|
|
2322
|
-
["fnof", "\u0192"],
|
|
2323
|
-
["circ", "\u02C6"],
|
|
2324
|
-
["tilde", "\u02DC"],
|
|
2325
|
-
["ensp", "\u2002"],
|
|
2326
|
-
["emsp", "\u2003"],
|
|
2327
|
-
["thinsp", "\u2009"],
|
|
2328
|
-
["zwnj", "\u200C"],
|
|
2329
|
-
["zwj", "\u200D"],
|
|
2330
|
-
["lrm", "\u200E"],
|
|
2331
|
-
["rlm", "\u200F"],
|
|
2332
|
-
["ndash", "\u2013"],
|
|
2333
|
-
["mdash", "\u2014"],
|
|
2334
|
-
["lsquo", "\u2018"],
|
|
2335
|
-
["rsquo", "\u2019"],
|
|
2336
|
-
["sbquo", "\u201A"],
|
|
2337
|
-
["ldquo", "\u201C"],
|
|
2338
|
-
["rdquo", "\u201D"],
|
|
2339
|
-
["bdquo", "\u201E"],
|
|
2340
|
-
["dagger", "\u2020"],
|
|
2341
|
-
["Dagger", "\u2021"],
|
|
2342
|
-
["bull", "\u2022"],
|
|
2343
|
-
["hellip", "\u2026"],
|
|
2344
|
-
["permil", "\u2030"],
|
|
2345
|
-
["prime", "\u2032"],
|
|
2346
|
-
["Prime", "\u2033"],
|
|
2347
|
-
["lsaquo", "\u2039"],
|
|
2348
|
-
["rsaquo", "\u203A"],
|
|
2349
|
-
["euro", "\u20AC"],
|
|
2350
|
-
["trade", "\u2122"],
|
|
2351
|
-
["larr", "\u2190"],
|
|
2352
|
-
["uarr", "\u2191"],
|
|
2353
|
-
["rarr", "\u2192"],
|
|
2354
|
-
["darr", "\u2193"],
|
|
2355
|
-
["hearts", "\u2665"],
|
|
2356
|
-
["check", "\u2713"],
|
|
2357
|
-
// The punctuation of a web address, as browsers read these names
|
|
2358
|
-
// ("https://bank.example@evil.example/" goes to evil.example)
|
|
2359
|
-
["Tab", " "],
|
|
2360
|
-
["NewLine", "\n"],
|
|
2361
|
-
["excl", "!"],
|
|
2362
|
-
["num", "#"],
|
|
2363
|
-
["dollar", "$"],
|
|
2364
|
-
["percnt", "%"],
|
|
2365
|
-
["lpar", "("],
|
|
2366
|
-
["rpar", ")"],
|
|
2367
|
-
["ast", "*"],
|
|
2368
|
-
["midast", "*"],
|
|
2369
|
-
["plus", "+"],
|
|
2370
|
-
["comma", ","],
|
|
2371
|
-
["period", "."],
|
|
2372
|
-
["sol", "/"],
|
|
2373
|
-
["colon", ":"],
|
|
2374
|
-
["semi", ";"],
|
|
2375
|
-
["equals", "="],
|
|
2376
|
-
["quest", "?"],
|
|
2377
|
-
["commat", "@"],
|
|
2378
|
-
["lsqb", "["],
|
|
2379
|
-
["lbrack", "["],
|
|
2380
|
-
["bsol", "\\"],
|
|
2381
|
-
["rsqb", "]"],
|
|
2382
|
-
["rbrack", "]"],
|
|
2383
|
-
["Hat", "^"],
|
|
2384
|
-
["lowbar", "_"],
|
|
2385
|
-
["UnderBar", "_"],
|
|
2386
|
-
["grave", "`"],
|
|
2387
|
-
["DiacriticalGrave", "`"],
|
|
2388
|
-
["lcub", "{"],
|
|
2389
|
-
["lbrace", "{"],
|
|
2390
|
-
["verbar", "|"],
|
|
2391
|
-
["vert", "|"],
|
|
2392
|
-
["VerticalLine", "|"],
|
|
2393
|
-
["rcub", "}"],
|
|
2394
|
-
["rbrace", "}"]
|
|
2395
|
-
]);
|
|
2396
2585
|
LEGACY = /* @__PURE__ */ new Set([...LATIN1, "amp", "lt", "gt", "quot", "AMP", "LT", "GT", "QUOT", "COPY", "REG"]);
|
|
2397
2586
|
LEGACY_LONGEST = Math.max(...[...LEGACY].map((name) => name.length));
|
|
2398
|
-
LONGER_NAMES = new Set("centerdot copysr divideontimes gtcc gtcir gtdot gtlPar gtquest gtrapprox gtrarr gtrdot gtreqless gtreqqless gtrless gtrsim ltcc ltcir ltdot lthree ltimes ltlarr ltquest ltrPar ltri ltrie ltrif notin notinE notindot notinva notinvb notinvc notni notniva notnivb notnivc parallel timesb timesbar timesd".split(" "));
|
|
2399
2587
|
WINDOWS_1252 = [8364, 129, 8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249, 338, 141, 381, 143, 144, 8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, 8482, 353, 8250, 339, 157, 382, 376];
|
|
2400
2588
|
REFERENCE = /&(?:#([xX])([\da-fA-F]+)|#(\d+)|([a-zA-Z][a-zA-Z\d]{0,31}))(;?)/g;
|
|
2401
2589
|
UNSHOWN = /* @__PURE__ */ new Set(["script", "style", "title", "noembed", "noframes", "iframe"]);
|
|
@@ -2790,7 +2978,7 @@ function endsInsideTag(html2, end, link) {
|
|
|
2790
2978
|
const joined = trimEndOf(link.replace(/^https?:\/\//i, "") + after, ".-");
|
|
2791
2979
|
return joined !== host && (!isHost(host) || isHost(joined) && registrableDomain(joined) !== registrableDomain(host));
|
|
2792
2980
|
}
|
|
2793
|
-
function extractLinks(text, html2, { maxLength = 5e5, bareHosts = false } = {}) {
|
|
2981
|
+
function extractLinks(text, html2, { maxLength = 5e5, bareHosts: bareHosts2 = false } = {}) {
|
|
2794
2982
|
text = typeof text === "string" ? foldToAscii(text) : text;
|
|
2795
2983
|
html2 = typeof html2 === "string" ? foldToAscii(html2) : html2;
|
|
2796
2984
|
const links = [];
|
|
@@ -2857,7 +3045,7 @@ ${shown || ""}`;
|
|
|
2857
3045
|
}
|
|
2858
3046
|
add(link);
|
|
2859
3047
|
}
|
|
2860
|
-
if (
|
|
3048
|
+
if (bareHosts2 && index < 2) {
|
|
2861
3049
|
bareLinkHosts(read, (host) => {
|
|
2862
3050
|
bareFound.push(host);
|
|
2863
3051
|
});
|
|
@@ -3797,7 +3985,16 @@ function shorten(name, max = 100) {
|
|
|
3797
3985
|
return characters.length <= max ? name : `${characters.slice(0, max - 41).join("")}\u2026${characters.slice(-40).join("")}`;
|
|
3798
3986
|
}
|
|
3799
3987
|
function extensionOf(name) {
|
|
3800
|
-
const base = trimEndOf(String(name).toLowerCase().split(/[/\\]/).pop(), ". ");
|
|
3988
|
+
const base = trimEndOf(String(name).toLowerCase().replace(ALL_BIDI_CONTROLS, "").split(/[/\\]/).pop(), ". ");
|
|
3989
|
+
const whole = lastExtension(base);
|
|
3990
|
+
const file = base.replace(/^[a-z]:/, "");
|
|
3991
|
+
const colon = file.indexOf(":");
|
|
3992
|
+
if (colon !== -1 && /^(?::?\$data)?$/.test(file.slice(colon + 1))) {
|
|
3993
|
+
return lastExtension(trimEndOf(file.slice(0, colon), ". "));
|
|
3994
|
+
}
|
|
3995
|
+
return whole;
|
|
3996
|
+
}
|
|
3997
|
+
function lastExtension(base) {
|
|
3801
3998
|
const dot = base.lastIndexOf(".");
|
|
3802
3999
|
return dot === -1 ? "" : base.slice(dot + 1).trim();
|
|
3803
4000
|
}
|
|
@@ -3882,7 +4079,7 @@ function inspectAttachments(attachments = []) {
|
|
|
3882
4079
|
}
|
|
3883
4080
|
return findings;
|
|
3884
4081
|
}
|
|
3885
|
-
var import_node_buffer, EXECUTABLE_EXTENSIONS, RISKY_EXTENSIONS, SCRIPT_EXTENSIONS, MACRO_EXTENSIONS, DOCUMENT_EXTENSIONS, TEMPORARY_EXTENSIONS, BIDI_CONTROLS, ARCHIVE_TYPES, ZIP_FAMILY, OFFICE_TYPES, OFFICE_EMBEDDED, ENTRIES, MAX_NAME_LENGTH, MAX_NAME_BYTES, DIRECTORY, isDirectory, VBA_NAMES, PDF_ACTIVE, escaped, WORD_ESCAPE, PDF_ACTIVE_ESCAPED, pdfActive;
|
|
4082
|
+
var import_node_buffer, EXECUTABLE_EXTENSIONS, RISKY_EXTENSIONS, SCRIPT_EXTENSIONS, MACRO_EXTENSIONS, DOCUMENT_EXTENSIONS, TEMPORARY_EXTENSIONS, BIDI_CONTROLS, ALL_BIDI_CONTROLS, ARCHIVE_TYPES, ZIP_FAMILY, OFFICE_TYPES, OFFICE_EMBEDDED, ENTRIES, MAX_NAME_LENGTH, MAX_NAME_BYTES, DIRECTORY, isDirectory, VBA_NAMES, PDF_ACTIVE, escaped, WORD_ESCAPE, PDF_ACTIVE_ESCAPED, pdfActive;
|
|
3886
4083
|
var init_attachments = __esm({
|
|
3887
4084
|
"src/attachments.js"() {
|
|
3888
4085
|
import_node_buffer = require("node:buffer");
|
|
@@ -4033,6 +4230,7 @@ var init_attachments = __esm({
|
|
|
4033
4230
|
DOCUMENT_EXTENSIONS = /* @__PURE__ */ new Set(["pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "rtf", "jpg", "jpeg", "png", "gif", "zip", "csv", "odt", "ods", "html", "htm", "mp3", "mp4", "mov", "wav", "eml", "msg", "xml", "json"]);
|
|
4034
4231
|
TEMPORARY_EXTENSIONS = /* @__PURE__ */ new Set(["tmp"]);
|
|
4035
4232
|
BIDI_CONTROLS = characterClass([[8234, 8238], [8294, 8297]], "u");
|
|
4233
|
+
ALL_BIDI_CONTROLS = characterClass([[8234, 8238], [8294, 8297]], "gu");
|
|
4036
4234
|
ARCHIVE_TYPES = /* @__PURE__ */ new Set(["zip", "rar", "7z", "gz", "bz2", "xz", "cab", "iso", "tar", "zst", "lzh", "ace", "arj"]);
|
|
4037
4235
|
ZIP_FAMILY = /* @__PURE__ */ new Set(["zip", "docx", "xlsx", "pptx"]);
|
|
4038
4236
|
OFFICE_TYPES = /* @__PURE__ */ new Set(["docx", "xlsx", "pptx"]);
|
|
@@ -4413,7 +4611,8 @@ async function parseWithin(raw, parse = parseMessage, deadline = Date.now() + PA
|
|
|
4413
4611
|
}
|
|
4414
4612
|
}
|
|
4415
4613
|
}
|
|
4416
|
-
async function expandAttachments(attachments = [], errors = [], parse = parseMessage,
|
|
4614
|
+
async function expandAttachments(attachments = [], errors = [], parse = parseMessage, gets = {}) {
|
|
4615
|
+
const { unopened = [], mails = [] } = Array.isArray(gets) ? { unopened: gets } : gets;
|
|
4417
4616
|
const all = [];
|
|
4418
4617
|
const deadline = Date.now() + PARSE_TIMEOUT;
|
|
4419
4618
|
let budget = MAX_NESTED_BYTES;
|
|
@@ -4462,6 +4661,7 @@ async function expandAttachments(attachments = [], errors = [], parse = parseMes
|
|
|
4462
4661
|
if (inner.error) {
|
|
4463
4662
|
errors.push(inner.error);
|
|
4464
4663
|
}
|
|
4664
|
+
mails.push(inner.mail);
|
|
4465
4665
|
await visit(inner.mail.attachments, prefix ? `${prefix}/${name}` : name || "attached message", depth + 1);
|
|
4466
4666
|
}
|
|
4467
4667
|
}
|
|
@@ -6005,6 +6205,924 @@ var init_classifier = __esm({
|
|
|
6005
6205
|
}
|
|
6006
6206
|
});
|
|
6007
6207
|
|
|
6208
|
+
// src/links.js
|
|
6209
|
+
function isHostCode2(code) {
|
|
6210
|
+
return code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 48 && code <= 57 || code === 45 || code === 46;
|
|
6211
|
+
}
|
|
6212
|
+
function isSpace(code) {
|
|
6213
|
+
return code === 32 || code >= 9 && code <= 13;
|
|
6214
|
+
}
|
|
6215
|
+
function urlOf(value) {
|
|
6216
|
+
let href = value.replaceAll(/[\t\n\r]/g, "");
|
|
6217
|
+
let start = 0;
|
|
6218
|
+
let end = href.length;
|
|
6219
|
+
while (start < end && href.codePointAt(start) <= 32) {
|
|
6220
|
+
start++;
|
|
6221
|
+
}
|
|
6222
|
+
while (end > start && href.codePointAt(end - 1) <= 32) {
|
|
6223
|
+
end--;
|
|
6224
|
+
}
|
|
6225
|
+
while (end > start && TRAILING.has(href[end - 1])) {
|
|
6226
|
+
end--;
|
|
6227
|
+
}
|
|
6228
|
+
href = href.slice(start, end);
|
|
6229
|
+
if (/^[\\/]{2}/.test(href)) {
|
|
6230
|
+
href = `https://${href.slice(2)}`;
|
|
6231
|
+
} else if (/^www\./i.test(href)) {
|
|
6232
|
+
href = `http://${href}`;
|
|
6233
|
+
} else if (!/^https?:/i.test(href)) {
|
|
6234
|
+
return null;
|
|
6235
|
+
}
|
|
6236
|
+
try {
|
|
6237
|
+
return new URL(href);
|
|
6238
|
+
} catch {
|
|
6239
|
+
return null;
|
|
6240
|
+
}
|
|
6241
|
+
}
|
|
6242
|
+
function hostOfUrl(url) {
|
|
6243
|
+
let host = url.hostname.toLowerCase();
|
|
6244
|
+
let dots = host.length;
|
|
6245
|
+
while (dots > 0 && host[dots - 1] === ".") {
|
|
6246
|
+
dots--;
|
|
6247
|
+
}
|
|
6248
|
+
host = host.slice(0, dots);
|
|
6249
|
+
if (host.startsWith("[") && host.endsWith("]")) {
|
|
6250
|
+
host = host.slice(1, -1);
|
|
6251
|
+
}
|
|
6252
|
+
if (!host || NAMESPACES.has(host)) {
|
|
6253
|
+
return null;
|
|
6254
|
+
}
|
|
6255
|
+
return (0, import_node_net4.isIP)(host) ? host : lookupName(host);
|
|
6256
|
+
}
|
|
6257
|
+
function hostsOf(value) {
|
|
6258
|
+
const url = urlOf(value);
|
|
6259
|
+
if (!url) {
|
|
6260
|
+
return [];
|
|
6261
|
+
}
|
|
6262
|
+
const host = hostOfUrl(url);
|
|
6263
|
+
const hosts = host ? [host] : [];
|
|
6264
|
+
const target = unwrapLink(url.href);
|
|
6265
|
+
if (target && target.href !== url.href) {
|
|
6266
|
+
const targetHost = hostOfUrl(target);
|
|
6267
|
+
if (targetHost && targetHost !== host) {
|
|
6268
|
+
hosts.push(targetHost);
|
|
6269
|
+
}
|
|
6270
|
+
const further = unwrapLink(target.href);
|
|
6271
|
+
if (further && further.href !== target.href) {
|
|
6272
|
+
hosts.unresolved = true;
|
|
6273
|
+
}
|
|
6274
|
+
}
|
|
6275
|
+
return hosts;
|
|
6276
|
+
}
|
|
6277
|
+
function* attributesOf(html2) {
|
|
6278
|
+
TAG_START.lastIndex = 0;
|
|
6279
|
+
let match;
|
|
6280
|
+
while ((match = TAG_START.exec(html2)) !== null) {
|
|
6281
|
+
let i = match.index + match[0].length;
|
|
6282
|
+
while (i < html2.length && html2[i] !== ">") {
|
|
6283
|
+
if (isSpace(html2.codePointAt(i)) || html2[i] === "/") {
|
|
6284
|
+
i++;
|
|
6285
|
+
continue;
|
|
6286
|
+
}
|
|
6287
|
+
let j = i;
|
|
6288
|
+
while (j < html2.length && html2[j] !== "=" && html2[j] !== ">" && html2[j] !== "/" && !isSpace(html2.codePointAt(j))) {
|
|
6289
|
+
j++;
|
|
6290
|
+
}
|
|
6291
|
+
const name = html2.slice(i, j).toLowerCase();
|
|
6292
|
+
if (j === i) {
|
|
6293
|
+
j++;
|
|
6294
|
+
}
|
|
6295
|
+
while (j < html2.length && isSpace(html2.codePointAt(j))) {
|
|
6296
|
+
j++;
|
|
6297
|
+
}
|
|
6298
|
+
if (html2[j] !== "=") {
|
|
6299
|
+
i = j;
|
|
6300
|
+
continue;
|
|
6301
|
+
}
|
|
6302
|
+
j++;
|
|
6303
|
+
while (j < html2.length && isSpace(html2.codePointAt(j))) {
|
|
6304
|
+
j++;
|
|
6305
|
+
}
|
|
6306
|
+
let value;
|
|
6307
|
+
if (html2[j] === '"' || html2[j] === "'") {
|
|
6308
|
+
const close = html2.indexOf(html2[j], j + 1);
|
|
6309
|
+
const stop = close === -1 ? html2.length : close;
|
|
6310
|
+
value = html2.slice(j + 1, stop);
|
|
6311
|
+
j = stop + 1;
|
|
6312
|
+
} else {
|
|
6313
|
+
const start = j;
|
|
6314
|
+
while (j < html2.length && html2[j] !== ">" && !isSpace(html2.codePointAt(j))) {
|
|
6315
|
+
j++;
|
|
6316
|
+
}
|
|
6317
|
+
value = html2.slice(start, j);
|
|
6318
|
+
}
|
|
6319
|
+
if (name) {
|
|
6320
|
+
yield [name, value];
|
|
6321
|
+
}
|
|
6322
|
+
i = j;
|
|
6323
|
+
}
|
|
6324
|
+
TAG_START.lastIndex = Math.max(i, match.index + 1);
|
|
6325
|
+
}
|
|
6326
|
+
}
|
|
6327
|
+
function linksOf(name, value, add, embed) {
|
|
6328
|
+
const decoded = decodeEntities(value, { attribute: true });
|
|
6329
|
+
switch (name) {
|
|
6330
|
+
case "srcdoc": {
|
|
6331
|
+
embed(decoded);
|
|
6332
|
+
break;
|
|
6333
|
+
}
|
|
6334
|
+
case "style": {
|
|
6335
|
+
for (const [, link] of decoded.matchAll(CSS_URL)) {
|
|
6336
|
+
add(link);
|
|
6337
|
+
}
|
|
6338
|
+
break;
|
|
6339
|
+
}
|
|
6340
|
+
case "srcset": {
|
|
6341
|
+
for (const candidate of decoded.split(",")) {
|
|
6342
|
+
add(candidate.trim().split(/\s/, 1)[0]);
|
|
6343
|
+
}
|
|
6344
|
+
break;
|
|
6345
|
+
}
|
|
6346
|
+
// (several, separated by spaces)
|
|
6347
|
+
case "ping": {
|
|
6348
|
+
for (const link of decoded.split(/\s+/)) {
|
|
6349
|
+
add(link);
|
|
6350
|
+
}
|
|
6351
|
+
break;
|
|
6352
|
+
}
|
|
6353
|
+
// (only the address of a refresh)
|
|
6354
|
+
case "content": {
|
|
6355
|
+
const match = /(?:^|[\s;,])url\s*=\s*["']?([^\s"';]+)/i.exec(decoded.slice(0, 4096));
|
|
6356
|
+
if (match) {
|
|
6357
|
+
add(match[1]);
|
|
6358
|
+
}
|
|
6359
|
+
break;
|
|
6360
|
+
}
|
|
6361
|
+
default: {
|
|
6362
|
+
add(decoded);
|
|
6363
|
+
}
|
|
6364
|
+
}
|
|
6365
|
+
}
|
|
6366
|
+
function lenientLinks(html2, add, done, embed) {
|
|
6367
|
+
LENIENT.lastIndex = 0;
|
|
6368
|
+
let match;
|
|
6369
|
+
while (!done() && (match = LENIENT.exec(html2)) !== null) {
|
|
6370
|
+
const name = match[1].toLowerCase();
|
|
6371
|
+
let i = LENIENT.lastIndex;
|
|
6372
|
+
let end = i;
|
|
6373
|
+
if (html2[i] === '"' || html2[i] === "'") {
|
|
6374
|
+
const quote = html2[i];
|
|
6375
|
+
i++;
|
|
6376
|
+
end = i;
|
|
6377
|
+
while (end < html2.length && html2[end] !== quote && html2[end] !== "<" && html2[end] !== ">") {
|
|
6378
|
+
end++;
|
|
6379
|
+
}
|
|
6380
|
+
if (end < html2.length && html2[end] !== quote) {
|
|
6381
|
+
const close = html2.indexOf(quote, end);
|
|
6382
|
+
if (close !== -1 && close - i <= MAX_LENIENT_VALUE) {
|
|
6383
|
+
linksOf(name, html2.slice(i, close), add, embed);
|
|
6384
|
+
}
|
|
6385
|
+
}
|
|
6386
|
+
} else {
|
|
6387
|
+
while (end < html2.length && !isSpace(html2.codePointAt(end)) && !UNQUOTED_END.has(html2[end])) {
|
|
6388
|
+
end++;
|
|
6389
|
+
}
|
|
6390
|
+
}
|
|
6391
|
+
linksOf(name, html2.slice(i, end), add, embed);
|
|
6392
|
+
}
|
|
6393
|
+
}
|
|
6394
|
+
function endsLink2(text, i) {
|
|
6395
|
+
const code = text.codePointAt(i);
|
|
6396
|
+
if (code < 128) {
|
|
6397
|
+
return isSpace(code) || code === 34 || code === 39 || code === 60 || code === 62 || code === 96;
|
|
6398
|
+
}
|
|
6399
|
+
return /\s/u.test(text[i]);
|
|
6400
|
+
}
|
|
6401
|
+
function linkReader(text) {
|
|
6402
|
+
let read = 0;
|
|
6403
|
+
let space = -1;
|
|
6404
|
+
let scheme = -1;
|
|
6405
|
+
return (start) => {
|
|
6406
|
+
for (; read < start; read++) {
|
|
6407
|
+
if (endsLink2(text, read)) {
|
|
6408
|
+
space = read;
|
|
6409
|
+
} else if (text[read] === "/" && text[read - 1] === "/" && text[read - 2] === ":") {
|
|
6410
|
+
scheme = read;
|
|
6411
|
+
}
|
|
6412
|
+
}
|
|
6413
|
+
return scheme > space;
|
|
6414
|
+
};
|
|
6415
|
+
}
|
|
6416
|
+
function isSchemeless(text, start) {
|
|
6417
|
+
if (start < 2 || text[start - 2] !== "/") {
|
|
6418
|
+
return false;
|
|
6419
|
+
}
|
|
6420
|
+
if (start === 2) {
|
|
6421
|
+
return true;
|
|
6422
|
+
}
|
|
6423
|
+
const before = text[start - 3];
|
|
6424
|
+
return !(before === ":" || before === "/" || isHostCode2(text.codePointAt(start - 3)));
|
|
6425
|
+
}
|
|
6426
|
+
function bareName(name) {
|
|
6427
|
+
const labels = name.split(".");
|
|
6428
|
+
const tld = labels.pop();
|
|
6429
|
+
if (!/^(?:[a-z]{2,24}|xn--[a-z\d-]{1,59})$/i.test(tld)) {
|
|
6430
|
+
return null;
|
|
6431
|
+
}
|
|
6432
|
+
const names = [];
|
|
6433
|
+
while (labels.length > 0 && names.length < 11) {
|
|
6434
|
+
const label = labels.pop();
|
|
6435
|
+
if (!/^[a-z\d-]{1,63}$/i.test(label)) {
|
|
6436
|
+
break;
|
|
6437
|
+
}
|
|
6438
|
+
names.unshift(label);
|
|
6439
|
+
}
|
|
6440
|
+
if (names.length === 0) {
|
|
6441
|
+
return null;
|
|
6442
|
+
}
|
|
6443
|
+
names[0] = names[0].replace(/^-+/, "");
|
|
6444
|
+
if (!names[0]) {
|
|
6445
|
+
return null;
|
|
6446
|
+
}
|
|
6447
|
+
return `${names.join(".")}.${tld}`.toLowerCase();
|
|
6448
|
+
}
|
|
6449
|
+
function isRealName(host) {
|
|
6450
|
+
const parsed = (0, import_tldts4.parse)(host);
|
|
6451
|
+
return Boolean(parsed.isIcann && parsed.domain);
|
|
6452
|
+
}
|
|
6453
|
+
function bareHosts(text, add, { done, seen, from = 0, cutEnd = false }) {
|
|
6454
|
+
let previous = -1;
|
|
6455
|
+
const inLink = linkReader(text);
|
|
6456
|
+
for (let slash = text.indexOf("/"); slash !== -1; slash = text.indexOf("/", slash + 1)) {
|
|
6457
|
+
if (done()) {
|
|
6458
|
+
return;
|
|
6459
|
+
}
|
|
6460
|
+
const floor = Math.max(previous + 1, slash - MAX_HOST);
|
|
6461
|
+
previous = slash;
|
|
6462
|
+
let end = slash;
|
|
6463
|
+
while (end > floor && text.codePointAt(end - 1) >= 48 && text.codePointAt(end - 1) <= 57) {
|
|
6464
|
+
end--;
|
|
6465
|
+
}
|
|
6466
|
+
end = end > floor && text[end - 1] === ":" ? end - 1 : slash;
|
|
6467
|
+
let start = end;
|
|
6468
|
+
while (start > floor && isHostCode2(text.codePointAt(start - 1))) {
|
|
6469
|
+
start--;
|
|
6470
|
+
}
|
|
6471
|
+
if (start === end || start < from || cutEnd && slash === text.length - 1) {
|
|
6472
|
+
continue;
|
|
6473
|
+
}
|
|
6474
|
+
if (start > 0 && (IN_WORD2.test(text[start - 1]) || text[start - 1] === "/" && !isSchemeless(text, start)) || inLink(start)) {
|
|
6475
|
+
continue;
|
|
6476
|
+
}
|
|
6477
|
+
while (end > start && text[end - 1] === ".") {
|
|
6478
|
+
end--;
|
|
6479
|
+
}
|
|
6480
|
+
const host = bareName(text.slice(start, end));
|
|
6481
|
+
if (!host || seen.has(host)) {
|
|
6482
|
+
continue;
|
|
6483
|
+
}
|
|
6484
|
+
if (seen.size < MAX_SEEN) {
|
|
6485
|
+
seen.add(host);
|
|
6486
|
+
}
|
|
6487
|
+
if (isRealName(host)) {
|
|
6488
|
+
add(`http://${host}/`);
|
|
6489
|
+
}
|
|
6490
|
+
}
|
|
6491
|
+
}
|
|
6492
|
+
function looseHosts(text, add, { from = 0, cutEnd = false, seen, done }) {
|
|
6493
|
+
const inLink = linkReader(text);
|
|
6494
|
+
const { length } = text;
|
|
6495
|
+
let i = 0;
|
|
6496
|
+
while (i < length) {
|
|
6497
|
+
if (!isHostCode2(text.codePointAt(i))) {
|
|
6498
|
+
i++;
|
|
6499
|
+
continue;
|
|
6500
|
+
}
|
|
6501
|
+
const start = i;
|
|
6502
|
+
while (i < length && isHostCode2(text.codePointAt(i))) {
|
|
6503
|
+
i++;
|
|
6504
|
+
}
|
|
6505
|
+
let end = i;
|
|
6506
|
+
if (end - start > MAX_HOST || start < from || cutEnd && end === length) {
|
|
6507
|
+
continue;
|
|
6508
|
+
}
|
|
6509
|
+
while (end > start && text[end - 1] === ".") {
|
|
6510
|
+
end--;
|
|
6511
|
+
}
|
|
6512
|
+
const before = start > 0 ? text[start - 1] : "";
|
|
6513
|
+
const after = end < length ? text[end] : "";
|
|
6514
|
+
if (after === "/" || after === "@" || before === "@") {
|
|
6515
|
+
continue;
|
|
6516
|
+
}
|
|
6517
|
+
if (before && (IN_WORD2.test(before) || before === "/" || before === "\\" || before === "&" || before === "#")) {
|
|
6518
|
+
continue;
|
|
6519
|
+
}
|
|
6520
|
+
if (after && after !== "." && IN_WORD2.test(after)) {
|
|
6521
|
+
continue;
|
|
6522
|
+
}
|
|
6523
|
+
const name = text.slice(start, end);
|
|
6524
|
+
if (!name.includes(".") || inLink(start)) {
|
|
6525
|
+
continue;
|
|
6526
|
+
}
|
|
6527
|
+
const lower = name.toLowerCase();
|
|
6528
|
+
if (seen.has(lower)) {
|
|
6529
|
+
continue;
|
|
6530
|
+
}
|
|
6531
|
+
if (seen.size < MAX_SEEN) {
|
|
6532
|
+
seen.add(lower);
|
|
6533
|
+
}
|
|
6534
|
+
if (done()) {
|
|
6535
|
+
return;
|
|
6536
|
+
}
|
|
6537
|
+
const host = bareName(name);
|
|
6538
|
+
if (host && isRealName(host)) {
|
|
6539
|
+
add(host);
|
|
6540
|
+
}
|
|
6541
|
+
}
|
|
6542
|
+
}
|
|
6543
|
+
function* chunksOf(html2) {
|
|
6544
|
+
let start = 0;
|
|
6545
|
+
let cutStart = false;
|
|
6546
|
+
while (start < html2.length) {
|
|
6547
|
+
const end = Math.min(html2.length, start + DECODE_CHUNK);
|
|
6548
|
+
if (end < html2.length) {
|
|
6549
|
+
let cut = end;
|
|
6550
|
+
while (cut > end - 65536 && cut > start) {
|
|
6551
|
+
if (html2[cut] === "<" || isSpace(html2.codePointAt(cut))) {
|
|
6552
|
+
break;
|
|
6553
|
+
}
|
|
6554
|
+
cut--;
|
|
6555
|
+
}
|
|
6556
|
+
if (cut > start && cut > end - 65536) {
|
|
6557
|
+
yield { text: html2.slice(start, cut), cutStart, cutEnd: false };
|
|
6558
|
+
start = cut;
|
|
6559
|
+
cutStart = false;
|
|
6560
|
+
continue;
|
|
6561
|
+
}
|
|
6562
|
+
yield { text: html2.slice(start, end), cutStart, cutEnd: true };
|
|
6563
|
+
start = end - CHUNK_OVERLAP;
|
|
6564
|
+
cutStart = true;
|
|
6565
|
+
continue;
|
|
6566
|
+
}
|
|
6567
|
+
yield { text: html2.slice(start, end), cutStart, cutEnd: false };
|
|
6568
|
+
start = end;
|
|
6569
|
+
}
|
|
6570
|
+
}
|
|
6571
|
+
function withoutNul(text) {
|
|
6572
|
+
return text.includes("\0") ? `${text}
|
|
6573
|
+
${text.replaceAll("\0", "")}` : text;
|
|
6574
|
+
}
|
|
6575
|
+
function hexValue(code) {
|
|
6576
|
+
if (code >= 48 && code <= 57) {
|
|
6577
|
+
return code - 48;
|
|
6578
|
+
}
|
|
6579
|
+
if (code >= 65 && code <= 70) {
|
|
6580
|
+
return code - 55;
|
|
6581
|
+
}
|
|
6582
|
+
if (code >= 97 && code <= 102) {
|
|
6583
|
+
return code - 87;
|
|
6584
|
+
}
|
|
6585
|
+
return -1;
|
|
6586
|
+
}
|
|
6587
|
+
function percentDecoded(text) {
|
|
6588
|
+
const input = import_node_buffer7.Buffer.from(text);
|
|
6589
|
+
const output = import_node_buffer7.Buffer.allocUnsafe(input.length);
|
|
6590
|
+
let length = 0;
|
|
6591
|
+
for (let i = 0; i < input.length; i++) {
|
|
6592
|
+
const high = input[i] === 37 ? hexValue(input[i + 1]) : -1;
|
|
6593
|
+
const low = high === -1 ? -1 : hexValue(input[i + 2]);
|
|
6594
|
+
if (low === -1) {
|
|
6595
|
+
output[length++] = input[i];
|
|
6596
|
+
continue;
|
|
6597
|
+
}
|
|
6598
|
+
output[length++] = high * 16 + low;
|
|
6599
|
+
i += 2;
|
|
6600
|
+
}
|
|
6601
|
+
return output.subarray(0, length);
|
|
6602
|
+
}
|
|
6603
|
+
function swapped(bytes) {
|
|
6604
|
+
return import_node_buffer7.Buffer.from(bytes.subarray(0, bytes.length - bytes.length % 2)).swap16().toString("utf16le");
|
|
6605
|
+
}
|
|
6606
|
+
function decodeText(content, charset = "") {
|
|
6607
|
+
if (content[0] === 255 && content[1] === 254) {
|
|
6608
|
+
return content.subarray(2).toString("utf16le");
|
|
6609
|
+
}
|
|
6610
|
+
if (content[0] === 254 && content[1] === 255) {
|
|
6611
|
+
return swapped(content.subarray(2));
|
|
6612
|
+
}
|
|
6613
|
+
if (UTF16LE.has(charset)) {
|
|
6614
|
+
return content.toString("utf16le");
|
|
6615
|
+
}
|
|
6616
|
+
return UTF16BE.has(charset) ? swapped(content) : content.toString("utf8");
|
|
6617
|
+
}
|
|
6618
|
+
function dataDocument(value) {
|
|
6619
|
+
const match = DATA_DOCUMENT.exec(value.slice(0, 1024));
|
|
6620
|
+
if (!match) {
|
|
6621
|
+
return null;
|
|
6622
|
+
}
|
|
6623
|
+
const bytes = percentDecoded(value.slice(match[0].length));
|
|
6624
|
+
const content = /;\s*base64\s*$/i.test(match[1]) ? import_node_buffer7.Buffer.from(bytes.toString("latin1"), "base64") : bytes;
|
|
6625
|
+
const charset = /;\s*charset\s*=\s*"?([^;"\s]+)/i.exec(match[1]);
|
|
6626
|
+
return decodeText(content, charset ? charset[1].toLowerCase() : "");
|
|
6627
|
+
}
|
|
6628
|
+
function readEscapes(text, lenient = false) {
|
|
6629
|
+
let index = text.indexOf("\\");
|
|
6630
|
+
if (index === -1) {
|
|
6631
|
+
return text;
|
|
6632
|
+
}
|
|
6633
|
+
let out = "";
|
|
6634
|
+
let parts = [];
|
|
6635
|
+
let start = 0;
|
|
6636
|
+
while (index !== -1 && index + 1 < text.length) {
|
|
6637
|
+
const next = text[index + 1];
|
|
6638
|
+
if (lenient || "nN,;\\".includes(next)) {
|
|
6639
|
+
parts.push(text.slice(start, index), next === "n" || next === "N" ? "\n" : next);
|
|
6640
|
+
start = index + 2;
|
|
6641
|
+
index = text.indexOf("\\", start);
|
|
6642
|
+
if (parts.length >= 65536) {
|
|
6643
|
+
out += parts.join("");
|
|
6644
|
+
parts = [];
|
|
6645
|
+
}
|
|
6646
|
+
} else {
|
|
6647
|
+
index = text.indexOf("\\", index + 1);
|
|
6648
|
+
}
|
|
6649
|
+
}
|
|
6650
|
+
parts.push(text.slice(start));
|
|
6651
|
+
return out + parts.join("");
|
|
6652
|
+
}
|
|
6653
|
+
function valueColon(line) {
|
|
6654
|
+
let colon = line.indexOf(":");
|
|
6655
|
+
let from = 0;
|
|
6656
|
+
for (; ; ) {
|
|
6657
|
+
const quote = line.indexOf('"', from);
|
|
6658
|
+
if (quote === -1 || colon === -1 || colon < quote) {
|
|
6659
|
+
return colon;
|
|
6660
|
+
}
|
|
6661
|
+
const end = line.indexOf('"', quote + 1);
|
|
6662
|
+
if (end === -1) {
|
|
6663
|
+
return -1;
|
|
6664
|
+
}
|
|
6665
|
+
from = end + 1;
|
|
6666
|
+
if (colon < from) {
|
|
6667
|
+
colon = line.indexOf(":", from);
|
|
6668
|
+
}
|
|
6669
|
+
}
|
|
6670
|
+
}
|
|
6671
|
+
function trimSpaceEnd(text) {
|
|
6672
|
+
let end = text.length;
|
|
6673
|
+
while (end > 0 && (text[end - 1] === " " || text[end - 1] === " ")) {
|
|
6674
|
+
end--;
|
|
6675
|
+
}
|
|
6676
|
+
return end === text.length ? text : text.slice(0, end);
|
|
6677
|
+
}
|
|
6678
|
+
function decodeQuotedPrintable(value, charset) {
|
|
6679
|
+
let decoder;
|
|
6680
|
+
try {
|
|
6681
|
+
decoder = new TextDecoder(charset || "utf8");
|
|
6682
|
+
} catch {
|
|
6683
|
+
decoder = new TextDecoder("utf8");
|
|
6684
|
+
}
|
|
6685
|
+
if (!/[\u0080-\u{10FFFF}]/u.test(value)) {
|
|
6686
|
+
const bytes = import_node_buffer7.Buffer.from(value, "latin1");
|
|
6687
|
+
let length = 0;
|
|
6688
|
+
for (let index = 0; index < bytes.length; index++) {
|
|
6689
|
+
const hex = bytes[index] === 61 ? value.slice(index + 1, index + 3) : "";
|
|
6690
|
+
if (/^[\da-f]{2}$/i.test(hex)) {
|
|
6691
|
+
bytes[length++] = Number.parseInt(hex, 16);
|
|
6692
|
+
index += 2;
|
|
6693
|
+
} else {
|
|
6694
|
+
bytes[length++] = bytes[index];
|
|
6695
|
+
}
|
|
6696
|
+
}
|
|
6697
|
+
return decoder.decode(bytes.subarray(0, length));
|
|
6698
|
+
}
|
|
6699
|
+
return value.replaceAll(/(?:=[\da-f]{2})+/gi, (run) => decoder.decode(import_node_buffer7.Buffer.from(run.replaceAll("=", ""), "hex")));
|
|
6700
|
+
}
|
|
6701
|
+
function quotedPrintableValues(text) {
|
|
6702
|
+
if (!/quoted-printable/i.test(text)) {
|
|
6703
|
+
return text;
|
|
6704
|
+
}
|
|
6705
|
+
const lines2 = text.split(LINE_BREAK);
|
|
6706
|
+
const out = [];
|
|
6707
|
+
for (let i = 0; i < lines2.length; i++) {
|
|
6708
|
+
const line = lines2[i];
|
|
6709
|
+
const colon = valueColon(line);
|
|
6710
|
+
const parameters = colon === -1 ? "" : line.slice(0, colon);
|
|
6711
|
+
if (colon === -1 || !QUOTED_PRINTABLE.test(parameters)) {
|
|
6712
|
+
out.push(line);
|
|
6713
|
+
continue;
|
|
6714
|
+
}
|
|
6715
|
+
const charset = /;\s*charset\s*=\s*"?([\w.:-]+)/i.exec(parameters)?.[1];
|
|
6716
|
+
const parts = [trimSpaceEnd(line.slice(colon + 1))];
|
|
6717
|
+
while (parts.at(-1).endsWith("=") && i + 1 < lines2.length) {
|
|
6718
|
+
parts[parts.length - 1] = parts.at(-1).slice(0, -1);
|
|
6719
|
+
parts.push(trimSpaceEnd(lines2[++i]));
|
|
6720
|
+
}
|
|
6721
|
+
out.push(line.slice(0, colon + 1) + decodeQuotedPrintable(parts.join(""), charset));
|
|
6722
|
+
}
|
|
6723
|
+
return out.join("\n");
|
|
6724
|
+
}
|
|
6725
|
+
function hasQuotedPrintable(text) {
|
|
6726
|
+
const unfolded = text.replaceAll(FOLD, "");
|
|
6727
|
+
if (!/quoted-printable/i.test(unfolded)) {
|
|
6728
|
+
return false;
|
|
6729
|
+
}
|
|
6730
|
+
return unfolded.split(LINE_BREAK).some((line) => {
|
|
6731
|
+
const colon = valueColon(line);
|
|
6732
|
+
return colon !== -1 && QUOTED_PRINTABLE.test(line.slice(0, colon));
|
|
6733
|
+
});
|
|
6734
|
+
}
|
|
6735
|
+
function shownText(text, full = true) {
|
|
6736
|
+
const unfolded = text.replaceAll(FOLD, "");
|
|
6737
|
+
const shown = /* @__PURE__ */ new Set([text, readEscapes(unfolded)]);
|
|
6738
|
+
let decoded = unfolded;
|
|
6739
|
+
if (full) {
|
|
6740
|
+
decoded = quotedPrintableValues(unfolded);
|
|
6741
|
+
if (decoded !== unfolded) {
|
|
6742
|
+
shown.add(readEscapes(decoded));
|
|
6743
|
+
if (unfolded !== text) {
|
|
6744
|
+
shown.add(quotedPrintableValues(text));
|
|
6745
|
+
}
|
|
6746
|
+
}
|
|
6747
|
+
}
|
|
6748
|
+
if (/\\[^nN,;\\]/.test(decoded)) {
|
|
6749
|
+
shown.add(readEscapes(decoded, true));
|
|
6750
|
+
}
|
|
6751
|
+
return [...shown].reverse().join("\n");
|
|
6752
|
+
}
|
|
6753
|
+
function htmlDescriptions(text) {
|
|
6754
|
+
if (!/[<&]|altrep/i.test(text)) {
|
|
6755
|
+
return "";
|
|
6756
|
+
}
|
|
6757
|
+
const html2 = [];
|
|
6758
|
+
for (const line of text.replaceAll(FOLD, "").split(LINE_BREAK)) {
|
|
6759
|
+
const colon = valueColon(line);
|
|
6760
|
+
if (colon === -1) {
|
|
6761
|
+
continue;
|
|
6762
|
+
}
|
|
6763
|
+
const altrep = /;\s*altrep\s*=\s*"([^"]*)"/i.exec(line.slice(0, colon))?.[1];
|
|
6764
|
+
if (altrep) {
|
|
6765
|
+
html2.push(`<iframe src="${altrep.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<")}"></iframe>`);
|
|
6766
|
+
}
|
|
6767
|
+
if (!HTML_PROPERTIES.test(line)) {
|
|
6768
|
+
continue;
|
|
6769
|
+
}
|
|
6770
|
+
const value = readEscapes(line.slice(colon + 1));
|
|
6771
|
+
if (/[<&]/.test(value)) {
|
|
6772
|
+
html2.push(value);
|
|
6773
|
+
}
|
|
6774
|
+
}
|
|
6775
|
+
return html2.join("\n");
|
|
6776
|
+
}
|
|
6777
|
+
function withoutBinaryValues(text) {
|
|
6778
|
+
if (!/base64|binary|encoding\s*=\s*"?b|;\s*b\s*[;:]/i.test(text)) {
|
|
6779
|
+
return text;
|
|
6780
|
+
}
|
|
6781
|
+
const lines2 = text.split(LINE_BREAK);
|
|
6782
|
+
const out = [];
|
|
6783
|
+
for (let i = 0; i < lines2.length; i++) {
|
|
6784
|
+
const line = lines2[i];
|
|
6785
|
+
const colon = valueColon(line);
|
|
6786
|
+
if (colon === -1 || !BINARY.test(line.slice(0, colon))) {
|
|
6787
|
+
out.push(line);
|
|
6788
|
+
continue;
|
|
6789
|
+
}
|
|
6790
|
+
const value = [line.slice(colon + 1)];
|
|
6791
|
+
let next = i + 1;
|
|
6792
|
+
while (next < lines2.length && (lines2[next].startsWith(" ") || lines2[next].startsWith(" "))) {
|
|
6793
|
+
value.push(lines2[next++]);
|
|
6794
|
+
}
|
|
6795
|
+
if (!value.every((part) => /^[\w+/=\s]*$/.test(part))) {
|
|
6796
|
+
for (let index = i; index < next; index++) {
|
|
6797
|
+
out.push(lines2[index]);
|
|
6798
|
+
}
|
|
6799
|
+
i = next - 1;
|
|
6800
|
+
continue;
|
|
6801
|
+
}
|
|
6802
|
+
while (next < lines2.length && lines2[next] !== "" && /^[\w+/=]+$/.test(lines2[next])) {
|
|
6803
|
+
value.push(lines2[next++]);
|
|
6804
|
+
}
|
|
6805
|
+
if (next < lines2.length && lines2[next] === "") {
|
|
6806
|
+
next++;
|
|
6807
|
+
}
|
|
6808
|
+
i = next - 1;
|
|
6809
|
+
const name = line.slice(0, colon).split(";")[0].split(".").pop().trim().toLowerCase();
|
|
6810
|
+
out.push(MEDIA_PROPERTIES.has(name) ? line.slice(0, colon + 1) : line.slice(0, colon + 1) + import_node_buffer7.Buffer.from(value.join("").replaceAll(/\s/g, ""), "base64").toString("utf8"));
|
|
6811
|
+
}
|
|
6812
|
+
return out.join("\n");
|
|
6813
|
+
}
|
|
6814
|
+
function extensionOf2(filename) {
|
|
6815
|
+
let end = filename.length;
|
|
6816
|
+
while (end > 0 && (filename[end - 1] === "." || filename[end - 1] === " ")) {
|
|
6817
|
+
end--;
|
|
6818
|
+
}
|
|
6819
|
+
const name = filename.slice(0, end).trim().toLowerCase();
|
|
6820
|
+
const index = name.lastIndexOf(".");
|
|
6821
|
+
return index !== -1 && index < name.length - 1 ? name.slice(index + 1) : null;
|
|
6822
|
+
}
|
|
6823
|
+
function extensionsOf(attachment) {
|
|
6824
|
+
const names = [];
|
|
6825
|
+
if (typeof attachment.filename === "string") {
|
|
6826
|
+
names.push(attachment.filename);
|
|
6827
|
+
}
|
|
6828
|
+
const { headers } = attachment;
|
|
6829
|
+
if (headers && typeof headers.get === "function") {
|
|
6830
|
+
for (const [field, parameter] of [["content-type", "name"], ["content-disposition", "filename"]]) {
|
|
6831
|
+
const value = headers.get(field)?.params?.[parameter];
|
|
6832
|
+
if (typeof value === "string" && value !== "") {
|
|
6833
|
+
names.push(value);
|
|
6834
|
+
}
|
|
6835
|
+
}
|
|
6836
|
+
}
|
|
6837
|
+
return new Set(names.flatMap((name) => [extensionOf2(name), extensionOf(name)]).filter(Boolean));
|
|
6838
|
+
}
|
|
6839
|
+
function charsetOf(attachment) {
|
|
6840
|
+
const { headers } = attachment;
|
|
6841
|
+
const charset = headers && typeof headers.get === "function" ? headers.get("content-type")?.params?.charset : null;
|
|
6842
|
+
return typeof charset === "string" ? charset.toLowerCase() : "";
|
|
6843
|
+
}
|
|
6844
|
+
function documentsOf(attachments, until) {
|
|
6845
|
+
const documents = [];
|
|
6846
|
+
let bytes = 0;
|
|
6847
|
+
let opened = 0;
|
|
6848
|
+
for (const attachment of attachments) {
|
|
6849
|
+
const { content } = attachment ?? {};
|
|
6850
|
+
if (!import_node_buffer7.Buffer.isBuffer(content) || content.length === 0) {
|
|
6851
|
+
continue;
|
|
6852
|
+
}
|
|
6853
|
+
const type = typeof attachment.contentType === "string" ? attachment.contentType.toLowerCase() : "";
|
|
6854
|
+
const extensions = extensionsOf(attachment);
|
|
6855
|
+
const has = (set) => [...extensions].some((name) => set.has(name));
|
|
6856
|
+
if (MESSAGE_TYPES.has(type) || extensions.has("eml") || extensions.has("u8msg")) {
|
|
6857
|
+
continue;
|
|
6858
|
+
}
|
|
6859
|
+
const isHtml = HTML_TYPES.has(type) || has(HTML_EXTENSIONS);
|
|
6860
|
+
const isCard = !isHtml && (CARD_TYPES.has(type) || has(CARD_EXTENSIONS));
|
|
6861
|
+
const isText = isCard || !isHtml && type === "text/plain";
|
|
6862
|
+
if (!isHtml && !isText) {
|
|
6863
|
+
continue;
|
|
6864
|
+
}
|
|
6865
|
+
if (!isText && ++opened > MAX_ATTACHED || bytes + content.length > MAX_ATTACHED_BYTES) {
|
|
6866
|
+
documents.tooComplex = true;
|
|
6867
|
+
return documents;
|
|
6868
|
+
}
|
|
6869
|
+
if (Date.now() > until) {
|
|
6870
|
+
documents.incomplete = true;
|
|
6871
|
+
return documents;
|
|
6872
|
+
}
|
|
6873
|
+
bytes += content.length;
|
|
6874
|
+
const text = decodeText(content, charsetOf(attachment));
|
|
6875
|
+
if (isHtml) {
|
|
6876
|
+
documents.push({ html: text });
|
|
6877
|
+
continue;
|
|
6878
|
+
}
|
|
6879
|
+
if (!isCard) {
|
|
6880
|
+
documents.push({ text });
|
|
6881
|
+
continue;
|
|
6882
|
+
}
|
|
6883
|
+
const readable = withoutBinaryValues(text);
|
|
6884
|
+
const full = readable.length <= MAX_SHOWN_BYTES;
|
|
6885
|
+
if (!full && hasQuotedPrintable(readable)) {
|
|
6886
|
+
documents.tooComplex = true;
|
|
6887
|
+
continue;
|
|
6888
|
+
}
|
|
6889
|
+
documents.push({ text: shownText(readable, full) });
|
|
6890
|
+
const html2 = htmlDescriptions(readable);
|
|
6891
|
+
if (html2 !== "") {
|
|
6892
|
+
documents.push({ html: html2 });
|
|
6893
|
+
}
|
|
6894
|
+
}
|
|
6895
|
+
return documents;
|
|
6896
|
+
}
|
|
6897
|
+
function carriedLinkHosts(mail, {
|
|
6898
|
+
mails = [],
|
|
6899
|
+
attachments = [],
|
|
6900
|
+
maxHosts = 250,
|
|
6901
|
+
hostsInText = false
|
|
6902
|
+
} = {}) {
|
|
6903
|
+
const hosts = /* @__PURE__ */ new Set();
|
|
6904
|
+
const loose = /* @__PURE__ */ new Set();
|
|
6905
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6906
|
+
const seenBare = /* @__PURE__ */ new Set();
|
|
6907
|
+
const seenLoose = /* @__PURE__ */ new Set();
|
|
6908
|
+
let more = false;
|
|
6909
|
+
let tooComplex = false;
|
|
6910
|
+
const done = () => more;
|
|
6911
|
+
const looseDone = () => more || loose.size > maxHosts;
|
|
6912
|
+
const addLoose = (host) => {
|
|
6913
|
+
if (!looseDone()) {
|
|
6914
|
+
loose.add(host);
|
|
6915
|
+
}
|
|
6916
|
+
};
|
|
6917
|
+
const until = Date.now() + MAX_READ_TIME;
|
|
6918
|
+
let incomplete = false;
|
|
6919
|
+
const late = () => {
|
|
6920
|
+
if (!incomplete && Date.now() > until) {
|
|
6921
|
+
incomplete = true;
|
|
6922
|
+
}
|
|
6923
|
+
return incomplete;
|
|
6924
|
+
};
|
|
6925
|
+
const carried = documentsOf(attachments, until);
|
|
6926
|
+
tooComplex = Boolean(carried.tooComplex);
|
|
6927
|
+
incomplete = Boolean(carried.incomplete);
|
|
6928
|
+
const queue = [mail, ...mails, ...carried].map((document) => ({ document, depth: 0 }));
|
|
6929
|
+
let depth = 0;
|
|
6930
|
+
let embedded = 0;
|
|
6931
|
+
let embeddedLength = 0;
|
|
6932
|
+
const embed = (html2) => {
|
|
6933
|
+
if (depth >= MAX_EMBED_DEPTH || embedded >= MAX_EMBEDDED || embeddedLength + html2.length > MAX_EMBEDDED_LENGTH) {
|
|
6934
|
+
tooComplex = true;
|
|
6935
|
+
return;
|
|
6936
|
+
}
|
|
6937
|
+
embedded++;
|
|
6938
|
+
embeddedLength += html2.length;
|
|
6939
|
+
queue.push({ document: { html: html2 }, depth: depth + 1 });
|
|
6940
|
+
};
|
|
6941
|
+
const add = (value) => {
|
|
6942
|
+
if (more || typeof value !== "string" || value === "" || seen.has(value)) {
|
|
6943
|
+
return;
|
|
6944
|
+
}
|
|
6945
|
+
if (seen.size < MAX_SEEN) {
|
|
6946
|
+
seen.add(value);
|
|
6947
|
+
}
|
|
6948
|
+
if (/^\s*data:/i.test(value)) {
|
|
6949
|
+
const html2 = dataDocument(value);
|
|
6950
|
+
if (html2 !== null) {
|
|
6951
|
+
embed(html2);
|
|
6952
|
+
}
|
|
6953
|
+
return;
|
|
6954
|
+
}
|
|
6955
|
+
const found = hostsOf(value);
|
|
6956
|
+
if (found.unresolved) {
|
|
6957
|
+
tooComplex = true;
|
|
6958
|
+
}
|
|
6959
|
+
for (const host of found) {
|
|
6960
|
+
if (hosts.has(host)) {
|
|
6961
|
+
continue;
|
|
6962
|
+
}
|
|
6963
|
+
if (hosts.size >= maxHosts) {
|
|
6964
|
+
more = true;
|
|
6965
|
+
return;
|
|
6966
|
+
}
|
|
6967
|
+
hosts.add(host);
|
|
6968
|
+
}
|
|
6969
|
+
};
|
|
6970
|
+
const readText = (source, { cutStart = false, cutEnd = false } = {}) => {
|
|
6971
|
+
for (const match of source.matchAll(URL_START)) {
|
|
6972
|
+
if (more) {
|
|
6973
|
+
break;
|
|
6974
|
+
}
|
|
6975
|
+
if (cutStart && match.index === 0) {
|
|
6976
|
+
continue;
|
|
6977
|
+
}
|
|
6978
|
+
if (cutEnd && match.index + match[0].length === source.length) {
|
|
6979
|
+
const value = match[0];
|
|
6980
|
+
const at = /^www\./i.test(value) ? 0 : value.indexOf("//") + 2;
|
|
6981
|
+
if (/[/?#\\]/.test(value.slice(at))) {
|
|
6982
|
+
add(value);
|
|
6983
|
+
} else if (source.length - match.index > CHUNK_OVERLAP) {
|
|
6984
|
+
tooComplex = true;
|
|
6985
|
+
}
|
|
6986
|
+
continue;
|
|
6987
|
+
}
|
|
6988
|
+
add(match[0]);
|
|
6989
|
+
}
|
|
6990
|
+
const from = cutStart ? 1 : 0;
|
|
6991
|
+
bareHosts(source, add, {
|
|
6992
|
+
done,
|
|
6993
|
+
seen: seenBare,
|
|
6994
|
+
from,
|
|
6995
|
+
cutEnd
|
|
6996
|
+
});
|
|
6997
|
+
if (hostsInText && !looseDone()) {
|
|
6998
|
+
looseHosts(source, addLoose, {
|
|
6999
|
+
from,
|
|
7000
|
+
cutEnd,
|
|
7001
|
+
seen: seenLoose,
|
|
7002
|
+
done: looseDone
|
|
7003
|
+
});
|
|
7004
|
+
}
|
|
7005
|
+
};
|
|
7006
|
+
for (const element of queue) {
|
|
7007
|
+
if (more || late()) {
|
|
7008
|
+
break;
|
|
7009
|
+
}
|
|
7010
|
+
({ depth } = element);
|
|
7011
|
+
const { document } = element;
|
|
7012
|
+
const html2 = withoutNul(typeof document?.html === "string" ? document.html : "");
|
|
7013
|
+
const text = withoutNul(typeof document?.text === "string" ? document.text : "");
|
|
7014
|
+
for (const [name, value] of attributesOf(html2)) {
|
|
7015
|
+
if (more) {
|
|
7016
|
+
break;
|
|
7017
|
+
}
|
|
7018
|
+
if (LINK_ATTRIBUTES.has(name)) {
|
|
7019
|
+
linksOf(name, value, add, embed);
|
|
7020
|
+
}
|
|
7021
|
+
}
|
|
7022
|
+
lenientLinks(html2, add, done, embed);
|
|
7023
|
+
for (const pattern of [CSS_URL, CSS_IMPORT]) {
|
|
7024
|
+
for (const [, link] of html2.matchAll(pattern)) {
|
|
7025
|
+
if (more) {
|
|
7026
|
+
break;
|
|
7027
|
+
}
|
|
7028
|
+
add(decodeEntities(link, { attribute: true }));
|
|
7029
|
+
}
|
|
7030
|
+
}
|
|
7031
|
+
if (!more) {
|
|
7032
|
+
readText(text);
|
|
7033
|
+
}
|
|
7034
|
+
for (const chunk2 of chunksOf(html2)) {
|
|
7035
|
+
if (more || late()) {
|
|
7036
|
+
break;
|
|
7037
|
+
}
|
|
7038
|
+
readText(decodeEntities(chunk2.text), chunk2);
|
|
7039
|
+
}
|
|
7040
|
+
}
|
|
7041
|
+
if (!more && !incomplete) {
|
|
7042
|
+
for (const name of loose) {
|
|
7043
|
+
if (hosts.size >= maxHosts) {
|
|
7044
|
+
break;
|
|
7045
|
+
}
|
|
7046
|
+
const [host] = hostsOf(`http://${name}/`);
|
|
7047
|
+
if (host) {
|
|
7048
|
+
hosts.add(host);
|
|
7049
|
+
}
|
|
7050
|
+
}
|
|
7051
|
+
}
|
|
7052
|
+
return {
|
|
7053
|
+
hosts: [...hosts],
|
|
7054
|
+
more,
|
|
7055
|
+
tooComplex,
|
|
7056
|
+
incomplete
|
|
7057
|
+
};
|
|
7058
|
+
}
|
|
7059
|
+
var import_node_buffer7, import_node_net4, import_tldts4, LINK_ATTRIBUTES, TAG_START, URL_START, CSS_URL, CSS_IMPORT, LENIENT, IN_WORD2, NAMESPACES, MAX_HOST, MAX_SEEN, TRAILING, DECODE_CHUNK, CHUNK_OVERLAP, MAX_EMBED_DEPTH, MAX_EMBEDDED, MAX_EMBEDDED_LENGTH, MAX_ATTACHED, MAX_ATTACHED_BYTES, MAX_READ_TIME, MAX_SHOWN_BYTES, MAX_LENIENT_VALUE, UNQUOTED_END, UTF16LE, UTF16BE, DATA_DOCUMENT, LINE_BREAK, FOLD, QUOTED_PRINTABLE, MEDIA_PROPERTIES, HTML_PROPERTIES, BINARY, HTML_TYPES, HTML_EXTENSIONS, CARD_TYPES, CARD_EXTENSIONS, MESSAGE_TYPES;
|
|
7060
|
+
var init_links = __esm({
|
|
7061
|
+
"src/links.js"() {
|
|
7062
|
+
import_node_buffer7 = require("node:buffer");
|
|
7063
|
+
import_node_net4 = require("node:net");
|
|
7064
|
+
import_tldts4 = require("tldts");
|
|
7065
|
+
init_attachments();
|
|
7066
|
+
init_dnsbl();
|
|
7067
|
+
init_html();
|
|
7068
|
+
init_tokenizer();
|
|
7069
|
+
LINK_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
7070
|
+
"href",
|
|
7071
|
+
"src",
|
|
7072
|
+
"srcset",
|
|
7073
|
+
"background",
|
|
7074
|
+
"action",
|
|
7075
|
+
"formaction",
|
|
7076
|
+
"poster",
|
|
7077
|
+
"cite",
|
|
7078
|
+
"longdesc",
|
|
7079
|
+
"xlink:href",
|
|
7080
|
+
"style",
|
|
7081
|
+
"data",
|
|
7082
|
+
"ping",
|
|
7083
|
+
// (of a <meta> refresh: "0;url=https://example.com/")
|
|
7084
|
+
"content",
|
|
7085
|
+
// (a document of its own, see linksOf)
|
|
7086
|
+
"srcdoc"
|
|
7087
|
+
]);
|
|
7088
|
+
TAG_START = /<[a-z][^\s/>]*/gi;
|
|
7089
|
+
URL_START = /\b(?:https?:\/\/|www\.)[^\s<>"'`]+/gi;
|
|
7090
|
+
CSS_URL = /url\(\s*["']?([^()"']*)/gi;
|
|
7091
|
+
CSS_IMPORT = /@import\s+["']([^"'<>]*)/gi;
|
|
7092
|
+
LENIENT = /[\s"'/<](href|src|srcset|background|action|formaction|poster|cite|longdesc|xlink:href|style|data|ping|content|srcdoc)\s*=\s*/gi;
|
|
7093
|
+
IN_WORD2 = /[\p{L}\p{N}\p{M}_%]/u;
|
|
7094
|
+
NAMESPACES = /* @__PURE__ */ new Set(["www.w3.org", "w3.org"]);
|
|
7095
|
+
MAX_HOST = 760;
|
|
7096
|
+
MAX_SEEN = 1e5;
|
|
7097
|
+
TRAILING = /* @__PURE__ */ new Set([")", ".", ",", ";", ":", "!", "?", "'", '"', "]"]);
|
|
7098
|
+
DECODE_CHUNK = 1024 * 1024;
|
|
7099
|
+
CHUNK_OVERLAP = 4096;
|
|
7100
|
+
MAX_EMBED_DEPTH = 3;
|
|
7101
|
+
MAX_EMBEDDED = 1e3;
|
|
7102
|
+
MAX_EMBEDDED_LENGTH = 10 * 1024 * 1024;
|
|
7103
|
+
MAX_ATTACHED = 100;
|
|
7104
|
+
MAX_ATTACHED_BYTES = 50 * 1024 * 1024;
|
|
7105
|
+
MAX_READ_TIME = 5e3;
|
|
7106
|
+
MAX_SHOWN_BYTES = 4 * 1024 * 1024;
|
|
7107
|
+
MAX_LENIENT_VALUE = 4096;
|
|
7108
|
+
UNQUOTED_END = /* @__PURE__ */ new Set(["<", ">", '"', "'", "`", "="]);
|
|
7109
|
+
UTF16LE = /* @__PURE__ */ new Set(["csunicode", "iso-10646-ucs-2", "ucs-2", "unicode", "unicodefeff", "utf-16", "utf-16le"]);
|
|
7110
|
+
UTF16BE = /* @__PURE__ */ new Set(["unicodefffe", "utf-16be"]);
|
|
7111
|
+
DATA_DOCUMENT = /^\s*data:\s*(?:text\/html|application\/xhtml\+xml|image\/svg\+xml|text\/xml|application\/xml)\b([^,]*),/i;
|
|
7112
|
+
LINE_BREAK = /\r\n?|\n/;
|
|
7113
|
+
FOLD = /(?:\r\n?|\n)[ \t]/g;
|
|
7114
|
+
QUOTED_PRINTABLE = /;\s*(?:encoding\s*=\s*)?"?quoted-printable"?\s*(?:;|$)/i;
|
|
7115
|
+
MEDIA_PROPERTIES = /* @__PURE__ */ new Set(["photo", "logo", "sound", "key", "attach"]);
|
|
7116
|
+
HTML_PROPERTIES = /^(?:x-alt-desc|styled-description|description|comment)[;:]/i;
|
|
7117
|
+
BINARY = /;\s*(?:(?:encoding\s*=\s*)?"?(?:b|base64)"?|value\s*=\s*"?binary"?)\s*(?:;|$)/i;
|
|
7118
|
+
HTML_TYPES = /* @__PURE__ */ new Set(["text/html", "application/xhtml+xml", "image/svg+xml", "text/xml", "application/xml"]);
|
|
7119
|
+
HTML_EXTENSIONS = /* @__PURE__ */ new Set(["html", "htm", "shtml", "xhtml", "xht", "svg", "xml"]);
|
|
7120
|
+
CARD_TYPES = /* @__PURE__ */ new Set(["text/calendar", "text/x-vcalendar", "application/ics", "text/vcard", "text/x-vcard", "text/directory"]);
|
|
7121
|
+
CARD_EXTENSIONS = /* @__PURE__ */ new Set(["ics", "ical", "ifb", "vcs", "vcf", "vcard"]);
|
|
7122
|
+
MESSAGE_TYPES = /* @__PURE__ */ new Set(["message/rfc822", "message/global"]);
|
|
7123
|
+
}
|
|
7124
|
+
});
|
|
7125
|
+
|
|
6008
7126
|
// src/is-arbitrary.js
|
|
6009
7127
|
function unquoted(text) {
|
|
6010
7128
|
let start = 0;
|
|
@@ -6069,13 +7187,13 @@ function joinsDisplay(brand, display, name) {
|
|
|
6069
7187
|
return false;
|
|
6070
7188
|
}
|
|
6071
7189
|
function isOfficial({ brand, official }, domain, display, shared = true) {
|
|
6072
|
-
const parsed = (0,
|
|
7190
|
+
const parsed = (0, import_tldts5.parse)(domain);
|
|
6073
7191
|
const name = parsed.domainWithoutSuffix ?? "";
|
|
6074
7192
|
const compact = brand.replaceAll(" ", "");
|
|
6075
7193
|
if (parsed.publicSuffix === compact || compact.length >= 5 && joinsDisplay(brand, display, name) && !JOINED_WORDS.some((word) => name.slice(compact.length).includes(word))) {
|
|
6076
7194
|
return true;
|
|
6077
7195
|
}
|
|
6078
|
-
return official.some((entry) => entry instanceof RegExp ? entry.test(registrableDomain(domain)) : entry.includes(".") ? (shared || (0,
|
|
7196
|
+
return official.some((entry) => entry instanceof RegExp ? entry.test(registrableDomain(domain)) : entry.includes(".") ? (shared || (0, import_tldts5.parse)(entry).domain !== null) && (domain === entry || domain.endsWith(`.${entry}`)) : name === entry);
|
|
6079
7197
|
}
|
|
6080
7198
|
function headerString(mail, name) {
|
|
6081
7199
|
const value = mail.headers?.get?.(name);
|
|
@@ -6177,7 +7295,7 @@ ${withoutHelp(markup)}`) || isInjection(readable) || attributeText(markup).some(
|
|
|
6177
7295
|
}
|
|
6178
7296
|
} else if (claimed && isWholeName(name, claimed)) {
|
|
6179
7297
|
const domain = claimed[1];
|
|
6180
|
-
const brand = MAILBOXES.has((0,
|
|
7298
|
+
const brand = MAILBOXES.has((0, import_tldts5.parse)(domain).domainWithoutSuffix) ? null : DISPLAY_BRANDS.find((entry) => isOfficial(entry, domain, "", false) && !isOfficial(entry, session.originalFromAddressDomain, ""));
|
|
6181
7299
|
if (brand) {
|
|
6182
7300
|
hit("FROM_NAME_BRAND", 2, `Display name is an address of "${brand.brand}" but the message is from ${fromRoot}`, "PHISHING");
|
|
6183
7301
|
}
|
|
@@ -6210,10 +7328,10 @@ ${withoutHelp(markup)}`) || isInjection(readable) || attributeText(markup).some(
|
|
|
6210
7328
|
category
|
|
6211
7329
|
};
|
|
6212
7330
|
}
|
|
6213
|
-
var
|
|
7331
|
+
var import_tldts5, GTUBE, BLOCKED_SUBJECT, HACKED_SUBJECT, COIN, CODE, CURRENCY, MONEY, CRYPTOCURRENCY, AMOUNT_DEMAND, AMOUNT_GIVEN, HARM_VERB, HARMED, RECORDING, THREAT, HOURS, COUNT, DEADLINE, isPaymentDemand, BITCOIN_ADDRESS, IGNORE_INSTRUCTIONS, AI_ACTION, AI_OBJECT, AI_ACTION_OBJECT, AI_NEAR, VERDICT, VERDICT_WORD, VERDICT_ORDER, VERDICT_CLAIM, CLASSIFY, SYSTEM_PROMPT, YOU_ARE, QUOTE, CONDITION, DISCUSSED, DISCUSSED_SHOWN, DISCUSSED_NEAR, isDiscussed, isInjection, QUOTE_OR_SPACE, SHOWN_NEAR, isOrder, PAYPAL_DOMAIN, PAYPAL_SPAM_TYPE_IDS, PAYPAL_OWN_REQUEST, PAYPAL_INVOICE_SUBJECT, MS_SPAM_VERDICT, MS_SPAM_CATEGORY, APPLE_NEXT, APPLE_FILLER, APPLE_STRONG, APPLE_BUSINESS, APPLE_ALONE, APPLE_BESIDE, APPLE_PART, NEXT_WORD, MAX_AFTER, APPLE, DISPLAY_BRANDS, ADDRESSES, LIST_HOSTS, VIA_LIST, MAILBOXES, BEFORE_ADDRESS, AFTER_ADDRESS, isWholeName, JOINED_WORDS, MAX_DISPLAY;
|
|
6214
7332
|
var init_is_arbitrary = __esm({
|
|
6215
7333
|
"src/is-arbitrary.js"() {
|
|
6216
|
-
|
|
7334
|
+
import_tldts5 = require("tldts");
|
|
6217
7335
|
init_homograph();
|
|
6218
7336
|
init_html();
|
|
6219
7337
|
init_linear();
|
|
@@ -6464,7 +7582,7 @@ function authHeaders(config) {
|
|
|
6464
7582
|
case "basic": {
|
|
6465
7583
|
const user = config.username ?? "";
|
|
6466
7584
|
const pass = config.password ?? config.apiKey ?? "";
|
|
6467
|
-
headers.authorization = `Basic ${
|
|
7585
|
+
headers.authorization = `Basic ${import_node_buffer8.Buffer.from(`${user}:${pass}`).toString("base64")}`;
|
|
6468
7586
|
break;
|
|
6469
7587
|
}
|
|
6470
7588
|
case "x-api-key": {
|
|
@@ -6911,10 +8029,10 @@ function replyText(api, reply2) {
|
|
|
6911
8029
|
}
|
|
6912
8030
|
return reply2?.choices?.[0]?.message?.content || null;
|
|
6913
8031
|
}
|
|
6914
|
-
var
|
|
8032
|
+
var import_node_buffer8, import_node_crypto2, import_node_os, import_node_process, PROVIDERS, DECISION_APIS, TOP_LOGPROBS, VERDICTS, VERDICT_CRITERIA, SIGNS, GUIDE, DEFAULT_SYSTEM_PROMPT, DECISION_SYSTEM_PROMPT, DECISION_INSTRUCTIONS, LOCALHOST, PRIVATE_HOST, REDACTIONS, THINK_OPEN, THINK_CLOSE, ANSWER_FIRST, LOCAL_CHARACTER, BREAKS2, VERDICT_WORD2, NOT, DENIED, JOINED, SPAM_LABEL, HAM_WORDS, HAM_LABEL, NOT_HAM_LABEL, UNWANTED, MIN_VERDICT_MASS, percent, MODES, LLMClassifier;
|
|
6915
8033
|
var init_llm = __esm({
|
|
6916
8034
|
"src/llm.js"() {
|
|
6917
|
-
|
|
8035
|
+
import_node_buffer8 = require("node:buffer");
|
|
6918
8036
|
import_node_crypto2 = require("node:crypto");
|
|
6919
8037
|
import_node_os = __toESM(require("node:os"), 1);
|
|
6920
8038
|
import_node_process = __toESM(require("node:process"), 1);
|
|
@@ -7666,7 +8784,7 @@ var init_package = __esm({
|
|
|
7666
8784
|
package_default = {
|
|
7667
8785
|
name: "spamscanner",
|
|
7668
8786
|
description: "Spam, phishing and malware filter for email in any language: a trainable classifier, link and attachment checks, SPF/DKIM/DMARC, and an optional AI second opinion from any LLM, including local Ollama models. Works as a library, CLI, Postfix milter or HTTP API.",
|
|
7669
|
-
version: "7.0.
|
|
8787
|
+
version: "7.0.11",
|
|
7670
8788
|
author: "Forward Email (https://forwardemail.net)",
|
|
7671
8789
|
bin: {
|
|
7672
8790
|
spamscanner: "./dist/esm/cli.js"
|
|
@@ -7855,10 +8973,10 @@ function splitMessage(raw) {
|
|
|
7855
8973
|
const match = /^\r?\n|\r?\n\r?\n/.exec(text);
|
|
7856
8974
|
if (!match) {
|
|
7857
8975
|
const newline2 = text.includes("\n") && !text.includes("\r\n") ? "\n" : "\r\n";
|
|
7858
|
-
return { header: text.replace(/\r?\n$/, ""), body:
|
|
8976
|
+
return { header: text.replace(/\r?\n$/, ""), body: import_node_buffer9.Buffer.alloc(0), newline: newline2 };
|
|
7859
8977
|
}
|
|
7860
8978
|
const newline = match[0].startsWith("\r") ? "\r\n" : "\n";
|
|
7861
|
-
return { header: text.slice(0, match.index), body: raw.subarray(
|
|
8979
|
+
return { header: text.slice(0, match.index), body: raw.subarray(import_node_buffer9.Buffer.byteLength(text.slice(0, match.index + match[0].length), "latin1")), newline };
|
|
7862
8980
|
}
|
|
7863
8981
|
function subjectTagText(tag, spaceAfter = false) {
|
|
7864
8982
|
const line = String(tag).replaceAll(new RegExp("\\p{Cc}+", "gu"), " ").trim();
|
|
@@ -7868,14 +8986,14 @@ function subjectTagText(tag, spaceAfter = false) {
|
|
|
7868
8986
|
const words2 = [];
|
|
7869
8987
|
let chunk2 = "";
|
|
7870
8988
|
for (const character of spaceAfter ? `${line} ` : line) {
|
|
7871
|
-
if (
|
|
8989
|
+
if (import_node_buffer9.Buffer.byteLength(chunk2 + character, "utf8") > ENCODED_BYTES) {
|
|
7872
8990
|
words2.push(chunk2);
|
|
7873
8991
|
chunk2 = "";
|
|
7874
8992
|
}
|
|
7875
8993
|
chunk2 += character;
|
|
7876
8994
|
}
|
|
7877
8995
|
words2.push(chunk2);
|
|
7878
|
-
return words2.map((word) => `=?UTF-8?B?${
|
|
8996
|
+
return words2.map((word) => `=?UTF-8?B?${import_node_buffer9.Buffer.from(word, "utf8").toString("base64")}?=`).join(" ");
|
|
7879
8997
|
}
|
|
7880
8998
|
function taggedSubject(tag, current, newline = "\r\n") {
|
|
7881
8999
|
const unfolded = current.replaceAll(/\r?\n/g, "");
|
|
@@ -7906,7 +9024,7 @@ function taggedSubject(tag, current, newline = "\r\n") {
|
|
|
7906
9024
|
return lines2.join(newline).slice("Subject: ".length);
|
|
7907
9025
|
}
|
|
7908
9026
|
function rewriteMessage(source, headers = [], options = {}) {
|
|
7909
|
-
const raw =
|
|
9027
|
+
const raw = import_node_buffer9.Buffer.isBuffer(source) ? source : import_node_buffer9.Buffer.from(String(source), "utf8");
|
|
7910
9028
|
const { header, body, newline } = splitMessage(raw);
|
|
7911
9029
|
const remove = options.remove ?? /^x-spam-/i;
|
|
7912
9030
|
const lines2 = header === "" ? [] : header.split(/\r?\n/);
|
|
@@ -7931,15 +9049,15 @@ function rewriteMessage(source, headers = [], options = {}) {
|
|
|
7931
9049
|
}
|
|
7932
9050
|
}
|
|
7933
9051
|
}
|
|
7934
|
-
const added = headers.map(([name, value]) => foldHeader(name,
|
|
9052
|
+
const added = headers.map(([name, value]) => foldHeader(name, import_node_buffer9.Buffer.from(String(value), "utf8").toString("latin1"), newline));
|
|
7935
9053
|
const mbox = kept.length > 0 && kept[0][0].startsWith("From ") ? kept.shift() : [];
|
|
7936
9054
|
const head = [...mbox, ...added, ...kept.map((field) => field.join(newline))].join(newline);
|
|
7937
|
-
return
|
|
9055
|
+
return import_node_buffer9.Buffer.concat([import_node_buffer9.Buffer.from(head === "" && header === "" ? newline : `${head}${newline}${newline}`, "latin1"), body]);
|
|
7938
9056
|
}
|
|
7939
|
-
var
|
|
9057
|
+
var import_node_buffer9, ENCODED_BYTES, PLAIN_WORD, ENCODED_LINE, MAX_LINE2, ENCODED_WORD, ENCODED_START;
|
|
7940
9058
|
var init_headers = __esm({
|
|
7941
9059
|
"src/headers.js"() {
|
|
7942
|
-
|
|
9060
|
+
import_node_buffer9 = require("node:buffer");
|
|
7943
9061
|
ENCODED_BYTES = 39;
|
|
7944
9062
|
PLAIN_WORD = 64;
|
|
7945
9063
|
ENCODED_LINE = 76;
|
|
@@ -8115,7 +9233,7 @@ async function* readJsonl(file, options = {}) {
|
|
|
8115
9233
|
}
|
|
8116
9234
|
async function* walk(directory) {
|
|
8117
9235
|
const entries = await import_promises.default.readdir(directory, { withFileTypes: true });
|
|
8118
|
-
entries.sort((a, b) =>
|
|
9236
|
+
entries.sort((a, b) => import_node_buffer10.Buffer.compare(import_node_buffer10.Buffer.from(a.name), import_node_buffer10.Buffer.from(b.name)));
|
|
8119
9237
|
for (const entry of entries) {
|
|
8120
9238
|
if (SKIP.has(entry.name) || entry.name.startsWith(".")) {
|
|
8121
9239
|
continue;
|
|
@@ -8140,7 +9258,7 @@ async function* readMessages(source) {
|
|
|
8140
9258
|
const handle = await import_promises.default.open(file);
|
|
8141
9259
|
let head;
|
|
8142
9260
|
try {
|
|
8143
|
-
const { buffer, bytesRead } = await handle.read(
|
|
9261
|
+
const { buffer, bytesRead } = await handle.read(import_node_buffer10.Buffer.alloc(64), 0, 64, 0);
|
|
8144
9262
|
head = buffer.subarray(0, bytesRead).toString("latin1");
|
|
8145
9263
|
} finally {
|
|
8146
9264
|
await handle.close();
|
|
@@ -8152,10 +9270,10 @@ async function* readMessages(source) {
|
|
|
8152
9270
|
}
|
|
8153
9271
|
}
|
|
8154
9272
|
}
|
|
8155
|
-
var
|
|
9273
|
+
var import_node_buffer10, import_node_fs3, import_promises, import_node_path2, import_node_readline, import_node_zlib, SKIP, SPAM_LABELS, HAM_LABELS, MAX_RECORD_LINES, MAX_RECORD_LENGTH, TEXT_NAMES, LABEL_NAMES, JSONL_LABEL_NAMES, JSONL_TEXT_NAMES;
|
|
8156
9274
|
var init_sources = __esm({
|
|
8157
9275
|
"src/sources.js"() {
|
|
8158
|
-
|
|
9276
|
+
import_node_buffer10 = require("node:buffer");
|
|
8159
9277
|
import_node_fs3 = require("node:fs");
|
|
8160
9278
|
import_promises = __toESM(require("node:fs/promises"), 1);
|
|
8161
9279
|
import_node_path2 = __toESM(require("node:path"), 1);
|
|
@@ -8329,8 +9447,8 @@ function sessionFromQuery(query) {
|
|
|
8329
9447
|
return session;
|
|
8330
9448
|
}
|
|
8331
9449
|
function sameToken(given, expected) {
|
|
8332
|
-
const a =
|
|
8333
|
-
const b =
|
|
9450
|
+
const a = import_node_buffer11.Buffer.from(String(given));
|
|
9451
|
+
const b = import_node_buffer11.Buffer.from(String(expected));
|
|
8334
9452
|
return a.length === b.length && (0, import_node_crypto5.timingSafeEqual)(a, b);
|
|
8335
9453
|
}
|
|
8336
9454
|
function readBody(request, limit) {
|
|
@@ -8350,7 +9468,7 @@ function readBody(request, limit) {
|
|
|
8350
9468
|
reject(error);
|
|
8351
9469
|
return;
|
|
8352
9470
|
}
|
|
8353
|
-
resolve(
|
|
9471
|
+
resolve(import_node_buffer11.Buffer.concat(chunks));
|
|
8354
9472
|
});
|
|
8355
9473
|
request.on("error", reject);
|
|
8356
9474
|
});
|
|
@@ -8365,7 +9483,7 @@ function createHttpServer(scanner, options = {}) {
|
|
|
8365
9483
|
let active = 0;
|
|
8366
9484
|
const server = import_node_http2.default.createServer(async (request, response) => {
|
|
8367
9485
|
const send = (status, body, headers = {}) => {
|
|
8368
|
-
const isBuffer =
|
|
9486
|
+
const isBuffer = import_node_buffer11.Buffer.isBuffer(body);
|
|
8369
9487
|
response.writeHead(status, { "content-type": isBuffer ? "message/rfc822" : "application/json; charset=utf-8", "cache-control": "no-store", ...headers });
|
|
8370
9488
|
response.end(isBuffer ? body : `${JSON.stringify(body)}
|
|
8371
9489
|
`);
|
|
@@ -8438,14 +9556,14 @@ function createTcpServer(scanner, options = {}) {
|
|
|
8438
9556
|
timeout = 6e4,
|
|
8439
9557
|
maxConnections = MAX_CONNECTIONS
|
|
8440
9558
|
} = options;
|
|
8441
|
-
const server =
|
|
9559
|
+
const server = import_node_net5.default.createServer({ allowHalfOpen: true }, (socket) => {
|
|
8442
9560
|
const chunks = [];
|
|
8443
9561
|
let size = 0;
|
|
8444
9562
|
socket.setTimeout(timeout, () => socket.destroy());
|
|
8445
9563
|
const onEnd = async () => {
|
|
8446
9564
|
socket.setTimeout(0);
|
|
8447
9565
|
try {
|
|
8448
|
-
const result = await scanner.scan(
|
|
9566
|
+
const result = await scanner.scan(import_node_buffer11.Buffer.concat(chunks));
|
|
8449
9567
|
socket.end(json ? `${JSON.stringify(serializeResult(result))}
|
|
8450
9568
|
` : `${result.isSpam ? "SPAM" : "HAM"} ${result.score.toFixed(1)}/${result.threshold.toFixed(1)} ${result.tests.map((test) => test.name).join(",")}
|
|
8451
9569
|
`);
|
|
@@ -8474,13 +9592,13 @@ function createTcpServer(scanner, options = {}) {
|
|
|
8474
9592
|
server.maxConnections = maxConnections;
|
|
8475
9593
|
return server;
|
|
8476
9594
|
}
|
|
8477
|
-
var
|
|
9595
|
+
var import_node_buffer11, import_node_crypto5, import_node_http2, import_node_net5, MAX_MESSAGE_SIZE, MAX_CONNECTIONS;
|
|
8478
9596
|
var init_server = __esm({
|
|
8479
9597
|
"src/server.js"() {
|
|
8480
|
-
|
|
9598
|
+
import_node_buffer11 = require("node:buffer");
|
|
8481
9599
|
import_node_crypto5 = require("node:crypto");
|
|
8482
9600
|
import_node_http2 = __toESM(require("node:http"), 1);
|
|
8483
|
-
|
|
9601
|
+
import_node_net5 = __toESM(require("node:net"), 1);
|
|
8484
9602
|
init_headers();
|
|
8485
9603
|
init_version();
|
|
8486
9604
|
MAX_MESSAGE_SIZE = 25 * 1024 * 1024;
|
|
@@ -8489,12 +9607,12 @@ var init_server = __esm({
|
|
|
8489
9607
|
});
|
|
8490
9608
|
|
|
8491
9609
|
// src/milter.js
|
|
8492
|
-
function packet(command, data2 =
|
|
8493
|
-
const payload =
|
|
8494
|
-
const header =
|
|
9610
|
+
function packet(command, data2 = import_node_buffer12.Buffer.alloc(0)) {
|
|
9611
|
+
const payload = import_node_buffer12.Buffer.isBuffer(data2) ? data2 : import_node_buffer12.Buffer.from(data2, "latin1");
|
|
9612
|
+
const header = import_node_buffer12.Buffer.alloc(5);
|
|
8495
9613
|
header.writeUInt32BE(payload.length + 1);
|
|
8496
9614
|
header.write(command, 4, "latin1");
|
|
8497
|
-
return
|
|
9615
|
+
return import_node_buffer12.Buffer.concat([header, payload]);
|
|
8498
9616
|
}
|
|
8499
9617
|
function cstrings(data2) {
|
|
8500
9618
|
const parts = data2.toString("latin1").split("\0");
|
|
@@ -8504,19 +9622,19 @@ function cstrings(data2) {
|
|
|
8504
9622
|
return parts;
|
|
8505
9623
|
}
|
|
8506
9624
|
function cstring(value) {
|
|
8507
|
-
return
|
|
9625
|
+
return import_node_buffer12.Buffer.from(`${value}\0`, "latin1");
|
|
8508
9626
|
}
|
|
8509
9627
|
function address(value) {
|
|
8510
9628
|
const text = String(value ?? "").trim();
|
|
8511
9629
|
const match = /^<?([^<>]*)>?$/.exec(text);
|
|
8512
9630
|
return match ? match[1] : text;
|
|
8513
9631
|
}
|
|
8514
|
-
var
|
|
9632
|
+
var import_node_buffer12, import_node_events, import_node_net6, COMMANDS, RESPONSES, ACTIONS, PROTOCOL, MAX_PACKET, MilterSession, MilterServer;
|
|
8515
9633
|
var init_milter = __esm({
|
|
8516
9634
|
"src/milter.js"() {
|
|
8517
|
-
|
|
9635
|
+
import_node_buffer12 = require("node:buffer");
|
|
8518
9636
|
import_node_events = require("node:events");
|
|
8519
|
-
|
|
9637
|
+
import_node_net6 = __toESM(require("node:net"), 1);
|
|
8520
9638
|
init_headers();
|
|
8521
9639
|
init_auth();
|
|
8522
9640
|
init_server();
|
|
@@ -8634,7 +9752,7 @@ var init_milter = __esm({
|
|
|
8634
9752
|
if (this.buffered < this.needed) {
|
|
8635
9753
|
return;
|
|
8636
9754
|
}
|
|
8637
|
-
let buffer = this.chunks.length === 1 ? this.chunks[0] :
|
|
9755
|
+
let buffer = this.chunks.length === 1 ? this.chunks[0] : import_node_buffer12.Buffer.concat(this.chunks);
|
|
8638
9756
|
this.needed = 4;
|
|
8639
9757
|
while (buffer.length >= 4) {
|
|
8640
9758
|
const length = buffer.readUInt32BE(0);
|
|
@@ -8679,7 +9797,7 @@ var init_milter = __esm({
|
|
|
8679
9797
|
const protocol = data2.readUInt32BE(8);
|
|
8680
9798
|
const wanted = ACTIONS.ADDHDRS | ACTIONS.CHGHDRS | ACTIONS.QUARANTINE;
|
|
8681
9799
|
this.leadingSpace = Boolean(protocol & PROTOCOL.HDR_LEADSPC);
|
|
8682
|
-
const reply2 =
|
|
9800
|
+
const reply2 = import_node_buffer12.Buffer.alloc(12);
|
|
8683
9801
|
reply2.writeUInt32BE(Math.min(version, 6), 0);
|
|
8684
9802
|
reply2.writeUInt32BE(actions & wanted, 4);
|
|
8685
9803
|
reply2.writeUInt32BE(protocol & (PROTOCOL.HDR_LEADSPC | PROTOCOL.NOUNKNOWN), 8);
|
|
@@ -8744,7 +9862,7 @@ var init_milter = __esm({
|
|
|
8744
9862
|
if (this.truncated || this.size + data2.length > options.maxSize) {
|
|
8745
9863
|
this.truncated = true;
|
|
8746
9864
|
} else {
|
|
8747
|
-
this.body.push(
|
|
9865
|
+
this.body.push(import_node_buffer12.Buffer.from(data2));
|
|
8748
9866
|
this.size += data2.length;
|
|
8749
9867
|
}
|
|
8750
9868
|
this.send(RESPONSES.CONTINUE);
|
|
@@ -8779,7 +9897,7 @@ var init_milter = __esm({
|
|
|
8779
9897
|
/** @returns {Buffer} */
|
|
8780
9898
|
rawMessage() {
|
|
8781
9899
|
const head = this.headers.map(([name, value]) => `${name}:${this.leadingSpace || value.startsWith(" ") || value.startsWith(" ") ? "" : " "}${value}`).join("\r\n");
|
|
8782
|
-
return
|
|
9900
|
+
return import_node_buffer12.Buffer.concat([import_node_buffer12.Buffer.from(this.headers.length > 0 ? `${head}\r
|
|
8783
9901
|
\r
|
|
8784
9902
|
` : "\r\n", "latin1"), ...this.body]);
|
|
8785
9903
|
}
|
|
@@ -8790,9 +9908,9 @@ var init_milter = __esm({
|
|
|
8790
9908
|
const key = name.toLowerCase();
|
|
8791
9909
|
counts.set(key, (counts.get(key) || 0) + 1);
|
|
8792
9910
|
if (key.startsWith("x-spam-")) {
|
|
8793
|
-
const index =
|
|
9911
|
+
const index = import_node_buffer12.Buffer.alloc(4);
|
|
8794
9912
|
index.writeUInt32BE(counts.get(key));
|
|
8795
|
-
this.send(RESPONSES.CHGHEADER,
|
|
9913
|
+
this.send(RESPONSES.CHGHEADER, import_node_buffer12.Buffer.concat([index, cstring(name), cstring("")]));
|
|
8796
9914
|
}
|
|
8797
9915
|
}
|
|
8798
9916
|
}
|
|
@@ -8815,7 +9933,7 @@ var init_milter = __esm({
|
|
|
8815
9933
|
}
|
|
8816
9934
|
this.server.report(error);
|
|
8817
9935
|
this.removeForgedHeaders();
|
|
8818
|
-
this.send(RESPONSES.ADDHEADER,
|
|
9936
|
+
this.send(RESPONSES.ADDHEADER, import_node_buffer12.Buffer.concat([cstring("X-Spam-Virus-Scan"), cstring(`${this.leadingSpace ? " " : ""}failed`)]));
|
|
8819
9937
|
this.send(RESPONSES.CONTINUE);
|
|
8820
9938
|
this.resetMessage();
|
|
8821
9939
|
return;
|
|
@@ -8836,15 +9954,15 @@ var init_milter = __esm({
|
|
|
8836
9954
|
headers.unshift(["Authentication-Results", formatAuthResultsHeader(result.results.authentication, options.hostname)]);
|
|
8837
9955
|
}
|
|
8838
9956
|
for (const [name, value] of headers) {
|
|
8839
|
-
this.send(RESPONSES.ADDHEADER,
|
|
9957
|
+
this.send(RESPONSES.ADDHEADER, import_node_buffer12.Buffer.concat([cstring(name), cstring(`${this.leadingSpace ? " " : ""}${value}`.replaceAll("\r\n", "\n"))]));
|
|
8840
9958
|
}
|
|
8841
9959
|
if (result.isSpam && options.subjectTag) {
|
|
8842
9960
|
const subject = this.headers.find(([name]) => name.toLowerCase() === "subject");
|
|
8843
9961
|
const value = taggedSubject(options.subjectTag, subject ? subject[1].trim() : "", "\n");
|
|
8844
9962
|
if (value !== null) {
|
|
8845
|
-
const index =
|
|
9963
|
+
const index = import_node_buffer12.Buffer.alloc(4);
|
|
8846
9964
|
index.writeUInt32BE(1);
|
|
8847
|
-
this.send(RESPONSES.CHGHEADER,
|
|
9965
|
+
this.send(RESPONSES.CHGHEADER, import_node_buffer12.Buffer.concat([index, cstring("Subject"), cstring(`${this.leadingSpace ? " " : ""}${value}`.replaceAll("\r\n", "\n"))]));
|
|
8848
9966
|
}
|
|
8849
9967
|
}
|
|
8850
9968
|
if (result.action === "reject" && options.reject) {
|
|
@@ -8895,7 +10013,7 @@ var init_milter = __esm({
|
|
|
8895
10013
|
throw new RangeError(`rejectCode must be a 4xx or 5xx SMTP code, not ${this.options.rejectCode}`);
|
|
8896
10014
|
}
|
|
8897
10015
|
this.sockets = /* @__PURE__ */ new Set();
|
|
8898
|
-
this.server =
|
|
10016
|
+
this.server = import_node_net6.default.createServer((socket) => {
|
|
8899
10017
|
this.sockets.add(socket);
|
|
8900
10018
|
socket.on("close", () => this.sockets.delete(socket));
|
|
8901
10019
|
return new MilterSession(socket, this);
|
|
@@ -8971,7 +10089,7 @@ function reply(code, text, headers = [], body = null) {
|
|
|
8971
10089
|
lines2.push(`Content-length: ${body.length}`);
|
|
8972
10090
|
}
|
|
8973
10091
|
lines2.push(...headers.map(([name, value]) => `${name}: ${value}`), "", "");
|
|
8974
|
-
return body === null ?
|
|
10092
|
+
return body === null ? import_node_buffer13.Buffer.from(lines2.join("\r\n")) : import_node_buffer13.Buffer.concat([import_node_buffer13.Buffer.from(lines2.join("\r\n")), body]);
|
|
8975
10093
|
}
|
|
8976
10094
|
function report(result) {
|
|
8977
10095
|
const lines2 = [
|
|
@@ -9016,11 +10134,11 @@ async function answer(scanner, request, message, options) {
|
|
|
9016
10134
|
return reply(EX_OK, "EX_OK", [verdict]);
|
|
9017
10135
|
}
|
|
9018
10136
|
case "SYMBOLS": {
|
|
9019
|
-
return reply(EX_OK, "EX_OK", [verdict],
|
|
10137
|
+
return reply(EX_OK, "EX_OK", [verdict], import_node_buffer13.Buffer.from(result.tests.map((test) => test.name).join(",")));
|
|
9020
10138
|
}
|
|
9021
10139
|
case "REPORT":
|
|
9022
10140
|
case "REPORT_IFSPAM": {
|
|
9023
|
-
return reply(EX_OK, "EX_OK", [verdict], command === "REPORT" || result.isSpam ?
|
|
10141
|
+
return reply(EX_OK, "EX_OK", [verdict], command === "REPORT" || result.isSpam ? import_node_buffer13.Buffer.from(report(result)) : import_node_buffer13.Buffer.alloc(0));
|
|
9024
10142
|
}
|
|
9025
10143
|
default: {
|
|
9026
10144
|
const rewritten = rewriteMessage(message, spamHeaders(result, { version: VERSION }), { subjectTag: result.isSpam ? options.subjectTag : null });
|
|
@@ -9028,7 +10146,7 @@ async function answer(scanner, request, message, options) {
|
|
|
9028
10146
|
return reply(EX_OK, "EX_OK", [verdict], rewritten);
|
|
9029
10147
|
}
|
|
9030
10148
|
const { header, newline } = splitMessage(rewritten);
|
|
9031
|
-
return reply(EX_OK, "EX_OK", [verdict],
|
|
10149
|
+
return reply(EX_OK, "EX_OK", [verdict], import_node_buffer13.Buffer.from(`${header}${newline}${newline}`, "latin1"));
|
|
9032
10150
|
}
|
|
9033
10151
|
}
|
|
9034
10152
|
}
|
|
@@ -9042,8 +10160,8 @@ function createSpamdServer(scanner, options = {}) {
|
|
|
9042
10160
|
maxConnections: MAX_CONNECTIONS,
|
|
9043
10161
|
...options
|
|
9044
10162
|
};
|
|
9045
|
-
const server =
|
|
9046
|
-
let head =
|
|
10163
|
+
const server = import_node_net7.default.createServer({ allowHalfOpen: true }, (socket) => {
|
|
10164
|
+
let head = import_node_buffer13.Buffer.alloc(0);
|
|
9047
10165
|
const chunks = [];
|
|
9048
10166
|
let size = 0;
|
|
9049
10167
|
let request = null;
|
|
@@ -9069,7 +10187,7 @@ function createSpamdServer(scanner, options = {}) {
|
|
|
9069
10187
|
return;
|
|
9070
10188
|
}
|
|
9071
10189
|
if (!request) {
|
|
9072
|
-
head =
|
|
10190
|
+
head = import_node_buffer13.Buffer.concat([head, chunk2]);
|
|
9073
10191
|
const end = head.indexOf("\r\n\r\n");
|
|
9074
10192
|
if (end === -1) {
|
|
9075
10193
|
if (head.length > 64 * 1024) {
|
|
@@ -9104,7 +10222,7 @@ function createSpamdServer(scanner, options = {}) {
|
|
|
9104
10222
|
chunks.push(chunk2);
|
|
9105
10223
|
size += chunk2.length;
|
|
9106
10224
|
if (request.length === null ? ["PING", "SKIP"].includes(request.command) : size >= request.length) {
|
|
9107
|
-
finish(
|
|
10225
|
+
finish(import_node_buffer13.Buffer.concat(chunks).subarray(0, request.length ?? 0));
|
|
9108
10226
|
} else if (size > settings.maxSize) {
|
|
9109
10227
|
fail(EX_DATAERR, `Message larger than ${settings.maxSize} bytes`);
|
|
9110
10228
|
}
|
|
@@ -9116,7 +10234,7 @@ function createSpamdServer(scanner, options = {}) {
|
|
|
9116
10234
|
if (!request) {
|
|
9117
10235
|
fail(EX_PROTOCOL, "Incomplete request");
|
|
9118
10236
|
} else if (request.length === null) {
|
|
9119
|
-
finish(
|
|
10237
|
+
finish(import_node_buffer13.Buffer.concat(chunks));
|
|
9120
10238
|
} else {
|
|
9121
10239
|
fail(EX_PROTOCOL, `Message shorter than its Content-length of ${request.length} bytes`);
|
|
9122
10240
|
}
|
|
@@ -9127,11 +10245,11 @@ function createSpamdServer(scanner, options = {}) {
|
|
|
9127
10245
|
server.maxConnections = settings.maxConnections;
|
|
9128
10246
|
return server;
|
|
9129
10247
|
}
|
|
9130
|
-
var
|
|
10248
|
+
var import_node_buffer13, import_node_net7, EX_OK, EX_USAGE, EX_DATAERR, EX_SOFTWARE, EX_PROTOCOL, EX_NOPERM, COMMANDS2;
|
|
9131
10249
|
var init_spamd = __esm({
|
|
9132
10250
|
"src/spamd.js"() {
|
|
9133
|
-
|
|
9134
|
-
|
|
10251
|
+
import_node_buffer13 = require("node:buffer");
|
|
10252
|
+
import_node_net7 = __toESM(require("node:net"), 1);
|
|
9135
10253
|
init_headers();
|
|
9136
10254
|
init_server();
|
|
9137
10255
|
init_version();
|
|
@@ -9343,21 +10461,21 @@ async function withTimeout(promise, ms, fallback) {
|
|
|
9343
10461
|
}
|
|
9344
10462
|
}
|
|
9345
10463
|
async function toBuffer(source) {
|
|
9346
|
-
if (
|
|
10464
|
+
if (import_node_buffer14.Buffer.isBuffer(source)) {
|
|
9347
10465
|
return source;
|
|
9348
10466
|
}
|
|
9349
10467
|
if (typeof source === "string") {
|
|
9350
|
-
return
|
|
10468
|
+
return import_node_buffer14.Buffer.from(source, "utf8");
|
|
9351
10469
|
}
|
|
9352
10470
|
if (source instanceof Uint8Array) {
|
|
9353
|
-
return
|
|
10471
|
+
return import_node_buffer14.Buffer.from(source);
|
|
9354
10472
|
}
|
|
9355
10473
|
if (source && typeof source[Symbol.asyncIterator] === "function") {
|
|
9356
10474
|
const chunks = [];
|
|
9357
10475
|
for await (const chunk2 of source) {
|
|
9358
|
-
chunks.push(
|
|
10476
|
+
chunks.push(import_node_buffer14.Buffer.isBuffer(chunk2) ? chunk2 : import_node_buffer14.Buffer.from(chunk2));
|
|
9359
10477
|
}
|
|
9360
|
-
return
|
|
10478
|
+
return import_node_buffer14.Buffer.concat(chunks);
|
|
9361
10479
|
}
|
|
9362
10480
|
throw new TypeError("A message must be a Buffer, a string, a Uint8Array or a readable stream");
|
|
9363
10481
|
}
|
|
@@ -9432,12 +10550,12 @@ function fromDomain(mail) {
|
|
|
9432
10550
|
function withHeader(raw) {
|
|
9433
10551
|
const first = raw.subarray(0, 1e3).toString("latin1");
|
|
9434
10552
|
const headerless = raw.length > 0 && !/^(?:[!-9;-~]+[ \t]*:|From |[\r\n])/.test(first);
|
|
9435
|
-
return headerless ?
|
|
10553
|
+
return headerless ? import_node_buffer14.Buffer.concat([import_node_buffer14.Buffer.from("\r\n"), raw]) : raw;
|
|
9436
10554
|
}
|
|
9437
|
-
var
|
|
10555
|
+
var import_node_buffer14, import_promises2, import_node_util2, debug2, DEFAULTS2, NESTED, MAX_LOOKALIKE_HOSTS, MAX_DECEPTIVE_LINKS, CLAMAV_CONCURRENCY, CLAMAV_TIMEOUT, CLAMAV_LIMITS, MAX_NSFW_IMAGES, MAX_REPUTATION_CACHES, SpamScanner, src_default;
|
|
9438
10556
|
var init_src = __esm({
|
|
9439
10557
|
"src/index.js"() {
|
|
9440
|
-
|
|
10558
|
+
import_node_buffer14 = require("node:buffer");
|
|
9441
10559
|
import_promises2 = require("node:fs/promises");
|
|
9442
10560
|
import_node_util2 = require("node:util");
|
|
9443
10561
|
init_attachments();
|
|
@@ -9446,6 +10564,7 @@ var init_src = __esm({
|
|
|
9446
10564
|
init_classifier();
|
|
9447
10565
|
init_dnsbl();
|
|
9448
10566
|
init_html();
|
|
10567
|
+
init_links();
|
|
9449
10568
|
init_homograph();
|
|
9450
10569
|
init_is_arbitrary();
|
|
9451
10570
|
init_language();
|
|
@@ -9488,6 +10607,19 @@ var init_src = __esm({
|
|
|
9488
10607
|
cloudflare: true,
|
|
9489
10608
|
adult: true,
|
|
9490
10609
|
maxHosts: 25,
|
|
10610
|
+
// Also read the links of the whole message and of what it carries
|
|
10611
|
+
// (attached messages, HTML, SVG and XML files, text files, invitations
|
|
10612
|
+
// and contact cards, documents in iframes and data: URLs) when link
|
|
10613
|
+
// hosts are looked up, for at most five seconds: off by default, as it
|
|
10614
|
+
// reads all of it, up to 50 MB of attachments.
|
|
10615
|
+
attachments: false,
|
|
10616
|
+
// Milliseconds the link lookups may take in all (default: timeout).
|
|
10617
|
+
timeout: void 0,
|
|
10618
|
+
// Also look up host names written in the text without a link or a path
|
|
10619
|
+
// ("evil.example"), which mail clients make links of, as far as there is
|
|
10620
|
+
// room: off by default, as a quoted reply or a signature may name any
|
|
10621
|
+
// site (they are checked for lookalikes either way).
|
|
10622
|
+
hostsInText: false,
|
|
9491
10623
|
// Characters of text read for links (twice as many of HTML): more than
|
|
9492
10624
|
// for the classifier (maxLength), as a link anywhere in a message may be
|
|
9493
10625
|
// followed; a longer message sets results.linksTruncated.
|
|
@@ -9689,7 +10821,10 @@ var init_src = __esm({
|
|
|
9689
10821
|
async scanFile(file, options) {
|
|
9690
10822
|
return this.scan(await (0, import_promises2.readFile)(file), options);
|
|
9691
10823
|
}
|
|
9692
|
-
|
|
10824
|
+
// (`from`: the sender's domain; `carried`: the link hosts of the whole
|
|
10825
|
+
// message and of what it carries, see carriedLinkHosts)
|
|
10826
|
+
async checkLinks(links, config, hosts = [], options = {}) {
|
|
10827
|
+
const { from = "", carried = null } = typeof options === "string" ? { from: options } : options;
|
|
9693
10828
|
const phishing = [];
|
|
9694
10829
|
const homographs = [];
|
|
9695
10830
|
const seenHosts = /* @__PURE__ */ new Set();
|
|
@@ -9745,7 +10880,11 @@ var init_src = __esm({
|
|
|
9745
10880
|
for (const host of hosts) {
|
|
9746
10881
|
lookalike(host, { source: "text" });
|
|
9747
10882
|
}
|
|
9748
|
-
const
|
|
10883
|
+
const carriedHosts = (carried?.hosts ?? []).map((host) => lookupName(host)).filter(Boolean);
|
|
10884
|
+
for (const host of carriedHosts) {
|
|
10885
|
+
seenHosts.add(host);
|
|
10886
|
+
}
|
|
10887
|
+
const ordered = [.../* @__PURE__ */ new Set([...[...found.filter((link) => link.text), ...found.filter((link) => !link.text), ...bare].map((link) => lookupName(destination(link))).filter(Boolean), ...carriedHosts])];
|
|
9749
10888
|
const firsts = /* @__PURE__ */ new Map();
|
|
9750
10889
|
for (const host of ordered) {
|
|
9751
10890
|
const domain = registrableDomain(host);
|
|
@@ -9757,6 +10896,7 @@ var init_src = __esm({
|
|
|
9757
10896
|
const domains = [...new Set(checked.map((host) => registrableDomain(host)))];
|
|
9758
10897
|
const blocked = [];
|
|
9759
10898
|
let answered = 0;
|
|
10899
|
+
const linkTimeout = Number(config.phishing.timeout) > 0 ? Number(config.phishing.timeout) : config.timeout;
|
|
9760
10900
|
const cloudflare = async () => {
|
|
9761
10901
|
await withTimeout(Promise.all(checked.map(async (host) => {
|
|
9762
10902
|
const found2 = await this.dns.checkCloudflare([host], { adult: config.phishing.adult });
|
|
@@ -9764,12 +10904,12 @@ var init_src = __esm({
|
|
|
9764
10904
|
if (!found2.unanswered?.length) {
|
|
9765
10905
|
answered++;
|
|
9766
10906
|
}
|
|
9767
|
-
})),
|
|
10907
|
+
})), linkTimeout, null);
|
|
9768
10908
|
return { found: [...blocked], unanswered: checked.length - answered };
|
|
9769
10909
|
};
|
|
9770
10910
|
const [cloudflareResult, listed] = await Promise.all([
|
|
9771
10911
|
config.phishing.cloudflare && checked.length > 0 ? cloudflare() : { found: [], unanswered: 0 },
|
|
9772
|
-
config.dnsbl.domain?.length > 0 && domains.length > 0 ? withTimeout(this.dns.checkDomains(domains, config.dnsbl.domain),
|
|
10912
|
+
config.dnsbl.domain?.length > 0 && domains.length > 0 ? withTimeout(this.dns.checkDomains(domains, config.dnsbl.domain), linkTimeout, []) : []
|
|
9773
10913
|
]);
|
|
9774
10914
|
for (const { host, category } of cloudflareResult.found) {
|
|
9775
10915
|
phishing.push(finding(category === "malware" ? { type: "malicious_domain", domain: host, message: `Link hostname ${host} is blocked by Cloudflare's malware filtering as phishing or malware` } : { type: "adult_domain", domain: host, message: `Link hostname ${host} was detected by Cloudflare's family filtering to contain adult-related content` }));
|
|
@@ -9785,7 +10925,8 @@ var init_src = __esm({
|
|
|
9785
10925
|
return {
|
|
9786
10926
|
phishing,
|
|
9787
10927
|
homographs,
|
|
9788
|
-
|
|
10928
|
+
// (at least one when the message has more hosts than were read)
|
|
10929
|
+
uncheckedHosts: Math.max(seenHosts.size - checked.length, carried?.more ? 1 : 0),
|
|
9789
10930
|
timedOutHosts: cloudflareResult.unanswered
|
|
9790
10931
|
};
|
|
9791
10932
|
}
|
|
@@ -9957,10 +11098,17 @@ ${visibleText(html2.slice(0, config.maxLength * 2)).text}`, { maxLength: config.
|
|
|
9957
11098
|
styled: plainObfuscation.styled || shownObfuscation.styled
|
|
9958
11099
|
};
|
|
9959
11100
|
const unopened = [];
|
|
9960
|
-
const
|
|
11101
|
+
const opened = [];
|
|
11102
|
+
const attached = await expandAttachments(mail.attachments, parseErrors, void 0, { unopened, mails: opened });
|
|
11103
|
+
const carried = config.phishing.attachments === true && (config.phishing.cloudflare || config.dnsbl.domain?.length > 0) ? carriedLinkHosts(mail, {
|
|
11104
|
+
mails: opened,
|
|
11105
|
+
attachments: attached,
|
|
11106
|
+
maxHosts: config.phishing.maxHosts,
|
|
11107
|
+
hostsInText: config.phishing.hostsInText === true
|
|
11108
|
+
}) : null;
|
|
9961
11109
|
const attachments = config.attachments === false ? [] : inspectAttachments(attached).filter((item) => config.macros !== false || !["macro", "pdf_active", "rtf_object"].includes(item.type)).map((item) => finding(item));
|
|
9962
11110
|
const [links, authentication, checkedReputation, dnsbl, virusScan, toxicity, nsfw] = await Promise.all([
|
|
9963
|
-
this.checkLinks(checkedLinks, config, extracted.hosts, fromDomain(mail)),
|
|
11111
|
+
this.checkLinks(checkedLinks, config, extracted.hosts, { from: fromDomain(mail), carried }),
|
|
9964
11112
|
config.authenticationResults && typeof config.authenticationResults === "object" ? normalizeAuthOutput(config.authenticationResults) : config.authentication && session.remoteAddress ? withTimeout(authenticate(raw, {
|
|
9965
11113
|
timeout: config.timeout,
|
|
9966
11114
|
...typeof config.authentication === "object" ? config.authentication : {},
|
|
@@ -10088,6 +11236,14 @@ ${visibleText(html2.slice(0, config.maxLength * 2)).text}`, { maxLength: config.
|
|
|
10088
11236
|
// Whether the message has more text than phishing.maxLength, whose
|
|
10089
11237
|
// links were not read.
|
|
10090
11238
|
linksTruncated,
|
|
11239
|
+
// Whether a link host of the message or of what it carries was
|
|
11240
|
+
// never read whole (it runs past where long text is cut to be
|
|
11241
|
+
// read, it goes through more security gateways than are
|
|
11242
|
+
// unwrapped, or it is in more documents than are read), and whether
|
|
11243
|
+
// an attachment was left unread for time: in either case not every
|
|
11244
|
+
// link was checked (see phishing.attachments).
|
|
11245
|
+
linksTooComplex: Boolean(carried?.tooComplex),
|
|
11246
|
+
linksIncomplete: Boolean(carried?.incomplete),
|
|
10091
11247
|
idnHomographAttack: {
|
|
10092
11248
|
detected: links.homographs.length > 0,
|
|
10093
11249
|
domains: links.homographs,
|
|
@@ -10099,6 +11255,9 @@ ${visibleText(html2.slice(0, config.maxLength * 2)).text}`, { maxLength: config.
|
|
|
10099
11255
|
language: extracted.language,
|
|
10100
11256
|
tokens: extracted.words,
|
|
10101
11257
|
mail,
|
|
11258
|
+
// (the attachments of the message and of its attached messages, as
|
|
11259
|
+
// read, an attached message's named after it)
|
|
11260
|
+
attached,
|
|
10102
11261
|
version: VERSION,
|
|
10103
11262
|
metrics: { totalTime: time }
|
|
10104
11263
|
};
|