nsURLHelperWin.cpp (3190B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=4 sw=2 et cindent: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* Windows-specific local file uri parsing */ 8 #include "nsComponentManagerUtils.h" 9 #include "nsURLHelper.h" 10 #include "nsEscape.h" 11 #include "nsIFile.h" 12 #include <windows.h> 13 #include "mozilla/StaticPrefs_network.h" 14 #include "mozilla/Utf8.h" 15 16 using namespace mozilla; 17 18 nsresult net_GetURLSpecFromActualFile(nsIFile* aFile, nsACString& result) { 19 nsresult rv; 20 nsAutoString path; 21 22 // construct URL spec from file path 23 rv = aFile->GetPath(path); 24 if (NS_FAILED(rv)) return rv; 25 26 // Replace \ with / to convert to an url 27 path.ReplaceChar(char16_t(0x5Cu), char16_t(0x2Fu)); 28 29 nsAutoCString escPath; 30 31 // Windows Desktop paths begin with a drive letter, so need an 'extra' 32 // slash at the begining 33 // C:\Windows => file:///C:/Windows 34 constexpr auto prefix = "file:///"_ns; 35 36 // Escape the path with the directory mask 37 NS_ConvertUTF16toUTF8 ePath(path); 38 if (NS_EscapeURL(ePath.get(), -1, esc_Directory + esc_Forced, escPath)) 39 escPath.Insert(prefix, 0); 40 else 41 escPath.Assign(prefix + ePath); 42 43 // esc_Directory does not escape the semicolons, so if a filename 44 // contains semicolons we need to manually escape them. 45 // This replacement should be removed in bug #473280 46 escPath.ReplaceSubstring(";", "%3b"); 47 48 result = escPath; 49 return NS_OK; 50 } 51 52 nsresult net_GetFileFromURLSpec(const nsACString& aURL, nsIFile** result) { 53 nsresult rv; 54 55 if (aURL.Length() > StaticPrefs::network_standard_url_max_length()) { 56 return NS_ERROR_MALFORMED_URI; 57 } 58 59 const nsACString* specPtr; 60 61 nsAutoCString buf; 62 if (net_NormalizeFileURL(aURL, buf)) 63 specPtr = &buf; 64 else 65 specPtr = &aURL; 66 67 nsAutoCString directory, fileBaseName, fileExtension; 68 69 rv = net_ParseFileURL(*specPtr, directory, fileBaseName, fileExtension); 70 if (NS_FAILED(rv)) return rv; 71 72 nsAutoCString path; 73 74 if (!directory.IsEmpty()) { 75 NS_EscapeURL(directory, esc_Directory | esc_AlwaysCopy, path); 76 if (path.Length() > 2 && path.CharAt(2) == '|') path.SetCharAt(':', 2); 77 path.ReplaceChar('/', '\\'); 78 } 79 if (!fileBaseName.IsEmpty()) 80 NS_EscapeURL(fileBaseName, esc_FileBaseName | esc_AlwaysCopy, path); 81 if (!fileExtension.IsEmpty()) { 82 path += '.'; 83 NS_EscapeURL(fileExtension, esc_FileExtension | esc_AlwaysCopy, path); 84 } 85 86 NS_UnescapeURL(path); 87 if (path.Length() != strlen(path.get())) return NS_ERROR_FILE_INVALID_PATH; 88 89 // remove leading '\' 90 if (path.CharAt(0) == '\\') path.Cut(0, 1); 91 92 if (IsUtf8(path)) { 93 return NS_NewUTF8LocalFile(path, result); 94 } 95 // XXX In rare cases, a valid UTF-8 string can be valid as a native 96 // encoding (e.g. 0xC5 0x83 is valid both as UTF-8 and Windows-125x). 97 // However, the chance is very low that a meaningful word in a legacy 98 // encoding is valid as UTF-8. 99 100 // if path is not in UTF-8, assume it is encoded in the native charset 101 return NS_NewNativeLocalFile(path, result); 102 }