spamscanner 7.0.13 → 7.0.15

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 CHANGED
@@ -31,15 +31,1150 @@ __export(arf_exports, {
31
31
  tryParse: () => tryParse
32
32
  });
33
33
  module.exports = __toCommonJS(arf_exports);
34
- var import_node_buffer2 = require("node:buffer");
34
+ var import_node_buffer3 = require("node:buffer");
35
35
  var import_node_crypto2 = require("node:crypto");
36
36
  var import_node_net = require("node:net");
37
37
 
38
38
  // src/parse.js
39
- var import_node_buffer = require("node:buffer");
39
+ var import_node_buffer2 = require("node:buffer");
40
40
  var import_node_crypto = require("node:crypto");
41
41
  var import_node_stream = require("node:stream");
42
42
  var import_mailparser = require("mailparser");
43
+
44
+ // src/attachments.js
45
+ var import_node_buffer = require("node:buffer");
46
+
47
+ // src/linear.js
48
+ var import_node_module = require("node:module");
49
+ function loadRe2(load = (0, import_node_module.createRequire)(__importMetaUrl)) {
50
+ try {
51
+ return load("re2");
52
+ } catch {
53
+ return null;
54
+ }
55
+ }
56
+ var RE2 = loadRe2();
57
+ var BOUNDED = /^{([01]),\d{2,}}/;
58
+ var WHITESPACE = String.raw`\t\n\x0B\f\r \x{A0}\x{1680}\x{2000}-\x{200A}\x{2028}\x{2029}\x{202F}\x{205F}\x{3000}\x{FEFF}`;
59
+ function re2Source(source) {
60
+ let out = "";
61
+ let inClass = false;
62
+ let unicodeClass = false;
63
+ let afterClass = false;
64
+ for (let i = 0; i < source.length; i++) {
65
+ const char = source[i];
66
+ const repeats = afterClass;
67
+ afterClass = false;
68
+ if (char === "{" && !inClass && repeats && unicodeClass) {
69
+ const bound = BOUNDED.exec(source.slice(i, i + 16));
70
+ if (bound) {
71
+ out += bound[1] === "0" ? "*" : "+";
72
+ i += bound[0].length - 1;
73
+ continue;
74
+ }
75
+ }
76
+ if (char === "\\") {
77
+ const next = source[++i] ?? "";
78
+ if (inClass && (next === "p" || next === "P")) {
79
+ unicodeClass = true;
80
+ }
81
+ if (next === "s") {
82
+ out += inClass ? WHITESPACE : `[${WHITESPACE}]`;
83
+ } else if (next === "S") {
84
+ if (inClass) {
85
+ throw new TypeError(String.raw`\S inside a character class has no RE2 equivalent here`);
86
+ }
87
+ out += `[^${WHITESPACE}]`;
88
+ } else {
89
+ out += `\\${next}`;
90
+ }
91
+ continue;
92
+ }
93
+ if (char === "[" && !inClass) {
94
+ inClass = true;
95
+ unicodeClass = false;
96
+ } else if (char === "]" && inClass) {
97
+ inClass = false;
98
+ afterClass = true;
99
+ }
100
+ out += char;
101
+ }
102
+ return out;
103
+ }
104
+ function linear(source, flags = "", Engine = RE2) {
105
+ return Engine ? new Engine(re2Source(source), flags) : new RegExp(source, flags);
106
+ }
107
+ function trimEndOf(value, characters) {
108
+ let end = value.length;
109
+ while (end > 0 && characters.includes(value[end - 1])) {
110
+ end--;
111
+ }
112
+ return value.slice(0, end);
113
+ }
114
+ function caseless(word) {
115
+ return [...word].map((letter) => `[${letter}${letter.toUpperCase()}]`).join("");
116
+ }
117
+ var OPENER = linear(String.raw`<(${caseless("script")}|${caseless("style")})\b`, "g");
118
+ var CLOSERS = {
119
+ script: linear(String.raw`<\/${caseless("script")}\s*>`, "g"),
120
+ style: linear(String.raw`<\/${caseless("style")}\s*>`, "g")
121
+ };
122
+
123
+ // src/tokenizer.js
124
+ var import_tldts2 = require("tldts");
125
+
126
+ // src/homograph.js
127
+ var import_node_url = require("node:url");
128
+ var import_tldts = require("tldts");
129
+
130
+ // src/language.js
131
+ var SCRIPTS = [
132
+ ["Latin", new RegExp("\\p{Script=Latin}", "u")],
133
+ ["Cyrillic", new RegExp("\\p{Script=Cyrillic}", "u")],
134
+ ["Greek", new RegExp("\\p{Script=Greek}", "u")],
135
+ ["Han", new RegExp("\\p{Script=Han}", "u")],
136
+ ["Hiragana", new RegExp("\\p{Script=Hiragana}", "u")],
137
+ ["Katakana", new RegExp("\\p{Script=Katakana}", "u")],
138
+ ["Hangul", new RegExp("\\p{Script=Hangul}", "u")],
139
+ ["Arabic", new RegExp("\\p{Script=Arabic}", "u")],
140
+ ["Hebrew", new RegExp("\\p{Script=Hebrew}", "u")],
141
+ ["Thai", new RegExp("\\p{Script=Thai}", "u")],
142
+ ["Devanagari", new RegExp("\\p{Script=Devanagari}", "u")],
143
+ ["Bengali", new RegExp("\\p{Script=Bengali}", "u")],
144
+ ["Tamil", new RegExp("\\p{Script=Tamil}", "u")],
145
+ ["Telugu", new RegExp("\\p{Script=Telugu}", "u")],
146
+ ["Gujarati", new RegExp("\\p{Script=Gujarati}", "u")],
147
+ ["Gurmukhi", new RegExp("\\p{Script=Gurmukhi}", "u")],
148
+ ["Kannada", new RegExp("\\p{Script=Kannada}", "u")],
149
+ ["Malayalam", new RegExp("\\p{Script=Malayalam}", "u")],
150
+ ["Armenian", new RegExp("\\p{Script=Armenian}", "u")],
151
+ ["Georgian", new RegExp("\\p{Script=Georgian}", "u")],
152
+ ["Ethiopic", new RegExp("\\p{Script=Ethiopic}", "u")],
153
+ ["Khmer", new RegExp("\\p{Script=Khmer}", "u")],
154
+ ["Lao", new RegExp("\\p{Script=Lao}", "u")],
155
+ ["Myanmar", new RegExp("\\p{Script=Myanmar}", "u")],
156
+ ["Sinhala", new RegExp("\\p{Script=Sinhala}", "u")]
157
+ ];
158
+ var LETTER = new RegExp("\\p{L}", "u");
159
+ function scriptOf(char) {
160
+ const entry = SCRIPTS.find(([, pattern]) => pattern.test(char));
161
+ return entry ? entry[0] : "Other";
162
+ }
163
+
164
+ // src/homograph.js
165
+ var INTERNATIONAL_BRANDS = [
166
+ "alipay",
167
+ "auspost",
168
+ "bancolombia",
169
+ "bnpparibas",
170
+ "bradesco",
171
+ "caixabank",
172
+ "canadapost",
173
+ "commerzbank",
174
+ "coupang",
175
+ "creditagricole",
176
+ "deutschebank",
177
+ "flipkart",
178
+ "gosuslugi",
179
+ "japanpost",
180
+ "kakaobank",
181
+ "klarna",
182
+ "kucoin",
183
+ "lazada",
184
+ "mercadolibre",
185
+ "mercadolivre",
186
+ "mercadopago",
187
+ "mercari",
188
+ "natwest",
189
+ "nubank",
190
+ "phonepe",
191
+ "postbank",
192
+ "rakuten",
193
+ "sberbank",
194
+ "swisscom",
195
+ "trustwallet",
196
+ "unicredit",
197
+ "vodafone",
198
+ "wechat",
199
+ "yandex"
200
+ ];
201
+ var BRANDS = [
202
+ "adobe",
203
+ "airbnb",
204
+ "alibaba",
205
+ "aliexpress",
206
+ "amazon",
207
+ "americanexpress",
208
+ "amex",
209
+ "apple",
210
+ "appleid",
211
+ "att",
212
+ "binance",
213
+ "bankofamerica",
214
+ "barclays",
215
+ "bestbuy",
216
+ "blockchain",
217
+ "booking",
218
+ "bybit",
219
+ "cashapp",
220
+ "chase",
221
+ "citibank",
222
+ "cloudflare",
223
+ "coinbase",
224
+ "comcast",
225
+ "costco",
226
+ "dhl",
227
+ "discord",
228
+ "docusign",
229
+ "dropbox",
230
+ "ebay",
231
+ "facebook",
232
+ "fedex",
233
+ "forwardemail",
234
+ "github",
235
+ "gitlab",
236
+ "gmail",
237
+ "godaddy",
238
+ "google",
239
+ "hmrc",
240
+ "hotmail",
241
+ "hsbc",
242
+ "icloud",
243
+ "instagram",
244
+ "intuit",
245
+ "irs",
246
+ "kraken",
247
+ "ledger",
248
+ "linkedin",
249
+ "mastercard",
250
+ "mcafee",
251
+ "metamask",
252
+ "microsoft",
253
+ "microsoftonline",
254
+ "namecheap",
255
+ "netflix",
256
+ "norton",
257
+ "office",
258
+ "office365",
259
+ "okta",
260
+ "onedrive",
261
+ "outlook",
262
+ "paypal",
263
+ "proton",
264
+ "protonmail",
265
+ "quickbooks",
266
+ "revolut",
267
+ "roblox",
268
+ "royalmail",
269
+ "salesforce",
270
+ "samsung",
271
+ "santander",
272
+ "sharepoint",
273
+ "shopify",
274
+ "skype",
275
+ "slack",
276
+ "sparkasse",
277
+ "spotify",
278
+ "steam",
279
+ "steampowered",
280
+ "stripe",
281
+ "telegram",
282
+ "tiktok",
283
+ "tmobile",
284
+ "trezor",
285
+ "tutanota",
286
+ "twitter",
287
+ "uber",
288
+ "ups",
289
+ "usps",
290
+ "venmo",
291
+ "verizon",
292
+ "visa",
293
+ "walmart",
294
+ "wellsfargo",
295
+ "whatsapp",
296
+ "wise",
297
+ "xfinity",
298
+ "yahoo",
299
+ "zelle",
300
+ "zoom",
301
+ ...INTERNATIONAL_BRANDS
302
+ ];
303
+ var WORD_BRANDS = /* @__PURE__ */ new Set(["apple", "blockchain", "booking", "chase", "discord", "kraken", "ledger", "office", "proton", "slack", "steam", "stripe"]);
304
+ var HELP_WORDS = ["help", "helpdesk", "support"];
305
+ var COMMON_WORD_BRANDS = /* @__PURE__ */ new Map([
306
+ ["blockchain", ["wallet", "wallets", ...HELP_WORDS]],
307
+ ["booking", []],
308
+ ["kraken", ["trade", "trading", "wallet", "wallets", ...HELP_WORDS]],
309
+ ["ledger", ["live", "wallet", "wallets", ...HELP_WORDS]],
310
+ ["office", []],
311
+ ["proton", ["pay", "wallet", ...HELP_WORDS]],
312
+ ["steam", ["community", "gift", "giftcard", "gifts", "trade", "trading", "wallet", ...HELP_WORDS]],
313
+ ["stripe", ["payment", "payments", ...HELP_WORDS]]
314
+ ]);
315
+ var TYPO_WORDS = /* @__PURE__ */ new Set([...WORD_BRANDS, "adobe", "binance", "fedex", "gmail", "icloud", "norton", "samsung", "tiktok", "tmobile", "trezor", "twitter", "venmo", "zelle"]);
316
+ var ASCII_TRICKS = [
317
+ [/rn/g, "m"],
318
+ [/vv/g, "w"],
319
+ [/cl/g, "d"],
320
+ [/0/g, "o"],
321
+ [/1/g, "l"],
322
+ [/3/g, "e"],
323
+ [/4/g, "a"],
324
+ [/5/g, "s"],
325
+ [/7/g, "t"],
326
+ [/8/g, "b"]
327
+ ];
328
+ var LETTER_TRICKS = ASCII_TRICKS.filter(([pattern]) => pattern.source === "cl" || pattern.source === "vv");
329
+
330
+ // src/entities.js
331
+ var NAMED = [
332
+ "AElig=c6,AMP=26,Aacute=c1,Abreve=102,Acirc=c2,Acy=410,Afr=1d504,Agrave=c0,Alpha=391,Amacr=100,And=2a",
333
+ "53,Aogon=104,Aopf=1d538,ApplyFunction=2061,Aring=c5,Ascr=1d49c,Assign=2254,Atilde=c3,Auml=c4,Backsla",
334
+ "sh=2216,Barv=2ae7,Barwed=2306,Bcy=411,Because=2235,Bernoullis=212c,Beta=392,Bfr=1d505,Bopf=1d539,Bre",
335
+ "ve=2d8,Bscr=212c,Bumpeq=224e,CHcy=427,COPY=a9,Cacute=106,Cap=22d2,CapitalDifferentialD=2145,Cayleys=",
336
+ "212d,Ccaron=10c,Ccedil=c7,Ccirc=108,Cconint=2230,Cdot=10a,Cedilla=b8,CenterDot=b7,Cfr=212d,Chi=3a7,C",
337
+ "ircleDot=2299,CircleMinus=2296,CirclePlus=2295,CircleTimes=2297,ClockwiseContourIntegral=2232,CloseC",
338
+ "urlyDoubleQuote=201d,CloseCurlyQuote=2019,Colon=2237,Colone=2a74,Congruent=2261,Conint=222f,ContourI",
339
+ "ntegral=222e,Copf=2102,Coproduct=2210,CounterClockwiseContourIntegral=2233,Cross=2a2f,Cscr=1d49e,Cup",
340
+ "=22d3,CupCap=224d,DD=2145,DDotrahd=2911,DJcy=402,DScy=405,DZcy=40f,Dagger=2021,Darr=21a1,Dashv=2ae4,",
341
+ "Dcaron=10e,Dcy=414,Del=2207,Delta=394,Dfr=1d507,DiacriticalAcute=b4,DiacriticalDot=2d9,DiacriticalDo",
342
+ "ubleAcute=2dd,DiacriticalGrave=60,DiacriticalTilde=2dc,Diamond=22c4,DifferentialD=2146,Dopf=1d53b,Do",
343
+ "t=a8,DotDot=20dc,DotEqual=2250,DoubleContourIntegral=222f,DoubleDot=a8,DoubleDownArrow=21d3,DoubleLe",
344
+ "ftArrow=21d0,DoubleLeftRightArrow=21d4,DoubleLeftTee=2ae4,DoubleLongLeftArrow=27f8,DoubleLongLeftRig",
345
+ "htArrow=27fa,DoubleLongRightArrow=27f9,DoubleRightArrow=21d2,DoubleRightTee=22a8,DoubleUpArrow=21d1,",
346
+ "DoubleUpDownArrow=21d5,DoubleVerticalBar=2225,DownArrow=2193,DownArrowBar=2913,DownArrowUpArrow=21f5",
347
+ ",DownBreve=311,DownLeftRightVector=2950,DownLeftTeeVector=295e,DownLeftVector=21bd,DownLeftVectorBar",
348
+ "=2956,DownRightTeeVector=295f,DownRightVector=21c1,DownRightVectorBar=2957,DownTee=22a4,DownTeeArrow",
349
+ "=21a7,Downarrow=21d3,Dscr=1d49f,Dstrok=110,ENG=14a,ETH=d0,Eacute=c9,Ecaron=11a,Ecirc=ca,Ecy=42d,Edot",
350
+ "=116,Efr=1d508,Egrave=c8,Element=2208,Emacr=112,EmptySmallSquare=25fb,EmptyVerySmallSquare=25ab,Eogo",
351
+ "n=118,Eopf=1d53c,Epsilon=395,Equal=2a75,EqualTilde=2242,Equilibrium=21cc,Escr=2130,Esim=2a73,Eta=397",
352
+ ",Euml=cb,Exists=2203,ExponentialE=2147,Fcy=424,Ffr=1d509,FilledSmallSquare=25fc,FilledVerySmallSquar",
353
+ "e=25aa,Fopf=1d53d,ForAll=2200,Fouriertrf=2131,Fscr=2131,GJcy=403,GT=3e,Gamma=393,Gammad=3dc,Gbreve=1",
354
+ "1e,Gcedil=122,Gcirc=11c,Gcy=413,Gdot=120,Gfr=1d50a,Gg=22d9,Gopf=1d53e,GreaterEqual=2265,GreaterEqual",
355
+ "Less=22db,GreaterFullEqual=2267,GreaterGreater=2aa2,GreaterLess=2277,GreaterSlantEqual=2a7e,GreaterT",
356
+ "ilde=2273,Gscr=1d4a2,Gt=226b,HARDcy=42a,Hacek=2c7,Hat=5e,Hcirc=124,Hfr=210c,HilbertSpace=210b,Hopf=2",
357
+ "10d,HorizontalLine=2500,Hscr=210b,Hstrok=126,HumpDownHump=224e,HumpEqual=224f,IEcy=415,IJlig=132,IOc",
358
+ "y=401,Iacute=cd,Icirc=ce,Icy=418,Idot=130,Ifr=2111,Igrave=cc,Im=2111,Imacr=12a,ImaginaryI=2148,Impli",
359
+ "es=21d2,Int=222c,Integral=222b,Intersection=22c2,InvisibleComma=2063,InvisibleTimes=2062,Iogon=12e,I",
360
+ "opf=1d540,Iota=399,Iscr=2110,Itilde=128,Iukcy=406,Iuml=cf,Jcirc=134,Jcy=419,Jfr=1d50d,Jopf=1d541,Jsc",
361
+ "r=1d4a5,Jsercy=408,Jukcy=404,KHcy=425,KJcy=40c,Kappa=39a,Kcedil=136,Kcy=41a,Kfr=1d50e,Kopf=1d542,Ksc",
362
+ "r=1d4a6,LJcy=409,LT=3c,Lacute=139,Lambda=39b,Lang=27ea,Laplacetrf=2112,Larr=219e,Lcaron=13d,Lcedil=1",
363
+ "3b,Lcy=41b,LeftAngleBracket=27e8,LeftArrow=2190,LeftArrowBar=21e4,LeftArrowRightArrow=21c6,LeftCeili",
364
+ "ng=2308,LeftDoubleBracket=27e6,LeftDownTeeVector=2961,LeftDownVector=21c3,LeftDownVectorBar=2959,Lef",
365
+ "tFloor=230a,LeftRightArrow=2194,LeftRightVector=294e,LeftTee=22a3,LeftTeeArrow=21a4,LeftTeeVector=29",
366
+ "5a,LeftTriangle=22b2,LeftTriangleBar=29cf,LeftTriangleEqual=22b4,LeftUpDownVector=2951,LeftUpTeeVect",
367
+ "or=2960,LeftUpVector=21bf,LeftUpVectorBar=2958,LeftVector=21bc,LeftVectorBar=2952,Leftarrow=21d0,Lef",
368
+ "trightarrow=21d4,LessEqualGreater=22da,LessFullEqual=2266,LessGreater=2276,LessLess=2aa1,LessSlantEq",
369
+ "ual=2a7d,LessTilde=2272,Lfr=1d50f,Ll=22d8,Lleftarrow=21da,Lmidot=13f,LongLeftArrow=27f5,LongLeftRigh",
370
+ "tArrow=27f7,LongRightArrow=27f6,Longleftarrow=27f8,Longleftrightarrow=27fa,Longrightarrow=27f9,Lopf=",
371
+ "1d543,LowerLeftArrow=2199,LowerRightArrow=2198,Lscr=2112,Lsh=21b0,Lstrok=141,Lt=226a,Map=2905,Mcy=41",
372
+ "c,MediumSpace=205f,Mellintrf=2133,Mfr=1d510,MinusPlus=2213,Mopf=1d544,Mscr=2133,Mu=39c,NJcy=40a,Nacu",
373
+ "te=143,Ncaron=147,Ncedil=145,Ncy=41d,NegativeMediumSpace=200b,NegativeThickSpace=200b,NegativeThinSp",
374
+ "ace=200b,NegativeVeryThinSpace=200b,NestedGreaterGreater=226b,NestedLessLess=226a,NewLine=a,Nfr=1d51",
375
+ "1,NoBreak=2060,NonBreakingSpace=a0,Nopf=2115,Not=2aec,NotCongruent=2262,NotCupCap=226d,NotDoubleVert",
376
+ "icalBar=2226,NotElement=2209,NotEqual=2260,NotEqualTilde=2242.338,NotExists=2204,NotGreater=226f,Not",
377
+ "GreaterEqual=2271,NotGreaterFullEqual=2267.338,NotGreaterGreater=226b.338,NotGreaterLess=2279,NotGre",
378
+ "aterSlantEqual=2a7e.338,NotGreaterTilde=2275,NotHumpDownHump=224e.338,NotHumpEqual=224f.338,NotLeftT",
379
+ "riangle=22ea,NotLeftTriangleBar=29cf.338,NotLeftTriangleEqual=22ec,NotLess=226e,NotLessEqual=2270,No",
380
+ "tLessGreater=2278,NotLessLess=226a.338,NotLessSlantEqual=2a7d.338,NotLessTilde=2274,NotNestedGreater",
381
+ "Greater=2aa2.338,NotNestedLessLess=2aa1.338,NotPrecedes=2280,NotPrecedesEqual=2aaf.338,NotPrecedesSl",
382
+ "antEqual=22e0,NotReverseElement=220c,NotRightTriangle=22eb,NotRightTriangleBar=29d0.338,NotRightTria",
383
+ "ngleEqual=22ed,NotSquareSubset=228f.338,NotSquareSubsetEqual=22e2,NotSquareSuperset=2290.338,NotSqua",
384
+ "reSupersetEqual=22e3,NotSubset=2282.20d2,NotSubsetEqual=2288,NotSucceeds=2281,NotSucceedsEqual=2ab0.",
385
+ "338,NotSucceedsSlantEqual=22e1,NotSucceedsTilde=227f.338,NotSuperset=2283.20d2,NotSupersetEqual=2289",
386
+ ",NotTilde=2241,NotTildeEqual=2244,NotTildeFullEqual=2247,NotTildeTilde=2249,NotVerticalBar=2224,Nscr",
387
+ "=1d4a9,Ntilde=d1,Nu=39d,OElig=152,Oacute=d3,Ocirc=d4,Ocy=41e,Odblac=150,Ofr=1d512,Ograve=d2,Omacr=14",
388
+ "c,Omega=3a9,Omicron=39f,Oopf=1d546,OpenCurlyDoubleQuote=201c,OpenCurlyQuote=2018,Or=2a54,Oscr=1d4aa,",
389
+ "Oslash=d8,Otilde=d5,Otimes=2a37,Ouml=d6,OverBar=203e,OverBrace=23de,OverBracket=23b4,OverParenthesis",
390
+ "=23dc,PartialD=2202,Pcy=41f,Pfr=1d513,Phi=3a6,Pi=3a0,PlusMinus=b1,Poincareplane=210c,Popf=2119,Pr=2a",
391
+ "bb,Precedes=227a,PrecedesEqual=2aaf,PrecedesSlantEqual=227c,PrecedesTilde=227e,Prime=2033,Product=22",
392
+ "0f,Proportion=2237,Proportional=221d,Pscr=1d4ab,Psi=3a8,QUOT=22,Qfr=1d514,Qopf=211a,Qscr=1d4ac,RBarr",
393
+ "=2910,REG=ae,Racute=154,Rang=27eb,Rarr=21a0,Rarrtl=2916,Rcaron=158,Rcedil=156,Rcy=420,Re=211c,Revers",
394
+ "eElement=220b,ReverseEquilibrium=21cb,ReverseUpEquilibrium=296f,Rfr=211c,Rho=3a1,RightAngleBracket=2",
395
+ "7e9,RightArrow=2192,RightArrowBar=21e5,RightArrowLeftArrow=21c4,RightCeiling=2309,RightDoubleBracket",
396
+ "=27e7,RightDownTeeVector=295d,RightDownVector=21c2,RightDownVectorBar=2955,RightFloor=230b,RightTee=",
397
+ "22a2,RightTeeArrow=21a6,RightTeeVector=295b,RightTriangle=22b3,RightTriangleBar=29d0,RightTriangleEq",
398
+ "ual=22b5,RightUpDownVector=294f,RightUpTeeVector=295c,RightUpVector=21be,RightUpVectorBar=2954,Right",
399
+ "Vector=21c0,RightVectorBar=2953,Rightarrow=21d2,Ropf=211d,RoundImplies=2970,Rrightarrow=21db,Rscr=21",
400
+ "1b,Rsh=21b1,RuleDelayed=29f4,SHCHcy=429,SHcy=428,SOFTcy=42c,Sacute=15a,Sc=2abc,Scaron=160,Scedil=15e",
401
+ ",Scirc=15c,Scy=421,Sfr=1d516,ShortDownArrow=2193,ShortLeftArrow=2190,ShortRightArrow=2192,ShortUpArr",
402
+ "ow=2191,Sigma=3a3,SmallCircle=2218,Sopf=1d54a,Sqrt=221a,Square=25a1,SquareIntersection=2293,SquareSu",
403
+ "bset=228f,SquareSubsetEqual=2291,SquareSuperset=2290,SquareSupersetEqual=2292,SquareUnion=2294,Sscr=",
404
+ "1d4ae,Star=22c6,Sub=22d0,Subset=22d0,SubsetEqual=2286,Succeeds=227b,SucceedsEqual=2ab0,SucceedsSlant",
405
+ "Equal=227d,SucceedsTilde=227f,SuchThat=220b,Sum=2211,Sup=22d1,Superset=2283,SupersetEqual=2287,Supse",
406
+ "t=22d1,THORN=de,TRADE=2122,TSHcy=40b,TScy=426,Tab=9,Tau=3a4,Tcaron=164,Tcedil=162,Tcy=422,Tfr=1d517,",
407
+ "Therefore=2234,Theta=398,ThickSpace=205f.200a,ThinSpace=2009,Tilde=223c,TildeEqual=2243,TildeFullEqu",
408
+ "al=2245,TildeTilde=2248,Topf=1d54b,TripleDot=20db,Tscr=1d4af,Tstrok=166,Uacute=da,Uarr=219f,Uarrocir",
409
+ "=2949,Ubrcy=40e,Ubreve=16c,Ucirc=db,Ucy=423,Udblac=170,Ufr=1d518,Ugrave=d9,Umacr=16a,UnderBar=5f,Und",
410
+ "erBrace=23df,UnderBracket=23b5,UnderParenthesis=23dd,Union=22c3,UnionPlus=228e,Uogon=172,Uopf=1d54c,",
411
+ "UpArrow=2191,UpArrowBar=2912,UpArrowDownArrow=21c5,UpDownArrow=2195,UpEquilibrium=296e,UpTee=22a5,Up",
412
+ "TeeArrow=21a5,Uparrow=21d1,Updownarrow=21d5,UpperLeftArrow=2196,UpperRightArrow=2197,Upsi=3d2,Upsilo",
413
+ "n=3a5,Uring=16e,Uscr=1d4b0,Utilde=168,Uuml=dc,VDash=22ab,Vbar=2aeb,Vcy=412,Vdash=22a9,Vdashl=2ae6,Ve",
414
+ "e=22c1,Verbar=2016,Vert=2016,VerticalBar=2223,VerticalLine=7c,VerticalSeparator=2758,VerticalTilde=2",
415
+ "240,VeryThinSpace=200a,Vfr=1d519,Vopf=1d54d,Vscr=1d4b1,Vvdash=22aa,Wcirc=174,Wedge=22c0,Wfr=1d51a,Wo",
416
+ "pf=1d54e,Wscr=1d4b2,Xfr=1d51b,Xi=39e,Xopf=1d54f,Xscr=1d4b3,YAcy=42f,YIcy=407,YUcy=42e,Yacute=dd,Ycir",
417
+ "c=176,Ycy=42b,Yfr=1d51c,Yopf=1d550,Yscr=1d4b4,Yuml=178,ZHcy=416,Zacute=179,Zcaron=17d,Zcy=417,Zdot=1",
418
+ "7b,ZeroWidthSpace=200b,Zeta=396,Zfr=2128,Zopf=2124,Zscr=1d4b5,aacute=e1,abreve=103,ac=223e,acE=223e.",
419
+ "333,acd=223f,acirc=e2,acute=b4,acy=430,aelig=e6,af=2061,afr=1d51e,agrave=e0,alefsym=2135,aleph=2135,",
420
+ "alpha=3b1,amacr=101,amalg=2a3f,amp=26,and=2227,andand=2a55,andd=2a5c,andslope=2a58,andv=2a5a,ang=222",
421
+ "0,ange=29a4,angle=2220,angmsd=2221,angmsdaa=29a8,angmsdab=29a9,angmsdac=29aa,angmsdad=29ab,angmsdae=",
422
+ "29ac,angmsdaf=29ad,angmsdag=29ae,angmsdah=29af,angrt=221f,angrtvb=22be,angrtvbd=299d,angsph=2222,ang",
423
+ "st=c5,angzarr=237c,aogon=105,aopf=1d552,ap=2248,apE=2a70,apacir=2a6f,ape=224a,apid=224b,apos=27,appr",
424
+ "ox=2248,approxeq=224a,aring=e5,ascr=1d4b6,ast=2a,asymp=2248,asympeq=224d,atilde=e3,auml=e4,awconint=",
425
+ "2233,awint=2a11,bNot=2aed,backcong=224c,backepsilon=3f6,backprime=2035,backsim=223d,backsimeq=22cd,b",
426
+ "arvee=22bd,barwed=2305,barwedge=2305,bbrk=23b5,bbrktbrk=23b6,bcong=224c,bcy=431,bdquo=201e,becaus=22",
427
+ "35,because=2235,bemptyv=29b0,bepsi=3f6,bernou=212c,beta=3b2,beth=2136,between=226c,bfr=1d51f,bigcap=",
428
+ "22c2,bigcirc=25ef,bigcup=22c3,bigodot=2a00,bigoplus=2a01,bigotimes=2a02,bigsqcup=2a06,bigstar=2605,b",
429
+ "igtriangledown=25bd,bigtriangleup=25b3,biguplus=2a04,bigvee=22c1,bigwedge=22c0,bkarow=290d,blackloze",
430
+ "nge=29eb,blacksquare=25aa,blacktriangle=25b4,blacktriangledown=25be,blacktriangleleft=25c2,blacktria",
431
+ "ngleright=25b8,blank=2423,blk12=2592,blk14=2591,blk34=2593,block=2588,bne=3d.20e5,bnequiv=2261.20e5,",
432
+ "bnot=2310,bopf=1d553,bot=22a5,bottom=22a5,bowtie=22c8,boxDL=2557,boxDR=2554,boxDl=2556,boxDr=2553,bo",
433
+ "xH=2550,boxHD=2566,boxHU=2569,boxHd=2564,boxHu=2567,boxUL=255d,boxUR=255a,boxUl=255c,boxUr=2559,boxV",
434
+ "=2551,boxVH=256c,boxVL=2563,boxVR=2560,boxVh=256b,boxVl=2562,boxVr=255f,boxbox=29c9,boxdL=2555,boxdR",
435
+ "=2552,boxdl=2510,boxdr=250c,boxh=2500,boxhD=2565,boxhU=2568,boxhd=252c,boxhu=2534,boxminus=229f,boxp",
436
+ "lus=229e,boxtimes=22a0,boxuL=255b,boxuR=2558,boxul=2518,boxur=2514,boxv=2502,boxvH=256a,boxvL=2561,b",
437
+ "oxvR=255e,boxvh=253c,boxvl=2524,boxvr=251c,bprime=2035,breve=2d8,brvbar=a6,bscr=1d4b7,bsemi=204f,bsi",
438
+ "m=223d,bsime=22cd,bsol=5c,bsolb=29c5,bsolhsub=27c8,bull=2022,bullet=2022,bump=224e,bumpE=2aae,bumpe=",
439
+ "224f,bumpeq=224f,cacute=107,cap=2229,capand=2a44,capbrcup=2a49,capcap=2a4b,capcup=2a47,capdot=2a40,c",
440
+ "aps=2229.fe00,caret=2041,caron=2c7,ccaps=2a4d,ccaron=10d,ccedil=e7,ccirc=109,ccups=2a4c,ccupssm=2a50",
441
+ ",cdot=10b,cedil=b8,cemptyv=29b2,cent=a2,centerdot=b7,cfr=1d520,chcy=447,check=2713,checkmark=2713,ch",
442
+ "i=3c7,cir=25cb,cirE=29c3,circ=2c6,circeq=2257,circlearrowleft=21ba,circlearrowright=21bb,circledR=ae",
443
+ ",circledS=24c8,circledast=229b,circledcirc=229a,circleddash=229d,cire=2257,cirfnint=2a10,cirmid=2aef",
444
+ ",cirscir=29c2,clubs=2663,clubsuit=2663,colon=3a,colone=2254,coloneq=2254,comma=2c,commat=40,comp=220",
445
+ "1,compfn=2218,complement=2201,complexes=2102,cong=2245,congdot=2a6d,conint=222e,copf=1d554,coprod=22",
446
+ "10,copy=a9,copysr=2117,crarr=21b5,cross=2717,cscr=1d4b8,csub=2acf,csube=2ad1,csup=2ad0,csupe=2ad2,ct",
447
+ "dot=22ef,cudarrl=2938,cudarrr=2935,cuepr=22de,cuesc=22df,cularr=21b6,cularrp=293d,cup=222a,cupbrcap=",
448
+ "2a48,cupcap=2a46,cupcup=2a4a,cupdot=228d,cupor=2a45,cups=222a.fe00,curarr=21b7,curarrm=293c,curlyeqp",
449
+ "rec=22de,curlyeqsucc=22df,curlyvee=22ce,curlywedge=22cf,curren=a4,curvearrowleft=21b6,curvearrowrigh",
450
+ "t=21b7,cuvee=22ce,cuwed=22cf,cwconint=2232,cwint=2231,cylcty=232d,dArr=21d3,dHar=2965,dagger=2020,da",
451
+ "leth=2138,darr=2193,dash=2010,dashv=22a3,dbkarow=290f,dblac=2dd,dcaron=10f,dcy=434,dd=2146,ddagger=2",
452
+ "021,ddarr=21ca,ddotseq=2a77,deg=b0,delta=3b4,demptyv=29b1,dfisht=297f,dfr=1d521,dharl=21c3,dharr=21c",
453
+ "2,diam=22c4,diamond=22c4,diamondsuit=2666,diams=2666,die=a8,digamma=3dd,disin=22f2,div=f7,divide=f7,",
454
+ "divideontimes=22c7,divonx=22c7,djcy=452,dlcorn=231e,dlcrop=230d,dollar=24,dopf=1d555,dot=2d9,doteq=2",
455
+ "250,doteqdot=2251,dotminus=2238,dotplus=2214,dotsquare=22a1,doublebarwedge=2306,downarrow=2193,downd",
456
+ "ownarrows=21ca,downharpoonleft=21c3,downharpoonright=21c2,drbkarow=2910,drcorn=231f,drcrop=230c,dscr",
457
+ "=1d4b9,dscy=455,dsol=29f6,dstrok=111,dtdot=22f1,dtri=25bf,dtrif=25be,duarr=21f5,duhar=296f,dwangle=2",
458
+ "9a6,dzcy=45f,dzigrarr=27ff,eDDot=2a77,eDot=2251,eacute=e9,easter=2a6e,ecaron=11b,ecir=2256,ecirc=ea,",
459
+ "ecolon=2255,ecy=44d,edot=117,ee=2147,efDot=2252,efr=1d522,eg=2a9a,egrave=e8,egs=2a96,egsdot=2a98,el=",
460
+ "2a99,elinters=23e7,ell=2113,els=2a95,elsdot=2a97,emacr=113,empty=2205,emptyset=2205,emptyv=2205,emsp",
461
+ "=2003,emsp13=2004,emsp14=2005,eng=14b,ensp=2002,eogon=119,eopf=1d556,epar=22d5,eparsl=29e3,eplus=2a7",
462
+ "1,epsi=3b5,epsilon=3b5,epsiv=3f5,eqcirc=2256,eqcolon=2255,eqsim=2242,eqslantgtr=2a96,eqslantless=2a9",
463
+ "5,equals=3d,equest=225f,equiv=2261,equivDD=2a78,eqvparsl=29e5,erDot=2253,erarr=2971,escr=212f,esdot=",
464
+ "2250,esim=2242,eta=3b7,eth=f0,euml=eb,euro=20ac,excl=21,exist=2203,expectation=2130,exponentiale=214",
465
+ "7,fallingdotseq=2252,fcy=444,female=2640,ffilig=fb03,fflig=fb00,ffllig=fb04,ffr=1d523,filig=fb01,fjl",
466
+ "ig=66.6a,flat=266d,fllig=fb02,fltns=25b1,fnof=192,fopf=1d557,forall=2200,fork=22d4,forkv=2ad9,fparti",
467
+ "nt=2a0d,frac12=bd,frac13=2153,frac14=bc,frac15=2155,frac16=2159,frac18=215b,frac23=2154,frac25=2156,",
468
+ "frac34=be,frac35=2157,frac38=215c,frac45=2158,frac56=215a,frac58=215d,frac78=215e,frasl=2044,frown=2",
469
+ "322,fscr=1d4bb,gE=2267,gEl=2a8c,gacute=1f5,gamma=3b3,gammad=3dd,gap=2a86,gbreve=11f,gcirc=11d,gcy=43",
470
+ "3,gdot=121,ge=2265,gel=22db,geq=2265,geqq=2267,geqslant=2a7e,ges=2a7e,gescc=2aa9,gesdot=2a80,gesdoto",
471
+ "=2a82,gesdotol=2a84,gesl=22db.fe00,gesles=2a94,gfr=1d524,gg=226b,ggg=22d9,gimel=2137,gjcy=453,gl=227",
472
+ "7,glE=2a92,gla=2aa5,glj=2aa4,gnE=2269,gnap=2a8a,gnapprox=2a8a,gne=2a88,gneq=2a88,gneqq=2269,gnsim=22",
473
+ "e7,gopf=1d558,grave=60,gscr=210a,gsim=2273,gsime=2a8e,gsiml=2a90,gt=3e,gtcc=2aa7,gtcir=2a7a,gtdot=22",
474
+ "d7,gtlPar=2995,gtquest=2a7c,gtrapprox=2a86,gtrarr=2978,gtrdot=22d7,gtreqless=22db,gtreqqless=2a8c,gt",
475
+ "rless=2277,gtrsim=2273,gvertneqq=2269.fe00,gvnE=2269.fe00,hArr=21d4,hairsp=200a,half=bd,hamilt=210b,",
476
+ "hardcy=44a,harr=2194,harrcir=2948,harrw=21ad,hbar=210f,hcirc=125,hearts=2665,heartsuit=2665,hellip=2",
477
+ "026,hercon=22b9,hfr=1d525,hksearow=2925,hkswarow=2926,hoarr=21ff,homtht=223b,hookleftarrow=21a9,hook",
478
+ "rightarrow=21aa,hopf=1d559,horbar=2015,hscr=1d4bd,hslash=210f,hstrok=127,hybull=2043,hyphen=2010,iac",
479
+ "ute=ed,ic=2063,icirc=ee,icy=438,iecy=435,iexcl=a1,iff=21d4,ifr=1d526,igrave=ec,ii=2148,iiiint=2a0c,i",
480
+ "iint=222d,iinfin=29dc,iiota=2129,ijlig=133,imacr=12b,image=2111,imagline=2110,imagpart=2111,imath=13",
481
+ "1,imof=22b7,imped=1b5,in=2208,incare=2105,infin=221e,infintie=29dd,inodot=131,int=222b,intcal=22ba,i",
482
+ "ntegers=2124,intercal=22ba,intlarhk=2a17,intprod=2a3c,iocy=451,iogon=12f,iopf=1d55a,iota=3b9,iprod=2",
483
+ "a3c,iquest=bf,iscr=1d4be,isin=2208,isinE=22f9,isindot=22f5,isins=22f4,isinsv=22f3,isinv=2208,it=2062",
484
+ ",itilde=129,iukcy=456,iuml=ef,jcirc=135,jcy=439,jfr=1d527,jmath=237,jopf=1d55b,jscr=1d4bf,jsercy=458",
485
+ ",jukcy=454,kappa=3ba,kappav=3f0,kcedil=137,kcy=43a,kfr=1d528,kgreen=138,khcy=445,kjcy=45c,kopf=1d55c",
486
+ ",kscr=1d4c0,lAarr=21da,lArr=21d0,lAtail=291b,lBarr=290e,lE=2266,lEg=2a8b,lHar=2962,lacute=13a,laempt",
487
+ "yv=29b4,lagran=2112,lambda=3bb,lang=27e8,langd=2991,langle=27e8,lap=2a85,laquo=ab,larr=2190,larrb=21",
488
+ "e4,larrbfs=291f,larrfs=291d,larrhk=21a9,larrlp=21ab,larrpl=2939,larrsim=2973,larrtl=21a2,lat=2aab,la",
489
+ "tail=2919,late=2aad,lates=2aad.fe00,lbarr=290c,lbbrk=2772,lbrace=7b,lbrack=5b,lbrke=298b,lbrksld=298",
490
+ "f,lbrkslu=298d,lcaron=13e,lcedil=13c,lceil=2308,lcub=7b,lcy=43b,ldca=2936,ldquo=201c,ldquor=201e,ldr",
491
+ "dhar=2967,ldrushar=294b,ldsh=21b2,le=2264,leftarrow=2190,leftarrowtail=21a2,leftharpoondown=21bd,lef",
492
+ "tharpoonup=21bc,leftleftarrows=21c7,leftrightarrow=2194,leftrightarrows=21c6,leftrightharpoons=21cb,",
493
+ "leftrightsquigarrow=21ad,leftthreetimes=22cb,leg=22da,leq=2264,leqq=2266,leqslant=2a7d,les=2a7d,lesc",
494
+ "c=2aa8,lesdot=2a7f,lesdoto=2a81,lesdotor=2a83,lesg=22da.fe00,lesges=2a93,lessapprox=2a85,lessdot=22d",
495
+ "6,lesseqgtr=22da,lesseqqgtr=2a8b,lessgtr=2276,lesssim=2272,lfisht=297c,lfloor=230a,lfr=1d529,lg=2276",
496
+ ",lgE=2a91,lhard=21bd,lharu=21bc,lharul=296a,lhblk=2584,ljcy=459,ll=226a,llarr=21c7,llcorner=231e,llh",
497
+ "ard=296b,lltri=25fa,lmidot=140,lmoust=23b0,lmoustache=23b0,lnE=2268,lnap=2a89,lnapprox=2a89,lne=2a87",
498
+ ",lneq=2a87,lneqq=2268,lnsim=22e6,loang=27ec,loarr=21fd,lobrk=27e6,longleftarrow=27f5,longleftrightar",
499
+ "row=27f7,longmapsto=27fc,longrightarrow=27f6,looparrowleft=21ab,looparrowright=21ac,lopar=2985,lopf=",
500
+ "1d55d,loplus=2a2d,lotimes=2a34,lowast=2217,lowbar=5f,loz=25ca,lozenge=25ca,lozf=29eb,lpar=28,lparlt=",
501
+ "2993,lrarr=21c6,lrcorner=231f,lrhar=21cb,lrhard=296d,lrm=200e,lrtri=22bf,lsaquo=2039,lscr=1d4c1,lsh=",
502
+ "21b0,lsim=2272,lsime=2a8d,lsimg=2a8f,lsqb=5b,lsquo=2018,lsquor=201a,lstrok=142,lt=3c,ltcc=2aa6,ltcir",
503
+ "=2a79,ltdot=22d6,lthree=22cb,ltimes=22c9,ltlarr=2976,ltquest=2a7b,ltrPar=2996,ltri=25c3,ltrie=22b4,l",
504
+ "trif=25c2,lurdshar=294a,luruhar=2966,lvertneqq=2268.fe00,lvnE=2268.fe00,mDDot=223a,macr=af,male=2642",
505
+ ",malt=2720,maltese=2720,map=21a6,mapsto=21a6,mapstodown=21a7,mapstoleft=21a4,mapstoup=21a5,marker=25",
506
+ "ae,mcomma=2a29,mcy=43c,mdash=2014,measuredangle=2221,mfr=1d52a,mho=2127,micro=b5,mid=2223,midast=2a,",
507
+ "midcir=2af0,middot=b7,minus=2212,minusb=229f,minusd=2238,minusdu=2a2a,mlcp=2adb,mldr=2026,mnplus=221",
508
+ "3,models=22a7,mopf=1d55e,mp=2213,mscr=1d4c2,mstpos=223e,mu=3bc,multimap=22b8,mumap=22b8,nGg=22d9.338",
509
+ ",nGt=226b.20d2,nGtv=226b.338,nLeftarrow=21cd,nLeftrightarrow=21ce,nLl=22d8.338,nLt=226a.20d2,nLtv=22",
510
+ "6a.338,nRightarrow=21cf,nVDash=22af,nVdash=22ae,nabla=2207,nacute=144,nang=2220.20d2,nap=2249,napE=2",
511
+ "a70.338,napid=224b.338,napos=149,napprox=2249,natur=266e,natural=266e,naturals=2115,nbsp=a0,nbump=22",
512
+ "4e.338,nbumpe=224f.338,ncap=2a43,ncaron=148,ncedil=146,ncong=2247,ncongdot=2a6d.338,ncup=2a42,ncy=43",
513
+ "d,ndash=2013,ne=2260,neArr=21d7,nearhk=2924,nearr=2197,nearrow=2197,nedot=2250.338,nequiv=2262,nesea",
514
+ "r=2928,nesim=2242.338,nexist=2204,nexists=2204,nfr=1d52b,ngE=2267.338,nge=2271,ngeq=2271,ngeqq=2267.",
515
+ "338,ngeqslant=2a7e.338,nges=2a7e.338,ngsim=2275,ngt=226f,ngtr=226f,nhArr=21ce,nharr=21ae,nhpar=2af2,",
516
+ "ni=220b,nis=22fc,nisd=22fa,niv=220b,njcy=45a,nlArr=21cd,nlE=2266.338,nlarr=219a,nldr=2025,nle=2270,n",
517
+ "leftarrow=219a,nleftrightarrow=21ae,nleq=2270,nleqq=2266.338,nleqslant=2a7d.338,nles=2a7d.338,nless=",
518
+ "226e,nlsim=2274,nlt=226e,nltri=22ea,nltrie=22ec,nmid=2224,nopf=1d55f,not=ac,notin=2209,notinE=22f9.3",
519
+ "38,notindot=22f5.338,notinva=2209,notinvb=22f7,notinvc=22f6,notni=220c,notniva=220c,notnivb=22fe,not",
520
+ "nivc=22fd,npar=2226,nparallel=2226,nparsl=2afd.20e5,npart=2202.338,npolint=2a14,npr=2280,nprcue=22e0",
521
+ ",npre=2aaf.338,nprec=2280,npreceq=2aaf.338,nrArr=21cf,nrarr=219b,nrarrc=2933.338,nrarrw=219d.338,nri",
522
+ "ghtarrow=219b,nrtri=22eb,nrtrie=22ed,nsc=2281,nsccue=22e1,nsce=2ab0.338,nscr=1d4c3,nshortmid=2224,ns",
523
+ "hortparallel=2226,nsim=2241,nsime=2244,nsimeq=2244,nsmid=2224,nspar=2226,nsqsube=22e2,nsqsupe=22e3,n",
524
+ "sub=2284,nsubE=2ac5.338,nsube=2288,nsubset=2282.20d2,nsubseteq=2288,nsubseteqq=2ac5.338,nsucc=2281,n",
525
+ "succeq=2ab0.338,nsup=2285,nsupE=2ac6.338,nsupe=2289,nsupset=2283.20d2,nsupseteq=2289,nsupseteqq=2ac6",
526
+ ".338,ntgl=2279,ntilde=f1,ntlg=2278,ntriangleleft=22ea,ntrianglelefteq=22ec,ntriangleright=22eb,ntria",
527
+ "nglerighteq=22ed,nu=3bd,num=23,numero=2116,numsp=2007,nvDash=22ad,nvHarr=2904,nvap=224d.20d2,nvdash=",
528
+ "22ac,nvge=2265.20d2,nvgt=3e.20d2,nvinfin=29de,nvlArr=2902,nvle=2264.20d2,nvlt=3c.20d2,nvltrie=22b4.2",
529
+ "0d2,nvrArr=2903,nvrtrie=22b5.20d2,nvsim=223c.20d2,nwArr=21d6,nwarhk=2923,nwarr=2196,nwarrow=2196,nwn",
530
+ "ear=2927,oS=24c8,oacute=f3,oast=229b,ocir=229a,ocirc=f4,ocy=43e,odash=229d,odblac=151,odiv=2a38,odot",
531
+ "=2299,odsold=29bc,oelig=153,ofcir=29bf,ofr=1d52c,ogon=2db,ograve=f2,ogt=29c1,ohbar=29b5,ohm=3a9,oint",
532
+ "=222e,olarr=21ba,olcir=29be,olcross=29bb,oline=203e,olt=29c0,omacr=14d,omega=3c9,omicron=3bf,omid=29",
533
+ "b6,ominus=2296,oopf=1d560,opar=29b7,operp=29b9,oplus=2295,or=2228,orarr=21bb,ord=2a5d,order=2134,ord",
534
+ "erof=2134,ordf=aa,ordm=ba,origof=22b6,oror=2a56,orslope=2a57,orv=2a5b,oscr=2134,oslash=f8,osol=2298,",
535
+ "otilde=f5,otimes=2297,otimesas=2a36,ouml=f6,ovbar=233d,par=2225,para=b6,parallel=2225,parsim=2af3,pa",
536
+ "rsl=2afd,part=2202,pcy=43f,percnt=25,period=2e,permil=2030,perp=22a5,pertenk=2031,pfr=1d52d,phi=3c6,",
537
+ "phiv=3d5,phmmat=2133,phone=260e,pi=3c0,pitchfork=22d4,piv=3d6,planck=210f,planckh=210e,plankv=210f,p",
538
+ "lus=2b,plusacir=2a23,plusb=229e,pluscir=2a22,plusdo=2214,plusdu=2a25,pluse=2a72,plusmn=b1,plussim=2a",
539
+ "26,plustwo=2a27,pm=b1,pointint=2a15,popf=1d561,pound=a3,pr=227a,prE=2ab3,prap=2ab7,prcue=227c,pre=2a",
540
+ "af,prec=227a,precapprox=2ab7,preccurlyeq=227c,preceq=2aaf,precnapprox=2ab9,precneqq=2ab5,precnsim=22",
541
+ "e8,precsim=227e,prime=2032,primes=2119,prnE=2ab5,prnap=2ab9,prnsim=22e8,prod=220f,profalar=232e,prof",
542
+ "line=2312,profsurf=2313,prop=221d,propto=221d,prsim=227e,prurel=22b0,pscr=1d4c5,psi=3c8,puncsp=2008,",
543
+ "qfr=1d52e,qint=2a0c,qopf=1d562,qprime=2057,qscr=1d4c6,quaternions=210d,quatint=2a16,quest=3f,questeq",
544
+ "=225f,quot=22,rAarr=21db,rArr=21d2,rAtail=291c,rBarr=290f,rHar=2964,race=223d.331,racute=155,radic=2",
545
+ "21a,raemptyv=29b3,rang=27e9,rangd=2992,range=29a5,rangle=27e9,raquo=bb,rarr=2192,rarrap=2975,rarrb=2",
546
+ "1e5,rarrbfs=2920,rarrc=2933,rarrfs=291e,rarrhk=21aa,rarrlp=21ac,rarrpl=2945,rarrsim=2974,rarrtl=21a3",
547
+ ",rarrw=219d,ratail=291a,ratio=2236,rationals=211a,rbarr=290d,rbbrk=2773,rbrace=7d,rbrack=5d,rbrke=29",
548
+ "8c,rbrksld=298e,rbrkslu=2990,rcaron=159,rcedil=157,rceil=2309,rcub=7d,rcy=440,rdca=2937,rdldhar=2969",
549
+ ",rdquo=201d,rdquor=201d,rdsh=21b3,real=211c,realine=211b,realpart=211c,reals=211d,rect=25ad,reg=ae,r",
550
+ "fisht=297d,rfloor=230b,rfr=1d52f,rhard=21c1,rharu=21c0,rharul=296c,rho=3c1,rhov=3f1,rightarrow=2192,",
551
+ "rightarrowtail=21a3,rightharpoondown=21c1,rightharpoonup=21c0,rightleftarrows=21c4,rightleftharpoons",
552
+ "=21cc,rightrightarrows=21c9,rightsquigarrow=219d,rightthreetimes=22cc,ring=2da,risingdotseq=2253,rla",
553
+ "rr=21c4,rlhar=21cc,rlm=200f,rmoust=23b1,rmoustache=23b1,rnmid=2aee,roang=27ed,roarr=21fe,robrk=27e7,",
554
+ "ropar=2986,ropf=1d563,roplus=2a2e,rotimes=2a35,rpar=29,rpargt=2994,rppolint=2a12,rrarr=21c9,rsaquo=2",
555
+ "03a,rscr=1d4c7,rsh=21b1,rsqb=5d,rsquo=2019,rsquor=2019,rthree=22cc,rtimes=22ca,rtri=25b9,rtrie=22b5,",
556
+ "rtrif=25b8,rtriltri=29ce,ruluhar=2968,rx=211e,sacute=15b,sbquo=201a,sc=227b,scE=2ab4,scap=2ab8,scaro",
557
+ "n=161,sccue=227d,sce=2ab0,scedil=15f,scirc=15d,scnE=2ab6,scnap=2aba,scnsim=22e9,scpolint=2a13,scsim=",
558
+ "227f,scy=441,sdot=22c5,sdotb=22a1,sdote=2a66,seArr=21d8,searhk=2925,searr=2198,searrow=2198,sect=a7,",
559
+ "semi=3b,seswar=2929,setminus=2216,setmn=2216,sext=2736,sfr=1d530,sfrown=2322,sharp=266f,shchcy=449,s",
560
+ "hcy=448,shortmid=2223,shortparallel=2225,shy=ad,sigma=3c3,sigmaf=3c2,sigmav=3c2,sim=223c,simdot=2a6a",
561
+ ",sime=2243,simeq=2243,simg=2a9e,simgE=2aa0,siml=2a9d,simlE=2a9f,simne=2246,simplus=2a24,simrarr=2972",
562
+ ",slarr=2190,smallsetminus=2216,smashp=2a33,smeparsl=29e4,smid=2223,smile=2323,smt=2aaa,smte=2aac,smt",
563
+ "es=2aac.fe00,softcy=44c,sol=2f,solb=29c4,solbar=233f,sopf=1d564,spades=2660,spadesuit=2660,spar=2225",
564
+ ",sqcap=2293,sqcaps=2293.fe00,sqcup=2294,sqcups=2294.fe00,sqsub=228f,sqsube=2291,sqsubset=228f,sqsubs",
565
+ "eteq=2291,sqsup=2290,sqsupe=2292,sqsupset=2290,sqsupseteq=2292,squ=25a1,square=25a1,squarf=25aa,squf",
566
+ "=25aa,srarr=2192,sscr=1d4c8,ssetmn=2216,ssmile=2323,sstarf=22c6,star=2606,starf=2605,straightepsilon",
567
+ "=3f5,straightphi=3d5,strns=af,sub=2282,subE=2ac5,subdot=2abd,sube=2286,subedot=2ac3,submult=2ac1,sub",
568
+ "nE=2acb,subne=228a,subplus=2abf,subrarr=2979,subset=2282,subseteq=2286,subseteqq=2ac5,subsetneq=228a",
569
+ ",subsetneqq=2acb,subsim=2ac7,subsub=2ad5,subsup=2ad3,succ=227b,succapprox=2ab8,succcurlyeq=227d,succ",
570
+ "eq=2ab0,succnapprox=2aba,succneqq=2ab6,succnsim=22e9,succsim=227f,sum=2211,sung=266a,sup=2283,sup1=b",
571
+ "9,sup2=b2,sup3=b3,supE=2ac6,supdot=2abe,supdsub=2ad8,supe=2287,supedot=2ac4,suphsol=27c9,suphsub=2ad",
572
+ "7,suplarr=297b,supmult=2ac2,supnE=2acc,supne=228b,supplus=2ac0,supset=2283,supseteq=2287,supseteqq=2",
573
+ "ac6,supsetneq=228b,supsetneqq=2acc,supsim=2ac8,supsub=2ad4,supsup=2ad6,swArr=21d9,swarhk=2926,swarr=",
574
+ "2199,swarrow=2199,swnwar=292a,szlig=df,target=2316,tau=3c4,tbrk=23b4,tcaron=165,tcedil=163,tcy=442,t",
575
+ "dot=20db,telrec=2315,tfr=1d531,there4=2234,therefore=2234,theta=3b8,thetasym=3d1,thetav=3d1,thickapp",
576
+ "rox=2248,thicksim=223c,thinsp=2009,thkap=2248,thksim=223c,thorn=fe,tilde=2dc,times=d7,timesb=22a0,ti",
577
+ "mesbar=2a31,timesd=2a30,tint=222d,toea=2928,top=22a4,topbot=2336,topcir=2af1,topf=1d565,topfork=2ada",
578
+ ",tosa=2929,tprime=2034,trade=2122,triangle=25b5,triangledown=25bf,triangleleft=25c3,trianglelefteq=2",
579
+ "2b4,triangleq=225c,triangleright=25b9,trianglerighteq=22b5,tridot=25ec,trie=225c,triminus=2a3a,tripl",
580
+ "us=2a39,trisb=29cd,tritime=2a3b,trpezium=23e2,tscr=1d4c9,tscy=446,tshcy=45b,tstrok=167,twixt=226c,tw",
581
+ "oheadleftarrow=219e,twoheadrightarrow=21a0,uArr=21d1,uHar=2963,uacute=fa,uarr=2191,ubrcy=45e,ubreve=",
582
+ "16d,ucirc=fb,ucy=443,udarr=21c5,udblac=171,udhar=296e,ufisht=297e,ufr=1d532,ugrave=f9,uharl=21bf,uha",
583
+ "rr=21be,uhblk=2580,ulcorn=231c,ulcorner=231c,ulcrop=230f,ultri=25f8,umacr=16b,uml=a8,uogon=173,uopf=",
584
+ "1d566,uparrow=2191,updownarrow=2195,upharpoonleft=21bf,upharpoonright=21be,uplus=228e,upsi=3c5,upsih",
585
+ "=3d2,upsilon=3c5,upuparrows=21c8,urcorn=231d,urcorner=231d,urcrop=230e,uring=16f,urtri=25f9,uscr=1d4",
586
+ "ca,utdot=22f0,utilde=169,utri=25b5,utrif=25b4,uuarr=21c8,uuml=fc,uwangle=29a7,vArr=21d5,vBar=2ae8,vB",
587
+ "arv=2ae9,vDash=22a8,vangrt=299c,varepsilon=3f5,varkappa=3f0,varnothing=2205,varphi=3d5,varpi=3d6,var",
588
+ "propto=221d,varr=2195,varrho=3f1,varsigma=3c2,varsubsetneq=228a.fe00,varsubsetneqq=2acb.fe00,varsups",
589
+ "etneq=228b.fe00,varsupsetneqq=2acc.fe00,vartheta=3d1,vartriangleleft=22b2,vartriangleright=22b3,vcy=",
590
+ "432,vdash=22a2,vee=2228,veebar=22bb,veeeq=225a,vellip=22ee,verbar=7c,vert=7c,vfr=1d533,vltri=22b2,vn",
591
+ "sub=2282.20d2,vnsup=2283.20d2,vopf=1d567,vprop=221d,vrtri=22b3,vscr=1d4cb,vsubnE=2acb.fe00,vsubne=22",
592
+ "8a.fe00,vsupnE=2acc.fe00,vsupne=228b.fe00,vzigzag=299a,wcirc=175,wedbar=2a5f,wedge=2227,wedgeq=2259,",
593
+ "weierp=2118,wfr=1d534,wopf=1d568,wp=2118,wr=2240,wreath=2240,wscr=1d4cc,xcap=22c2,xcirc=25ef,xcup=22",
594
+ "c3,xdtri=25bd,xfr=1d535,xhArr=27fa,xharr=27f7,xi=3be,xlArr=27f8,xlarr=27f5,xmap=27fc,xnis=22fb,xodot",
595
+ "=2a00,xopf=1d569,xoplus=2a01,xotime=2a02,xrArr=27f9,xrarr=27f6,xscr=1d4cd,xsqcup=2a06,xuplus=2a04,xu",
596
+ "tri=25b3,xvee=22c1,xwedge=22c0,yacute=fd,yacy=44f,ycirc=177,ycy=44b,yen=a5,yfr=1d536,yicy=457,yopf=1",
597
+ "d56a,yscr=1d4ce,yucy=44e,yuml=ff,zacute=17a,zcaron=17e,zcy=437,zdot=17c,zeetrf=2128,zeta=3b6,zfr=1d5",
598
+ "37,zhcy=436,zigrarr=21dd,zopf=1d56b,zscr=1d4cf,zwj=200d,zwnj=200c"
599
+ ].join("");
600
+ var NAMED_REFERENCES = new Map(NAMED.split(",").map((entry) => {
601
+ const [name, codes] = entry.split("=");
602
+ return [name, String.fromCodePoint(...codes.split(".").map((code) => Number.parseInt(code, 16)))];
603
+ }));
604
+
605
+ // src/html.js
606
+ 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(" ");
607
+ var LEGACY = /* @__PURE__ */ new Set([...LATIN1, "amp", "lt", "gt", "quot", "AMP", "LT", "GT", "QUOT", "COPY", "REG"]);
608
+ var LEGACY_LONGEST = Math.max(...[...LEGACY].map((name) => name.length));
609
+ var UNSHOWN = /* @__PURE__ */ new Set(["script", "style", "title", "noembed", "noframes", "iframe"]);
610
+ var RAW_SHOWN = /* @__PURE__ */ new Set(["textarea", "xmp"]);
611
+ var RAW_END = Object.fromEntries([...UNSHOWN, ...RAW_SHOWN].map((name) => [name, linear(String.raw`<\/${caseless(name)}[\s/>]`, "g")]));
612
+ var CLOSES_PARAGRAPH = /* @__PURE__ */ new Set(["address", "article", "aside", "blockquote", "center", "dd", "details", "dialog", "dir", "div", "dl", "dt", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "header", "hgroup", "hr", "li", "listing", "main", "menu", "nav", "ol", "p", "plaintext", "pre", "search", "section", "summary", "table", "ul", "xmp"]);
613
+ var PARTS_OF_TABLE = /* @__PURE__ */ new Set(["caption", "col", "colgroup", "tbody", "td", "tfoot", "th", "thead", "tr"]);
614
+ var TABLE_STRUCTURE = [...PARTS_OF_TABLE, "table", "template"];
615
+ var NOT_REOPENING = /* @__PURE__ */ new Set([...CLOSES_PARAGRAPH, "base", "basefont", "bgsound", "body", "caption", "col", "colgroup", "frame", "frameset", "head", "html", "iframe", "link", "meta", "noembed", "noframes", "script", "style", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "title", "tr"]);
616
+ var COMMENT_END = linear("--!?>", "g");
617
+ var LABEL_END = linear(String.raw`<\/${caseless("label")}[\s/>]`);
618
+ var UNITS = {
619
+ px: 1,
620
+ pt: 4 / 3,
621
+ pc: 16,
622
+ in: 96,
623
+ cm: 96 / 2.54,
624
+ mm: 96 / 25.4,
625
+ q: 96 / 101.6,
626
+ rem: 16
627
+ };
628
+
629
+ // src/tokenizer.js
630
+ function characterClass(ranges, flags = "gu") {
631
+ const hex = (code) => `\\u{${code.toString(16)}}`;
632
+ return new RegExp(`[${ranges.map(([first, last]) => last ? `${hex(first)}-${hex(last)}` : hex(first)).join("")}]`, flags);
633
+ }
634
+ var INVISIBLE = [[173], [847], [4447, 4448], [6068, 6069], [6158], [8203], [8206, 8207], [8234, 8238], [8288, 8292], [8294, 8297], [12644], [65279], [65440]];
635
+ var OBFUSCATING = characterClass(INVISIBLE);
636
+ var JOINERS = characterClass([[8204, 8205], [65024, 65039]]);
637
+ var INVISIBLE_OR_JOINER = characterClass([...INVISIBLE, [8204, 8205]]);
638
+ var LATIN_END = new RegExp("\\p{Script=Latin}$", "u");
639
+ var LATIN_START = new RegExp("^\\p{Script=Latin}", "u");
640
+ var ZWSP_SCRIPTS = String.raw`\p{Script=Thai}\p{Script=Lao}\p{Script=Khmer}\p{Script=Myanmar}\p{Script=Tibetan}`;
641
+ var ZWSP_SCRIPT_END = new RegExp(`[${ZWSP_SCRIPTS}]$`, "u");
642
+ var ZWSP_SCRIPT_START = new RegExp(`^[${ZWSP_SCRIPTS}]`, "u");
643
+ var BIDI = characterClass([[8206, 8207], [8234, 8236], [8294, 8297]], "u");
644
+ var DIGIT_END = new RegExp("\\p{N}$", "u");
645
+ var DIGIT_START = new RegExp("^\\p{N}", "u");
646
+ var STYLED_LETTERS = characterClass([[119808, 120831], [127280, 127305]], "u");
647
+ var WIDE_LETTERS = characterClass([[9312, 9471], [65313, 65338], [65345, 65370]], "u");
648
+ var LOOKALIKES = {
649
+ \u0430: "a",
650
+ \u0432: "b",
651
+ \u0435: "e",
652
+ \u0451: "e",
653
+ \u043A: "k",
654
+ \u043C: "m",
655
+ \u043D: "h",
656
+ \u043E: "o",
657
+ \u0440: "p",
658
+ \u0441: "c",
659
+ \u0442: "t",
660
+ \u0443: "y",
661
+ \u0445: "x",
662
+ \u0455: "s",
663
+ \u0456: "i",
664
+ \u0457: "i",
665
+ \u0458: "j",
666
+ "\u0501": "d",
667
+ "\u051B": "q",
668
+ "\u051D": "w",
669
+ \u04BB: "h",
670
+ "\u04CF": "l",
671
+ \u0261: "g",
672
+ \u044C: "b",
673
+ \u043F: "n",
674
+ \u0433: "r",
675
+ \u03B1: "a",
676
+ \u03B2: "b",
677
+ \u03B5: "e",
678
+ \u03B7: "n",
679
+ \u03B9: "i",
680
+ \u03BA: "k",
681
+ \u03BD: "v",
682
+ \u03BF: "o",
683
+ \u03C1: "p",
684
+ \u03C4: "t",
685
+ \u03C5: "u",
686
+ \u03C7: "x",
687
+ \u03C9: "w",
688
+ \u03B3: "y",
689
+ \u03BC: "u"
690
+ };
691
+ var LEET_DIGITS = new RegExp("\\p{L}[0134578]{1,2}\\p{L}", "u");
692
+ var URL_PATTERN = linear(String.raw`\b(?:https?:\/\/|www\.)[^\s<>"'\x60]+|\b[a-z\d][a-z\d-]{0,62}(?:\.[a-z\d-]{1,63}){0,10}\.[a-z]{2,24}\/[^\s<>"'\x60]*`, "giu");
693
+ var EMAIL_SOURCE = String.raw`[\p{L}\p{N}._%+-]{1,64}@([\p{L}\p{N}-]{1,63}(?:\.[\p{L}\p{N}-]{1,63}){0,10}\.\p{L}{2,24})`;
694
+ var EMAIL_PATTERN = linear(EMAIL_SOURCE, "gu");
695
+ var PHONE_PATTERN = linear(String.raw`(?:\+|0{2})\d[\d\s().-]{7,}\d|\(\d{3}\)\s?\d{3}[\s.-]\d{4}|\b(?:\d{3}[.-]){2}\d{4}\b`, "g");
696
+ var IP_PATTERN = linear(String.raw`\b(?:25[0-5]|2[0-4]\d|1?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|1?\d?\d)){3}\b`, "g");
697
+ var MONEY_PATTERN = linear(String.raw`[$€£¥₹₽₩₺₦]\s?\d|\d\s?(?:[$€£¥₹₽₩₺₦]|usd|eur|gbp|dollars?|euros?)\b`, "giu");
698
+ var BITCOIN_PATTERN = linear(String.raw`\b(?:bc1[ac-hj-np-z02-9]{25,60}|[13][a-km-zA-HJ-NP-Z1-9]{25,34})\b`, "g");
699
+ var CARD_PATTERN = linear(String.raw`\b(?:\d[ -]?){13,19}\b`, "g");
700
+ var ANCHOR_START = linear(String.raw`<a[\t\n\f\r />]`, "gi");
701
+ var SHOWN_URL = linear(String.raw`^(?:https?:\/\/|www\.)\S+$|^[a-z\d-]{1,63}(?:\.[a-z\d-]{1,63}){1,10}(?:\/\S*)?$`, "i");
702
+ var IMG_PIXEL = linear(String.raw`<img\b[^<>]*\b(?:width|height)\s*=\s*["']?[01]["'\s>]`, "i");
703
+ var IMG = linear(String.raw`<img\b`, "gi");
704
+ var BARE_HOST = linear(String.raw`\b[a-z\d][a-z\d-]{0,62}(?:\.[a-z\d-]{1,63}){0,9}\.[a-z]{2,24}\b`, "gi");
705
+ var BRAND_NAMES = new Set(BRANDS);
706
+ var LATIN_LOOKALIKES = { Cyrillic: {}, Greek: {} };
707
+ for (const [char, latin] of Object.entries(LOOKALIKES)) {
708
+ const target = LATIN_LOOKALIKES[scriptOf(char)];
709
+ if (target && !target[latin]) {
710
+ target[latin] = char;
711
+ }
712
+ }
713
+ var LATIN = new RegExp("\\p{Script=Latin}", "u");
714
+ var ADDRESS_SOURCE = String.raw`[\p{L}\p{N}._%+-]{1,64}@([\p{L}\p{N}-]{1,63}(?:\.[\p{L}\p{N}-]{1,63}){1,10})`;
715
+ var NAMED_ADDRESS = linear(ADDRESS_SOURCE, "u");
716
+
717
+ // src/attachments.js
718
+ var EXECUTABLE_EXTENSIONS = /* @__PURE__ */ new Set([
719
+ "ade",
720
+ "adp",
721
+ "apk",
722
+ "app",
723
+ "appimage",
724
+ "appinstaller",
725
+ "application",
726
+ "appref-ms",
727
+ "appx",
728
+ "appxbundle",
729
+ "asp",
730
+ "aspx",
731
+ "asx",
732
+ "bas",
733
+ "bat",
734
+ "bgi",
735
+ "cab",
736
+ "chm",
737
+ "cmd",
738
+ "cnt",
739
+ "com",
740
+ "command",
741
+ "cpl",
742
+ "csh",
743
+ "diagcab",
744
+ "dll",
745
+ "dmg",
746
+ "docm",
747
+ "dotm",
748
+ "elf",
749
+ "exe",
750
+ "fxp",
751
+ "gadget",
752
+ "grp",
753
+ "hlp",
754
+ "hpj",
755
+ "hta",
756
+ "htc",
757
+ "img",
758
+ "inf",
759
+ "ins",
760
+ "ipa",
761
+ "iqy",
762
+ "iso",
763
+ "isp",
764
+ "its",
765
+ "jar",
766
+ "jnlp",
767
+ "js",
768
+ "jse",
769
+ "ksh",
770
+ "library-ms",
771
+ "lnk",
772
+ "mad",
773
+ "maf",
774
+ "mag",
775
+ "mam",
776
+ "maq",
777
+ "mar",
778
+ "mas",
779
+ "mau",
780
+ "mav",
781
+ "maw",
782
+ "mcf",
783
+ "mda",
784
+ "mde",
785
+ "mdt",
786
+ "mdw",
787
+ "mdz",
788
+ "msc",
789
+ "msh",
790
+ "msh1",
791
+ "msh1xml",
792
+ "msh2",
793
+ "msh2xml",
794
+ "mshxml",
795
+ "msi",
796
+ "msix",
797
+ "msixbundle",
798
+ "msp",
799
+ "mst",
800
+ "msu",
801
+ "nsh",
802
+ "one",
803
+ "onepkg",
804
+ "ops",
805
+ "osd",
806
+ "pcd",
807
+ "pif",
808
+ "pkg",
809
+ "pl",
810
+ "plg",
811
+ "potm",
812
+ "ppam",
813
+ "ppsm",
814
+ "pptm",
815
+ "prf",
816
+ "prg",
817
+ "ps1",
818
+ "ps1xml",
819
+ "ps2",
820
+ "ps2xml",
821
+ "psc1",
822
+ "psc2",
823
+ "py",
824
+ "pyc",
825
+ "pyo",
826
+ "pyw",
827
+ "pyz",
828
+ "pyzw",
829
+ "reg",
830
+ "scf",
831
+ "scpt",
832
+ "scr",
833
+ "sct",
834
+ "search-ms",
835
+ "searchconnector-ms",
836
+ "settingcontent-ms",
837
+ "sh",
838
+ "shb",
839
+ "shs",
840
+ "slk",
841
+ "sys",
842
+ "vb",
843
+ "vbe",
844
+ "vbp",
845
+ "vbs",
846
+ "vhd",
847
+ "vhdx",
848
+ "vsmacros",
849
+ "vsw",
850
+ "webpnp",
851
+ "website",
852
+ "ws",
853
+ "wsb",
854
+ "wsc",
855
+ "wsf",
856
+ "wsh",
857
+ "xbap",
858
+ "xlam",
859
+ "xll",
860
+ "xlsm",
861
+ "xltm",
862
+ "xnk"
863
+ ]);
864
+ var RISKY_EXTENSIONS = /* @__PURE__ */ new Set(["cer", "der", "mat", "pst", "theme", "tmp", "url"]);
865
+ var SCRIPT_EXTENSIONS = /* @__PURE__ */ new Set(["asp", "aspx", "csh", "js", "ksh", "pl", "py", "pyc", "pyo", "pyw", "pyz", "pyzw", "sh"]);
866
+ var MACRO_EXTENSIONS = /* @__PURE__ */ new Set(["docm", "dotm", "xlsm", "xltm", "xlam", "pptm", "potm", "ppsm", "ppam", "sldm"]);
867
+ 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"]);
868
+ var TEMPORARY_EXTENSIONS = /* @__PURE__ */ new Set(["tmp"]);
869
+ var BIDI_CONTROLS = characterClass([[8234, 8238], [8294, 8297]], "u");
870
+ var ALL_BIDI_CONTROLS = characterClass([[8234, 8238], [8294, 8297]], "gu");
871
+ var ARCHIVE_TYPES = /* @__PURE__ */ new Set(["zip", "rar", "7z", "gz", "bz2", "xz", "cab", "iso", "tar", "zst", "lzh", "ace", "arj"]);
872
+ function sniff(buffer) {
873
+ if (!import_node_buffer.Buffer.isBuffer(buffer) || buffer.length < 4) {
874
+ return null;
875
+ }
876
+ const at = (offset, bytes) => buffer.length >= offset + bytes.length && bytes.every((byte, i) => buffer[offset + i] === byte);
877
+ const ascii = (offset, text) => at(offset, [...import_node_buffer.Buffer.from(text, "latin1")]);
878
+ const result = (type, executable = false) => ({ type, executable, archive: ARCHIVE_TYPES.has(type) });
879
+ if (ascii(0, "MZ") && buffer.length >= 64 && at(buffer.readUInt32LE(60), [80, 69, 0, 0])) {
880
+ return result("exe", true);
881
+ }
882
+ if (at(0, [127, 69, 76, 70])) {
883
+ return result("elf", true);
884
+ }
885
+ const magic = buffer.readUInt32BE(0);
886
+ if ([4277009102, 4277009103, 3472551422, 3489328638].includes(magic)) {
887
+ return result("macho", true);
888
+ }
889
+ if (magic === 3405691582) {
890
+ return result("macho", true);
891
+ }
892
+ if (at(0, [76, 0, 0, 0, 1, 20, 2, 0])) {
893
+ return result("lnk", true);
894
+ }
895
+ if (at(0, [208, 207, 17, 224, 161, 177, 26, 225])) {
896
+ return result("ole");
897
+ }
898
+ if (at(0, [80, 75, 3, 4]) || at(0, [80, 75, 5, 6])) {
899
+ const names = entriesOf(buffer).map((entry) => entry.name);
900
+ if (names.includes("AndroidManifest.xml") || names.includes("classes.dex")) {
901
+ return result("apk", true);
902
+ }
903
+ if (names.includes("META-INF/MANIFEST.MF") && names.some((name) => name.endsWith(".class"))) {
904
+ return result("jar", true);
905
+ }
906
+ if (names.some((name) => name.startsWith("word/"))) {
907
+ return result("docx");
908
+ }
909
+ if (names.some((name) => name.startsWith("xl/"))) {
910
+ return result("xlsx");
911
+ }
912
+ if (names.some((name) => name.startsWith("ppt/"))) {
913
+ return result("pptx");
914
+ }
915
+ return result("zip");
916
+ }
917
+ if (ascii(0, "Rar!")) {
918
+ return result("rar");
919
+ }
920
+ if (at(0, [55, 122, 188, 175, 39, 28])) {
921
+ return result("7z");
922
+ }
923
+ if (at(0, [31, 139])) {
924
+ return result("gz");
925
+ }
926
+ if (ascii(0, "MSCF")) {
927
+ return result("cab");
928
+ }
929
+ if (ascii(32769, "CD001") || ascii(34817, "CD001") || ascii(36865, "CD001")) {
930
+ return result("iso");
931
+ }
932
+ if (ascii(0, "conectix") || ascii(0, "vhdxfile")) {
933
+ return result("vhd", true);
934
+ }
935
+ if (ascii(0, "%PDF")) {
936
+ return result("pdf");
937
+ }
938
+ if (ascii(0, String.raw`{\rt`)) {
939
+ return result("rtf");
940
+ }
941
+ if (at(0, [137, 80, 78, 71])) {
942
+ return result("png");
943
+ }
944
+ if (at(0, [255, 216, 255])) {
945
+ return result("jpg");
946
+ }
947
+ if (ascii(0, "GIF8")) {
948
+ return result("gif");
949
+ }
950
+ if (ascii(0, "RIFF") && ascii(8, "WEBP")) {
951
+ return result("webp");
952
+ }
953
+ if (ascii(0, "#!")) {
954
+ return result("script", true);
955
+ }
956
+ const head = buffer.subarray(0, 1024).toString("utf8").replace(/^\uFEFF/u, "").trimStart().toLowerCase();
957
+ if (head.startsWith("<svg") || head.startsWith("<?xml") && head.includes("<svg")) {
958
+ return result("svg");
959
+ }
960
+ if (head.startsWith("<!doctype html") || head.startsWith("<html") || head.startsWith("<head") || head.startsWith("<script")) {
961
+ return result("html");
962
+ }
963
+ return null;
964
+ }
965
+ var ZIP_FAMILY = /* @__PURE__ */ new Set(["zip", "docx", "xlsx", "pptx"]);
966
+ var OFFICE_TYPES = /* @__PURE__ */ new Set(["docx", "xlsx", "pptx"]);
967
+ var OFFICE_EMBEDDED = MACRO_EXTENSIONS;
968
+ var ENTRIES = /* @__PURE__ */ new WeakMap();
969
+ function entriesOf(buffer) {
970
+ let entries = ENTRIES.get(buffer);
971
+ if (!entries) {
972
+ entries = zipEntries(buffer);
973
+ ENTRIES.set(buffer, entries);
974
+ }
975
+ return entries;
976
+ }
977
+ function zipEntries(buffer, limit = 2e3) {
978
+ const start = Math.max(0, buffer.length - 65557);
979
+ const records = [];
980
+ for (let i = buffer.length - 22; i >= start; i--) {
981
+ if (buffer.readUInt32LE(i) === 101010256 && (records.length === 0 || i + 22 + buffer.readUInt16LE(i + 20) === buffer.length)) {
982
+ records.push(i);
983
+ }
984
+ }
985
+ const state = {
986
+ entries: [],
987
+ limit,
988
+ read: /* @__PURE__ */ new Set(),
989
+ names: MAX_NAME_BYTES
990
+ };
991
+ for (const eocd of records) {
992
+ const offset = directoryOf(buffer, eocd);
993
+ if (offset !== -1) {
994
+ readDirectory(buffer, offset, state);
995
+ }
996
+ }
997
+ return state.entries;
998
+ }
999
+ var MAX_NAME_LENGTH = 1024;
1000
+ var MAX_NAME_BYTES = 1024 * 1024;
1001
+ var DIRECTORY = 33639248;
1002
+ var isDirectory = (buffer, offset) => offset >= 0 && offset + 46 <= buffer.length && buffer.readUInt32LE(offset) === DIRECTORY;
1003
+ function directoryOf(buffer, eocd) {
1004
+ let offset = buffer.readUInt32LE(eocd + 16);
1005
+ let size = buffer.readUInt32LE(eocd + 12);
1006
+ const locator = eocd - 20;
1007
+ if ((offset === 4294967295 || size === 4294967295) && locator >= 0 && buffer.readUInt32LE(locator) === 117853008) {
1008
+ const stated = Number(buffer.readBigUInt64LE(locator + 8));
1009
+ const isRecord = (at) => at >= 0 && at + 56 <= locator && buffer.readUInt32LE(at) === 101075792;
1010
+ const record = isRecord(stated) ? stated : locator - 56;
1011
+ if (isRecord(record)) {
1012
+ size = Number(buffer.readBigUInt64LE(record + 40));
1013
+ offset = Number(buffer.readBigUInt64LE(record + 48));
1014
+ }
1015
+ }
1016
+ if (isDirectory(buffer, offset)) {
1017
+ return offset;
1018
+ }
1019
+ for (const end of [eocd, locator - 56]) {
1020
+ const directory = end - size;
1021
+ if (directory < end && isDirectory(buffer, directory)) {
1022
+ return directory;
1023
+ }
1024
+ }
1025
+ return -1;
1026
+ }
1027
+ function readDirectory(buffer, offset, state) {
1028
+ while (state.entries.length < state.limit && isDirectory(buffer, offset) && !state.read.has(offset)) {
1029
+ state.read.add(offset);
1030
+ const flags = buffer.readUInt16LE(offset + 8);
1031
+ const size = buffer.readUInt32LE(offset + 24);
1032
+ const nameLength = buffer.readUInt16LE(offset + 28);
1033
+ const extraLength = buffer.readUInt16LE(offset + 30);
1034
+ const commentLength = buffer.readUInt16LE(offset + 32);
1035
+ const encoding = flags & 2048 ? "utf8" : "latin1";
1036
+ const start = offset + 46;
1037
+ const end = Math.min(buffer.length, start + nameLength);
1038
+ const kept = Math.min(end - start, MAX_NAME_LENGTH);
1039
+ state.names -= kept;
1040
+ if (state.names < 0) {
1041
+ return;
1042
+ }
1043
+ const half = MAX_NAME_LENGTH / 2;
1044
+ const name = end - start > MAX_NAME_LENGTH ? `${buffer.toString(encoding, start, start + half)}\u2026${buffer.toString(encoding, end - half, end)}` : buffer.toString(encoding, start, end);
1045
+ state.entries.push({ name, encrypted: (flags & 1) === 1, size });
1046
+ offset += 46 + nameLength + extraLength + commentLength;
1047
+ }
1048
+ }
1049
+ function shorten(name, max = 100) {
1050
+ const characters = [...name];
1051
+ return characters.length <= max ? name : `${characters.slice(0, max - 41).join("")}\u2026${characters.slice(-40).join("")}`;
1052
+ }
1053
+ function extensionOf(name) {
1054
+ const base = trimEndOf(String(name).toLowerCase().replace(ALL_BIDI_CONTROLS, "").split(/[/\\]/).pop(), ". ");
1055
+ const whole = lastExtension(base);
1056
+ const file = base.replace(/^[a-z]:/, "");
1057
+ const colon = file.indexOf(":");
1058
+ if (colon !== -1 && /^(?::?\$data)?$/.test(file.slice(colon + 1))) {
1059
+ return lastExtension(trimEndOf(file.slice(0, colon), ". "));
1060
+ }
1061
+ return whole;
1062
+ }
1063
+ var COMPRESSED_EXTENSIONS = /* @__PURE__ */ new Set(["gz", "bz2", "xz", "zst"]);
1064
+ function uncompressedName(name) {
1065
+ if (!COMPRESSED_EXTENSIONS.has(extensionOf(name))) {
1066
+ return String(name);
1067
+ }
1068
+ const trimmed = trimEndOf(String(name).replace(ALL_BIDI_CONTROLS, ""), ". ");
1069
+ return trimmed.slice(0, trimmed.lastIndexOf("."));
1070
+ }
1071
+ function lastExtension(base) {
1072
+ const dot = base.lastIndexOf(".");
1073
+ return dot === -1 ? "" : base.slice(dot + 1).trim();
1074
+ }
1075
+ var VBA_NAMES = /* @__PURE__ */ new Set(["vba", "_vba_project", "_vba_project_cur", "macros"]);
1076
+ function oleHasMacros(buffer) {
1077
+ for (let offset = 512; offset + 128 <= buffer.length; offset += 128) {
1078
+ const length = buffer.readUInt16LE(offset + 64);
1079
+ const type = buffer[offset + 66];
1080
+ if ((type === 1 || type === 2) && length >= 4 && length <= 64 && length % 2 === 0 && VBA_NAMES.has(buffer.subarray(offset, offset + length - 2).toString("utf16le").toLowerCase())) {
1081
+ return true;
1082
+ }
1083
+ }
1084
+ return false;
1085
+ }
1086
+ var PDF_ACTIVE = linear(String.raw`\/(?:JavaScript|JS|Launch)\b`);
1087
+ var escaped = (character) => {
1088
+ const hex = character.codePointAt(0).toString(16);
1089
+ return `(?:${character}|#${hex[0]}[${hex[1].toLowerCase()}${hex[1].toUpperCase()}])`;
1090
+ };
1091
+ var WORD_ESCAPE = String.raw`#(?:3\d|4[1-9a-fA-F]|5[\daA]|5[fF]|6[1-9a-fA-F]|7[\daA])`;
1092
+ var PDF_ACTIVE_ESCAPED = new RegExp(`/(?:${["JavaScript", "JS", "Launch"].map((name) => [...name].map((character) => escaped(character)).join("")).join("|")})(?![\\w]|${WORD_ESCAPE})`);
1093
+ var pdfActive = (text) => PDF_ACTIVE.test(text) || PDF_ACTIVE_ESCAPED.test(text);
1094
+ function inspectAttachments(attachments = []) {
1095
+ const findings = [];
1096
+ for (const attachment of attachments) {
1097
+ const filename = typeof attachment.filename === "string" ? attachment.filename : "";
1098
+ const name = filename || "unnamed attachment";
1099
+ const content = import_node_buffer.Buffer.isBuffer(attachment.content) ? attachment.content : null;
1100
+ const extension = extensionOf(filename);
1101
+ const detected = content ? sniff(content) : null;
1102
+ const add = (type, message, extra = {}) => findings.push({
1103
+ type,
1104
+ filename: name,
1105
+ message,
1106
+ ...extra
1107
+ });
1108
+ if (BIDI_CONTROLS.test(filename)) {
1109
+ add("rtl_override", `Attachment "${name}" uses a right-to-left override to hide its real extension`);
1110
+ }
1111
+ const parts = trimEndOf(filename.toLowerCase(), ". ").split(".");
1112
+ if (parts.length >= 3 && (EXECUTABLE_EXTENSIONS.has(extension) || RISKY_EXTENSIONS.has(extension)) && !TEMPORARY_EXTENSIONS.has(extension) && DOCUMENT_EXTENSIONS.has(parts.at(-2).trim())) {
1113
+ add("double_extension", `Attachment "${name}" has a document extension followed by a program extension`, { extension });
1114
+ }
1115
+ const byName = EXECUTABLE_EXTENSIONS.has(extension) && !MACRO_EXTENSIONS.has(extension);
1116
+ if (detected?.executable && (detected.type !== "script" || !byName)) {
1117
+ add(extension && !EXECUTABLE_EXTENSIONS.has(extension) ? "disguised_executable" : "executable", `Attachment "${name}" contains a program (${detected.type})${extension && extension !== detected.type ? ` but is named .${extension}` : ""}`, { extension: detected.type });
1118
+ } else if (byName) {
1119
+ add("executable", `Attachment "${name}" is a file type that runs code (.${extension})`, { extension });
1120
+ } else if (RISKY_EXTENSIONS.has(extension)) {
1121
+ add("risky_attachment", `Attachment "${name}" is a risky file type (.${extension})`, { extension });
1122
+ }
1123
+ const held = COMPRESSED_EXTENSIONS.has(extension) ? extensionOf(uncompressedName(filename)) : "";
1124
+ if (EXECUTABLE_EXTENSIONS.has(held)) {
1125
+ const script = SCRIPT_EXTENSIONS.has(held);
1126
+ add(script ? "script_in_archive" : "executable_in_archive", `Archive "${name}" contains ${script ? "a script" : "a program"} (${shorten(uncompressedName(filename).split(/[/\\]/).pop())})`, { extension: held, extensions: [held] });
1127
+ }
1128
+ const webPage = detected?.type === "html" || detected?.type === "svg" || ["htm", "html", "mht", "mhtml", "shtml", "xht", "xhtml", "svg"].includes(extension);
1129
+ const addWebPage = () => {
1130
+ const active = content !== null && /<script\b|<form\b|\bon(?:load|error|click)\s*=|javascript:|window\.location|document\.location|atob\(/i.test(content.subarray(0, 2e5).toString("utf8"));
1131
+ add("html_attachment", `Attachment "${name}" is ${detected?.type === "svg" || extension === "svg" ? "an SVG image" : "a web page"}${active ? " with scripts or forms" : ""}`, { extension: extension || detected?.type, active });
1132
+ };
1133
+ if (!content) {
1134
+ if (webPage) {
1135
+ addWebPage();
1136
+ }
1137
+ continue;
1138
+ }
1139
+ const zipFamily = ZIP_FAMILY.has(detected?.type) || extension === "zip" && !detected?.executable && entriesOf(content).length > 0;
1140
+ if (zipFamily) {
1141
+ const entries = entriesOf(content);
1142
+ const office = OFFICE_TYPES.has(detected?.type);
1143
+ if (entries.some((entry) => /(?:^|\/)vbaproject\.bin$/i.test(entry.name))) {
1144
+ add("macro", `Attachment "${name}" is an Office document with a VBA macro project`, { extension });
1145
+ } else if (office && entries.some((entry) => MACRO_EXTENSIONS.has(extensionOf(entry.name)))) {
1146
+ add("macro", `Attachment "${name}" is an Office document holding another with macros`, { extension });
1147
+ }
1148
+ const inner = entries.filter((entry) => EXECUTABLE_EXTENSIONS.has(extensionOf(uncompressedName(entry.name))) && !(office && OFFICE_EMBEDDED.has(extensionOf(entry.name))));
1149
+ const details = { extension: extensionOf(uncompressedName(inner[0]?.name ?? "")), extensions: [...new Set(inner.map((entry) => extensionOf(uncompressedName(entry.name))))] };
1150
+ const listed = inner.slice(0, 3).map((entry) => shorten(entry.name.split("/").pop())).join(", ");
1151
+ if (inner.some((entry) => !SCRIPT_EXTENSIONS.has(extensionOf(uncompressedName(entry.name))))) {
1152
+ add("executable_in_archive", `Archive "${name}" contains ${inner.length === 1 ? "a program" : `${inner.length} programs`} (${listed})`, details);
1153
+ } else if (inner.length > 0) {
1154
+ add("script_in_archive", `Archive "${name}" contains ${inner.length === 1 ? "a script" : `${inner.length} scripts`} (${listed})`, details);
1155
+ }
1156
+ if ((detected?.type === "zip" || !ZIP_FAMILY.has(detected?.type)) && entries.some((entry) => entry.encrypted)) {
1157
+ add("encrypted_archive", `Archive "${name}" is password protected, so its contents cannot be scanned`, { extension });
1158
+ }
1159
+ } else if (detected?.type === "ole") {
1160
+ if (oleHasMacros(content)) {
1161
+ add("macro", `Attachment "${name}" is an Office document with a VBA macro project`, { extension });
1162
+ }
1163
+ } else if (detected?.type === "pdf" || extension === "pdf") {
1164
+ if (pdfActive(content.toString("latin1"))) {
1165
+ add("pdf_active", `PDF "${name}" contains JavaScript or a launch action`, { extension: "pdf" });
1166
+ }
1167
+ } else if (detected?.type === "rtf" && /\\object\b|\\objdata\b|\\objupdate\b/.test(content.toString("latin1"))) {
1168
+ add("rtf_object", `RTF document "${name}" embeds an OLE object`, { extension: "rtf" });
1169
+ }
1170
+ if (webPage) {
1171
+ addWebPage();
1172
+ }
1173
+ }
1174
+ return findings;
1175
+ }
1176
+
1177
+ // src/parse.js
43
1178
  var ADDRESS_FIELDS = /* @__PURE__ */ new Set(["from", "to", "cc", "bcc", "sender", "reply-to", "delivered-to", "return-path", "disposition-notification-to"]);
44
1179
  var MAX_ADDRESS_FIELD = 16 * 1024;
45
1180
  var MAX_ADDRESS_SEPARATORS = 2e3;
@@ -48,21 +1183,21 @@ var MAX_ADDRESS_TOTAL = 64 * 1024;
48
1183
  var ADDRESS_OPERATORS = /* @__PURE__ */ new Map([['"', '"'], ["(", ")"], ["<", ">"], [",", ""], [":", ";"], [";", ""]]);
49
1184
  var SINGLE_FIELDS = /* @__PURE__ */ new Set(["message-id", "content-id", "from", "sender", "in-reply-to", "reply-to", "subject", "date", "content-disposition", "content-type", "content-transfer-encoding", "priority", "mime-version", "content-description", "precedence", "errors-to", "disposition-notification-to"]);
50
1185
  var PRIORITY_FIELDS = /* @__PURE__ */ new Set(["priority", "x-priority", "x-msmail-priority", "importance"]);
51
- var BOUNDED = /* @__PURE__ */ Symbol("bounded address fields");
1186
+ var BOUNDED2 = /* @__PURE__ */ Symbol("bounded address fields");
52
1187
  var ROOM = /* @__PURE__ */ Symbol("room left for address fields");
53
1188
  var PARSER_OPTIONS = {
54
1189
  skipHtmlToText: true,
55
1190
  skipImageLinks: true,
56
1191
  skipTextToHtml: true,
57
1192
  skipTextLinks: true,
58
- [BOUNDED]: true
1193
+ [BOUNDED2]: true
59
1194
  };
60
1195
  function boundAddressField(line, room) {
61
1196
  const start = line.indexOf(":") + 1;
62
1197
  const limit = Math.min(line.length, MAX_ADDRESS_FIELD, room);
63
1198
  let end = start;
64
1199
  let expecting = "";
65
- let escaped = false;
1200
+ let escaped2 = false;
66
1201
  let separators = 0;
67
1202
  let groups = 0;
68
1203
  let index = start;
@@ -71,8 +1206,8 @@ function boundAddressField(line, room) {
71
1206
  if ((chr === "," || chr === ";") && ++separators > MAX_ADDRESS_SEPARATORS) {
72
1207
  break;
73
1208
  }
74
- if (escaped) {
75
- escaped = false;
1209
+ if (escaped2) {
1210
+ escaped2 = false;
76
1211
  } else if (expecting !== "" && chr === expecting) {
77
1212
  expecting = "";
78
1213
  end = chr === ";" ? index + 1 : end;
@@ -80,7 +1215,7 @@ function boundAddressField(line, room) {
80
1215
  expecting = ADDRESS_OPERATORS.get(chr);
81
1216
  end = chr === "," || chr === ";" ? index : end;
82
1217
  } else if (expecting === '"' && chr === "\\") {
83
- escaped = true;
1218
+ escaped2 = true;
84
1219
  }
85
1220
  if (chr === ":" && expecting === ";" && ++groups > MAX_ADDRESS_GROUPS) {
86
1221
  break;
@@ -106,7 +1241,7 @@ function boundAddressLines(lines, budget, only = null) {
106
1241
  }
107
1242
  var { processHeaders } = import_mailparser.MailParser.prototype;
108
1243
  import_mailparser.MailParser.prototype.processHeaders = function(lines) {
109
- if (!this.options[BOUNDED]) {
1244
+ if (!this.options[BOUNDED2]) {
110
1245
  return processHeaders.call(this, lines);
111
1246
  }
112
1247
  this[ROOM] ??= { room: MAX_ADDRESS_TOTAL };
@@ -152,18 +1287,103 @@ var KEPT_FIELDS = /* @__PURE__ */ new Set([
152
1287
  var AUTH_FIELDS = /* @__PURE__ */ new Set([...KEPT_FIELDS, "arc-seal", "arc-message-signature"]);
153
1288
  var MAX_NESTED_BYTES = 25 * 1024 * 1024;
154
1289
  var PARSE_TIMEOUT = 6e4;
1290
+ var NAMED_TEXT = /* @__PURE__ */ Symbol("named text parts");
1291
+ var ENCODED_FILES = /^(?:begin [0-7]{3,4} |=ybegin\b[^\r\n\u2028\u2029]*?\bname=)([^\r\n\u2028\u2029]+)\r?$/gm;
1292
+ var MAX_ENCODED_FILES = 1e3;
1293
+ var foundIn = /* @__PURE__ */ new WeakMap();
1294
+ function addFinding(list, part) {
1295
+ const found = foundIn.get(list) ?? /* @__PURE__ */ new Set();
1296
+ foundIn.set(list, found);
1297
+ const types = inspectAttachments([part]).map((finding) => finding.type);
1298
+ if (types.some((type) => !found.has(type))) {
1299
+ list.push(part);
1300
+ for (const type of types) {
1301
+ found.add(type);
1302
+ }
1303
+ }
1304
+ }
1305
+ function parametersOf(value) {
1306
+ const parameters = [];
1307
+ let start = -1;
1308
+ let quoted = false;
1309
+ for (let i = 0; i < value.length; i++) {
1310
+ if (quoted && value[i] === "\\") {
1311
+ i++;
1312
+ } else if (value[i] === '"') {
1313
+ quoted = !quoted;
1314
+ } else if (value[i] === ";" && !quoted) {
1315
+ if (start !== -1) {
1316
+ parameters.push(value.slice(start, i));
1317
+ }
1318
+ start = i + 1;
1319
+ }
1320
+ }
1321
+ if (start !== -1) {
1322
+ parameters.push(value.slice(start));
1323
+ }
1324
+ return parameters;
1325
+ }
1326
+ var MAX_NAME_FIELDS = 8;
1327
+ var MAX_NAME_PARAMETERS = 32;
1328
+ function repeatedNames(node) {
1329
+ const names = [];
1330
+ const { headers, libmime } = node ?? {};
1331
+ if (typeof headers?.get !== "function" || typeof libmime?.parseHeaderValue !== "function") {
1332
+ return names;
1333
+ }
1334
+ const read = (value, parameter) => {
1335
+ let name = "";
1336
+ try {
1337
+ name = libmime.decodeWords(String(libmime.parseHeaderValue(value, { stripComments: true }).params[parameter] ?? "")).trim();
1338
+ } catch {
1339
+ }
1340
+ if (name !== "") {
1341
+ names.push(name);
1342
+ }
1343
+ };
1344
+ for (const [field, parameter] of [["content-disposition", "filename"], ["content-type", "name"]]) {
1345
+ const values = headers.get(field).slice(0, MAX_NAME_FIELDS);
1346
+ for (const value of values) {
1347
+ const parameters = parametersOf(value).slice(0, MAX_NAME_PARAMETERS).map((text) => ({ text, key: text.slice(0, Math.max(0, text.indexOf("="))).trim().toLowerCase() }));
1348
+ const repeated = parameters.filter(({ key }) => (key === parameter || key.startsWith(`${parameter}*`)) && parameters.filter((other) => other.key === key).length > 1);
1349
+ if (values.length > 1) {
1350
+ read(value, parameter);
1351
+ }
1352
+ for (const { text } of repeated) {
1353
+ read(`x;${text}`, text.slice(0, text.indexOf("=")).trim().toLowerCase().replace(/\*.*$/, ""));
1354
+ }
1355
+ }
1356
+ }
1357
+ return names;
1358
+ }
155
1359
  async function simpleParse(raw, { timeout = PARSE_TIMEOUT, parser = import_mailparser.simpleParser } = {}) {
156
1360
  const input = import_node_stream.Readable.from([finishable(unfoldHeaders(raw))], { objectMode: false, autoDestroy: false });
157
1361
  input.on("error", () => {
158
1362
  });
1363
+ const named = [];
159
1364
  const { pipe } = input;
160
1365
  input.pipe = function(parser2, options) {
161
1366
  parser2.splitter?.on("error", (error) => input.destroy(error));
1367
+ const { createNode } = parser2;
1368
+ if (typeof createNode === "function") {
1369
+ parser2.createNode = function(node) {
1370
+ const created = createNode.call(this, node);
1371
+ if (created?.isAttachment === false && node?.filename) {
1372
+ addFinding(named, { filename: String(node.filename), contentType: created.contentType, content: null });
1373
+ }
1374
+ for (const filename of repeatedNames(node)) {
1375
+ if (filename !== node?.filename) {
1376
+ addFinding(named, { filename, contentType: created?.contentType || "application/octet-stream", content: null });
1377
+ }
1378
+ }
1379
+ return created;
1380
+ };
1381
+ }
162
1382
  return pipe.call(this, parser2, options);
163
1383
  };
164
1384
  let timer;
165
1385
  try {
166
- return await Promise.race([
1386
+ const mail = await Promise.race([
167
1387
  parser(input, PARSER_OPTIONS),
168
1388
  new Promise((resolve, reject) => {
169
1389
  timer = setTimeout(() => {
@@ -173,14 +1393,25 @@ async function simpleParse(raw, { timeout = PARSE_TIMEOUT, parser = import_mailp
173
1393
  }, timeout);
174
1394
  })
175
1395
  ]);
1396
+ if (mail && typeof mail === "object") {
1397
+ let count = 0;
1398
+ for (const [, filename] of String(mail.text ?? "").matchAll(ENCODED_FILES)) {
1399
+ addFinding(named, { filename: filename.trim(), contentType: "application/octet-stream", content: null });
1400
+ if (++count >= MAX_ENCODED_FILES) {
1401
+ break;
1402
+ }
1403
+ }
1404
+ Object.defineProperty(mail, NAMED_TEXT, { value: named });
1405
+ }
1406
+ return mail;
176
1407
  } finally {
177
1408
  clearTimeout(timer);
178
1409
  input.destroy();
179
1410
  }
180
1411
  }
181
1412
  function finishable(raw) {
182
- const buffer = import_node_buffer.Buffer.isBuffer(raw) ? raw : import_node_buffer.Buffer.from(raw);
183
- return import_node_buffer.Buffer.concat([buffer, import_node_buffer.Buffer.from(buffer.at(-1) === 10 ? "\r\n\r\n" : "\r\n\r\n\r\n")]);
1413
+ const buffer = import_node_buffer2.Buffer.isBuffer(raw) ? raw : import_node_buffer2.Buffer.from(raw);
1414
+ return import_node_buffer2.Buffer.concat([buffer, import_node_buffer2.Buffer.from(buffer.at(-1) === 10 ? "\r\n\r\n" : "\r\n\r\n\r\n")]);
184
1415
  }
185
1416
  var MAX_FOLDS = 256;
186
1417
  function headerValue(line) {
@@ -188,18 +1419,18 @@ function headerValue(line) {
188
1419
  let key = null;
189
1420
  let inKey = false;
190
1421
  let quoted = false;
191
- let escaped = false;
1422
+ let escaped2 = false;
192
1423
  let value = "";
193
1424
  for (const chr of line.slice(line.indexOf(":") + 1).replaceAll(/\r?\n[ \t]*/g, " ")) {
194
1425
  if (inKey && chr === "=") {
195
1426
  key = value.trim().toLowerCase();
196
1427
  inKey = false;
197
1428
  value = "";
198
- } else if (inKey || escaped) {
1429
+ } else if (inKey || escaped2) {
199
1430
  value += chr;
200
- escaped = false;
1431
+ escaped2 = false;
201
1432
  } else if (chr === "\\") {
202
- escaped = true;
1433
+ escaped2 = true;
203
1434
  } else if (chr === '"') {
204
1435
  quoted = !quoted;
205
1436
  } else if (chr === ";" && !quoted) {
@@ -245,7 +1476,7 @@ function unfoldHeaders(raw) {
245
1476
  const type = first.get("content-type") ?? { value: "", boundary: "" };
246
1477
  const encoding = (first.get("content-transfer-encoding")?.value ?? "").replaceAll(/\(.*\)/g, "").trim();
247
1478
  if (blank && type.boundary) {
248
- boundaries.push(import_node_buffer.Buffer.from(type.boundary));
1479
+ boundaries.push(import_node_buffer2.Buffer.from(type.boundary));
249
1480
  }
250
1481
  head = blank && ["message/rfc822", "message/global"].includes(type.value) && ["", "7bit", "8bit", "binary"].includes(encoding) && first.get("content-disposition")?.value === "inline";
251
1482
  };
@@ -279,11 +1510,11 @@ function unfoldHeaders(raw) {
279
1510
  const chunks = [];
280
1511
  let copied = 0;
281
1512
  for (const field of unfold) {
282
- chunks.push(raw.subarray(copied, field.start), import_node_buffer.Buffer.from(raw.toString("latin1", field.start, field.end).replaceAll(/\r?\n[ \t]*/g, " "), "latin1"));
1513
+ chunks.push(raw.subarray(copied, field.start), import_node_buffer2.Buffer.from(raw.toString("latin1", field.start, field.end).replaceAll(/\r?\n[ \t]*/g, " "), "latin1"));
283
1514
  copied = field.end;
284
1515
  }
285
1516
  chunks.push(raw.subarray(copied));
286
- return import_node_buffer.Buffer.concat(chunks);
1517
+ return import_node_buffer2.Buffer.concat(chunks);
287
1518
  }
288
1519
 
289
1520
  // src/arf.js
@@ -343,7 +1574,7 @@ function parseReportingMta(value) {
343
1574
  }
344
1575
  function decodeQuotedPrintable(text) {
345
1576
  const soft = text.replaceAll(/=\r?\n/g, "");
346
- const bytes = import_node_buffer2.Buffer.allocUnsafe(soft.length);
1577
+ const bytes = import_node_buffer3.Buffer.allocUnsafe(soft.length);
347
1578
  let length = 0;
348
1579
  for (let i = 0; i < soft.length; i++) {
349
1580
  if (soft[i] === "=" && /^[\da-f]{2}$/i.test(soft.slice(i + 1, i + 3))) {
@@ -356,8 +1587,8 @@ function decodeQuotedPrintable(text) {
356
1587
  return bytes.subarray(0, length);
357
1588
  }
358
1589
  function findPart(raw, boundary, types) {
359
- const escaped = boundary.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
360
- const parts = raw.split(new RegExp(String.raw`\r?\n--${escaped}(?:--)?[ \t]*(?=\r?\n|$)`));
1590
+ const escaped2 = boundary.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
1591
+ const parts = raw.split(new RegExp(String.raw`\r?\n--${escaped2}(?:--)?[ \t]*(?=\r?\n|$)`));
361
1592
  for (const part of parts.slice(1)) {
362
1593
  const match = /^\r?\n((?:[^\r\n]+\r?\n)*)\r?\n([\s\S]*)$/.exec(part);
363
1594
  if (!match) {
@@ -371,11 +1602,11 @@ function findPart(raw, boundary, types) {
371
1602
  const encoding = (/^content-transfer-encoding:\s*(\S+)/im.exec(headers)?.[1] || "").toLowerCase();
372
1603
  let content;
373
1604
  if (encoding === "base64") {
374
- content = import_node_buffer2.Buffer.from(match[2], "base64");
1605
+ content = import_node_buffer3.Buffer.from(match[2], "base64");
375
1606
  } else if (encoding === "quoted-printable") {
376
1607
  content = decodeQuotedPrintable(match[2]);
377
1608
  } else {
378
- content = import_node_buffer2.Buffer.from(match[2], "latin1");
1609
+ content = import_node_buffer3.Buffer.from(match[2], "latin1");
379
1610
  }
380
1611
  return { type, content };
381
1612
  }
@@ -391,7 +1622,7 @@ function isArfMessage(parsed) {
391
1622
  return /^multipart\/report\b/i.test(String(value)) && type.toLowerCase() === "feedback-report";
392
1623
  }
393
1624
  async function parse(message) {
394
- const source = message instanceof Uint8Array && !import_node_buffer2.Buffer.isBuffer(message) ? import_node_buffer2.Buffer.from(message.buffer, message.byteOffset, message.byteLength) : message;
1625
+ const source = message instanceof Uint8Array && !import_node_buffer3.Buffer.isBuffer(message) ? import_node_buffer3.Buffer.from(message.buffer, message.byteOffset, message.byteLength) : message;
395
1626
  const parsed = await simpleParse(source);
396
1627
  if (!isArfMessage(parsed)) {
397
1628
  throw new Error("Not an ARF report: expected multipart/report with report-type=feedback-report");
@@ -436,7 +1667,7 @@ async function parse(message) {
436
1667
  originalHeaders: null,
437
1668
  rawFeedbackReport: raw
438
1669
  };
439
- const text = (import_node_buffer2.Buffer.isBuffer(source) ? source : import_node_buffer2.Buffer.from(String(source))).toString("latin1");
1670
+ const text = (import_node_buffer3.Buffer.isBuffer(source) ? source : import_node_buffer3.Buffer.from(String(source))).toString("latin1");
440
1671
  const { boundary } = parsed.headers.get("content-type").params;
441
1672
  const human = findPart(text, boundary, ["text/plain"]);
442
1673
  result.humanReadable = human ? human.content.toString("utf8").trim() || null : null;
@@ -536,9 +1767,9 @@ function create(options = {}) {
536
1767
  const tail = `\r
537
1768
  --${boundary}--\r
538
1769
  `;
539
- if (import_node_buffer2.Buffer.isBuffer(originalMessage)) {
1770
+ if (import_node_buffer3.Buffer.isBuffer(originalMessage)) {
540
1771
  const end = originalMessage.at(-1) === 10 ? originalMessage.at(-2) === 13 ? 2 : 1 : 0;
541
- return import_node_buffer2.Buffer.concat([import_node_buffer2.Buffer.from(head), originalMessage.subarray(0, originalMessage.length - end), import_node_buffer2.Buffer.from(tail)]);
1772
+ return import_node_buffer3.Buffer.concat([import_node_buffer3.Buffer.from(head), originalMessage.subarray(0, originalMessage.length - end), import_node_buffer3.Buffer.from(tail)]);
542
1773
  }
543
1774
  return head + String(originalMessage).replace(/\r?\n$/, "") + tail;
544
1775
  }
@@ -549,14 +1780,14 @@ function encodeWords(text) {
549
1780
  const words = [];
550
1781
  let word = "";
551
1782
  for (const character of text) {
552
- if (import_node_buffer2.Buffer.byteLength(word + character) > 45) {
1783
+ if (import_node_buffer3.Buffer.byteLength(word + character) > 45) {
553
1784
  words.push(word);
554
1785
  word = "";
555
1786
  }
556
1787
  word += character;
557
1788
  }
558
1789
  words.push(word);
559
- return words.map((part) => `=?UTF-8?B?${import_node_buffer2.Buffer.from(part).toString("base64")}?=`).join("\r\n ");
1790
+ return words.map((part) => `=?UTF-8?B?${import_node_buffer3.Buffer.from(part).toString("base64")}?=`).join("\r\n ");
560
1791
  }
561
1792
  var ArfParser = {
562
1793
  isArfMessage,