Bug 460926 A11y hierachy is broken on Ubuntu 8.10 (GNOME 2.24), r=Evan.Yan sr=roc
[wine-gecko.git] / netwerk / protocol / file / src / nsFileProtocolHandler.cpp
blobf0a43a00b764f1342dcbd78aad41bae5a1214495
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
14 * License.
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.
23 * Contributor(s):
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"
45 #include "nsNetCID.h"
47 #include "nsIServiceManager.h"
48 #include "nsIURL.h"
50 #include "nsNetUtil.h"
52 // URL file handling, copied and modified from xpfe/components/bookmarks/src/nsBookmarksService.cpp
53 #ifdef XP_WIN
54 #ifndef WINCE
55 // Windows mobile does not support internet shortcuts including
56 // CLSID_InternetShortcut and IUniformResourceLocator used in
57 // this file
58 #include <shlobj.h>
59 #include <intshcut.h>
60 #endif
61 #include "nsIFileURL.h"
62 #ifdef CompareString
63 #undef CompareString
64 #endif
65 #endif
67 // URL file handling for OS/2
68 #ifdef XP_OS2
69 #include "prio.h"
70 #include "nsIFileURL.h"
71 #include "nsILocalFileOS2.h"
72 #endif
74 // URL file handling for freedesktop.org
75 #ifdef XP_UNIX
76 #include "nsINIParser.h"
77 #define DESKTOP_ENTRY_SECTION "Desktop Entry"
78 #endif
80 //-----------------------------------------------------------------------------
82 nsFileProtocolHandler::nsFileProtocolHandler()
86 nsresult
87 nsFileProtocolHandler::Init()
89 return NS_OK;
92 NS_IMPL_THREADSAFE_ISUPPORTS3(nsFileProtocolHandler,
93 nsIFileProtocolHandler,
94 nsIProtocolHandler,
95 nsISupportsWeakReference)
97 //-----------------------------------------------------------------------------
98 // nsIProtocolHandler methods:
100 #if defined(XP_WIN)
101 NS_IMETHODIMP
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;
107 #else
108 nsAutoString path;
109 nsresult rv = aFile->GetPath(path);
110 if (NS_FAILED(rv))
111 return rv;
113 if (path.Length() < 4)
114 return NS_ERROR_NOT_AVAILABLE;
115 if (!StringTail(path, 4).LowerCaseEqualsLiteral(".url"))
116 return NS_ERROR_NOT_AVAILABLE;
118 HRESULT result;
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);
142 urlFile->Release();
144 urlLink->Release();
146 return rv;
148 #endif //_MSC_VER < 1200 || defined (WINCE)
151 #elif defined(XP_OS2)
152 NS_IMETHODIMP
153 nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI)
155 nsresult rv;
157 nsCOMPtr<nsILocalFileOS2> os2File (do_QueryInterface(aFile, &rv));
158 if (NS_FAILED(rv))
159 return NS_ERROR_NOT_AVAILABLE;
161 // see if this file is a WPS UrlObject
162 PRBool isUrl;
163 rv = os2File->IsFileType(NS_LITERAL_CSTRING("UniformResourceLocator"),
164 &isUrl);
165 if (NS_FAILED(rv) || !isUrl)
166 return NS_ERROR_NOT_AVAILABLE;
168 // if so, open it & get its size
169 PRFileDesc *file;
170 rv = os2File->OpenNSPRFileDesc(PR_RDONLY, 0, &file);
171 if (NS_FAILED(rv))
172 return NS_ERROR_NOT_AVAILABLE;
174 PRInt64 fileSize;
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);
181 if (buffer) {
182 PRInt32 cnt = PR_Read(file, buffer, fileSize);
183 if (cnt > 0) {
184 buffer[cnt] = '\0';
185 if (NS_SUCCEEDED(NS_NewURI(aURI, nsDependentCString(buffer))))
186 rv = NS_OK;
188 NS_Free(buffer);
190 PR_Close(file);
192 return rv;
195 #elif defined(XP_UNIX)
196 NS_IMETHODIMP
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);
203 if (NS_FAILED(rv) ||
204 !StringEndsWith(leafName, NS_LITERAL_CSTRING(".desktop")))
205 return NS_ERROR_NOT_AVAILABLE;
207 nsCOMPtr<nsILocalFile> file(do_QueryInterface(aFile, &rv));
208 if (NS_FAILED(rv))
209 return rv;
211 nsINIParser parser;
212 rv = parser.Init(file);
213 if (NS_FAILED(rv))
214 return rv;
216 nsCAutoString type;
217 parser.GetString(DESKTOP_ENTRY_SECTION, "Type", type);
218 if (!type.EqualsLiteral("Link"))
219 return NS_ERROR_NOT_AVAILABLE;
221 nsCAutoString url;
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
230 NS_IMETHODIMP
231 nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI)
233 return NS_ERROR_NOT_AVAILABLE;
235 #endif // ReadURLFile()
237 NS_IMETHODIMP
238 nsFileProtocolHandler::GetScheme(nsACString &result)
240 result.AssignLiteral("file");
241 return NS_OK;
244 NS_IMETHODIMP
245 nsFileProtocolHandler::GetDefaultPort(PRInt32 *result)
247 *result = -1; // no port for file: URLs
248 return NS_OK;
251 NS_IMETHODIMP
252 nsFileProtocolHandler::GetProtocolFlags(PRUint32 *result)
254 *result = URI_NOAUTH | URI_IS_LOCAL_FILE;
255 return NS_OK;
258 NS_IMETHODIMP
259 nsFileProtocolHandler::NewURI(const nsACString &spec,
260 const char *charset,
261 nsIURI *baseURI,
262 nsIURI **result)
264 nsCOMPtr<nsIStandardURL> url = new nsStandardURL(PR_TRUE);
265 if (!url)
266 return NS_ERROR_OUT_OF_MEMORY;
268 const nsACString *specPtr = &spec;
270 #if defined(XP_WIN) || defined(XP_OS2)
271 nsCAutoString buf;
272 if (net_NormalizeFileURL(spec, buf))
273 specPtr = &buf;
274 #endif
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);
283 NS_IMETHODIMP
284 nsFileProtocolHandler::NewChannel(nsIURI *uri, nsIChannel **result)
286 nsFileChannel *chan = new nsFileChannel(uri);
287 if (!chan)
288 return NS_ERROR_OUT_OF_MEMORY;
289 NS_ADDREF(chan);
291 nsresult rv = chan->Init();
292 if (NS_FAILED(rv)) {
293 NS_RELEASE(chan);
294 return rv;
297 *result = chan;
298 return NS_OK;
301 NS_IMETHODIMP
302 nsFileProtocolHandler::AllowPort(PRInt32 port, const char *scheme, PRBool *result)
304 // don't override anything.
305 *result = PR_FALSE;
306 return NS_OK;
309 //-----------------------------------------------------------------------------
310 // nsIFileProtocolHandler methods:
312 NS_IMETHODIMP
313 nsFileProtocolHandler::NewFileURI(nsIFile *file, nsIURI **result)
315 NS_ENSURE_ARG_POINTER(file);
316 nsresult rv;
318 nsCOMPtr<nsIFileURL> url = new nsStandardURL(PR_TRUE);
319 if (!url)
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);
330 NS_IMETHODIMP
331 nsFileProtocolHandler::GetURLSpecFromFile(nsIFile *file, nsACString &result)
333 NS_ENSURE_ARG_POINTER(file);
334 return net_GetURLSpecFromFile(file, result);
337 NS_IMETHODIMP
338 nsFileProtocolHandler::GetFileFromURLSpec(const nsACString &spec, nsIFile **result)
340 return net_GetFileFromURLSpec(spec, result);