pptx-viewer-core 1.1.33 → 1.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6984,15 +6984,15 @@ var PptxMediaDataParser = class {
6984
6984
 
6985
6985
  // src/core/utils/ole-utils.ts
6986
6986
  var PROG_ID_MAP = [
6987
- { pattern: /^Excel\./i, type: "excel", extension: "xlsx" },
6988
- { pattern: /^Word\./i, type: "word", extension: "docx" },
6989
- { pattern: /^PowerPoint\./i, type: "excel", extension: "pptx" },
6990
- { pattern: /^Visio\./i, type: "visio", extension: "vsdx" },
6991
- { pattern: /^Equation\./i, type: "mathtype", extension: "wmf" },
6992
- { pattern: /^MathType/i, type: "mathtype", extension: "wmf" },
6993
- { pattern: /^AcroExch\./i, type: "pdf", extension: "pdf" },
6994
- { pattern: /^Acrobat\./i, type: "pdf", extension: "pdf" },
6995
- { pattern: /^Package$/i, type: "package", extension: "bin" }
6987
+ { pattern: /^Excel\./iu, type: "excel", extension: "xlsx" },
6988
+ { pattern: /^Word\./iu, type: "word", extension: "docx" },
6989
+ { pattern: /^PowerPoint\./iu, type: "excel", extension: "pptx" },
6990
+ { pattern: /^Visio\./iu, type: "visio", extension: "vsdx" },
6991
+ { pattern: /^Equation\./iu, type: "mathtype", extension: "wmf" },
6992
+ { pattern: /^MathType/iu, type: "mathtype", extension: "wmf" },
6993
+ { pattern: /^AcroExch\./iu, type: "pdf", extension: "pdf" },
6994
+ { pattern: /^Acrobat\./iu, type: "pdf", extension: "pdf" },
6995
+ { pattern: /^Package$/iu, type: "package", extension: "bin" }
6996
6996
  ];
6997
6997
  var CLSID_MAP = /* @__PURE__ */ new Map([
6998
6998
  // Excel Workbook
@@ -7019,7 +7019,7 @@ function detectOleObjectType(progId, clsId) {
7019
7019
  }
7020
7020
  }
7021
7021
  if (clsId) {
7022
- const normalised = clsId.replace(/[{}]/g, "").toUpperCase().trim();
7022
+ const normalised = clsId.replace(/[{}]/gu, "").toUpperCase().trim();
7023
7023
  const match = CLSID_MAP.get(normalised);
7024
7024
  if (match) {
7025
7025
  return { oleObjectType: match.type, oleFileExtension: match.extension };
@@ -7041,6 +7041,38 @@ function inferOleExtensionFromTarget(oleTarget) {
7041
7041
  }
7042
7042
  return void 0;
7043
7043
  }
7044
+ var OLE_EXTENSION_MIME_MAP = /* @__PURE__ */ new Map([
7045
+ ["xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],
7046
+ ["xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12"],
7047
+ ["xls", "application/vnd.ms-excel"],
7048
+ ["docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"],
7049
+ ["docm", "application/vnd.ms-word.document.macroEnabled.12"],
7050
+ ["doc", "application/msword"],
7051
+ ["pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"],
7052
+ ["ppt", "application/vnd.ms-powerpoint"],
7053
+ ["vsdx", "application/vnd.ms-visio.drawing"],
7054
+ ["vsd", "application/vnd.visio"],
7055
+ ["pdf", "application/pdf"],
7056
+ ["rtf", "application/rtf"],
7057
+ ["txt", "text/plain"],
7058
+ ["csv", "text/csv"],
7059
+ ["png", "image/png"],
7060
+ ["jpg", "image/jpeg"],
7061
+ ["jpeg", "image/jpeg"],
7062
+ ["gif", "image/gif"],
7063
+ ["wmf", "image/wmf"],
7064
+ ["emf", "image/emf"],
7065
+ ["zip", "application/zip"]
7066
+ ]);
7067
+ function mimeTypeForOleFile(fileNameOrExtension) {
7068
+ const fallback = "application/octet-stream";
7069
+ if (!fileNameOrExtension) {
7070
+ return fallback;
7071
+ }
7072
+ const lastDot = fileNameOrExtension.lastIndexOf(".");
7073
+ const ext = (lastDot === -1 ? fileNameOrExtension : fileNameOrExtension.slice(lastDot + 1)).toLowerCase().trim();
7074
+ return OLE_EXTENSION_MIME_MAP.get(ext) ?? fallback;
7075
+ }
7044
7076
  function getOleObjectTypeLabel(oleObjectType) {
7045
7077
  switch (oleObjectType) {
7046
7078
  case "excel":
@@ -8767,6 +8799,7 @@ var PptxSlideLoaderService = class {
8767
8799
  if (mediaTimingMap.size > 0) {
8768
8800
  await params.enrichMediaElementsWithTiming(slideElements, mediaTimingMap);
8769
8801
  }
8802
+ await params.enrichOleElementsWithEmbeddedData(slideElements, path);
8770
8803
  const elements = [...layoutElements, ...slideElements];
8771
8804
  const backgroundColor = params.extractBackgroundColor(slideXmlObj) || await params.getLayoutBackgroundColor(path);
8772
8805
  const backgroundGradient = params.extractBackgroundGradient(slideXmlObj) || await params.getLayoutBackgroundGradient(path);
@@ -12348,6 +12381,321 @@ function resolveLayoutDisplayName(input) {
12348
12381
  return fallbackFromPath(input.path);
12349
12382
  }
12350
12383
 
12384
+ // src/core/utils/ole2-parser-types.ts
12385
+ var OLE_MAGIC = new Uint8Array([208, 207, 17, 224, 161, 27, 26, 225]);
12386
+ var ENDOFCHAIN = 4294967294;
12387
+ var FREESECT = 4294967295;
12388
+ var FATSECT = 4294967293;
12389
+ var MAXREGSECT = 4294967290;
12390
+ var ENTRY_TYPE_EMPTY = 0;
12391
+ var ENTRY_TYPE_STREAM = 2;
12392
+ var ENTRY_TYPE_ROOT = 5;
12393
+ var DIR_ENTRY_SIZE = 128;
12394
+ var Ole2ParseError = class extends Error {
12395
+ constructor(message) {
12396
+ super(message);
12397
+ this.name = "Ole2ParseError";
12398
+ }
12399
+ };
12400
+
12401
+ // src/core/utils/ole2-parser-read.ts
12402
+ function parseOle2(buffer) {
12403
+ const data = new Uint8Array(buffer);
12404
+ const view = new DataView(buffer);
12405
+ for (let i = 0; i < OLE_MAGIC.length; i++) {
12406
+ if (data[i] !== OLE_MAGIC[i]) {
12407
+ throw new Ole2ParseError("Not a valid OLE2 compound file");
12408
+ }
12409
+ }
12410
+ view.getUint16(24, true);
12411
+ const majorVersion = view.getUint16(26, true);
12412
+ const byteOrder = view.getUint16(28, true);
12413
+ if (byteOrder !== 65534) {
12414
+ throw new Ole2ParseError("Invalid byte order mark");
12415
+ }
12416
+ const sectorSizePower = view.getUint16(30, true);
12417
+ const miniSectorSizePower = view.getUint16(32, true);
12418
+ const sectorSize = 1 << sectorSizePower;
12419
+ const miniSectorSize = 1 << miniSectorSizePower;
12420
+ const totalFATSectors = view.getUint32(44, true);
12421
+ const firstDirectorySector = view.getUint32(48, true);
12422
+ const miniStreamCutoff = view.getUint32(56, true);
12423
+ const firstMiniFATSector = view.getUint32(60, true);
12424
+ const totalMiniFATSectors = view.getUint32(64, true);
12425
+ const firstDIFATSector = view.getUint32(68, true);
12426
+ const totalDIFATSectors = view.getUint32(72, true);
12427
+ function sectorOffset(sector) {
12428
+ return (sector + 1) * sectorSize;
12429
+ }
12430
+ function readSector(sector) {
12431
+ const offset = sectorOffset(sector);
12432
+ if (offset + sectorSize > data.length) {
12433
+ throw new Ole2ParseError(
12434
+ `Sector ${sector} at offset ${offset} exceeds file size ${data.length}`
12435
+ );
12436
+ }
12437
+ return data.subarray(offset, offset + sectorSize);
12438
+ }
12439
+ const fatSectors = [];
12440
+ for (let i = 0; i < 109 && fatSectors.length < totalFATSectors; i++) {
12441
+ const sector = view.getUint32(76 + i * 4, true);
12442
+ if (sector <= MAXREGSECT) {
12443
+ fatSectors.push(sector);
12444
+ }
12445
+ }
12446
+ let difatSector = firstDIFATSector;
12447
+ for (let d = 0; d < totalDIFATSectors && difatSector <= MAXREGSECT; d++) {
12448
+ const difatData = readSector(difatSector);
12449
+ const difatView = new DataView(difatData.buffer, difatData.byteOffset, difatData.byteLength);
12450
+ const entriesPerSector = (sectorSize - 4) / 4;
12451
+ for (let i = 0; i < entriesPerSector && fatSectors.length < totalFATSectors; i++) {
12452
+ const sector = difatView.getUint32(i * 4, true);
12453
+ if (sector <= MAXREGSECT) {
12454
+ fatSectors.push(sector);
12455
+ }
12456
+ }
12457
+ difatSector = difatView.getUint32(sectorSize - 4, true);
12458
+ }
12459
+ const fatEntries = [];
12460
+ for (const fatSector of fatSectors) {
12461
+ const fatData = readSector(fatSector);
12462
+ const fatView = new DataView(fatData.buffer, fatData.byteOffset, fatData.byteLength);
12463
+ for (let i = 0; i < sectorSize / 4; i++) {
12464
+ fatEntries.push(fatView.getUint32(i * 4, true));
12465
+ }
12466
+ }
12467
+ function readSectorChain(startSector) {
12468
+ const sectors = [];
12469
+ let current = startSector;
12470
+ const visited = /* @__PURE__ */ new Set();
12471
+ while (current <= MAXREGSECT) {
12472
+ if (visited.has(current)) {
12473
+ throw new Ole2ParseError(`Circular reference in FAT chain at sector ${current}`);
12474
+ }
12475
+ visited.add(current);
12476
+ sectors.push(readSector(current));
12477
+ current = fatEntries[current] ?? ENDOFCHAIN;
12478
+ }
12479
+ const totalLength = sectors.length * sectorSize;
12480
+ const result = new Uint8Array(totalLength);
12481
+ let offset = 0;
12482
+ for (const sector of sectors) {
12483
+ result.set(sector, offset);
12484
+ offset += sectorSize;
12485
+ }
12486
+ return result;
12487
+ }
12488
+ function readStream(startSector, size) {
12489
+ const raw = readSectorChain(startSector);
12490
+ return raw.subarray(0, Math.min(size, raw.length));
12491
+ }
12492
+ const miniFatEntries = [];
12493
+ if (firstMiniFATSector <= MAXREGSECT && totalMiniFATSectors > 0) {
12494
+ const miniFatRaw = readSectorChain(firstMiniFATSector);
12495
+ const miniFatView = new DataView(
12496
+ miniFatRaw.buffer,
12497
+ miniFatRaw.byteOffset,
12498
+ miniFatRaw.byteLength
12499
+ );
12500
+ for (let i = 0; i < miniFatRaw.length / 4; i++) {
12501
+ miniFatEntries.push(miniFatView.getUint32(i * 4, true));
12502
+ }
12503
+ }
12504
+ const dirRaw = readSectorChain(firstDirectorySector);
12505
+ const numEntries = Math.floor(dirRaw.length / DIR_ENTRY_SIZE);
12506
+ const entries = [];
12507
+ for (let i = 0; i < numEntries; i++) {
12508
+ const entryOffset = i * DIR_ENTRY_SIZE;
12509
+ const entryView = new DataView(dirRaw.buffer, dirRaw.byteOffset + entryOffset, DIR_ENTRY_SIZE);
12510
+ const nameLen = entryView.getUint16(64, true);
12511
+ const objectType = entryView.getUint8(66);
12512
+ if (objectType === ENTRY_TYPE_EMPTY) {
12513
+ continue;
12514
+ }
12515
+ const nameBytes = Math.max(0, nameLen - 2);
12516
+ let name = "";
12517
+ for (let j = 0; j < nameBytes; j += 2) {
12518
+ name += String.fromCharCode(entryView.getUint16(j, true));
12519
+ }
12520
+ const leftSiblingId = entryView.getUint32(68, true);
12521
+ const rightSiblingId = entryView.getUint32(72, true);
12522
+ const childId = entryView.getUint32(76, true);
12523
+ const startSector = entryView.getUint32(116, true);
12524
+ const sizeLow = entryView.getUint32(120, true);
12525
+ let size = sizeLow;
12526
+ if (majorVersion === 4) {
12527
+ entryView.getUint32(124, true);
12528
+ size = sizeLow;
12529
+ }
12530
+ entries.push({
12531
+ name,
12532
+ type: objectType,
12533
+ startSector,
12534
+ size,
12535
+ childId: childId === 4294967295 ? -1 : childId,
12536
+ leftSiblingId: leftSiblingId === 4294967295 ? -1 : leftSiblingId,
12537
+ rightSiblingId: rightSiblingId === 4294967295 ? -1 : rightSiblingId
12538
+ });
12539
+ }
12540
+ const rootEntry = entries.find((e) => e.type === ENTRY_TYPE_ROOT);
12541
+ let miniStreamData;
12542
+ if (rootEntry && rootEntry.startSector <= MAXREGSECT) {
12543
+ miniStreamData = readSectorChain(rootEntry.startSector);
12544
+ }
12545
+ function readMiniStream(startSector, size) {
12546
+ if (!miniStreamData) {
12547
+ throw new Ole2ParseError("Mini stream container not found");
12548
+ }
12549
+ const sectors = [];
12550
+ let current = startSector;
12551
+ const visited = /* @__PURE__ */ new Set();
12552
+ while (current <= MAXREGSECT) {
12553
+ if (visited.has(current)) {
12554
+ throw new Ole2ParseError(`Circular reference in mini FAT chain at sector ${current}`);
12555
+ }
12556
+ visited.add(current);
12557
+ const offset2 = current * miniSectorSize;
12558
+ sectors.push(miniStreamData.subarray(offset2, offset2 + miniSectorSize));
12559
+ current = miniFatEntries[current] ?? ENDOFCHAIN;
12560
+ }
12561
+ const totalLength = sectors.length * miniSectorSize;
12562
+ const result = new Uint8Array(totalLength);
12563
+ let offset = 0;
12564
+ for (const sector of sectors) {
12565
+ result.set(sector, offset);
12566
+ offset += miniSectorSize;
12567
+ }
12568
+ return result.subarray(0, Math.min(size, result.length));
12569
+ }
12570
+ function getStream(name) {
12571
+ const entry = entries.find(
12572
+ (e) => (e.type === ENTRY_TYPE_STREAM || e.type === ENTRY_TYPE_ROOT) && e.name === name
12573
+ );
12574
+ if (!entry) {
12575
+ return void 0;
12576
+ }
12577
+ if (entry.size < miniStreamCutoff && entry.type !== ENTRY_TYPE_ROOT) {
12578
+ return readMiniStream(entry.startSector, entry.size);
12579
+ }
12580
+ return readStream(entry.startSector, entry.size);
12581
+ }
12582
+ return { entries, getStream };
12583
+ }
12584
+
12585
+ // src/core/utils/ole-embedded-extract.ts
12586
+ function oleBytesToDataUrl(bytes, mimeType) {
12587
+ let binary = "";
12588
+ const chunkSize = 32768;
12589
+ for (let i = 0; i < bytes.length; i += chunkSize) {
12590
+ const chunk = bytes.subarray(i, i + chunkSize);
12591
+ binary += String.fromCharCode.apply(null, Array.from(chunk));
12592
+ }
12593
+ return `data:${mimeType};base64,${btoa(binary)}`;
12594
+ }
12595
+ var OLE10_NATIVE_STREAM_NAMES = [`${String.fromCharCode(1)}Ole10Native`, "Ole10Native"];
12596
+ var CONTENTS_STREAM = "CONTENTS";
12597
+ function isOle2CompoundFile(bytes) {
12598
+ if (bytes.length < OLE_MAGIC.length) {
12599
+ return false;
12600
+ }
12601
+ for (let i = 0; i < OLE_MAGIC.length; i++) {
12602
+ if (bytes[i] !== OLE_MAGIC[i]) {
12603
+ return false;
12604
+ }
12605
+ }
12606
+ return true;
12607
+ }
12608
+ function baseNameFromPath(raw) {
12609
+ const trimmed = raw.trim();
12610
+ if (trimmed.length === 0) {
12611
+ return void 0;
12612
+ }
12613
+ const lastSlash = Math.max(trimmed.lastIndexOf("\\"), trimmed.lastIndexOf("/"));
12614
+ const base = lastSlash === -1 ? trimmed : trimmed.slice(lastSlash + 1);
12615
+ return base.length > 0 ? base : void 0;
12616
+ }
12617
+ function readAsciiZ(bytes, offset) {
12618
+ let end = offset;
12619
+ while (end < bytes.length && bytes[end] !== 0) {
12620
+ end++;
12621
+ }
12622
+ let value = "";
12623
+ for (let i = offset; i < end; i++) {
12624
+ value += String.fromCharCode(bytes[i]);
12625
+ }
12626
+ return { value, next: end < bytes.length ? end + 1 : end };
12627
+ }
12628
+ function decodeOle10Native(stream) {
12629
+ if (stream.length < 6) {
12630
+ return void 0;
12631
+ }
12632
+ const view = new DataView(stream.buffer, stream.byteOffset, stream.byteLength);
12633
+ const declaredSize = view.getUint32(0, true);
12634
+ const bodyEnd = Math.min(stream.length, 4 + declaredSize);
12635
+ if (bodyEnd <= 4) {
12636
+ return void 0;
12637
+ }
12638
+ let cursor = 6;
12639
+ const label = readAsciiZ(stream, cursor);
12640
+ cursor = label.next;
12641
+ const sourcePath = readAsciiZ(stream, cursor);
12642
+ cursor = sourcePath.next;
12643
+ if (cursor + 8 > stream.length) {
12644
+ return void 0;
12645
+ }
12646
+ cursor += 4;
12647
+ const tempLen = view.getUint32(cursor, true);
12648
+ cursor += 4;
12649
+ if (tempLen > stream.length) {
12650
+ return void 0;
12651
+ }
12652
+ cursor += tempLen;
12653
+ if (cursor + 4 > stream.length) {
12654
+ return void 0;
12655
+ }
12656
+ const nativeSize = view.getUint32(cursor, true);
12657
+ cursor += 4;
12658
+ const dataEnd = Math.min(stream.length, cursor + nativeSize);
12659
+ if (dataEnd <= cursor) {
12660
+ return void 0;
12661
+ }
12662
+ const data = stream.subarray(cursor, dataEnd);
12663
+ const fileName = baseNameFromPath(sourcePath.value) ?? baseNameFromPath(label.value) ?? void 0;
12664
+ return { fileName, data };
12665
+ }
12666
+ function unwrapOleEmbedding(bytes) {
12667
+ if (bytes.length === 0) {
12668
+ return { data: bytes };
12669
+ }
12670
+ if (!isOle2CompoundFile(bytes)) {
12671
+ return { data: bytes };
12672
+ }
12673
+ try {
12674
+ const buffer = bytes.buffer.slice(
12675
+ bytes.byteOffset,
12676
+ bytes.byteOffset + bytes.byteLength
12677
+ );
12678
+ const ole = parseOle2(buffer);
12679
+ for (const name of OLE10_NATIVE_STREAM_NAMES) {
12680
+ const ole10 = ole.getStream(name);
12681
+ if (!ole10) {
12682
+ continue;
12683
+ }
12684
+ const decoded = decodeOle10Native(ole10);
12685
+ if (decoded && decoded.data.length > 0) {
12686
+ return decoded;
12687
+ }
12688
+ return { data: ole10 };
12689
+ }
12690
+ const contents = ole.getStream(CONTENTS_STREAM);
12691
+ if (contents && contents.length > 0) {
12692
+ return { data: contents };
12693
+ }
12694
+ } catch {
12695
+ }
12696
+ return { data: bytes };
12697
+ }
12698
+
12351
12699
  // src/core/utils/signature-constants.ts
12352
12700
  var DIGITAL_SIGNATURE_ORIGIN_REL_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin";
12353
12701
  var DIGITAL_SIGNATURE_REL_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/signature";
@@ -18314,14 +18662,14 @@ function resolveLayoutCategory(layoutType) {
18314
18662
  }
18315
18663
 
18316
18664
  // src/core/utils/encryption-detection.ts
18317
- var OLE_MAGIC = new Uint8Array([208, 207, 17, 224, 161, 27, 26, 225]);
18665
+ var OLE_MAGIC2 = new Uint8Array([208, 207, 17, 224, 161, 27, 26, 225]);
18318
18666
  var ZIP_MAGIC = new Uint8Array([80, 75]);
18319
18667
  function detectFileFormat(data) {
18320
18668
  if (data.byteLength < 8) {
18321
18669
  return { format: "unknown", encrypted: false };
18322
18670
  }
18323
18671
  const header = new Uint8Array(data, 0, 8);
18324
- if (OLE_MAGIC.every((byte, i) => header[i] === byte)) {
18672
+ if (OLE_MAGIC2.every((byte, i) => header[i] === byte)) {
18325
18673
  return { format: "ole", encrypted: true };
18326
18674
  }
18327
18675
  if (header[0] === ZIP_MAGIC[0] && header[1] === ZIP_MAGIC[1]) {
@@ -18337,207 +18685,6 @@ var EncryptedFileError = class extends Error {
18337
18685
  }
18338
18686
  };
18339
18687
 
18340
- // src/core/utils/ole2-parser-types.ts
18341
- var OLE_MAGIC2 = new Uint8Array([208, 207, 17, 224, 161, 27, 26, 225]);
18342
- var ENDOFCHAIN = 4294967294;
18343
- var FREESECT = 4294967295;
18344
- var FATSECT = 4294967293;
18345
- var MAXREGSECT = 4294967290;
18346
- var ENTRY_TYPE_EMPTY = 0;
18347
- var ENTRY_TYPE_STREAM = 2;
18348
- var ENTRY_TYPE_ROOT = 5;
18349
- var DIR_ENTRY_SIZE = 128;
18350
- var Ole2ParseError = class extends Error {
18351
- constructor(message) {
18352
- super(message);
18353
- this.name = "Ole2ParseError";
18354
- }
18355
- };
18356
-
18357
- // src/core/utils/ole2-parser-read.ts
18358
- function parseOle2(buffer) {
18359
- const data = new Uint8Array(buffer);
18360
- const view = new DataView(buffer);
18361
- for (let i = 0; i < OLE_MAGIC2.length; i++) {
18362
- if (data[i] !== OLE_MAGIC2[i]) {
18363
- throw new Ole2ParseError("Not a valid OLE2 compound file");
18364
- }
18365
- }
18366
- view.getUint16(24, true);
18367
- const majorVersion = view.getUint16(26, true);
18368
- const byteOrder = view.getUint16(28, true);
18369
- if (byteOrder !== 65534) {
18370
- throw new Ole2ParseError("Invalid byte order mark");
18371
- }
18372
- const sectorSizePower = view.getUint16(30, true);
18373
- const miniSectorSizePower = view.getUint16(32, true);
18374
- const sectorSize = 1 << sectorSizePower;
18375
- const miniSectorSize = 1 << miniSectorSizePower;
18376
- const totalFATSectors = view.getUint32(44, true);
18377
- const firstDirectorySector = view.getUint32(48, true);
18378
- const miniStreamCutoff = view.getUint32(56, true);
18379
- const firstMiniFATSector = view.getUint32(60, true);
18380
- const totalMiniFATSectors = view.getUint32(64, true);
18381
- const firstDIFATSector = view.getUint32(68, true);
18382
- const totalDIFATSectors = view.getUint32(72, true);
18383
- function sectorOffset(sector) {
18384
- return (sector + 1) * sectorSize;
18385
- }
18386
- function readSector(sector) {
18387
- const offset = sectorOffset(sector);
18388
- if (offset + sectorSize > data.length) {
18389
- throw new Ole2ParseError(
18390
- `Sector ${sector} at offset ${offset} exceeds file size ${data.length}`
18391
- );
18392
- }
18393
- return data.subarray(offset, offset + sectorSize);
18394
- }
18395
- const fatSectors = [];
18396
- for (let i = 0; i < 109 && fatSectors.length < totalFATSectors; i++) {
18397
- const sector = view.getUint32(76 + i * 4, true);
18398
- if (sector <= MAXREGSECT) {
18399
- fatSectors.push(sector);
18400
- }
18401
- }
18402
- let difatSector = firstDIFATSector;
18403
- for (let d = 0; d < totalDIFATSectors && difatSector <= MAXREGSECT; d++) {
18404
- const difatData = readSector(difatSector);
18405
- const difatView = new DataView(difatData.buffer, difatData.byteOffset, difatData.byteLength);
18406
- const entriesPerSector = (sectorSize - 4) / 4;
18407
- for (let i = 0; i < entriesPerSector && fatSectors.length < totalFATSectors; i++) {
18408
- const sector = difatView.getUint32(i * 4, true);
18409
- if (sector <= MAXREGSECT) {
18410
- fatSectors.push(sector);
18411
- }
18412
- }
18413
- difatSector = difatView.getUint32(sectorSize - 4, true);
18414
- }
18415
- const fatEntries = [];
18416
- for (const fatSector of fatSectors) {
18417
- const fatData = readSector(fatSector);
18418
- const fatView = new DataView(fatData.buffer, fatData.byteOffset, fatData.byteLength);
18419
- for (let i = 0; i < sectorSize / 4; i++) {
18420
- fatEntries.push(fatView.getUint32(i * 4, true));
18421
- }
18422
- }
18423
- function readSectorChain(startSector) {
18424
- const sectors = [];
18425
- let current = startSector;
18426
- const visited = /* @__PURE__ */ new Set();
18427
- while (current <= MAXREGSECT) {
18428
- if (visited.has(current)) {
18429
- throw new Ole2ParseError(`Circular reference in FAT chain at sector ${current}`);
18430
- }
18431
- visited.add(current);
18432
- sectors.push(readSector(current));
18433
- current = fatEntries[current] ?? ENDOFCHAIN;
18434
- }
18435
- const totalLength = sectors.length * sectorSize;
18436
- const result = new Uint8Array(totalLength);
18437
- let offset = 0;
18438
- for (const sector of sectors) {
18439
- result.set(sector, offset);
18440
- offset += sectorSize;
18441
- }
18442
- return result;
18443
- }
18444
- function readStream(startSector, size) {
18445
- const raw = readSectorChain(startSector);
18446
- return raw.subarray(0, Math.min(size, raw.length));
18447
- }
18448
- const miniFatEntries = [];
18449
- if (firstMiniFATSector <= MAXREGSECT && totalMiniFATSectors > 0) {
18450
- const miniFatRaw = readSectorChain(firstMiniFATSector);
18451
- const miniFatView = new DataView(
18452
- miniFatRaw.buffer,
18453
- miniFatRaw.byteOffset,
18454
- miniFatRaw.byteLength
18455
- );
18456
- for (let i = 0; i < miniFatRaw.length / 4; i++) {
18457
- miniFatEntries.push(miniFatView.getUint32(i * 4, true));
18458
- }
18459
- }
18460
- const dirRaw = readSectorChain(firstDirectorySector);
18461
- const numEntries = Math.floor(dirRaw.length / DIR_ENTRY_SIZE);
18462
- const entries = [];
18463
- for (let i = 0; i < numEntries; i++) {
18464
- const entryOffset = i * DIR_ENTRY_SIZE;
18465
- const entryView = new DataView(dirRaw.buffer, dirRaw.byteOffset + entryOffset, DIR_ENTRY_SIZE);
18466
- const nameLen = entryView.getUint16(64, true);
18467
- const objectType = entryView.getUint8(66);
18468
- if (objectType === ENTRY_TYPE_EMPTY) {
18469
- continue;
18470
- }
18471
- const nameBytes = Math.max(0, nameLen - 2);
18472
- let name = "";
18473
- for (let j = 0; j < nameBytes; j += 2) {
18474
- name += String.fromCharCode(entryView.getUint16(j, true));
18475
- }
18476
- const leftSiblingId = entryView.getUint32(68, true);
18477
- const rightSiblingId = entryView.getUint32(72, true);
18478
- const childId = entryView.getUint32(76, true);
18479
- const startSector = entryView.getUint32(116, true);
18480
- const sizeLow = entryView.getUint32(120, true);
18481
- let size = sizeLow;
18482
- if (majorVersion === 4) {
18483
- entryView.getUint32(124, true);
18484
- size = sizeLow;
18485
- }
18486
- entries.push({
18487
- name,
18488
- type: objectType,
18489
- startSector,
18490
- size,
18491
- childId: childId === 4294967295 ? -1 : childId,
18492
- leftSiblingId: leftSiblingId === 4294967295 ? -1 : leftSiblingId,
18493
- rightSiblingId: rightSiblingId === 4294967295 ? -1 : rightSiblingId
18494
- });
18495
- }
18496
- const rootEntry = entries.find((e) => e.type === ENTRY_TYPE_ROOT);
18497
- let miniStreamData;
18498
- if (rootEntry && rootEntry.startSector <= MAXREGSECT) {
18499
- miniStreamData = readSectorChain(rootEntry.startSector);
18500
- }
18501
- function readMiniStream(startSector, size) {
18502
- if (!miniStreamData) {
18503
- throw new Ole2ParseError("Mini stream container not found");
18504
- }
18505
- const sectors = [];
18506
- let current = startSector;
18507
- const visited = /* @__PURE__ */ new Set();
18508
- while (current <= MAXREGSECT) {
18509
- if (visited.has(current)) {
18510
- throw new Ole2ParseError(`Circular reference in mini FAT chain at sector ${current}`);
18511
- }
18512
- visited.add(current);
18513
- const offset2 = current * miniSectorSize;
18514
- sectors.push(miniStreamData.subarray(offset2, offset2 + miniSectorSize));
18515
- current = miniFatEntries[current] ?? ENDOFCHAIN;
18516
- }
18517
- const totalLength = sectors.length * miniSectorSize;
18518
- const result = new Uint8Array(totalLength);
18519
- let offset = 0;
18520
- for (const sector of sectors) {
18521
- result.set(sector, offset);
18522
- offset += miniSectorSize;
18523
- }
18524
- return result.subarray(0, Math.min(size, result.length));
18525
- }
18526
- function getStream(name) {
18527
- const entry = entries.find(
18528
- (e) => (e.type === ENTRY_TYPE_STREAM || e.type === ENTRY_TYPE_ROOT) && e.name === name
18529
- );
18530
- if (!entry) {
18531
- return void 0;
18532
- }
18533
- if (entry.size < miniStreamCutoff && entry.type !== ENTRY_TYPE_ROOT) {
18534
- return readMiniStream(entry.startSector, entry.size);
18535
- }
18536
- return readStream(entry.startSector, entry.size);
18537
- }
18538
- return { entries, getStream };
18539
- }
18540
-
18541
18688
  // src/core/utils/ole2-parser-write.ts
18542
18689
  function compareDirEntryNames(a, b) {
18543
18690
  if (a.length !== b.length) {
@@ -18584,7 +18731,7 @@ function writeInt32Sectors(outBytes, int32Data, firstSector, numSectors, sectorS
18584
18731
  }
18585
18732
  }
18586
18733
  function writeHeader(outView, outBytes, params) {
18587
- outBytes.set(OLE_MAGIC2, 0);
18734
+ outBytes.set(OLE_MAGIC, 0);
18588
18735
  outView.setUint16(24, 62, true);
18589
18736
  outView.setUint16(26, 3, true);
18590
18737
  outView.setUint16(28, 65534, true);
@@ -45131,6 +45278,7 @@ var PptxHandlerRuntime77 = class extends PptxHandlerRuntime76 {
45131
45278
  };
45132
45279
 
45133
45280
  // src/core/core/runtime/PptxHandlerRuntimeLoadSession.ts
45281
+ var MAX_OLE_EMBEDDING_BYTES = 25 * 1024 * 1024;
45134
45282
  var PptxHandlerRuntime78 = class _PptxHandlerRuntime extends PptxHandlerRuntime77 {
45135
45283
  isZipContainer(data) {
45136
45284
  const bytes = new Uint8Array(data);
@@ -45350,6 +45498,59 @@ var PptxHandlerRuntime78 = class _PptxHandlerRuntime extends PptxHandlerRuntime7
45350
45498
  orderedSections
45351
45499
  };
45352
45500
  }
45501
+ /**
45502
+ * Recover and attach the real embedded binary for each OLE element on a
45503
+ * slide so callers can download / open the inner file.
45504
+ *
45505
+ * For each embedded (non-linked) OLE object: resolve its relationship
45506
+ * target to a zip path (same resolution as images), read the bytes, unwrap
45507
+ * a generic "Package" wrapper (recovering the original file name) when
45508
+ * present, derive a MIME type, and expose the payload as a data-URL on the
45509
+ * element. Linked objects, missing targets, oversized payloads, and parse
45510
+ * failures are skipped silently so existing behaviour is preserved.
45511
+ */
45512
+ async enrichOleElementsWithEmbeddedData(elements, slidePath, depth = 0) {
45513
+ const MAX_OLE_DEPTH = 32;
45514
+ if (depth > MAX_OLE_DEPTH) {
45515
+ return;
45516
+ }
45517
+ for (const el of elements) {
45518
+ if (el.type === "group" && el.children) {
45519
+ await this.enrichOleElementsWithEmbeddedData(el.children, slidePath, depth + 1);
45520
+ continue;
45521
+ }
45522
+ if (el.type !== "ole" || el.isLinked || !el.oleTarget) {
45523
+ continue;
45524
+ }
45525
+ try {
45526
+ const embeddingPath = this.resolveImagePath(slidePath, el.oleTarget);
45527
+ if (!embeddingPath) {
45528
+ continue;
45529
+ }
45530
+ const file = this.zip.file(embeddingPath);
45531
+ if (!file) {
45532
+ continue;
45533
+ }
45534
+ const buffer = await file.async("arraybuffer");
45535
+ if (buffer.byteLength === 0 || buffer.byteLength > MAX_OLE_EMBEDDING_BYTES) {
45536
+ continue;
45537
+ }
45538
+ const unwrapped = unwrapOleEmbedding(new Uint8Array(buffer));
45539
+ if (unwrapped.data.length === 0) {
45540
+ continue;
45541
+ }
45542
+ const fileName = unwrapped.fileName ?? el.fileName ?? (el.oleName && el.oleFileExtension ? `${el.oleName}.${el.oleFileExtension}` : void 0);
45543
+ const mimeType = mimeTypeForOleFile(fileName ?? `x.${el.oleFileExtension ?? "bin"}`);
45544
+ el.oleEmbeddedData = oleBytesToDataUrl(unwrapped.data, mimeType);
45545
+ el.oleEmbeddedByteSize = unwrapped.data.length;
45546
+ el.oleEmbeddedMimeType = mimeType;
45547
+ if (fileName) {
45548
+ el.oleEmbeddedFileName = fileName;
45549
+ }
45550
+ } catch {
45551
+ }
45552
+ }
45553
+ }
45353
45554
  async loadSlidesForPresentation(sectionBySlideId) {
45354
45555
  if (!this.presentationData) {
45355
45556
  return [];
@@ -45377,6 +45578,7 @@ var PptxHandlerRuntime78 = class _PptxHandlerRuntime extends PptxHandlerRuntime7
45377
45578
  parseSlide: (slideXml2, slidePath) => this.parseSlide(slideXml2, slidePath),
45378
45579
  extractMediaTimingMap: (slideXml2, slidePath) => this.extractMediaTimingMap(slideXml2, slidePath),
45379
45580
  enrichMediaElementsWithTiming: (elements, timingMap) => this.enrichMediaElementsWithTiming(elements, timingMap),
45581
+ enrichOleElementsWithEmbeddedData: (elements, slidePath) => this.enrichOleElementsWithEmbeddedData(elements, slidePath),
45380
45582
  extractBackgroundColor: (slideXml2) => this.extractBackgroundColor(slideXml2),
45381
45583
  getLayoutBackgroundColor: (slidePath) => this.getLayoutBackgroundColor(slidePath),
45382
45584
  extractBackgroundGradient: (slideXml2) => this.extractBackgroundGradient(slideXml2),
@@ -63707,6 +63909,7 @@ exports.createTemplateShapeRawXml = createTemplateShapeRawXml;
63707
63909
  exports.createTextElement = createTextElement;
63708
63910
  exports.createUniformTextSegments = createUniformTextSegments;
63709
63911
  exports.dataUrlToMediaBytes = dataUrlToMediaBytes;
63912
+ exports.decodeOle10Native = decodeOle10Native;
63710
63913
  exports.decomposeSmartArt = decomposeSmartArt;
63711
63914
  exports.decryptPptx = decryptPptx;
63712
63915
  exports.demoteSmartArtNode = demoteSmartArtNode;
@@ -63814,6 +64017,7 @@ exports.isEditableTextElement = isEditableTextElement;
63814
64017
  exports.isImageLikeElement = isImageLikeElement;
63815
64018
  exports.isInkElement = isInkElement;
63816
64019
  exports.isNamespaceSupported = isNamespaceSupported;
64020
+ exports.isOle2CompoundFile = isOle2CompoundFile;
63817
64021
  exports.isShapeElement = isShapeElement;
63818
64022
  exports.isStrictNamespaceUri = isStrictNamespaceUri;
63819
64023
  exports.isSummaryZoomSlide = isSummaryZoomSlide;
@@ -63832,6 +64036,7 @@ exports.mergePresentation = mergePresentation;
63832
64036
  exports.mergeShapes = mergeShapes;
63833
64037
  exports.mergeStyleParts = mergeStyleParts;
63834
64038
  exports.mergeThemeColorOverride = mergeThemeColorOverride;
64039
+ exports.mimeTypeForOleFile = mimeTypeForOleFile;
63835
64040
  exports.mm = mm;
63836
64041
  exports.moveSlidesToSection = moveSlidesToSection;
63837
64042
  exports.navigateCustomShow = navigateCustomShow;
@@ -63842,6 +64047,7 @@ exports.normalizePath = normalizePath;
63842
64047
  exports.normalizeStrictXml = normalizeStrictXml;
63843
64048
  exports.normalizeStrokeDashType = normalizeStrokeDashType;
63844
64049
  exports.obfuscateFont = obfuscateFont;
64050
+ exports.oleBytesToDataUrl = oleBytesToDataUrl;
63845
64051
  exports.ooxmlArcToSvg = ooxmlArcToSvg;
63846
64052
  exports.ooxmlToPresetName = ooxmlToPresetName;
63847
64053
  exports.parseActiveXControlsFromSlide = parseActiveXControlsFromSlide;
@@ -63954,6 +64160,7 @@ exports.unionPolygons = unionPolygons;
63954
64160
  exports.unionShapes = unionShapes;
63955
64161
  exports.unionSvgPaths = unionSvgPaths;
63956
64162
  exports.unwrapAlternateContent = unwrapAlternateContent;
64163
+ exports.unwrapOleEmbedding = unwrapOleEmbedding;
63957
64164
  exports.updateCellTextInRawXml = updateCellTextInRawXml;
63958
64165
  exports.updateCellTextStyleInRawXml = updateCellTextStyleInRawXml;
63959
64166
  exports.updateChartDataPoint = updateChartDataPoint;