From 86f9dd74008b65a8d00c8946c056faf7bcb087e1 Mon Sep 17 00:00:00 2001 From: Abe Jellinek Date: Fri, 15 Aug 2025 01:29:05 -0400 Subject: [PATCH] Handle invalid path when launching/revealing on macOS (#5485) --- chrome/content/zotero/zoteroPane.js | 20 +++++++++++++++++--- test/tests/zoteroPaneTest.js | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index e1b4e56505..efa1da5e70 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -5106,12 +5106,15 @@ var ZoteroPane = new function () { return; } let fileExists; + let pathIsValid; try { fileExists = await IOUtils.exists(path); + pathIsValid = true; } catch (e) { Zotero.logError(e); fileExists = false; + pathIsValid = false; } // If the file is an evicted iCloud Drive file, launch that to trigger a download. @@ -5120,7 +5123,7 @@ var ZoteroPane = new function () { // for the original file to exist and then continue with regular file opening below. // // To trigger eviction for testing, use Cirrus from https://eclecticlight.co/downloads/ - if (!fileExists && Zotero.isMac && isLinkedFile) { + if (!fileExists && pathIsValid && Zotero.isMac && isLinkedFile) { // Get the path to the .icloud file let iCloudPath = Zotero.File.getEvictedICloudPath(path); if (await IOUtils.exists(iCloudPath)) { @@ -5381,10 +5384,21 @@ var ZoteroPane = new function () { if (attachment.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_URL) return; var path = attachment.getFilePath(); - var fileExists = await IOUtils.exists(path); + + let fileExists; + let pathIsValid; + try { + fileExists = await IOUtils.exists(path); + pathIsValid = true; + } + catch (e) { + Zotero.logError(e); + fileExists = false; + pathIsValid = false; + } // If file doesn't exist but an evicted iCloud Drive file does, reveal that instead - if (!fileExists && Zotero.isMac && !attachment.isStoredFileAttachment()) { + if (!fileExists && pathIsValid && Zotero.isMac && !attachment.isStoredFileAttachment()) { let iCloudPath = Zotero.File.getEvictedICloudPath(path); if (await IOUtils.exists(iCloudPath)) { path = iCloudPath; diff --git a/test/tests/zoteroPaneTest.js b/test/tests/zoteroPaneTest.js index 9b843028cc..01cde40633 100644 --- a/test/tests/zoteroPaneTest.js +++ b/test/tests/zoteroPaneTest.js @@ -368,6 +368,25 @@ describe("ZoteroPane", function () { await zp.viewAttachment(attachment.id); assert.equal(attachment.attachmentContentType, 'application/epub+zip'); }); + + it("should handle Windows paths on macOS/Linux", async function () { + if (!Zotero.isMac && !Zotero.isLinux) { + this.skip(); + return; + } + + let file = getTestDataDirectory(); + file.append('test.pdf'); + let attachment = await Zotero.Attachments.linkFromFile({ file }); + attachment.attachmentPath = 'C:\\some\\windows\\path'; + await attachment.saveTx(); + + let stub = sinon.stub(zp, 'showAttachmentNotFoundDialog'); + await zp.viewAttachment(attachment.id); + assert.ok(stub.calledOnce); + assert.ok(stub.calledWith(attachment)); + stub.restore(); + }); })