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
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/
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
16 * The Original Code is mozilla.org code.
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.
24 * Rich Walsh <dragtext@e-vertise.com>
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.
38 * ***** END LICENSE BLOCK ***** */
40 #include "nsFileProtocolHandler.h"
41 #include "nsFileChannel.h"
42 #include "nsInputStreamChannel.h"
43 #include "nsStandardURL.h"
44 #include "nsURLHelper.h"
47 #include "nsIServiceManager.h"
50 #include "nsNetUtil.h"
52 // URL file handling, copied and modified from xpfe/components/bookmarks/src/nsBookmarksService.cpp
55 // Windows mobile does not support internet shortcuts including
56 // CLSID_InternetShortcut and IUniformResourceLocator used in
61 #include "nsIFileURL.h"
67 // URL file handling for OS/2
70 #include "nsIFileURL.h"
71 #include "nsILocalFileOS2.h"
74 // URL file handling for freedesktop.org
76 #include "nsINIParser.h"
77 #define DESKTOP_ENTRY_SECTION "Desktop Entry"
80 //-----------------------------------------------------------------------------
82 nsFileProtocolHandler::nsFileProtocolHandler()
87 nsFileProtocolHandler::Init()
92 NS_IMPL_THREADSAFE_ISUPPORTS3(nsFileProtocolHandler
,
93 nsIFileProtocolHandler
,
95 nsISupportsWeakReference
)
97 //-----------------------------------------------------------------------------
98 // nsIProtocolHandler methods:
102 nsFileProtocolHandler::ReadURLFile(nsIFile
* aFile
, nsIURI
** aURI
)
104 // IUniformResourceLocator isn't supported by VC5 (bless its little heart)
105 #if _MSC_VER < 1200 || defined (WINCE)
106 return NS_ERROR_NOT_AVAILABLE
;
109 nsresult rv
= aFile
->GetPath(path
);
113 if (path
.Length() < 4)
114 return NS_ERROR_NOT_AVAILABLE
;
115 if (!StringTail(path
, 4).LowerCaseEqualsLiteral(".url"))
116 return NS_ERROR_NOT_AVAILABLE
;
120 rv
= NS_ERROR_NOT_AVAILABLE
;
122 IUniformResourceLocatorW
* urlLink
= nsnull
;
123 result
= ::CoCreateInstance(CLSID_InternetShortcut
, NULL
, CLSCTX_INPROC_SERVER
,
124 IID_IUniformResourceLocatorW
, (void**)&urlLink
);
125 if (SUCCEEDED(result
) && urlLink
) {
126 IPersistFile
* urlFile
= nsnull
;
127 result
= urlLink
->QueryInterface(IID_IPersistFile
, (void**)&urlFile
);
128 if (SUCCEEDED(result
) && urlFile
) {
129 result
= urlFile
->Load(path
.get(), STGM_READ
);
130 if (SUCCEEDED(result
) ) {
131 LPWSTR lpTemp
= nsnull
;
133 // The URL this method will give us back seems to be already
134 // escaped. Hence, do not do escaping of our own.
135 result
= urlLink
->GetURL(&lpTemp
);
136 if (SUCCEEDED(result
) && lpTemp
) {
137 rv
= NS_NewURI(aURI
, nsDependentString(lpTemp
));
138 // free the string that GetURL alloc'd
139 CoTaskMemFree(lpTemp
);
148 #endif //_MSC_VER < 1200 || defined (WINCE)
151 #elif defined(XP_OS2)
153 nsFileProtocolHandler::ReadURLFile(nsIFile
* aFile
, nsIURI
** aURI
)
157 nsCOMPtr
<nsILocalFileOS2
> os2File (do_QueryInterface(aFile
, &rv
));
159 return NS_ERROR_NOT_AVAILABLE
;
161 // see if this file is a WPS UrlObject
163 rv
= os2File
->IsFileType(NS_LITERAL_CSTRING("UniformResourceLocator"),
165 if (NS_FAILED(rv
) || !isUrl
)
166 return NS_ERROR_NOT_AVAILABLE
;
168 // if so, open it & get its size
170 rv
= os2File
->OpenNSPRFileDesc(PR_RDONLY
, 0, &file
);
172 return NS_ERROR_NOT_AVAILABLE
;
175 os2File
->GetFileSize(&fileSize
);
176 rv
= NS_ERROR_NOT_AVAILABLE
;
178 // get a buffer, read the entire file, then create
179 // an nsURI; we assume the string is already escaped
180 char * buffer
= (char*)NS_Alloc(fileSize
+1);
182 PRInt32 cnt
= PR_Read(file
, buffer
, fileSize
);
185 if (NS_SUCCEEDED(NS_NewURI(aURI
, nsDependentCString(buffer
))))
195 #elif defined(XP_UNIX)
197 nsFileProtocolHandler::ReadURLFile(nsIFile
* aFile
, nsIURI
** aURI
)
199 // We only support desktop files that end in ".desktop" like the spec says:
200 // http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s02.html
201 nsCAutoString leafName
;
202 nsresult rv
= aFile
->GetNativeLeafName(leafName
);
204 !StringEndsWith(leafName
, NS_LITERAL_CSTRING(".desktop")))
205 return NS_ERROR_NOT_AVAILABLE
;
207 nsCOMPtr
<nsILocalFile
> file(do_QueryInterface(aFile
, &rv
));
212 rv
= parser
.Init(file
);
217 parser
.GetString(DESKTOP_ENTRY_SECTION
, "Type", type
);
218 if (!type
.EqualsLiteral("Link"))
219 return NS_ERROR_NOT_AVAILABLE
;
222 rv
= parser
.GetString(DESKTOP_ENTRY_SECTION
, "URL", url
);
223 if (NS_FAILED(rv
) || url
.IsEmpty())
224 return NS_ERROR_NOT_AVAILABLE
;
226 return NS_NewURI(aURI
, url
);
229 #else // other platforms
231 nsFileProtocolHandler::ReadURLFile(nsIFile
* aFile
, nsIURI
** aURI
)
233 return NS_ERROR_NOT_AVAILABLE
;
235 #endif // ReadURLFile()
238 nsFileProtocolHandler::GetScheme(nsACString
&result
)
240 result
.AssignLiteral("file");
245 nsFileProtocolHandler::GetDefaultPort(PRInt32
*result
)
247 *result
= -1; // no port for file: URLs
252 nsFileProtocolHandler::GetProtocolFlags(PRUint32
*result
)
254 *result
= URI_NOAUTH
| URI_IS_LOCAL_FILE
;
259 nsFileProtocolHandler::NewURI(const nsACString
&spec
,
264 nsCOMPtr
<nsIStandardURL
> url
= new nsStandardURL(PR_TRUE
);
266 return NS_ERROR_OUT_OF_MEMORY
;
268 const nsACString
*specPtr
= &spec
;
270 #if defined(XP_WIN) || defined(XP_OS2)
272 if (net_NormalizeFileURL(spec
, buf
))
276 nsresult rv
= url
->Init(nsIStandardURL::URLTYPE_NO_AUTHORITY
, -1,
277 *specPtr
, charset
, baseURI
);
278 if (NS_FAILED(rv
)) return rv
;
280 return CallQueryInterface(url
, result
);
284 nsFileProtocolHandler::NewChannel(nsIURI
*uri
, nsIChannel
**result
)
286 nsFileChannel
*chan
= new nsFileChannel(uri
);
288 return NS_ERROR_OUT_OF_MEMORY
;
291 nsresult rv
= chan
->Init();
302 nsFileProtocolHandler::AllowPort(PRInt32 port
, const char *scheme
, PRBool
*result
)
304 // don't override anything.
309 //-----------------------------------------------------------------------------
310 // nsIFileProtocolHandler methods:
313 nsFileProtocolHandler::NewFileURI(nsIFile
*file
, nsIURI
**result
)
315 NS_ENSURE_ARG_POINTER(file
);
318 nsCOMPtr
<nsIFileURL
> url
= new nsStandardURL(PR_TRUE
);
320 return NS_ERROR_OUT_OF_MEMORY
;
322 // NOTE: the origin charset is assigned the value of the platform
323 // charset by the SetFile method.
324 rv
= url
->SetFile(file
);
325 if (NS_FAILED(rv
)) return rv
;
327 return CallQueryInterface(url
, result
);
331 nsFileProtocolHandler::GetURLSpecFromFile(nsIFile
*file
, nsACString
&result
)
333 NS_ENSURE_ARG_POINTER(file
);
334 return net_GetURLSpecFromFile(file
, result
);
338 nsFileProtocolHandler::GetFileFromURLSpec(const nsACString
&spec
, nsIFile
**result
)
340 return net_GetFileFromURLSpec(spec
, result
);