Переглянути джерело

be less strict when validating mime types of images (fix #166)

Gildas 7 роки тому
батько
коміт
ec68e7792a
1 змінених файлів з 16 додано та 14 видалено
  1. 16 14
      lib/single-file/single-file-core.js

+ 16 - 14
lib/single-file/single-file-core.js

@@ -317,7 +317,7 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 	// ---------
 	// Processor
 	// ---------
-	const PREFIX_DATA_URI_IMAGE = "data:image/";
+	const PREFIXES_DATA_URI_IMAGE = ["data:image/", "data:application/"];
 	const PREFIX_DATA_URI_AUDIO = "data:audio/";
 	const PREFIX_DATA_URI_VIDEO = "data:video/";
 	const PREFIX_DATA_URI_IMAGE_SVG = "data:image/svg+xml";
@@ -923,26 +923,26 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 
 		async processPageResources() {
 			const processAttributeArgs = [
-				["link[href][rel*=\"icon\"]", "href", "data:", false, true],
-				["object[type=\"image/svg+xml\"], object[type=\"image/svg-xml\"]", "data", PREFIX_DATA_URI_IMAGE_SVG],
-				["img[src], input[src][type=image]", "src", PREFIX_DATA_URI_IMAGE, true],
+				["link[href][rel*=\"icon\"]", "href", ["data:"], false, true],
+				["object[type=\"image/svg+xml\"], object[type=\"image/svg-xml\"]", "data", [PREFIX_DATA_URI_IMAGE_SVG]],
+				["img[src], input[src][type=image]", "src", PREFIXES_DATA_URI_IMAGE, true],
 				["embed[src*=\".svg\"], embed[src*=\".pdf\"]", "src", "data:"],
-				["video[poster]", "poster", PREFIX_DATA_URI_IMAGE],
-				["*[background]", "background", PREFIX_DATA_URI_IMAGE],
-				["image", "xlink:href", PREFIX_DATA_URI_IMAGE]
+				["video[poster]", "poster", PREFIXES_DATA_URI_IMAGE],
+				["*[background]", "background", PREFIXES_DATA_URI_IMAGE],
+				["image", "xlink:href", PREFIXES_DATA_URI_IMAGE]
 			];
 			let resourcePromises = processAttributeArgs.map(([selector, attributeName, prefixDataURI, processDuplicates, removeElementIfMissing]) =>
 				ProcessorHelper.processAttribute(this.doc.querySelectorAll(selector), attributeName, prefixDataURI, this.baseURI, this.options, this.cssVariables, this.styles, this.batchRequest, processDuplicates, removeElementIfMissing)
 			);
 			resourcePromises = resourcePromises.concat([
 				ProcessorHelper.processXLinks(this.doc.querySelectorAll("use"), this.baseURI, this.options, this.batchRequest),
-				ProcessorHelper.processSrcset(this.doc.querySelectorAll("img[srcset], source[srcset]"), "srcset", PREFIX_DATA_URI_IMAGE, this.baseURI, this.options, this.batchRequest)
+				ProcessorHelper.processSrcset(this.doc.querySelectorAll("img[srcset], source[srcset]"), "srcset", PREFIXES_DATA_URI_IMAGE, this.baseURI, this.options, this.batchRequest)
 			]);
 			if (!this.options.removeAudioSrc) {
-				resourcePromises.push(ProcessorHelper.processAttribute(this.doc.querySelectorAll("audio[src], audio > source[src]"), "src", PREFIX_DATA_URI_AUDIO, this.baseURI, this.options, this.cssVariables, this.styles, this.batchRequest));
+				resourcePromises.push(ProcessorHelper.processAttribute(this.doc.querySelectorAll("audio[src], audio > source[src]"), "src", [PREFIX_DATA_URI_AUDIO], this.baseURI, this.options, this.cssVariables, this.styles, this.batchRequest));
 			}
 			if (!this.options.removeVideoSrc) {
-				resourcePromises.push(ProcessorHelper.processAttribute(this.doc.querySelectorAll("video[src], video > source[src]"), "src", PREFIX_DATA_URI_VIDEO, this.baseURI, this.options, this.cssVariables, this.styles, this.batchRequest));
+				resourcePromises.push(ProcessorHelper.processAttribute(this.doc.querySelectorAll("video[src], video > source[src]"), "src", [PREFIX_DATA_URI_VIDEO], this.baseURI, this.options, this.cssVariables, this.styles, this.batchRequest));
 			}
 			await Promise.all(resourcePromises);
 			ProcessorHelper.processShortcutIcons(this.doc);
@@ -1404,7 +1404,7 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 			}
 		}
 
