pdf-lite 1.7.2 → 1.7.3-alpha.1

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.
@@ -147,7 +147,7 @@ export class PdfDecoder extends IncrementalParser {
147
147
  const postTokens = this.nextExtraTokens();
148
148
  const stream = new PdfStream({
149
149
  header,
150
- original: concatUint8Arrays(...chunks),
150
+ original: concatUint8Arrays(chunks),
151
151
  });
152
152
  stream.preStreamDataTokens = preStreamTokens;
153
153
  stream.postStreamDataTokens = postStreamDataTokens;
@@ -62,7 +62,7 @@ export class PdfObject {
62
62
  /** Converts the object to a ByteArray, optionally padding to a specified length */
63
63
  toBytes(padTo) {
64
64
  const tokens = this.toTokens();
65
- const byteArray = concatUint8Arrays(...tokens.map((token) => token.toBytes()));
65
+ const byteArray = concatUint8Arrays(tokens.map((token) => token.toBytes()));
66
66
  if (padTo) {
67
67
  const paddedArray = new Uint8Array(padTo);
68
68
  paddedArray.set(byteArray);
@@ -292,7 +292,10 @@ export class PdfByteStreamTokeniser extends IncrementalParser {
292
292
  }
293
293
  // Note: If there's no EOL marker, we continue anyway (malformed PDF)
294
294
  this.inStream = true;
295
- return new PdfStartStreamToken(concatUint8Arrays(stringToBytes('stream'), new Uint8Array(whitespaceBytes)));
295
+ return new PdfStartStreamToken(concatUint8Arrays([
296
+ stringToBytes('stream'),
297
+ new Uint8Array(whitespaceBytes),
298
+ ]));
296
299
  }
297
300
  nextStreamChunkToken() {
298
301
  if (!this.inStream) {
@@ -15,7 +15,7 @@ export class PdfCommentToken extends PdfToken {
15
15
  }
16
16
  static toBytes(comment) {
17
17
  const tokenBytes = typeof comment === 'string' ? stringToBytes(comment) : comment;
18
- return concatUint8Arrays(stringToBytes('%'), tokenBytes);
18
+ return concatUint8Arrays([stringToBytes('%'), tokenBytes]);
19
19
  }
20
20
  static isEofCommentToken(token) {
21
21
  if (!(token instanceof PdfCommentToken))
@@ -100,9 +100,20 @@ export class PdfNumberToken extends PdfToken {
100
100
  return value.toBytes();
101
101
  }
102
102
  const numberValue = value instanceof Ref ? value.resolve() : value;
103
- const valueString = decimalPlaces
103
+ let valueString = decimalPlaces
104
104
  ? numberValue.toFixed(decimalPlaces)
105
105
  : numberValue.toString();
106
+ // toFixed() always adds a leading zero (e.g. 0.5), but the original PDF
107
+ // may have omitted it (e.g. .5). If padTo is set and the formatted string
108
+ // is longer than padTo, strip the leading zero to match the original length.
109
+ if (padTo !== undefined && valueString.length > padTo) {
110
+ if (valueString.startsWith('0.')) {
111
+ valueString = valueString.slice(1);
112
+ }
113
+ else if (valueString.startsWith('-0.')) {
114
+ valueString = '-' + valueString.slice(2);
115
+ }
116
+ }
106
117
  const tokenString = valueString.padStart(padTo ?? 0, '0');
107
118
  return stringToBytes(tokenString);
108
119
  }
@@ -23,7 +23,7 @@ export async function computeMasterKey(password, ownerKey, permissions, id0, key
23
23
  hashInputParts.push(new Uint8Array([0xff, 0xff, 0xff, 0xff]));
24
24
  }
25
25
  // Initial MD5 hash
26
- let digest = await md5(concatUint8Arrays(...hashInputParts));
26
+ let digest = await md5(concatUint8Arrays(hashInputParts));
27
27
  if (keyLengthBits > 40) {
28
28
  // Perform 50 iterations of MD5 rehash
29
29
  for (let i = 0; i < 50; i++) {
@@ -81,9 +81,15 @@ export async function computeOValueRc4_128(ownerPassword, userPassword) {
81
81
  */
82
82
  async function computeEncryptionKeyRc4_128(userPad, oValue, permissions, id, encryptMetadata, revision = 3) {
83
83
  const perms = int32ToLittleEndianBytes(permissions);
84
- let digest = await md5(concatUint8Arrays(userPad, oValue, perms, id, revision >= 4 && !encryptMetadata
85
- ? new Uint8Array([0xff, 0xff, 0xff, 0xff])
86
- : new Uint8Array()));
84
+ let digest = await md5(concatUint8Arrays([
85
+ userPad,
86
+ oValue,
87
+ perms,
88
+ id,
89
+ revision >= 4 && !encryptMetadata
90
+ ? new Uint8Array([0xff, 0xff, 0xff, 0xff])
91
+ : new Uint8Array(),
92
+ ]));
87
93
  // 50 iterations
88
94
  for (let i = 0; i < 50; i++) {
89
95
  digest = await md5(digest);
@@ -112,7 +118,7 @@ export async function computeUValueRc4_128(userPassword, oValue, permissions, id
112
118
  // Step 1: Compute encryption key
113
119
  const encryptionKey = await computeEncryptionKeyRc4_128(userPad, oValue, permissions, id, encryptMetadata, revision);
114
120
  // Step 2 & 3: MD5 of padding + file ID
115
- const hash = await md5(concatUint8Arrays(DEFAULT_PADDING, id)); // 16 bytes
121
+ const hash = await md5(concatUint8Arrays([DEFAULT_PADDING, id])); // 16 bytes
116
122
  // Step 4: First RC4 encrypt with base key
117
123
  let data = await rc4EncryptWithKey(encryptionKey, hash);
118
124
  // Step 5: 19 more rounds of RC4 with key XOR i
@@ -68,7 +68,7 @@ export async function computeORc4_40(ownerPw, userPw) {
68
68
  export async function computeEncryptionKeyRc4_40(userPw, oValue, permissions, fileId) {
69
69
  const userPad = padPassword(userPw);
70
70
  const permissionsLE = int32ToLittleEndianBytes(permissions);
71
- const digest = await md5(concatUint8Arrays(userPad, oValue, permissionsLE, fileId));
71
+ const digest = await md5(concatUint8Arrays([userPad, oValue, permissionsLE, fileId]));
72
72
  return digest.slice(0, 5); // 40-bit key
73
73
  }
74
74
  /**
@@ -952,7 +952,7 @@ export class PdfDocument extends PdfObject {
952
952
  */
953
953
  toBytes() {
954
954
  this.update();
955
- return concatUint8Arrays(...this.revisions.map((x) => x.toBytes()));
955
+ return concatUint8Arrays(this.revisions.map((x) => x.toBytes()));
956
956
  }
957
957
  /**
958
958
  * Creates a deep copy of the document.
@@ -92,7 +92,10 @@ export class PdfSigner {
92
92
  ];
93
93
  signature.setByteRange(byteRange);
94
94
  const allBytes = this.document.toBytes();
95
- const toSign = concatUint8Arrays(allBytes.slice(byteRange[0], byteRange[1]), allBytes.slice(byteRange[2], byteRange[3] + byteRange[2]));
95
+ const toSign = concatUint8Arrays([
96
+ allBytes.slice(byteRange[0], byteRange[1]),
97
+ allBytes.slice(byteRange[2], byteRange[3] + byteRange[2]),
98
+ ]);
96
99
  const { signedBytes, revocationInfo } = await signature.sign({
97
100
  bytes: toSign,
98
101
  embedRevocationInfo: !Boolean(dss),
@@ -276,7 +279,10 @@ export class PdfSigner {
276
279
  continue;
277
280
  }
278
281
  // Compute the bytes that were signed (excluding the signature contents)
279
- const signedBytes = concatUint8Arrays(documentBytes.slice(byteRange[0], byteRange[0] + byteRange[1]), documentBytes.slice(byteRange[2], byteRange[2] + byteRange[3]));
282
+ const signedBytes = concatUint8Arrays([
283
+ documentBytes.slice(byteRange[0], byteRange[0] + byteRange[1]),
284
+ documentBytes.slice(byteRange[2], byteRange[2] + byteRange[3]),
285
+ ]);
280
286
  // Verify the signature
281
287
  const result = await signature.verify({
282
288
  bytes: signedBytes,
@@ -7,10 +7,10 @@ import { ByteArray } from '../types.js';
7
7
  *
8
8
  * @example
9
9
  * ```typescript
10
- * const result = concatUint8Arrays(
10
+ * const result = concatUint8Arrays([
11
11
  * new Uint8Array([1, 2]),
12
12
  * new Uint8Array([3, 4])
13
- * ) // Returns Uint8Array([1, 2, 3, 4])
13
+ * ]) // Returns Uint8Array([1, 2, 3, 4])
14
14
  * ```
15
15
  */
16
- export declare function concatUint8Arrays(...arrays: Uint8Array[]): ByteArray;
16
+ export declare function concatUint8Arrays(arrays: Uint8Array[]): ByteArray;
@@ -6,19 +6,22 @@
6
6
  *
7
7
  * @example
8
8
  * ```typescript
9
- * const result = concatUint8Arrays(
9
+ * const result = concatUint8Arrays([
10
10
  * new Uint8Array([1, 2]),
11
11
  * new Uint8Array([3, 4])
12
- * ) // Returns Uint8Array([1, 2, 3, 4])
12
+ * ]) // Returns Uint8Array([1, 2, 3, 4])
13
13
  * ```
14
14
  */
15
- export function concatUint8Arrays(...arrays) {
16
- const totalLength = arrays.reduce((acc, arr) => acc + arr.length, 0);
15
+ export function concatUint8Arrays(arrays) {
16
+ let totalLength = 0;
17
+ for (let i = 0; i < arrays.length; i++) {
18
+ totalLength += arrays[i].length;
19
+ }
17
20
  const result = new Uint8Array(totalLength);
18
21
  let offset = 0;
19
- for (const arr of arrays) {
20
- result.set(arr, offset);
21
- offset += arr.length;
22
+ for (let i = 0; i < arrays.length; i++) {
23
+ result.set(arrays[i], offset);
24
+ offset += arrays[i].length;
22
25
  }
23
26
  return result;
24
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pdf-lite",
3
- "version": "1.7.2",
3
+ "version": "1.7.3-alpha.1",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "exports": {