/src/mozilla-central/netwerk/protocol/file/nsFileProtocolHandler.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | // vim:ts=4 sw=4 sts=4 et cin: |
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 | | #include "nsIFile.h" |
8 | | #include "nsFileProtocolHandler.h" |
9 | | #include "nsFileChannel.h" |
10 | | #include "nsStandardURL.h" |
11 | | #include "nsURLHelper.h" |
12 | | #include "nsIURIMutator.h" |
13 | | |
14 | | #include "nsNetUtil.h" |
15 | | |
16 | | #include "FileChannelChild.h" |
17 | | |
18 | | // URL file handling, copied and modified from xpfe/components/bookmarks/src/nsBookmarksService.cpp |
19 | | #ifdef XP_WIN |
20 | | #include <shlobj.h> |
21 | | #include <intshcut.h> |
22 | | #include "nsIFileURL.h" |
23 | | #ifdef CompareString |
24 | | #undef CompareString |
25 | | #endif |
26 | | #endif |
27 | | |
28 | | // URL file handling for freedesktop.org |
29 | | #ifdef XP_UNIX |
30 | | #include "nsINIParser.h" |
31 | 0 | #define DESKTOP_ENTRY_SECTION "Desktop Entry" |
32 | | #endif |
33 | | |
34 | | //----------------------------------------------------------------------------- |
35 | | |
36 | | nsresult |
37 | | nsFileProtocolHandler::Init() |
38 | 3 | { |
39 | 3 | return NS_OK; |
40 | 3 | } |
41 | | |
42 | | NS_IMPL_ISUPPORTS(nsFileProtocolHandler, |
43 | | nsIFileProtocolHandler, |
44 | | nsIProtocolHandler, |
45 | | nsISupportsWeakReference) |
46 | | |
47 | | //----------------------------------------------------------------------------- |
48 | | // nsIProtocolHandler methods: |
49 | | |
50 | | #if defined(XP_WIN) |
51 | | NS_IMETHODIMP |
52 | | nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI) |
53 | | { |
54 | | nsAutoString path; |
55 | | nsresult rv = aFile->GetPath(path); |
56 | | if (NS_FAILED(rv)) |
57 | | return rv; |
58 | | |
59 | | if (path.Length() < 4) |
60 | | return NS_ERROR_NOT_AVAILABLE; |
61 | | if (!StringTail(path, 4).LowerCaseEqualsLiteral(".url")) |
62 | | return NS_ERROR_NOT_AVAILABLE; |
63 | | |
64 | | HRESULT result; |
65 | | |
66 | | rv = NS_ERROR_NOT_AVAILABLE; |
67 | | |
68 | | IUniformResourceLocatorW* urlLink = nullptr; |
69 | | result = ::CoCreateInstance(CLSID_InternetShortcut, nullptr, CLSCTX_INPROC_SERVER, |
70 | | IID_IUniformResourceLocatorW, (void**)&urlLink); |
71 | | if (SUCCEEDED(result) && urlLink) { |
72 | | IPersistFile* urlFile = nullptr; |
73 | | result = urlLink->QueryInterface(IID_IPersistFile, (void**)&urlFile); |
74 | | if (SUCCEEDED(result) && urlFile) { |
75 | | result = urlFile->Load(path.get(), STGM_READ); |
76 | | if (SUCCEEDED(result) ) { |
77 | | LPWSTR lpTemp = nullptr; |
78 | | |
79 | | // The URL this method will give us back seems to be already |
80 | | // escaped. Hence, do not do escaping of our own. |
81 | | result = urlLink->GetURL(&lpTemp); |
82 | | if (SUCCEEDED(result) && lpTemp) { |
83 | | rv = NS_NewURI(aURI, nsDependentString(lpTemp)); |
84 | | // free the string that GetURL alloc'd |
85 | | CoTaskMemFree(lpTemp); |
86 | | } |
87 | | } |
88 | | urlFile->Release(); |
89 | | } |
90 | | urlLink->Release(); |
91 | | } |
92 | | return rv; |
93 | | } |
94 | | |
95 | | #elif defined(XP_UNIX) |
96 | | NS_IMETHODIMP |
97 | | nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI) |
98 | 0 | { |
99 | 0 | // We only support desktop files that end in ".desktop" like the spec says: |
100 | 0 | // http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s02.html |
101 | 0 | nsAutoCString leafName; |
102 | 0 | nsresult rv = aFile->GetNativeLeafName(leafName); |
103 | 0 | if (NS_FAILED(rv) || |
104 | 0 | !StringEndsWith(leafName, NS_LITERAL_CSTRING(".desktop"))) |
105 | 0 | return NS_ERROR_NOT_AVAILABLE; |
106 | 0 | |
107 | 0 | bool isFile = false; |
108 | 0 | rv = aFile->IsFile(&isFile); |
109 | 0 | if (NS_FAILED(rv) || !isFile) { |
110 | 0 | return NS_ERROR_NOT_AVAILABLE; |
111 | 0 | } |
112 | 0 | |
113 | 0 | nsINIParser parser; |
114 | 0 | rv = parser.Init(aFile); |
115 | 0 | if (NS_FAILED(rv)) |
116 | 0 | return rv; |
117 | 0 | |
118 | 0 | nsAutoCString type; |
119 | 0 | parser.GetString(DESKTOP_ENTRY_SECTION, "Type", type); |
120 | 0 | if (!type.EqualsLiteral("Link")) |
121 | 0 | return NS_ERROR_NOT_AVAILABLE; |
122 | 0 | |
123 | 0 | nsAutoCString url; |
124 | 0 | rv = parser.GetString(DESKTOP_ENTRY_SECTION, "URL", url); |
125 | 0 | if (NS_FAILED(rv) || url.IsEmpty()) |
126 | 0 | return NS_ERROR_NOT_AVAILABLE; |
127 | 0 | |
128 | 0 | return NS_NewURI(aURI, url); |
129 | 0 | } |
130 | | |
131 | | #else // other platforms |
132 | | NS_IMETHODIMP |
133 | | nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI) |
134 | | { |
135 | | return NS_ERROR_NOT_AVAILABLE; |
136 | | } |
137 | | #endif // ReadURLFile() |
138 | | |
139 | | NS_IMETHODIMP |
140 | | nsFileProtocolHandler::GetScheme(nsACString &result) |
141 | 0 | { |
142 | 0 | result.AssignLiteral("file"); |
143 | 0 | return NS_OK; |
144 | 0 | } |
145 | | |
146 | | NS_IMETHODIMP |
147 | | nsFileProtocolHandler::GetDefaultPort(int32_t *result) |
148 | 0 | { |
149 | 0 | *result = -1; // no port for file: URLs |
150 | 0 | return NS_OK; |
151 | 0 | } |
152 | | |
153 | | NS_IMETHODIMP |
154 | | nsFileProtocolHandler::GetProtocolFlags(uint32_t *result) |
155 | 90 | { |
156 | 90 | *result = URI_NOAUTH | URI_IS_LOCAL_FILE | |
157 | 90 | URI_IS_LOCAL_RESOURCE | URI_IS_POTENTIALLY_TRUSTWORTHY; |
158 | 90 | return NS_OK; |
159 | 90 | } |
160 | | |
161 | | NS_IMETHODIMP |
162 | | nsFileProtocolHandler::NewURI(const nsACString &spec, |
163 | | const char *charset, |
164 | | nsIURI *aBaseURI, |
165 | | nsIURI **result) |
166 | 4.68k | { |
167 | 4.68k | nsAutoCString buf(spec); |
168 | | #if defined(XP_WIN) |
169 | | buf.Truncate(); |
170 | | if (!net_NormalizeFileURL(spec, buf)) { |
171 | | buf = spec; |
172 | | } |
173 | | #endif |
174 | | |
175 | 4.68k | nsCOMPtr<nsIURI> base(aBaseURI); |
176 | 4.68k | return NS_MutateURI(new nsStandardURL::Mutator()) |
177 | 4.68k | .Apply(NS_MutatorMethod(&nsIFileURLMutator::MarkFileURL)) |
178 | 4.68k | .Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init, |
179 | 4.68k | nsIStandardURL::URLTYPE_NO_AUTHORITY, |
180 | 4.68k | -1, buf, charset, base, nullptr)) |
181 | 4.68k | .Finalize(result); |
182 | 4.68k | } |
183 | | |
184 | | NS_IMETHODIMP |
185 | | nsFileProtocolHandler::NewChannel2(nsIURI* uri, |
186 | | nsILoadInfo* aLoadInfo, |
187 | | nsIChannel** result) |
188 | 0 | { |
189 | 0 | nsresult rv; |
190 | 0 |
|
191 | 0 | nsFileChannel *chan; |
192 | 0 | if (IsNeckoChild()) { |
193 | 0 | chan = new mozilla::net::FileChannelChild(uri); |
194 | 0 | } else { |
195 | 0 | chan = new nsFileChannel(uri); |
196 | 0 | } |
197 | 0 | if (!chan) |
198 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
199 | 0 | NS_ADDREF(chan); |
200 | 0 |
|
201 | 0 | // set the loadInfo on the new channel ; must do this |
202 | 0 | // before calling Init() on it, since it needs the load |
203 | 0 | // info be already set. |
204 | 0 | rv = chan->SetLoadInfo(aLoadInfo); |
205 | 0 | if (NS_FAILED(rv)) { |
206 | 0 | NS_RELEASE(chan); |
207 | 0 | return rv; |
208 | 0 | } |
209 | 0 |
|
210 | 0 | rv = chan->Init(); |
211 | 0 | if (NS_FAILED(rv)) { |
212 | 0 | NS_RELEASE(chan); |
213 | 0 | return rv; |
214 | 0 | } |
215 | 0 |
|
216 | 0 | *result = chan; |
217 | 0 | return NS_OK; |
218 | 0 | } |
219 | | |
220 | | NS_IMETHODIMP |
221 | | nsFileProtocolHandler::NewChannel(nsIURI *uri, nsIChannel **result) |
222 | 0 | { |
223 | 0 | return NewChannel2(uri, nullptr, result); |
224 | 0 | } |
225 | | |
226 | | NS_IMETHODIMP |
227 | | nsFileProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *result) |
228 | 0 | { |
229 | 0 | // don't override anything. |
230 | 0 | *result = false; |
231 | 0 | return NS_OK; |
232 | 0 | } |
233 | | |
234 | | //----------------------------------------------------------------------------- |
235 | | // nsIFileProtocolHandler methods: |
236 | | |
237 | | NS_IMETHODIMP |
238 | | nsFileProtocolHandler::NewFileURI(nsIFile *aFile, nsIURI **aResult) |
239 | 0 | { |
240 | 0 | NS_ENSURE_ARG_POINTER(aFile); |
241 | 0 |
|
242 | 0 | RefPtr<nsIFile> file(aFile); |
243 | 0 | // NOTE: the origin charset is assigned the value of the platform |
244 | 0 | // charset by the SetFile method. |
245 | 0 | return NS_MutateURI(new nsStandardURL::Mutator()) |
246 | 0 | .Apply(NS_MutatorMethod(&nsIFileURLMutator::SetFile, file)) |
247 | 0 | .Finalize(aResult); |
248 | 0 | } |
249 | | |
250 | | NS_IMETHODIMP |
251 | | nsFileProtocolHandler::NewFileURIMutator(nsIFile *aFile, nsIURIMutator **aResult) |
252 | 0 | { |
253 | 0 | NS_ENSURE_ARG_POINTER(aFile); |
254 | 0 | nsresult rv; |
255 | 0 |
|
256 | 0 | nsCOMPtr<nsIURIMutator> mutator = new nsStandardURL::Mutator(); |
257 | 0 | nsCOMPtr<nsIFileURLMutator> fileMutator = do_QueryInterface(mutator, &rv); |
258 | 0 | if (NS_FAILED(rv)) { |
259 | 0 | return rv; |
260 | 0 | } |
261 | 0 | |
262 | 0 | // NOTE: the origin charset is assigned the value of the platform |
263 | 0 | // charset by the SetFile method. |
264 | 0 | rv = fileMutator->SetFile(aFile); |
265 | 0 | if (NS_FAILED(rv)) { |
266 | 0 | return rv; |
267 | 0 | } |
268 | 0 | |
269 | 0 | mutator.forget(aResult); |
270 | 0 | return NS_OK; |
271 | 0 | } |
272 | | |
273 | | NS_IMETHODIMP |
274 | | nsFileProtocolHandler::GetURLSpecFromFile(nsIFile *file, nsACString &result) |
275 | 0 | { |
276 | 0 | NS_ENSURE_ARG_POINTER(file); |
277 | 0 | return net_GetURLSpecFromFile(file, result); |
278 | 0 | } |
279 | | |
280 | | NS_IMETHODIMP |
281 | | nsFileProtocolHandler::GetURLSpecFromActualFile(nsIFile *file, |
282 | | nsACString &result) |
283 | 11 | { |
284 | 11 | NS_ENSURE_ARG_POINTER(file); |
285 | 11 | return net_GetURLSpecFromActualFile(file, result); |
286 | 11 | } |
287 | | |
288 | | NS_IMETHODIMP |
289 | | nsFileProtocolHandler::GetURLSpecFromDir(nsIFile *file, nsACString &result) |
290 | 0 | { |
291 | 0 | NS_ENSURE_ARG_POINTER(file); |
292 | 0 | return net_GetURLSpecFromDir(file, result); |
293 | 0 | } |
294 | | |
295 | | NS_IMETHODIMP |
296 | | nsFileProtocolHandler::GetFileFromURLSpec(const nsACString &spec, nsIFile **result) |
297 | 0 | { |
298 | 0 | return net_GetFileFromURLSpec(spec, result); |
299 | 0 | } |