From 64f99356a557a42e3abd7586ba408d944175fba4 Mon Sep 17 00:00:00 2001 From: Lukasr29 Date: Fri, 12 Jan 2018 02:39:42 +0100 Subject: [PATCH] improve(tio): extract file name from `Content-Disposition` (#4035) * Added extraction of quoted file name from content disposition header * Added extraction of quoted file name from content disposition header - PR Fixes * Added extraction of quoted file name from content disposition header - PR Fixes * Added extraction of quoted file name from content disposition header - PR Fixes --- src/core/components/response-body.jsx | 10 ++++++---- src/core/utils.js | 11 +++++++++++ test/core/utils.js | 23 ++++++++++++++++++++++- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/core/components/response-body.jsx b/src/core/components/response-body.jsx index e239c258..2c1eb92f 100644 --- a/src/core/components/response-body.jsx +++ b/src/core/components/response-body.jsx @@ -2,6 +2,7 @@ import React from "react" import PropTypes from "prop-types" import formatXml from "xml-but-prettier" import lowerCase from "lodash/lowerCase" +import { extractFileNameFromContentDispositionHeader } from "core/utils" export default class ResponseBody extends React.Component { @@ -70,12 +71,13 @@ export default class ResponseBody extends React.Component { let fileName = url.substr(url.lastIndexOf("/") + 1) let download = [type, fileName, href].join(":") - // Use filename from response header + // Use filename from response header, + // First check if filename is quoted (e.g. contains space), if no, fallback to not quoted check let disposition = headers["content-disposition"] || headers["Content-Disposition"] if (typeof disposition !== "undefined") { - let responseFilename = /filename=([^;]*);?/i.exec(disposition) - if (responseFilename !== null && responseFilename.length > 1) { - download = responseFilename[1] + let responseFilename = extractFileNameFromContentDispositionHeader(disposition) + if (responseFilename !== null) { + download = responseFilename } } diff --git a/src/core/utils.js b/src/core/utils.js index 10274904..b691468f 100644 --- a/src/core/utils.js +++ b/src/core/utils.js @@ -342,6 +342,17 @@ export function mapToList(map, keyNames="key", collectedKeys=Im.Map()) { return list } +export function extractFileNameFromContentDispositionHeader(value){ + let responseFilename = /filename="([^;]*);?"/i.exec(value) + if (responseFilename === null) { + responseFilename = /filename=([^;]*);?/i.exec(value) + } + if (responseFilename !== null && responseFilename.length > 1) { + return responseFilename[1] + } + return null +} + // PascalCase, aka UpperCamelCase export function pascalCase(str) { return upperFirst(camelCase(str)) diff --git a/test/core/utils.js b/test/core/utils.js index cd6fd386..45f7860f 100644 --- a/test/core/utils.js +++ b/test/core/utils.js @@ -18,7 +18,8 @@ import { getAcceptControllingResponse, createDeepLinkPath, escapeDeepLinkPath, - sanitizeUrl + sanitizeUrl, + extractFileNameFromContentDispositionHeader } from "core/utils" import win from "core/window" @@ -90,6 +91,26 @@ describe("utils", function() { }) + describe("extractFileNameFromContentDispositionHeader", function(){ + it("should extract quoted filename", function(){ + let cdHeader = "attachment; filename=\"file name.jpg\"" + let expectedResult = "file name.jpg" + expect(extractFileNameFromContentDispositionHeader(cdHeader)).toEqual(expectedResult) + }) + + it("should extract filename", function(){ + let cdHeader = "attachment; filename=filename.jpg" + let expectedResult = "filename.jpg" + expect(extractFileNameFromContentDispositionHeader(cdHeader)).toEqual(expectedResult) + }) + + it("should not extract filename and return null", function(){ + let cdHeader = "attachment; no file name provided" + let expectedResult = null + expect(extractFileNameFromContentDispositionHeader(cdHeader)).toEqual(expectedResult) + }) + }) + describe("validateMaximum", function() { let errorMessage = "Value must be less than Maximum"