Source code

Revision control

Other Tools

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