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 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 1998
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Rich Walsh <dragtext@e-vertise.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "nsFileProtocolHandler.h"
41 : #include "nsFileChannel.h"
42 : #include "nsInputStreamChannel.h"
43 : #include "nsStandardURL.h"
44 : #include "nsURLHelper.h"
45 : #include "nsNetCID.h"
46 :
47 : #include "nsIServiceManager.h"
48 : #include "nsIURL.h"
49 :
50 : #include "nsNetUtil.h"
51 :
52 : // URL file handling, copied and modified from xpfe/components/bookmarks/src/nsBookmarksService.cpp
53 : #ifdef XP_WIN
54 : #include <shlobj.h>
55 : #include <intshcut.h>
56 : #include "nsIFileURL.h"
57 : #ifdef CompareString
58 : #undef CompareString
59 : #endif
60 : #endif
61 :
62 : // URL file handling for OS/2
63 : #ifdef XP_OS2
64 : #include "prio.h"
65 : #include "nsIFileURL.h"
66 : #include "nsILocalFileOS2.h"
67 : #endif
68 :
69 : // URL file handling for freedesktop.org
70 : #ifdef XP_UNIX
71 : #include "nsINIParser.h"
72 : #define DESKTOP_ENTRY_SECTION "Desktop Entry"
73 : #endif
74 :
75 : //-----------------------------------------------------------------------------
76 :
77 1419 : nsFileProtocolHandler::nsFileProtocolHandler()
78 : {
79 1419 : }
80 :
81 : nsresult
82 1419 : nsFileProtocolHandler::Init()
83 : {
84 1419 : return NS_OK;
85 : }
86 :
87 1787100 : NS_IMPL_THREADSAFE_ISUPPORTS3(nsFileProtocolHandler,
88 : nsIFileProtocolHandler,
89 : nsIProtocolHandler,
90 : nsISupportsWeakReference)
91 :
92 : //-----------------------------------------------------------------------------
93 : // nsIProtocolHandler methods:
94 :
95 : #if defined(XP_WIN)
96 : NS_IMETHODIMP
97 : nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI)
98 : {
99 : nsAutoString path;
100 : nsresult rv = aFile->GetPath(path);
101 : if (NS_FAILED(rv))
102 : return rv;
103 :
104 : if (path.Length() < 4)
105 : return NS_ERROR_NOT_AVAILABLE;
106 : if (!StringTail(path, 4).LowerCaseEqualsLiteral(".url"))
107 : return NS_ERROR_NOT_AVAILABLE;
108 :
109 : HRESULT result;
110 :
111 : rv = NS_ERROR_NOT_AVAILABLE;
112 :
113 : IUniformResourceLocatorW* urlLink = nsnull;
114 : result = ::CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
115 : IID_IUniformResourceLocatorW, (void**)&urlLink);
116 : if (SUCCEEDED(result) && urlLink) {
117 : IPersistFile* urlFile = nsnull;
118 : result = urlLink->QueryInterface(IID_IPersistFile, (void**)&urlFile);
119 : if (SUCCEEDED(result) && urlFile) {
120 : result = urlFile->Load(path.get(), STGM_READ);
121 : if (SUCCEEDED(result) ) {
122 : LPWSTR lpTemp = nsnull;
123 :
124 : // The URL this method will give us back seems to be already
125 : // escaped. Hence, do not do escaping of our own.
126 : result = urlLink->GetURL(&lpTemp);
127 : if (SUCCEEDED(result) && lpTemp) {
128 : rv = NS_NewURI(aURI, nsDependentString(lpTemp));
129 : // free the string that GetURL alloc'd
130 : CoTaskMemFree(lpTemp);
131 : }
132 : }
133 : urlFile->Release();
134 : }
135 : urlLink->Release();
136 : }
137 : return rv;
138 : }
139 :
140 : #elif defined(XP_OS2)
141 : NS_IMETHODIMP
142 : nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI)
143 : {
144 : nsresult rv;
145 :
146 : nsCOMPtr<nsILocalFileOS2> os2File (do_QueryInterface(aFile, &rv));
147 : if (NS_FAILED(rv))
148 : return NS_ERROR_NOT_AVAILABLE;
149 :
150 : // see if this file is a WPS UrlObject
151 : bool isUrl;
152 : rv = os2File->IsFileType(NS_LITERAL_CSTRING("UniformResourceLocator"),
153 : &isUrl);
154 : if (NS_FAILED(rv) || !isUrl)
155 : return NS_ERROR_NOT_AVAILABLE;
156 :
157 : // if so, open it & get its size
158 : PRFileDesc *file;
159 : rv = os2File->OpenNSPRFileDesc(PR_RDONLY, 0, &file);
160 : if (NS_FAILED(rv))
161 : return NS_ERROR_NOT_AVAILABLE;
162 :
163 : PRInt64 fileSize;
164 : os2File->GetFileSize(&fileSize);
165 : rv = NS_ERROR_NOT_AVAILABLE;
166 :
167 : // get a buffer, read the entire file, then create
168 : // an nsURI; we assume the string is already escaped
169 : char * buffer = (char*)NS_Alloc(fileSize+1);
170 : if (buffer) {
171 : PRInt32 cnt = PR_Read(file, buffer, fileSize);
172 : if (cnt > 0) {
173 : buffer[cnt] = '\0';
174 : if (NS_SUCCEEDED(NS_NewURI(aURI, nsDependentCString(buffer))))
175 : rv = NS_OK;
176 : }
177 : NS_Free(buffer);
178 : }
179 : PR_Close(file);
180 :
181 : return rv;
182 : }
183 :
184 : #elif defined(XP_UNIX)
185 : NS_IMETHODIMP
186 2915 : nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI)
187 : {
188 : // We only support desktop files that end in ".desktop" like the spec says:
189 : // http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s02.html
190 5830 : nsCAutoString leafName;
191 2915 : nsresult rv = aFile->GetNativeLeafName(leafName);
192 11660 : if (NS_FAILED(rv) ||
193 8745 : !StringEndsWith(leafName, NS_LITERAL_CSTRING(".desktop")))
194 2914 : return NS_ERROR_NOT_AVAILABLE;
195 :
196 2 : nsCOMPtr<nsILocalFile> file(do_QueryInterface(aFile, &rv));
197 1 : if (NS_FAILED(rv))
198 0 : return rv;
199 :
200 2 : nsINIParser parser;
201 1 : rv = parser.Init(file);
202 1 : if (NS_FAILED(rv))
203 0 : return rv;
204 :
205 2 : nsCAutoString type;
206 1 : parser.GetString(DESKTOP_ENTRY_SECTION, "Type", type);
207 1 : if (!type.EqualsLiteral("Link"))
208 0 : return NS_ERROR_NOT_AVAILABLE;
209 :
210 2 : nsCAutoString url;
211 1 : rv = parser.GetString(DESKTOP_ENTRY_SECTION, "URL", url);
212 1 : if (NS_FAILED(rv) || url.IsEmpty())
213 0 : return NS_ERROR_NOT_AVAILABLE;
214 :
215 1 : return NS_NewURI(aURI, url);
216 : }
217 :
218 : #else // other platforms
219 : NS_IMETHODIMP
220 : nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI)
221 : {
222 : return NS_ERROR_NOT_AVAILABLE;
223 : }
224 : #endif // ReadURLFile()
225 :
226 : NS_IMETHODIMP
227 0 : nsFileProtocolHandler::GetScheme(nsACString &result)
228 : {
229 0 : result.AssignLiteral("file");
230 0 : return NS_OK;
231 : }
232 :
233 : NS_IMETHODIMP
234 0 : nsFileProtocolHandler::GetDefaultPort(PRInt32 *result)
235 : {
236 0 : *result = -1; // no port for file: URLs
237 0 : return NS_OK;
238 : }
239 :
240 : NS_IMETHODIMP
241 109814 : nsFileProtocolHandler::GetProtocolFlags(PRUint32 *result)
242 : {
243 109814 : *result = URI_NOAUTH | URI_IS_LOCAL_FILE | URI_IS_LOCAL_RESOURCE;
244 109814 : return NS_OK;
245 : }
246 :
247 : NS_IMETHODIMP
248 141511 : nsFileProtocolHandler::NewURI(const nsACString &spec,
249 : const char *charset,
250 : nsIURI *baseURI,
251 : nsIURI **result)
252 : {
253 283022 : nsCOMPtr<nsIStandardURL> url = new nsStandardURL(true);
254 141511 : if (!url)
255 0 : return NS_ERROR_OUT_OF_MEMORY;
256 :
257 141511 : const nsACString *specPtr = &spec;
258 :
259 : #if defined(XP_WIN) || defined(XP_OS2)
260 : nsCAutoString buf;
261 : if (net_NormalizeFileURL(spec, buf))
262 : specPtr = &buf;
263 : #endif
264 :
265 141511 : nsresult rv = url->Init(nsIStandardURL::URLTYPE_NO_AUTHORITY, -1,
266 141511 : *specPtr, charset, baseURI);
267 141511 : if (NS_FAILED(rv)) return rv;
268 :
269 141511 : return CallQueryInterface(url, result);
270 : }
271 :
272 : NS_IMETHODIMP
273 49867 : nsFileProtocolHandler::NewChannel(nsIURI *uri, nsIChannel **result)
274 : {
275 49867 : nsFileChannel *chan = new nsFileChannel(uri);
276 49867 : if (!chan)
277 0 : return NS_ERROR_OUT_OF_MEMORY;
278 49867 : NS_ADDREF(chan);
279 :
280 49867 : nsresult rv = chan->Init();
281 49867 : if (NS_FAILED(rv)) {
282 0 : NS_RELEASE(chan);
283 0 : return rv;
284 : }
285 :
286 49867 : *result = chan;
287 49867 : return NS_OK;
288 : }
289 :
290 : NS_IMETHODIMP
291 0 : nsFileProtocolHandler::AllowPort(PRInt32 port, const char *scheme, bool *result)
292 : {
293 : // don't override anything.
294 0 : *result = false;
295 0 : return NS_OK;
296 : }
297 :
298 : //-----------------------------------------------------------------------------
299 : // nsIFileProtocolHandler methods:
300 :
301 : NS_IMETHODIMP
302 6324 : nsFileProtocolHandler::NewFileURI(nsIFile *file, nsIURI **result)
303 : {
304 6324 : NS_ENSURE_ARG_POINTER(file);
305 : nsresult rv;
306 :
307 12648 : nsCOMPtr<nsIFileURL> url = new nsStandardURL(true);
308 6324 : if (!url)
309 0 : return NS_ERROR_OUT_OF_MEMORY;
310 :
311 : // NOTE: the origin charset is assigned the value of the platform
312 : // charset by the SetFile method.
313 6324 : rv = url->SetFile(file);
314 6324 : if (NS_FAILED(rv)) return rv;
315 :
316 6324 : return CallQueryInterface(url, result);
317 : }
318 :
319 : NS_IMETHODIMP
320 3 : nsFileProtocolHandler::GetURLSpecFromFile(nsIFile *file, nsACString &result)
321 : {
322 3 : NS_ENSURE_ARG_POINTER(file);
323 3 : return net_GetURLSpecFromFile(file, result);
324 : }
325 :
326 : NS_IMETHODIMP
327 14178 : nsFileProtocolHandler::GetURLSpecFromActualFile(nsIFile *file,
328 : nsACString &result)
329 : {
330 14178 : NS_ENSURE_ARG_POINTER(file);
331 14178 : return net_GetURLSpecFromActualFile(file, result);
332 : }
333 :
334 : NS_IMETHODIMP
335 0 : nsFileProtocolHandler::GetURLSpecFromDir(nsIFile *file, nsACString &result)
336 : {
337 0 : NS_ENSURE_ARG_POINTER(file);
338 0 : return net_GetURLSpecFromDir(file, result);
339 : }
340 :
341 : NS_IMETHODIMP
342 0 : nsFileProtocolHandler::GetFileFromURLSpec(const nsACString &spec, nsIFile **result)
343 : {
344 0 : return net_GetFileFromURLSpec(spec, result);
345 : }
|