From df22b6f424815a5bf68b5c22ba42a674aa70efb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Thu, 14 Jun 2018 15:05:13 +0200 Subject: [PATCH] Use download manager from PDF.js to download the file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default implementation of "PDFViewerApplication.download" creates a blob which is then downloaded using the download manager from PDF.js. This causes a CSP error in Firefox, so in 7bcdc4fb29 the default implementation was replaced with a "window.open" call with the URL of the file. Besides through a blob, the download manager from PDF.js also supports downloading a file through its URL. Thus, in order to keep closer to the default PDF.js viewer, now the custom implementation of "PDFViewerApplication.download" was changed to download the file using the download manager from PDF.js. Note that "window.open" does not work in Internet Explorer 11 (in this specific case, probably due to the use of iframes or something like that), so this change also fixes the download in Internet Explorer 11, it is not just an "academic" change. Signed-off-by: Daniel Calviño Sánchez --- js/workersrc.js | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/js/workersrc.js b/js/workersrc.js index fa26d8d3..6c7590f6 100644 --- a/js/workersrc.js +++ b/js/workersrc.js @@ -32,8 +32,47 @@ function initializeCustomPDFViewerApplication() { PDFJS.isEvalSupported = false; PDFJS.workerSrc = document.getElementsByTagName('head')[0].getAttribute('data-workersrc'); + // The download has to be forced to use the URL of the file; by default + // "PDFViewerApplication.download" uses a blob, but this causes a CSP error + // (at least, in Firefox) when trying to download it. PDFViewerApplication.download = function() { - window.open(decodeURIComponent(window.location.search.substr(6)), '_blank'); + // "isDataSchema()" and "getPDFFileNameFromURL()" are copied from + // "vendor/pdfjs/web/viewer.js", as the functions defined in that file + // can not be accessed from the outside. + function isDataSchema(url) { + var i = 0, + ii = url.length; + while (i < ii && url[i].trim() === '') { + i++; + } + return url.substr(i, 5).toLowerCase() === 'data:'; + } + + function getPDFFileNameFromURL(url) { + var defaultFilename = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'document.pdf'; + + if (isDataSchema(url)) { + console.warn('getPDFFileNameFromURL: ' + 'ignoring "data:" URL for performance reasons.'); + return defaultFilename; + } + var reURI = /^(?:(?:[^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/; + var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i; + var splitURI = reURI.exec(url); + var suggestedFilename = reFilename.exec(splitURI[1]) || reFilename.exec(splitURI[2]) || reFilename.exec(splitURI[3]); + if (suggestedFilename) { + suggestedFilename = suggestedFilename[0]; + if (suggestedFilename.indexOf('%') !== -1) { + try { + suggestedFilename = reFilename.exec(decodeURIComponent(suggestedFilename))[0]; + } catch (ex) {} + } + } + return suggestedFilename || defaultFilename; + } + + var url = decodeURIComponent(window.location.search.substr(6)); + + this.downloadManager.downloadUrl(url, getPDFFileNameFromURL(url)); }; }