archive-codec 1.11.2 → 1.11.3

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.
@@ -8,9 +8,8 @@ var OlePackageFormatError = class extends Error {
8
8
  };
9
9
  const ANSI_DECODER = new TextDecoder("windows-1252");
10
10
  function readZeroTerminated(bytes, offset, fieldName) {
11
- let end = offset;
12
- while (end < bytes.length && bytes[end] !== 0) end++;
13
- if (end >= bytes.length) throw new OlePackageFormatError(`Package stream ends inside its ${fieldName} string with no terminator`);
11
+ const end = bytes.indexOf(0, offset);
12
+ if (end === -1) throw new OlePackageFormatError(`Package stream ends inside its ${fieldName} string with no terminator`);
14
13
  return {
15
14
  value: ANSI_DECODER.decode(bytes.subarray(offset, end)),
16
15
  next: end + 1
@@ -45,12 +44,13 @@ var OlePackageWriteError = class extends Error {
45
44
  };
46
45
  function asciiZeroTerminated(value, fieldName) {
47
46
  const bytes = new Uint8Array(value.length + 1);
48
- for (let index = 0; index < value.length; index++) {
49
- const code = value.charCodeAt(index);
47
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
48
+ value.split("").forEach((char, index) => {
49
+ const code = char.charCodeAt(0);
50
50
  if (code === 0) throw new OlePackageWriteError(`Package stream's ${fieldName} contains an embedded NUL byte, which this field's own null-terminated encoding cannot carry: it would silently truncate the field and mis-frame every field written after it`);
51
51
  if (code > 127) throw new OlePackageWriteError(`Package stream's ${fieldName} contains a character (U+${code.toString(16).padStart(4, "0")}) outside ASCII; encoding it to an arbitrary windows-1252 byte would need a full codepage table this package does not carry`);
52
- bytes[index] = code;
53
- }
52
+ view.setUint8(index, code);
53
+ });
54
54
  return bytes;
55
55
  }
56
56
  function writeOlePackage(pkg) {
@@ -7,9 +7,8 @@ var OlePackageFormatError = class extends Error {
7
7
  };
8
8
  const ANSI_DECODER = new TextDecoder("windows-1252");
9
9
  function readZeroTerminated(bytes, offset, fieldName) {
10
- let end = offset;
11
- while (end < bytes.length && bytes[end] !== 0) end++;
12
- if (end >= bytes.length) throw new OlePackageFormatError(`Package stream ends inside its ${fieldName} string with no terminator`);
10
+ const end = bytes.indexOf(0, offset);
11
+ if (end === -1) throw new OlePackageFormatError(`Package stream ends inside its ${fieldName} string with no terminator`);
13
12
  return {
14
13
  value: ANSI_DECODER.decode(bytes.subarray(offset, end)),
15
14
  next: end + 1
@@ -44,12 +43,13 @@ var OlePackageWriteError = class extends Error {
44
43
  };
45
44
  function asciiZeroTerminated(value, fieldName) {
46
45
  const bytes = new Uint8Array(value.length + 1);
47
- for (let index = 0; index < value.length; index++) {
48
- const code = value.charCodeAt(index);
46
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
47
+ value.split("").forEach((char, index) => {
48
+ const code = char.charCodeAt(0);
49
49
  if (code === 0) throw new OlePackageWriteError(`Package stream's ${fieldName} contains an embedded NUL byte, which this field's own null-terminated encoding cannot carry: it would silently truncate the field and mis-frame every field written after it`);
50
50
  if (code > 127) throw new OlePackageWriteError(`Package stream's ${fieldName} contains a character (U+${code.toString(16).padStart(4, "0")}) outside ASCII; encoding it to an arbitrary windows-1252 byte would need a full codepage table this package does not carry`);
51
- bytes[index] = code;
52
- }
51
+ view.setUint8(index, code);
52
+ });
53
53
  return bytes;
54
54
  }
55
55
  function writeOlePackage(pkg) {
package/dist/cfb/read.cjs CHANGED
@@ -70,15 +70,17 @@ function readCompoundFile(bytes, options = {}) {
70
70
  const fat = new DataView(fatBytes.buffer);
71
71
  const fatEntry = (sector) => {
72
72
  const offset = sector * 4;
73
- if (offset < 0 || offset + 4 > fatBytes.length) throw new CompoundFileFormatError(`FAT entry for sector ${sector} lies beyond the sectors the DIFAT named`);
73
+ if (offset + 4 > fatBytes.length) throw new CompoundFileFormatError(`FAT entry for sector ${sector} lies beyond the sectors the DIFAT named`);
74
74
  return fat.getUint32(offset, true);
75
75
  };
76
76
  const chainSectorIds = (start) => {
77
77
  const ids = [];
78
+ const visited = /* @__PURE__ */ new Set();
78
79
  let current = start;
79
80
  while (current !== ENDOFCHAIN) {
80
81
  if (current >= sectorCount) throw new CompoundFileFormatError(`a FAT chain steps to sector ${current}, which is outside the file's ${sectorCount} sectors`);
81
- if (ids.length >= sectorCount) throw new CompoundFileFormatError("a FAT chain visits more sectors than the file holds, so it must cycle");
82
+ if (visited.has(current)) throw new CompoundFileFormatError("a FAT chain visits more sectors than the file holds, so it must cycle");
83
+ visited.add(current);
82
84
  ids.push(current);
83
85
  const next = fatEntry(current);
84
86
  if (next === FREESECT || next === FATSECT || next === DIFSECT) throw new CompoundFileFormatError(`a FAT chain steps to sector ${current}'s entry ${next}, which is a sector-role marker, not a chain continuation`);
@@ -120,10 +122,12 @@ function readCompoundFile(bytes, options = {}) {
120
122
  const miniFat = new DataView(miniFatBytes.buffer);
121
123
  const miniChainSectorIds = (start) => {
122
124
  const ids = [];
125
+ const visited = /* @__PURE__ */ new Set();
123
126
  let current = start;
124
127
  while (current !== ENDOFCHAIN) {
125
128
  if (current >= miniSectorCount) throw new CompoundFileFormatError(`a mini-FAT chain steps to mini sector ${current}, which is outside the mini stream's ${miniSectorCount} mini sectors`);
126
- if (ids.length >= miniSectorCount) throw new CompoundFileFormatError("a mini-FAT chain visits more mini sectors than the mini stream holds, so it must cycle");
129
+ if (visited.has(current)) throw new CompoundFileFormatError("a mini-FAT chain visits more mini sectors than the mini stream holds, so it must cycle");
130
+ visited.add(current);
127
131
  ids.push(current);
128
132
  const next = miniFat.getUint32(current * 4, true);
129
133
  if (next === FREESECT || next === FATSECT || next === DIFSECT) throw new CompoundFileFormatError(`a mini-FAT chain steps to mini sector ${current}'s entry ${next}, which is a sector-role marker, not a chain continuation`);
@@ -161,7 +165,7 @@ function readCompoundFile(bytes, options = {}) {
161
165
  const { id, prefix } = frame;
162
166
  if (id === NOSTREAM) continue;
163
167
  const entry = entries[id];
164
- if (id >= entryCount || entry === void 0) throw new CompoundFileFormatError(`the directory tree links to entry ${id}, which is outside the directory's ${entryCount} entries`);
168
+ if (entry === void 0) throw new CompoundFileFormatError(`the directory tree links to entry ${id}, which is outside the directory's ${entryCount} entries`);
165
169
  if (visited.has(id)) throw new CompoundFileFormatError(`the directory tree reaches entry ${id} twice, so its sibling and child links cycle`);
166
170
  visited.add(id);
167
171
  if (entry.nameLength < 2 || entry.nameLength > 64 || entry.nameLength % 2 === 1) throw new CompoundFileFormatError(`directory entry ${id} declares name length ${entry.nameLength}, which is not an even byte count between 2 and 64`);
package/dist/cfb/read.js CHANGED
@@ -69,15 +69,17 @@ function readCompoundFile(bytes, options = {}) {
69
69
  const fat = new DataView(fatBytes.buffer);
70
70
  const fatEntry = (sector) => {
71
71
  const offset = sector * 4;
72
- if (offset < 0 || offset + 4 > fatBytes.length) throw new CompoundFileFormatError(`FAT entry for sector ${sector} lies beyond the sectors the DIFAT named`);
72
+ if (offset + 4 > fatBytes.length) throw new CompoundFileFormatError(`FAT entry for sector ${sector} lies beyond the sectors the DIFAT named`);
73
73
  return fat.getUint32(offset, true);
74
74
  };
75
75
  const chainSectorIds = (start) => {
76
76
  const ids = [];
77
+ const visited = /* @__PURE__ */ new Set();
77
78
  let current = start;
78
79
  while (current !== ENDOFCHAIN) {
79
80
  if (current >= sectorCount) throw new CompoundFileFormatError(`a FAT chain steps to sector ${current}, which is outside the file's ${sectorCount} sectors`);
80
- if (ids.length >= sectorCount) throw new CompoundFileFormatError("a FAT chain visits more sectors than the file holds, so it must cycle");
81
+ if (visited.has(current)) throw new CompoundFileFormatError("a FAT chain visits more sectors than the file holds, so it must cycle");
82
+ visited.add(current);
81
83
  ids.push(current);
82
84
  const next = fatEntry(current);
83
85
  if (next === FREESECT || next === FATSECT || next === DIFSECT) throw new CompoundFileFormatError(`a FAT chain steps to sector ${current}'s entry ${next}, which is a sector-role marker, not a chain continuation`);
@@ -119,10 +121,12 @@ function readCompoundFile(bytes, options = {}) {
119
121
  const miniFat = new DataView(miniFatBytes.buffer);
120
122
  const miniChainSectorIds = (start) => {
121
123
  const ids = [];
124
+ const visited = /* @__PURE__ */ new Set();
122
125
  let current = start;
123
126
  while (current !== ENDOFCHAIN) {
124
127
  if (current >= miniSectorCount) throw new CompoundFileFormatError(`a mini-FAT chain steps to mini sector ${current}, which is outside the mini stream's ${miniSectorCount} mini sectors`);
125
- if (ids.length >= miniSectorCount) throw new CompoundFileFormatError("a mini-FAT chain visits more mini sectors than the mini stream holds, so it must cycle");
128
+ if (visited.has(current)) throw new CompoundFileFormatError("a mini-FAT chain visits more mini sectors than the mini stream holds, so it must cycle");
129
+ visited.add(current);
126
130
  ids.push(current);
127
131
  const next = miniFat.getUint32(current * 4, true);
128
132
  if (next === FREESECT || next === FATSECT || next === DIFSECT) throw new CompoundFileFormatError(`a mini-FAT chain steps to mini sector ${current}'s entry ${next}, which is a sector-role marker, not a chain continuation`);
@@ -160,7 +164,7 @@ function readCompoundFile(bytes, options = {}) {
160
164
  const { id, prefix } = frame;
161
165
  if (id === NOSTREAM) continue;
162
166
  const entry = entries[id];
163
- if (id >= entryCount || entry === void 0) throw new CompoundFileFormatError(`the directory tree links to entry ${id}, which is outside the directory's ${entryCount} entries`);
167
+ if (entry === void 0) throw new CompoundFileFormatError(`the directory tree links to entry ${id}, which is outside the directory's ${entryCount} entries`);
164
168
  if (visited.has(id)) throw new CompoundFileFormatError(`the directory tree reaches entry ${id} twice, so its sibling and child links cycle`);
165
169
  visited.add(id);
166
170
  if (entry.nameLength < 2 || entry.nameLength > 64 || entry.nameLength % 2 === 1) throw new CompoundFileFormatError(`directory entry ${id} declares name length ${entry.nameLength}, which is not an even byte count between 2 and 64`);
@@ -39,17 +39,21 @@ function objectTypeOf(entry) {
39
39
  }
40
40
  function upperCodeUnit(value, index) {
41
41
  const unit = value.charCodeAt(index);
42
- if (unit >= 55296 && unit <= 57343) return unit;
43
42
  const upper = String.fromCharCode(unit).toUpperCase();
44
43
  return upper.length === 1 ? upper.charCodeAt(0) : unit;
45
44
  }
46
45
  function compareEntryNames(left, right) {
47
46
  if (left.length !== right.length) return left.length - right.length;
48
- for (let i = 0; i < left.length; i++) {
47
+ let result = 0;
48
+ left.split("").every((_unit, i) => {
49
49
  const difference = upperCodeUnit(left, i) - upperCodeUnit(right, i);
50
- if (difference !== 0) return difference;
51
- }
52
- return 0;
50
+ if (difference !== 0) {
51
+ result = difference;
52
+ return false;
53
+ }
54
+ return true;
55
+ });
56
+ return result;
53
57
  }
54
58
  function checkedSegment(name, path) {
55
59
  if (name.length === 0) throw new CompoundFileWriteError(`stream path ${JSON.stringify(path)} has an empty name segment; every segment must name a storage, and the last must name the stream`);
@@ -137,6 +141,12 @@ function planDirectory(root) {
137
141
  plans
138
142
  };
139
143
  }
144
+ function exceedsVersion3StreamCeiling(majorVersion, byteLength) {
145
+ return majorVersion === 3 && byteLength > MAX_VERSION_3_STREAM_BYTES;
146
+ }
147
+ function highSizeWord(size) {
148
+ return Math.floor(size / 4294967296);
149
+ }
140
150
  function writeCompoundFile(streams, options = {}) {
141
151
  const majorVersion = options.majorVersion ?? 3;
142
152
  const sectorShift = majorVersion === 4 ? 12 : 9;
@@ -149,7 +159,7 @@ function writeCompoundFile(streams, options = {}) {
149
159
  children: []
150
160
  };
151
161
  for (const { path, bytes } of streams) {
152
- if (majorVersion === 3 && bytes.length > MAX_VERSION_3_STREAM_BYTES) throw new CompoundFileWriteError(`stream ${JSON.stringify(path)} is ${bytes.length} bytes, past the ${MAX_VERSION_3_STREAM_BYTES}-byte ceiling [MS-CFB] 2.6.1 puts on a version 3 stream; write the file as version 4 instead`);
162
+ if (exceedsVersion3StreamCeiling(majorVersion, bytes.length)) throw new CompoundFileWriteError(`stream ${JSON.stringify(path)} is ${bytes.length} bytes, past the ${MAX_VERSION_3_STREAM_BYTES}-byte ceiling [MS-CFB] 2.6.1 puts on a version 3 stream; write the file as version 4 instead`);
153
163
  addStream(root, path, bytes);
154
164
  }
155
165
  const { rootPlan, plans } = planDirectory(root);
@@ -185,8 +195,8 @@ function writeCompoundFile(streams, options = {}) {
185
195
  let difatSectorCount = 0;
186
196
  for (;;) {
187
197
  const neededFat = Math.max(1, Math.ceil(totalSectorsGiven(fatSectorCount, difatSectorCount) / entriesPerFatSector));
188
- const neededDifat = neededFat <= HEADER_DIFAT_ENTRIES ? 0 : Math.ceil((neededFat - HEADER_DIFAT_ENTRIES) / difatEntriesPerSector);
189
- if (neededFat === fatSectorCount && neededDifat === difatSectorCount) break;
198
+ const neededDifat = Math.max(0, Math.ceil((neededFat - HEADER_DIFAT_ENTRIES) / difatEntriesPerSector));
199
+ if (neededFat === fatSectorCount) break;
190
200
  fatSectorCount = neededFat;
191
201
  difatSectorCount = neededDifat;
192
202
  }
@@ -222,8 +232,8 @@ function writeCompoundFile(streams, options = {}) {
222
232
  const chainSectors = (start, count) => {
223
233
  for (let i = 0; i < count; i++) setFat(start + i, i === count - 1 ? ENDOFCHAIN : start + i + 1);
224
234
  };
225
- for (let i = 0; i < fatSectorCount; i++) setFat(i, FATSECT);
226
- for (let i = 0; i < difatSectorCount; i++) setFat(difatStart + i, DIFSECT);
235
+ for (const i of Array.from({ length: fatSectorCount }, (_unused, n) => n)) setFat(i, FATSECT);
236
+ for (const i of Array.from({ length: difatSectorCount }, (_unused, n) => n)) setFat(difatStart + i, DIFSECT);
227
237
  chainSectors(directoryStart, directorySectorCount);
228
238
  for (const { entry, bytes } of fatResident) chainSectors(entry.startSector, Math.ceil(bytes.length / sectorSize));
229
239
  chainSectors(miniStreamStart, miniStreamSectorCount);
@@ -231,7 +241,7 @@ function writeCompoundFile(streams, options = {}) {
231
241
  for (let i = 0; i < Math.min(fatSectorCount, HEADER_DIFAT_ENTRIES); i++) putU32(HEADER_DIFAT_OFFSET + i * 4, i);
232
242
  for (let sector = 0; sector < difatSectorCount; sector++) {
233
243
  const base = sectorOffset(difatStart + sector);
234
- for (let i = 0; i < difatEntriesPerSector; i++) {
244
+ for (const i of Array.from({ length: difatEntriesPerSector }, (_unused, n) => n)) {
235
245
  const fatIndex = HEADER_DIFAT_ENTRIES + sector * difatEntriesPerSector + i;
236
246
  if (fatIndex < fatSectorCount) putU32(base + i * 4, fatIndex);
237
247
  }
@@ -250,7 +260,7 @@ function writeCompoundFile(streams, options = {}) {
250
260
  for (const entry of plans) {
251
261
  const base = entryOffset(entry.id);
252
262
  const name = entry.node.name;
253
- for (let i = 0; i < name.length; i++) putU16(base + i * 2, name.charCodeAt(i));
263
+ for (const i of Array.from({ length: name.length }, (_unused, n) => n)) putU16(base + i * 2, name.charCodeAt(i));
254
264
  putU16(base + 64, (name.length + 1) * 2);
255
265
  view.setUint8(base + 66, objectTypeOf(entry));
256
266
  view.setUint8(base + 67, entry.colour);
@@ -259,7 +269,7 @@ function writeCompoundFile(streams, options = {}) {
259
269
  putU32(base + 76, entry.child);
260
270
  putU32(base + 116, entry.startSector);
261
271
  putU32(base + 120, entry.size >>> 0);
262
- putU32(base + 124, Math.floor(entry.size / 4294967296));
272
+ putU32(base + 124, highSizeWord(entry.size));
263
273
  }
264
274
  for (let id = plans.length; id < directorySectorCount * entriesPerDirectorySector; id++) {
265
275
  const base = entryOffset(id);
@@ -294,4 +304,7 @@ function writeCompoundFile(streams, options = {}) {
294
304
  }
295
305
  //#endregion
296
306
  exports.CompoundFileWriteError = CompoundFileWriteError;
307
+ exports.deepestDepth = deepestDepth;
308
+ exports.exceedsVersion3StreamCeiling = exceedsVersion3StreamCeiling;
309
+ exports.highSizeWord = highSizeWord;
297
310
  exports.writeCompoundFile = writeCompoundFile;
@@ -6,6 +6,9 @@ declare class CompoundFileWriteError extends Error {
6
6
  interface WriteCompoundFileOptions {
7
7
  readonly majorVersion?: 3 | 4;
8
8
  }
9
+ declare function deepestDepth(count: number): number;
10
+ declare function exceedsVersion3StreamCeiling(majorVersion: 3 | 4, byteLength: number): boolean;
11
+ declare function highSizeWord(size: number): number;
9
12
  declare function writeCompoundFile(streams: readonly CompoundFileStream[], options?: WriteCompoundFileOptions): Uint8Array<ArrayBuffer>;
10
13
  //#endregion
11
- export { CompoundFileWriteError, WriteCompoundFileOptions, writeCompoundFile };
14
+ export { CompoundFileWriteError, WriteCompoundFileOptions, deepestDepth, exceedsVersion3StreamCeiling, highSizeWord, writeCompoundFile };
@@ -6,6 +6,9 @@ declare class CompoundFileWriteError extends Error {
6
6
  interface WriteCompoundFileOptions {
7
7
  readonly majorVersion?: 3 | 4;
8
8
  }
9
+ declare function deepestDepth(count: number): number;
10
+ declare function exceedsVersion3StreamCeiling(majorVersion: 3 | 4, byteLength: number): boolean;
11
+ declare function highSizeWord(size: number): number;
9
12
  declare function writeCompoundFile(streams: readonly CompoundFileStream[], options?: WriteCompoundFileOptions): Uint8Array<ArrayBuffer>;
10
13
  //#endregion
11
- export { CompoundFileWriteError, WriteCompoundFileOptions, writeCompoundFile };
14
+ export { CompoundFileWriteError, WriteCompoundFileOptions, deepestDepth, exceedsVersion3StreamCeiling, highSizeWord, writeCompoundFile };
package/dist/cfb/write.js CHANGED
@@ -38,17 +38,21 @@ function objectTypeOf(entry) {
38
38
  }
39
39
  function upperCodeUnit(value, index) {
40
40
  const unit = value.charCodeAt(index);
41
- if (unit >= 55296 && unit <= 57343) return unit;
42
41
  const upper = String.fromCharCode(unit).toUpperCase();
43
42
  return upper.length === 1 ? upper.charCodeAt(0) : unit;
44
43
  }
45
44
  function compareEntryNames(left, right) {
46
45
  if (left.length !== right.length) return left.length - right.length;
47
- for (let i = 0; i < left.length; i++) {
46
+ let result = 0;
47
+ left.split("").every((_unit, i) => {
48
48
  const difference = upperCodeUnit(left, i) - upperCodeUnit(right, i);
49
- if (difference !== 0) return difference;
50
- }
51
- return 0;
49
+ if (difference !== 0) {
50
+ result = difference;
51
+ return false;
52
+ }
53
+ return true;
54
+ });
55
+ return result;
52
56
  }
53
57
  function checkedSegment(name, path) {
54
58
  if (name.length === 0) throw new CompoundFileWriteError(`stream path ${JSON.stringify(path)} has an empty name segment; every segment must name a storage, and the last must name the stream`);
@@ -136,6 +140,12 @@ function planDirectory(root) {
136
140
  plans
137
141
  };
138
142
  }
143
+ function exceedsVersion3StreamCeiling(majorVersion, byteLength) {
144
+ return majorVersion === 3 && byteLength > MAX_VERSION_3_STREAM_BYTES;
145
+ }
146
+ function highSizeWord(size) {
147
+ return Math.floor(size / 4294967296);
148
+ }
139
149
  function writeCompoundFile(streams, options = {}) {
140
150
  const majorVersion = options.majorVersion ?? 3;
141
151
  const sectorShift = majorVersion === 4 ? 12 : 9;
@@ -148,7 +158,7 @@ function writeCompoundFile(streams, options = {}) {
148
158
  children: []
149
159
  };
150
160
  for (const { path, bytes } of streams) {
151
- if (majorVersion === 3 && bytes.length > MAX_VERSION_3_STREAM_BYTES) throw new CompoundFileWriteError(`stream ${JSON.stringify(path)} is ${bytes.length} bytes, past the ${MAX_VERSION_3_STREAM_BYTES}-byte ceiling [MS-CFB] 2.6.1 puts on a version 3 stream; write the file as version 4 instead`);
161
+ if (exceedsVersion3StreamCeiling(majorVersion, bytes.length)) throw new CompoundFileWriteError(`stream ${JSON.stringify(path)} is ${bytes.length} bytes, past the ${MAX_VERSION_3_STREAM_BYTES}-byte ceiling [MS-CFB] 2.6.1 puts on a version 3 stream; write the file as version 4 instead`);
152
162
  addStream(root, path, bytes);
153
163
  }
154
164
  const { rootPlan, plans } = planDirectory(root);
@@ -184,8 +194,8 @@ function writeCompoundFile(streams, options = {}) {
184
194
  let difatSectorCount = 0;
185
195
  for (;;) {
186
196
  const neededFat = Math.max(1, Math.ceil(totalSectorsGiven(fatSectorCount, difatSectorCount) / entriesPerFatSector));
187
- const neededDifat = neededFat <= HEADER_DIFAT_ENTRIES ? 0 : Math.ceil((neededFat - HEADER_DIFAT_ENTRIES) / difatEntriesPerSector);
188
- if (neededFat === fatSectorCount && neededDifat === difatSectorCount) break;
197
+ const neededDifat = Math.max(0, Math.ceil((neededFat - HEADER_DIFAT_ENTRIES) / difatEntriesPerSector));
198
+ if (neededFat === fatSectorCount) break;
189
199
  fatSectorCount = neededFat;
190
200
  difatSectorCount = neededDifat;
191
201
  }
@@ -221,8 +231,8 @@ function writeCompoundFile(streams, options = {}) {
221
231
  const chainSectors = (start, count) => {
222
232
  for (let i = 0; i < count; i++) setFat(start + i, i === count - 1 ? ENDOFCHAIN : start + i + 1);
223
233
  };
224
- for (let i = 0; i < fatSectorCount; i++) setFat(i, FATSECT);
225
- for (let i = 0; i < difatSectorCount; i++) setFat(difatStart + i, DIFSECT);
234
+ for (const i of Array.from({ length: fatSectorCount }, (_unused, n) => n)) setFat(i, FATSECT);
235
+ for (const i of Array.from({ length: difatSectorCount }, (_unused, n) => n)) setFat(difatStart + i, DIFSECT);
226
236
  chainSectors(directoryStart, directorySectorCount);
227
237
  for (const { entry, bytes } of fatResident) chainSectors(entry.startSector, Math.ceil(bytes.length / sectorSize));
228
238
  chainSectors(miniStreamStart, miniStreamSectorCount);
@@ -230,7 +240,7 @@ function writeCompoundFile(streams, options = {}) {
230
240
  for (let i = 0; i < Math.min(fatSectorCount, HEADER_DIFAT_ENTRIES); i++) putU32(HEADER_DIFAT_OFFSET + i * 4, i);
231
241
  for (let sector = 0; sector < difatSectorCount; sector++) {
232
242
  const base = sectorOffset(difatStart + sector);
233
- for (let i = 0; i < difatEntriesPerSector; i++) {
243
+ for (const i of Array.from({ length: difatEntriesPerSector }, (_unused, n) => n)) {
234
244
  const fatIndex = HEADER_DIFAT_ENTRIES + sector * difatEntriesPerSector + i;
235
245
  if (fatIndex < fatSectorCount) putU32(base + i * 4, fatIndex);
236
246
  }
@@ -249,7 +259,7 @@ function writeCompoundFile(streams, options = {}) {
249
259
  for (const entry of plans) {
250
260
  const base = entryOffset(entry.id);
251
261
  const name = entry.node.name;
252
- for (let i = 0; i < name.length; i++) putU16(base + i * 2, name.charCodeAt(i));
262
+ for (const i of Array.from({ length: name.length }, (_unused, n) => n)) putU16(base + i * 2, name.charCodeAt(i));
253
263
  putU16(base + 64, (name.length + 1) * 2);
254
264
  view.setUint8(base + 66, objectTypeOf(entry));
255
265
  view.setUint8(base + 67, entry.colour);
@@ -258,7 +268,7 @@ function writeCompoundFile(streams, options = {}) {
258
268
  putU32(base + 76, entry.child);
259
269
  putU32(base + 116, entry.startSector);
260
270
  putU32(base + 120, entry.size >>> 0);
261
- putU32(base + 124, Math.floor(entry.size / 4294967296));
271
+ putU32(base + 124, highSizeWord(entry.size));
262
272
  }
263
273
  for (let id = plans.length; id < directorySectorCount * entriesPerDirectorySector; id++) {
264
274
  const base = entryOffset(id);
@@ -292,4 +302,4 @@ function writeCompoundFile(streams, options = {}) {
292
302
  return file;
293
303
  }
294
304
  //#endregion
295
- export { CompoundFileWriteError, writeCompoundFile };
305
+ export { CompoundFileWriteError, deepestDepth, exceedsVersion3StreamCeiling, highSizeWord, writeCompoundFile };
@@ -151,21 +151,23 @@ const INITIAL_D = 271733878;
151
151
  function rotl32(value, bits) {
152
152
  return (value << bits | value >>> 32 - bits) >>> 0;
153
153
  }
154
+ function splitBitLength64(bitLength) {
155
+ return {
156
+ low: bitLength % 4294967296,
157
+ high: Math.floor(bitLength / 4294967296)
158
+ };
159
+ }
160
+ function writeBitLength64(view, offset, bitLength) {
161
+ const { low, high } = splitBitLength64(bitLength);
162
+ view.setUint32(offset, low, true);
163
+ view.setUint32(offset + 4, high, true);
164
+ }
154
165
  function padMessage(bytes) {
155
166
  const paddedLength = (Math.floor((bytes.length + 8) / BLOCK_BYTES) + 1) * BLOCK_BYTES;
156
167
  const padded = new Uint8Array(paddedLength);
157
168
  padded.set(bytes);
158
169
  padded[bytes.length] = 128;
159
- const view = new DataView(padded.buffer);
160
- const bitLength = bytes.length * 8;
161
- let low = bitLength % 4294967296;
162
- let high = Math.floor(bitLength / 4294967296);
163
- for (let i = 0; i < 4; i++) {
164
- view.setUint8(paddedLength - 8 + i, low & 255);
165
- low = Math.floor(low / 256);
166
- view.setUint8(paddedLength - 4 + i, high & 255);
167
- high = Math.floor(high / 256);
168
- }
170
+ writeBitLength64(new DataView(padded.buffer), paddedLength - 8, bytes.length * 8);
169
171
  return padded;
170
172
  }
171
173
  function md5(bytes) {
@@ -219,3 +221,5 @@ function md5(bytes) {
219
221
  }
220
222
  //#endregion
221
223
  exports.md5 = md5;
224
+ exports.splitBitLength64 = splitBitLength64;
225
+ exports.writeBitLength64 = writeBitLength64;
@@ -1,4 +1,9 @@
1
1
  //#region src/crypto/md5.d.ts
2
+ declare function splitBitLength64(bitLength: number): {
3
+ readonly low: number;
4
+ readonly high: number;
5
+ };
6
+ declare function writeBitLength64(view: DataView, offset: number, bitLength: number): void;
2
7
  declare function md5(bytes: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>;
3
8
  //#endregion
4
- export { md5 };
9
+ export { md5, splitBitLength64, writeBitLength64 };
@@ -1,4 +1,9 @@
1
1
  //#region src/crypto/md5.d.ts
2
+ declare function splitBitLength64(bitLength: number): {
3
+ readonly low: number;
4
+ readonly high: number;
5
+ };
6
+ declare function writeBitLength64(view: DataView, offset: number, bitLength: number): void;
2
7
  declare function md5(bytes: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>;
3
8
  //#endregion
4
- export { md5 };
9
+ export { md5, splitBitLength64, writeBitLength64 };
@@ -150,21 +150,23 @@ const INITIAL_D = 271733878;
150
150
  function rotl32(value, bits) {
151
151
  return (value << bits | value >>> 32 - bits) >>> 0;
152
152
  }
153
+ function splitBitLength64(bitLength) {
154
+ return {
155
+ low: bitLength % 4294967296,
156
+ high: Math.floor(bitLength / 4294967296)
157
+ };
158
+ }
159
+ function writeBitLength64(view, offset, bitLength) {
160
+ const { low, high } = splitBitLength64(bitLength);
161
+ view.setUint32(offset, low, true);
162
+ view.setUint32(offset + 4, high, true);
163
+ }
153
164
  function padMessage(bytes) {
154
165
  const paddedLength = (Math.floor((bytes.length + 8) / BLOCK_BYTES) + 1) * BLOCK_BYTES;
155
166
  const padded = new Uint8Array(paddedLength);
156
167
  padded.set(bytes);
157
168
  padded[bytes.length] = 128;
158
- const view = new DataView(padded.buffer);
159
- const bitLength = bytes.length * 8;
160
- let low = bitLength % 4294967296;
161
- let high = Math.floor(bitLength / 4294967296);
162
- for (let i = 0; i < 4; i++) {
163
- view.setUint8(paddedLength - 8 + i, low & 255);
164
- low = Math.floor(low / 256);
165
- view.setUint8(paddedLength - 4 + i, high & 255);
166
- high = Math.floor(high / 256);
167
- }
169
+ writeBitLength64(new DataView(padded.buffer), paddedLength - 8, bytes.length * 8);
168
170
  return padded;
169
171
  }
170
172
  function md5(bytes) {
@@ -217,4 +219,4 @@ function md5(bytes) {
217
219
  return digest;
218
220
  }
219
221
  //#endregion
220
- export { md5 };
222
+ export { md5, splitBitLength64, writeBitLength64 };
@@ -15,7 +15,6 @@ function keySizeBitsOf(keySizeBits) {
15
15
  return keySizeBits === 0 ? 40 : keySizeBits;
16
16
  }
17
17
  function bytesEqual(a, b) {
18
- if (a.length !== b.length) return false;
19
18
  return a.every((byte, index) => byte === b[index]);
20
19
  }
21
20
  /** The per-persist-object RC4 key: SHA1(SHA1(salt + UTF-16LE password) + the block number as 4 little-endian bytes), truncated to `keySizeBits`. [MS-OFFCRYPTO] 2.3.5.1's own 40-bit special case is real, not a rounding artefact: a 40-bit key is still carried in a 16-byte buffer (the derived hash's own first 5 bytes, zero-padded to 16), confirmed directly against nolze/msoffcrypto-tool's `_makekey` (`key = hfinal[:5] + b"\x00" * 11`) -- the "effective" key strength is 40 bits, but the RC4 key schedule this package's own `rc4` runs still consumes all 16 bytes of it. */
@@ -14,7 +14,6 @@ function keySizeBitsOf(keySizeBits) {
14
14
  return keySizeBits === 0 ? 40 : keySizeBits;
15
15
  }
16
16
  function bytesEqual(a, b) {
17
- if (a.length !== b.length) return false;
18
17
  return a.every((byte, index) => byte === b[index]);
19
18
  }
20
19
  /** The per-persist-object RC4 key: SHA1(SHA1(salt + UTF-16LE password) + the block number as 4 little-endian bytes), truncated to `keySizeBits`. [MS-OFFCRYPTO] 2.3.5.1's own 40-bit special case is real, not a rounding artefact: a 40-bit key is still carried in a 16-byte buffer (the derived hash's own first 5 bytes, zero-padded to 16), confirmed directly against nolze/msoffcrypto-tool's `_makekey` (`key = hfinal[:5] + b"\x00" * 11`) -- the "effective" key strength is 40 bits, but the RC4 key schedule this package's own `rc4` runs still consumes all 16 bytes of it. */
@@ -13,11 +13,8 @@ const INTERMEDIATE_HASH_LENGTH_BYTES = 5;
13
13
  /** UTF-16LE password encoding, shared with office-rc4-cryptoapi.ts: both [MS-OFFCRYPTO] key-derivation schemes this package implements hash a password in this same encoding, per their own respective specs (2.3.6.2 and 2.3.5.2). */
14
14
  function passwordToUtf16LeBytes(password) {
15
15
  const bytes = new Uint8Array(password.length * 2);
16
- for (let i = 0; i < password.length; i += 1) {
17
- const code = password.charCodeAt(i);
18
- bytes[i * 2] = code & 255;
19
- bytes[i * 2 + 1] = code >>> 8 & 255;
20
- }
16
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
17
+ for (let i = 0; i < password.length; i += 1) view.setUint16(i * 2, password.charCodeAt(i), true);
21
18
  return bytes;
22
19
  }
23
20
  /** The per-workbook intermediate hash (H1's own first 5 bytes) every block's key derives from -- computed once per password+salt pair, then reused across every block via deriveOfficeRc4BlockKey, since recomputing H0/H1 per block would be needless repeated work over the identical 336-byte buffer. */
@@ -12,11 +12,8 @@ const INTERMEDIATE_HASH_LENGTH_BYTES = 5;
12
12
  /** UTF-16LE password encoding, shared with office-rc4-cryptoapi.ts: both [MS-OFFCRYPTO] key-derivation schemes this package implements hash a password in this same encoding, per their own respective specs (2.3.6.2 and 2.3.5.2). */
13
13
  function passwordToUtf16LeBytes(password) {
14
14
  const bytes = new Uint8Array(password.length * 2);
15
- for (let i = 0; i < password.length; i += 1) {
16
- const code = password.charCodeAt(i);
17
- bytes[i * 2] = code & 255;
18
- bytes[i * 2 + 1] = code >>> 8 & 255;
19
- }
15
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
16
+ for (let i = 0; i < password.length; i += 1) view.setUint16(i * 2, password.charCodeAt(i), true);
20
17
  return bytes;
21
18
  }
22
19
  /** The per-workbook intermediate hash (H1's own first 5 bytes) every block's key derives from -- computed once per password+salt pair, then reused across every block via deriveOfficeRc4BlockKey, since recomputing H0/H1 per block would be needless repeated work over the identical 336-byte buffer. */
@@ -170,10 +170,11 @@ const XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD2 = 7;
170
170
  function passwordToAsciiBytes(password) {
171
171
  if (password.length === 0 || password.length > 15) throw new RangeError(`XOR obfuscation passwords must be 1-15 characters, got ${password.length}`);
172
172
  const bytes = new Uint8Array(password.length);
173
+ const bytesView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
173
174
  for (let i = 0; i < password.length; i += 1) {
174
175
  const code = password.charCodeAt(i);
175
176
  if (code > 255) throw new RangeError(`XOR obfuscation passwords must be single-byte ASCII/Latin-1 characters, got code point ${code} at index ${i}`);
176
- bytes[i] = code;
177
+ bytesView.setUint8(i, code);
177
178
  }
178
179
  return bytes;
179
180
  }
@@ -212,12 +213,12 @@ function rotateLeft8(byte, distance) {
212
213
  function createXorObfuscationArray(password, rotateDistance) {
213
214
  const passwordBytes = passwordToAsciiBytes(password);
214
215
  const array = /* @__PURE__ */ new Uint8Array(16);
216
+ const arrayView = new DataView(array.buffer, array.byteOffset, array.byteLength);
215
217
  array.set(passwordBytes, 0);
216
- for (let i = passwordBytes.length; i < 16; i += 1) array[i] = PAD_ARRAY.getUint8(i - passwordBytes.length);
218
+ for (let i = passwordBytes.length; i < 16; i += 1) arrayView.setUint8(i, PAD_ARRAY.getUint8(i - passwordBytes.length));
217
219
  const xorKey = createXorObfuscationKey(password);
218
220
  const keyLow = xorKey & 255;
219
221
  const keyHigh = xorKey >>> 8 & 255;
220
- const arrayView = new DataView(array.buffer, array.byteOffset, array.byteLength);
221
222
  for (let i = 0; i < 16; i += 1) {
222
223
  const withKey = arrayView.getUint8(i) ^ (i % 2 === 0 ? keyLow : keyHigh);
223
224
  array[i] = rotateLeft8(withKey, rotateDistance);
@@ -169,10 +169,11 @@ const XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD2 = 7;
169
169
  function passwordToAsciiBytes(password) {
170
170
  if (password.length === 0 || password.length > 15) throw new RangeError(`XOR obfuscation passwords must be 1-15 characters, got ${password.length}`);
171
171
  const bytes = new Uint8Array(password.length);
172
+ const bytesView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
172
173
  for (let i = 0; i < password.length; i += 1) {
173
174
  const code = password.charCodeAt(i);
174
175
  if (code > 255) throw new RangeError(`XOR obfuscation passwords must be single-byte ASCII/Latin-1 characters, got code point ${code} at index ${i}`);
175
- bytes[i] = code;
176
+ bytesView.setUint8(i, code);
176
177
  }
177
178
  return bytes;
178
179
  }
@@ -211,12 +212,12 @@ function rotateLeft8(byte, distance) {
211
212
  function createXorObfuscationArray(password, rotateDistance) {
212
213
  const passwordBytes = passwordToAsciiBytes(password);
213
214
  const array = /* @__PURE__ */ new Uint8Array(16);
215
+ const arrayView = new DataView(array.buffer, array.byteOffset, array.byteLength);
214
216
  array.set(passwordBytes, 0);
215
- for (let i = passwordBytes.length; i < 16; i += 1) array[i] = PAD_ARRAY.getUint8(i - passwordBytes.length);
217
+ for (let i = passwordBytes.length; i < 16; i += 1) arrayView.setUint8(i, PAD_ARRAY.getUint8(i - passwordBytes.length));
216
218
  const xorKey = createXorObfuscationKey(password);
217
219
  const keyLow = xorKey & 255;
218
220
  const keyHigh = xorKey >>> 8 & 255;
219
- const arrayView = new DataView(array.buffer, array.byteOffset, array.byteLength);
220
221
  for (let i = 0; i < 16; i += 1) {
221
222
  const withKey = arrayView.getUint8(i) ^ (i % 2 === 0 ? keyLow : keyHigh);
222
223
  array[i] = rotateLeft8(withKey, rotateDistance);
package/dist/index.cjs CHANGED
@@ -41,14 +41,18 @@ exports.XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD2 = require_crypto_xor_obfuscation
41
41
  exports.createXorObfuscationArray = require_crypto_xor_obfuscation.createXorObfuscationArray;
42
42
  exports.createXorObfuscationKey = require_crypto_xor_obfuscation.createXorObfuscationKey;
43
43
  exports.createXorObfuscationPasswordVerifier = require_crypto_xor_obfuscation.createXorObfuscationPasswordVerifier;
44
+ exports.decodeCodepage = require_oleps_read.decodeCodepage;
44
45
  exports.decryptOfficeRc4 = require_crypto_office_rc4.decryptOfficeRc4;
45
46
  exports.decryptXorObfuscationMethod1 = require_crypto_xor_obfuscation.decryptXorObfuscationMethod1;
46
47
  exports.decryptXorObfuscationMethod2 = require_crypto_xor_obfuscation.decryptXorObfuscationMethod2;
48
+ exports.deepestDepth = require_cfb_write.deepestDepth;
47
49
  exports.deriveOfficeRc4BaseHash = require_crypto_office_rc4.deriveOfficeRc4BaseHash;
48
50
  exports.deriveOfficeRc4BlockKey = require_crypto_office_rc4.deriveOfficeRc4BlockKey;
49
51
  exports.deriveRc4CryptoApiBlockKey = require_crypto_office_rc4_cryptoapi.deriveRc4CryptoApiBlockKey;
50
52
  exports.detectArchiveFormat = require_zip_detect.detectArchiveFormat;
53
+ exports.exceedsVersion3StreamCeiling = require_cfb_write.exceedsVersion3StreamCeiling;
51
54
  exports.hasSummaryInformationFields = require_oleps_layout_metadata.hasSummaryInformationFields;
55
+ exports.highSizeWord = require_cfb_write.highSizeWord;
52
56
  exports.isCompoundFile = require_cfb_detect.isCompoundFile;
53
57
  exports.isZipArchive = require_zip_detect.isZipArchive;
54
58
  exports.layoutMetadataToSummaryInformation = require_oleps_layout_metadata.layoutMetadataToSummaryInformation;
@@ -60,10 +64,13 @@ exports.readOlePackage = require_cfb_ole_package.readOlePackage;
60
64
  exports.readPropertySetStream = require_oleps_read.readPropertySetStream;
61
65
  exports.readSummaryInformation = require_oleps_summary_information.readSummaryInformation;
62
66
  exports.sha1 = require_crypto_sha1.sha1;
67
+ exports.splitBitLength64 = require_crypto_md5.splitBitLength64;
63
68
  exports.summaryInformationToLayoutMetadata = require_oleps_layout_metadata.summaryInformationToLayoutMetadata;
69
+ exports.truncateAtNull = require_oleps_read.truncateAtNull;
64
70
  exports.unzipPackage = require_zip_container.unzipPackage;
65
71
  exports.verifyRc4CryptoApiPassword = require_crypto_office_rc4_cryptoapi.verifyRc4CryptoApiPassword;
66
72
  exports.walkArchive = require_zip_walk.walkArchive;
73
+ exports.writeBitLength64 = require_crypto_md5.writeBitLength64;
67
74
  exports.writeCompoundFile = require_cfb_write.writeCompoundFile;
68
75
  exports.writeOlePackage = require_cfb_ole_package.writeOlePackage;
69
76
  exports.writePropertySetStream = require_oleps_write.writePropertySetStream;
package/dist/index.d.cts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { isCompoundFile } from "./cfb/detect.cjs";
2
2
  import { OlePackage, OlePackageFormatError, OlePackageWriteError, readOlePackage, writeOlePackage } from "./cfb/ole-package.cjs";
3
3
  import { CompoundFileFormatError, CompoundFileStream, MAX_CFB_TOTAL_STREAM_BYTES, ReadCompoundFileOptions, readCompoundFile } from "./cfb/read.cjs";
4
- import { CompoundFileWriteError, WriteCompoundFileOptions, writeCompoundFile } from "./cfb/write.cjs";
5
- import { md5 } from "./crypto/md5.cjs";
4
+ import { CompoundFileWriteError, WriteCompoundFileOptions, deepestDepth, exceedsVersion3StreamCeiling, highSizeWord, writeCompoundFile } from "./cfb/write.cjs";
5
+ import { md5, splitBitLength64, writeBitLength64 } from "./crypto/md5.cjs";
6
6
  import { RC4_CRYPTOAPI_DEFAULT_KEY_SIZE_BITS, RC4_CRYPTOAPI_SALT_LENGTH, RC4_CRYPTOAPI_VERIFIER_HASH_LENGTH, RC4_CRYPTOAPI_VERIFIER_LENGTH, deriveRc4CryptoApiBlockKey, verifyRc4CryptoApiPassword } from "./crypto/office-rc4-cryptoapi.cjs";
7
7
  import { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, passwordToUtf16LeBytes } from "./crypto/office-rc4.cjs";
8
8
  import { rc4 } from "./crypto/rc4.cjs";
@@ -11,9 +11,9 @@ import { XOR_OBFUSCATION_ARRAY_LENGTH, XOR_OBFUSCATION_MAX_PASSWORD_LENGTH, XOR_
11
11
  import { FMTID_SUMMARY_INFORMATION, SummaryInformationProperties, readSummaryInformation, writeSummaryInformationStream } from "./oleps/summary-information.cjs";
12
12
  import { hasSummaryInformationFields, layoutMetadataToSummaryInformation, summaryInformationToLayoutMetadata } from "./oleps/layout-metadata.cjs";
13
13
  import { PropertySet, PropertyValue } from "./oleps/wire.cjs";
14
- import { PropertySetFormatError, readPropertySetStream } from "./oleps/read.cjs";
14
+ import { PropertySetFormatError, decodeCodepage, readPropertySetStream, truncateAtNull } from "./oleps/read.cjs";
15
15
  import { PropertySetWriteError, writePropertySetStream } from "./oleps/write.cjs";
16
16
  import { ZipEntry, unzipPackage, zipPackage } from "./zip/container.cjs";
17
17
  import { ArchiveFormat, detectArchiveFormat, isZipArchive } from "./zip/detect.cjs";
18
18
  import { ArchiveWalkEntry, ArchiveWalkLimit, ArchiveWalkLimitError, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, WalkArchiveOptions, walkArchive } from "./zip/walk.cjs";
19
- export { ArchiveFormat, ArchiveWalkEntry, ArchiveWalkLimit, ArchiveWalkLimitError, CompoundFileFormatError, CompoundFileStream, CompoundFileWriteError, FMTID_SUMMARY_INFORMATION, MAX_CFB_TOTAL_STREAM_BYTES, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, OlePackage, OlePackageFormatError, OlePackageWriteError, type PropertySet, PropertySetFormatError, PropertySetWriteError, type PropertyValue, RC4_CRYPTOAPI_DEFAULT_KEY_SIZE_BITS, RC4_CRYPTOAPI_SALT_LENGTH, RC4_CRYPTOAPI_VERIFIER_HASH_LENGTH, RC4_CRYPTOAPI_VERIFIER_LENGTH, ReadCompoundFileOptions, SummaryInformationProperties, WalkArchiveOptions, WriteCompoundFileOptions, XOR_OBFUSCATION_ARRAY_LENGTH, XOR_OBFUSCATION_MAX_PASSWORD_LENGTH, XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD1, XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD2, ZipEntry, createXorObfuscationArray, createXorObfuscationKey, createXorObfuscationPasswordVerifier, decryptOfficeRc4, decryptXorObfuscationMethod1, decryptXorObfuscationMethod2, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, deriveRc4CryptoApiBlockKey, detectArchiveFormat, hasSummaryInformationFields, isCompoundFile, isZipArchive, layoutMetadataToSummaryInformation, md5, passwordToUtf16LeBytes, rc4, readCompoundFile, readOlePackage, readPropertySetStream, readSummaryInformation, sha1, summaryInformationToLayoutMetadata, unzipPackage, verifyRc4CryptoApiPassword, walkArchive, writeCompoundFile, writeOlePackage, writePropertySetStream, writeSummaryInformationStream, zipPackage };
19
+ export { ArchiveFormat, ArchiveWalkEntry, ArchiveWalkLimit, ArchiveWalkLimitError, CompoundFileFormatError, CompoundFileStream, CompoundFileWriteError, FMTID_SUMMARY_INFORMATION, MAX_CFB_TOTAL_STREAM_BYTES, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, OlePackage, OlePackageFormatError, OlePackageWriteError, type PropertySet, PropertySetFormatError, PropertySetWriteError, type PropertyValue, RC4_CRYPTOAPI_DEFAULT_KEY_SIZE_BITS, RC4_CRYPTOAPI_SALT_LENGTH, RC4_CRYPTOAPI_VERIFIER_HASH_LENGTH, RC4_CRYPTOAPI_VERIFIER_LENGTH, ReadCompoundFileOptions, SummaryInformationProperties, WalkArchiveOptions, WriteCompoundFileOptions, XOR_OBFUSCATION_ARRAY_LENGTH, XOR_OBFUSCATION_MAX_PASSWORD_LENGTH, XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD1, XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD2, ZipEntry, createXorObfuscationArray, createXorObfuscationKey, createXorObfuscationPasswordVerifier, decodeCodepage, decryptOfficeRc4, decryptXorObfuscationMethod1, decryptXorObfuscationMethod2, deepestDepth, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, deriveRc4CryptoApiBlockKey, detectArchiveFormat, exceedsVersion3StreamCeiling, hasSummaryInformationFields, highSizeWord, isCompoundFile, isZipArchive, layoutMetadataToSummaryInformation, md5, passwordToUtf16LeBytes, rc4, readCompoundFile, readOlePackage, readPropertySetStream, readSummaryInformation, sha1, splitBitLength64, summaryInformationToLayoutMetadata, truncateAtNull, unzipPackage, verifyRc4CryptoApiPassword, walkArchive, writeBitLength64, writeCompoundFile, writeOlePackage, writePropertySetStream, writeSummaryInformationStream, zipPackage };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { isCompoundFile } from "./cfb/detect.js";
2
2
  import { OlePackage, OlePackageFormatError, OlePackageWriteError, readOlePackage, writeOlePackage } from "./cfb/ole-package.js";
3
3
  import { CompoundFileFormatError, CompoundFileStream, MAX_CFB_TOTAL_STREAM_BYTES, ReadCompoundFileOptions, readCompoundFile } from "./cfb/read.js";
4
- import { CompoundFileWriteError, WriteCompoundFileOptions, writeCompoundFile } from "./cfb/write.js";
5
- import { md5 } from "./crypto/md5.js";
4
+ import { CompoundFileWriteError, WriteCompoundFileOptions, deepestDepth, exceedsVersion3StreamCeiling, highSizeWord, writeCompoundFile } from "./cfb/write.js";
5
+ import { md5, splitBitLength64, writeBitLength64 } from "./crypto/md5.js";
6
6
  import { RC4_CRYPTOAPI_DEFAULT_KEY_SIZE_BITS, RC4_CRYPTOAPI_SALT_LENGTH, RC4_CRYPTOAPI_VERIFIER_HASH_LENGTH, RC4_CRYPTOAPI_VERIFIER_LENGTH, deriveRc4CryptoApiBlockKey, verifyRc4CryptoApiPassword } from "./crypto/office-rc4-cryptoapi.js";
7
7
  import { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, passwordToUtf16LeBytes } from "./crypto/office-rc4.js";
8
8
  import { rc4 } from "./crypto/rc4.js";
@@ -11,9 +11,9 @@ import { XOR_OBFUSCATION_ARRAY_LENGTH, XOR_OBFUSCATION_MAX_PASSWORD_LENGTH, XOR_
11
11
  import { FMTID_SUMMARY_INFORMATION, SummaryInformationProperties, readSummaryInformation, writeSummaryInformationStream } from "./oleps/summary-information.js";
12
12
  import { hasSummaryInformationFields, layoutMetadataToSummaryInformation, summaryInformationToLayoutMetadata } from "./oleps/layout-metadata.js";
13
13
  import { PropertySet, PropertyValue } from "./oleps/wire.js";
14
- import { PropertySetFormatError, readPropertySetStream } from "./oleps/read.js";
14
+ import { PropertySetFormatError, decodeCodepage, readPropertySetStream, truncateAtNull } from "./oleps/read.js";
15
15
  import { PropertySetWriteError, writePropertySetStream } from "./oleps/write.js";
16
16
  import { ZipEntry, unzipPackage, zipPackage } from "./zip/container.js";
17
17
  import { ArchiveFormat, detectArchiveFormat, isZipArchive } from "./zip/detect.js";
18
18
  import { ArchiveWalkEntry, ArchiveWalkLimit, ArchiveWalkLimitError, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, WalkArchiveOptions, walkArchive } from "./zip/walk.js";
19
- export { ArchiveFormat, ArchiveWalkEntry, ArchiveWalkLimit, ArchiveWalkLimitError, CompoundFileFormatError, CompoundFileStream, CompoundFileWriteError, FMTID_SUMMARY_INFORMATION, MAX_CFB_TOTAL_STREAM_BYTES, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, OlePackage, OlePackageFormatError, OlePackageWriteError, type PropertySet, PropertySetFormatError, PropertySetWriteError, type PropertyValue, RC4_CRYPTOAPI_DEFAULT_KEY_SIZE_BITS, RC4_CRYPTOAPI_SALT_LENGTH, RC4_CRYPTOAPI_VERIFIER_HASH_LENGTH, RC4_CRYPTOAPI_VERIFIER_LENGTH, ReadCompoundFileOptions, SummaryInformationProperties, WalkArchiveOptions, WriteCompoundFileOptions, XOR_OBFUSCATION_ARRAY_LENGTH, XOR_OBFUSCATION_MAX_PASSWORD_LENGTH, XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD1, XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD2, ZipEntry, createXorObfuscationArray, createXorObfuscationKey, createXorObfuscationPasswordVerifier, decryptOfficeRc4, decryptXorObfuscationMethod1, decryptXorObfuscationMethod2, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, deriveRc4CryptoApiBlockKey, detectArchiveFormat, hasSummaryInformationFields, isCompoundFile, isZipArchive, layoutMetadataToSummaryInformation, md5, passwordToUtf16LeBytes, rc4, readCompoundFile, readOlePackage, readPropertySetStream, readSummaryInformation, sha1, summaryInformationToLayoutMetadata, unzipPackage, verifyRc4CryptoApiPassword, walkArchive, writeCompoundFile, writeOlePackage, writePropertySetStream, writeSummaryInformationStream, zipPackage };
19
+ export { ArchiveFormat, ArchiveWalkEntry, ArchiveWalkLimit, ArchiveWalkLimitError, CompoundFileFormatError, CompoundFileStream, CompoundFileWriteError, FMTID_SUMMARY_INFORMATION, MAX_CFB_TOTAL_STREAM_BYTES, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, OlePackage, OlePackageFormatError, OlePackageWriteError, type PropertySet, PropertySetFormatError, PropertySetWriteError, type PropertyValue, RC4_CRYPTOAPI_DEFAULT_KEY_SIZE_BITS, RC4_CRYPTOAPI_SALT_LENGTH, RC4_CRYPTOAPI_VERIFIER_HASH_LENGTH, RC4_CRYPTOAPI_VERIFIER_LENGTH, ReadCompoundFileOptions, SummaryInformationProperties, WalkArchiveOptions, WriteCompoundFileOptions, XOR_OBFUSCATION_ARRAY_LENGTH, XOR_OBFUSCATION_MAX_PASSWORD_LENGTH, XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD1, XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD2, ZipEntry, createXorObfuscationArray, createXorObfuscationKey, createXorObfuscationPasswordVerifier, decodeCodepage, decryptOfficeRc4, decryptXorObfuscationMethod1, decryptXorObfuscationMethod2, deepestDepth, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, deriveRc4CryptoApiBlockKey, detectArchiveFormat, exceedsVersion3StreamCeiling, hasSummaryInformationFields, highSizeWord, isCompoundFile, isZipArchive, layoutMetadataToSummaryInformation, md5, passwordToUtf16LeBytes, rc4, readCompoundFile, readOlePackage, readPropertySetStream, readSummaryInformation, sha1, splitBitLength64, summaryInformationToLayoutMetadata, truncateAtNull, unzipPackage, verifyRc4CryptoApiPassword, walkArchive, writeBitLength64, writeCompoundFile, writeOlePackage, writePropertySetStream, writeSummaryInformationStream, zipPackage };
package/dist/index.js CHANGED
@@ -1,18 +1,18 @@
1
1
  import { isCompoundFile } from "./cfb/detect.js";
2
2
  import { OlePackageFormatError, OlePackageWriteError, readOlePackage, writeOlePackage } from "./cfb/ole-package.js";
3
3
  import { CompoundFileFormatError, MAX_CFB_TOTAL_STREAM_BYTES, readCompoundFile } from "./cfb/read.js";
4
- import { CompoundFileWriteError, writeCompoundFile } from "./cfb/write.js";
5
- import { md5 } from "./crypto/md5.js";
4
+ import { CompoundFileWriteError, deepestDepth, exceedsVersion3StreamCeiling, highSizeWord, writeCompoundFile } from "./cfb/write.js";
5
+ import { md5, splitBitLength64, writeBitLength64 } from "./crypto/md5.js";
6
6
  import { sha1 } from "./crypto/sha1.js";
7
7
  import { rc4 } from "./crypto/rc4.js";
8
8
  import { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, passwordToUtf16LeBytes } from "./crypto/office-rc4.js";
9
9
  import { RC4_CRYPTOAPI_DEFAULT_KEY_SIZE_BITS, RC4_CRYPTOAPI_SALT_LENGTH, RC4_CRYPTOAPI_VERIFIER_HASH_LENGTH, RC4_CRYPTOAPI_VERIFIER_LENGTH, deriveRc4CryptoApiBlockKey, verifyRc4CryptoApiPassword } from "./crypto/office-rc4-cryptoapi.js";
10
10
  import { XOR_OBFUSCATION_ARRAY_LENGTH, XOR_OBFUSCATION_MAX_PASSWORD_LENGTH, XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD1, XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD2, createXorObfuscationArray, createXorObfuscationKey, createXorObfuscationPasswordVerifier, decryptXorObfuscationMethod1, decryptXorObfuscationMethod2 } from "./crypto/xor-obfuscation.js";
11
11
  import { hasSummaryInformationFields, layoutMetadataToSummaryInformation, summaryInformationToLayoutMetadata } from "./oleps/layout-metadata.js";
12
- import { PropertySetFormatError, readPropertySetStream } from "./oleps/read.js";
12
+ import { PropertySetFormatError, decodeCodepage, readPropertySetStream, truncateAtNull } from "./oleps/read.js";
13
13
  import { PropertySetWriteError, writePropertySetStream } from "./oleps/write.js";
14
14
  import { FMTID_SUMMARY_INFORMATION, readSummaryInformation, writeSummaryInformationStream } from "./oleps/summary-information.js";
15
15
  import { unzipPackage, zipPackage } from "./zip/container.js";
16
16
  import { detectArchiveFormat, isZipArchive } from "./zip/detect.js";
17
17
  import { ArchiveWalkLimitError, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, walkArchive } from "./zip/walk.js";
18
- export { ArchiveWalkLimitError, CompoundFileFormatError, CompoundFileWriteError, FMTID_SUMMARY_INFORMATION, MAX_CFB_TOTAL_STREAM_BYTES, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, OlePackageFormatError, OlePackageWriteError, PropertySetFormatError, PropertySetWriteError, RC4_CRYPTOAPI_DEFAULT_KEY_SIZE_BITS, RC4_CRYPTOAPI_SALT_LENGTH, RC4_CRYPTOAPI_VERIFIER_HASH_LENGTH, RC4_CRYPTOAPI_VERIFIER_LENGTH, XOR_OBFUSCATION_ARRAY_LENGTH, XOR_OBFUSCATION_MAX_PASSWORD_LENGTH, XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD1, XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD2, createXorObfuscationArray, createXorObfuscationKey, createXorObfuscationPasswordVerifier, decryptOfficeRc4, decryptXorObfuscationMethod1, decryptXorObfuscationMethod2, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, deriveRc4CryptoApiBlockKey, detectArchiveFormat, hasSummaryInformationFields, isCompoundFile, isZipArchive, layoutMetadataToSummaryInformation, md5, passwordToUtf16LeBytes, rc4, readCompoundFile, readOlePackage, readPropertySetStream, readSummaryInformation, sha1, summaryInformationToLayoutMetadata, unzipPackage, verifyRc4CryptoApiPassword, walkArchive, writeCompoundFile, writeOlePackage, writePropertySetStream, writeSummaryInformationStream, zipPackage };
18
+ export { ArchiveWalkLimitError, CompoundFileFormatError, CompoundFileWriteError, FMTID_SUMMARY_INFORMATION, MAX_CFB_TOTAL_STREAM_BYTES, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, OlePackageFormatError, OlePackageWriteError, PropertySetFormatError, PropertySetWriteError, RC4_CRYPTOAPI_DEFAULT_KEY_SIZE_BITS, RC4_CRYPTOAPI_SALT_LENGTH, RC4_CRYPTOAPI_VERIFIER_HASH_LENGTH, RC4_CRYPTOAPI_VERIFIER_LENGTH, XOR_OBFUSCATION_ARRAY_LENGTH, XOR_OBFUSCATION_MAX_PASSWORD_LENGTH, XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD1, XOR_OBFUSCATION_ROTATE_DISTANCE_METHOD2, createXorObfuscationArray, createXorObfuscationKey, createXorObfuscationPasswordVerifier, decodeCodepage, decryptOfficeRc4, decryptXorObfuscationMethod1, decryptXorObfuscationMethod2, deepestDepth, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, deriveRc4CryptoApiBlockKey, detectArchiveFormat, exceedsVersion3StreamCeiling, hasSummaryInformationFields, highSizeWord, isCompoundFile, isZipArchive, layoutMetadataToSummaryInformation, md5, passwordToUtf16LeBytes, rc4, readCompoundFile, readOlePackage, readPropertySetStream, readSummaryInformation, sha1, splitBitLength64, summaryInformationToLayoutMetadata, truncateAtNull, unzipPackage, verifyRc4CryptoApiPassword, walkArchive, writeBitLength64, writeCompoundFile, writeOlePackage, writePropertySetStream, writeSummaryInformationStream, zipPackage };
package/dist/magic.cjs CHANGED
@@ -1,7 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#region src/magic.ts
3
3
  function startsWithMagic(bytes, magic) {
4
- if (bytes.length < magic.length) return false;
5
4
  for (let i = 0; i < magic.length; i++) if (bytes[i] !== magic[i]) return false;
6
5
  return true;
7
6
  }
package/dist/magic.js CHANGED
@@ -1,6 +1,5 @@
1
1
  //#region src/magic.ts
2
2
  function startsWithMagic(bytes, magic) {
3
- if (bytes.length < magic.length) return false;
4
3
  for (let i = 0; i < magic.length; i++) if (bytes[i] !== magic[i]) return false;
5
4
  return true;
6
5
  }
@@ -8,7 +8,10 @@ var PropertySetFormatError = class extends Error {
8
8
  }
9
9
  };
10
10
  function requireBytes(byteLength, offset, length, what) {
11
- if (offset < 0 || length < 0 || offset + length > byteLength) throw new PropertySetFormatError(`property set stream ends before ${what} (needs ${length} bytes at offset ${offset}, stream is ${byteLength} bytes)`);
11
+ if (offset + length > byteLength) throw new PropertySetFormatError(`property set stream ends before ${what} (needs ${length} bytes at offset ${offset}, stream is ${byteLength} bytes)`);
12
+ }
13
+ function decodeCodepage(raw) {
14
+ return raw < 0 ? raw + 65536 : raw;
12
15
  }
13
16
  const ANSI_DECODER = new TextDecoder("windows-1252");
14
17
  const UTF16_DECODER = new TextDecoder("utf-16le");
@@ -68,8 +71,7 @@ function readPropertySetStream(bytes) {
68
71
  requireBytes(bytes.length, abs, 8, "the CodePage property's TypedPropertyValue");
69
72
  const type = view.getUint16(abs, true);
70
73
  if (type !== 2) throw new PropertySetFormatError(`CodePage property (PID 1) has type 0x${type.toString(16)}, not VT_I2 as [MS-OLEPS] requires`);
71
- const raw = view.getInt16(abs + 4, true);
72
- codepage = raw < 0 ? raw + 65536 : raw;
74
+ codepage = decodeCodepage(view.getInt16(abs + 4, true));
73
75
  }
74
76
  const properties = /* @__PURE__ */ new Map();
75
77
  for (const entry of entries) {
@@ -129,4 +131,6 @@ function readPropertySetStream(bytes) {
129
131
  }
130
132
  //#endregion
131
133
  exports.PropertySetFormatError = PropertySetFormatError;
134
+ exports.decodeCodepage = decodeCodepage;
132
135
  exports.readPropertySetStream = readPropertySetStream;
136
+ exports.truncateAtNull = truncateAtNull;
@@ -3,6 +3,8 @@ import { PropertySet } from "./wire.cjs";
3
3
  declare class PropertySetFormatError extends Error {
4
4
  constructor(message: string);
5
5
  }
6
+ declare function decodeCodepage(raw: number): number;
7
+ declare function truncateAtNull(value: string): string;
6
8
  declare function readPropertySetStream(bytes: Uint8Array<ArrayBuffer>): PropertySet;
7
9
  //#endregion
8
- export { PropertySetFormatError, readPropertySetStream };
10
+ export { PropertySetFormatError, decodeCodepage, readPropertySetStream, truncateAtNull };
@@ -3,6 +3,8 @@ import { PropertySet } from "./wire.js";
3
3
  declare class PropertySetFormatError extends Error {
4
4
  constructor(message: string);
5
5
  }
6
+ declare function decodeCodepage(raw: number): number;
7
+ declare function truncateAtNull(value: string): string;
6
8
  declare function readPropertySetStream(bytes: Uint8Array<ArrayBuffer>): PropertySet;
7
9
  //#endregion
8
- export { PropertySetFormatError, readPropertySetStream };
10
+ export { PropertySetFormatError, decodeCodepage, readPropertySetStream, truncateAtNull };
@@ -7,7 +7,10 @@ var PropertySetFormatError = class extends Error {
7
7
  }
8
8
  };
9
9
  function requireBytes(byteLength, offset, length, what) {
10
- if (offset < 0 || length < 0 || offset + length > byteLength) throw new PropertySetFormatError(`property set stream ends before ${what} (needs ${length} bytes at offset ${offset}, stream is ${byteLength} bytes)`);
10
+ if (offset + length > byteLength) throw new PropertySetFormatError(`property set stream ends before ${what} (needs ${length} bytes at offset ${offset}, stream is ${byteLength} bytes)`);
11
+ }
12
+ function decodeCodepage(raw) {
13
+ return raw < 0 ? raw + 65536 : raw;
11
14
  }
12
15
  const ANSI_DECODER = new TextDecoder("windows-1252");
13
16
  const UTF16_DECODER = new TextDecoder("utf-16le");
@@ -67,8 +70,7 @@ function readPropertySetStream(bytes) {
67
70
  requireBytes(bytes.length, abs, 8, "the CodePage property's TypedPropertyValue");
68
71
  const type = view.getUint16(abs, true);
69
72
  if (type !== 2) throw new PropertySetFormatError(`CodePage property (PID 1) has type 0x${type.toString(16)}, not VT_I2 as [MS-OLEPS] requires`);
70
- const raw = view.getInt16(abs + 4, true);
71
- codepage = raw < 0 ? raw + 65536 : raw;
73
+ codepage = decodeCodepage(view.getInt16(abs + 4, true));
72
74
  }
73
75
  const properties = /* @__PURE__ */ new Map();
74
76
  for (const entry of entries) {
@@ -127,4 +129,4 @@ function readPropertySetStream(bytes) {
127
129
  };
128
130
  }
129
131
  //#endregion
130
- export { PropertySetFormatError, readPropertySetStream };
132
+ export { PropertySetFormatError, decodeCodepage, readPropertySetStream, truncateAtNull };
@@ -28,12 +28,24 @@ function readGuid(view, offset) {
28
28
  for (let i = 2; i < 8; i++) data4b += hex(view.getUint8(offset + 8 + i), 2);
29
29
  return `{${data1}-${data2}-${data3}-${data4a}-${data4b}}`.toUpperCase();
30
30
  }
31
+ function hexByte(digits, charIndex) {
32
+ return Number.parseInt(digits.slice(charIndex, charIndex + 2), 16);
33
+ }
31
34
  function writeGuid(view, offset, guid) {
32
35
  const digits = guid.replace(/[{}-]/g, "");
33
36
  view.setUint32(offset, Number.parseInt(digits.slice(0, 8), 16), true);
34
37
  view.setUint16(offset + 4, Number.parseInt(digits.slice(8, 12), 16), true);
35
38
  view.setUint16(offset + 6, Number.parseInt(digits.slice(12, 16), 16), true);
36
- for (let i = 0; i < 8; i++) view.setUint8(offset + 8 + i, Number.parseInt(digits.slice(16 + i * 2, 18 + i * 2), 16));
39
+ for (const i of [
40
+ 0,
41
+ 1,
42
+ 2,
43
+ 3,
44
+ 4,
45
+ 5,
46
+ 6,
47
+ 7
48
+ ]) view.setUint8(offset + 8 + i, hexByte(digits, 16 + i * 2));
37
49
  }
38
50
  const FILETIME_EPOCH_OFFSET_100NS = 116444736000000000n;
39
51
  const HUNDRED_NS_PER_MS = 10000n;
@@ -27,12 +27,24 @@ function readGuid(view, offset) {
27
27
  for (let i = 2; i < 8; i++) data4b += hex(view.getUint8(offset + 8 + i), 2);
28
28
  return `{${data1}-${data2}-${data3}-${data4a}-${data4b}}`.toUpperCase();
29
29
  }
30
+ function hexByte(digits, charIndex) {
31
+ return Number.parseInt(digits.slice(charIndex, charIndex + 2), 16);
32
+ }
30
33
  function writeGuid(view, offset, guid) {
31
34
  const digits = guid.replace(/[{}-]/g, "");
32
35
  view.setUint32(offset, Number.parseInt(digits.slice(0, 8), 16), true);
33
36
  view.setUint16(offset + 4, Number.parseInt(digits.slice(8, 12), 16), true);
34
37
  view.setUint16(offset + 6, Number.parseInt(digits.slice(12, 16), 16), true);
35
- for (let i = 0; i < 8; i++) view.setUint8(offset + 8 + i, Number.parseInt(digits.slice(16 + i * 2, 18 + i * 2), 16));
38
+ for (const i of [
39
+ 0,
40
+ 1,
41
+ 2,
42
+ 3,
43
+ 4,
44
+ 5,
45
+ 6,
46
+ 7
47
+ ]) view.setUint8(offset + 8 + i, hexByte(digits, 16 + i * 2));
36
48
  }
37
49
  const FILETIME_EPOCH_OFFSET_100NS = 116444736000000000n;
38
50
  const HUNDRED_NS_PER_MS = 10000n;
@@ -10,8 +10,9 @@ var PropertySetWriteError = class extends Error {
10
10
  function encodeUnicodeStringValue(value) {
11
11
  const characterBytes = new Uint8Array((value.length + 1) * 2);
12
12
  const charView = new DataView(characterBytes.buffer);
13
- for (let i = 0; i < value.length; i++) charView.setUint16(i * 2, value.charCodeAt(i), true);
14
- charView.setUint16(value.length * 2, 0, true);
13
+ value.split("").forEach((unit, i) => {
14
+ charView.setUint16(i * 2, unit.charCodeAt(0), true);
15
+ });
15
16
  return characterBytes;
16
17
  }
17
18
  function padTo4(length) {
@@ -23,16 +24,13 @@ function encodeTypedPropertyValue(value) {
23
24
  const bytes = /* @__PURE__ */ new Uint8Array(8);
24
25
  const view = new DataView(bytes.buffer);
25
26
  view.setUint16(0, 2, true);
26
- view.setUint16(2, 0, true);
27
27
  view.setInt16(4, value.value, true);
28
- view.setUint16(6, 0, true);
29
28
  return bytes;
30
29
  }
31
30
  case "VT_I4": {
32
31
  const bytes = /* @__PURE__ */ new Uint8Array(8);
33
32
  const view = new DataView(bytes.buffer);
34
33
  view.setUint16(0, 3, true);
35
- view.setUint16(2, 0, true);
36
34
  view.setInt32(4, value.value, true);
37
35
  return bytes;
38
36
  }
@@ -41,7 +39,6 @@ function encodeTypedPropertyValue(value) {
41
39
  const bytes = /* @__PURE__ */ new Uint8Array(12);
42
40
  const view = new DataView(bytes.buffer);
43
41
  view.setUint16(0, 64, true);
44
- view.setUint16(2, 0, true);
45
42
  view.setUint32(4, low, true);
46
43
  view.setUint32(8, high, true);
47
44
  return bytes;
@@ -52,7 +49,6 @@ function encodeTypedPropertyValue(value) {
52
49
  const bytes = new Uint8Array(8 + paddedLength);
53
50
  const view = new DataView(bytes.buffer);
54
51
  view.setUint16(0, 31, true);
55
- view.setUint16(2, 0, true);
56
52
  view.setUint32(4, characters.length / 2, true);
57
53
  bytes.set(characters, 8);
58
54
  return bytes;
@@ -89,9 +85,6 @@ function writePropertySetStream(propertySet) {
89
85
  const streamBytes = new Uint8Array(48 + propertySetBytes.length);
90
86
  const view = new DataView(streamBytes.buffer);
91
87
  view.setUint16(0, require_oleps_wire.BYTE_ORDER_MARK, true);
92
- view.setUint16(2, 0, true);
93
- view.setUint32(4, 0, true);
94
- require_oleps_wire.writeGuid(view, 8, require_oleps_wire.GUID_NULL);
95
88
  view.setUint32(24, 1, true);
96
89
  require_oleps_wire.writeGuid(view, 28, propertySet.formatId);
97
90
  view.setUint32(44, 48, true);
@@ -1,4 +1,4 @@
1
- import { BYTE_ORDER_MARK, GUID_NULL, dateToFiletime, writeGuid } from "./wire.js";
1
+ import { BYTE_ORDER_MARK, dateToFiletime, writeGuid } from "./wire.js";
2
2
  //#region src/oleps/write.ts
3
3
  var PropertySetWriteError = class extends Error {
4
4
  constructor(message) {
@@ -9,8 +9,9 @@ var PropertySetWriteError = class extends Error {
9
9
  function encodeUnicodeStringValue(value) {
10
10
  const characterBytes = new Uint8Array((value.length + 1) * 2);
11
11
  const charView = new DataView(characterBytes.buffer);
12
- for (let i = 0; i < value.length; i++) charView.setUint16(i * 2, value.charCodeAt(i), true);
13
- charView.setUint16(value.length * 2, 0, true);
12
+ value.split("").forEach((unit, i) => {
13
+ charView.setUint16(i * 2, unit.charCodeAt(0), true);
14
+ });
14
15
  return characterBytes;
15
16
  }
16
17
  function padTo4(length) {
@@ -22,16 +23,13 @@ function encodeTypedPropertyValue(value) {
22
23
  const bytes = /* @__PURE__ */ new Uint8Array(8);
23
24
  const view = new DataView(bytes.buffer);
24
25
  view.setUint16(0, 2, true);
25
- view.setUint16(2, 0, true);
26
26
  view.setInt16(4, value.value, true);
27
- view.setUint16(6, 0, true);
28
27
  return bytes;
29
28
  }
30
29
  case "VT_I4": {
31
30
  const bytes = /* @__PURE__ */ new Uint8Array(8);
32
31
  const view = new DataView(bytes.buffer);
33
32
  view.setUint16(0, 3, true);
34
- view.setUint16(2, 0, true);
35
33
  view.setInt32(4, value.value, true);
36
34
  return bytes;
37
35
  }
@@ -40,7 +38,6 @@ function encodeTypedPropertyValue(value) {
40
38
  const bytes = /* @__PURE__ */ new Uint8Array(12);
41
39
  const view = new DataView(bytes.buffer);
42
40
  view.setUint16(0, 64, true);
43
- view.setUint16(2, 0, true);
44
41
  view.setUint32(4, low, true);
45
42
  view.setUint32(8, high, true);
46
43
  return bytes;
@@ -51,7 +48,6 @@ function encodeTypedPropertyValue(value) {
51
48
  const bytes = new Uint8Array(8 + paddedLength);
52
49
  const view = new DataView(bytes.buffer);
53
50
  view.setUint16(0, 31, true);
54
- view.setUint16(2, 0, true);
55
51
  view.setUint32(4, characters.length / 2, true);
56
52
  bytes.set(characters, 8);
57
53
  return bytes;
@@ -88,9 +84,6 @@ function writePropertySetStream(propertySet) {
88
84
  const streamBytes = new Uint8Array(48 + propertySetBytes.length);
89
85
  const view = new DataView(streamBytes.buffer);
90
86
  view.setUint16(0, BYTE_ORDER_MARK, true);
91
- view.setUint16(2, 0, true);
92
- view.setUint32(4, 0, true);
93
- writeGuid(view, 8, GUID_NULL);
94
87
  view.setUint32(24, 1, true);
95
88
  writeGuid(view, 28, propertySet.formatId);
96
89
  view.setUint32(44, 48, true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archive-codec",
3
- "version": "1.11.2",
3
+ "version": "1.11.3",
4
4
  "description": "ZIP-in-ZIP recursive walking with depth and cumulative decompressed-size guards, bounded classic OLE compound-file ([MS-CFB]) reading and writing, and [MS-OLEPS] Property Set Stream reading and writing - zero document-format knowledge, the archive and container utility package for the documents.js family.",
5
5
  "type": "module",
6
6
  "repository": {