diff --git a/chrome/content/zotero/xpcom/data/item.js b/chrome/content/zotero/xpcom/data/item.js index ed89ab3cf4..014934fff9 100644 --- a/chrome/content/zotero/xpcom/data/item.js +++ b/chrome/content/zotero/xpcom/data/item.js @@ -3663,6 +3663,9 @@ Zotero.defineProperty(Zotero.Item.prototype, 'attachmentPath', { } val = 'storage:' + PathUtils.filename(val); } + if (/^storage:.*[/\\]/.test(val)) { + throw new Error(`Stored file filename cannot contain a slash -- got '${val}'`); + } } if (val == this.attachmentPath) { diff --git a/chrome/content/zotero/xpcom/schema.js b/chrome/content/zotero/xpcom/schema.js index 8803b1d200..1b5872baeb 100644 --- a/chrome/content/zotero/xpcom/schema.js +++ b/chrome/content/zotero/xpcom/schema.js @@ -3690,6 +3690,19 @@ Zotero.Schema = new function () { await Zotero.DB.queryAsync("INSERT INTO savedSearchConditions SELECT savedSearchID, searchConditionID, condition, operator, value FROM savedSearchConditionsOld"); await Zotero.DB.queryAsync("DROP TABLE savedSearchConditionsOld"); } + + else if (i == 128) { + // Strip full paths (e.g., from third-party tools) from stored-file attachment + // paths, which should contain only a filename after 'storage:' + let rows = await Zotero.DB.queryAsync("SELECT itemID, path FROM itemAttachments WHERE linkMode IN (0, 1) AND (path LIKE ? OR path LIKE ?)", ['storage:%/%', 'storage:%\\%']); + for (let row of rows) { + let filename = row.path.substr(8).split(/[/\\]/).pop(); + if (!filename) { + continue; + } + await Zotero.DB.queryAsync("UPDATE itemAttachments SET path=? WHERE itemID=?", ['storage:' + filename, row.itemID]); + } + } } await _updateDBVersion('userdata', toVersion); diff --git a/resource/schema/userdata.sql b/resource/schema/userdata.sql index cc25b7c841..c0d5724a31 100644 --- a/resource/schema/userdata.sql +++ b/resource/schema/userdata.sql @@ -1,4 +1,4 @@ --- 127 +-- 128 -- Copyright (c) 2009 Center for History and New Media -- George Mason University, Fairfax, Virginia, USA diff --git a/test/tests/itemTest.js b/test/tests/itemTest.js index 4589179370..32afa28f60 100644 --- a/test/tests/itemTest.js +++ b/test/tests/itemTest.js @@ -1158,7 +1158,17 @@ describe("Zotero.Item", function () { assert.equal(attachment.attachmentFilename, filename); }); - + + it("should reject a filename containing a slash", async function () { + var item = await createDataObject('item'); + + var attachment = new Zotero.Item("attachment"); + attachment.attachmentLinkMode = Zotero.Attachments.LINK_MODE_IMPORTED_FILE; + attachment.parentID = item.id; + assert.throws(() => attachment.attachmentFilename = "D:/Foo/Bar/test.pdf", /slash/); + assert.throws(() => attachment.attachmentFilename = "D:\\Foo\\Bar\\test.pdf", /slash/); + }); + it("should get a filename for a base-dir-relative file", function () { var dir = getTestDataDirectory().path; Zotero.Prefs.set('saveRelativeAttachmentPath', true)