Bug 1746052, use validateFileNameForSaving in DownloadPaths.sanitize with flags to emulate something similar to the existing behaviour, r=mak

Differential Revision: https://phabricator.services.mozilla.com/D138738
This commit is contained in:
Neil Deakin 2022-05-03 19:44:29 +00:00
Родитель 2be09b9192
Коммит 660ff47e74
4 изменённых файлов: 25 добавлений и 84 удалений

Просмотреть файл

@ -100,7 +100,7 @@ function test() {
aCallback();
};
launcherDialog.promptForSaveToFileAsync(launcher, aWin, null, null, null);
launcherDialog.promptForSaveToFileAsync(launcher, aWin, "", "", false);
}
testOnWindow(false, function(win, downloadDir) {

Просмотреть файл

@ -10,83 +10,22 @@
var EXPORTED_SYMBOLS = ["DownloadPaths"];
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"AppConstants",
"resource://gre/modules/AppConstants.jsm"
);
/**
* Platform-dependent regular expression used by the "sanitize" method.
*/
XPCOMUtils.defineLazyGetter(this, "gConvertToSpaceRegExp", () => {
// Note: we remove colons everywhere to avoid issues in subresource URL
// parsing, as well as filename restrictions on some OSes (see bug 1562176).
/* eslint-disable no-control-regex */
switch (AppConstants.platform) {
// On mobile devices, the file system may be very limited in what it
// considers valid characters. To avoid errors, sanitize conservatively.
case "android":
return /[\x00-\x1f\x7f-\x9f:*?|"<>;,+=\[\]]+/g;
case "win":
return /[\x00-\x1f\x7f-\x9f:*?|]+/g;
default:
return /[\x00-\x1f\x7f-\x9f:]+/g;
}
/* eslint-enable no-control-regex */
});
var DownloadPaths = {
/**
* Sanitizes an arbitrary string for use as the local file name of a download.
* The input is often a document title or a manually edited name. The output
* can be an empty string if the input does not include any valid character.
*
* The length of the resulting string is not limited, because restrictions
* apply to the full path name after the target folder has been added.
*
* Splitting the base name and extension to add a counter or to identify the
* file type should only be done after the sanitization process, because it
* can alter the final part of the string or remove leading dots.
*
* Runs of slashes and backslashes are replaced with an underscore.
*
* On Windows, the angular brackets `<` and `>` are replaced with parentheses,
* and double quotes are replaced with single quotes.
*
* Runs of control characters are replaced with a space. On Mac, colons are
* also included in this group. On Windows, stars, question marks, and pipes
* are additionally included. On Android, semicolons, commas, plus signs,
* equal signs, and brackets are additionally included.
*
* Leading and trailing dots and whitespace are removed on all platforms. This
* avoids the accidental creation of hidden files on Unix and invalid or
* inaccessible file names on Windows. These characters are not removed when
* located at the end of the base name or at the beginning of the extension.
* Sanitizes an arbitrary string via mimeSvc.validateFileNameForSaving.
*
* @param {string} leafName The full leaf name to sanitize
* @param {boolean} [compressWhitespaces] Whether consecutive whitespaces
* should be compressed.
*/
sanitize(leafName, { compressWhitespaces = true } = {}) {
if (AppConstants.platform == "win") {
leafName = leafName
.replace(/</g, "(")
.replace(/>/g, ")")
.replace(/"/g, "'");
const mimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
let flags = mimeSvc.VALIDATE_SANITIZE_ONLY | mimeSvc.VALIDATE_DONT_TRUNCATE;
if (!compressWhitespaces) {
flags |= mimeSvc.VALIDATE_DONT_COLLAPSE_WHITESPACE;
}
leafName = leafName
.replace(/[\\/]+/g, "_")
.replace(/[\u200e\u200f\u202a-\u202e]/g, "")
.replace(gConvertToSpaceRegExp, " ");
if (compressWhitespaces) {
leafName = leafName.replace(/\s{2,}/g, " ");
}
return leafName.replace(/^[\s\u180e.]+|[\s\u180e.]+$/g, "");
return mimeSvc.validateFileNameForSaving(leafName, "", flags);
},
/**

Просмотреть файл

@ -40,27 +40,27 @@ add_task(async function test_sanitize() {
testSanitize("Website | Page!", "Website Page!");
testSanitize("Directory Listing: /a/b/", "Directory Listing _a_b_");
} else if (AppConstants.platform == "win") {
testSanitize(kSpecialChars, "A ''(());,+=[]B][=+,;))(('' C");
testSanitize(kSpecialChars, "A ;,+=[]B][=+,; C");
testSanitize(" :: Website :: ", "Website");
testSanitize("* Website!", "Website!");
testSanitize("Website | Page!", "Website Page!");
testSanitize("Directory Listing: /a/b/", "Directory Listing _a_b_");
} else if (AppConstants.platform == "macosx") {
testSanitize(kSpecialChars, 'A *?|""<<>>;,+=[]B][=+,;>><<""|?* C');
testSanitize(kSpecialChars, "A ;,+=[]B][=+,; C");
testSanitize(" :: Website :: ", "Website");
testSanitize("* Website!", "* Website!");
testSanitize("Website | Page!", "Website | Page!");
testSanitize("* Website!", "Website!");
testSanitize("Website | Page!", "Website Page!");
testSanitize("Directory Listing: /a/b/", "Directory Listing _a_b_");
} else {
testSanitize(kSpecialChars, kSpecialChars.replace(/[:]/g, " "));
testSanitize(kSpecialChars, "A ;,+=[]B][=+,; C");
testSanitize(" :: Website :: ", "Website");
testSanitize("* Website!", "* Website!");
testSanitize("Website | Page!", "Website | Page!");
testSanitize("* Website!", "Website!");
testSanitize("Website | Page!", "Website Page!");
testSanitize("Directory Listing: /a/b/", "Directory Listing _a_b_");
}
// Conversion of consecutive runs of slashes and backslashes to underscores.
testSanitize("\\ \\\\Website\\/Page// /", "_ _Website_Page_ _");
testSanitize("\\ \\\\Website\\/Page// /", "_ __Website__Page__ _");
// Removal of leading and trailing whitespace and dots after conversion.
testSanitize(" Website ", "Website");
@ -77,8 +77,8 @@ add_task(async function test_sanitize() {
testSanitize(" . ", "");
// Stripping of BIDI formatting characters.
testSanitize("\u200e \u202b\u202c\u202d\u202etest\x7f\u200f", "test");
testSanitize("AB\x7f\u202a\x7f\u202a\x7fCD", "AB CD");
testSanitize("\u200e \u202b\u202c\u202d\u202etest\x7f\u200f", "_ ____test _");
testSanitize("AB\x7f\u202a\x7f\u202a\x7fCD", "AB _ _ CD");
// Stripping of colons:
testSanitize("foo:bar", "foo bar");

Просмотреть файл

@ -294,11 +294,13 @@ nsUnknownContentTypeDialog.prototype = {
let defaultFolder = new FileUtils.File(preferredDir);
try {
result = this.validateLeafName(
defaultFolder,
aDefaultFileName,
aSuggestedFileExtension
);
if (aDefaultFileName) {
result = this.validateLeafName(
defaultFolder,
aDefaultFileName,
aSuggestedFileExtension
);
}
} catch (ex) {
// When the default download directory is write-protected,
// prompt the user for a different target file.