pdf-parser.js 3.0.8 → 4.5.2

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.
Files changed (240) hide show
  1. package/README.md +105 -54
  2. package/dist/{afm-widths-Dxucrg7D.js → afm-widths-BTu0IDp2.cjs} +1517 -4
  3. package/dist/{afm-widths-DyDq56Ph.d.cts → afm-widths-CneRyu5l.d.cts} +1 -1
  4. package/dist/{afm-widths-DyDq56Ph.d.ts → afm-widths-CneRyu5l.d.ts} +1 -1
  5. package/dist/{afm-widths-BoeTOK2r.cjs → afm-widths-De_QMWgC.js} +1416 -51
  6. package/dist/afm-widths.cjs +1 -1
  7. package/dist/afm-widths.d.cts +1 -1
  8. package/dist/afm-widths.d.ts +1 -1
  9. package/dist/afm-widths.js +1 -1
  10. package/dist/annotations.cjs +104 -0
  11. package/dist/annotations.d.cts +9 -0
  12. package/dist/annotations.d.ts +9 -0
  13. package/dist/annotations.js +103 -0
  14. package/dist/attachments.cjs +65 -0
  15. package/dist/attachments.d.cts +8 -0
  16. package/dist/attachments.d.ts +8 -0
  17. package/dist/attachments.js +64 -0
  18. package/dist/builtin-encoding.cjs +221 -0
  19. package/dist/builtin-encoding.d.cts +8 -0
  20. package/dist/builtin-encoding.d.ts +8 -0
  21. package/dist/builtin-encoding.js +220 -0
  22. package/dist/bytes/flate.cjs +1 -1
  23. package/dist/bytes/flate.js +1 -1
  24. package/dist/cff.cjs +14 -0
  25. package/dist/cff.d.cts +4 -1
  26. package/dist/cff.d.ts +4 -1
  27. package/dist/cff.js +12 -1
  28. package/dist/cmap-table.cjs +76 -13
  29. package/dist/cmap-table.d.cts +9 -1
  30. package/dist/cmap-table.d.ts +9 -1
  31. package/dist/cmap-table.js +77 -15
  32. package/dist/codec.cjs +1 -1
  33. package/dist/codec.d.cts +134 -0
  34. package/dist/codec.d.ts +134 -0
  35. package/dist/codec.js +1 -1
  36. package/dist/content-read.cjs +1 -1
  37. package/dist/content-read.d.cts +3 -3
  38. package/dist/content-read.d.ts +3 -3
  39. package/dist/content-read.js +1 -1
  40. package/dist/content-write.cjs +32 -10
  41. package/dist/content-write.d.cts +12 -5
  42. package/dist/content-write.d.ts +12 -5
  43. package/dist/content-write.js +32 -10
  44. package/dist/crypto/random.cjs +9 -0
  45. package/dist/crypto/random.d.cts +4 -0
  46. package/dist/crypto/random.d.ts +4 -0
  47. package/dist/crypto/random.js +8 -0
  48. package/dist/diagnostics.d.cts +1 -1
  49. package/dist/diagnostics.d.ts +1 -1
  50. package/dist/document.cjs +12 -3
  51. package/dist/document.d.cts +3 -1
  52. package/dist/document.d.ts +3 -1
  53. package/dist/document.js +12 -3
  54. package/dist/{embedded-font-fREdbxnr.d.ts → embedded-font-B4p9a3O3.d.ts} +3 -1
  55. package/dist/{embedded-font-BU6Jgcof.d.cts → embedded-font-oc65VGlr.d.cts} +3 -1
  56. package/dist/embedded-font-write.cjs +1 -1
  57. package/dist/embedded-font-write.d.cts +3 -3
  58. package/dist/embedded-font-write.d.ts +3 -3
  59. package/dist/embedded-font-write.js +1 -1
  60. package/dist/embedded-font.cjs +46 -15
  61. package/dist/embedded-font.d.cts +1 -1
  62. package/dist/embedded-font.d.ts +1 -1
  63. package/dist/embedded-font.js +46 -15
  64. package/dist/encoding.cjs +10 -1
  65. package/dist/encoding.d.cts +10 -1
  66. package/dist/encoding.d.ts +10 -1
  67. package/dist/encoding.js +2 -2
  68. package/dist/encrypt-write.cjs +234 -0
  69. package/dist/encrypt-write.d.cts +31 -0
  70. package/dist/encrypt-write.d.ts +31 -0
  71. package/dist/encrypt-write.js +231 -0
  72. package/dist/encrypt.cjs +51 -21
  73. package/dist/encrypt.d.cts +19 -3
  74. package/dist/encrypt.d.ts +19 -3
  75. package/dist/encrypt.js +36 -22
  76. package/dist/filters.cjs +18 -14
  77. package/dist/filters.d.cts +1 -1
  78. package/dist/filters.d.ts +1 -1
  79. package/dist/filters.js +18 -14
  80. package/dist/font-read.cjs +68 -13
  81. package/dist/font-read.d.cts +1 -1
  82. package/dist/font-read.d.ts +1 -1
  83. package/dist/font-read.js +69 -14
  84. package/dist/font-registry.cjs +1 -1
  85. package/dist/font-registry.d.cts +4 -4
  86. package/dist/font-registry.d.ts +4 -4
  87. package/dist/font-registry.js +1 -1
  88. package/dist/font-substitutes.d.cts +1 -1
  89. package/dist/font-substitutes.d.ts +1 -1
  90. package/dist/font-tables.cjs +31 -0
  91. package/dist/font-tables.d.cts +3 -1
  92. package/dist/font-tables.d.ts +3 -1
  93. package/dist/font-tables.js +31 -2
  94. package/dist/fonts.d.cts +2 -2
  95. package/dist/fonts.d.ts +2 -2
  96. package/dist/form.cjs +138 -0
  97. package/dist/form.d.cts +9 -0
  98. package/dist/form.d.ts +9 -0
  99. package/dist/form.js +137 -0
  100. package/dist/gsub-table-BRTQ8EUW.d.ts +10 -0
  101. package/dist/gsub-table-URczLd85.d.cts +10 -0
  102. package/dist/gsub-table.cjs +225 -0
  103. package/dist/gsub-table.d.cts +2 -0
  104. package/dist/gsub-table.d.ts +2 -0
  105. package/dist/gsub-table.js +224 -0
  106. package/dist/image/ccitt-encode.cjs +119 -0
  107. package/dist/image/ccitt-encode.d.cts +9 -0
  108. package/dist/image/ccitt-encode.d.ts +9 -0
  109. package/dist/image/ccitt-encode.js +118 -0
  110. package/dist/image/ccitt.cjs +3 -0
  111. package/dist/image/ccitt.d.cts +4 -1
  112. package/dist/image/ccitt.d.ts +4 -1
  113. package/dist/image/ccitt.js +1 -1
  114. package/dist/image/jbig2-bitmap.d.cts +1 -1
  115. package/dist/image/jbig2-bitmap.d.ts +1 -1
  116. package/dist/image/jbig2.cjs +3 -1
  117. package/dist/image/jbig2.js +3 -1
  118. package/dist/image/jp2-boxes.d.cts +1 -1
  119. package/dist/image/jp2-boxes.d.ts +1 -1
  120. package/dist/image/jpeg2000-codestream.d.cts +3 -3
  121. package/dist/image/jpeg2000-codestream.d.ts +3 -3
  122. package/dist/image/jpeg2000-t1.d.cts +1 -1
  123. package/dist/image/jpeg2000-t1.d.ts +1 -1
  124. package/dist/image/jpeg2000.cjs +1 -0
  125. package/dist/image/jpeg2000.d.cts +3 -0
  126. package/dist/image/jpeg2000.d.ts +3 -0
  127. package/dist/image/jpeg2000.js +1 -0
  128. package/dist/image/png-decode.cjs +1 -1
  129. package/dist/image/png-decode.js +1 -1
  130. package/dist/image/png-filter.d.cts +1 -1
  131. package/dist/image/png-filter.d.ts +1 -1
  132. package/dist/images-read.cjs +18 -12
  133. package/dist/images-read.d.cts +2 -2
  134. package/dist/images-read.d.ts +2 -2
  135. package/dist/images-read.js +15 -9
  136. package/dist/index.cjs +17 -4
  137. package/dist/index.d.cts +7 -6
  138. package/dist/index.d.ts +7 -6
  139. package/dist/index.js +6 -5
  140. package/dist/interpret.cjs +178 -56
  141. package/dist/interpret.d.cts +27 -12
  142. package/dist/interpret.d.ts +27 -12
  143. package/dist/interpret.js +178 -56
  144. package/dist/layout.cjs +149 -2
  145. package/dist/layout.d.cts +394 -1
  146. package/dist/layout.d.ts +394 -1
  147. package/dist/layout.js +140 -4
  148. package/dist/lexer.d.cts +9 -9
  149. package/dist/lexer.d.ts +9 -9
  150. package/dist/math-content-write.cjs +1 -1
  151. package/dist/math-content-write.js +1 -1
  152. package/dist/math-font-write.cjs +1 -1
  153. package/dist/math-font-write.d.cts +1 -1
  154. package/dist/math-font-write.d.ts +1 -1
  155. package/dist/math-font-write.js +1 -1
  156. package/dist/math-font.cjs +2 -2
  157. package/dist/math-font.d.cts +1 -1
  158. package/dist/math-font.d.ts +1 -1
  159. package/dist/math-font.js +2 -2
  160. package/dist/{math-stretch-a_rHNRvc.d.ts → math-stretch-BbC2o4Br.d.ts} +1 -1
  161. package/dist/{math-stretch-E26z6byT.d.cts → math-stretch-C2JanDAz.d.cts} +1 -1
  162. package/dist/math-stretch.d.cts +1 -1
  163. package/dist/math-stretch.d.ts +1 -1
  164. package/dist/measure.cjs +1 -1
  165. package/dist/measure.d.cts +1 -1
  166. package/dist/measure.d.ts +1 -1
  167. package/dist/measure.js +1 -1
  168. package/dist/names.cjs +41 -0
  169. package/dist/names.d.cts +11 -0
  170. package/dist/names.d.ts +11 -0
  171. package/dist/names.js +40 -0
  172. package/dist/navigation.cjs +210 -0
  173. package/dist/navigation.d.cts +18 -0
  174. package/dist/navigation.d.ts +18 -0
  175. package/dist/navigation.js +207 -0
  176. package/dist/notes-annotation-author.cjs +5 -0
  177. package/dist/notes-annotation-author.d.cts +4 -0
  178. package/dist/notes-annotation-author.d.ts +4 -0
  179. package/dist/notes-annotation-author.js +4 -0
  180. package/dist/objects-B7HdMeWS.d.cts +59 -0
  181. package/dist/objects-B7HdMeWS.d.ts +59 -0
  182. package/dist/objects.d.cts +1 -58
  183. package/dist/objects.d.ts +1 -58
  184. package/dist/optional-content.cjs +63 -0
  185. package/dist/optional-content.d.cts +12 -0
  186. package/dist/optional-content.d.ts +12 -0
  187. package/dist/optional-content.js +62 -0
  188. package/dist/parse.cjs +1 -1
  189. package/dist/parse.d.cts +2 -2
  190. package/dist/parse.d.ts +2 -2
  191. package/dist/parse.js +1 -1
  192. package/dist/pdf-text.cjs +21 -0
  193. package/dist/pdf-text.d.cts +5 -0
  194. package/dist/pdf-text.d.ts +5 -0
  195. package/dist/pdf-text.js +19 -0
  196. package/dist/predictors.d.cts +1 -1
  197. package/dist/predictors.d.ts +1 -1
  198. package/dist/read.cjs +287 -72
  199. package/dist/read.d.cts +2 -4
  200. package/dist/read.d.ts +2 -4
  201. package/dist/read.js +284 -67
  202. package/dist/serialize.cjs +5 -1
  203. package/dist/serialize.d.cts +3 -2
  204. package/dist/serialize.d.ts +3 -2
  205. package/dist/serialize.js +5 -2
  206. package/dist/sfnt-subset.cjs +10 -3
  207. package/dist/sfnt-subset.d.cts +1 -1
  208. package/dist/sfnt-subset.d.ts +1 -1
  209. package/dist/sfnt-subset.js +10 -3
  210. package/dist/structure.cjs +184 -0
  211. package/dist/structure.d.cts +12 -0
  212. package/dist/structure.d.ts +12 -0
  213. package/dist/structure.js +183 -0
  214. package/dist/tounicode.cjs +8 -3
  215. package/dist/tounicode.d.cts +2 -2
  216. package/dist/tounicode.d.ts +2 -2
  217. package/dist/tounicode.js +8 -3
  218. package/dist/util/base64.cjs +4 -4
  219. package/dist/util/base64.js +4 -4
  220. package/dist/winansi.cjs +1 -1
  221. package/dist/winansi.d.cts +1 -1
  222. package/dist/winansi.d.ts +1 -1
  223. package/dist/winansi.js +1 -1
  224. package/dist/write.cjs +464 -21
  225. package/dist/write.d.cts +4 -3
  226. package/dist/write.d.ts +4 -3
  227. package/dist/write.js +464 -20
  228. package/dist/xmp.cjs +46 -0
  229. package/dist/xmp.d.cts +14 -0
  230. package/dist/xmp.d.ts +14 -0
  231. package/dist/xmp.js +45 -0
  232. package/dist/xref.cjs +2 -2
  233. package/dist/xref.d.cts +3 -3
  234. package/dist/xref.d.ts +3 -3
  235. package/dist/xref.js +2 -2
  236. package/package.json +46 -31
  237. package/dist/image/png-encode.cjs +0 -64
  238. package/dist/image/png-encode.d.cts +0 -8
  239. package/dist/image/png-encode.d.ts +0 -8
  240. package/dist/image/png-encode.js +0 -63
