nsURLHelperWin.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* vim:set ts=4 sw=4 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. /* Windows-specific local file uri parsing */
  7. #include "nsURLHelper.h"
  8. #include "nsEscape.h"
  9. #include "nsIFile.h"
  10. #include <windows.h>
  11. nsresult
  12. net_GetURLSpecFromActualFile(nsIFile *aFile, nsACString &result)
  13. {
  14. nsresult rv;
  15. nsAutoString path;
  16. // construct URL spec from file path
  17. rv = aFile->GetPath(path);
  18. if (NS_FAILED(rv)) return rv;
  19. // Replace \ with / to convert to an url
  20. path.ReplaceChar(char16_t(0x5Cu), char16_t(0x2Fu));
  21. nsAutoCString escPath;
  22. // Windows Desktop paths begin with a drive letter, so need an 'extra'
  23. // slash at the begining
  24. // C:\Windows => file:///C:/Windows
  25. NS_NAMED_LITERAL_CSTRING(prefix, "file:///");
  26. // Escape the path with the directory mask
  27. NS_ConvertUTF16toUTF8 ePath(path);
  28. if (NS_EscapeURL(ePath.get(), -1, esc_Directory+esc_Forced, escPath))
  29. escPath.Insert(prefix, 0);
  30. else
  31. escPath.Assign(prefix + ePath);
  32. // esc_Directory does not escape the semicolons, so if a filename
  33. // contains semicolons we need to manually escape them.
  34. // This replacement should be removed in bug #473280
  35. escPath.ReplaceSubstring(";", "%3b");
  36. result = escPath;
  37. return NS_OK;
  38. }
  39. nsresult
  40. net_GetFileFromURLSpec(const nsACString &aURL, nsIFile **result)
  41. {
  42. nsresult rv;
  43. if (aURL.Length() > (uint32_t) net_GetURLMaxLength()) {
  44. return NS_ERROR_MALFORMED_URI;
  45. }
  46. nsCOMPtr<nsIFile> localFile(
  47. do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
  48. if (NS_FAILED(rv)) {
  49. NS_ERROR("Only nsIFile supported right now");
  50. return rv;
  51. }
  52. localFile->SetFollowLinks(true);
  53. const nsACString *specPtr;
  54. nsAutoCString buf;
  55. if (net_NormalizeFileURL(aURL, buf))
  56. specPtr = &buf;
  57. else
  58. specPtr = &aURL;
  59. nsAutoCString directory, fileBaseName, fileExtension;
  60. rv = net_ParseFileURL(*specPtr, directory, fileBaseName, fileExtension);
  61. if (NS_FAILED(rv)) return rv;
  62. nsAutoCString path;
  63. if (!directory.IsEmpty()) {
  64. NS_EscapeURL(directory, esc_Directory|esc_AlwaysCopy, path);
  65. if (path.Length() > 2 && path.CharAt(2) == '|')
  66. path.SetCharAt(':', 2);
  67. path.ReplaceChar('/', '\\');
  68. }
  69. if (!fileBaseName.IsEmpty())
  70. NS_EscapeURL(fileBaseName, esc_FileBaseName|esc_AlwaysCopy, path);
  71. if (!fileExtension.IsEmpty()) {
  72. path += '.';
  73. NS_EscapeURL(fileExtension, esc_FileExtension|esc_AlwaysCopy, path);
  74. }
  75. NS_UnescapeURL(path);
  76. if (path.Length() != strlen(path.get()))
  77. return NS_ERROR_FILE_INVALID_PATH;
  78. // remove leading '\'
  79. if (path.CharAt(0) == '\\')
  80. path.Cut(0, 1);
  81. if (IsUTF8(path))
  82. rv = localFile->InitWithPath(NS_ConvertUTF8toUTF16(path));
  83. // XXX In rare cases, a valid UTF-8 string can be valid as a native
  84. // encoding (e.g. 0xC5 0x83 is valid both as UTF-8 and Windows-125x).
  85. // However, the chance is very low that a meaningful word in a legacy
  86. // encoding is valid as UTF-8.
  87. else
  88. // if path is not in UTF-8, assume it is encoded in the native charset
  89. rv = localFile->InitWithNativePath(path);
  90. if (NS_FAILED(rv)) return rv;
  91. localFile.forget(result);
  92. return NS_OK;
  93. }