Use BrowserDownload for 403 when enforcing type in downloadFile()

Fixed regression (probably in 1f401f0897) causing Find Full Text not to
use BrowserDownload for a 403

https://forums.zotero.org/discussion/125581/zotero-suddenly-fails-to-retrieve-full-text-although-i-have-access
This commit is contained in:
Dan Stillman 2025-07-22 22:08:48 -04:00
parent 445737c261
commit b95f9eea89
2 changed files with 60 additions and 6 deletions

View file

@ -1175,7 +1175,6 @@ Zotero.Attachments = new function () {
this.downloadFile = async function (url, path, options = {}) {
Zotero.debug(`Downloading file from ${url}`);
let enforcingFileType = false;
try {
let headers = {};
if (options.referrer) {
@ -1189,9 +1188,8 @@ Zotero.Attachments = new function () {
cookieSandbox: options.cookieSandbox
}
);
// Check that the downloaded file is the expected type
if (options.enforceFileType) {
enforcingFileType = true;
await _enforceFileType(path);
}
}
@ -1202,9 +1200,13 @@ Zotero.Attachments = new function () {
catch (e) {
Zotero.logError(e);
}
// Custom handling for PDFs that are bot-guarded
// via a JS-redirect
if (enforcingFileType && e instanceof this.InvalidPDFException) {
// Custom handling for files that are bot-guarded via a JS redirect and/or that require
// a CAPTCHA
if (options.enforceFileType
// Thrown by _enforceFileType()
&& (e instanceof this.InvalidPDFException
// Thrown by HTTP.download()
|| (e instanceof Zotero.HTTP.UnexpectedStatusException && e.status == 403))) {
if (Zotero.BrowserDownload.shouldAttemptDownloadViaBrowser(url)) {
return Zotero.BrowserDownload.downloadPDF(url, path, options);
}

View file

@ -609,6 +609,58 @@ describe("Zotero.Attachments", function() {
});
});
describe("#downloadFile()", function () {
var httpd;
var testServerPort;
before(async () => {
({ httpd, port: testServerPort } = await startHTTPServer());
});
after(async () => {
await new Promise((resolve) => {
httpd.stop(() => resolve());
});
});
it("should use BrowserDownload for 403 when enforcing file type", async function () {
let prefix = Zotero.Utilities.randomString();
let testServerPath = 'http://127.0.0.1:' + testServerPort + '/' + prefix;
let pdfURL = testServerPath + '/test.pdf';
httpd.registerPathHandler(
"/" + prefix + '/test.pdf',
{
handle: function (request, response) {
response.setStatusLine(null, 403, "Forbidden");
response.write("Forbidden");
}
}
);
let path = OS.Path.join(Zotero.getTempDirectory().path, 'test.pdf');
let shouldAttemptStub = sinon.stub(Zotero.BrowserDownload, "shouldAttemptDownloadViaBrowser");
let downloadPDFStub = sinon.stub(Zotero.BrowserDownload, "downloadPDF");
shouldAttemptStub.returns(true);
downloadPDFStub.callsFake(async (_url, path) => {
await OS.File.copy(OS.Path.join(getTestDataDirectory().path, 'test.pdf'), path);
});
var item;
try {
item = await Zotero.Attachments.downloadFile(pdfURL, path, { enforceFileType: true });
assert.isTrue(shouldAttemptStub.calledOnce);
assert.isTrue(downloadPDFStub.calledOnce);
}
finally {
// Clean up
if (item) await Zotero.Items.erase(item.id);
downloadPDFStub.restore();
shouldAttemptStub.restore();
}
});
});
describe("Find Full Text", function () {
var doiPrefix = 'https://doi.org/';
var doi1 = '10.1111/abcd';