@dereekb/nestjs 13.10.7 → 13.10.9

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/index.esm.js CHANGED
@@ -5,9 +5,9 @@ import { createParamDecorator, Logger, BadRequestException, InternalServerErrorE
5
5
  import rawbody from 'raw-body';
6
6
  import { parse } from 'querystring';
7
7
  import bodyParser from 'body-parser';
8
- import { asArray, mergeArrays, isHex, getValueFromGetter } from '@dereekb/util';
8
+ import { asArray, mergeArrays, isHex, getValueFromGetter, PDF_ENCRYPT_MARKER } from '@dereekb/util';
9
9
  import { ConfigService, ConfigModule } from '@nestjs/config';
10
- import { createDecipheriv, randomBytes, createCipheriv } from 'node:crypto';
10
+ import { createDecipheriv, randomBytes, createCipheriv, createHash } from 'node:crypto';
11
11
 
12
12
  function asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, key, arg) {
13
13
  try {
@@ -1305,4 +1305,792 @@ var ENCRYPTED_FIELD_KEY_LENGTH = 32;
1305
1305
  return result;
1306
1306
  }
1307
1307
 
1308
- export { AppModuleWithWebhooksEnabled, CLIENT_WEB_APP_URL_ENV_VAR, ClientAppModule, ClientAppService, ClientAppServiceConfig, ConfigureWebhookMiddlewareModule, DEFAULT_BASE_WEBHOOK_PATH, DEFAULT_WEBHOOK_MIDDLEWARE_ROUTE_INFO, IsRequestFromLocalHost, JsonBodyMiddleware, ParseRawBody, ParsedQueryRawBody, RawBody, RawBodyMiddleware, RawBodyToJson, RawBodyToParsedQueryString, RawBodyToString, SERVER_ENV_TOKEN, ServerEnvironmentConfig, ServerEnvironmentService, appAssetLoaderModuleMetadata, clientAppConfigFactory, consumeWebhooksWithRawBodyMiddleware, createAES256GCMEncryption, createAesStringEncryptionProvider, decryptValue, encryptValue, injectionTokensFromProviders, isLocalhost, isTestNodeEnv, isValidAES256GCMEncryptionSecret, mergeModuleMetadata, nodeJsLocalAssetLoader, resolveEncryptionKey, serverEnvTokenProvider };
1308
+ function _array_like_to_array(arr, len) {
1309
+ if (len == null || len > arr.length) len = arr.length;
1310
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
1311
+ return arr2;
1312
+ }
1313
+ function _array_with_holes(arr) {
1314
+ if (Array.isArray(arr)) return arr;
1315
+ }
1316
+ function _iterable_to_array_limit(arr, i) {
1317
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
1318
+ if (_i == null) return;
1319
+ var _arr = [];
1320
+ var _n = true;
1321
+ var _d = false;
1322
+ var _s, _e;
1323
+ try {
1324
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
1325
+ _arr.push(_s.value);
1326
+ if (i && _arr.length === i) break;
1327
+ }
1328
+ } catch (err) {
1329
+ _d = true;
1330
+ _e = err;
1331
+ } finally{
1332
+ try {
1333
+ if (!_n && _i["return"] != null) _i["return"]();
1334
+ } finally{
1335
+ if (_d) throw _e;
1336
+ }
1337
+ }
1338
+ return _arr;
1339
+ }
1340
+ function _non_iterable_rest() {
1341
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1342
+ }
1343
+ function _sliced_to_array(arr, i) {
1344
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
1345
+ }
1346
+ function _unsupported_iterable_to_array(o, minLen) {
1347
+ if (!o) return;
1348
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
1349
+ var n = Object.prototype.toString.call(o).slice(8, -1);
1350
+ if (n === "Object" && o.constructor) n = o.constructor.name;
1351
+ if (n === "Map" || n === "Set") return Array.from(n);
1352
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
1353
+ }
1354
+ /**
1355
+ * 32-byte password padding string defined by ISO 32000 §7.6.3.3 (Algorithm 2).
1356
+ * Used to pad short or empty user/owner passwords for the standard security handler.
1357
+ */ var PDF_PASSWORD_PADDING = Buffer.from([
1358
+ 0x28,
1359
+ 0xbf,
1360
+ 0x4e,
1361
+ 0x5e,
1362
+ 0x4e,
1363
+ 0x75,
1364
+ 0x8a,
1365
+ 0x41,
1366
+ 0x64,
1367
+ 0x00,
1368
+ 0x4e,
1369
+ 0x56,
1370
+ 0xff,
1371
+ 0xfa,
1372
+ 0x01,
1373
+ 0x08,
1374
+ 0x2e,
1375
+ 0x2e,
1376
+ 0x00,
1377
+ 0xb6,
1378
+ 0xd0,
1379
+ 0x68,
1380
+ 0x3e,
1381
+ 0x80,
1382
+ 0x2f,
1383
+ 0x0c,
1384
+ 0xa9,
1385
+ 0xfe,
1386
+ 0x64,
1387
+ 0x53,
1388
+ 0x69,
1389
+ 0x7a
1390
+ ]);
1391
+ /**
1392
+ * Detects whether a PDF is unencrypted, write-protected (openable without a password
1393
+ * but restricted from editing/printing), or fully encrypted (requires a password to open).
1394
+ *
1395
+ * Implements the user-password validation algorithms from ISO 32000-1 §7.6.3 (R≤4) and
1396
+ * ISO 32000-2 §7.6.4.4 (R=5/6) using only the empty password. If the empty password
1397
+ * validates successfully, the PDF is openable by anyone and only its modify/print/copy
1398
+ * permissions are restricted; otherwise a non-empty user password is required.
1399
+ *
1400
+ * Supported security handlers:
1401
+ * - Standard security handler, R=2,3,4 (RC4-40, RC4-128, AES-128 with crypt filters).
1402
+ * - Standard security handler, R=5 (AES-256, deprecated Adobe extension).
1403
+ * - Standard security handler, R=6 (AES-256, ISO 32000-2 / PDF 2.0).
1404
+ *
1405
+ * Unrecognised security handlers (e.g. PubSec, custom handlers) return
1406
+ * `unknown_encrypted` so callers can choose whether to treat them as fully encrypted.
1407
+ *
1408
+ * Lives in `@dereekb/nestjs` (rather than `@dereekb/util`) because it uses Node's
1409
+ * built-in `node:crypto` module, which isn't available in the browser.
1410
+ *
1411
+ * @example
1412
+ * ```ts
1413
+ * const status = detectPdfEncryption(buffer);
1414
+ *
1415
+ * if (status === 'fully_encrypted') {
1416
+ * throw new Error('PDF requires a password to open.');
1417
+ * }
1418
+ * if (status === 'write_protected_only') {
1419
+ * // Safe to read, but not to mutate without the owner password.
1420
+ * }
1421
+ * ```
1422
+ *
1423
+ * @param buffer - PDF file contents.
1424
+ * @returns The encryption status of the PDF.
1425
+ */ function detectPdfEncryption(buffer) {
1426
+ var result = 'unknown_encrypted';
1427
+ var encryptIndex = findEncryptKeywordIndex(buffer);
1428
+ if (encryptIndex < 0) {
1429
+ result = 'none';
1430
+ } else {
1431
+ var dict = extractEncryptionDictionary(buffer, encryptIndex);
1432
+ var info = dict ? parseEncryptionInfo(dict) : null;
1433
+ if ((info === null || info === void 0 ? void 0 : info.filter) === 'Standard') {
1434
+ var opensWithEmptyPassword = checkStandardHandlerEmptyPassword(info, buffer);
1435
+ if (opensWithEmptyPassword !== null) {
1436
+ result = opensWithEmptyPassword ? 'write_protected_only' : 'fully_encrypted';
1437
+ }
1438
+ }
1439
+ }
1440
+ return result;
1441
+ }
1442
+ function checkStandardHandlerEmptyPassword(info, buffer) {
1443
+ var result = null;
1444
+ if (info.R >= 2 && info.R <= 4) {
1445
+ var fileId = extractFirstFileId(buffer);
1446
+ if (fileId && info.O.length >= 32 && info.U.length >= 32) {
1447
+ result = validateEmptyPasswordR2to4(info, fileId);
1448
+ }
1449
+ } else if (info.R === 5 && info.U.length >= 48) {
1450
+ result = validateEmptyPasswordR5(info);
1451
+ } else if (info.R === 6 && info.U.length >= 48) {
1452
+ result = validateEmptyPasswordR6(info);
1453
+ }
1454
+ return result;
1455
+ }
1456
+ function isPdfWhitespaceByte(b) {
1457
+ return b === 0x00 || b === 0x09 || b === 0x0a || b === 0x0c || b === 0x0d || b === 0x20;
1458
+ }
1459
+ function isPdfDelimiterByte(b) {
1460
+ return b === 0x28 || b === 0x29 || b === 0x3c || b === 0x3e || b === 0x5b || b === 0x5d || b === 0x7b || b === 0x7d || b === 0x2f || b === 0x25;
1461
+ }
1462
+ function isPdfWhitespaceOrDelimiter(b) {
1463
+ return isPdfWhitespaceByte(b) || isPdfDelimiterByte(b);
1464
+ }
1465
+ function skipPdfWhitespaceAndComments(buffer, start) {
1466
+ var i = start;
1467
+ while(i < buffer.length){
1468
+ var b = buffer[i];
1469
+ if (isPdfWhitespaceByte(b)) {
1470
+ i++;
1471
+ } else if (b === 0x25 /* % */ ) {
1472
+ while(i < buffer.length && buffer[i] !== 0x0a && buffer[i] !== 0x0d)i++;
1473
+ } else {
1474
+ break;
1475
+ }
1476
+ }
1477
+ return i;
1478
+ }
1479
+ function skipPdfLiteralString(buffer, start) {
1480
+ var depth = 1;
1481
+ var i = start + 1;
1482
+ while(i < buffer.length && depth > 0){
1483
+ var b = buffer[i];
1484
+ if (b === 0x5c /* \ */ ) {
1485
+ i += 2;
1486
+ } else if (b === 0x28 /* ( */ ) {
1487
+ depth++;
1488
+ i++;
1489
+ } else if (b === 0x29 /* ) */ ) {
1490
+ depth--;
1491
+ i++;
1492
+ } else {
1493
+ i++;
1494
+ }
1495
+ }
1496
+ return i;
1497
+ }
1498
+ function skipPdfHexString(buffer, start) {
1499
+ var i = start + 1;
1500
+ while(i < buffer.length && buffer[i] !== 0x3e /* > */ )i++;
1501
+ return i < buffer.length ? i + 1 : i;
1502
+ }
1503
+ function findDictEnd(buffer, start) {
1504
+ var depth = 1;
1505
+ var i = start;
1506
+ var endIndex = -1;
1507
+ while(i < buffer.length && endIndex < 0){
1508
+ var b = buffer[i];
1509
+ if (b === 0x3c && buffer[i + 1] === 0x3c) {
1510
+ depth++;
1511
+ i += 2;
1512
+ } else if (b === 0x3e && buffer[i + 1] === 0x3e) {
1513
+ depth--;
1514
+ if (depth === 0) {
1515
+ endIndex = i;
1516
+ } else {
1517
+ i += 2;
1518
+ }
1519
+ } else if (b === 0x28) {
1520
+ i = skipPdfLiteralString(buffer, i);
1521
+ } else if (b === 0x3c) {
1522
+ i = skipPdfHexString(buffer, i);
1523
+ } else if (b === 0x25) {
1524
+ while(i < buffer.length && buffer[i] !== 0x0a && buffer[i] !== 0x0d)i++;
1525
+ } else {
1526
+ i++;
1527
+ }
1528
+ }
1529
+ return endIndex >= 0 ? endIndex : i;
1530
+ }
1531
+ function decodePdfLiteralString(content) {
1532
+ var out = [];
1533
+ var i = 0;
1534
+ while(i < content.length){
1535
+ var b = content[i];
1536
+ if (b !== 0x5c /* \ */ ) {
1537
+ out.push(b);
1538
+ i++;
1539
+ continue;
1540
+ }
1541
+ i++;
1542
+ if (i >= content.length) break;
1543
+ var c = content[i];
1544
+ if (c >= 0x30 && c <= 0x37) {
1545
+ var oct = c - 0x30;
1546
+ i++;
1547
+ if (i < content.length && content[i] >= 0x30 && content[i] <= 0x37) {
1548
+ oct = oct * 8 + (content[i] - 0x30);
1549
+ i++;
1550
+ if (i < content.length && content[i] >= 0x30 && content[i] <= 0x37) {
1551
+ oct = oct * 8 + (content[i] - 0x30);
1552
+ i++;
1553
+ }
1554
+ }
1555
+ out.push(oct & 0xff);
1556
+ } else if (c === 0x6e /* n */ ) {
1557
+ out.push(0x0a);
1558
+ i++;
1559
+ } else if (c === 0x72 /* r */ ) {
1560
+ out.push(0x0d);
1561
+ i++;
1562
+ } else if (c === 0x74 /* t */ ) {
1563
+ out.push(0x09);
1564
+ i++;
1565
+ } else if (c === 0x62 /* b */ ) {
1566
+ out.push(0x08);
1567
+ i++;
1568
+ } else if (c === 0x66 /* f */ ) {
1569
+ out.push(0x0c);
1570
+ i++;
1571
+ } else if (c === 0x0a) {
1572
+ i++;
1573
+ } else if (c === 0x0d) {
1574
+ i++;
1575
+ if (i < content.length && content[i] === 0x0a) i++;
1576
+ } else {
1577
+ out.push(c);
1578
+ i++;
1579
+ }
1580
+ }
1581
+ return Buffer.from(out);
1582
+ }
1583
+ function decodePdfHexString(content) {
1584
+ var hex = [];
1585
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1586
+ try {
1587
+ for(var _iterator = content[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1588
+ var b = _step.value;
1589
+ if (isPdfWhitespaceByte(b)) continue;
1590
+ if (b >= 0x30 && b <= 0x39 || b >= 0x41 && b <= 0x46 || b >= 0x61 && b <= 0x66) hex.push(b);
1591
+ }
1592
+ } catch (err) {
1593
+ _didIteratorError = true;
1594
+ _iteratorError = err;
1595
+ } finally{
1596
+ try {
1597
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1598
+ _iterator.return();
1599
+ }
1600
+ } finally{
1601
+ if (_didIteratorError) {
1602
+ throw _iteratorError;
1603
+ }
1604
+ }
1605
+ }
1606
+ if (hex.length % 2 === 1) hex.push(0x30);
1607
+ var out = Buffer.alloc(hex.length / 2);
1608
+ for(var i = 0; i < out.length; i++){
1609
+ out[i] = parseInt(String.fromCharCode(hex[i * 2], hex[i * 2 + 1]), 16);
1610
+ }
1611
+ return out;
1612
+ }
1613
+ function readPdfNumber(buffer, start) {
1614
+ var i = start;
1615
+ while(i < buffer.length && !isPdfWhitespaceOrDelimiter(buffer[i]))i++;
1616
+ var result = null;
1617
+ if (i > start) {
1618
+ var text = buffer.toString('latin1', start, i);
1619
+ var value = Number(text);
1620
+ if (!Number.isNaN(value)) {
1621
+ result = {
1622
+ value: value,
1623
+ end: i
1624
+ };
1625
+ }
1626
+ }
1627
+ return result;
1628
+ }
1629
+ function parsePdfDict(buffer, dictStart) {
1630
+ // dictStart is the byte after `<<`.
1631
+ var entries = new Map();
1632
+ var i = skipPdfWhitespaceAndComments(buffer, dictStart);
1633
+ var result = null;
1634
+ var aborted = false;
1635
+ while(i < buffer.length && !aborted && result === null){
1636
+ if (buffer[i] === 0x3e && buffer[i + 1] === 0x3e) {
1637
+ result = {
1638
+ entries: entries,
1639
+ end: i + 2
1640
+ };
1641
+ } else if (buffer[i] !== 0x2f /* / */ ) {
1642
+ aborted = true;
1643
+ } else {
1644
+ var nameStart = i + 1;
1645
+ var nameEnd = nameStart;
1646
+ while(nameEnd < buffer.length && !isPdfWhitespaceOrDelimiter(buffer[nameEnd]))nameEnd++;
1647
+ var name = buffer.toString('latin1', nameStart, nameEnd);
1648
+ i = skipPdfWhitespaceAndComments(buffer, nameEnd);
1649
+ if (i >= buffer.length) {
1650
+ aborted = true;
1651
+ } else {
1652
+ var valueResult = readPdfValue(buffer, i);
1653
+ if (!valueResult) {
1654
+ aborted = true;
1655
+ } else {
1656
+ entries.set(name, valueResult.entry);
1657
+ i = skipPdfWhitespaceAndComments(buffer, valueResult.end);
1658
+ }
1659
+ }
1660
+ }
1661
+ }
1662
+ return result;
1663
+ }
1664
+ function readPdfValue(buffer, start) {
1665
+ var b = buffer[start];
1666
+ var result;
1667
+ if (b === 0x3c && buffer[start + 1] === 0x3c) {
1668
+ result = readPdfDictValue(buffer, start);
1669
+ } else if (b === 0x3c) {
1670
+ result = readPdfHexStringValue(buffer, start);
1671
+ } else if (b === 0x28) {
1672
+ result = readPdfLiteralStringValue(buffer, start);
1673
+ } else if (b === 0x5b /* [ */ ) {
1674
+ result = readPdfArrayValue(buffer, start);
1675
+ } else if (b === 0x2f /* / */ ) {
1676
+ result = readPdfNameValue(buffer, start);
1677
+ } else {
1678
+ result = readPdfTokenOrRefValue(buffer, start);
1679
+ }
1680
+ return result;
1681
+ }
1682
+ function readPdfDictValue(buffer, start) {
1683
+ var dictEnd = findDictEnd(buffer, start + 2);
1684
+ var end = dictEnd < buffer.length && buffer[dictEnd] === 0x3e && buffer[dictEnd + 1] === 0x3e ? dictEnd + 2 : dictEnd;
1685
+ return {
1686
+ entry: {
1687
+ type: 'dict',
1688
+ raw: buffer.subarray(start, end)
1689
+ },
1690
+ end: end
1691
+ };
1692
+ }
1693
+ function readPdfHexStringValue(buffer, start) {
1694
+ var end = skipPdfHexString(buffer, start);
1695
+ return {
1696
+ entry: {
1697
+ type: 'string',
1698
+ raw: decodePdfHexString(buffer.subarray(start + 1, end - 1))
1699
+ },
1700
+ end: end
1701
+ };
1702
+ }
1703
+ function readPdfLiteralStringValue(buffer, start) {
1704
+ var end = skipPdfLiteralString(buffer, start);
1705
+ return {
1706
+ entry: {
1707
+ type: 'string',
1708
+ raw: decodePdfLiteralString(buffer.subarray(start + 1, end - 1))
1709
+ },
1710
+ end: end
1711
+ };
1712
+ }
1713
+ function readPdfArrayValue(buffer, start) {
1714
+ var depth = 1;
1715
+ var i = start + 1;
1716
+ while(i < buffer.length && depth > 0){
1717
+ var c = buffer[i];
1718
+ if (c === 0x5b) {
1719
+ depth++;
1720
+ i++;
1721
+ } else if (c === 0x5d) {
1722
+ depth--;
1723
+ i++;
1724
+ } else if (c === 0x28) {
1725
+ i = skipPdfLiteralString(buffer, i);
1726
+ } else if (c === 0x3c && buffer[i + 1] === 0x3c) {
1727
+ var e = findDictEnd(buffer, i + 2);
1728
+ i = e < buffer.length && buffer[e] === 0x3e && buffer[e + 1] === 0x3e ? e + 2 : e;
1729
+ } else if (c === 0x3c) {
1730
+ i = skipPdfHexString(buffer, i);
1731
+ } else if (c === 0x25) {
1732
+ while(i < buffer.length && buffer[i] !== 0x0a && buffer[i] !== 0x0d)i++;
1733
+ } else {
1734
+ i++;
1735
+ }
1736
+ }
1737
+ return {
1738
+ entry: {
1739
+ type: 'array',
1740
+ raw: buffer.subarray(start, i)
1741
+ },
1742
+ end: i
1743
+ };
1744
+ }
1745
+ function readPdfNameValue(buffer, start) {
1746
+ var i = start + 1;
1747
+ while(i < buffer.length && !isPdfWhitespaceOrDelimiter(buffer[i]))i++;
1748
+ return {
1749
+ entry: {
1750
+ type: 'name',
1751
+ raw: buffer.subarray(start + 1, i)
1752
+ },
1753
+ end: i
1754
+ };
1755
+ }
1756
+ function readPdfTokenOrRefValue(buffer, start) {
1757
+ // Number, boolean, null, or indirect reference like `12 0 R`.
1758
+ var i = start;
1759
+ while(i < buffer.length && !isPdfWhitespaceOrDelimiter(buffer[i]))i++;
1760
+ var tokenEnd = i;
1761
+ var token = buffer.toString('latin1', start, tokenEnd);
1762
+ var referenceEnd = readIndirectReferenceEnd(buffer, tokenEnd);
1763
+ var result;
1764
+ if (referenceEnd !== null) {
1765
+ result = {
1766
+ entry: {
1767
+ type: 'ref',
1768
+ raw: buffer.subarray(start, referenceEnd)
1769
+ },
1770
+ end: referenceEnd
1771
+ };
1772
+ } else if (token === 'true' || token === 'false') {
1773
+ result = {
1774
+ entry: {
1775
+ type: 'boolean',
1776
+ raw: buffer.subarray(start, tokenEnd)
1777
+ },
1778
+ end: tokenEnd
1779
+ };
1780
+ } else if (token === 'null') {
1781
+ result = {
1782
+ entry: {
1783
+ type: 'null',
1784
+ raw: buffer.subarray(start, tokenEnd)
1785
+ },
1786
+ end: tokenEnd
1787
+ };
1788
+ } else {
1789
+ result = {
1790
+ entry: {
1791
+ type: 'number',
1792
+ raw: buffer.subarray(start, tokenEnd)
1793
+ },
1794
+ end: tokenEnd
1795
+ };
1796
+ }
1797
+ return result;
1798
+ }
1799
+ function readIndirectReferenceEnd(buffer, tokenEnd) {
1800
+ // Probe ahead for `GEN R` after a leading object number to detect `N G R`.
1801
+ var result = null;
1802
+ var probe = skipPdfWhitespaceAndComments(buffer, tokenEnd);
1803
+ if (probe < buffer.length) {
1804
+ var c = buffer[probe];
1805
+ if (c >= 0x30 && c <= 0x39) {
1806
+ var secondEnd = probe;
1807
+ while(secondEnd < buffer.length && !isPdfWhitespaceOrDelimiter(buffer[secondEnd]))secondEnd++;
1808
+ var probe2 = skipPdfWhitespaceAndComments(buffer, secondEnd);
1809
+ if (probe2 < buffer.length && buffer[probe2] === 0x52 /* R */ && (probe2 + 1 === buffer.length || isPdfWhitespaceOrDelimiter(buffer[probe2 + 1]))) {
1810
+ result = probe2 + 1;
1811
+ }
1812
+ }
1813
+ }
1814
+ return result;
1815
+ }
1816
+ function findEncryptKeywordIndex(buffer) {
1817
+ var marker = PDF_ENCRYPT_MARKER;
1818
+ var last = -1;
1819
+ var pos = 0;
1820
+ while(true){
1821
+ var found = buffer.indexOf(marker, pos);
1822
+ if (found < 0) break;
1823
+ var next = buffer[found + marker.length];
1824
+ // Avoid matching `/EncryptMetadata` (a different name).
1825
+ var isAlpha = next >= 0x41 && next <= 0x5a || next >= 0x61 && next <= 0x7a;
1826
+ if (!isAlpha) last = found;
1827
+ pos = found + marker.length;
1828
+ }
1829
+ return last;
1830
+ }
1831
+ function extractEncryptionDictionary(buffer, encryptIndex) {
1832
+ var result = null;
1833
+ var i = encryptIndex + PDF_ENCRYPT_MARKER.length;
1834
+ i = skipPdfWhitespaceAndComments(buffer, i);
1835
+ if (i < buffer.length) {
1836
+ if (buffer[i] === 0x3c && buffer[i + 1] === 0x3c) {
1837
+ // Inline dictionary.
1838
+ var dictEnd = findDictEnd(buffer, i + 2);
1839
+ result = buffer.subarray(i, dictEnd + 2);
1840
+ } else {
1841
+ // Indirect reference: `N G R`.
1842
+ result = resolveIndirectEncryptionDictionary(buffer, i);
1843
+ }
1844
+ }
1845
+ return result;
1846
+ }
1847
+ function resolveIndirectEncryptionDictionary(buffer, start) {
1848
+ var result = null;
1849
+ var numResult = readPdfNumber(buffer, start);
1850
+ if (numResult) {
1851
+ var afterFirst = skipPdfWhitespaceAndComments(buffer, numResult.end);
1852
+ var genResult = readPdfNumber(buffer, afterFirst);
1853
+ if (genResult) {
1854
+ var afterSecond = skipPdfWhitespaceAndComments(buffer, genResult.end);
1855
+ if (buffer[afterSecond] === 0x52 /* R */ ) {
1856
+ var objStart = findIndirectObjectStart(buffer, numResult.value, genResult.value);
1857
+ if (objStart >= 0) {
1858
+ var dictStart = buffer.indexOf('<<', objStart);
1859
+ if (dictStart >= 0) {
1860
+ var dictEnd = findDictEnd(buffer, dictStart + 2);
1861
+ result = buffer.subarray(dictStart, dictEnd + 2);
1862
+ }
1863
+ }
1864
+ }
1865
+ }
1866
+ }
1867
+ return result;
1868
+ }
1869
+ function findIndirectObjectStart(buffer, objNum, objGen) {
1870
+ var text = buffer.toString('latin1');
1871
+ var re = new RegExp("(?:^|[\\r\\n\\s])".concat(objNum, "\\s+").concat(objGen, "\\s+obj\\b"));
1872
+ var match = re.exec(text);
1873
+ return match ? match.index + match[0].length : -1;
1874
+ }
1875
+ function parseEncryptionInfo(dictBuffer) {
1876
+ // `dictBuffer` is the full `<< ... >>`; pass the body to parsePdfDict.
1877
+ var result = null;
1878
+ var isDict = dictBuffer.length >= 4 && dictBuffer[0] === 0x3c && dictBuffer[1] === 0x3c;
1879
+ var parsed = isDict ? parsePdfDict(dictBuffer, 2) : null;
1880
+ if (parsed) {
1881
+ var _readNameValue, _readNumberValue, _readNumberValue1, _readNumberValue2, _readStringValue, _readStringValue1, _readNumberValue3, _readBooleanValue;
1882
+ var entries = parsed.entries;
1883
+ var filter = (_readNameValue = readNameValue(entries.get('Filter'))) !== null && _readNameValue !== void 0 ? _readNameValue : '';
1884
+ var V = (_readNumberValue = readNumberValue(entries.get('V'))) !== null && _readNumberValue !== void 0 ? _readNumberValue : 0;
1885
+ var R = (_readNumberValue1 = readNumberValue(entries.get('R'))) !== null && _readNumberValue1 !== void 0 ? _readNumberValue1 : 0;
1886
+ var Length = (_readNumberValue2 = readNumberValue(entries.get('Length'))) !== null && _readNumberValue2 !== void 0 ? _readNumberValue2 : V >= 5 ? 256 : 40;
1887
+ var O = (_readStringValue = readStringValue(entries.get('O'))) !== null && _readStringValue !== void 0 ? _readStringValue : Buffer.alloc(0);
1888
+ var U = (_readStringValue1 = readStringValue(entries.get('U'))) !== null && _readStringValue1 !== void 0 ? _readStringValue1 : Buffer.alloc(0);
1889
+ var P = (_readNumberValue3 = readNumberValue(entries.get('P'))) !== null && _readNumberValue3 !== void 0 ? _readNumberValue3 : 0;
1890
+ var encryptMetadataEntry = entries.get('EncryptMetadata');
1891
+ var encryptMetadata = encryptMetadataEntry ? (_readBooleanValue = readBooleanValue(encryptMetadataEntry)) !== null && _readBooleanValue !== void 0 ? _readBooleanValue : true : true;
1892
+ if (R !== 0 && V !== 0) {
1893
+ result = {
1894
+ filter: filter,
1895
+ V: V,
1896
+ R: R,
1897
+ Length: Length,
1898
+ O: O,
1899
+ U: U,
1900
+ P: P,
1901
+ encryptMetadata: encryptMetadata
1902
+ };
1903
+ }
1904
+ }
1905
+ return result;
1906
+ }
1907
+ function readNumberValue(entry) {
1908
+ var result = null;
1909
+ if ((entry === null || entry === void 0 ? void 0 : entry.type) === 'number') {
1910
+ var value = Number(entry.raw.toString('latin1'));
1911
+ if (!Number.isNaN(value)) {
1912
+ result = value;
1913
+ }
1914
+ }
1915
+ return result;
1916
+ }
1917
+ function readNameValue(entry) {
1918
+ return (entry === null || entry === void 0 ? void 0 : entry.type) === 'name' ? entry.raw.toString('latin1') : null;
1919
+ }
1920
+ function readStringValue(entry) {
1921
+ return (entry === null || entry === void 0 ? void 0 : entry.type) === 'string' ? entry.raw : null;
1922
+ }
1923
+ function readBooleanValue(entry) {
1924
+ return entry.type === 'boolean' ? entry.raw.toString('latin1') === 'true' : null;
1925
+ }
1926
+ function extractFirstFileId(buffer) {
1927
+ // The /ID array lives in the trailer or the cross-reference stream dictionary.
1928
+ // Walk the buffer right-to-left to find the most recent /ID array.
1929
+ var result = null;
1930
+ var pos = buffer.length;
1931
+ var done = false;
1932
+ while(pos > 0 && !done){
1933
+ var found = buffer.lastIndexOf('/ID', pos);
1934
+ if (found < 0) {
1935
+ done = true;
1936
+ } else {
1937
+ var after = found + 3;
1938
+ var isExactName = after >= buffer.length || isPdfWhitespaceOrDelimiter(buffer[after]);
1939
+ if (isExactName) {
1940
+ var i = skipPdfWhitespaceAndComments(buffer, after);
1941
+ if (buffer[i] === 0x5b /* [ */ ) {
1942
+ i = skipPdfWhitespaceAndComments(buffer, i + 1);
1943
+ var valueResult = readPdfValue(buffer, i);
1944
+ if ((valueResult === null || valueResult === void 0 ? void 0 : valueResult.entry.type) === 'string') {
1945
+ result = valueResult.entry.raw;
1946
+ done = true;
1947
+ }
1948
+ }
1949
+ }
1950
+ if (!done) {
1951
+ pos = found - 1;
1952
+ }
1953
+ }
1954
+ }
1955
+ return result;
1956
+ }
1957
+ // MARK: Standard security handler — empty-password validation
1958
+ function rc4(key, data) {
1959
+ var S = new Uint8Array(256);
1960
+ for(var i = 0; i < 256; i++)S[i] = i;
1961
+ var j = 0;
1962
+ for(var i1 = 0; i1 < 256; i1++){
1963
+ j = j + S[i1] + key[i1 % key.length] & 0xff;
1964
+ var t = S[i1];
1965
+ S[i1] = S[j];
1966
+ S[j] = t;
1967
+ }
1968
+ var out = Buffer.alloc(data.length);
1969
+ var ii = 0;
1970
+ var jj = 0;
1971
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1972
+ try {
1973
+ for(var _iterator = data.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1974
+ var _step_value = _sliced_to_array(_step.value, 2), n = _step_value[0], byte = _step_value[1];
1975
+ ii = ii + 1 & 0xff;
1976
+ jj = jj + S[ii] & 0xff;
1977
+ var t1 = S[ii];
1978
+ S[ii] = S[jj];
1979
+ S[jj] = t1;
1980
+ out[n] = byte ^ S[S[ii] + S[jj] & 0xff];
1981
+ }
1982
+ } catch (err) {
1983
+ _didIteratorError = true;
1984
+ _iteratorError = err;
1985
+ } finally{
1986
+ try {
1987
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1988
+ _iterator.return();
1989
+ }
1990
+ } finally{
1991
+ if (_didIteratorError) {
1992
+ throw _iteratorError;
1993
+ }
1994
+ }
1995
+ }
1996
+ return out;
1997
+ }
1998
+ function computeFileEncryptionKeyR2to4(info, password, fileId) {
1999
+ var padded = Buffer.alloc(32);
2000
+ password.copy(padded, 0, 0, Math.min(password.length, 32));
2001
+ if (password.length < 32) PDF_PASSWORD_PADDING.copy(padded, password.length, 0, 32 - password.length);
2002
+ var md5 = createHash('md5');
2003
+ md5.update(padded);
2004
+ md5.update(info.O);
2005
+ var pBytes = Buffer.alloc(4);
2006
+ pBytes.writeInt32LE(info.P | 0, 0);
2007
+ md5.update(pBytes);
2008
+ md5.update(fileId);
2009
+ if (info.R >= 4 && !info.encryptMetadata) md5.update(Buffer.from([
2010
+ 0xff,
2011
+ 0xff,
2012
+ 0xff,
2013
+ 0xff
2014
+ ]));
2015
+ var key = md5.digest();
2016
+ var keyBytes = Math.min(Math.floor(info.Length / 8), key.length);
2017
+ if (info.R >= 3) {
2018
+ for(var i = 0; i < 50; i++){
2019
+ key = createHash('md5').update(key.subarray(0, keyBytes)).digest();
2020
+ }
2021
+ }
2022
+ return key.subarray(0, keyBytes);
2023
+ }
2024
+ function validateEmptyPasswordR2to4(info, fileId) {
2025
+ var password = Buffer.alloc(0);
2026
+ var key = computeFileEncryptionKeyR2to4(info, password, fileId);
2027
+ var matches;
2028
+ if (info.R === 2) {
2029
+ var expected = rc4(key, PDF_PASSWORD_PADDING);
2030
+ matches = constantTimeEquals(expected, info.U.subarray(0, 32));
2031
+ } else {
2032
+ var computed = createHash('md5').update(PDF_PASSWORD_PADDING).update(fileId).digest();
2033
+ computed = rc4(key, computed);
2034
+ for(var i = 1; i <= 19; i++){
2035
+ var xorKey = Buffer.alloc(key.length);
2036
+ for(var j = 0; j < key.length; j++)xorKey[j] = key[j] ^ i;
2037
+ computed = rc4(xorKey, computed);
2038
+ }
2039
+ matches = constantTimeEquals(computed, info.U.subarray(0, 16));
2040
+ }
2041
+ return matches;
2042
+ }
2043
+ function validateEmptyPasswordR5(info) {
2044
+ var validationSalt = info.U.subarray(32, 40);
2045
+ var computed = createHash('sha256').update(validationSalt).digest();
2046
+ return constantTimeEquals(computed, info.U.subarray(0, 32));
2047
+ }
2048
+ function validateEmptyPasswordR6(info) {
2049
+ var validationSalt = info.U.subarray(32, 40);
2050
+ var password = Buffer.alloc(0);
2051
+ var computed = pdfAlgorithm2B(Buffer.concat([
2052
+ password,
2053
+ validationSalt
2054
+ ]), password, Buffer.alloc(0));
2055
+ return constantTimeEquals(computed, info.U.subarray(0, 32));
2056
+ }
2057
+ function pdfAlgorithm2B(input, password, userKey) {
2058
+ var K = createHash('sha256').update(input).digest();
2059
+ var round = 0;
2060
+ var lastE = Buffer.alloc(0);
2061
+ while(true){
2062
+ var part = Buffer.concat([
2063
+ password,
2064
+ K,
2065
+ userKey
2066
+ ]);
2067
+ var K1 = Buffer.alloc(part.length * 64);
2068
+ for(var i = 0; i < 64; i++)part.copy(K1, i * part.length);
2069
+ var cipher = createCipheriv('aes-128-cbc', K.subarray(0, 16), K.subarray(16, 32));
2070
+ cipher.setAutoPadding(false);
2071
+ var E = Buffer.concat([
2072
+ cipher.update(K1),
2073
+ cipher.final()
2074
+ ]);
2075
+ lastE = E;
2076
+ var n = 0;
2077
+ for(var i1 = 0; i1 < 16; i1++)n = (n * 256 + E[i1]) % 3;
2078
+ if (n === 0) K = createHash('sha256').update(E).digest();
2079
+ else if (n === 1) K = createHash('sha384').update(E).digest();
2080
+ else K = createHash('sha512').update(E).digest();
2081
+ round++;
2082
+ if (round >= 64 && lastE[lastE.length - 1] <= round - 32) break;
2083
+ }
2084
+ return K.subarray(0, 32);
2085
+ }
2086
+ function constantTimeEquals(a, b) {
2087
+ var result = false;
2088
+ if (a.length === b.length) {
2089
+ var diff = 0;
2090
+ for(var i = 0; i < a.length; i++)diff |= a[i] ^ b[i];
2091
+ result = diff === 0;
2092
+ }
2093
+ return result;
2094
+ }
2095
+
2096
+ export { AppModuleWithWebhooksEnabled, CLIENT_WEB_APP_URL_ENV_VAR, ClientAppModule, ClientAppService, ClientAppServiceConfig, ConfigureWebhookMiddlewareModule, DEFAULT_BASE_WEBHOOK_PATH, DEFAULT_WEBHOOK_MIDDLEWARE_ROUTE_INFO, IsRequestFromLocalHost, JsonBodyMiddleware, ParseRawBody, ParsedQueryRawBody, RawBody, RawBodyMiddleware, RawBodyToJson, RawBodyToParsedQueryString, RawBodyToString, SERVER_ENV_TOKEN, ServerEnvironmentConfig, ServerEnvironmentService, appAssetLoaderModuleMetadata, clientAppConfigFactory, consumeWebhooksWithRawBodyMiddleware, createAES256GCMEncryption, createAesStringEncryptionProvider, decryptValue, detectPdfEncryption, encryptValue, injectionTokensFromProviders, isLocalhost, isTestNodeEnv, isValidAES256GCMEncryptionSecret, mergeModuleMetadata, nodeJsLocalAssetLoader, resolveEncryptionKey, serverEnvTokenProvider };