From ce66fefbffe0f3a0d9b36636ec4d92afda74f959 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Mon, 3 Oct 2022 17:55:13 +0200 Subject: [PATCH] [api-minor] Add partial support for the "GoToE" action (issue 8844) *Please note:* The referenced issue is the only mention that I can find, in either GitHub or Bugzilla, of "GoToE" actions. Hence why I've purposely settled for a very simple, and partial, "GoToE" implementation to avoid complicating things initially.[1] In particular, this patch only supports "GoToE" actions that references the /EmbeddedFiles-dict in the PDF document. See https://web.archive.org/web/20220309040754if_/https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf#G11.2048909 --- [1] Usually I always prefer having *real-world* test-cases to work with, whenever I'm implementing new features. --- src/core/annotation.js | 10 +++++++++- src/core/catalog.js | 25 +++++++++++++++++++++++++ src/display/annotation_layer.js | 21 +++++++++++++++++++++ test/pdfs/.gitignore | 1 + test/pdfs/issue8844.pdf | Bin 0 -> 38910 bytes test/unit/api_spec.js | 21 +++++++++++++++++++++ web/app.js | 1 + web/pdf_outline_viewer.js | 21 +++++++++++++++++++-- 8 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 test/pdfs/issue8844.pdf diff --git a/src/core/annotation.js b/src/core/annotation.js index 6aa8b4d20..aa312e157 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -80,15 +80,19 @@ class AnnotationFactory { // Only necessary to prevent the `pdfManager.docBaseUrl`-getter, used // with certain Annotations, from throwing and thus breaking parsing: pdfManager.ensureCatalog("baseUrl"), + // Only necessary in the `Catalog.parseDestDictionary`-method, + // when parsing "GoToE" actions: + pdfManager.ensureCatalog("attachments"), pdfManager.ensureDoc("xfaDatasets"), collectFields ? this._getPageIndex(xref, ref, pdfManager) : -1, - ]).then(([acroForm, baseUrl, xfaDatasets, pageIndex]) => + ]).then(([acroForm, baseUrl, attachments, xfaDatasets, pageIndex]) => pdfManager.ensure(this, "_create", [ xref, ref, pdfManager, idFactory, acroForm, + attachments, xfaDatasets, collectFields, pageIndex, @@ -105,6 +109,7 @@ class AnnotationFactory { pdfManager, idFactory, acroForm, + attachments = null, xfaDatasets, collectFields, pageIndex = -1 @@ -130,6 +135,7 @@ class AnnotationFactory { id, pdfManager, acroForm: acroForm instanceof Dict ? acroForm : Dict.empty, + attachments, xfaDatasets, collectFields, pageIndex, @@ -2893,6 +2899,7 @@ class ButtonWidgetAnnotation extends WidgetAnnotation { destDict: params.dict, resultObj: this.data, docBaseUrl: params.pdfManager.docBaseUrl, + docAttachments: params.attachments, }); } @@ -3221,6 +3228,7 @@ class LinkAnnotation extends Annotation { destDict: params.dict, resultObj: this.data, docBaseUrl: params.pdfManager.docBaseUrl, + docAttachments: params.attachments, }); } } diff --git a/src/core/catalog.js b/src/core/catalog.js index f60d740f3..561d6a9be 100644 --- a/src/core/catalog.js +++ b/src/core/catalog.js @@ -307,6 +307,7 @@ class Catalog { destDict: outlineDict, resultObj: data, docBaseUrl: this.pdfManager.docBaseUrl, + docAttachments: this.attachments, }); const title = outlineDict.get("Title"); const flags = outlineDict.get("F") || 0; @@ -325,6 +326,7 @@ class Catalog { const outlineItem = { action: data.action, + attachment: data.attachment, dest: data.dest, url: data.url, unsafeUrl: data.unsafeUrl, @@ -1412,6 +1414,8 @@ class Catalog { * properties will be placed. * @property {string} [docBaseUrl] - The document base URL that is used when * attempting to recover valid absolute URLs from relative ones. + * @property {Object} [docAttachments] - The document attachments (may not + * exist in most PDF documents). */ /** @@ -1430,6 +1434,7 @@ class Catalog { return; } const docBaseUrl = params.docBaseUrl || null; + const docAttachments = params.docAttachments || null; let action = destDict.get("A"), url, @@ -1526,6 +1531,26 @@ class Catalog { } break; + case "GoToE": + const target = action.get("T"); + let attachment; + + if (docAttachments && target instanceof Dict) { + const relationship = target.get("R"); + const name = target.get("N"); + + if (isName(relationship, "C") && typeof name === "string") { + attachment = docAttachments[stringToPDFString(name)]; + } + } + + if (attachment) { + resultObj.attachment = attachment; + } else { + warn(`parseDestDictionary - unimplemented "GoToE" action.`); + } + break; + case "Named": const namedAction = action.get("N"); if (namedAction instanceof Name) { diff --git a/src/display/annotation_layer.js b/src/display/annotation_layer.js index 9839506e8..85cb93c9c 100644 --- a/src/display/annotation_layer.js +++ b/src/display/annotation_layer.js @@ -595,6 +595,9 @@ class LinkAnnotationElement extends AnnotationElement { } else if (data.action) { this._bindNamedAction(link, data.action); isBound = true; + } else if (data.attachment) { + this._bindAttachment(link, data.attachment); + isBound = true; } else if (data.setOCGState) { this.#bindSetOCGState(link, data.setOCGState); isBound = true; @@ -679,6 +682,24 @@ class LinkAnnotationElement extends AnnotationElement { link.className = "internalLink"; } + /** + * Bind attachments to the link element. + * @param {Object} link + * @param {Object} attachment + */ + _bindAttachment(link, attachment) { + link.href = this.linkService.getAnchorUrl(""); + link.onclick = () => { + this.downloadManager?.openOrDownloadData( + this.container, + attachment.content, + attachment.filename + ); + return false; + }; + link.className = "internalLink"; + } + /** * Bind SetOCGState actions to the link element. * @param {Object} link diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 1b0d41af4..80524c365 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -49,6 +49,7 @@ !issue7426.pdf !issue7439.pdf !issue7847_radial.pdf +!issue8844.pdf !issue14953.pdf !issue15367.pdf !issue15372.pdf diff --git a/test/pdfs/issue8844.pdf b/test/pdfs/issue8844.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c1f25ffe4f098df23ba31b9c08f77161b816bc89 GIT binary patch literal 38910 zcmc$^RdgK9ckVr6W+rPSOR|`mnVFfHnVFfHnVA_ZW{a80lEuvW{N|rzC11`(uFmOM zy=tnude7|Ne!4EY9#VN>Q5ptX7Fg20r@~KIW*|M#&d?H;n;S?cZDDI-;Ar7#Vhm*X z+XFJOb1={Y>BNCrKsF9`AOj-{PzOjS2V@7*i2#|H8R?mTbh7_URsK7bm5~|9%L{8_ zYy3|*;Q#FdmgT=BqU>RB0;E${G%@{~hKa42vpJB31xP1qVeM?<__wt-a5fP(F|srM zJL_Mqyn&;Q6Yw7hLUz_JHnvVcW+0usqlvMFk+YrS-_-x+2BcH_OM(H&`1kzFLBiJ9 z#QpC8Gmw$vUwu=%zt`x2ia%YD${RIkS`itssIM;sz#qvMk&`AgbwYV7> znOInvjM(Ve=s8$fS(zCO>6sZ!7>$h$j9FO>42*fXjhKv#O<7sk8JXD_SWJ!B7}(hj zOifKWI2f2sOqmQ!cy<1%fs?bNiGdBQd$y6G@vfP^p*}kdN&2ckcoA5*7Mx*AKzJIz z-~y`nZ(0ac%UF2n=m$A|No;HjK>(m(22%T<68?LH|5wHQAAJ6|1F-)v{|`CK8rYaP z0h#{2B=QDke|vu={BH&NmqLULoDHn)%>IjR+5XG@|3|qf0hw6;Q&i0C{~fo!zP^#Z zeyR~5kPH&szcC{q9YP`uh5Ccko{$bTWU{X&`9#j|S=geponIXc^g9f$Yo-wCw+;$iJfg zJO4j(Ry1+4b8$5KhXTXD#iaWeg@4HW7X<%A{||)!M+E==L@}`b^HBV!*w#&AdEkE1 zql-L!MzWC!E%X+@IHF$wW7if75|c4)C^Ns}XavaHyP?vY=*+GnD@9;ZHHIJg=z=h*%O7)Pv0bM>)@WW7qPijYBo{eOvB@rGx>Zw2uc-%PCR~KBS9d7GAP`P z=b}l&>qg=oUBS&V8|x}>WhKu*e{AD+N$BzZqN}f_x8g`vq@m!u}V< z|4-I`*S7yvrVKy^mcPXQeI;Q8axgRfT^0XDf$49E|5#!e=$V=6{~MB+W(ehEEj(6f zaW_e(VrC&XH%T`H`dxV;$uwuFAn{1%KxYXzHpTfI$)~U%+fUg~Un{S@ELJ>CbzP4H zD?O*>i_99N)CI@-8s$M$R8V;G$iNcfict`7K!CP2Kkx@7K@R5765@Lseu^yA`8j9+ zC-mo_-~G2=Mc>mpWwlpLW_h1Q2U$TU%Re{ExKO@@7^FqL}_%Lk|f2VCSH&zHqJJ@3c7i zu#He(D!6!*1pI#xhK}Sy$QCD-2oB*Px#7-%nEFs@W>{=cQuR!`FRuQjfsDH?-&gnK zjE?va)B%1hQ2hfVH+lAc9$$#y4$p%)#s(lQZr~j5g80=Ss>odQyDim>Syf?FaDYSo zmkng&6HuQ=s2&J`bN=I5NWWr4&@st!F#cJLPnEo=5T>EIrI2X|!>2CM#~p**4eA4Z z3W%0AD6aO-{LdLV+{pU-NUDapnXjC_6_Ww|rK}SCkuI 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 literal 0 HcmV?d00001 diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index 591f94624..cea08e235 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -15,6 +15,7 @@ import { AnnotationMode, + AnnotationType, createPromiseCapability, FontType, ImageKind, @@ -1536,6 +1537,7 @@ describe("api", function () { expect(outline[4]).toEqual({ action: null, + attachment: undefined, dest: "Händel -- Halle🎆lujah", url: null, unsafeUrl: undefined, @@ -1562,6 +1564,7 @@ describe("api", function () { expect(outline[1]).toEqual({ action: "PrevPage", + attachment: undefined, dest: null, url: null, unsafeUrl: undefined, @@ -1588,6 +1591,7 @@ describe("api", function () { expect(outline[0]).toEqual({ action: null, + attachment: undefined, dest: null, url: null, unsafeUrl: undefined, @@ -2155,6 +2159,23 @@ describe("api", function () { ]); }); + it("gets annotations containing GoToE action (issue 8844)", async function () { + const loadingTask = getDocument(buildGetDocumentParams("issue8844.pdf")); + const pdfDoc = await loadingTask.promise; + const pdfPage = await pdfDoc.getPage(1); + const annotations = await pdfPage.getAnnotations(); + + expect(annotations.length).toEqual(1); + expect(annotations[0].annotationType).toEqual(AnnotationType.LINK); + + const { filename, content } = annotations[0].attachment; + expect(filename).toEqual("man.pdf"); + expect(content instanceof Uint8Array).toEqual(true); + expect(content.length).toEqual(4508); + + await loadingTask.destroy(); + }); + it("gets text content", async function () { const defaultPromise = page.getTextContent(); const parametersPromise = page.getTextContent({ diff --git a/web/app.js b/web/app.js index 37a655b39..046f498ee 100644 --- a/web/app.js +++ b/web/app.js @@ -636,6 +636,7 @@ const PDFViewerApplication = { container: appConfig.sidebar.outlineView, eventBus, linkService: pdfLinkService, + downloadManager, }); this.pdfAttachmentViewer = new PDFAttachmentViewer({ diff --git a/web/pdf_outline_viewer.js b/web/pdf_outline_viewer.js index 9bcb8179a..42ac42c6c 100644 --- a/web/pdf_outline_viewer.js +++ b/web/pdf_outline_viewer.js @@ -20,8 +20,9 @@ import { SidebarView } from "./ui_utils.js"; /** * @typedef {Object} PDFOutlineViewerOptions * @property {HTMLDivElement} container - The viewer element. - * @property {IPDFLinkService} linkService - The navigation/linking service. * @property {EventBus} eventBus - The application event bus. + * @property {IPDFLinkService} linkService - The navigation/linking service. + * @property {DownloadManager} downloadManager - The download manager. */ /** @@ -37,6 +38,7 @@ class PDFOutlineViewer extends BaseTreeViewer { constructor(options) { super(options); this.linkService = options.linkService; + this.downloadManager = options.downloadManager; this.eventBus._on("toggleoutlinetree", this._toggleAllTreeItems.bind(this)); this.eventBus._on( @@ -109,7 +111,10 @@ class PDFOutlineViewer extends BaseTreeViewer { /** * @private */ - _bindLink(element, { url, newWindow, action, dest, setOCGState }) { + _bindLink( + element, + { url, newWindow, action, attachment, dest, setOCGState } + ) { const { linkService } = this; if (url) { @@ -124,6 +129,18 @@ class PDFOutlineViewer extends BaseTreeViewer { }; return; } + if (attachment) { + element.href = linkService.getAnchorUrl(""); + element.onclick = () => { + this.downloadManager.openOrDownloadData( + element, + attachment.content, + attachment.filename + ); + return false; + }; + return; + } if (setOCGState) { element.href = linkService.getAnchorUrl(""); element.onclick = () => {