package/dist/encrypt.cjs CHANGED
@@ -1,11 +1,11 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_objects = require("./objects.cjs");
2
3
  const require_bytes_writer = require("./bytes/writer.cjs");
3
4
  const require_diagnostics = require("./diagnostics.cjs");
4
5
  const require_crypto_aes = require("./crypto/aes.cjs");
5
6
  const require_crypto_md5 = require("./crypto/md5.cjs");
6
7
  const require_crypto_rc4 = require("./crypto/rc4.cjs");
7
8
  const require_crypto_sha2 = require("./crypto/sha2.cjs");
8
- const require_objects = require("./objects.cjs");
9
9
  //#region src/encrypt.ts
10
10
  const PASSWORD_PADDING = new Uint8Array([
11
11
  40,
@@ -50,11 +50,12 @@ const AES_OBJECT_KEY_SALT = new Uint8Array([
50
50
  const MD5_DIGEST_BYTES = 16;
51
51
  const OBJECT_KEY_EXTRA_BYTES = 5;
52
52
  const LEGACY_KEY_ITERATIONS = 50;
53
- const ALGORITHM_5_ITERATIONS = 19;
53
+ const RC4_OBFUSCATION_ROUNDS = 19;
54
54
  const R6_MINIMUM_ROUNDS = 64;
55
55
  const R6_ROUND_REPEATS = 64;
56
56
  const R6_TERMINATION_MARGIN = 32;
57
57
  const AESV3_KEY_BYTES = 32;
58
+ const AESV3_SALT_BYTES = 8;
58
59
  const RC4_40_KEY_BYTES = 5;
59
60
  const AESV2_KEY_BYTES = 16;
60
61
  const DEFAULT_KEY_BITS = 40;
@@ -80,11 +81,16 @@ function permissionsBytes(p) {
80
81
  unsigned >>> 24 & 255
81
82
  ]);
82
83
  }
83
- function computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMetadata) {
84
- const owner = requireStringBytes(encryptDict, "O");
85
- const permissions = require_objects.asNumber(require_objects.dictGet(encryptDict, "P")) ?? 0;
84
+ function padOrTruncatePassword(password) {
85
+ if (password.length >= PASSWORD_PADDING.length) return password.subarray(0, PASSWORD_PADDING.length);
86
+ const padded = new Uint8Array(PASSWORD_PADDING.length);
87
+ padded.set(password);
88
+ padded.set(PASSWORD_PADDING.subarray(0, PASSWORD_PADDING.length - password.length), password.length);
89
+ return padded;
90
+ }
91
+ function computeLegacyFileKeyFromPaddedPassword(paddedPassword, owner, permissions, fileId, revision, keyBytes, encryptMetadata) {
86
92
  const parts = [
87
- PASSWORD_PADDING,
93
+ paddedPassword,
88
94
  owner.subarray(0, PASSWORD_PADDING.length),
89
95
  permissionsBytes(permissions),
90
96
  fileId
@@ -96,18 +102,26 @@ function computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMe
96
102
  255
97
103
  ]));
98
104
  let digest = require_crypto_md5.md5(require_bytes_writer.concatBytes(parts));
99
- if (revision >= 3) for (let i = 0; i < LEGACY_KEY_ITERATIONS; i++) digest = require_crypto_md5.md5(digest.subarray(0, keyBytes));
105
+ if (revision >= 3) for (let i = 0; i < 50; i++) digest = require_crypto_md5.md5(digest.subarray(0, keyBytes));
100
106
  return digest.subarray(0, keyBytes);
101
107
  }
