tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 41afd870cb76c9ec85986b8d7280a4c1b38dfd80
parent 46ea2de4d34ffc65490b6a756301a24384d1e464
Author: Jonathan Kew <jkew@mozilla.com>
Date:   Wed, 26 Nov 2025 15:46:37 +0000

Bug 1959738 - Use a standard "_files" suffix for associated files folder in all locales. r=Gijs,mak

As suggested in comments 13-15, this removes localization support for the
filesFolder suffix, so the hardcoded "_files" string is used everywhere.

Differential Revision: https://phabricator.services.mozilla.com/D273031

Diffstat:
Mtoolkit/content/contentAreaUtils.js | 9+++++----
Mtoolkit/locales/en-US/chrome/global/contentAreaCommands.properties | 6------
Muriloader/exthandler/nsExternalHelperAppService.cpp | 62++++++++++++++++++++++++++++++++++++++++++--------------------
3 files changed, 47 insertions(+), 30 deletions(-)

diff --git a/toolkit/content/contentAreaUtils.js b/toolkit/content/contentAreaUtils.js @@ -507,10 +507,11 @@ function internalPersist(persistArgs) { filesFolder = persistArgs.targetFile.clone(); var nameWithoutExtension = getFileBaseName(filesFolder.leafName); - var filesFolderLeafName = - ContentAreaUtils.stringBundle.formatStringFromName("filesFolder", [ - nameWithoutExtension, - ]); + // Given the minimal benefits, the "_files" suffix is intentionally not + // localized. Localizing it introduces complexity in handling OS filename + // length limits (e.g. bug 1959738) and risks breaking the folder-linking + // feature if an unsupported suffix is used. + var filesFolderLeafName = nameWithoutExtension + "_files"; filesFolder.leafName = filesFolderLeafName; } diff --git a/toolkit/locales/en-US/chrome/global/contentAreaCommands.properties b/toolkit/locales/en-US/chrome/global/contentAreaCommands.properties @@ -20,9 +20,3 @@ WebPageXMLOnlyFilter=Web Page, XML only # not be determined or if a filename was invalid. A period and file # extension may be appended to this string. UntitledSaveFileName=Untitled - -# LOCALIZATION NOTE (filesFolder): -# This is the name of the folder that is created parallel to a HTML file -# when it is saved "With Images". The %S section is replaced with the -# leaf name of the file being saved (minus extension). -filesFolder=%S_files diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -3565,9 +3565,35 @@ void nsExternalHelperAppService::SanitizeFileName(nsAString& aFileName, // Linux (ext3/ext4...) stores filenames with a maximum 255 bytes. // So here we just use the maximum of 255 bytes. // 0 means don't truncate at a maximum size. - const uint32_t maxBytes = + uint32_t maxBytes = (aFlags & VALIDATE_DONT_TRUNCATE) ? 0 : kDefaultMaxFileNameLength; + const auto downloadSuffix = u".download"_ns; + bool appendDownloadSuffix = false; + + if (!(aFlags & VALIDATE_ALLOW_INVALID_FILENAMES)) { + // If the extension is one these types, we append .download, as these + // types of files can have significance on Windows or Linux. + // This happens for any file, not just those with the shortcut mime type. + if (StringEndsWith(fileName, u".lnk"_ns, + nsCaseInsensitiveStringComparator) || + StringEndsWith(fileName, u".local"_ns, + nsCaseInsensitiveStringComparator) || + StringEndsWith(fileName, u".url"_ns, + nsCaseInsensitiveStringComparator) || + StringEndsWith(fileName, u".scf"_ns, + nsCaseInsensitiveStringComparator) || + StringEndsWith(fileName, u".desktop"_ns, + nsCaseInsensitiveStringComparator)) { + appendDownloadSuffix = true; + + // To ensure this will not make the final name too long, adjust maxBytes. + if (maxBytes) { + maxBytes -= downloadSuffix.Length(); + } + } + } + // True if the last character added was whitespace. bool lastWasWhitespace = false; @@ -3588,6 +3614,13 @@ void nsExternalHelperAppService::SanitizeFileName(nsAString& aFileName, // The length of the extension in bytes. uint32_t extensionBytesLength = 0; + // Given the minimal benefits, the "_files" suffix is intentionally not + // localized (see also contentAreaUtils.js). Localizing it introduces + // complexity in handling OS filename length limits (e.g. bug 1959738) + // and risks breaking the folder-linking feature if an unsupported suffix + // is used. + constexpr uint32_t filesFolderLength = "_files"_ns.Length(); + // This algorithm iterates over each character in the string and appends it // or a replacement character if needed to outFileName. nsAutoString outFileName; @@ -3676,10 +3709,13 @@ void nsExternalHelperAppService::SanitizeFileName(nsAString& aFileName, AppendUCS4ToUTF16(nextChar, outFileName); } - // If the filename is longer than the maximum allowed filename size, + // If the filename is longer than the maximum allowed filename size, or + // if replacing the extension with the filesFolder name would make it so, // truncate it, but preserve the desired extension that is currently // on the filename. - if (bytesLength > maxBytes && !outFileName.IsEmpty()) { + if ((bytesLength > std::min(maxBytes, maxBytes - filesFolderLength + + extensionBytesLength)) && + !outFileName.IsEmpty()) { // Get the sanitized extension from the filename without the dot. nsAutoString extension; int32_t dotidx = outFileName.RFind(u"."); @@ -3701,7 +3737,7 @@ void nsExternalHelperAppService::SanitizeFileName(nsAString& aFileName, // characters, but if they don't match, it just means we crop off // more than is necessary. This is OK since it is better than cropping // off too little. - longFileNameEnd -= extensionBytesLength; + longFileNameEnd -= std::max(extensionBytesLength, filesFolderLength); if (longFileNameEnd <= 0) { // This is extremely unlikely, but if the extension is larger than the // maximum size, just get rid of it. In this case, the extension @@ -3752,22 +3788,8 @@ void nsExternalHelperAppService::SanitizeFileName(nsAString& aFileName, } #endif - if (!(aFlags & VALIDATE_ALLOW_INVALID_FILENAMES)) { - // If the extension is one these types, replace it with .download, as these - // types of files can have significance on Windows or Linux. - // This happens for any file, not just those with the shortcut mime type. - if (StringEndsWith(outFileName, u".lnk"_ns, - nsCaseInsensitiveStringComparator) || - StringEndsWith(outFileName, u".local"_ns, - nsCaseInsensitiveStringComparator) || - StringEndsWith(outFileName, u".url"_ns, - nsCaseInsensitiveStringComparator) || - StringEndsWith(outFileName, u".scf"_ns, - nsCaseInsensitiveStringComparator) || - StringEndsWith(outFileName, u".desktop"_ns, - nsCaseInsensitiveStringComparator)) { - outFileName.AppendLiteral(".download"); - } + if (appendDownloadSuffix) { + outFileName.Append(downloadSuffix); } aFileName = outFileName;