netwerk/protocol/file/nsFileProtocolHandler.cpp

branch
TOR_BUG_9701
changeset 10
ac0c01689b40
equal deleted inserted replaced
-1:000000000000 0:025b8667100b
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 "nsFileProtocolHandler.h"
8 #include "nsFileChannel.h"
9 #include "nsStandardURL.h"
10 #include "nsURLHelper.h"
11
12 #include "nsNetUtil.h"
13
14 // URL file handling, copied and modified from xpfe/components/bookmarks/src/nsBookmarksService.cpp
15 #ifdef XP_WIN
16 #include <shlobj.h>
17 #include <intshcut.h>
18 #include "nsIFileURL.h"
19 #ifdef CompareString
20 #undef CompareString
21 #endif
22 #endif
23
24 // URL file handling for freedesktop.org
25 #ifdef XP_UNIX
26 #include "nsINIParser.h"
27 #define DESKTOP_ENTRY_SECTION "Desktop Entry"
28 #endif
29
30 //-----------------------------------------------------------------------------
31
32 nsFileProtocolHandler::nsFileProtocolHandler()
33 {
34 }
35
36 nsresult
37 nsFileProtocolHandler::Init()
38 {
39 return NS_OK;
40 }
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 {
99 // We only support desktop files that end in ".desktop" like the spec says:
100 // http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s02.html
101 nsAutoCString leafName;
102 nsresult rv = aFile->GetNativeLeafName(leafName);
103 if (NS_FAILED(rv) ||
104 !StringEndsWith(leafName, NS_LITERAL_CSTRING(".desktop")))
105 return NS_ERROR_NOT_AVAILABLE;
106
107 nsINIParser parser;
108 rv = parser.Init(aFile);
109 if (NS_FAILED(rv))
110 return rv;
111
112 nsAutoCString type;
113 parser.GetString(DESKTOP_ENTRY_SECTION, "Type", type);
114 if (!type.EqualsLiteral("Link"))
115 return NS_ERROR_NOT_AVAILABLE;
116
117 nsAutoCString url;
118 rv = parser.GetString(DESKTOP_ENTRY_SECTION, "URL", url);
119 if (NS_FAILED(rv) || url.IsEmpty())
120 return NS_ERROR_NOT_AVAILABLE;
121
122 return NS_NewURI(aURI, url);
123 }
124
125 #else // other platforms
126 NS_IMETHODIMP
127 nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI)
128 {
129 return NS_ERROR_NOT_AVAILABLE;
130 }
131 #endif // ReadURLFile()
132
133 NS_IMETHODIMP
134 nsFileProtocolHandler::GetScheme(nsACString &result)
135 {
136 result.AssignLiteral("file");
137 return NS_OK;
138 }
139
140 NS_IMETHODIMP
141 nsFileProtocolHandler::GetDefaultPort(int32_t *result)
142 {
143 *result = -1; // no port for file: URLs
144 return NS_OK;
145 }
146
147 NS_IMETHODIMP
148 nsFileProtocolHandler::GetProtocolFlags(uint32_t *result)
149 {
150 *result = URI_NOAUTH | URI_IS_LOCAL_FILE | URI_IS_LOCAL_RESOURCE;
151 return NS_OK;
152 }
153
154 NS_IMETHODIMP
155 nsFileProtocolHandler::NewURI(const nsACString &spec,
156 const char *charset,
157 nsIURI *baseURI,
158 nsIURI **result)
159 {
160 nsCOMPtr<nsIStandardURL> url = new nsStandardURL(true);
161 if (!url)
162 return NS_ERROR_OUT_OF_MEMORY;
163
164 const nsACString *specPtr = &spec;
165
166 #if defined(XP_WIN)
167 nsAutoCString buf;
168 if (net_NormalizeFileURL(spec, buf))
169 specPtr = &buf;
170 #endif
171
172 nsresult rv = url->Init(nsIStandardURL::URLTYPE_NO_AUTHORITY, -1,
173 *specPtr, charset, baseURI);
174 if (NS_FAILED(rv)) return rv;
175
176 return CallQueryInterface(url, result);
177 }
178
179 NS_IMETHODIMP
180 nsFileProtocolHandler::NewChannel(nsIURI *uri, nsIChannel **result)
181 {
182 nsFileChannel *chan = new nsFileChannel(uri);
183 if (!chan)
184 return NS_ERROR_OUT_OF_MEMORY;
185 NS_ADDREF(chan);
186
187 nsresult rv = chan->Init();
188 if (NS_FAILED(rv)) {
189 NS_RELEASE(chan);
190 return rv;
191 }
192
193 *result = chan;
194 return NS_OK;
195 }
196
197 NS_IMETHODIMP
198 nsFileProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *result)
199 {
200 // don't override anything.
201 *result = false;
202 return NS_OK;
203 }
204
205 //-----------------------------------------------------------------------------
206 // nsIFileProtocolHandler methods:
207
208 NS_IMETHODIMP
209 nsFileProtocolHandler::NewFileURI(nsIFile *file, nsIURI **result)
210 {
211 NS_ENSURE_ARG_POINTER(file);
212 nsresult rv;
213
214 nsCOMPtr<nsIFileURL> url = new nsStandardURL(true);
215 if (!url)
216 return NS_ERROR_OUT_OF_MEMORY;
217
218 // NOTE: the origin charset is assigned the value of the platform
219 // charset by the SetFile method.
220 rv = url->SetFile(file);
221 if (NS_FAILED(rv)) return rv;
222
223 return CallQueryInterface(url, result);
224 }
225
226 NS_IMETHODIMP
227 nsFileProtocolHandler::GetURLSpecFromFile(nsIFile *file, nsACString &result)
228 {
229 NS_ENSURE_ARG_POINTER(file);
230 return net_GetURLSpecFromFile(file, result);
231 }
232
233 NS_IMETHODIMP
234 nsFileProtocolHandler::GetURLSpecFromActualFile(nsIFile *file,
235 nsACString &result)
236 {
237 NS_ENSURE_ARG_POINTER(file);
238 return net_GetURLSpecFromActualFile(file, result);
239 }
240
241 NS_IMETHODIMP
242 nsFileProtocolHandler::GetURLSpecFromDir(nsIFile *file, nsACString &result)
243 {
244 NS_ENSURE_ARG_POINTER(file);
245 return net_GetURLSpecFromDir(file, result);
246 }
247
248 NS_IMETHODIMP
249 nsFileProtocolHandler::GetFileFromURLSpec(const nsACString &spec, nsIFile **result)
250 {
251 return net_GetFileFromURLSpec(spec, result);
252 }

mercurial