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/esm/cli.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import process4 from "node:process";
|
|
5
5
|
|
|
6
6
|
// src/cli.js
|
|
7
|
-
import { Buffer as
|
|
7
|
+
import { Buffer as Buffer15 } from "node:buffer";
|
|
8
8
|
import { spawn } from "node:child_process";
|
|
9
9
|
import {
|
|
10
10
|
createReadStream as createReadStream2,
|
|
@@ -1730,103 +1730,285 @@ var HomographDetector = class {
|
|
|
1730
1730
|
}
|
|
1731
1731
|
};
|
|
1732
1732
|
|
|
1733
|
+
// src/entities.js
|
|
1734
|
+
var NAMED = [
|
|
1735
|
+
"AElig=c6,AMP=26,Aacute=c1,Abreve=102,Acirc=c2,Acy=410,Afr=1d504,Agrave=c0,Alpha=391,Amacr=100,And=2a",
|
|
1736
|
+
"53,Aogon=104,Aopf=1d538,ApplyFunction=2061,Aring=c5,Ascr=1d49c,Assign=2254,Atilde=c3,Auml=c4,Backsla",
|
|
1737
|
+
"sh=2216,Barv=2ae7,Barwed=2306,Bcy=411,Because=2235,Bernoullis=212c,Beta=392,Bfr=1d505,Bopf=1d539,Bre",
|
|
1738
|
+
"ve=2d8,Bscr=212c,Bumpeq=224e,CHcy=427,COPY=a9,Cacute=106,Cap=22d2,CapitalDifferentialD=2145,Cayleys=",
|
|
1739
|
+
"212d,Ccaron=10c,Ccedil=c7,Ccirc=108,Cconint=2230,Cdot=10a,Cedilla=b8,CenterDot=b7,Cfr=212d,Chi=3a7,C",
|
|
1740
|
+
"ircleDot=2299,CircleMinus=2296,CirclePlus=2295,CircleTimes=2297,ClockwiseContourIntegral=2232,CloseC",
|
|
1741
|
+
"urlyDoubleQuote=201d,CloseCurlyQuote=2019,Colon=2237,Colone=2a74,Congruent=2261,Conint=222f,ContourI",
|
|
1742
|
+
"ntegral=222e,Copf=2102,Coproduct=2210,CounterClockwiseContourIntegral=2233,Cross=2a2f,Cscr=1d49e,Cup",
|
|
1743
|
+
"=22d3,CupCap=224d,DD=2145,DDotrahd=2911,DJcy=402,DScy=405,DZcy=40f,Dagger=2021,Darr=21a1,Dashv=2ae4,",
|
|
1744
|
+
"Dcaron=10e,Dcy=414,Del=2207,Delta=394,Dfr=1d507,DiacriticalAcute=b4,DiacriticalDot=2d9,DiacriticalDo",
|
|
1745
|
+
"ubleAcute=2dd,DiacriticalGrave=60,DiacriticalTilde=2dc,Diamond=22c4,DifferentialD=2146,Dopf=1d53b,Do",
|
|
1746
|
+
"t=a8,DotDot=20dc,DotEqual=2250,DoubleContourIntegral=222f,DoubleDot=a8,DoubleDownArrow=21d3,DoubleLe",
|
|
1747
|
+
"ftArrow=21d0,DoubleLeftRightArrow=21d4,DoubleLeftTee=2ae4,DoubleLongLeftArrow=27f8,DoubleLongLeftRig",
|
|
1748
|
+
"htArrow=27fa,DoubleLongRightArrow=27f9,DoubleRightArrow=21d2,DoubleRightTee=22a8,DoubleUpArrow=21d1,",
|
|
1749
|
+
"DoubleUpDownArrow=21d5,DoubleVerticalBar=2225,DownArrow=2193,DownArrowBar=2913,DownArrowUpArrow=21f5",
|
|
1750
|
+
",DownBreve=311,DownLeftRightVector=2950,DownLeftTeeVector=295e,DownLeftVector=21bd,DownLeftVectorBar",
|
|
1751
|
+
"=2956,DownRightTeeVector=295f,DownRightVector=21c1,DownRightVectorBar=2957,DownTee=22a4,DownTeeArrow",
|
|
1752
|
+
"=21a7,Downarrow=21d3,Dscr=1d49f,Dstrok=110,ENG=14a,ETH=d0,Eacute=c9,Ecaron=11a,Ecirc=ca,Ecy=42d,Edot",
|
|
1753
|
+
"=116,Efr=1d508,Egrave=c8,Element=2208,Emacr=112,EmptySmallSquare=25fb,EmptyVerySmallSquare=25ab,Eogo",
|
|
1754
|
+
"n=118,Eopf=1d53c,Epsilon=395,Equal=2a75,EqualTilde=2242,Equilibrium=21cc,Escr=2130,Esim=2a73,Eta=397",
|
|
1755
|
+
",Euml=cb,Exists=2203,ExponentialE=2147,Fcy=424,Ffr=1d509,FilledSmallSquare=25fc,FilledVerySmallSquar",
|
|
1756
|
+
"e=25aa,Fopf=1d53d,ForAll=2200,Fouriertrf=2131,Fscr=2131,GJcy=403,GT=3e,Gamma=393,Gammad=3dc,Gbreve=1",
|
|
1757
|
+
"1e,Gcedil=122,Gcirc=11c,Gcy=413,Gdot=120,Gfr=1d50a,Gg=22d9,Gopf=1d53e,GreaterEqual=2265,GreaterEqual",
|
|
1758
|
+
"Less=22db,GreaterFullEqual=2267,GreaterGreater=2aa2,GreaterLess=2277,GreaterSlantEqual=2a7e,GreaterT",
|
|
1759
|
+
"ilde=2273,Gscr=1d4a2,Gt=226b,HARDcy=42a,Hacek=2c7,Hat=5e,Hcirc=124,Hfr=210c,HilbertSpace=210b,Hopf=2",
|
|
1760
|
+
"10d,HorizontalLine=2500,Hscr=210b,Hstrok=126,HumpDownHump=224e,HumpEqual=224f,IEcy=415,IJlig=132,IOc",
|
|
1761
|
+
"y=401,Iacute=cd,Icirc=ce,Icy=418,Idot=130,Ifr=2111,Igrave=cc,Im=2111,Imacr=12a,ImaginaryI=2148,Impli",
|
|
1762
|
+
"es=21d2,Int=222c,Integral=222b,Intersection=22c2,InvisibleComma=2063,InvisibleTimes=2062,Iogon=12e,I",
|
|
1763
|
+
"opf=1d540,Iota=399,Iscr=2110,Itilde=128,Iukcy=406,Iuml=cf,Jcirc=134,Jcy=419,Jfr=1d50d,Jopf=1d541,Jsc",
|
|
1764
|
+
"r=1d4a5,Jsercy=408,Jukcy=404,KHcy=425,KJcy=40c,Kappa=39a,Kcedil=136,Kcy=41a,Kfr=1d50e,Kopf=1d542,Ksc",
|
|
1765
|
+
"r=1d4a6,LJcy=409,LT=3c,Lacute=139,Lambda=39b,Lang=27ea,Laplacetrf=2112,Larr=219e,Lcaron=13d,Lcedil=1",
|
|
1766
|
+
"3b,Lcy=41b,LeftAngleBracket=27e8,LeftArrow=2190,LeftArrowBar=21e4,LeftArrowRightArrow=21c6,LeftCeili",
|
|
1767
|
+
"ng=2308,LeftDoubleBracket=27e6,LeftDownTeeVector=2961,LeftDownVector=21c3,LeftDownVectorBar=2959,Lef",
|
|
1768
|
+
"tFloor=230a,LeftRightArrow=2194,LeftRightVector=294e,LeftTee=22a3,LeftTeeArrow=21a4,LeftTeeVector=29",
|
|
1769
|
+
"5a,LeftTriangle=22b2,LeftTriangleBar=29cf,LeftTriangleEqual=22b4,LeftUpDownVector=2951,LeftUpTeeVect",
|
|
1770
|
+
"or=2960,LeftUpVector=21bf,LeftUpVectorBar=2958,LeftVector=21bc,LeftVectorBar=2952,Leftarrow=21d0,Lef",
|
|
1771
|
+
"trightarrow=21d4,LessEqualGreater=22da,LessFullEqual=2266,LessGreater=2276,LessLess=2aa1,LessSlantEq",
|
|
1772
|
+
"ual=2a7d,LessTilde=2272,Lfr=1d50f,Ll=22d8,Lleftarrow=21da,Lmidot=13f,LongLeftArrow=27f5,LongLeftRigh",
|
|
1773
|
+
"tArrow=27f7,LongRightArrow=27f6,Longleftarrow=27f8,Longleftrightarrow=27fa,Longrightarrow=27f9,Lopf=",
|
|
1774
|
+
"1d543,LowerLeftArrow=2199,LowerRightArrow=2198,Lscr=2112,Lsh=21b0,Lstrok=141,Lt=226a,Map=2905,Mcy=41",
|
|
1775
|
+
"c,MediumSpace=205f,Mellintrf=2133,Mfr=1d510,MinusPlus=2213,Mopf=1d544,Mscr=2133,Mu=39c,NJcy=40a,Nacu",
|
|
1776
|
+
"te=143,Ncaron=147,Ncedil=145,Ncy=41d,NegativeMediumSpace=200b,NegativeThickSpace=200b,NegativeThinSp",
|
|
1777
|
+
"ace=200b,NegativeVeryThinSpace=200b,NestedGreaterGreater=226b,NestedLessLess=226a,NewLine=a,Nfr=1d51",
|
|
1778
|
+
"1,NoBreak=2060,NonBreakingSpace=a0,Nopf=2115,Not=2aec,NotCongruent=2262,NotCupCap=226d,NotDoubleVert",
|
|
1779
|
+
"icalBar=2226,NotElement=2209,NotEqual=2260,NotEqualTilde=2242.338,NotExists=2204,NotGreater=226f,Not",
|
|
1780
|
+
"GreaterEqual=2271,NotGreaterFullEqual=2267.338,NotGreaterGreater=226b.338,NotGreaterLess=2279,NotGre",
|
|
1781
|
+
"aterSlantEqual=2a7e.338,NotGreaterTilde=2275,NotHumpDownHump=224e.338,NotHumpEqual=224f.338,NotLeftT",
|
|
1782
|
+
"riangle=22ea,NotLeftTriangleBar=29cf.338,NotLeftTriangleEqual=22ec,NotLess=226e,NotLessEqual=2270,No",
|
|
1783
|
+
"tLessGreater=2278,NotLessLess=226a.338,NotLessSlantEqual=2a7d.338,NotLessTilde=2274,NotNestedGreater",
|
|
1784
|
+
"Greater=2aa2.338,NotNestedLessLess=2aa1.338,NotPrecedes=2280,NotPrecedesEqual=2aaf.338,NotPrecedesSl",
|
|
1785
|
+
"antEqual=22e0,NotReverseElement=220c,NotRightTriangle=22eb,NotRightTriangleBar=29d0.338,NotRightTria",
|
|
1786
|
+
"ngleEqual=22ed,NotSquareSubset=228f.338,NotSquareSubsetEqual=22e2,NotSquareSuperset=2290.338,NotSqua",
|
|
1787
|
+
"reSupersetEqual=22e3,NotSubset=2282.20d2,NotSubsetEqual=2288,NotSucceeds=2281,NotSucceedsEqual=2ab0.",
|
|
1788
|
+
"338,NotSucceedsSlantEqual=22e1,NotSucceedsTilde=227f.338,NotSuperset=2283.20d2,NotSupersetEqual=2289",
|
|
1789
|
+
",NotTilde=2241,NotTildeEqual=2244,NotTildeFullEqual=2247,NotTildeTilde=2249,NotVerticalBar=2224,Nscr",
|
|
1790
|
+
"=1d4a9,Ntilde=d1,Nu=39d,OElig=152,Oacute=d3,Ocirc=d4,Ocy=41e,Odblac=150,Ofr=1d512,Ograve=d2,Omacr=14",
|
|
1791
|
+
"c,Omega=3a9,Omicron=39f,Oopf=1d546,OpenCurlyDoubleQuote=201c,OpenCurlyQuote=2018,Or=2a54,Oscr=1d4aa,",
|
|
1792
|
+
"Oslash=d8,Otilde=d5,Otimes=2a37,Ouml=d6,OverBar=203e,OverBrace=23de,OverBracket=23b4,OverParenthesis",
|
|
1793
|
+
"=23dc,PartialD=2202,Pcy=41f,Pfr=1d513,Phi=3a6,Pi=3a0,PlusMinus=b1,Poincareplane=210c,Popf=2119,Pr=2a",
|
|
1794
|
+
"bb,Precedes=227a,PrecedesEqual=2aaf,PrecedesSlantEqual=227c,PrecedesTilde=227e,Prime=2033,Product=22",
|
|
1795
|
+
"0f,Proportion=2237,Proportional=221d,Pscr=1d4ab,Psi=3a8,QUOT=22,Qfr=1d514,Qopf=211a,Qscr=1d4ac,RBarr",
|
|
1796
|
+
"=2910,REG=ae,Racute=154,Rang=27eb,Rarr=21a0,Rarrtl=2916,Rcaron=158,Rcedil=156,Rcy=420,Re=211c,Revers",
|
|
1797
|
+
"eElement=220b,ReverseEquilibrium=21cb,ReverseUpEquilibrium=296f,Rfr=211c,Rho=3a1,RightAngleBracket=2",
|
|
1798
|
+
"7e9,RightArrow=2192,RightArrowBar=21e5,RightArrowLeftArrow=21c4,RightCeiling=2309,RightDoubleBracket",
|
|
1799
|
+
"=27e7,RightDownTeeVector=295d,RightDownVector=21c2,RightDownVectorBar=2955,RightFloor=230b,RightTee=",
|
|
1800
|
+
"22a2,RightTeeArrow=21a6,RightTeeVector=295b,RightTriangle=22b3,RightTriangleBar=29d0,RightTriangleEq",
|
|
1801
|
+
"ual=22b5,RightUpDownVector=294f,RightUpTeeVector=295c,RightUpVector=21be,RightUpVectorBar=2954,Right",
|
|
1802
|
+
"Vector=21c0,RightVectorBar=2953,Rightarrow=21d2,Ropf=211d,RoundImplies=2970,Rrightarrow=21db,Rscr=21",
|
|
1803
|
+
"1b,Rsh=21b1,RuleDelayed=29f4,SHCHcy=429,SHcy=428,SOFTcy=42c,Sacute=15a,Sc=2abc,Scaron=160,Scedil=15e",
|
|
1804
|
+
",Scirc=15c,Scy=421,Sfr=1d516,ShortDownArrow=2193,ShortLeftArrow=2190,ShortRightArrow=2192,ShortUpArr",
|
|
1805
|
+
"ow=2191,Sigma=3a3,SmallCircle=2218,Sopf=1d54a,Sqrt=221a,Square=25a1,SquareIntersection=2293,SquareSu",
|
|
1806
|
+
"bset=228f,SquareSubsetEqual=2291,SquareSuperset=2290,SquareSupersetEqual=2292,SquareUnion=2294,Sscr=",
|
|
1807
|
+
"1d4ae,Star=22c6,Sub=22d0,Subset=22d0,SubsetEqual=2286,Succeeds=227b,SucceedsEqual=2ab0,SucceedsSlant",
|
|
1808
|
+
"Equal=227d,SucceedsTilde=227f,SuchThat=220b,Sum=2211,Sup=22d1,Superset=2283,SupersetEqual=2287,Supse",
|
|
1809
|
+
"t=22d1,THORN=de,TRADE=2122,TSHcy=40b,TScy=426,Tab=9,Tau=3a4,Tcaron=164,Tcedil=162,Tcy=422,Tfr=1d517,",
|
|
1810
|
+
"Therefore=2234,Theta=398,ThickSpace=205f.200a,ThinSpace=2009,Tilde=223c,TildeEqual=2243,TildeFullEqu",
|
|
1811
|
+
"al=2245,TildeTilde=2248,Topf=1d54b,TripleDot=20db,Tscr=1d4af,Tstrok=166,Uacute=da,Uarr=219f,Uarrocir",
|
|
1812
|
+
"=2949,Ubrcy=40e,Ubreve=16c,Ucirc=db,Ucy=423,Udblac=170,Ufr=1d518,Ugrave=d9,Umacr=16a,UnderBar=5f,Und",
|
|
1813
|
+
"erBrace=23df,UnderBracket=23b5,UnderParenthesis=23dd,Union=22c3,UnionPlus=228e,Uogon=172,Uopf=1d54c,",
|
|
1814
|
+
"UpArrow=2191,UpArrowBar=2912,UpArrowDownArrow=21c5,UpDownArrow=2195,UpEquilibrium=296e,UpTee=22a5,Up",
|
|
1815
|
+
"TeeArrow=21a5,Uparrow=21d1,Updownarrow=21d5,UpperLeftArrow=2196,UpperRightArrow=2197,Upsi=3d2,Upsilo",
|
|
1816
|
+
"n=3a5,Uring=16e,Uscr=1d4b0,Utilde=168,Uuml=dc,VDash=22ab,Vbar=2aeb,Vcy=412,Vdash=22a9,Vdashl=2ae6,Ve",
|
|
1817
|
+
"e=22c1,Verbar=2016,Vert=2016,VerticalBar=2223,VerticalLine=7c,VerticalSeparator=2758,VerticalTilde=2",
|
|
1818
|
+
"240,VeryThinSpace=200a,Vfr=1d519,Vopf=1d54d,Vscr=1d4b1,Vvdash=22aa,Wcirc=174,Wedge=22c0,Wfr=1d51a,Wo",
|
|
1819
|
+
"pf=1d54e,Wscr=1d4b2,Xfr=1d51b,Xi=39e,Xopf=1d54f,Xscr=1d4b3,YAcy=42f,YIcy=407,YUcy=42e,Yacute=dd,Ycir",
|
|
1820
|
+
"c=176,Ycy=42b,Yfr=1d51c,Yopf=1d550,Yscr=1d4b4,Yuml=178,ZHcy=416,Zacute=179,Zcaron=17d,Zcy=417,Zdot=1",
|
|
1821
|
+
"7b,ZeroWidthSpace=200b,Zeta=396,Zfr=2128,Zopf=2124,Zscr=1d4b5,aacute=e1,abreve=103,ac=223e,acE=223e.",
|
|
1822
|
+
"333,acd=223f,acirc=e2,acute=b4,acy=430,aelig=e6,af=2061,afr=1d51e,agrave=e0,alefsym=2135,aleph=2135,",
|
|
1823
|
+
"alpha=3b1,amacr=101,amalg=2a3f,amp=26,and=2227,andand=2a55,andd=2a5c,andslope=2a58,andv=2a5a,ang=222",
|
|
1824
|
+
"0,ange=29a4,angle=2220,angmsd=2221,angmsdaa=29a8,angmsdab=29a9,angmsdac=29aa,angmsdad=29ab,angmsdae=",
|
|
1825
|
+
"29ac,angmsdaf=29ad,angmsdag=29ae,angmsdah=29af,angrt=221f,angrtvb=22be,angrtvbd=299d,angsph=2222,ang",
|
|
1826
|
+
"st=c5,angzarr=237c,aogon=105,aopf=1d552,ap=2248,apE=2a70,apacir=2a6f,ape=224a,apid=224b,apos=27,appr",
|
|
1827
|
+
"ox=2248,approxeq=224a,aring=e5,ascr=1d4b6,ast=2a,asymp=2248,asympeq=224d,atilde=e3,auml=e4,awconint=",
|
|
1828
|
+
"2233,awint=2a11,bNot=2aed,backcong=224c,backepsilon=3f6,backprime=2035,backsim=223d,backsimeq=22cd,b",
|
|
1829
|
+
"arvee=22bd,barwed=2305,barwedge=2305,bbrk=23b5,bbrktbrk=23b6,bcong=224c,bcy=431,bdquo=201e,becaus=22",
|
|
1830
|
+
"35,because=2235,bemptyv=29b0,bepsi=3f6,bernou=212c,beta=3b2,beth=2136,between=226c,bfr=1d51f,bigcap=",
|
|
1831
|
+
"22c2,bigcirc=25ef,bigcup=22c3,bigodot=2a00,bigoplus=2a01,bigotimes=2a02,bigsqcup=2a06,bigstar=2605,b",
|
|
1832
|
+
"igtriangledown=25bd,bigtriangleup=25b3,biguplus=2a04,bigvee=22c1,bigwedge=22c0,bkarow=290d,blackloze",
|
|
1833
|
+
"nge=29eb,blacksquare=25aa,blacktriangle=25b4,blacktriangledown=25be,blacktriangleleft=25c2,blacktria",
|
|
1834
|
+
"ngleright=25b8,blank=2423,blk12=2592,blk14=2591,blk34=2593,block=2588,bne=3d.20e5,bnequiv=2261.20e5,",
|
|
1835
|
+
"bnot=2310,bopf=1d553,bot=22a5,bottom=22a5,bowtie=22c8,boxDL=2557,boxDR=2554,boxDl=2556,boxDr=2553,bo",
|
|
1836
|
+
"xH=2550,boxHD=2566,boxHU=2569,boxHd=2564,boxHu=2567,boxUL=255d,boxUR=255a,boxUl=255c,boxUr=2559,boxV",
|
|
1837
|
+
"=2551,boxVH=256c,boxVL=2563,boxVR=2560,boxVh=256b,boxVl=2562,boxVr=255f,boxbox=29c9,boxdL=2555,boxdR",
|
|
1838
|
+
"=2552,boxdl=2510,boxdr=250c,boxh=2500,boxhD=2565,boxhU=2568,boxhd=252c,boxhu=2534,boxminus=229f,boxp",
|
|
1839
|
+
"lus=229e,boxtimes=22a0,boxuL=255b,boxuR=2558,boxul=2518,boxur=2514,boxv=2502,boxvH=256a,boxvL=2561,b",
|
|
1840
|
+
"oxvR=255e,boxvh=253c,boxvl=2524,boxvr=251c,bprime=2035,breve=2d8,brvbar=a6,bscr=1d4b7,bsemi=204f,bsi",
|
|
1841
|
+
"m=223d,bsime=22cd,bsol=5c,bsolb=29c5,bsolhsub=27c8,bull=2022,bullet=2022,bump=224e,bumpE=2aae,bumpe=",
|
|
1842
|
+
"224f,bumpeq=224f,cacute=107,cap=2229,capand=2a44,capbrcup=2a49,capcap=2a4b,capcup=2a47,capdot=2a40,c",
|
|
1843
|
+
"aps=2229.fe00,caret=2041,caron=2c7,ccaps=2a4d,ccaron=10d,ccedil=e7,ccirc=109,ccups=2a4c,ccupssm=2a50",
|
|
1844
|
+
",cdot=10b,cedil=b8,cemptyv=29b2,cent=a2,centerdot=b7,cfr=1d520,chcy=447,check=2713,checkmark=2713,ch",
|
|
1845
|
+
"i=3c7,cir=25cb,cirE=29c3,circ=2c6,circeq=2257,circlearrowleft=21ba,circlearrowright=21bb,circledR=ae",
|
|
1846
|
+
",circledS=24c8,circledast=229b,circledcirc=229a,circleddash=229d,cire=2257,cirfnint=2a10,cirmid=2aef",
|
|
1847
|
+
",cirscir=29c2,clubs=2663,clubsuit=2663,colon=3a,colone=2254,coloneq=2254,comma=2c,commat=40,comp=220",
|
|
1848
|
+
"1,compfn=2218,complement=2201,complexes=2102,cong=2245,congdot=2a6d,conint=222e,copf=1d554,coprod=22",
|
|
1849
|
+
"10,copy=a9,copysr=2117,crarr=21b5,cross=2717,cscr=1d4b8,csub=2acf,csube=2ad1,csup=2ad0,csupe=2ad2,ct",
|
|
1850
|
+
"dot=22ef,cudarrl=2938,cudarrr=2935,cuepr=22de,cuesc=22df,cularr=21b6,cularrp=293d,cup=222a,cupbrcap=",
|
|
1851
|
+
"2a48,cupcap=2a46,cupcup=2a4a,cupdot=228d,cupor=2a45,cups=222a.fe00,curarr=21b7,curarrm=293c,curlyeqp",
|
|
1852
|
+
"rec=22de,curlyeqsucc=22df,curlyvee=22ce,curlywedge=22cf,curren=a4,curvearrowleft=21b6,curvearrowrigh",
|
|
1853
|
+
"t=21b7,cuvee=22ce,cuwed=22cf,cwconint=2232,cwint=2231,cylcty=232d,dArr=21d3,dHar=2965,dagger=2020,da",
|
|
1854
|
+
"leth=2138,darr=2193,dash=2010,dashv=22a3,dbkarow=290f,dblac=2dd,dcaron=10f,dcy=434,dd=2146,ddagger=2",
|
|
1855
|
+
"021,ddarr=21ca,ddotseq=2a77,deg=b0,delta=3b4,demptyv=29b1,dfisht=297f,dfr=1d521,dharl=21c3,dharr=21c",
|
|
1856
|
+
"2,diam=22c4,diamond=22c4,diamondsuit=2666,diams=2666,die=a8,digamma=3dd,disin=22f2,div=f7,divide=f7,",
|
|
1857
|
+
"divideontimes=22c7,divonx=22c7,djcy=452,dlcorn=231e,dlcrop=230d,dollar=24,dopf=1d555,dot=2d9,doteq=2",
|
|
1858
|
+
"250,doteqdot=2251,dotminus=2238,dotplus=2214,dotsquare=22a1,doublebarwedge=2306,downarrow=2193,downd",
|
|
1859
|
+
"ownarrows=21ca,downharpoonleft=21c3,downharpoonright=21c2,drbkarow=2910,drcorn=231f,drcrop=230c,dscr",
|
|
1860
|
+
"=1d4b9,dscy=455,dsol=29f6,dstrok=111,dtdot=22f1,dtri=25bf,dtrif=25be,duarr=21f5,duhar=296f,dwangle=2",
|
|
1861
|
+
"9a6,dzcy=45f,dzigrarr=27ff,eDDot=2a77,eDot=2251,eacute=e9,easter=2a6e,ecaron=11b,ecir=2256,ecirc=ea,",
|
|
1862
|
+
"ecolon=2255,ecy=44d,edot=117,ee=2147,efDot=2252,efr=1d522,eg=2a9a,egrave=e8,egs=2a96,egsdot=2a98,el=",
|
|
1863
|
+
"2a99,elinters=23e7,ell=2113,els=2a95,elsdot=2a97,emacr=113,empty=2205,emptyset=2205,emptyv=2205,emsp",
|
|
1864
|
+
"=2003,emsp13=2004,emsp14=2005,eng=14b,ensp=2002,eogon=119,eopf=1d556,epar=22d5,eparsl=29e3,eplus=2a7",
|
|
1865
|
+
"1,epsi=3b5,epsilon=3b5,epsiv=3f5,eqcirc=2256,eqcolon=2255,eqsim=2242,eqslantgtr=2a96,eqslantless=2a9",
|
|
1866
|
+
"5,equals=3d,equest=225f,equiv=2261,equivDD=2a78,eqvparsl=29e5,erDot=2253,erarr=2971,escr=212f,esdot=",
|
|
1867
|
+
"2250,esim=2242,eta=3b7,eth=f0,euml=eb,euro=20ac,excl=21,exist=2203,expectation=2130,exponentiale=214",
|
|
1868
|
+
"7,fallingdotseq=2252,fcy=444,female=2640,ffilig=fb03,fflig=fb00,ffllig=fb04,ffr=1d523,filig=fb01,fjl",
|
|
1869
|
+
"ig=66.6a,flat=266d,fllig=fb02,fltns=25b1,fnof=192,fopf=1d557,forall=2200,fork=22d4,forkv=2ad9,fparti",
|
|
1870
|
+
"nt=2a0d,frac12=bd,frac13=2153,frac14=bc,frac15=2155,frac16=2159,frac18=215b,frac23=2154,frac25=2156,",
|
|
1871
|
+
"frac34=be,frac35=2157,frac38=215c,frac45=2158,frac56=215a,frac58=215d,frac78=215e,frasl=2044,frown=2",
|
|
1872
|
+
"322,fscr=1d4bb,gE=2267,gEl=2a8c,gacute=1f5,gamma=3b3,gammad=3dd,gap=2a86,gbreve=11f,gcirc=11d,gcy=43",
|
|
1873
|
+
"3,gdot=121,ge=2265,gel=22db,geq=2265,geqq=2267,geqslant=2a7e,ges=2a7e,gescc=2aa9,gesdot=2a80,gesdoto",
|
|
1874
|
+
"=2a82,gesdotol=2a84,gesl=22db.fe00,gesles=2a94,gfr=1d524,gg=226b,ggg=22d9,gimel=2137,gjcy=453,gl=227",
|
|
1875
|
+
"7,glE=2a92,gla=2aa5,glj=2aa4,gnE=2269,gnap=2a8a,gnapprox=2a8a,gne=2a88,gneq=2a88,gneqq=2269,gnsim=22",
|
|
1876
|
+
"e7,gopf=1d558,grave=60,gscr=210a,gsim=2273,gsime=2a8e,gsiml=2a90,gt=3e,gtcc=2aa7,gtcir=2a7a,gtdot=22",
|
|
1877
|
+
"d7,gtlPar=2995,gtquest=2a7c,gtrapprox=2a86,gtrarr=2978,gtrdot=22d7,gtreqless=22db,gtreqqless=2a8c,gt",
|
|
1878
|
+
"rless=2277,gtrsim=2273,gvertneqq=2269.fe00,gvnE=2269.fe00,hArr=21d4,hairsp=200a,half=bd,hamilt=210b,",
|
|
1879
|
+
"hardcy=44a,harr=2194,harrcir=2948,harrw=21ad,hbar=210f,hcirc=125,hearts=2665,heartsuit=2665,hellip=2",
|
|
1880
|
+
"026,hercon=22b9,hfr=1d525,hksearow=2925,hkswarow=2926,hoarr=21ff,homtht=223b,hookleftarrow=21a9,hook",
|
|
1881
|
+
"rightarrow=21aa,hopf=1d559,horbar=2015,hscr=1d4bd,hslash=210f,hstrok=127,hybull=2043,hyphen=2010,iac",
|
|
1882
|
+
"ute=ed,ic=2063,icirc=ee,icy=438,iecy=435,iexcl=a1,iff=21d4,ifr=1d526,igrave=ec,ii=2148,iiiint=2a0c,i",
|
|
1883
|
+
"iint=222d,iinfin=29dc,iiota=2129,ijlig=133,imacr=12b,image=2111,imagline=2110,imagpart=2111,imath=13",
|
|
1884
|
+
"1,imof=22b7,imped=1b5,in=2208,incare=2105,infin=221e,infintie=29dd,inodot=131,int=222b,intcal=22ba,i",
|
|
1885
|
+
"ntegers=2124,intercal=22ba,intlarhk=2a17,intprod=2a3c,iocy=451,iogon=12f,iopf=1d55a,iota=3b9,iprod=2",
|
|
1886
|
+
"a3c,iquest=bf,iscr=1d4be,isin=2208,isinE=22f9,isindot=22f5,isins=22f4,isinsv=22f3,isinv=2208,it=2062",
|
|
1887
|
+
",itilde=129,iukcy=456,iuml=ef,jcirc=135,jcy=439,jfr=1d527,jmath=237,jopf=1d55b,jscr=1d4bf,jsercy=458",
|
|
1888
|
+
",jukcy=454,kappa=3ba,kappav=3f0,kcedil=137,kcy=43a,kfr=1d528,kgreen=138,khcy=445,kjcy=45c,kopf=1d55c",
|
|
1889
|
+
",kscr=1d4c0,lAarr=21da,lArr=21d0,lAtail=291b,lBarr=290e,lE=2266,lEg=2a8b,lHar=2962,lacute=13a,laempt",
|
|
1890
|
+
"yv=29b4,lagran=2112,lambda=3bb,lang=2329,langd=2991,langle=27e8,lap=2a85,laquo=ab,larr=2190,larrb=21",
|
|
1891
|
+
"e4,larrbfs=291f,larrfs=291d,larrhk=21a9,larrlp=21ab,larrpl=2939,larrsim=2973,larrtl=21a2,lat=2aab,la",
|
|
1892
|
+
"tail=2919,late=2aad,lates=2aad.fe00,lbarr=290c,lbbrk=2772,lbrace=7b,lbrack=5b,lbrke=298b,lbrksld=298",
|
|
1893
|
+
"f,lbrkslu=298d,lcaron=13e,lcedil=13c,lceil=2308,lcub=7b,lcy=43b,ldca=2936,ldquo=201c,ldquor=201e,ldr",
|
|
1894
|
+
"dhar=2967,ldrushar=294b,ldsh=21b2,le=2264,leftarrow=2190,leftarrowtail=21a2,leftharpoondown=21bd,lef",
|
|
1895
|
+
"tharpoonup=21bc,leftleftarrows=21c7,leftrightarrow=2194,leftrightarrows=21c6,leftrightharpoons=21cb,",
|
|
1896
|
+
"leftrightsquigarrow=21ad,leftthreetimes=22cb,leg=22da,leq=2264,leqq=2266,leqslant=2a7d,les=2a7d,lesc",
|
|
1897
|
+
"c=2aa8,lesdot=2a7f,lesdoto=2a81,lesdotor=2a83,lesg=22da.fe00,lesges=2a93,lessapprox=2a85,lessdot=22d",
|
|
1898
|
+
"6,lesseqgtr=22da,lesseqqgtr=2a8b,lessgtr=2276,lesssim=2272,lfisht=297c,lfloor=230a,lfr=1d529,lg=2276",
|
|
1899
|
+
",lgE=2a91,lhard=21bd,lharu=21bc,lharul=296a,lhblk=2584,ljcy=459,ll=226a,llarr=21c7,llcorner=231e,llh",
|
|
1900
|
+
"ard=296b,lltri=25fa,lmidot=140,lmoust=23b0,lmoustache=23b0,lnE=2268,lnap=2a89,lnapprox=2a89,lne=2a87",
|
|
1901
|
+
",lneq=2a87,lneqq=2268,lnsim=22e6,loang=27ec,loarr=21fd,lobrk=27e6,longleftarrow=27f5,longleftrightar",
|
|
1902
|
+
"row=27f7,longmapsto=27fc,longrightarrow=27f6,looparrowleft=21ab,looparrowright=21ac,lopar=2985,lopf=",
|
|
1903
|
+
"1d55d,loplus=2a2d,lotimes=2a34,lowast=2217,lowbar=5f,loz=25ca,lozenge=25ca,lozf=29eb,lpar=28,lparlt=",
|
|
1904
|
+
"2993,lrarr=21c6,lrcorner=231f,lrhar=21cb,lrhard=296d,lrm=200e,lrtri=22bf,lsaquo=2039,lscr=1d4c1,lsh=",
|
|
1905
|
+
"21b0,lsim=2272,lsime=2a8d,lsimg=2a8f,lsqb=5b,lsquo=2018,lsquor=201a,lstrok=142,lt=3c,ltcc=2aa6,ltcir",
|
|
1906
|
+
"=2a79,ltdot=22d6,lthree=22cb,ltimes=22c9,ltlarr=2976,ltquest=2a7b,ltrPar=2996,ltri=25c3,ltrie=22b4,l",
|
|
1907
|
+
"trif=25c2,lurdshar=294a,luruhar=2966,lvertneqq=2268.fe00,lvnE=2268.fe00,mDDot=223a,macr=af,male=2642",
|
|
1908
|
+
",malt=2720,maltese=2720,map=21a6,mapsto=21a6,mapstodown=21a7,mapstoleft=21a4,mapstoup=21a5,marker=25",
|
|
1909
|
+
"ae,mcomma=2a29,mcy=43c,mdash=2014,measuredangle=2221,mfr=1d52a,mho=2127,micro=b5,mid=2223,midast=2a,",
|
|
1910
|
+
"midcir=2af0,middot=b7,minus=2212,minusb=229f,minusd=2238,minusdu=2a2a,mlcp=2adb,mldr=2026,mnplus=221",
|
|
1911
|
+
"3,models=22a7,mopf=1d55e,mp=2213,mscr=1d4c2,mstpos=223e,mu=3bc,multimap=22b8,mumap=22b8,nGg=22d9.338",
|
|
1912
|
+
",nGt=226b.20d2,nGtv=226b.338,nLeftarrow=21cd,nLeftrightarrow=21ce,nLl=22d8.338,nLt=226a.20d2,nLtv=22",
|
|
1913
|
+
"6a.338,nRightarrow=21cf,nVDash=22af,nVdash=22ae,nabla=2207,nacute=144,nang=2220.20d2,nap=2249,napE=2",
|
|
1914
|
+
"a70.338,napid=224b.338,napos=149,napprox=2249,natur=266e,natural=266e,naturals=2115,nbsp=a0,nbump=22",
|
|
1915
|
+
"4e.338,nbumpe=224f.338,ncap=2a43,ncaron=148,ncedil=146,ncong=2247,ncongdot=2a6d.338,ncup=2a42,ncy=43",
|
|
1916
|
+
"d,ndash=2013,ne=2260,neArr=21d7,nearhk=2924,nearr=2197,nearrow=2197,nedot=2250.338,nequiv=2262,nesea",
|
|
1917
|
+
"r=2928,nesim=2242.338,nexist=2204,nexists=2204,nfr=1d52b,ngE=2267.338,nge=2271,ngeq=2271,ngeqq=2267.",
|
|
1918
|
+
"338,ngeqslant=2a7e.338,nges=2a7e.338,ngsim=2275,ngt=226f,ngtr=226f,nhArr=21ce,nharr=21ae,nhpar=2af2,",
|
|
1919
|
+
"ni=220b,nis=22fc,nisd=22fa,niv=220b,njcy=45a,nlArr=21cd,nlE=2266.338,nlarr=219a,nldr=2025,nle=2270,n",
|
|
1920
|
+
"leftarrow=219a,nleftrightarrow=21ae,nleq=2270,nleqq=2266.338,nleqslant=2a7d.338,nles=2a7d.338,nless=",
|
|
1921
|
+
"226e,nlsim=2274,nlt=226e,nltri=22ea,nltrie=22ec,nmid=2224,nopf=1d55f,not=ac,notin=2209,notinE=22f9.3",
|
|
1922
|
+
"38,notindot=22f5.338,notinva=2209,notinvb=22f7,notinvc=22f6,notni=220c,notniva=220c,notnivb=22fe,not",
|
|
1923
|
+
"nivc=22fd,npar=2226,nparallel=2226,nparsl=2afd.20e5,npart=2202.338,npolint=2a14,npr=2280,nprcue=22e0",
|
|
1924
|
+
",npre=2aaf.338,nprec=2280,npreceq=2aaf.338,nrArr=21cf,nrarr=219b,nrarrc=2933.338,nrarrw=219d.338,nri",
|
|
1925
|
+
"ghtarrow=219b,nrtri=22eb,nrtrie=22ed,nsc=2281,nsccue=22e1,nsce=2ab0.338,nscr=1d4c3,nshortmid=2224,ns",
|
|
1926
|
+
"hortparallel=2226,nsim=2241,nsime=2244,nsimeq=2244,nsmid=2224,nspar=2226,nsqsube=22e2,nsqsupe=22e3,n",
|
|
1927
|
+
"sub=2284,nsubE=2ac5.338,nsube=2288,nsubset=2282.20d2,nsubseteq=2288,nsubseteqq=2ac5.338,nsucc=2281,n",
|
|
1928
|
+
"succeq=2ab0.338,nsup=2285,nsupE=2ac6.338,nsupe=2289,nsupset=2283.20d2,nsupseteq=2289,nsupseteqq=2ac6",
|
|
1929
|
+
".338,ntgl=2279,ntilde=f1,ntlg=2278,ntriangleleft=22ea,ntrianglelefteq=22ec,ntriangleright=22eb,ntria",
|
|
1930
|
+
"nglerighteq=22ed,nu=3bd,num=23,numero=2116,numsp=2007,nvDash=22ad,nvHarr=2904,nvap=224d.20d2,nvdash=",
|
|
1931
|
+
"22ac,nvge=2265.20d2,nvgt=3e.20d2,nvinfin=29de,nvlArr=2902,nvle=2264.20d2,nvlt=3c.20d2,nvltrie=22b4.2",
|
|
1932
|
+
"0d2,nvrArr=2903,nvrtrie=22b5.20d2,nvsim=223c.20d2,nwArr=21d6,nwarhk=2923,nwarr=2196,nwarrow=2196,nwn",
|
|
1933
|
+
"ear=2927,oS=24c8,oacute=f3,oast=229b,ocir=229a,ocirc=f4,ocy=43e,odash=229d,odblac=151,odiv=2a38,odot",
|
|
1934
|
+
"=2299,odsold=29bc,oelig=153,ofcir=29bf,ofr=1d52c,ogon=2db,ograve=f2,ogt=29c1,ohbar=29b5,ohm=3a9,oint",
|
|
1935
|
+
"=222e,olarr=21ba,olcir=29be,olcross=29bb,oline=203e,olt=29c0,omacr=14d,omega=3c9,omicron=3bf,omid=29",
|
|
1936
|
+
"b6,ominus=2296,oopf=1d560,opar=29b7,operp=29b9,oplus=2295,or=2228,orarr=21bb,ord=2a5d,order=2134,ord",
|
|
1937
|
+
"erof=2134,ordf=aa,ordm=ba,origof=22b6,oror=2a56,orslope=2a57,orv=2a5b,oscr=2134,oslash=f8,osol=2298,",
|
|
1938
|
+
"otilde=f5,otimes=2297,otimesas=2a36,ouml=f6,ovbar=233d,par=2225,para=b6,parallel=2225,parsim=2af3,pa",
|
|
1939
|
+
"rsl=2afd,part=2202,pcy=43f,percnt=25,period=2e,permil=2030,perp=22a5,pertenk=2031,pfr=1d52d,phi=3c6,",
|
|
1940
|
+
"phiv=3d5,phmmat=2133,phone=260e,pi=3c0,pitchfork=22d4,piv=3d6,planck=210f,planckh=210e,plankv=210f,p",
|
|
1941
|
+
"lus=2b,plusacir=2a23,plusb=229e,pluscir=2a22,plusdo=2214,plusdu=2a25,pluse=2a72,plusmn=b1,plussim=2a",
|
|
1942
|
+
"26,plustwo=2a27,pm=b1,pointint=2a15,popf=1d561,pound=a3,pr=227a,prE=2ab3,prap=2ab7,prcue=227c,pre=2a",
|
|
1943
|
+
"af,prec=227a,precapprox=2ab7,preccurlyeq=227c,preceq=2aaf,precnapprox=2ab9,precneqq=2ab5,precnsim=22",
|
|
1944
|
+
"e8,precsim=227e,prime=2032,primes=2119,prnE=2ab5,prnap=2ab9,prnsim=22e8,prod=220f,profalar=232e,prof",
|
|
1945
|
+
"line=2312,profsurf=2313,prop=221d,propto=221d,prsim=227e,prurel=22b0,pscr=1d4c5,psi=3c8,puncsp=2008,",
|
|
1946
|
+
"qfr=1d52e,qint=2a0c,qopf=1d562,qprime=2057,qscr=1d4c6,quaternions=210d,quatint=2a16,quest=3f,questeq",
|
|
1947
|
+
"=225f,quot=22,rAarr=21db,rArr=21d2,rAtail=291c,rBarr=290f,rHar=2964,race=223d.331,racute=155,radic=2",
|
|
1948
|
+
"21a,raemptyv=29b3,rang=232a,rangd=2992,range=29a5,rangle=27e9,raquo=bb,rarr=2192,rarrap=2975,rarrb=2",
|
|
1949
|
+
"1e5,rarrbfs=2920,rarrc=2933,rarrfs=291e,rarrhk=21aa,rarrlp=21ac,rarrpl=2945,rarrsim=2974,rarrtl=21a3",
|
|
1950
|
+
",rarrw=219d,ratail=291a,ratio=2236,rationals=211a,rbarr=290d,rbbrk=2773,rbrace=7d,rbrack=5d,rbrke=29",
|
|
1951
|
+
"8c,rbrksld=298e,rbrkslu=2990,rcaron=159,rcedil=157,rceil=2309,rcub=7d,rcy=440,rdca=2937,rdldhar=2969",
|
|
1952
|
+
",rdquo=201d,rdquor=201d,rdsh=21b3,real=211c,realine=211b,realpart=211c,reals=211d,rect=25ad,reg=ae,r",
|
|
1953
|
+
"fisht=297d,rfloor=230b,rfr=1d52f,rhard=21c1,rharu=21c0,rharul=296c,rho=3c1,rhov=3f1,rightarrow=2192,",
|
|
1954
|
+
"rightarrowtail=21a3,rightharpoondown=21c1,rightharpoonup=21c0,rightleftarrows=21c4,rightleftharpoons",
|
|
1955
|
+
"=21cc,rightrightarrows=21c9,rightsquigarrow=219d,rightthreetimes=22cc,ring=2da,risingdotseq=2253,rla",
|
|
1956
|
+
"rr=21c4,rlhar=21cc,rlm=200f,rmoust=23b1,rmoustache=23b1,rnmid=2aee,roang=27ed,roarr=21fe,robrk=27e7,",
|
|
1957
|
+
"ropar=2986,ropf=1d563,roplus=2a2e,rotimes=2a35,rpar=29,rpargt=2994,rppolint=2a12,rrarr=21c9,rsaquo=2",
|
|
1958
|
+
"03a,rscr=1d4c7,rsh=21b1,rsqb=5d,rsquo=2019,rsquor=2019,rthree=22cc,rtimes=22ca,rtri=25b9,rtrie=22b5,",
|
|
1959
|
+
"rtrif=25b8,rtriltri=29ce,ruluhar=2968,rx=211e,sacute=15b,sbquo=201a,sc=227b,scE=2ab4,scap=2ab8,scaro",
|
|
1960
|
+
"n=161,sccue=227d,sce=2ab0,scedil=15f,scirc=15d,scnE=2ab6,scnap=2aba,scnsim=22e9,scpolint=2a13,scsim=",
|
|
1961
|
+
"227f,scy=441,sdot=22c5,sdotb=22a1,sdote=2a66,seArr=21d8,searhk=2925,searr=2198,searrow=2198,sect=a7,",
|
|
1962
|
+
"semi=3b,seswar=2929,setminus=2216,setmn=2216,sext=2736,sfr=1d530,sfrown=2322,sharp=266f,shchcy=449,s",
|
|
1963
|
+
"hcy=448,shortmid=2223,shortparallel=2225,shy=ad,sigma=3c3,sigmaf=3c2,sigmav=3c2,sim=223c,simdot=2a6a",
|
|
1964
|
+
",sime=2243,simeq=2243,simg=2a9e,simgE=2aa0,siml=2a9d,simlE=2a9f,simne=2246,simplus=2a24,simrarr=2972",
|
|
1965
|
+
",slarr=2190,smallsetminus=2216,smashp=2a33,smeparsl=29e4,smid=2223,smile=2323,smt=2aaa,smte=2aac,smt",
|
|
1966
|
+
"es=2aac.fe00,softcy=44c,sol=2f,solb=29c4,solbar=233f,sopf=1d564,spades=2660,spadesuit=2660,spar=2225",
|
|
1967
|
+
",sqcap=2293,sqcaps=2293.fe00,sqcup=2294,sqcups=2294.fe00,sqsub=228f,sqsube=2291,sqsubset=228f,sqsubs",
|
|
1968
|
+
"eteq=2291,sqsup=2290,sqsupe=2292,sqsupset=2290,sqsupseteq=2292,squ=25a1,square=25a1,squarf=25aa,squf",
|
|
1969
|
+
"=25aa,srarr=2192,sscr=1d4c8,ssetmn=2216,ssmile=2323,sstarf=22c6,star=2606,starf=2605,straightepsilon",
|
|
1970
|
+
"=3f5,straightphi=3d5,strns=af,sub=2282,subE=2ac5,subdot=2abd,sube=2286,subedot=2ac3,submult=2ac1,sub",
|
|
1971
|
+
"nE=2acb,subne=228a,subplus=2abf,subrarr=2979,subset=2282,subseteq=2286,subseteqq=2ac5,subsetneq=228a",
|
|
1972
|
+
",subsetneqq=2acb,subsim=2ac7,subsub=2ad5,subsup=2ad3,succ=227b,succapprox=2ab8,succcurlyeq=227d,succ",
|
|
1973
|
+
"eq=2ab0,succnapprox=2aba,succneqq=2ab6,succnsim=22e9,succsim=227f,sum=2211,sung=266a,sup=2283,sup1=b",
|
|
1974
|
+
"9,sup2=b2,sup3=b3,supE=2ac6,supdot=2abe,supdsub=2ad8,supe=2287,supedot=2ac4,suphsol=27c9,suphsub=2ad",
|
|
1975
|
+
"7,suplarr=297b,supmult=2ac2,supnE=2acc,supne=228b,supplus=2ac0,supset=2283,supseteq=2287,supseteqq=2",
|
|
1976
|
+
"ac6,supsetneq=228b,supsetneqq=2acc,supsim=2ac8,supsub=2ad4,supsup=2ad6,swArr=21d9,swarhk=2926,swarr=",
|
|
1977
|
+
"2199,swarrow=2199,swnwar=292a,szlig=df,target=2316,tau=3c4,tbrk=23b4,tcaron=165,tcedil=163,tcy=442,t",
|
|
1978
|
+
"dot=20db,telrec=2315,tfr=1d531,there4=2234,therefore=2234,theta=3b8,thetasym=3d1,thetav=3d1,thickapp",
|
|
1979
|
+
"rox=2248,thicksim=223c,thinsp=2009,thkap=2248,thksim=223c,thorn=fe,tilde=2dc,times=d7,timesb=22a0,ti",
|
|
1980
|
+
"mesbar=2a31,timesd=2a30,tint=222d,toea=2928,top=22a4,topbot=2336,topcir=2af1,topf=1d565,topfork=2ada",
|
|
1981
|
+
",tosa=2929,tprime=2034,trade=2122,triangle=25b5,triangledown=25bf,triangleleft=25c3,trianglelefteq=2",
|
|
1982
|
+
"2b4,triangleq=225c,triangleright=25b9,trianglerighteq=22b5,tridot=25ec,trie=225c,triminus=2a3a,tripl",
|
|
1983
|
+
"us=2a39,trisb=29cd,tritime=2a3b,trpezium=23e2,tscr=1d4c9,tscy=446,tshcy=45b,tstrok=167,twixt=226c,tw",
|
|
1984
|
+
"oheadleftarrow=219e,twoheadrightarrow=21a0,uArr=21d1,uHar=2963,uacute=fa,uarr=2191,ubrcy=45e,ubreve=",
|
|
1985
|
+
"16d,ucirc=fb,ucy=443,udarr=21c5,udblac=171,udhar=296e,ufisht=297e,ufr=1d532,ugrave=f9,uharl=21bf,uha",
|
|
1986
|
+
"rr=21be,uhblk=2580,ulcorn=231c,ulcorner=231c,ulcrop=230f,ultri=25f8,umacr=16b,uml=a8,uogon=173,uopf=",
|
|
1987
|
+
"1d566,uparrow=2191,updownarrow=2195,upharpoonleft=21bf,upharpoonright=21be,uplus=228e,upsi=3c5,upsih",
|
|
1988
|
+
"=3d2,upsilon=3c5,upuparrows=21c8,urcorn=231d,urcorner=231d,urcrop=230e,uring=16f,urtri=25f9,uscr=1d4",
|
|
1989
|
+
"ca,utdot=22f0,utilde=169,utri=25b5,utrif=25b4,uuarr=21c8,uuml=fc,uwangle=29a7,vArr=21d5,vBar=2ae8,vB",
|
|
1990
|
+
"arv=2ae9,vDash=22a8,vangrt=299c,varepsilon=3f5,varkappa=3f0,varnothing=2205,varphi=3d5,varpi=3d6,var",
|
|
1991
|
+
"propto=221d,varr=2195,varrho=3f1,varsigma=3c2,varsubsetneq=228a.fe00,varsubsetneqq=2acb.fe00,varsups",
|
|
1992
|
+
"etneq=228b.fe00,varsupsetneqq=2acc.fe00,vartheta=3d1,vartriangleleft=22b2,vartriangleright=22b3,vcy=",
|
|
1993
|
+
"432,vdash=22a2,vee=2228,veebar=22bb,veeeq=225a,vellip=22ee,verbar=7c,vert=7c,vfr=1d533,vltri=22b2,vn",
|
|
1994
|
+
"sub=2282.20d2,vnsup=2283.20d2,vopf=1d567,vprop=221d,vrtri=22b3,vscr=1d4cb,vsubnE=2acb.fe00,vsubne=22",
|
|
1995
|
+
"8a.fe00,vsupnE=2acc.fe00,vsupne=228b.fe00,vzigzag=299a,wcirc=175,wedbar=2a5f,wedge=2227,wedgeq=2259,",
|
|
1996
|
+
"weierp=2118,wfr=1d534,wopf=1d568,wp=2118,wr=2240,wreath=2240,wscr=1d4cc,xcap=22c2,xcirc=25ef,xcup=22",
|
|
1997
|
+
"c3,xdtri=25bd,xfr=1d535,xhArr=27fa,xharr=27f7,xi=3be,xlArr=27f8,xlarr=27f5,xmap=27fc,xnis=22fb,xodot",
|
|
1998
|
+
"=2a00,xopf=1d569,xoplus=2a01,xotime=2a02,xrArr=27f9,xrarr=27f6,xscr=1d4cd,xsqcup=2a06,xuplus=2a04,xu",
|
|
1999
|
+
"tri=25b3,xvee=22c1,xwedge=22c0,yacute=fd,yacy=44f,ycirc=177,ycy=44b,yen=a5,yfr=1d536,yicy=457,yopf=1",
|
|
2000
|
+
"d56a,yscr=1d4ce,yucy=44e,yuml=ff,zacute=17a,zcaron=17e,zcy=437,zdot=17c,zeetrf=2128,zeta=3b6,zfr=1d5",
|
|
2001
|
+
"37,zhcy=436,zigrarr=21dd,zopf=1d56b,zscr=1d4cf,zwj=200d,zwnj=200c"
|
|
2002
|
+
].join("");
|
|
2003
|
+
var NAMED_REFERENCES = new Map(NAMED.split(",").map((entry) => {
|
|
2004
|
+
const [name, codes] = entry.split("=");
|
|
2005
|
+
return [name, String.fromCodePoint(...codes.split(".").map((code) => Number.parseInt(code, 16)))];
|
|
2006
|
+
}));
|
|
2007
|
+
|
|
1733
2008
|
// src/html.js
|
|
1734
2009
|
var 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(" ");
|
|
1735
|
-
var ENTITIES = new Map([
|
|
1736
|
-
...LATIN1.map((name, index) => [name, String.fromCodePoint(160 + index)]),
|
|
1737
|
-
["amp", "&"],
|
|
1738
|
-
["lt", "<"],
|
|
1739
|
-
["gt", ">"],
|
|
1740
|
-
["quot", '"'],
|
|
1741
|
-
["apos", "'"],
|
|
1742
|
-
["AMP", "&"],
|
|
1743
|
-
["LT", "<"],
|
|
1744
|
-
["GT", ">"],
|
|
1745
|
-
["QUOT", '"'],
|
|
1746
|
-
["COPY", "\xA9"],
|
|
1747
|
-
["REG", "\xAE"],
|
|
1748
|
-
["OElig", "\u0152"],
|
|
1749
|
-
["oelig", "\u0153"],
|
|
1750
|
-
["Scaron", "\u0160"],
|
|
1751
|
-
["scaron", "\u0161"],
|
|
1752
|
-
["Yuml", "\u0178"],
|
|
1753
|
-
["fnof", "\u0192"],
|
|
1754
|
-
["circ", "\u02C6"],
|
|
1755
|
-
["tilde", "\u02DC"],
|
|
1756
|
-
["ensp", "\u2002"],
|
|
1757
|
-
["emsp", "\u2003"],
|
|
1758
|
-
["thinsp", "\u2009"],
|
|
1759
|
-
["zwnj", "\u200C"],
|
|
1760
|
-
["zwj", "\u200D"],
|
|
1761
|
-
["lrm", "\u200E"],
|
|
1762
|
-
["rlm", "\u200F"],
|
|
1763
|
-
["ndash", "\u2013"],
|
|
1764
|
-
["mdash", "\u2014"],
|
|
1765
|
-
["lsquo", "\u2018"],
|
|
1766
|
-
["rsquo", "\u2019"],
|
|
1767
|
-
["sbquo", "\u201A"],
|
|
1768
|
-
["ldquo", "\u201C"],
|
|
1769
|
-
["rdquo", "\u201D"],
|
|
1770
|
-
["bdquo", "\u201E"],
|
|
1771
|
-
["dagger", "\u2020"],
|
|
1772
|
-
["Dagger", "\u2021"],
|
|
1773
|
-
["bull", "\u2022"],
|
|
1774
|
-
["hellip", "\u2026"],
|
|
1775
|
-
["permil", "\u2030"],
|
|
1776
|
-
["prime", "\u2032"],
|
|
1777
|
-
["Prime", "\u2033"],
|
|
1778
|
-
["lsaquo", "\u2039"],
|
|
1779
|
-
["rsaquo", "\u203A"],
|
|
1780
|
-
["euro", "\u20AC"],
|
|
1781
|
-
["trade", "\u2122"],
|
|
1782
|
-
["larr", "\u2190"],
|
|
1783
|
-
["uarr", "\u2191"],
|
|
1784
|
-
["rarr", "\u2192"],
|
|
1785
|
-
["darr", "\u2193"],
|
|
1786
|
-
["hearts", "\u2665"],
|
|
1787
|
-
["check", "\u2713"],
|
|
1788
|
-
// The punctuation of a web address, as browsers read these names
|
|
1789
|
-
// ("https://bank.example@evil.example/" goes to evil.example)
|
|
1790
|
-
["Tab", " "],
|
|
1791
|
-
["NewLine", "\n"],
|
|
1792
|
-
["excl", "!"],
|
|
1793
|
-
["num", "#"],
|
|
1794
|
-
["dollar", "$"],
|
|
1795
|
-
["percnt", "%"],
|
|
1796
|
-
["lpar", "("],
|
|
1797
|
-
["rpar", ")"],
|
|
1798
|
-
["ast", "*"],
|
|
1799
|
-
["midast", "*"],
|
|
1800
|
-
["plus", "+"],
|
|
1801
|
-
["comma", ","],
|
|
1802
|
-
["period", "."],
|
|
1803
|
-
["sol", "/"],
|
|
1804
|
-
["colon", ":"],
|
|
1805
|
-
["semi", ";"],
|
|
1806
|
-
["equals", "="],
|
|
1807
|
-
["quest", "?"],
|
|
1808
|
-
["commat", "@"],
|
|
1809
|
-
["lsqb", "["],
|
|
1810
|
-
["lbrack", "["],
|
|
1811
|
-
["bsol", "\\"],
|
|
1812
|
-
["rsqb", "]"],
|
|
1813
|
-
["rbrack", "]"],
|
|
1814
|
-
["Hat", "^"],
|
|
1815
|
-
["lowbar", "_"],
|
|
1816
|
-
["UnderBar", "_"],
|
|
1817
|
-
["grave", "`"],
|
|
1818
|
-
["DiacriticalGrave", "`"],
|
|
1819
|
-
["lcub", "{"],
|
|
1820
|
-
["lbrace", "{"],
|
|
1821
|
-
["verbar", "|"],
|
|
1822
|
-
["vert", "|"],
|
|
1823
|
-
["VerticalLine", "|"],
|
|
1824
|
-
["rcub", "}"],
|
|
1825
|
-
["rbrace", "}"]
|
|
1826
|
-
]);
|
|
1827
2010
|
var LEGACY = /* @__PURE__ */ new Set([...LATIN1, "amp", "lt", "gt", "quot", "AMP", "LT", "GT", "QUOT", "COPY", "REG"]);
|
|
1828
2011
|
var LEGACY_LONGEST = Math.max(...[...LEGACY].map((name) => name.length));
|
|
1829
|
-
var 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(" "));
|
|
1830
2012
|
var 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];
|
|
1831
2013
|
var REFERENCE = /&(?:#([xX])([\da-fA-F]+)|#(\d+)|([a-zA-Z][a-zA-Z\d]{0,31}))(;?)/g;
|
|
1832
2014
|
function fromCode(code) {
|
|
@@ -1844,8 +2026,8 @@ function decodeEntities(value, { attribute = false } = {}) {
|
|
|
1844
2026
|
if (hex !== void 0 || decimal !== void 0) {
|
|
1845
2027
|
return fromCode(hex === void 0 ? Number.parseInt(decimal, 10) : Number.parseInt(hex, 16));
|
|
1846
2028
|
}
|
|
1847
|
-
if (semicolon &&
|
|
1848
|
-
return
|
|
2029
|
+
if (semicolon && NAMED_REFERENCES.has(name)) {
|
|
2030
|
+
return NAMED_REFERENCES.get(name);
|
|
1849
2031
|
}
|
|
1850
2032
|
let legacy;
|
|
1851
2033
|
for (let length = Math.min(name.length, LEGACY_LONGEST); length >= 2 && legacy === void 0; length--) {
|
|
@@ -1859,7 +2041,7 @@ function decodeEntities(value, { attribute = false } = {}) {
|
|
|
1859
2041
|
if (attribute && /[\da-zA-Z=]/.test(next)) {
|
|
1860
2042
|
return match;
|
|
1861
2043
|
}
|
|
1862
|
-
return
|
|
2044
|
+
return NAMED_REFERENCES.get(legacy) + rest;
|
|
1863
2045
|
});
|
|
1864
2046
|
}
|
|
1865
2047
|
var UNSHOWN = /* @__PURE__ */ new Set(["script", "style", "title", "noembed", "noframes", "iframe"]);
|
|
@@ -3005,7 +3187,7 @@ function endsInsideTag(html, end, link) {
|
|
|
3005
3187
|
return joined !== host && (!isHost(host) || isHost(joined) && registrableDomain(joined) !== registrableDomain(host));
|
|
3006
3188
|
}
|
|
3007
3189
|
var MAX_SHOWN_HTML = 2e5;
|
|
3008
|
-
function extractLinks(text, html, { maxLength = 5e5, bareHosts = false } = {}) {
|
|
3190
|
+
function extractLinks(text, html, { maxLength = 5e5, bareHosts: bareHosts2 = false } = {}) {
|
|
3009
3191
|
text = typeof text === "string" ? foldToAscii(text) : text;
|
|
3010
3192
|
html = typeof html === "string" ? foldToAscii(html) : html;
|
|
3011
3193
|
const links = [];
|
|
@@ -3072,7 +3254,7 @@ ${shown || ""}`;
|
|
|
3072
3254
|
}
|
|
3073
3255
|
add(link);
|
|
3074
3256
|
}
|
|
3075
|
-
if (
|
|
3257
|
+
if (bareHosts2 && index < 2) {
|
|
3076
3258
|
bareLinkHosts(read, (host) => {
|
|
3077
3259
|
bareFound.push(host);
|
|
3078
3260
|
});
|
|
@@ -5160,7 +5342,8 @@ async function parseWithin(raw, parse = parseMessage, deadline = Date.now() + PA
|
|
|
5160
5342
|
}
|
|
5161
5343
|
}
|
|
5162
5344
|
}
|
|
5163
|
-
async function expandAttachments(attachments = [], errors = [], parse = parseMessage,
|
|
5345
|
+
async function expandAttachments(attachments = [], errors = [], parse = parseMessage, gets = {}) {
|
|
5346
|
+
const { unopened = [], mails = [] } = Array.isArray(gets) ? { unopened: gets } : gets;
|
|
5164
5347
|
const all = [];
|
|
5165
5348
|
const deadline = Date.now() + PARSE_TIMEOUT;
|
|
5166
5349
|
let budget = MAX_NESTED_BYTES;
|
|
@@ -5209,6 +5392,7 @@ async function expandAttachments(attachments = [], errors = [], parse = parseMes
|
|
|
5209
5392
|
if (inner.error) {
|
|
5210
5393
|
errors.push(inner.error);
|
|
5211
5394
|
}
|
|
5395
|
+
mails.push(inner.mail);
|
|
5212
5396
|
await visit(inner.mail.attachments, prefix ? `${prefix}/${name}` : name || "attached message", depth + 1);
|
|
5213
5397
|
}
|
|
5214
5398
|
}
|
|
@@ -6089,7 +6273,7 @@ import net from "node:net";
|
|
|
6089
6273
|
var package_default = {
|
|
6090
6274
|
name: "spamscanner",
|
|
6091
6275
|
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.",
|
|
6092
|
-
version: "7.0.
|
|
6276
|
+
version: "7.0.11",
|
|
6093
6277
|
author: "Forward Email (https://forwardemail.net)",
|
|
6094
6278
|
bin: {
|
|
6095
6279
|
spamscanner: "./dist/esm/cli.js"
|
|
@@ -7629,7 +7813,7 @@ async function evaluate(classifier, examples) {
|
|
|
7629
7813
|
}
|
|
7630
7814
|
|
|
7631
7815
|
// src/index.js
|
|
7632
|
-
import { Buffer as
|
|
7816
|
+
import { Buffer as Buffer14 } from "node:buffer";
|
|
7633
7817
|
import { readFile } from "node:fs/promises";
|
|
7634
7818
|
import { debuglog as debuglog2 } from "node:util";
|
|
7635
7819
|
|
|
@@ -7780,6 +7964,7 @@ var MACRO_EXTENSIONS = /* @__PURE__ */ new Set(["docm", "dotm", "xlsm", "xltm",
|
|
|
7780
7964
|
var 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"]);
|
|
7781
7965
|
var TEMPORARY_EXTENSIONS = /* @__PURE__ */ new Set(["tmp"]);
|
|
7782
7966
|
var BIDI_CONTROLS = characterClass([[8234, 8238], [8294, 8297]], "u");
|
|
7967
|
+
var ALL_BIDI_CONTROLS = characterClass([[8234, 8238], [8294, 8297]], "gu");
|
|
7783
7968
|
var ARCHIVE_TYPES = /* @__PURE__ */ new Set(["zip", "rar", "7z", "gz", "bz2", "xz", "cab", "iso", "tar", "zst", "lzh", "ace", "arj"]);
|
|
7784
7969
|
function sniff(buffer) {
|
|
7785
7970
|
if (!Buffer11.isBuffer(buffer) || buffer.length < 4) {
|
|
@@ -7963,7 +8148,16 @@ function shorten(name, max = 100) {
|
|
|
7963
8148
|
return characters.length <= max ? name : `${characters.slice(0, max - 41).join("")}\u2026${characters.slice(-40).join("")}`;
|
|
7964
8149
|
}
|
|
7965
8150
|
function extensionOf(name) {
|
|
7966
|
-
const base = trimEndOf(String(name).toLowerCase().split(/[/\\]/).pop(), ". ");
|
|
8151
|
+
const base = trimEndOf(String(name).toLowerCase().replace(ALL_BIDI_CONTROLS, "").split(/[/\\]/).pop(), ". ");
|
|
8152
|
+
const whole = lastExtension(base);
|
|
8153
|
+
const file = base.replace(/^[a-z]:/, "");
|
|
8154
|
+
const colon = file.indexOf(":");
|
|
8155
|
+
if (colon !== -1 && /^(?::?\$data)?$/.test(file.slice(colon + 1))) {
|
|
8156
|
+
return lastExtension(trimEndOf(file.slice(0, colon), ". "));
|
|
8157
|
+
}
|
|
8158
|
+
return whole;
|
|
8159
|
+
}
|
|
8160
|
+
function lastExtension(base) {
|
|
7967
8161
|
const dot = base.lastIndexOf(".");
|
|
7968
8162
|
return dot === -1 ? "" : base.slice(dot + 1).trim();
|
|
7969
8163
|
}
|
|
@@ -8120,8 +8314,917 @@ async function scanBuffer(buffer, options = {}) {
|
|
|
8120
8314
|
throw new Error(`clamd: ${reply2 || "no reply"}`);
|
|
8121
8315
|
}
|
|
8122
8316
|
|
|
8123
|
-
// src/
|
|
8317
|
+
// src/links.js
|
|
8318
|
+
import { Buffer as Buffer13 } from "node:buffer";
|
|
8319
|
+
import { isIP as isIP3 } from "node:net";
|
|
8124
8320
|
import { parse as parseDomain3 } from "tldts";
|
|
8321
|
+
var LINK_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
8322
|
+
"href",
|
|
8323
|
+
"src",
|
|
8324
|
+
"srcset",
|
|
8325
|
+
"background",
|
|
8326
|
+
"action",
|
|
8327
|
+
"formaction",
|
|
8328
|
+
"poster",
|
|
8329
|
+
"cite",
|
|
8330
|
+
"longdesc",
|
|
8331
|
+
"xlink:href",
|
|
8332
|
+
"style",
|
|
8333
|
+
"data",
|
|
8334
|
+
"ping",
|
|
8335
|
+
// (of a <meta> refresh: "0;url=https://example.com/")
|
|
8336
|
+
"content",
|
|
8337
|
+
// (a document of its own, see linksOf)
|
|
8338
|
+
"srcdoc"
|
|
8339
|
+
]);
|
|
8340
|
+
var TAG_START = /<[a-z][^\s/>]*/gi;
|
|
8341
|
+
var URL_START = /\b(?:https?:\/\/|www\.)[^\s<>"'`]+/gi;
|
|
8342
|
+
var CSS_URL = /url\(\s*["']?([^()"']*)/gi;
|
|
8343
|
+
var CSS_IMPORT = /@import\s+["']([^"'<>]*)/gi;
|
|
8344
|
+
var LENIENT = /[\s"'/<](href|src|srcset|background|action|formaction|poster|cite|longdesc|xlink:href|style|data|ping|content|srcdoc)\s*=\s*/gi;
|
|
8345
|
+
var IN_WORD2 = /[\p{L}\p{N}\p{M}_%]/u;
|
|
8346
|
+
var NAMESPACES = /* @__PURE__ */ new Set(["www.w3.org", "w3.org"]);
|
|
8347
|
+
var MAX_HOST = 760;
|
|
8348
|
+
var MAX_SEEN = 1e5;
|
|
8349
|
+
var TRAILING = /* @__PURE__ */ new Set([")", ".", ",", ";", ":", "!", "?", "'", '"', "]"]);
|
|
8350
|
+
var DECODE_CHUNK = 1024 * 1024;
|
|
8351
|
+
var CHUNK_OVERLAP = 4096;
|
|
8352
|
+
var MAX_EMBED_DEPTH = 3;
|
|
8353
|
+
var MAX_EMBEDDED = 1e3;
|
|
8354
|
+
var MAX_EMBEDDED_LENGTH = 10 * 1024 * 1024;
|
|
8355
|
+
var MAX_ATTACHED = 100;
|
|
8356
|
+
var MAX_ATTACHED_BYTES = 50 * 1024 * 1024;
|
|
8357
|
+
var MAX_READ_TIME = 5e3;
|
|
8358
|
+
var MAX_SHOWN_BYTES = 4 * 1024 * 1024;
|
|
8359
|
+
function isHostCode2(code) {
|
|
8360
|
+
return code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 48 && code <= 57 || code === 45 || code === 46;
|
|
8361
|
+
}
|
|
8362
|
+
function isSpace(code) {
|
|
8363
|
+
return code === 32 || code >= 9 && code <= 13;
|
|
8364
|
+
}
|
|
8365
|
+
function urlOf(value) {
|
|
8366
|
+
let href = value.replaceAll(/[\t\n\r]/g, "");
|
|
8367
|
+
let start = 0;
|
|
8368
|
+
let end = href.length;
|
|
8369
|
+
while (start < end && href.codePointAt(start) <= 32) {
|
|
8370
|
+
start++;
|
|
8371
|
+
}
|
|
8372
|
+
while (end > start && href.codePointAt(end - 1) <= 32) {
|
|
8373
|
+
end--;
|
|
8374
|
+
}
|
|
8375
|
+
while (end > start && TRAILING.has(href[end - 1])) {
|
|
8376
|
+
end--;
|
|
8377
|
+
}
|
|
8378
|
+
href = href.slice(start, end);
|
|
8379
|
+
if (/^[\\/]{2}/.test(href)) {
|
|
8380
|
+
href = `https://${href.slice(2)}`;
|
|
8381
|
+
} else if (/^www\./i.test(href)) {
|
|
8382
|
+
href = `http://${href}`;
|
|
8383
|
+
} else if (!/^https?:/i.test(href)) {
|
|
8384
|
+
return null;
|
|
8385
|
+
}
|
|
8386
|
+
try {
|
|
8387
|
+
return new URL(href);
|
|
8388
|
+
} catch {
|
|
8389
|
+
return null;
|
|
8390
|
+
}
|
|
8391
|
+
}
|
|
8392
|
+
function hostOfUrl(url) {
|
|
8393
|
+
let host = url.hostname.toLowerCase();
|
|
8394
|
+
let dots = host.length;
|
|
8395
|
+
while (dots > 0 && host[dots - 1] === ".") {
|
|
8396
|
+
dots--;
|
|
8397
|
+
}
|
|
8398
|
+
host = host.slice(0, dots);
|
|
8399
|
+
if (host.startsWith("[") && host.endsWith("]")) {
|
|
8400
|
+
host = host.slice(1, -1);
|
|
8401
|
+
}
|
|
8402
|
+
if (!host || NAMESPACES.has(host)) {
|
|
8403
|
+
return null;
|
|
8404
|
+
}
|
|
8405
|
+
return isIP3(host) ? host : lookupName(host);
|
|
8406
|
+
}
|
|
8407
|
+
function hostsOf(value) {
|
|
8408
|
+
const url = urlOf(value);
|
|
8409
|
+
if (!url) {
|
|
8410
|
+
return [];
|
|
8411
|
+
}
|
|
8412
|
+
const host = hostOfUrl(url);
|
|
8413
|
+
const hosts = host ? [host] : [];
|
|
8414
|
+
const target = unwrapLink(url.href);
|
|
8415
|
+
if (target && target.href !== url.href) {
|
|
8416
|
+
const targetHost = hostOfUrl(target);
|
|
8417
|
+
if (targetHost && targetHost !== host) {
|
|
8418
|
+
hosts.push(targetHost);
|
|
8419
|
+
}
|
|
8420
|
+
const further = unwrapLink(target.href);
|
|
8421
|
+
if (further && further.href !== target.href) {
|
|
8422
|
+
hosts.unresolved = true;
|
|
8423
|
+
}
|
|
8424
|
+
}
|
|
8425
|
+
return hosts;
|
|
8426
|
+
}
|
|
8427
|
+
function* attributesOf(html) {
|
|
8428
|
+
TAG_START.lastIndex = 0;
|
|
8429
|
+
let match;
|
|
8430
|
+
while ((match = TAG_START.exec(html)) !== null) {
|
|
8431
|
+
let i = match.index + match[0].length;
|
|
8432
|
+
while (i < html.length && html[i] !== ">") {
|
|
8433
|
+
if (isSpace(html.codePointAt(i)) || html[i] === "/") {
|
|
8434
|
+
i++;
|
|
8435
|
+
continue;
|
|
8436
|
+
}
|
|
8437
|
+
let j = i;
|
|
8438
|
+
while (j < html.length && html[j] !== "=" && html[j] !== ">" && html[j] !== "/" && !isSpace(html.codePointAt(j))) {
|
|
8439
|
+
j++;
|
|
8440
|
+
}
|
|
8441
|
+
const name = html.slice(i, j).toLowerCase();
|
|
8442
|
+
if (j === i) {
|
|
8443
|
+
j++;
|
|
8444
|
+
}
|
|
8445
|
+
while (j < html.length && isSpace(html.codePointAt(j))) {
|
|
8446
|
+
j++;
|
|
8447
|
+
}
|
|
8448
|
+
if (html[j] !== "=") {
|
|
8449
|
+
i = j;
|
|
8450
|
+
continue;
|
|
8451
|
+
}
|
|
8452
|
+
j++;
|
|
8453
|
+
while (j < html.length && isSpace(html.codePointAt(j))) {
|
|
8454
|
+
j++;
|
|
8455
|
+
}
|
|
8456
|
+
let value;
|
|
8457
|
+
if (html[j] === '"' || html[j] === "'") {
|
|
8458
|
+
const close = html.indexOf(html[j], j + 1);
|
|
8459
|
+
const stop = close === -1 ? html.length : close;
|
|
8460
|
+
value = html.slice(j + 1, stop);
|
|
8461
|
+
j = stop + 1;
|
|
8462
|
+
} else {
|
|
8463
|
+
const start = j;
|
|
8464
|
+
while (j < html.length && html[j] !== ">" && !isSpace(html.codePointAt(j))) {
|
|
8465
|
+
j++;
|
|
8466
|
+
}
|
|
8467
|
+
value = html.slice(start, j);
|
|
8468
|
+
}
|
|
8469
|
+
if (name) {
|
|
8470
|
+
yield [name, value];
|
|
8471
|
+
}
|
|
8472
|
+
i = j;
|
|
8473
|
+
}
|
|
8474
|
+
TAG_START.lastIndex = Math.max(i, match.index + 1);
|
|
8475
|
+
}
|
|
8476
|
+
}
|
|
8477
|
+
function linksOf(name, value, add, embed) {
|
|
8478
|
+
const decoded = decodeEntities(value, { attribute: true });
|
|
8479
|
+
switch (name) {
|
|
8480
|
+
case "srcdoc": {
|
|
8481
|
+
embed(decoded);
|
|
8482
|
+
break;
|
|
8483
|
+
}
|
|
8484
|
+
case "style": {
|
|
8485
|
+
for (const [, link] of decoded.matchAll(CSS_URL)) {
|
|
8486
|
+
add(link);
|
|
8487
|
+
}
|
|
8488
|
+
break;
|
|
8489
|
+
}
|
|
8490
|
+
case "srcset": {
|
|
8491
|
+
for (const candidate of decoded.split(",")) {
|
|
8492
|
+
add(candidate.trim().split(/\s/, 1)[0]);
|
|
8493
|
+
}
|
|
8494
|
+
break;
|
|
8495
|
+
}
|
|
8496
|
+
// (several, separated by spaces)
|
|
8497
|
+
case "ping": {
|
|
8498
|
+
for (const link of decoded.split(/\s+/)) {
|
|
8499
|
+
add(link);
|
|
8500
|
+
}
|
|
8501
|
+
break;
|
|
8502
|
+
}
|
|
8503
|
+
// (only the address of a refresh)
|
|
8504
|
+
case "content": {
|
|
8505
|
+
const match = /(?:^|[\s;,])url\s*=\s*["']?([^\s"';]+)/i.exec(decoded.slice(0, 4096));
|
|
8506
|
+
if (match) {
|
|
8507
|
+
add(match[1]);
|
|
8508
|
+
}
|
|
8509
|
+
break;
|
|
8510
|
+
}
|
|
8511
|
+
default: {
|
|
8512
|
+
add(decoded);
|
|
8513
|
+
}
|
|
8514
|
+
}
|
|
8515
|
+
}
|
|
8516
|
+
var MAX_LENIENT_VALUE = 4096;
|
|
8517
|
+
var UNQUOTED_END = /* @__PURE__ */ new Set(["<", ">", '"', "'", "`", "="]);
|
|
8518
|
+
function lenientLinks(html, add, done, embed) {
|
|
8519
|
+
LENIENT.lastIndex = 0;
|
|
8520
|
+
let match;
|
|
8521
|
+
while (!done() && (match = LENIENT.exec(html)) !== null) {
|
|
8522
|
+
const name = match[1].toLowerCase();
|
|
8523
|
+
let i = LENIENT.lastIndex;
|
|
8524
|
+
let end = i;
|
|
8525
|
+
if (html[i] === '"' || html[i] === "'") {
|
|
8526
|
+
const quote = html[i];
|
|
8527
|
+
i++;
|
|
8528
|
+
end = i;
|
|
8529
|
+
while (end < html.length && html[end] !== quote && html[end] !== "<" && html[end] !== ">") {
|
|
8530
|
+
end++;
|
|
8531
|
+
}
|
|
8532
|
+
if (end < html.length && html[end] !== quote) {
|
|
8533
|
+
const close = html.indexOf(quote, end);
|
|
8534
|
+
if (close !== -1 && close - i <= MAX_LENIENT_VALUE) {
|
|
8535
|
+
linksOf(name, html.slice(i, close), add, embed);
|
|
8536
|
+
}
|
|
8537
|
+
}
|
|
8538
|
+
} else {
|
|
8539
|
+
while (end < html.length && !isSpace(html.codePointAt(end)) && !UNQUOTED_END.has(html[end])) {
|
|
8540
|
+
end++;
|
|
8541
|
+
}
|
|
8542
|
+
}
|
|
8543
|
+
linksOf(name, html.slice(i, end), add, embed);
|
|
8544
|
+
}
|
|
8545
|
+
}
|
|
8546
|
+
function endsLink2(text, i) {
|
|
8547
|
+
const code = text.codePointAt(i);
|
|
8548
|
+
if (code < 128) {
|
|
8549
|
+
return isSpace(code) || code === 34 || code === 39 || code === 60 || code === 62 || code === 96;
|
|
8550
|
+
}
|
|
8551
|
+
return /\s/u.test(text[i]);
|
|
8552
|
+
}
|
|
8553
|
+
function linkReader(text) {
|
|
8554
|
+
let read = 0;
|
|
8555
|
+
let space = -1;
|
|
8556
|
+
let scheme = -1;
|
|
8557
|
+
return (start) => {
|
|
8558
|
+
for (; read < start; read++) {
|
|
8559
|
+
if (endsLink2(text, read)) {
|
|
8560
|
+
space = read;
|
|
8561
|
+
} else if (text[read] === "/" && text[read - 1] === "/" && text[read - 2] === ":") {
|
|
8562
|
+
scheme = read;
|
|
8563
|
+
}
|
|
8564
|
+
}
|
|
8565
|
+
return scheme > space;
|
|
8566
|
+
};
|
|
8567
|
+
}
|
|
8568
|
+
function isSchemeless(text, start) {
|
|
8569
|
+
if (start < 2 || text[start - 2] !== "/") {
|
|
8570
|
+
return false;
|
|
8571
|
+
}
|
|
8572
|
+
if (start === 2) {
|
|
8573
|
+
return true;
|
|
8574
|
+
}
|
|
8575
|
+
const before = text[start - 3];
|
|
8576
|
+
return !(before === ":" || before === "/" || isHostCode2(text.codePointAt(start - 3)));
|
|
8577
|
+
}
|
|
8578
|
+
function bareName(name) {
|
|
8579
|
+
const labels = name.split(".");
|
|
8580
|
+
const tld = labels.pop();
|
|
8581
|
+
if (!/^(?:[a-z]{2,24}|xn--[a-z\d-]{1,59})$/i.test(tld)) {
|
|
8582
|
+
return null;
|
|
8583
|
+
}
|
|
8584
|
+
const names = [];
|
|
8585
|
+
while (labels.length > 0 && names.length < 11) {
|
|
8586
|
+
const label = labels.pop();
|
|
8587
|
+
if (!/^[a-z\d-]{1,63}$/i.test(label)) {
|
|
8588
|
+
break;
|
|
8589
|
+
}
|
|
8590
|
+
names.unshift(label);
|
|
8591
|
+
}
|
|
8592
|
+
if (names.length === 0) {
|
|
8593
|
+
return null;
|
|
8594
|
+
}
|
|
8595
|
+
names[0] = names[0].replace(/^-+/, "");
|
|
8596
|
+
if (!names[0]) {
|
|
8597
|
+
return null;
|
|
8598
|
+
}
|
|
8599
|
+
return `${names.join(".")}.${tld}`.toLowerCase();
|
|
8600
|
+
}
|
|
8601
|
+
function isRealName(host) {
|
|
8602
|
+
const parsed = parseDomain3(host);
|
|
8603
|
+
return Boolean(parsed.isIcann && parsed.domain);
|
|
8604
|
+
}
|
|
8605
|
+
function bareHosts(text, add, { done, seen, from = 0, cutEnd = false }) {
|
|
8606
|
+
let previous = -1;
|
|
8607
|
+
const inLink = linkReader(text);
|
|
8608
|
+
for (let slash = text.indexOf("/"); slash !== -1; slash = text.indexOf("/", slash + 1)) {
|
|
8609
|
+
if (done()) {
|
|
8610
|
+
return;
|
|
8611
|
+
}
|
|
8612
|
+
const floor = Math.max(previous + 1, slash - MAX_HOST);
|
|
8613
|
+
previous = slash;
|
|
8614
|
+
let end = slash;
|
|
8615
|
+
while (end > floor && text.codePointAt(end - 1) >= 48 && text.codePointAt(end - 1) <= 57) {
|
|
8616
|
+
end--;
|
|
8617
|
+
}
|
|
8618
|
+
end = end > floor && text[end - 1] === ":" ? end - 1 : slash;
|
|
8619
|
+
let start = end;
|
|
8620
|
+
while (start > floor && isHostCode2(text.codePointAt(start - 1))) {
|
|
8621
|
+
start--;
|
|
8622
|
+
}
|
|
8623
|
+
if (start === end || start < from || cutEnd && slash === text.length - 1) {
|
|
8624
|
+
continue;
|
|
8625
|
+
}
|
|
8626
|
+
if (start > 0 && (IN_WORD2.test(text[start - 1]) || text[start - 1] === "/" && !isSchemeless(text, start)) || inLink(start)) {
|
|
8627
|
+
continue;
|
|
8628
|
+
}
|
|
8629
|
+
while (end > start && text[end - 1] === ".") {
|
|
8630
|
+
end--;
|
|
8631
|
+
}
|
|
8632
|
+
const host = bareName(text.slice(start, end));
|
|
8633
|
+
if (!host || seen.has(host)) {
|
|
8634
|
+
continue;
|
|
8635
|
+
}
|
|
8636
|
+
if (seen.size < MAX_SEEN) {
|
|
8637
|
+
seen.add(host);
|
|
8638
|
+
}
|
|
8639
|
+
if (isRealName(host)) {
|
|
8640
|
+
add(`http://${host}/`);
|
|
8641
|
+
}
|
|
8642
|
+
}
|
|
8643
|
+
}
|
|
8644
|
+
function looseHosts(text, add, { from = 0, cutEnd = false, seen, done }) {
|
|
8645
|
+
const inLink = linkReader(text);
|
|
8646
|
+
const { length } = text;
|
|
8647
|
+
let i = 0;
|
|
8648
|
+
while (i < length) {
|
|
8649
|
+
if (!isHostCode2(text.codePointAt(i))) {
|
|
8650
|
+
i++;
|
|
8651
|
+
continue;
|
|
8652
|
+
}
|
|
8653
|
+
const start = i;
|
|
8654
|
+
while (i < length && isHostCode2(text.codePointAt(i))) {
|
|
8655
|
+
i++;
|
|
8656
|
+
}
|
|
8657
|
+
let end = i;
|
|
8658
|
+
if (end - start > MAX_HOST || start < from || cutEnd && end === length) {
|
|
8659
|
+
continue;
|
|
8660
|
+
}
|
|
8661
|
+
while (end > start && text[end - 1] === ".") {
|
|
8662
|
+
end--;
|
|
8663
|
+
}
|
|
8664
|
+
const before = start > 0 ? text[start - 1] : "";
|
|
8665
|
+
const after = end < length ? text[end] : "";
|
|
8666
|
+
if (after === "/" || after === "@" || before === "@") {
|
|
8667
|
+
continue;
|
|
8668
|
+
}
|
|
8669
|
+
if (before && (IN_WORD2.test(before) || before === "/" || before === "\\" || before === "&" || before === "#")) {
|
|
8670
|
+
continue;
|
|
8671
|
+
}
|
|
8672
|
+
if (after && after !== "." && IN_WORD2.test(after)) {
|
|
8673
|
+
continue;
|
|
8674
|
+
}
|
|
8675
|
+
const name = text.slice(start, end);
|
|
8676
|
+
if (!name.includes(".") || inLink(start)) {
|
|
8677
|
+
continue;
|
|
8678
|
+
}
|
|
8679
|
+
const lower = name.toLowerCase();
|
|
8680
|
+
if (seen.has(lower)) {
|
|
8681
|
+
continue;
|
|
8682
|
+
}
|
|
8683
|
+
if (seen.size < MAX_SEEN) {
|
|
8684
|
+
seen.add(lower);
|
|
8685
|
+
}
|
|
8686
|
+
if (done()) {
|
|
8687
|
+
return;
|
|
8688
|
+
}
|
|
8689
|
+
const host = bareName(name);
|
|
8690
|
+
if (host && isRealName(host)) {
|
|
8691
|
+
add(host);
|
|
8692
|
+
}
|
|
8693
|
+
}
|
|
8694
|
+
}
|
|
8695
|
+
function* chunksOf(html) {
|
|
8696
|
+
let start = 0;
|
|
8697
|
+
let cutStart = false;
|
|
8698
|
+
while (start < html.length) {
|
|
8699
|
+
const end = Math.min(html.length, start + DECODE_CHUNK);
|
|
8700
|
+
if (end < html.length) {
|
|
8701
|
+
let cut = end;
|
|
8702
|
+
while (cut > end - 65536 && cut > start) {
|
|
8703
|
+
if (html[cut] === "<" || isSpace(html.codePointAt(cut))) {
|
|
8704
|
+
break;
|
|
8705
|
+
}
|
|
8706
|
+
cut--;
|
|
8707
|
+
}
|
|
8708
|
+
if (cut > start && cut > end - 65536) {
|
|
8709
|
+
yield { text: html.slice(start, cut), cutStart, cutEnd: false };
|
|
8710
|
+
start = cut;
|
|
8711
|
+
cutStart = false;
|
|
8712
|
+
continue;
|
|
8713
|
+
}
|
|
8714
|
+
yield { text: html.slice(start, end), cutStart, cutEnd: true };
|
|
8715
|
+
start = end - CHUNK_OVERLAP;
|
|
8716
|
+
cutStart = true;
|
|
8717
|
+
continue;
|
|
8718
|
+
}
|
|
8719
|
+
yield { text: html.slice(start, end), cutStart, cutEnd: false };
|
|
8720
|
+
start = end;
|
|
8721
|
+
}
|
|
8722
|
+
}
|
|
8723
|
+
function withoutNul(text) {
|
|
8724
|
+
return text.includes("\0") ? `${text}
|
|
8725
|
+
${text.replaceAll("\0", "")}` : text;
|
|
8726
|
+
}
|
|
8727
|
+
function hexValue(code) {
|
|
8728
|
+
if (code >= 48 && code <= 57) {
|
|
8729
|
+
return code - 48;
|
|
8730
|
+
}
|
|
8731
|
+
if (code >= 65 && code <= 70) {
|
|
8732
|
+
return code - 55;
|
|
8733
|
+
}
|
|
8734
|
+
if (code >= 97 && code <= 102) {
|
|
8735
|
+
return code - 87;
|
|
8736
|
+
}
|
|
8737
|
+
return -1;
|
|
8738
|
+
}
|
|
8739
|
+
function percentDecoded(text) {
|
|
8740
|
+
const input = Buffer13.from(text);
|
|
8741
|
+
const output = Buffer13.allocUnsafe(input.length);
|
|
8742
|
+
let length = 0;
|
|
8743
|
+
for (let i = 0; i < input.length; i++) {
|
|
8744
|
+
const high = input[i] === 37 ? hexValue(input[i + 1]) : -1;
|
|
8745
|
+
const low = high === -1 ? -1 : hexValue(input[i + 2]);
|
|
8746
|
+
if (low === -1) {
|
|
8747
|
+
output[length++] = input[i];
|
|
8748
|
+
continue;
|
|
8749
|
+
}
|
|
8750
|
+
output[length++] = high * 16 + low;
|
|
8751
|
+
i += 2;
|
|
8752
|
+
}
|
|
8753
|
+
return output.subarray(0, length);
|
|
8754
|
+
}
|
|
8755
|
+
var UTF16LE = /* @__PURE__ */ new Set(["csunicode", "iso-10646-ucs-2", "ucs-2", "unicode", "unicodefeff", "utf-16", "utf-16le"]);
|
|
8756
|
+
var UTF16BE = /* @__PURE__ */ new Set(["unicodefffe", "utf-16be"]);
|
|
8757
|
+
function swapped(bytes) {
|
|
8758
|
+
return Buffer13.from(bytes.subarray(0, bytes.length - bytes.length % 2)).swap16().toString("utf16le");
|
|
8759
|
+
}
|
|
8760
|
+
function decodeText(content, charset = "") {
|
|
8761
|
+
if (content[0] === 255 && content[1] === 254) {
|
|
8762
|
+
return content.subarray(2).toString("utf16le");
|
|
8763
|
+
}
|
|
8764
|
+
if (content[0] === 254 && content[1] === 255) {
|
|
8765
|
+
return swapped(content.subarray(2));
|
|
8766
|
+
}
|
|
8767
|
+
if (UTF16LE.has(charset)) {
|
|
8768
|
+
return content.toString("utf16le");
|
|
8769
|
+
}
|
|
8770
|
+
return UTF16BE.has(charset) ? swapped(content) : content.toString("utf8");
|
|
8771
|
+
}
|
|
8772
|
+
var DATA_DOCUMENT = /^\s*data:\s*(?:text\/html|application\/xhtml\+xml|image\/svg\+xml|text\/xml|application\/xml)\b([^,]*),/i;
|
|
8773
|
+
function dataDocument(value) {
|
|
8774
|
+
const match = DATA_DOCUMENT.exec(value.slice(0, 1024));
|
|
8775
|
+
if (!match) {
|
|
8776
|
+
return null;
|
|
8777
|
+
}
|
|
8778
|
+
const bytes = percentDecoded(value.slice(match[0].length));
|
|
8779
|
+
const content = /;\s*base64\s*$/i.test(match[1]) ? Buffer13.from(bytes.toString("latin1"), "base64") : bytes;
|
|
8780
|
+
const charset = /;\s*charset\s*=\s*"?([^;"\s]+)/i.exec(match[1]);
|
|
8781
|
+
return decodeText(content, charset ? charset[1].toLowerCase() : "");
|
|
8782
|
+
}
|
|
8783
|
+
var LINE_BREAK = /\r\n?|\n/;
|
|
8784
|
+
var FOLD = /(?:\r\n?|\n)[ \t]/g;
|
|
8785
|
+
var QUOTED_PRINTABLE = /;\s*(?:encoding\s*=\s*)?"?quoted-printable"?\s*(?:;|$)/i;
|
|
8786
|
+
var MEDIA_PROPERTIES = /* @__PURE__ */ new Set(["photo", "logo", "sound", "key", "attach"]);
|
|
8787
|
+
var HTML_PROPERTIES = /^(?:x-alt-desc|styled-description|description|comment)[;:]/i;
|
|
8788
|
+
function readEscapes(text, lenient = false) {
|
|
8789
|
+
let index = text.indexOf("\\");
|
|
8790
|
+
if (index === -1) {
|
|
8791
|
+
return text;
|
|
8792
|
+
}
|
|
8793
|
+
let out = "";
|
|
8794
|
+
let parts = [];
|
|
8795
|
+
let start = 0;
|
|
8796
|
+
while (index !== -1 && index + 1 < text.length) {
|
|
8797
|
+
const next = text[index + 1];
|
|
8798
|
+
if (lenient || "nN,;\\".includes(next)) {
|
|
8799
|
+
parts.push(text.slice(start, index), next === "n" || next === "N" ? "\n" : next);
|
|
8800
|
+
start = index + 2;
|
|
8801
|
+
index = text.indexOf("\\", start);
|
|
8802
|
+
if (parts.length >= 65536) {
|
|
8803
|
+
out += parts.join("");
|
|
8804
|
+
parts = [];
|
|
8805
|
+
}
|
|
8806
|
+
} else {
|
|
8807
|
+
index = text.indexOf("\\", index + 1);
|
|
8808
|
+
}
|
|
8809
|
+
}
|
|
8810
|
+
parts.push(text.slice(start));
|
|
8811
|
+
return out + parts.join("");
|
|
8812
|
+
}
|
|
8813
|
+
function valueColon(line) {
|
|
8814
|
+
let colon = line.indexOf(":");
|
|
8815
|
+
let from = 0;
|
|
8816
|
+
for (; ; ) {
|
|
8817
|
+
const quote = line.indexOf('"', from);
|
|
8818
|
+
if (quote === -1 || colon === -1 || colon < quote) {
|
|
8819
|
+
return colon;
|
|
8820
|
+
}
|
|
8821
|
+
const end = line.indexOf('"', quote + 1);
|
|
8822
|
+
if (end === -1) {
|
|
8823
|
+
return -1;
|
|
8824
|
+
}
|
|
8825
|
+
from = end + 1;
|
|
8826
|
+
if (colon < from) {
|
|
8827
|
+
colon = line.indexOf(":", from);
|
|
8828
|
+
}
|
|
8829
|
+
}
|
|
8830
|
+
}
|
|
8831
|
+
function trimSpaceEnd(text) {
|
|
8832
|
+
let end = text.length;
|
|
8833
|
+
while (end > 0 && (text[end - 1] === " " || text[end - 1] === " ")) {
|
|
8834
|
+
end--;
|
|
8835
|
+
}
|
|
8836
|
+
return end === text.length ? text : text.slice(0, end);
|
|
8837
|
+
}
|
|
8838
|
+
function decodeQuotedPrintable(value, charset) {
|
|
8839
|
+
let decoder;
|
|
8840
|
+
try {
|
|
8841
|
+
decoder = new TextDecoder(charset || "utf8");
|
|
8842
|
+
} catch {
|
|
8843
|
+
decoder = new TextDecoder("utf8");
|
|
8844
|
+
}
|
|
8845
|
+
if (!/[\u0080-\u{10FFFF}]/u.test(value)) {
|
|
8846
|
+
const bytes = Buffer13.from(value, "latin1");
|
|
8847
|
+
let length = 0;
|
|
8848
|
+
for (let index = 0; index < bytes.length; index++) {
|
|
8849
|
+
const hex = bytes[index] === 61 ? value.slice(index + 1, index + 3) : "";
|
|
8850
|
+
if (/^[\da-f]{2}$/i.test(hex)) {
|
|
8851
|
+
bytes[length++] = Number.parseInt(hex, 16);
|
|
8852
|
+
index += 2;
|
|
8853
|
+
} else {
|
|
8854
|
+
bytes[length++] = bytes[index];
|
|
8855
|
+
}
|
|
8856
|
+
}
|
|
8857
|
+
return decoder.decode(bytes.subarray(0, length));
|
|
8858
|
+
}
|
|
8859
|
+
return value.replaceAll(/(?:=[\da-f]{2})+/gi, (run) => decoder.decode(Buffer13.from(run.replaceAll("=", ""), "hex")));
|
|
8860
|
+
}
|
|
8861
|
+
function quotedPrintableValues(text) {
|
|
8862
|
+
if (!/quoted-printable/i.test(text)) {
|
|
8863
|
+
return text;
|
|
8864
|
+
}
|
|
8865
|
+
const lines2 = text.split(LINE_BREAK);
|
|
8866
|
+
const out = [];
|
|
8867
|
+
for (let i = 0; i < lines2.length; i++) {
|
|
8868
|
+
const line = lines2[i];
|
|
8869
|
+
const colon = valueColon(line);
|
|
8870
|
+
const parameters = colon === -1 ? "" : line.slice(0, colon);
|
|
8871
|
+
if (colon === -1 || !QUOTED_PRINTABLE.test(parameters)) {
|
|
8872
|
+
out.push(line);
|
|
8873
|
+
continue;
|
|
8874
|
+
}
|
|
8875
|
+
const charset = /;\s*charset\s*=\s*"?([\w.:-]+)/i.exec(parameters)?.[1];
|
|
8876
|
+
const parts = [trimSpaceEnd(line.slice(colon + 1))];
|
|
8877
|
+
while (parts.at(-1).endsWith("=") && i + 1 < lines2.length) {
|
|
8878
|
+
parts[parts.length - 1] = parts.at(-1).slice(0, -1);
|
|
8879
|
+
parts.push(trimSpaceEnd(lines2[++i]));
|
|
8880
|
+
}
|
|
8881
|
+
out.push(line.slice(0, colon + 1) + decodeQuotedPrintable(parts.join(""), charset));
|
|
8882
|
+
}
|
|
8883
|
+
return out.join("\n");
|
|
8884
|
+
}
|
|
8885
|
+
function hasQuotedPrintable(text) {
|
|
8886
|
+
const unfolded = text.replaceAll(FOLD, "");
|
|
8887
|
+
if (!/quoted-printable/i.test(unfolded)) {
|
|
8888
|
+
return false;
|
|
8889
|
+
}
|
|
8890
|
+
return unfolded.split(LINE_BREAK).some((line) => {
|
|
8891
|
+
const colon = valueColon(line);
|
|
8892
|
+
return colon !== -1 && QUOTED_PRINTABLE.test(line.slice(0, colon));
|
|
8893
|
+
});
|
|
8894
|
+
}
|
|
8895
|
+
function shownText(text, full = true) {
|
|
8896
|
+
const unfolded = text.replaceAll(FOLD, "");
|
|
8897
|
+
const shown = /* @__PURE__ */ new Set([text, readEscapes(unfolded)]);
|
|
8898
|
+
let decoded = unfolded;
|
|
8899
|
+
if (full) {
|
|
8900
|
+
decoded = quotedPrintableValues(unfolded);
|
|
8901
|
+
if (decoded !== unfolded) {
|
|
8902
|
+
shown.add(readEscapes(decoded));
|
|
8903
|
+
if (unfolded !== text) {
|
|
8904
|
+
shown.add(quotedPrintableValues(text));
|
|
8905
|
+
}
|
|
8906
|
+
}
|
|
8907
|
+
}
|
|
8908
|
+
if (/\\[^nN,;\\]/.test(decoded)) {
|
|
8909
|
+
shown.add(readEscapes(decoded, true));
|
|
8910
|
+
}
|
|
8911
|
+
return [...shown].reverse().join("\n");
|
|
8912
|
+
}
|
|
8913
|
+
function htmlDescriptions(text) {
|
|
8914
|
+
if (!/[<&]|altrep/i.test(text)) {
|
|
8915
|
+
return "";
|
|
8916
|
+
}
|
|
8917
|
+
const html = [];
|
|
8918
|
+
for (const line of text.replaceAll(FOLD, "").split(LINE_BREAK)) {
|
|
8919
|
+
const colon = valueColon(line);
|
|
8920
|
+
if (colon === -1) {
|
|
8921
|
+
continue;
|
|
8922
|
+
}
|
|
8923
|
+
const altrep = /;\s*altrep\s*=\s*"([^"]*)"/i.exec(line.slice(0, colon))?.[1];
|
|
8924
|
+
if (altrep) {
|
|
8925
|
+
html.push(`<iframe src="${altrep.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<")}"></iframe>`);
|
|
8926
|
+
}
|
|
8927
|
+
if (!HTML_PROPERTIES.test(line)) {
|
|
8928
|
+
continue;
|
|
8929
|
+
}
|
|
8930
|
+
const value = readEscapes(line.slice(colon + 1));
|
|
8931
|
+
if (/[<&]/.test(value)) {
|
|
8932
|
+
html.push(value);
|
|
8933
|
+
}
|
|
8934
|
+
}
|
|
8935
|
+
return html.join("\n");
|
|
8936
|
+
}
|
|
8937
|
+
var BINARY = /;\s*(?:(?:encoding\s*=\s*)?"?(?:b|base64)"?|value\s*=\s*"?binary"?)\s*(?:;|$)/i;
|
|
8938
|
+
function withoutBinaryValues(text) {
|
|
8939
|
+
if (!/base64|binary|encoding\s*=\s*"?b|;\s*b\s*[;:]/i.test(text)) {
|
|
8940
|
+
return text;
|
|
8941
|
+
}
|
|
8942
|
+
const lines2 = text.split(LINE_BREAK);
|
|
8943
|
+
const out = [];
|
|
8944
|
+
for (let i = 0; i < lines2.length; i++) {
|
|
8945
|
+
const line = lines2[i];
|
|
8946
|
+
const colon = valueColon(line);
|
|
8947
|
+
if (colon === -1 || !BINARY.test(line.slice(0, colon))) {
|
|
8948
|
+
out.push(line);
|
|
8949
|
+
continue;
|
|
8950
|
+
}
|
|
8951
|
+
const value = [line.slice(colon + 1)];
|
|
8952
|
+
let next = i + 1;
|
|
8953
|
+
while (next < lines2.length && (lines2[next].startsWith(" ") || lines2[next].startsWith(" "))) {
|
|
8954
|
+
value.push(lines2[next++]);
|
|
8955
|
+
}
|
|
8956
|
+
if (!value.every((part) => /^[\w+/=\s]*$/.test(part))) {
|
|
8957
|
+
for (let index = i; index < next; index++) {
|
|
8958
|
+
out.push(lines2[index]);
|
|
8959
|
+
}
|
|
8960
|
+
i = next - 1;
|
|
8961
|
+
continue;
|
|
8962
|
+
}
|
|
8963
|
+
while (next < lines2.length && lines2[next] !== "" && /^[\w+/=]+$/.test(lines2[next])) {
|
|
8964
|
+
value.push(lines2[next++]);
|
|
8965
|
+
}
|
|
8966
|
+
if (next < lines2.length && lines2[next] === "") {
|
|
8967
|
+
next++;
|
|
8968
|
+
}
|
|
8969
|
+
i = next - 1;
|
|
8970
|
+
const name = line.slice(0, colon).split(";")[0].split(".").pop().trim().toLowerCase();
|
|
8971
|
+
out.push(MEDIA_PROPERTIES.has(name) ? line.slice(0, colon + 1) : line.slice(0, colon + 1) + Buffer13.from(value.join("").replaceAll(/\s/g, ""), "base64").toString("utf8"));
|
|
8972
|
+
}
|
|
8973
|
+
return out.join("\n");
|
|
8974
|
+
}
|
|
8975
|
+
var HTML_TYPES = /* @__PURE__ */ new Set(["text/html", "application/xhtml+xml", "image/svg+xml", "text/xml", "application/xml"]);
|
|
8976
|
+
var HTML_EXTENSIONS = /* @__PURE__ */ new Set(["html", "htm", "shtml", "xhtml", "xht", "svg", "xml"]);
|
|
8977
|
+
var CARD_TYPES = /* @__PURE__ */ new Set(["text/calendar", "text/x-vcalendar", "application/ics", "text/vcard", "text/x-vcard", "text/directory"]);
|
|
8978
|
+
var CARD_EXTENSIONS = /* @__PURE__ */ new Set(["ics", "ical", "ifb", "vcs", "vcf", "vcard"]);
|
|
8979
|
+
var MESSAGE_TYPES = /* @__PURE__ */ new Set(["message/rfc822", "message/global"]);
|
|
8980
|
+
function extensionOf2(filename) {
|
|
8981
|
+
let end = filename.length;
|
|
8982
|
+
while (end > 0 && (filename[end - 1] === "." || filename[end - 1] === " ")) {
|
|
8983
|
+
end--;
|
|
8984
|
+
}
|
|
8985
|
+
const name = filename.slice(0, end).trim().toLowerCase();
|
|
8986
|
+
const index = name.lastIndexOf(".");
|
|
8987
|
+
return index !== -1 && index < name.length - 1 ? name.slice(index + 1) : null;
|
|
8988
|
+
}
|
|
8989
|
+
function extensionsOf(attachment) {
|
|
8990
|
+
const names = [];
|
|
8991
|
+
if (typeof attachment.filename === "string") {
|
|
8992
|
+
names.push(attachment.filename);
|
|
8993
|
+
}
|
|
8994
|
+
const { headers } = attachment;
|
|
8995
|
+
if (headers && typeof headers.get === "function") {
|
|
8996
|
+
for (const [field, parameter] of [["content-type", "name"], ["content-disposition", "filename"]]) {
|
|
8997
|
+
const value = headers.get(field)?.params?.[parameter];
|
|
8998
|
+
if (typeof value === "string" && value !== "") {
|
|
8999
|
+
names.push(value);
|
|
9000
|
+
}
|
|
9001
|
+
}
|
|
9002
|
+
}
|
|
9003
|
+
return new Set(names.flatMap((name) => [extensionOf2(name), extensionOf(name)]).filter(Boolean));
|
|
9004
|
+
}
|
|
9005
|
+
function charsetOf(attachment) {
|
|
9006
|
+
const { headers } = attachment;
|
|
9007
|
+
const charset = headers && typeof headers.get === "function" ? headers.get("content-type")?.params?.charset : null;
|
|
9008
|
+
return typeof charset === "string" ? charset.toLowerCase() : "";
|
|
9009
|
+
}
|
|
9010
|
+
function documentsOf(attachments, until) {
|
|
9011
|
+
const documents = [];
|
|
9012
|
+
let bytes = 0;
|
|
9013
|
+
let opened = 0;
|
|
9014
|
+
for (const attachment of attachments) {
|
|
9015
|
+
const { content } = attachment ?? {};
|
|
9016
|
+
if (!Buffer13.isBuffer(content) || content.length === 0) {
|
|
9017
|
+
continue;
|
|
9018
|
+
}
|
|
9019
|
+
const type = typeof attachment.contentType === "string" ? attachment.contentType.toLowerCase() : "";
|
|
9020
|
+
const extensions = extensionsOf(attachment);
|
|
9021
|
+
const has = (set) => [...extensions].some((name) => set.has(name));
|
|
9022
|
+
if (MESSAGE_TYPES.has(type) || extensions.has("eml") || extensions.has("u8msg")) {
|
|
9023
|
+
continue;
|
|
9024
|
+
}
|
|
9025
|
+
const isHtml = HTML_TYPES.has(type) || has(HTML_EXTENSIONS);
|
|
9026
|
+
const isCard = !isHtml && (CARD_TYPES.has(type) || has(CARD_EXTENSIONS));
|
|
9027
|
+
const isText = isCard || !isHtml && type === "text/plain";
|
|
9028
|
+
if (!isHtml && !isText) {
|
|
9029
|
+
continue;
|
|
9030
|
+
}
|
|
9031
|
+
if (!isText && ++opened > MAX_ATTACHED || bytes + content.length > MAX_ATTACHED_BYTES) {
|
|
9032
|
+
documents.tooComplex = true;
|
|
9033
|
+
return documents;
|
|
9034
|
+
}
|
|
9035
|
+
if (Date.now() > until) {
|
|
9036
|
+
documents.incomplete = true;
|
|
9037
|
+
return documents;
|
|
9038
|
+
}
|
|
9039
|
+
bytes += content.length;
|
|
9040
|
+
const text = decodeText(content, charsetOf(attachment));
|
|
9041
|
+
if (isHtml) {
|
|
9042
|
+
documents.push({ html: text });
|
|
9043
|
+
continue;
|
|
9044
|
+
}
|
|
9045
|
+
if (!isCard) {
|
|
9046
|
+
documents.push({ text });
|
|
9047
|
+
continue;
|
|
9048
|
+
}
|
|
9049
|
+
const readable = withoutBinaryValues(text);
|
|
9050
|
+
const full = readable.length <= MAX_SHOWN_BYTES;
|
|
9051
|
+
if (!full && hasQuotedPrintable(readable)) {
|
|
9052
|
+
documents.tooComplex = true;
|
|
9053
|
+
continue;
|
|
9054
|
+
}
|
|
9055
|
+
documents.push({ text: shownText(readable, full) });
|
|
9056
|
+
const html = htmlDescriptions(readable);
|
|
9057
|
+
if (html !== "") {
|
|
9058
|
+
documents.push({ html });
|
|
9059
|
+
}
|
|
9060
|
+
}
|
|
9061
|
+
return documents;
|
|
9062
|
+
}
|
|
9063
|
+
function carriedLinkHosts(mail, {
|
|
9064
|
+
mails = [],
|
|
9065
|
+
attachments = [],
|
|
9066
|
+
maxHosts = 250,
|
|
9067
|
+
hostsInText = false
|
|
9068
|
+
} = {}) {
|
|
9069
|
+
const hosts = /* @__PURE__ */ new Set();
|
|
9070
|
+
const loose = /* @__PURE__ */ new Set();
|
|
9071
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9072
|
+
const seenBare = /* @__PURE__ */ new Set();
|
|
9073
|
+
const seenLoose = /* @__PURE__ */ new Set();
|
|
9074
|
+
let more = false;
|
|
9075
|
+
let tooComplex = false;
|
|
9076
|
+
const done = () => more;
|
|
9077
|
+
const looseDone = () => more || loose.size > maxHosts;
|
|
9078
|
+
const addLoose = (host) => {
|
|
9079
|
+
if (!looseDone()) {
|
|
9080
|
+
loose.add(host);
|
|
9081
|
+
}
|
|
9082
|
+
};
|
|
9083
|
+
const until = Date.now() + MAX_READ_TIME;
|
|
9084
|
+
let incomplete = false;
|
|
9085
|
+
const late = () => {
|
|
9086
|
+
if (!incomplete && Date.now() > until) {
|
|
9087
|
+
incomplete = true;
|
|
9088
|
+
}
|
|
9089
|
+
return incomplete;
|
|
9090
|
+
};
|
|
9091
|
+
const carried = documentsOf(attachments, until);
|
|
9092
|
+
tooComplex = Boolean(carried.tooComplex);
|
|
9093
|
+
incomplete = Boolean(carried.incomplete);
|
|
9094
|
+
const queue = [mail, ...mails, ...carried].map((document) => ({ document, depth: 0 }));
|
|
9095
|
+
let depth = 0;
|
|
9096
|
+
let embedded = 0;
|
|
9097
|
+
let embeddedLength = 0;
|
|
9098
|
+
const embed = (html) => {
|
|
9099
|
+
if (depth >= MAX_EMBED_DEPTH || embedded >= MAX_EMBEDDED || embeddedLength + html.length > MAX_EMBEDDED_LENGTH) {
|
|
9100
|
+
tooComplex = true;
|
|
9101
|
+
return;
|
|
9102
|
+
}
|
|
9103
|
+
embedded++;
|
|
9104
|
+
embeddedLength += html.length;
|
|
9105
|
+
queue.push({ document: { html }, depth: depth + 1 });
|
|
9106
|
+
};
|
|
9107
|
+
const add = (value) => {
|
|
9108
|
+
if (more || typeof value !== "string" || value === "" || seen.has(value)) {
|
|
9109
|
+
return;
|
|
9110
|
+
}
|
|
9111
|
+
if (seen.size < MAX_SEEN) {
|
|
9112
|
+
seen.add(value);
|
|
9113
|
+
}
|
|
9114
|
+
if (/^\s*data:/i.test(value)) {
|
|
9115
|
+
const html = dataDocument(value);
|
|
9116
|
+
if (html !== null) {
|
|
9117
|
+
embed(html);
|
|
9118
|
+
}
|
|
9119
|
+
return;
|
|
9120
|
+
}
|
|
9121
|
+
const found = hostsOf(value);
|
|
9122
|
+
if (found.unresolved) {
|
|
9123
|
+
tooComplex = true;
|
|
9124
|
+
}
|
|
9125
|
+
for (const host of found) {
|
|
9126
|
+
if (hosts.has(host)) {
|
|
9127
|
+
continue;
|
|
9128
|
+
}
|
|
9129
|
+
if (hosts.size >= maxHosts) {
|
|
9130
|
+
more = true;
|
|
9131
|
+
return;
|
|
9132
|
+
}
|
|
9133
|
+
hosts.add(host);
|
|
9134
|
+
}
|
|
9135
|
+
};
|
|
9136
|
+
const readText = (source, { cutStart = false, cutEnd = false } = {}) => {
|
|
9137
|
+
for (const match of source.matchAll(URL_START)) {
|
|
9138
|
+
if (more) {
|
|
9139
|
+
break;
|
|
9140
|
+
}
|
|
9141
|
+
if (cutStart && match.index === 0) {
|
|
9142
|
+
continue;
|
|
9143
|
+
}
|
|
9144
|
+
if (cutEnd && match.index + match[0].length === source.length) {
|
|
9145
|
+
const value = match[0];
|
|
9146
|
+
const at = /^www\./i.test(value) ? 0 : value.indexOf("//") + 2;
|
|
9147
|
+
if (/[/?#\\]/.test(value.slice(at))) {
|
|
9148
|
+
add(value);
|
|
9149
|
+
} else if (source.length - match.index > CHUNK_OVERLAP) {
|
|
9150
|
+
tooComplex = true;
|
|
9151
|
+
}
|
|
9152
|
+
continue;
|
|
9153
|
+
}
|
|
9154
|
+
add(match[0]);
|
|
9155
|
+
}
|
|
9156
|
+
const from = cutStart ? 1 : 0;
|
|
9157
|
+
bareHosts(source, add, {
|
|
9158
|
+
done,
|
|
9159
|
+
seen: seenBare,
|
|
9160
|
+
from,
|
|
9161
|
+
cutEnd
|
|
9162
|
+
});
|
|
9163
|
+
if (hostsInText && !looseDone()) {
|
|
9164
|
+
looseHosts(source, addLoose, {
|
|
9165
|
+
from,
|
|
9166
|
+
cutEnd,
|
|
9167
|
+
seen: seenLoose,
|
|
9168
|
+
done: looseDone
|
|
9169
|
+
});
|
|
9170
|
+
}
|
|
9171
|
+
};
|
|
9172
|
+
for (const element of queue) {
|
|
9173
|
+
if (more || late()) {
|
|
9174
|
+
break;
|
|
9175
|
+
}
|
|
9176
|
+
({ depth } = element);
|
|
9177
|
+
const { document } = element;
|
|
9178
|
+
const html = withoutNul(typeof document?.html === "string" ? document.html : "");
|
|
9179
|
+
const text = withoutNul(typeof document?.text === "string" ? document.text : "");
|
|
9180
|
+
for (const [name, value] of attributesOf(html)) {
|
|
9181
|
+
if (more) {
|
|
9182
|
+
break;
|
|
9183
|
+
}
|
|
9184
|
+
if (LINK_ATTRIBUTES.has(name)) {
|
|
9185
|
+
linksOf(name, value, add, embed);
|
|
9186
|
+
}
|
|
9187
|
+
}
|
|
9188
|
+
lenientLinks(html, add, done, embed);
|
|
9189
|
+
for (const pattern of [CSS_URL, CSS_IMPORT]) {
|
|
9190
|
+
for (const [, link] of html.matchAll(pattern)) {
|
|
9191
|
+
if (more) {
|
|
9192
|
+
break;
|
|
9193
|
+
}
|
|
9194
|
+
add(decodeEntities(link, { attribute: true }));
|
|
9195
|
+
}
|
|
9196
|
+
}
|
|
9197
|
+
if (!more) {
|
|
9198
|
+
readText(text);
|
|
9199
|
+
}
|
|
9200
|
+
for (const chunk2 of chunksOf(html)) {
|
|
9201
|
+
if (more || late()) {
|
|
9202
|
+
break;
|
|
9203
|
+
}
|
|
9204
|
+
readText(decodeEntities(chunk2.text), chunk2);
|
|
9205
|
+
}
|
|
9206
|
+
}
|
|
9207
|
+
if (!more && !incomplete) {
|
|
9208
|
+
for (const name of loose) {
|
|
9209
|
+
if (hosts.size >= maxHosts) {
|
|
9210
|
+
break;
|
|
9211
|
+
}
|
|
9212
|
+
const [host] = hostsOf(`http://${name}/`);
|
|
9213
|
+
if (host) {
|
|
9214
|
+
hosts.add(host);
|
|
9215
|
+
}
|
|
9216
|
+
}
|
|
9217
|
+
}
|
|
9218
|
+
return {
|
|
9219
|
+
hosts: [...hosts],
|
|
9220
|
+
more,
|
|
9221
|
+
tooComplex,
|
|
9222
|
+
incomplete
|
|
9223
|
+
};
|
|
9224
|
+
}
|
|
9225
|
+
|
|
9226
|
+
// src/is-arbitrary.js
|
|
9227
|
+
import { parse as parseDomain4 } from "tldts";
|
|
8125
9228
|
var GTUBE = "XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X";
|
|
8126
9229
|
var BLOCKED_SUBJECT = /cheecck y0ur acc0untt|\brecorded\s+you\s+(?:masturbating|jerking|touching\s+yourself|watching\s+porn)\b|personal data has leaked|private information has been stolen/i;
|
|
8127
9230
|
var HACKED_SUBJECT = /\byou['’]ve been hacked\b|\baccount is hacked\b|\b(?:i|we)(?:\s+have|['’]ve)?\s+recorded\s+you\b|\brecorded\s+you\s+(?:doing|while|watching|through|on\s+(?:cam|camera|video|webcam))\b/i;
|
|
@@ -8312,13 +9415,13 @@ function joinsDisplay(brand, display, name) {
|
|
|
8312
9415
|
return false;
|
|
8313
9416
|
}
|
|
8314
9417
|
function isOfficial({ brand, official }, domain, display, shared = true) {
|
|
8315
|
-
const parsed =
|
|
9418
|
+
const parsed = parseDomain4(domain);
|
|
8316
9419
|
const name = parsed.domainWithoutSuffix ?? "";
|
|
8317
9420
|
const compact = brand.replaceAll(" ", "");
|
|
8318
9421
|
if (parsed.publicSuffix === compact || compact.length >= 5 && joinsDisplay(brand, display, name) && !JOINED_WORDS.some((word) => name.slice(compact.length).includes(word))) {
|
|
8319
9422
|
return true;
|
|
8320
9423
|
}
|
|
8321
|
-
return official.some((entry) => entry instanceof RegExp ? entry.test(registrableDomain(domain)) : entry.includes(".") ? (shared ||
|
|
9424
|
+
return official.some((entry) => entry instanceof RegExp ? entry.test(registrableDomain(domain)) : entry.includes(".") ? (shared || parseDomain4(entry).domain !== null) && (domain === entry || domain.endsWith(`.${entry}`)) : name === entry);
|
|
8322
9425
|
}
|
|
8323
9426
|
function headerString(mail, name) {
|
|
8324
9427
|
const value = mail.headers?.get?.(name);
|
|
@@ -8420,7 +9523,7 @@ ${withoutHelp(markup)}`) || isInjection(readable) || attributeText(markup).some(
|
|
|
8420
9523
|
}
|
|
8421
9524
|
} else if (claimed && isWholeName(name, claimed)) {
|
|
8422
9525
|
const domain = claimed[1];
|
|
8423
|
-
const brand = MAILBOXES.has(
|
|
9526
|
+
const brand = MAILBOXES.has(parseDomain4(domain).domainWithoutSuffix) ? null : DISPLAY_BRANDS.find((entry) => isOfficial(entry, domain, "", false) && !isOfficial(entry, session.originalFromAddressDomain, ""));
|
|
8424
9527
|
if (brand) {
|
|
8425
9528
|
hit("FROM_NAME_BRAND", 2, `Display name is an address of "${brand.brand}" but the message is from ${fromRoot}`, "PHISHING");
|
|
8426
9529
|
}
|
|
@@ -8691,21 +9794,21 @@ async function withTimeout(promise, ms, fallback) {
|
|
|
8691
9794
|
}
|
|
8692
9795
|
}
|
|
8693
9796
|
async function toBuffer(source) {
|
|
8694
|
-
if (
|
|
9797
|
+
if (Buffer14.isBuffer(source)) {
|
|
8695
9798
|
return source;
|
|
8696
9799
|
}
|
|
8697
9800
|
if (typeof source === "string") {
|
|
8698
|
-
return
|
|
9801
|
+
return Buffer14.from(source, "utf8");
|
|
8699
9802
|
}
|
|
8700
9803
|
if (source instanceof Uint8Array) {
|
|
8701
|
-
return
|
|
9804
|
+
return Buffer14.from(source);
|
|
8702
9805
|
}
|
|
8703
9806
|
if (source && typeof source[Symbol.asyncIterator] === "function") {
|
|
8704
9807
|
const chunks = [];
|
|
8705
9808
|
for await (const chunk2 of source) {
|
|
8706
|
-
chunks.push(
|
|
9809
|
+
chunks.push(Buffer14.isBuffer(chunk2) ? chunk2 : Buffer14.from(chunk2));
|
|
8707
9810
|
}
|
|
8708
|
-
return
|
|
9811
|
+
return Buffer14.concat(chunks);
|
|
8709
9812
|
}
|
|
8710
9813
|
throw new TypeError("A message must be a Buffer, a string, a Uint8Array or a readable stream");
|
|
8711
9814
|
}
|
|
@@ -8727,6 +9830,19 @@ var DEFAULTS2 = {
|
|
|
8727
9830
|
cloudflare: true,
|
|
8728
9831
|
adult: true,
|
|
8729
9832
|
maxHosts: 25,
|
|
9833
|
+
// Also read the links of the whole message and of what it carries
|
|
9834
|
+
// (attached messages, HTML, SVG and XML files, text files, invitations
|
|
9835
|
+
// and contact cards, documents in iframes and data: URLs) when link
|
|
9836
|
+
// hosts are looked up, for at most five seconds: off by default, as it
|
|
9837
|
+
// reads all of it, up to 50 MB of attachments.
|
|
9838
|
+
attachments: false,
|
|
9839
|
+
// Milliseconds the link lookups may take in all (default: timeout).
|
|
9840
|
+
timeout: void 0,
|
|
9841
|
+
// Also look up host names written in the text without a link or a path
|
|
9842
|
+
// ("evil.example"), which mail clients make links of, as far as there is
|
|
9843
|
+
// room: off by default, as a quoted reply or a signature may name any
|
|
9844
|
+
// site (they are checked for lookalikes either way).
|
|
9845
|
+
hostsInText: false,
|
|
8730
9846
|
// Characters of text read for links (twice as many of HTML): more than
|
|
8731
9847
|
// for the classifier (maxLength), as a link anywhere in a message may be
|
|
8732
9848
|
// followed; a longer message sets results.linksTruncated.
|
|
@@ -8839,7 +9955,7 @@ function fromDomain(mail) {
|
|
|
8839
9955
|
function withHeader(raw) {
|
|
8840
9956
|
const first = raw.subarray(0, 1e3).toString("latin1");
|
|
8841
9957
|
const headerless = raw.length > 0 && !/^(?:[!-9;-~]+[ \t]*:|From |[\r\n])/.test(first);
|
|
8842
|
-
return headerless ?
|
|
9958
|
+
return headerless ? Buffer14.concat([Buffer14.from("\r\n"), raw]) : raw;
|
|
8843
9959
|
}
|
|
8844
9960
|
var SpamScanner = class {
|
|
8845
9961
|
/**
|
|
@@ -9001,7 +10117,10 @@ var SpamScanner = class {
|
|
|
9001
10117
|
async scanFile(file, options) {
|
|
9002
10118
|
return this.scan(await readFile(file), options);
|
|
9003
10119
|
}
|
|
9004
|
-
|
|
10120
|
+
// (`from`: the sender's domain; `carried`: the link hosts of the whole
|
|
10121
|
+
// message and of what it carries, see carriedLinkHosts)
|
|
10122
|
+
async checkLinks(links, config, hosts = [], options = {}) {
|
|
10123
|
+
const { from = "", carried = null } = typeof options === "string" ? { from: options } : options;
|
|
9005
10124
|
const phishing = [];
|
|
9006
10125
|
const homographs = [];
|
|
9007
10126
|
const seenHosts = /* @__PURE__ */ new Set();
|
|
@@ -9057,7 +10176,11 @@ var SpamScanner = class {
|
|
|
9057
10176
|
for (const host of hosts) {
|
|
9058
10177
|
lookalike(host, { source: "text" });
|
|
9059
10178
|
}
|
|
9060
|
-
const
|
|
10179
|
+
const carriedHosts = (carried?.hosts ?? []).map((host) => lookupName(host)).filter(Boolean);
|
|
10180
|
+
for (const host of carriedHosts) {
|
|
10181
|
+
seenHosts.add(host);
|
|
10182
|
+
}
|
|
10183
|
+
const ordered = [.../* @__PURE__ */ new Set([...[...found.filter((link) => link.text), ...found.filter((link) => !link.text), ...bare].map((link) => lookupName(destination(link))).filter(Boolean), ...carriedHosts])];
|
|
9061
10184
|
const firsts = /* @__PURE__ */ new Map();
|
|
9062
10185
|
for (const host of ordered) {
|
|
9063
10186
|
const domain = registrableDomain(host);
|
|
@@ -9069,6 +10192,7 @@ var SpamScanner = class {
|
|
|
9069
10192
|
const domains = [...new Set(checked.map((host) => registrableDomain(host)))];
|
|
9070
10193
|
const blocked = [];
|
|
9071
10194
|
let answered = 0;
|
|
10195
|
+
const linkTimeout = Number(config.phishing.timeout) > 0 ? Number(config.phishing.timeout) : config.timeout;
|
|
9072
10196
|
const cloudflare = async () => {
|
|
9073
10197
|
await withTimeout(Promise.all(checked.map(async (host) => {
|
|
9074
10198
|
const found2 = await this.dns.checkCloudflare([host], { adult: config.phishing.adult });
|
|
@@ -9076,12 +10200,12 @@ var SpamScanner = class {
|
|
|
9076
10200
|
if (!found2.unanswered?.length) {
|
|
9077
10201
|
answered++;
|
|
9078
10202
|
}
|
|
9079
|
-
})),
|
|
10203
|
+
})), linkTimeout, null);
|
|
9080
10204
|
return { found: [...blocked], unanswered: checked.length - answered };
|
|
9081
10205
|
};
|
|
9082
10206
|
const [cloudflareResult, listed] = await Promise.all([
|
|
9083
10207
|
config.phishing.cloudflare && checked.length > 0 ? cloudflare() : { found: [], unanswered: 0 },
|
|
9084
|
-
config.dnsbl.domain?.length > 0 && domains.length > 0 ? withTimeout(this.dns.checkDomains(domains, config.dnsbl.domain),
|
|
10208
|
+
config.dnsbl.domain?.length > 0 && domains.length > 0 ? withTimeout(this.dns.checkDomains(domains, config.dnsbl.domain), linkTimeout, []) : []
|
|
9085
10209
|
]);
|
|
9086
10210
|
for (const { host, category } of cloudflareResult.found) {
|
|
9087
10211
|
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` }));
|
|
@@ -9097,7 +10221,8 @@ var SpamScanner = class {
|
|
|
9097
10221
|
return {
|
|
9098
10222
|
phishing,
|
|
9099
10223
|
homographs,
|
|
9100
|
-
|
|
10224
|
+
// (at least one when the message has more hosts than were read)
|
|
10225
|
+
uncheckedHosts: Math.max(seenHosts.size - checked.length, carried?.more ? 1 : 0),
|
|
9101
10226
|
timedOutHosts: cloudflareResult.unanswered
|
|
9102
10227
|
};
|
|
9103
10228
|
}
|
|
@@ -9269,10 +10394,17 @@ ${visibleText(html.slice(0, config.maxLength * 2)).text}`, { maxLength: config.m
|
|
|
9269
10394
|
styled: plainObfuscation.styled || shownObfuscation.styled
|
|
9270
10395
|
};
|
|
9271
10396
|
const unopened = [];
|
|
9272
|
-
const
|
|
10397
|
+
const opened = [];
|
|
10398
|
+
const attached = await expandAttachments(mail.attachments, parseErrors, void 0, { unopened, mails: opened });
|
|
10399
|
+
const carried = config.phishing.attachments === true && (config.phishing.cloudflare || config.dnsbl.domain?.length > 0) ? carriedLinkHosts(mail, {
|
|
10400
|
+
mails: opened,
|
|
10401
|
+
attachments: attached,
|
|
10402
|
+
maxHosts: config.phishing.maxHosts,
|
|
10403
|
+
hostsInText: config.phishing.hostsInText === true
|
|
10404
|
+
}) : null;
|
|
9273
10405
|
const attachments = config.attachments === false ? [] : inspectAttachments(attached).filter((item) => config.macros !== false || !["macro", "pdf_active", "rtf_object"].includes(item.type)).map((item) => finding(item));
|
|
9274
10406
|
const [links, authentication, checkedReputation, dnsbl, virusScan, toxicity, nsfw] = await Promise.all([
|
|
9275
|
-
this.checkLinks(checkedLinks, config, extracted.hosts, fromDomain(mail)),
|
|
10407
|
+
this.checkLinks(checkedLinks, config, extracted.hosts, { from: fromDomain(mail), carried }),
|
|
9276
10408
|
config.authenticationResults && typeof config.authenticationResults === "object" ? normalizeAuthOutput(config.authenticationResults) : config.authentication && session.remoteAddress ? withTimeout(authenticate(raw, {
|
|
9277
10409
|
timeout: config.timeout,
|
|
9278
10410
|
...typeof config.authentication === "object" ? config.authentication : {},
|
|
@@ -9400,6 +10532,14 @@ ${visibleText(html.slice(0, config.maxLength * 2)).text}`, { maxLength: config.m
|
|
|
9400
10532
|
// Whether the message has more text than phishing.maxLength, whose
|
|
9401
10533
|
// links were not read.
|
|
9402
10534
|
linksTruncated,
|
|
10535
|
+
// Whether a link host of the message or of what it carries was
|
|
10536
|
+
// never read whole (it runs past where long text is cut to be
|
|
10537
|
+
// read, it goes through more security gateways than are
|
|
10538
|
+
// unwrapped, or it is in more documents than are read), and whether
|
|
10539
|
+
// an attachment was left unread for time: in either case not every
|
|
10540
|
+
// link was checked (see phishing.attachments).
|
|
10541
|
+
linksTooComplex: Boolean(carried?.tooComplex),
|
|
10542
|
+
linksIncomplete: Boolean(carried?.incomplete),
|
|
9403
10543
|
idnHomographAttack: {
|
|
9404
10544
|
detected: links.homographs.length > 0,
|
|
9405
10545
|
domains: links.homographs,
|
|
@@ -9411,6 +10551,9 @@ ${visibleText(html.slice(0, config.maxLength * 2)).text}`, { maxLength: config.m
|
|
|
9411
10551
|
language: extracted.language,
|
|
9412
10552
|
tokens: extracted.words,
|
|
9413
10553
|
mail,
|
|
10554
|
+
// (the attachments of the message and of its attached messages, as
|
|
10555
|
+
// read, an attached message's named after it)
|
|
10556
|
+
attached,
|
|
9414
10557
|
version: VERSION,
|
|
9415
10558
|
metrics: { totalTime: time }
|
|
9416
10559
|
};
|
|
@@ -9763,13 +10906,13 @@ async function readMessage(stream, maxSize) {
|
|
|
9763
10906
|
for (; ; ) {
|
|
9764
10907
|
const { value, done } = await iterator.next();
|
|
9765
10908
|
if (done) {
|
|
9766
|
-
return { data:
|
|
10909
|
+
return { data: Buffer15.concat(chunks), complete: true, rest: iterator };
|
|
9767
10910
|
}
|
|
9768
|
-
const chunk2 =
|
|
10911
|
+
const chunk2 = Buffer15.from(value);
|
|
9769
10912
|
chunks.push(chunk2);
|
|
9770
10913
|
size += chunk2.length;
|
|
9771
10914
|
if (size > maxSize) {
|
|
9772
|
-
return { data:
|
|
10915
|
+
return { data: Buffer15.concat(chunks), complete: false, rest: iterator };
|
|
9773
10916
|
}
|
|
9774
10917
|
}
|
|
9775
10918
|
}
|