michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: // vim:ts=4 sw=4 sts=4 et cin: michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsFileProtocolHandler.h" michael@0: #include "nsFileChannel.h" michael@0: #include "nsStandardURL.h" michael@0: #include "nsURLHelper.h" michael@0: michael@0: #include "nsNetUtil.h" michael@0: michael@0: // URL file handling, copied and modified from xpfe/components/bookmarks/src/nsBookmarksService.cpp michael@0: #ifdef XP_WIN michael@0: #include michael@0: #include michael@0: #include "nsIFileURL.h" michael@0: #ifdef CompareString michael@0: #undef CompareString michael@0: #endif michael@0: #endif michael@0: michael@0: // URL file handling for freedesktop.org michael@0: #ifdef XP_UNIX michael@0: #include "nsINIParser.h" michael@0: #define DESKTOP_ENTRY_SECTION "Desktop Entry" michael@0: #endif michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: nsFileProtocolHandler::nsFileProtocolHandler() michael@0: { michael@0: } michael@0: michael@0: nsresult michael@0: nsFileProtocolHandler::Init() michael@0: { michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsFileProtocolHandler, michael@0: nsIFileProtocolHandler, michael@0: nsIProtocolHandler, michael@0: nsISupportsWeakReference) michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsIProtocolHandler methods: michael@0: michael@0: #if defined(XP_WIN) michael@0: NS_IMETHODIMP michael@0: nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI) michael@0: { michael@0: nsAutoString path; michael@0: nsresult rv = aFile->GetPath(path); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: if (path.Length() < 4) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: if (!StringTail(path, 4).LowerCaseEqualsLiteral(".url")) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: michael@0: HRESULT result; michael@0: michael@0: rv = NS_ERROR_NOT_AVAILABLE; michael@0: michael@0: IUniformResourceLocatorW* urlLink = nullptr; michael@0: result = ::CoCreateInstance(CLSID_InternetShortcut, nullptr, CLSCTX_INPROC_SERVER, michael@0: IID_IUniformResourceLocatorW, (void**)&urlLink); michael@0: if (SUCCEEDED(result) && urlLink) { michael@0: IPersistFile* urlFile = nullptr; michael@0: result = urlLink->QueryInterface(IID_IPersistFile, (void**)&urlFile); michael@0: if (SUCCEEDED(result) && urlFile) { michael@0: result = urlFile->Load(path.get(), STGM_READ); michael@0: if (SUCCEEDED(result) ) { michael@0: LPWSTR lpTemp = nullptr; michael@0: michael@0: // The URL this method will give us back seems to be already michael@0: // escaped. Hence, do not do escaping of our own. michael@0: result = urlLink->GetURL(&lpTemp); michael@0: if (SUCCEEDED(result) && lpTemp) { michael@0: rv = NS_NewURI(aURI, nsDependentString(lpTemp)); michael@0: // free the string that GetURL alloc'd michael@0: CoTaskMemFree(lpTemp); michael@0: } michael@0: } michael@0: urlFile->Release(); michael@0: } michael@0: urlLink->Release(); michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: #elif defined(XP_UNIX) michael@0: NS_IMETHODIMP michael@0: nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI) michael@0: { michael@0: // We only support desktop files that end in ".desktop" like the spec says: michael@0: // http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s02.html michael@0: nsAutoCString leafName; michael@0: nsresult rv = aFile->GetNativeLeafName(leafName); michael@0: if (NS_FAILED(rv) || michael@0: !StringEndsWith(leafName, NS_LITERAL_CSTRING(".desktop"))) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: michael@0: nsINIParser parser; michael@0: rv = parser.Init(aFile); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: nsAutoCString type; michael@0: parser.GetString(DESKTOP_ENTRY_SECTION, "Type", type); michael@0: if (!type.EqualsLiteral("Link")) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: michael@0: nsAutoCString url; michael@0: rv = parser.GetString(DESKTOP_ENTRY_SECTION, "URL", url); michael@0: if (NS_FAILED(rv) || url.IsEmpty()) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: michael@0: return NS_NewURI(aURI, url); michael@0: } michael@0: michael@0: #else // other platforms michael@0: NS_IMETHODIMP michael@0: nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: #endif // ReadURLFile() michael@0: michael@0: NS_IMETHODIMP michael@0: nsFileProtocolHandler::GetScheme(nsACString &result) michael@0: { michael@0: result.AssignLiteral("file"); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsFileProtocolHandler::GetDefaultPort(int32_t *result) michael@0: { michael@0: *result = -1; // no port for file: URLs michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsFileProtocolHandler::GetProtocolFlags(uint32_t *result) michael@0: { michael@0: *result = URI_NOAUTH | URI_IS_LOCAL_FILE | URI_IS_LOCAL_RESOURCE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsFileProtocolHandler::NewURI(const nsACString &spec, michael@0: const char *charset, michael@0: nsIURI *baseURI, michael@0: nsIURI **result) michael@0: { michael@0: nsCOMPtr url = new nsStandardURL(true); michael@0: if (!url) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: const nsACString *specPtr = &spec; michael@0: michael@0: #if defined(XP_WIN) michael@0: nsAutoCString buf; michael@0: if (net_NormalizeFileURL(spec, buf)) michael@0: specPtr = &buf; michael@0: #endif michael@0: michael@0: nsresult rv = url->Init(nsIStandardURL::URLTYPE_NO_AUTHORITY, -1, michael@0: *specPtr, charset, baseURI); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: return CallQueryInterface(url, result); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsFileProtocolHandler::NewChannel(nsIURI *uri, nsIChannel **result) michael@0: { michael@0: nsFileChannel *chan = new nsFileChannel(uri); michael@0: if (!chan) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: NS_ADDREF(chan); michael@0: michael@0: nsresult rv = chan->Init(); michael@0: if (NS_FAILED(rv)) { michael@0: NS_RELEASE(chan); michael@0: return rv; michael@0: } michael@0: michael@0: *result = chan; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsFileProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *result) michael@0: { michael@0: // don't override anything. michael@0: *result = false; michael@0: return NS_OK; michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsIFileProtocolHandler methods: michael@0: michael@0: NS_IMETHODIMP michael@0: nsFileProtocolHandler::NewFileURI(nsIFile *file, nsIURI **result) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(file); michael@0: nsresult rv; michael@0: michael@0: nsCOMPtr url = new nsStandardURL(true); michael@0: if (!url) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: // NOTE: the origin charset is assigned the value of the platform michael@0: // charset by the SetFile method. michael@0: rv = url->SetFile(file); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: return CallQueryInterface(url, result); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsFileProtocolHandler::GetURLSpecFromFile(nsIFile *file, nsACString &result) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(file); michael@0: return net_GetURLSpecFromFile(file, result); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsFileProtocolHandler::GetURLSpecFromActualFile(nsIFile *file, michael@0: nsACString &result) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(file); michael@0: return net_GetURLSpecFromActualFile(file, result); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsFileProtocolHandler::GetURLSpecFromDir(nsIFile *file, nsACString &result) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(file); michael@0: return net_GetURLSpecFromDir(file, result); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsFileProtocolHandler::GetFileFromURLSpec(const nsACString &spec, nsIFile **result) michael@0: { michael@0: return net_GetFileFromURLSpec(spec, result); michael@0: }