-		static async processAttribute(resourceElements, attributeName, prefixDataURI, baseURI, options, cssVariables, styles, batchRequest, processDuplicates, removeElementIfMissing) {
+		static async processAttribute(resourceElements, attributeName, prefixesDataURI, baseURI, options, cssVariables, styles, batchRequest, processDuplicates, removeElementIfMissing) {
 			await Promise.all(Array.from(resourceElements).map(async resourceElement => {
 				let resourceURL = resourceElement.getAttribute(attributeName);
 				resourceURL = Util.normalizeURL(resourceURL);
@@ -1421,7 +1421,8 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 							if (removeElementIfMissing && content == EMPTY_DATA_URI) {
 								resourceElement.remove();
 							} else {
-								if (content.startsWith(prefixDataURI) || content.startsWith(PREFIX_DATA_URI_NO_MIMETYPE) || content.match(PREFIX_DATA_URI_OCTET_STREAM) || content.match(PREFIX_DATA_URI_NULL_STREAM)) {
+								const prefixFound = prefixesDataURI.filter(prefixDataURI => content.startsWith(prefixDataURI)).length;
+								if (prefixFound || content.startsWith(PREFIX_DATA_URI_NO_MIMETYPE) || content.match(PREFIX_DATA_URI_OCTET_STREAM) || content.match(PREFIX_DATA_URI_NULL_STREAM)) {
 									const isSVG = content.startsWith(PREFIX_DATA_URI_IMAGE_SVG);
 									if (processDuplicates && duplicate && options.groupDuplicateImages && !isSVG) {
 										if (ProcessorHelper.replaceImageSource(resourceElement, SINGLE_FILE_VARIABLE_NAME_PREFIX + indexResource, options)) {
@@ -1478,7 +1479,7 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 			}));
 		}
 
-		static async processSrcset(resourceElements, attributeName, prefixDataURI, baseURI, options, batchRequest) {
+		static async processSrcset(resourceElements, attributeName, prefixesDataURI, baseURI, options, batchRequest) {
 			await Promise.all(Array.from(resourceElements).map(async resourceElement => {
 				const srcset = docUtil.parseSrcset(resourceElement.getAttribute(attributeName));
 				const srcsetValues = await Promise.all(srcset.map(async srcsetValue => {
@@ -1492,7 +1493,8 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 							}
 							if (Util.testValidURL(resourceURL)) {
 								const { content } = await batchRequest.addURL(resourceURL, true);
-								if (!content.startsWith(prefixDataURI) && !content.startsWith(PREFIX_DATA_URI_NO_MIMETYPE) && !content.match(PREFIX_DATA_URI_OCTET_STREAM) && !content.match(PREFIX_DATA_URI_NULL_STREAM)) {
+								const prefixFound = prefixesDataURI.filter(prefixDataURI => content.startsWith(prefixDataURI)).length;
+								if (prefixFound && !content.startsWith(PREFIX_DATA_URI_NO_MIMETYPE) && !content.match(PREFIX_DATA_URI_OCTET_STREAM) && !content.match(PREFIX_DATA_URI_NULL_STREAM)) {
 									resourceElement.setAttribute(attributeName, EMPTY_IMAGE);
 								}
 								return content + (srcsetValue.w ? " " + srcsetValue.w + "w" : srcsetValue.d ? " " + srcsetValue.d + "x" : "");