102
- function legacyUserPasswordVerifies(encryptDict, fileId, revision, fileKey) {
103
- const storedUser = requireStringBytes(encryptDict, "U");
104
- if (revision === 2) return bytesEqual(require_crypto_rc4.rc4(fileKey, PASSWORD_PADDING), storedUser, PASSWORD_PADDING.length);
108
+ function computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMetadata) {
109
+ const owner = requireStringBytes(encryptDict, "O");
110
+ const permissions = require_objects.asNumber(require_objects.dictGet(encryptDict, "P")) ?? 0;
111
+ return computeLegacyFileKeyFromPaddedPassword(PASSWORD_PADDING, owner, permissions, fileId, revision, keyBytes, encryptMetadata);
112
+ }
113
+ function legacyUserValueCore(fileKey, fileId, revision) {
114
+ if (revision === 2) return require_crypto_rc4.rc4(fileKey, PASSWORD_PADDING);
105
115
  let value = require_crypto_rc4.rc4(fileKey, require_crypto_md5.md5(require_bytes_writer.concatBytes([PASSWORD_PADDING, fileId])));
106
- for (let i = 1; i <= ALGORITHM_5_ITERATIONS; i++) {
116
+ for (let i = 1; i <= 19; i++) {
107
117
  const roundKey = Uint8Array.from(fileKey, (byte) => byte ^ i);
108
118
  value = require_crypto_rc4.rc4(roundKey, value);
109
119
  }
110
- return bytesEqual(value, storedUser, MD5_DIGEST_BYTES);
120
+ return value;
121
+ }
122
+ function legacyUserPasswordVerifies(encryptDict, fileId, revision, fileKey) {
123
+ const storedUser = requireStringBytes(encryptDict, "U");
124
+ return bytesEqual(legacyUserValueCore(fileKey, fileId, revision), storedUser, revision === 2 ? PASSWORD_PADDING.length : 16);
111
125
  }
112
126
  function hardenedHash(password, salt, userData, revision) {
113
127
  let k = require_crypto_sha2.sha256(require_bytes_writer.concatBytes([
@@ -133,20 +147,20 @@ function hardenedHash(password, salt, userData, revision) {
133
147
  k = selector === 0 ? require_crypto_sha2.sha256(e) : selector === 1 ? require_crypto_sha2.sha384(e) : require_crypto_sha2.sha512(e);
134
148
  round++;
135
149
  }
136
- return k.subarray(0, AESV3_KEY_BYTES);
150
+ return k.subarray(0, 32);
137
151
  }
138
152
  function computeAesV3FileKey(encryptDict, revision) {
139
153
  const storedUser = requireStringBytes(encryptDict, "U");
140
154
  const expectedLength = 48;
141
155
  if (storedUser.length < expectedLength) throw new require_diagnostics.PdfEncryptedError(`the /Encrypt dictionary's /U entry is ${String(storedUser.length)} bytes; revision ${String(revision)} requires ${String(expectedLength)}`);
142
156
  const empty = /* @__PURE__ */ new Uint8Array(0);
143
- const validationSalt = storedUser.subarray(AESV3_KEY_BYTES, 40);
157
+ const validationSalt = storedUser.subarray(32, 40);
144
158
  const keySalt = storedUser.subarray(40, expectedLength);
145
- if (!bytesEqual(hardenedHash(empty, validationSalt, empty, revision), storedUser, AESV3_KEY_BYTES)) throw new require_diagnostics.PdfPasswordRequiredError();
159
+ if (!bytesEqual(hardenedHash(empty, validationSalt, empty, revision), storedUser, 32)) throw new require_diagnostics.PdfPasswordRequiredError();
146
160
  const intermediateKey = hardenedHash(empty, keySalt, empty, revision);
147
161
  const wrappedKey = requireStringBytes(encryptDict, "UE");
148
- if (wrappedKey.length < AESV3_KEY_BYTES) throw new require_diagnostics.PdfEncryptedError(`the /Encrypt dictionary's /UE entry is ${String(wrappedKey.length)} bytes; revision ${String(revision)} requires ${String(AESV3_KEY_BYTES)}`);
149
- return require_crypto_aes.aesCbcDecrypt(intermediateKey, ZERO_IV, wrappedKey.subarray(0, AESV3_KEY_BYTES));
162
+ if (wrappedKey.length < 32) throw new require_diagnostics.PdfEncryptedError(`the /Encrypt dictionary's /UE entry is ${String(wrappedKey.length)} bytes; revision ${String(revision)} requires ${String(32)}`);
163
+ return require_crypto_aes.aesCbcDecrypt(intermediateKey, ZERO_IV, wrappedKey.subarray(0, 32));
150
164
  }
151
165
  function methodFromCryptFilterName(encryptDict, entryKey) {
152
166
  const name = require_objects.asName(require_objects.dictGet(encryptDict, entryKey)) ?? "Identity";
@@ -164,7 +178,7 @@ function cryptFilterKeyBytes(encryptDict, declaredBits) {
164
178
  const streamFilterName = require_objects.asName(require_objects.dictGet(encryptDict, "StmF")) ?? "Identity";
165
179
  const filters = require_objects.asDict(require_objects.dictGet(encryptDict, "CF"));
166
180
  const filter = filters !== void 0 ? require_objects.asDict(require_objects.dictGet(filters, streamFilterName)) : void 0;
167
- if ((filter !== void 0 ? require_objects.asName(require_objects.dictGet(filter, "CFM")) : void 0) === "AESV2") return AESV2_KEY_BYTES;
181
+ if ((filter !== void 0 ? require_objects.asName(require_objects.dictGet(filter, "CFM")) : void 0) === "AESV2") return 16;
168
182
  const declared = filter !== void 0 ? require_objects.asNumber(require_objects.dictGet(filter, "Length")) : void 0;
169
183
  if (declared === void 0) return Math.floor(declaredBits / BITS_PER_BYTE);
170
184
  return declared >= DEFAULT_KEY_BITS ? Math.floor(declared / BITS_PER_BYTE) : declared;
@@ -189,8 +203,8 @@ function setUpHandler(encryptDict, fileId) {
189
203
  if (revision < 2 || revision > 4) throw new require_diagnostics.PdfEncryptedError(`unsupported standard security handler revision /R ${String(revision)}`);
190
204
  const streamMethod = version === 4 ? methodFromCryptFilterName(encryptDict, "StmF") : "rc4";
191
205
  const stringMethod = version === 4 ? methodFromCryptFilterName(encryptDict, "StrF") : "rc4";
192
- const keyBytes = version === 1 ? RC4_40_KEY_BYTES : version === 2 ? Math.floor(declaredBits / BITS_PER_BYTE) : cryptFilterKeyBytes(encryptDict, declaredBits);
193
- if (keyBytes < RC4_40_KEY_BYTES || keyBytes > MAX_RC4_KEY_BYTES) throw new require_diagnostics.PdfEncryptedError(`the /Encrypt dictionary declares a ${String(keyBytes * BITS_PER_BYTE)}-bit file key, outside the 40-128 bit range /V ${String(version)} permits`);
206
+ const keyBytes = version === 1 ? 5 : version === 2 ? Math.floor(declaredBits / BITS_PER_BYTE) : cryptFilterKeyBytes(encryptDict, declaredBits);
207
+ if (keyBytes < 5 || keyBytes > MAX_RC4_KEY_BYTES) throw new require_diagnostics.PdfEncryptedError(`the /Encrypt dictionary declares a ${String(keyBytes * BITS_PER_BYTE)}-bit file key, outside the 40-128 bit range /V ${String(version)} permits`);
194
208
  const fileKey = computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMetadata);
195
209
  if (!legacyUserPasswordVerifies(encryptDict, fileId, revision, fileKey)) throw new require_diagnostics.PdfPasswordRequiredError();
196
210
  return {
@@ -212,7 +226,7 @@ function objectKey(fileKey, num, gen, method) {
212
226
  fileKey,
213
227
  extra,
214
228
  AES_OBJECT_KEY_SALT
215
- ] : [fileKey, extra])).subarray(0, Math.min(fileKey.length + OBJECT_KEY_EXTRA_BYTES, MD5_DIGEST_BYTES));
229
+ ] : [fileKey, extra])).subarray(0, Math.min(fileKey.length + OBJECT_KEY_EXTRA_BYTES, 16));
216
230
  }
217
231
  function decryptAes(key, data, sink) {
218
232
  if (data.length <= 16) {
@@ -261,4 +275,20 @@ function createStandardDecryptor(encryptDict, fileId, sink) {
261
275
  };
262
276
  }
263
277
  //#endregion
278
+ exports.AESV2_KEY_BYTES = AESV2_KEY_BYTES;
279
+ exports.AESV3_KEY_BYTES = AESV3_KEY_BYTES;
280
+ exports.AESV3_SALT_BYTES = AESV3_SALT_BYTES;
281
+ exports.AES_OBJECT_KEY_SALT = AES_OBJECT_KEY_SALT;
282
+ exports.LEGACY_KEY_ITERATIONS = LEGACY_KEY_ITERATIONS;
283
+ exports.MD5_DIGEST_BYTES = MD5_DIGEST_BYTES;
284
+ exports.PASSWORD_PADDING = PASSWORD_PADDING;
285
+ exports.RC4_40_KEY_BYTES = RC4_40_KEY_BYTES;
286
+ exports.RC4_OBFUSCATION_ROUNDS = RC4_OBFUSCATION_ROUNDS;
287
+ exports.ZERO_IV = ZERO_IV;
288
+ exports.computeLegacyFileKeyFromPaddedPassword = computeLegacyFileKeyFromPaddedPassword;
264
289
  exports.createStandardDecryptor = createStandardDecryptor;
290
+ exports.hardenedHash = hardenedHash;
291
+ exports.legacyUserValueCore = legacyUserValueCore;
292
+ exports.objectKey = objectKey;
293
+ exports.padOrTruncatePassword = padOrTruncatePassword;
294
+ exports.permissionsBytes = permissionsBytes;
@@ -1,11 +1,27 @@
1
1
  import { PdfDiagnosticSink } from "./diagnostics.cjs";
2
- import { PdfDict } from "./objects.cjs";
2
+ import { n as PdfDict } from "./objects-B7HdMeWS.cjs";
3
3
  //#region src/encrypt.d.ts
4
- type CipherMethod = 'identity' | 'rc4' | 'aes';
4
+ type CipherMethod = "identity" | "rc4" | "aes";
5
5
  interface PdfDecryptor {
6
6
  decryptString(bytes: Uint8Array<ArrayBuffer>, num: number, gen: number): Uint8Array<ArrayBuffer>;
7
7
  decryptStream(bytes: Uint8Array<ArrayBuffer>, dict: PdfDict, num: number, gen: number): Uint8Array<ArrayBuffer>;
8
8
  }
9
+ declare const PASSWORD_PADDING: Uint8Array<ArrayBuffer>;
10
+ declare const AES_OBJECT_KEY_SALT: Uint8Array<ArrayBuffer>;
11
+ declare const MD5_DIGEST_BYTES = 16;
12
+ declare const LEGACY_KEY_ITERATIONS = 50;
13
+ declare const RC4_OBFUSCATION_ROUNDS = 19;
14
+ declare const AESV3_KEY_BYTES = 32;
15
+ declare const AESV3_SALT_BYTES = 8;
16
+ declare const RC4_40_KEY_BYTES = 5;
17
+ declare const AESV2_KEY_BYTES = 16;
18
+ declare const ZERO_IV: Uint8Array<ArrayBuffer>;
19
+ declare function permissionsBytes(p: number): Uint8Array<ArrayBuffer>;
20
+ declare function padOrTruncatePassword(password: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>;
21
+ declare function computeLegacyFileKeyFromPaddedPassword(paddedPassword: Uint8Array<ArrayBuffer>, owner: Uint8Array<ArrayBuffer>, permissions: number, fileId: Uint8Array<ArrayBuffer>, revision: number, keyBytes: number, encryptMetadata: boolean): Uint8Array<ArrayBuffer>;
22
+ declare function legacyUserValueCore(fileKey: Uint8Array<ArrayBuffer>, fileId: Uint8Array<ArrayBuffer>, revision: number): Uint8Array<ArrayBuffer>;
23
+ declare function hardenedHash(password: Uint8Array<ArrayBuffer>, salt: Uint8Array<ArrayBuffer>, userData: Uint8Array<ArrayBuffer>, revision: number): Uint8Array<ArrayBuffer>;
24
+ declare function objectKey(fileKey: Uint8Array<ArrayBuffer>, num: number, gen: number, method: CipherMethod): Uint8Array<ArrayBuffer>;
9
25
  declare function createStandardDecryptor(encryptDict: PdfDict, fileId: Uint8Array<ArrayBuffer>, sink: PdfDiagnosticSink): PdfDecryptor;
10
26
  //#endregion
11
- export { CipherMethod, PdfDecryptor, createStandardDecryptor };
27
+ export { AESV2_KEY_BYTES, AESV3_KEY_BYTES, AESV3_SALT_BYTES, AES_OBJECT_KEY_SALT, CipherMethod, LEGACY_KEY_ITERATIONS, MD5_DIGEST_BYTES, PASSWORD_PADDING, PdfDecryptor, RC4_40_KEY_BYTES, RC4_OBFUSCATION_ROUNDS, ZERO_IV, computeLegacyFileKeyFromPaddedPassword, createStandardDecryptor, hardenedHash, legacyUserValueCore, objectKey, padOrTruncatePassword, permissionsBytes };
package/dist/encrypt.d.ts CHANGED
@@ -1,11 +1,27 @@
1
1
  import { PdfDiagnosticSink } from "./diagnostics.js";
2
- import { PdfDict } from "./objects.js";
2
+ import { n as PdfDict } from "./objects-B7HdMeWS.js";
3
3
  //#region src/encrypt.d.ts
4
- type CipherMethod = 'identity' | 'rc4' | 'aes';
4
+ type CipherMethod = "identity" | "rc4" | "aes";
5
5
  interface PdfDecryptor {
6
6
  decryptString(bytes: Uint8Array<ArrayBuffer>, num: number, gen: number): Uint8Array<ArrayBuffer>;
7
7
  decryptStream(bytes: Uint8Array<ArrayBuffer>, dict: PdfDict, num: number, gen: number): Uint8Array<ArrayBuffer>;
8
8
  }
9
+ declare const PASSWORD_PADDING: Uint8Array<ArrayBuffer>;
10
+ declare const AES_OBJECT_KEY_SALT: Uint8Array<ArrayBuffer>;
11
+ declare const MD5_DIGEST_BYTES = 16;
12
+ declare const LEGACY_KEY_ITERATIONS = 50;
13
+ declare const RC4_OBFUSCATION_ROUNDS = 19;
14
+ declare const AESV3_KEY_BYTES = 32;
15
+ declare const AESV3_SALT_BYTES = 8;
16
+ declare const RC4_40_KEY_BYTES = 5;
17
+ declare const AESV2_KEY_BYTES = 16;
18
+ declare const ZERO_IV: Uint8Array<ArrayBuffer>;
19
+ declare function permissionsBytes(p: number): Uint8Array<ArrayBuffer>;
20
+ declare function padOrTruncatePassword(password: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>;
21
+ declare function computeLegacyFileKeyFromPaddedPassword(paddedPassword: Uint8Array<ArrayBuffer>, owner: Uint8Array<ArrayBuffer>, permissions: number, fileId: Uint8Array<ArrayBuffer>, revision: number, keyBytes: number, encryptMetadata: boolean): Uint8Array<ArrayBuffer>;
22
+ declare function legacyUserValueCore(fileKey: Uint8Array<ArrayBuffer>, fileId: Uint8Array<ArrayBuffer>, revision: number): Uint8Array<ArrayBuffer>;
23
+ declare function hardenedHash(password: Uint8Array<ArrayBuffer>, salt: Uint8Array<ArrayBuffer>, userData: Uint8Array<ArrayBuffer>, revision: number): Uint8Array<ArrayBuffer>;
24
+ declare function objectKey(fileKey: Uint8Array<ArrayBuffer>, num: number, gen: number, method: CipherMethod): Uint8Array<ArrayBuffer>;
9
25
  declare function createStandardDecryptor(encryptDict: PdfDict, fileId: Uint8Array<ArrayBuffer>, sink: PdfDiagnosticSink): PdfDecryptor;
10
26
  //#endregion
11
- export { CipherMethod, PdfDecryptor, createStandardDecryptor };
27
+ export { AESV2_KEY_BYTES, AESV3_KEY_BYTES, AESV3_SALT_BYTES, AES_OBJECT_KEY_SALT, CipherMethod, LEGACY_KEY_ITERATIONS, MD5_DIGEST_BYTES, PASSWORD_PADDING, PdfDecryptor, RC4_40_KEY_BYTES, RC4_OBFUSCATION_ROUNDS, ZERO_IV, computeLegacyFileKeyFromPaddedPassword, createStandardDecryptor, hardenedHash, legacyUserValueCore, objectKey, padOrTruncatePassword, permissionsBytes };
package/dist/encrypt.js CHANGED
@@ -1,10 +1,10 @@
1
+ import { asDict, asName, asNumber, dictGet } from "./objects.js";
1
2
  import { concatBytes } from "./bytes/writer.js";
2
3
  import { PdfEncryptedError, PdfPasswordRequiredError } from "./diagnostics.js";
3
4
  import { aesCbcDecrypt, aesCbcEncrypt } from "./crypto/aes.js";
4
5
  import { md5 } from "./crypto/md5.js";
5
6
  import { rc4 } from "./crypto/rc4.js";
6
7
  import { sha256, sha384, sha512 } from "./crypto/sha2.js";
7
- import { asDict, asName, asNumber, dictGet } from "./objects.js";
8
8
  //#region src/encrypt.ts
9
9
  const PASSWORD_PADDING = new Uint8Array([
10
10
  40,
@@ -49,11 +49,12 @@ const AES_OBJECT_KEY_SALT = new Uint8Array([
49
49
  const MD5_DIGEST_BYTES = 16;
50
50
  const OBJECT_KEY_EXTRA_BYTES = 5;
51
51
  const LEGACY_KEY_ITERATIONS = 50;
52
- const ALGORITHM_5_ITERATIONS = 19;
52
+ const RC4_OBFUSCATION_ROUNDS = 19;
53
53
  const R6_MINIMUM_ROUNDS = 64;
54
54
  const R6_ROUND_REPEATS = 64;
55
55
  const R6_TERMINATION_MARGIN = 32;
56
56
  const AESV3_KEY_BYTES = 32;
57
+ const AESV3_SALT_BYTES = 8;
57
58
  const RC4_40_KEY_BYTES = 5;
58
59
  const AESV2_KEY_BYTES = 16;
59
60
  const DEFAULT_KEY_BITS = 40;
@@ -79,11 +80,16 @@ function permissionsBytes(p) {
79
80
  unsigned >>> 24 & 255
80
81
  ]);
81
82
  }
82
- function computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMetadata) {
83
- const owner = requireStringBytes(encryptDict, "O");
84
- const permissions = asNumber(dictGet(encryptDict, "P")) ?? 0;
83
+ function padOrTruncatePassword(password) {
84
+ if (password.length >= PASSWORD_PADDING.length) return password.subarray(0, PASSWORD_PADDING.length);
85
+ const padded = new Uint8Array(PASSWORD_PADDING.length);
86
+ padded.set(password);
87
+ padded.set(PASSWORD_PADDING.subarray(0, PASSWORD_PADDING.length - password.length), password.length);
88
+ return padded;
89
+ }
90
+ function computeLegacyFileKeyFromPaddedPassword(paddedPassword, owner, permissions, fileId, revision, keyBytes, encryptMetadata) {
85
91
  const parts = [
86
- PASSWORD_PADDING,
92
+ paddedPassword,
87
93
  owner.subarray(0, PASSWORD_PADDING.length),
88
94
  permissionsBytes(permissions),
89
95
  fileId
@@ -95,18 +101,26 @@ function computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMe
95
101
  255
96
102
  ]));
97
103
  let digest = md5(concatBytes(parts));
98
- if (revision >= 3) for (let i = 0; i < LEGACY_KEY_ITERATIONS; i++) digest = md5(digest.subarray(0, keyBytes));
104
+ if (revision >= 3) for (let i = 0; i < 50; i++) digest = md5(digest.subarray(0, keyBytes));
99
105
  return digest.subarray(0, keyBytes);
100
106
  }
101
- function legacyUserPasswordVerifies(encryptDict, fileId, revision, fileKey) {
102
- const storedUser = requireStringBytes(encryptDict, "U");
103
- if (revision === 2) return bytesEqual(rc4(fileKey, PASSWORD_PADDING), storedUser, PASSWORD_PADDING.length);
107
+ function computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMetadata) {
108
+ const owner = requireStringBytes(encryptDict, "O");
109
+ const permissions = asNumber(dictGet(encryptDict, "P")) ?? 0;
110
+ return computeLegacyFileKeyFromPaddedPassword(PASSWORD_PADDING, owner, permissions, fileId, revision, keyBytes, encryptMetadata);
111
+ }
112
+ function legacyUserValueCore(fileKey, fileId, revision) {
113
+ if (revision === 2) return rc4(fileKey, PASSWORD_PADDING);
104
114
  let value = rc4(fileKey, md5(concatBytes([PASSWORD_PADDING, fileId])));
105
- for (let i = 1; i <= ALGORITHM_5_ITERATIONS; i++) {
115
+ for (let i = 1; i <= 19; i++) {
106
116
  const roundKey = Uint8Array.from(fileKey, (byte) => byte ^ i);
107
117
  value = rc4(roundKey, value);
108
118
  }
109
- return bytesEqual(value, storedUser, MD5_DIGEST_BYTES);
119
+ return value;
120
+ }
121
+ function legacyUserPasswordVerifies(encryptDict, fileId, revision, fileKey) {
122
+ const storedUser = requireStringBytes(encryptDict, "U");
123
+ return bytesEqual(legacyUserValueCore(fileKey, fileId, revision), storedUser, revision === 2 ? PASSWORD_PADDING.length : 16);
110
124
  }
111
125
  function hardenedHash(password, salt, userData, revision) {
112
126
  let k = sha256(concatBytes([
@@ -132,20 +146,20 @@ function hardenedHash(password, salt, userData, revision) {
132
146
  k = selector === 0 ? sha256(e) : selector === 1 ? sha384(e) : sha512(e);
133
147
  round++;
134
148
  }
135
- return k.subarray(0, AESV3_KEY_BYTES);
149
+ return k.subarray(0, 32);
136
150
  }
137
151
  function computeAesV3FileKey(encryptDict, revision) {
138
152
  const storedUser = requireStringBytes(encryptDict, "U");
139
153
  const expectedLength = 48;
140
154
  if (storedUser.length < expectedLength) throw new PdfEncryptedError(`the /Encrypt dictionary's /U entry is ${String(storedUser.length)} bytes; revision ${String(revision)} requires ${String(expectedLength)}`);
141
155
  const empty = /* @__PURE__ */ new Uint8Array(0);
142
- const validationSalt = storedUser.subarray(AESV3_KEY_BYTES, 40);
156
+ const validationSalt = storedUser.subarray(32, 40);
143
157
  const keySalt = storedUser.subarray(40, expectedLength);
144
- if (!bytesEqual(hardenedHash(empty, validationSalt, empty, revision), storedUser, AESV3_KEY_BYTES)) throw new PdfPasswordRequiredError();
158
+ if (!bytesEqual(hardenedHash(empty, validationSalt, empty, revision), storedUser, 32)) throw new PdfPasswordRequiredError();
145
159
  const intermediateKey = hardenedHash(empty, keySalt, empty, revision);
146
160
  const wrappedKey = requireStringBytes(encryptDict, "UE");
147
- if (wrappedKey.length < AESV3_KEY_BYTES) throw new PdfEncryptedError(`the /Encrypt dictionary's /UE entry is ${String(wrappedKey.length)} bytes; revision ${String(revision)} requires ${String(AESV3_KEY_BYTES)}`);
148
- return aesCbcDecrypt(intermediateKey, ZERO_IV, wrappedKey.subarray(0, AESV3_KEY_BYTES));
161
+ if (wrappedKey.length < 32) throw new PdfEncryptedError(`the /Encrypt dictionary's /UE entry is ${String(wrappedKey.length)} bytes; revision ${String(revision)} requires ${String(32)}`);
162
+ return aesCbcDecrypt(intermediateKey, ZERO_IV, wrappedKey.subarray(0, 32));
149
163
  }
150
164
  function methodFromCryptFilterName(encryptDict, entryKey) {
151
165
  const name = asName(dictGet(encryptDict, entryKey)) ?? "Identity";
@@ -163,7 +177,7 @@ function cryptFilterKeyBytes(encryptDict, declaredBits) {
163
177
  const streamFilterName = asName(dictGet(encryptDict, "StmF")) ?? "Identity";
164
178
  const filters = asDict(dictGet(encryptDict, "CF"));
165
179
  const filter = filters !== void 0 ? asDict(dictGet(filters, streamFilterName)) : void 0;
166
- if ((filter !== void 0 ? asName(dictGet(filter, "CFM")) : void 0) === "AESV2") return AESV2_KEY_BYTES;
180
+ if ((filter !== void 0 ? asName(dictGet(filter, "CFM")) : void 0) === "AESV2") return 16;
167
181
  const declared = filter !== void 0 ? asNumber(dictGet(filter, "Length")) : void 0;
168
182
  if (declared === void 0) return Math.floor(declaredBits / BITS_PER_BYTE);
169
183
  return declared >= DEFAULT_KEY_BITS ? Math.floor(declared / BITS_PER_BYTE) : declared;
@@ -188,8 +202,8 @@ function setUpHandler(encryptDict, fileId) {
188
202
  if (revision < 2 || revision > 4) throw new PdfEncryptedError(`unsupported standard security handler revision /R ${String(revision)}`);
189
203
  const streamMethod = version === 4 ? methodFromCryptFilterName(encryptDict, "StmF") : "rc4";
190
204
  const stringMethod = version === 4 ? methodFromCryptFilterName(encryptDict, "StrF") : "rc4";
191
- const keyBytes = version === 1 ? RC4_40_KEY_BYTES : version === 2 ? Math.floor(declaredBits / BITS_PER_BYTE) : cryptFilterKeyBytes(encryptDict, declaredBits);
192
- if (keyBytes < RC4_40_KEY_BYTES || keyBytes > MAX_RC4_KEY_BYTES) throw new PdfEncryptedError(`the /Encrypt dictionary declares a ${String(keyBytes * BITS_PER_BYTE)}-bit file key, outside the 40-128 bit range /V ${String(version)} permits`);
205
+ const keyBytes = version === 1 ? 5 : version === 2 ? Math.floor(declaredBits / BITS_PER_BYTE) : cryptFilterKeyBytes(encryptDict, declaredBits);
206
+ if (keyBytes < 5 || keyBytes > MAX_RC4_KEY_BYTES) throw new PdfEncryptedError(`the /Encrypt dictionary declares a ${String(keyBytes * BITS_PER_BYTE)}-bit file key, outside the 40-128 bit range /V ${String(version)} permits`);
193
207
  const fileKey = computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMetadata);
194
208
  if (!legacyUserPasswordVerifies(encryptDict, fileId, revision, fileKey)) throw new PdfPasswordRequiredError();
195
209
  return {
@@ -211,7 +225,7 @@ function objectKey(fileKey, num, gen, method) {
211
225
  fileKey,
212
226
  extra,
213
227
  AES_OBJECT_KEY_SALT
214
- ] : [fileKey, extra])).subarray(0, Math.min(fileKey.length + OBJECT_KEY_EXTRA_BYTES, MD5_DIGEST_BYTES));
228
+ ] : [fileKey, extra])).subarray(0, Math.min(fileKey.length + OBJECT_KEY_EXTRA_BYTES, 16));
215
229
  }
216
230
  function decryptAes(key, data, sink) {
217
231
  if (data.length <= 16) {
@@ -260,4 +274,4 @@ function createStandardDecryptor(encryptDict, fileId, sink) {
260
274
  };
261
275
  }
262
276
  //#endregion
263
- export { createStandardDecryptor };
277
+ export { AESV2_KEY_BYTES, AESV3_KEY_BYTES, AESV3_SALT_BYTES, AES_OBJECT_KEY_SALT, LEGACY_KEY_ITERATIONS, MD5_DIGEST_BYTES, PASSWORD_PADDING, RC4_40_KEY_BYTES, RC4_OBFUSCATION_ROUNDS, ZERO_IV, computeLegacyFileKeyFromPaddedPassword, createStandardDecryptor, hardenedHash, legacyUserValueCore, objectKey, padOrTruncatePassword, permissionsBytes };
package/dist/filters.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_bytes_reader = require("./bytes/reader.cjs");
3
2
  const require_objects = require("./objects.cjs");
3
+ const require_bytes_reader = require("./bytes/reader.cjs");
4
4
  const require_bytes_flate = require("./bytes/flate.cjs");
5
5
  const require_image_ccitt = require("./image/ccitt.cjs");
6
6
  const require_image_jbig2 = require("./image/jbig2.cjs");
@@ -62,11 +62,13 @@ function ccittFaxDecode(data, parm, dict, sink) {
62
62
  rows,
63
63
  blackIs1: require_objects.asBool(parmGet("BlackIs1")),
64
64
  encodedByteAlign: require_objects.asBool(parmGet("EncodedByteAlign")),
65
- onWarning: (message) => sink({
66
- code: "pdf/ccitt-fax-degraded",
67
- severity: "warning",
68
- message
69
- })
65
+ onWarning: (message) => {
66
+ sink({
67
+ code: "pdf/ccitt-fax-degraded",
68
+ severity: "warning",
69
+ message
70
+ });
71
+ }
70
72
  }).bytes;
71
73
  }
72
74
  function jbig2Decode(data, parm, dict, sink, resolve) {
@@ -84,11 +86,13 @@ function jbig2Decode(data, parm, dict, sink, resolve) {
84
86
  globals,
85
87
  width: require_objects.asNumber(require_objects.dictGet(dict, "Width") ?? require_objects.dictGet(dict, "W")),
86
88
  height: require_objects.asNumber(require_objects.dictGet(dict, "Height") ?? require_objects.dictGet(dict, "H")),
87
- onWarning: (message) => sink({
88
- code: "pdf/jbig2-degraded",
89
- severity: "warning",
90
- message
91
- })
89
+ onWarning: (message) => {
90
+ sink({
91
+ code: "pdf/jbig2-degraded",
92
+ severity: "warning",
93
+ message
94
+ });
95
+ }
92
96
  });
93
97
  return Uint8Array.from(image.bytes, (byte) => byte ^ 255);
94
98
  } catch (error) {
@@ -188,9 +192,9 @@ function lzwDecode(data, earlyChange, sink) {
188
192
  if (prevEntry !== void 0) {
189
193
  dict[nextCode] = concatTwo(prevEntry, new Uint8Array([entry[0] ?? 0]));
190
194
  nextCode++;
191
- if (nextCode + bias === 2 ** 9) codeWidth = 10;
192
- else if (nextCode + bias === 2 ** 10) codeWidth = 11;
193
- else if (nextCode + bias === 2 ** 11) codeWidth = 12;
195
+ if (nextCode + bias === 512) codeWidth = 10;
196
+ else if (nextCode + bias === 1024) codeWidth = 11;
197
+ else if (nextCode + bias === 2048) codeWidth = 12;
194
198
  }
195
199
  prevEntry = entry;
196
200
  }
@@ -1,5 +1,5 @@
1
1
  import { PdfDiagnosticSink } from "./diagnostics.cjs";
2
- import { PdfDict, PdfObject } from "./objects.cjs";
2
+ import { n as PdfDict, r as PdfObject } from "./objects-B7HdMeWS.cjs";
3
3
  //#region src/filters.d.ts
4
4
  interface DecodedStream {
5
5
  readonly bytes: Uint8Array<ArrayBuffer>;
package/dist/filters.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { PdfDiagnosticSink } from "./diagnostics.js";
2
- import { PdfDict, PdfObject } from "./objects.js";
2
+ import { n as PdfDict, r as PdfObject } from "./objects-B7HdMeWS.js";
3
3
  //#region src/filters.d.ts
4
4
  interface DecodedStream {
5
5
  readonly bytes: Uint8Array<ArrayBuffer>;
package/dist/filters.js CHANGED
@@ -1,5 +1,5 @@
1
- import { isAsciiWhitespace } from "./bytes/reader.js";
2
1
  import { asArray, asBool, asDict, asName, asNumber, dictGet } from "./objects.js";
2
+ import { isAsciiWhitespace } from "./bytes/reader.js";
3
3
  import { inflateTolerant } from "./bytes/flate.js";
4
4
  import { decodeCcittFax } from "./image/ccitt.js";
5
5
  import { decodeJbig2Embedded } from "./image/jbig2.js";
@@ -61,11 +61,13 @@ function ccittFaxDecode(data, parm, dict, sink) {
61
61
  rows,
62
62
  blackIs1: asBool(parmGet("BlackIs1")),
63
63
  encodedByteAlign: asBool(parmGet("EncodedByteAlign")),
64
- onWarning: (message) => sink({
65
- code: "pdf/ccitt-fax-degraded",
66
- severity: "warning",
67
- message
68
- })
64
+ onWarning: (message) => {
65
+ sink({
66
+ code: "pdf/ccitt-fax-degraded",
67
+ severity: "warning",
68
+ message
69
+ });
70
+ }
69
71
  }).bytes;
70
72
  }
71
73
  function jbig2Decode(data, parm, dict, sink, resolve) {
@@ -83,11 +85,13 @@ function jbig2Decode(data, parm, dict, sink, resolve) {
83
85
  globals,
84
86
  width: asNumber(dictGet(dict, "Width") ?? dictGet(dict, "W")),
85
87
  height: asNumber(dictGet(dict, "Height") ?? dictGet(dict, "H")),
86
- onWarning: (message) => sink({
87
- code: "pdf/jbig2-degraded",
88
- severity: "warning",
89
- message
90
- })
88
+ onWarning: (message) => {
89
+ sink({
90
+ code: "pdf/jbig2-degraded",
91
+ severity: "warning",
92
+ message
93
+ });
94
+ }
91
95
  });
92
96
  return Uint8Array.from(image.bytes, (byte) => byte ^ 255);
93
97
  } catch (error) {
@@ -187,9 +191,9 @@ function lzwDecode(data, earlyChange, sink) {
187
191
  if (prevEntry !== void 0) {
188
192
  dict[nextCode] = concatTwo(prevEntry, new Uint8Array([entry[0] ?? 0]));
189
193
  nextCode++;
190
- if (nextCode + bias === 2 ** 9) codeWidth = 10;
191
- else if (nextCode + bias === 2 ** 10) codeWidth = 11;
192
- else if (nextCode + bias === 2 ** 11) codeWidth = 12;
194
+ if (nextCode + bias === 512) codeWidth = 10;
195
+ else if (nextCode + bias === 1024) codeWidth = 11;
196
+ else if (nextCode + bias === 2048) codeWidth = 12;
193
197
  }
194
198
  prevEntry = entry;
195
199
  }
@@ -1,11 +1,13 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_afm_widths = require("./afm-widths-BoeTOK2r.cjs");
3
- const require_cmap = require("./cmap.cjs");
2
+ const require_afm_widths = require("./afm-widths-BTu0IDp2.cjs");
4
3
  const require_objects = require("./objects.cjs");
5
4
  const require_filters = require("./filters.cjs");
5
+ const require_builtin_encoding = require("./builtin-encoding.cjs");
6
+ const require_cmap = require("./cmap.cjs");
6
7
  const require_fonts = require("./fonts.cjs");
7
8
  const require_font_style = require("./font-style.cjs");
8
9
  //#region src/font-read.ts
10
+ const SYMBOLIC_FLAG_BIT = 4;
9
11
  const ITALIC_FLAG_BIT = 64;
10
12
  const FORCE_BOLD_FLAG_BIT = 1 << 18;
11
13
  const REPLACEMENT_CHARACTER = "�";
@@ -14,14 +16,34 @@ function styleFlagsFromDescriptor(descriptor) {
14
16
  return {
15
17
  forceBold: flags !== void 0 ? (flags & FORCE_BOLD_FLAG_BIT) !== 0 : void 0,
16
18
  italicFlag: flags !== void 0 ? (flags & ITALIC_FLAG_BIT) !== 0 : void 0,
17
- italicAngle: descriptor !== void 0 ? require_objects.asNumber(require_objects.dictGet(descriptor, "ItalicAngle")) : void 0
19
+ italicAngle: descriptor !== void 0 ? require_objects.asNumber(require_objects.dictGet(descriptor, "ItalicAngle")) : void 0,
20
+ symbolic: flags !== void 0 ? (flags & SYMBOLIC_FLAG_BIT) !== 0 : void 0
18
21
  };
19
22
  }
20
- function glyphNameToUnicodeWithUniFallback(name) {
21
- const direct = require_afm_widths.glyphNameToUnicode(name);
22
- if (direct !== void 0) return direct;
23
- const uniMatch = /^uni([0-9A-Fa-f]{4,6})$/.exec(name);
24
- return uniMatch?.[1] !== void 0 ? Number.parseInt(uniMatch[1], 16) : void 0;
23
+ function builtinSymbolGlyphNameLookup(baseFamily) {
24
+ if (baseFamily === "Symbol") return require_afm_widths.symbolGlyphName;
25
+ if (baseFamily === "ZapfDingbats") return require_afm_widths.zapfDingbatsGlyphName;
26
+ }
27
+ function readFontProgram(descriptor, context) {
28
+ if (descriptor === void 0) return;
29
+ for (const key of [
30
+ "FontFile2",
31
+ "FontFile3",
32
+ "FontFile"
33
+ ]) {
34
+ const stream = context.resolver.resolve(require_objects.dictGet(descriptor, key));
35
+ if (stream?.kind !== "stream") continue;
36
+ const decoded = require_filters.decodeStream(stream.raw, stream.dict, context.sink);
37
+ const encoding = require_builtin_encoding.readFontProgramEncoding(decoded.bytes);
38
+ if (encoding !== void 0) return encoding;
39
+ }
40
+ }
41
+ function lazyFontProgram(descriptor, context) {
42
+ let read;
43
+ return () => {
44
+ read ??= { encoding: readFontProgram(descriptor, context) };
45
+ return read.encoding;
46
+ };
25
47
  }
26
48
  function readDifferencesMap(differences) {
27
49
  const map = /* @__PURE__ */ new Map();
@@ -43,7 +65,10 @@ function readToUnicodeCMap(fontDict, context) {
43
65
  function buildSimpleFont(fontDict, context) {
44
66
  const baseFont = require_objects.asName(require_objects.dictGet(fontDict, "BaseFont")) ?? "Helvetica";
45
67
  const descriptor = context.resolver.resolveDict(require_objects.dictGet(fontDict, "FontDescriptor"));
46
- const { baseFamily, bold, italic } = require_font_style.styleFromBaseFontName(baseFont, styleFlagsFromDescriptor(descriptor));
68
+ const styleFlags = styleFlagsFromDescriptor(descriptor);
69
+ const { baseFamily, bold, italic } = require_font_style.styleFromBaseFontName(baseFont, styleFlags);
70
+ const symbolic = styleFlags.symbolic ?? false;
71
+ const builtinGlyphName = builtinSymbolGlyphNameLookup(baseFamily);
47
72
  const widthsArr = require_objects.asArray(require_objects.dictGet(fontDict, "Widths"));
48
73
  const firstChar = require_objects.asNumber(require_objects.dictGet(fontDict, "FirstChar")) ?? 0;
49
74
  const missingWidth = (descriptor !== void 0 ? require_objects.asNumber(require_objects.dictGet(descriptor, "MissingWidth")) : void 0) ?? 0;
@@ -62,12 +87,36 @@ function buildSimpleFont(fontDict, context) {
62
87
  const encodingObj = require_objects.dictGet(fontDict, "Encoding");
63
88
  const encodingDict = context.resolver.resolveDict(encodingObj);
64
89
  const baseEncodingName = require_objects.asName(encodingDict !== void 0 ? require_objects.dictGet(encodingDict, "BaseEncoding") : encodingObj);
65
- if (baseEncodingName !== void 0 && baseEncodingName !== "WinAnsiEncoding") context.sink({
90
+ const namedBaseGlyphName = baseEncodingName !== void 0 ? require_afm_widths.namedEncodingGlyphName(baseEncodingName) : void 0;
91
+ if (baseEncodingName !== void 0 && namedBaseGlyphName === void 0) context.sink({
66
92
  code: "char/encoding-approximated",
67
93
  severity: "info",
68
94
  message: `base encoding "${baseEncodingName}" has no dedicated table here and is approximated as WinAnsiEncoding`
69
95
  });
70
96
  const differencesMap = readDifferencesMap(encodingDict !== void 0 ? require_objects.asArray(require_objects.dictGet(encodingDict, "Differences")) : void 0);
97
+ const programEncoding = lazyFontProgram(descriptor, context);
98
+ const symbolEncoded = symbolic || builtinGlyphName !== void 0;
99
+ const byGlyphName = (source) => (code) => {
100
+ const name = source(code);
101
+ return name === void 0 ? void 0 : require_afm_widths.glyphNameToUnicode(name);
102
+ };
103
+ const fromProgram = (code) => programEncoding()?.codeToUnicode(code);
104
+ const namedBase = namedBaseGlyphName === void 0 ? void 0 : byGlyphName(namedBaseGlyphName);
105
+ const resolvers = [byGlyphName((code) => differencesMap.get(code)), ...symbolEncoded ? [
106
+ fromProgram,
107
+ builtinGlyphName === void 0 ? void 0 : byGlyphName(builtinGlyphName),
108
+ namedBase
109
+ ] : [
110
+ namedBase,
111
+ fromProgram,
112
+ byGlyphName(require_afm_widths.winAnsiGlyphName)
113
+ ]].filter((resolver) => resolver !== void 0);
114
+ const unicodeForCode = (code) => {
115
+ for (const resolve of resolvers) {
116
+ const unicode = resolve(code);
117
+ if (unicode !== void 0) return unicode;
118
+ }
119
+ };
71
120
  const decodeToUnicode = (codes) => {
72
121
  let out = "";
73
122
  let unmapped = 0;
@@ -77,10 +126,9 @@ function buildSimpleFont(fontDict, context) {
77
126
  out += viaToUnicode;
78
127
  continue;
79
128
  }
80
- const name = differencesMap.get(code) ?? require_afm_widths.winAnsiGlyphName(code);
81
- const unicode = name !== void 0 ? glyphNameToUnicodeWithUniFallback(name) : void 0;
129
+ const unicode = unicodeForCode(code);
82
130
  if (unicode !== void 0) {
83
- out += String.fromCharCode(unicode);
131
+ out += String.fromCodePoint(unicode);
84
132
  continue;
85
133
  }
86
134
  unmapped++;
@@ -139,6 +187,8 @@ function buildCompositeFont(fontDict, context) {
139
187
  const widthMap = readCidWidths(descendantDict !== void 0 ? require_objects.asArray(require_objects.dictGet(descendantDict, "W")) : void 0);
140
188
  const widthOf = (cid) => widthMap.get(cid) ?? dw;
141
189
  const toUnicode = readToUnicodeCMap(fontDict, context);
190
+ const cidToGidMap = descendantDict !== void 0 ? require_objects.dictGet(descendantDict, "CIDToGIDMap") : void 0;
191
+ const programEncoding = require_objects.isName(require_objects.dictGet(fontDict, "Encoding"), "Identity-H") && (cidToGidMap === void 0 || require_objects.isName(cidToGidMap, "Identity")) ? lazyFontProgram(descriptor, context) : void 0;
142
192
  const decodeToUnicode = (codes) => {
143
193
  let out = "";
144
194
  let glyphCount = 0;
@@ -151,6 +201,11 @@ function buildCompositeFont(fontDict, context) {
151
201
  out += mapped;
152
202
  continue;
153
203
  }
204
+ const fromProgram = programEncoding?.()?.glyphIdToUnicode(cid);
205
+ if (fromProgram !== void 0) {
206
+ out += String.fromCodePoint(fromProgram);
207
+ continue;
208
+ }
154
209
  unmapped++;
155
210
  out += REPLACEMENT_CHARACTER;
156
211
  }
@@ -1,5 +1,5 @@
1
1
  import { PdfDiagnosticSink } from "./diagnostics.cjs";
2
- import { PdfDict } from "./objects.cjs";
2
+ import { n as PdfDict } from "./objects-B7HdMeWS.cjs";
3
3
  import { FontMetricsPort, PdfObjectResolver } from "./interpret.cjs";
4
4
  //#region src/font-read.d.ts
5
5
  interface PdfFont {