From 2f19d9d9068a98b8502038e56b84bf3a2fd067d8 Mon Sep 17 00:00:00 2001 From: Rob Wu Date: Sun, 4 Feb 2018 16:19:40 +0100 Subject: [PATCH] Support spaces and semicolons in filename Imports the following changes: https://github.com/Rob--W/open-in-browser/commit/5b1afa7c29339627a7ed230473ab715d1364a740 https://github.com/Rob--W/open-in-browser/commit/7e2e35a38b8b4e981b11da7b2f01df0149049e92 --- src/display/content_disposition.js | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/display/content_disposition.js b/src/display/content_disposition.js index 4b3608814..98c2efa8d 100644 --- a/src/display/content_disposition.js +++ b/src/display/content_disposition.js @@ -14,7 +14,7 @@ */ // This getFilenameFromContentDispositionHeader function is adapted from -// https://github.com/Rob--W/open-in-browser/blob/9f5fcae11cf6d99c503a15894f22efdfcd2075b7/extension/content-disposition.js +// https://github.com/Rob--W/open-in-browser/blob/7e2e35a38b8b4e981b11da7b2f01df0149049e92/extension/content-disposition.js // with the following changes: // - Modified to conform to PDF.js's coding style. // - Support UTF-8 decoding when TextDecoder is unsupported. @@ -33,7 +33,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) { let needsEncodingFixup = true; // filename*=ext-value ("ext-value" from RFC 5987, referenced by RFC 6266). - let tmp = /(?:^|;)\s*filename\*\s*=\s*([^;\s]+)/i.exec(contentDisposition); + let tmp = toParamRegExp('filename\\*', 'i').exec(contentDisposition); if (tmp) { tmp = tmp[1]; let filename = rfc2616unquote(tmp); @@ -54,7 +54,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) { } // filename=value (RFC 5987, section 4.1). - tmp = /(?:^|;)\s*filename\s*=\s*([^;\s]+)/.exec(contentDisposition); + tmp = toParamRegExp('filename', 'i').exec(contentDisposition); if (tmp) { tmp = tmp[1]; let filename = rfc2616unquote(tmp); @@ -65,7 +65,17 @@ function getFilenameFromContentDispositionHeader(contentDisposition) { // After this line there are only function declarations. We cannot put // "return" here for readability because babel would then drop the function // declarations... - + function toParamRegExp(attributePattern, flags) { + return new RegExp( + '(?:^|;)\\s*' + attributePattern + '\\s*=\\s*' + + // Captures: value = token | quoted-string + // (RFC 2616, section 3.6 and referenced by RFC 6266 4.1) + '(' + + '[^";\\s][^;\\s]*' + + '|' + + '"(?:[^"\\\\]|\\\\"?)+"?' + + ')', flags); + } function textdecode(encoding, value) { if (encoding) { if (!/^[^\x00-\xFF]+$/.test(value)) { @@ -102,7 +112,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) { let matches = [], match; // Iterate over all filename*n= and filename*n*= with n being an integer // of at least zero. Any non-zero number must not start with '0'. - let iter = /(?:^|;)\s*filename\*((?!0\d)\d+)(\*?)\s*=\s*([^;\s]+)/ig; + let iter = toParamRegExp('filename\\*((?!0\\d)\\d+)(\\*?)', 'ig'); while ((match = iter.exec(contentDisposition)) !== null) { let [, n, quot, part] = match; n = parseInt(n, 10); @@ -185,7 +195,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) { // encoding = q or b // encoded-text = any printable ASCII character other than ? or space. // ... but Firefox permits ? and space. - return value.replace(/=\?([\w\-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g, + return value.replace(/=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g, function(_, charset, encoding, text) { if (encoding === 'q' || encoding === 'Q') { // RFC 2047 section 4.2.