2015-02-13 19:36:47 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
2012-05-21 11:12:37 +00:00
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2000-11-08 21:00:37 +00:00
|
|
|
|
2015-07-07 02:17:00 +00:00
|
|
|
#include "nsNetCID.h"
|
2000-11-08 21:00:37 +00:00
|
|
|
#include "nsNetUtil.h"
|
2015-07-07 02:17:00 +00:00
|
|
|
#include "nsIProtocolHandler.h"
|
2002-09-30 22:38:31 +00:00
|
|
|
#include "nsCRT.h"
|
2000-11-08 21:00:37 +00:00
|
|
|
|
2012-06-06 02:08:30 +00:00
|
|
|
#include "nsIFile.h"
|
2013-01-15 12:22:03 +00:00
|
|
|
#include <algorithm>
|
2010-09-18 12:42:07 +00:00
|
|
|
|
|
|
|
#ifdef MOZ_TOOLKIT_SEARCH
|
2010-08-14 16:15:21 +00:00
|
|
|
#include "nsIBrowserSearchService.h"
|
2010-09-18 12:42:07 +00:00
|
|
|
#endif
|
2000-11-08 21:00:37 +00:00
|
|
|
|
|
|
|
#include "nsIURIFixup.h"
|
|
|
|
#include "nsDefaultURIFixup.h"
|
2011-06-25 01:55:46 +00:00
|
|
|
#include "mozilla/Preferences.h"
|
2013-08-16 17:59:31 +00:00
|
|
|
#include "mozilla/dom/ContentChild.h"
|
|
|
|
#include "mozilla/ipc/InputStreamUtils.h"
|
|
|
|
#include "mozilla/ipc/URIUtils.h"
|
2015-09-22 15:26:15 +00:00
|
|
|
#include "mozilla/Tokenizer.h"
|
2012-11-06 17:14:35 +00:00
|
|
|
#include "nsIObserverService.h"
|
2013-09-23 21:30:40 +00:00
|
|
|
#include "nsXULAppAPI.h"
|
2011-06-25 01:55:46 +00:00
|
|
|
|
2014-06-19 18:22:45 +00:00
|
|
|
// Used to check if external protocol schemes are usable
|
|
|
|
#include "nsCExternalHandlerService.h"
|
|
|
|
#include "nsIExternalProtocolService.h"
|
|
|
|
|
2011-06-25 01:55:46 +00:00
|
|
|
using namespace mozilla;
|
2000-11-08 21:00:37 +00:00
|
|
|
|
|
|
|
/* Implementation file */
|
2014-04-27 07:06:00 +00:00
|
|
|
NS_IMPL_ISUPPORTS(nsDefaultURIFixup, nsIURIFixup)
|
2000-11-08 21:00:37 +00:00
|
|
|
|
2014-06-19 18:22:45 +00:00
|
|
|
static bool sInitializedPrefCaches = false;
|
2013-11-17 20:16:45 +00:00
|
|
|
static bool sFixTypos = true;
|
2014-11-16 23:01:59 +00:00
|
|
|
static bool sDNSFirstForSingleWords = false;
|
2014-06-19 18:22:45 +00:00
|
|
|
static bool sFixupKeywords = true;
|
2013-11-17 20:16:45 +00:00
|
|
|
|
2000-11-08 21:00:37 +00:00
|
|
|
nsDefaultURIFixup::nsDefaultURIFixup()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
nsDefaultURIFixup::~nsDefaultURIFixup()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2002-09-11 01:44:13 +00:00
|
|
|
NS_IMETHODIMP
|
2015-02-13 19:36:37 +00:00
|
|
|
nsDefaultURIFixup::CreateExposableURI(nsIURI* aURI, nsIURI** aReturn)
|
2002-09-11 01:44:13 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(aURI);
|
|
|
|
NS_ENSURE_ARG_POINTER(aReturn);
|
2002-09-11 01:44:13 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
bool isWyciwyg = false;
|
|
|
|
aURI->SchemeIs("wyciwyg", &isWyciwyg);
|
2002-09-11 01:44:13 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
nsAutoCString userPass;
|
|
|
|
aURI->GetUserPass(userPass);
|
2004-09-09 14:27:52 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// most of the time we can just AddRef and return
|
|
|
|
if (!isWyciwyg && userPass.IsEmpty()) {
|
|
|
|
*aReturn = aURI;
|
|
|
|
NS_ADDREF(*aReturn);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2002-09-11 01:44:13 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// Rats, we have to massage the URI
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
if (isWyciwyg) {
|
|
|
|
nsAutoCString path;
|
|
|
|
nsresult rv = aURI->GetPath(path);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2004-09-09 14:27:52 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
uint32_t pathLength = path.Length();
|
|
|
|
if (pathLength <= 2) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Path is of the form "//123/http://foo/bar", with a variable number of
|
|
|
|
// digits. To figure out where the "real" URL starts, search path for a '/',
|
|
|
|
// starting at the third character.
|
|
|
|
int32_t slashIndex = path.FindChar('/', 2);
|
|
|
|
if (slashIndex == kNotFound) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2004-09-09 14:27:52 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// Get the charset of the original URI so we can pass it to our fixed up
|
|
|
|
// URI.
|
|
|
|
nsAutoCString charset;
|
|
|
|
aURI->GetOriginCharset(charset);
|
2004-09-09 14:27:52 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
rv = NS_NewURI(getter_AddRefs(uri),
|
2004-09-09 14:27:52 +00:00
|
|
|
Substring(path, slashIndex + 1, pathLength - slashIndex - 1),
|
|
|
|
charset.get());
|
2015-02-13 19:36:37 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
} else {
|
|
|
|
// clone the URI so zapping user:pass doesn't change the original
|
|
|
|
nsresult rv = aURI->Clone(getter_AddRefs(uri));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
2002-09-11 01:44:13 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// hide user:pass unless overridden by pref
|
|
|
|
if (Preferences::GetBool("browser.fixup.hide_user_pass", true)) {
|
|
|
|
uri->SetUserPass(EmptyCString());
|
|
|
|
}
|
2002-09-11 01:44:13 +00:00
|
|
|
|
2015-04-17 13:19:00 +00:00
|
|
|
uri.forget(aReturn);
|
2015-02-13 19:36:37 +00:00
|
|
|
return NS_OK;
|
2002-09-11 01:44:13 +00:00
|
|
|
}
|
2000-11-08 21:00:37 +00:00
|
|
|
|
2001-11-06 22:55:30 +00:00
|
|
|
NS_IMETHODIMP
|
2015-02-13 19:36:37 +00:00
|
|
|
nsDefaultURIFixup::CreateFixupURI(const nsACString& aStringURI,
|
|
|
|
uint32_t aFixupFlags,
|
|
|
|
nsIInputStream** aPostData, nsIURI** aURI)
|
2014-04-24 22:42:00 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIURIFixupInfo> fixupInfo;
|
|
|
|
nsresult rv = GetFixupURIInfo(aStringURI, aFixupFlags, aPostData,
|
|
|
|
getter_AddRefs(fixupInfo));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
fixupInfo->GetPreferredURI(aURI);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2015-09-22 15:26:15 +00:00
|
|
|
// Returns true if the URL contains a user:password@ or user@
|
|
|
|
static bool
|
|
|
|
HasUserPassword(const nsACString& aStringURI)
|
|
|
|
{
|
|
|
|
mozilla::Tokenizer parser(aStringURI);
|
|
|
|
mozilla::Tokenizer::Token token;
|
|
|
|
|
|
|
|
// May start with any of "protocol:", "protocol://", "//", "://"
|
|
|
|
if (parser.Check(Tokenizer::TOKEN_WORD, token)) { // Skip protocol if any
|
|
|
|
}
|
|
|
|
if (parser.CheckChar(':')) { // Skip colon if found
|
|
|
|
}
|
|
|
|
while (parser.CheckChar('/')) { // Skip all of the following slashes
|
|
|
|
}
|
|
|
|
|
|
|
|
while (parser.Next(token)) {
|
|
|
|
if (token.Type() == Tokenizer::TOKEN_CHAR) {
|
|
|
|
if (token.AsChar() == '/') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (token.AsChar() == '@') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-04-24 22:42:00 +00:00
|
|
|
NS_IMETHODIMP
|
2015-02-13 19:36:37 +00:00
|
|
|
nsDefaultURIFixup::GetFixupURIInfo(const nsACString& aStringURI,
|
|
|
|
uint32_t aFixupFlags,
|
|
|
|
nsIInputStream** aPostData,
|
|
|
|
nsIURIFixupInfo** aInfo)
|
2000-11-08 21:00:37 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
NS_ENSURE_ARG(!aStringURI.IsEmpty());
|
2001-11-06 22:55:30 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
nsresult rv;
|
2000-11-08 21:00:37 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
nsAutoCString uriString(aStringURI);
|
2000-11-08 21:00:37 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// Eliminate embedded newlines, which single-line text fields now allow:
|
|
|
|
uriString.StripChars("\r\n");
|
|
|
|
// Cleanup the empty spaces that might be on each end:
|
|
|
|
uriString.Trim(" ");
|
2000-11-08 21:00:37 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE);
|
2002-09-11 01:44:13 +00:00
|
|
|
|
2015-10-18 05:24:48 +00:00
|
|
|
RefPtr<nsDefaultURIFixupInfo> info = new nsDefaultURIFixupInfo(uriString);
|
2015-02-13 19:36:37 +00:00
|
|
|
NS_ADDREF(*aInfo = info);
|
2014-08-25 13:54:00 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
nsCOMPtr<nsIIOService> ioService =
|
|
|
|
do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString scheme;
|
|
|
|
ioService->ExtractScheme(aStringURI, scheme);
|
|
|
|
|
|
|
|
// View-source is a pseudo scheme. We're interested in fixing up the stuff
|
|
|
|
// after it. The easiest way to do that is to call this method again with the
|
|
|
|
// "view-source:" lopped off and then prepend it again afterwards.
|
|
|
|
|
|
|
|
if (scheme.LowerCaseEqualsLiteral("view-source")) {
|
|
|
|
nsCOMPtr<nsIURIFixupInfo> uriInfo;
|
2015-07-07 10:26:15 +00:00
|
|
|
// We disable keyword lookup and alternate URIs so that small typos don't
|
|
|
|
// cause us to look at very different domains
|
|
|
|
uint32_t newFixupFlags = aFixupFlags & ~FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP
|
|
|
|
& ~FIXUP_FLAGS_MAKE_ALTERNATE_URI;
|
2015-02-13 19:36:37 +00:00
|
|
|
|
|
|
|
rv = GetFixupURIInfo(Substring(uriString,
|
|
|
|
sizeof("view-source:") - 1,
|
|
|
|
uriString.Length() -
|
|
|
|
(sizeof("view-source:") - 1)),
|
|
|
|
newFixupFlags, aPostData, getter_AddRefs(uriInfo));
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
2001-11-06 22:55:30 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
nsAutoCString spec;
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
uriInfo->GetPreferredURI(getter_AddRefs(uri));
|
|
|
|
if (!uri) {
|
|
|
|
return NS_ERROR_FAILURE;
|
2014-06-19 18:22:45 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
uri->GetSpec(spec);
|
|
|
|
uriString.AssignLiteral("view-source:");
|
|
|
|
uriString.Append(spec);
|
|
|
|
} else {
|
|
|
|
// Check for if it is a file URL
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
FileURIFixup(uriString, getter_AddRefs(uri));
|
|
|
|
// NB: FileURIFixup only returns a URI if it had to fix the protocol to
|
|
|
|
// do so, so passing in file:///foo/bar will not hit this path:
|
|
|
|
if (uri) {
|
|
|
|
uri.swap(info->mFixedURI);
|
|
|
|
info->mPreferredURI = info->mFixedURI;
|
|
|
|
info->mFixupChangedProtocol = true;
|
|
|
|
return NS_OK;
|
2013-11-17 20:16:45 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!sInitializedPrefCaches) {
|
|
|
|
// Check if we want to fix up common scheme typos.
|
|
|
|
rv = Preferences::AddBoolVarCache(&sFixTypos,
|
|
|
|
"browser.fixup.typo.scheme",
|
|
|
|
sFixTypos);
|
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(rv),
|
|
|
|
"Failed to observe \"browser.fixup.typo.scheme\"");
|
|
|
|
|
|
|
|
rv = Preferences::AddBoolVarCache(&sDNSFirstForSingleWords,
|
|
|
|
"browser.fixup.dns_first_for_single_words",
|
|
|
|
sDNSFirstForSingleWords);
|
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(rv),
|
|
|
|
"Failed to observe \"browser.fixup.dns_first_for_single_words\"");
|
|
|
|
|
|
|
|
rv = Preferences::AddBoolVarCache(&sFixupKeywords, "keyword.enabled",
|
|
|
|
sFixupKeywords);
|
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to observe \"keyword.enabled\"");
|
|
|
|
sInitializedPrefCaches = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix up common scheme typos.
|
|
|
|
if (sFixTypos && (aFixupFlags & FIXUP_FLAG_FIX_SCHEME_TYPOS)) {
|
|
|
|
// Fast-path for common cases.
|
|
|
|
if (scheme.IsEmpty() ||
|
|
|
|
scheme.LowerCaseEqualsLiteral("http") ||
|
|
|
|
scheme.LowerCaseEqualsLiteral("https") ||
|
|
|
|
scheme.LowerCaseEqualsLiteral("ftp") ||
|
|
|
|
scheme.LowerCaseEqualsLiteral("file")) {
|
|
|
|
// Do nothing.
|
|
|
|
} else if (scheme.LowerCaseEqualsLiteral("ttp")) {
|
|
|
|
// ttp -> http.
|
|
|
|
uriString.Replace(0, 3, "http");
|
|
|
|
scheme.AssignLiteral("http");
|
|
|
|
info->mFixupChangedProtocol = true;
|
|
|
|
} else if (scheme.LowerCaseEqualsLiteral("ttps")) {
|
|
|
|
// ttps -> https.
|
|
|
|
uriString.Replace(0, 4, "https");
|
|
|
|
scheme.AssignLiteral("https");
|
|
|
|
info->mFixupChangedProtocol = true;
|
|
|
|
} else if (scheme.LowerCaseEqualsLiteral("tps")) {
|
|
|
|
// tps -> https.
|
|
|
|
uriString.Replace(0, 3, "https");
|
|
|
|
scheme.AssignLiteral("https");
|
|
|
|
info->mFixupChangedProtocol = true;
|
|
|
|
} else if (scheme.LowerCaseEqualsLiteral("ps")) {
|
|
|
|
// ps -> https.
|
|
|
|
uriString.Replace(0, 2, "https");
|
|
|
|
scheme.AssignLiteral("https");
|
|
|
|
info->mFixupChangedProtocol = true;
|
|
|
|
} else if (scheme.LowerCaseEqualsLiteral("ile")) {
|
|
|
|
// ile -> file.
|
|
|
|
uriString.Replace(0, 3, "file");
|
|
|
|
scheme.AssignLiteral("file");
|
|
|
|
info->mFixupChangedProtocol = true;
|
|
|
|
} else if (scheme.LowerCaseEqualsLiteral("le")) {
|
|
|
|
// le -> file.
|
|
|
|
uriString.Replace(0, 2, "file");
|
|
|
|
scheme.AssignLiteral("file");
|
|
|
|
info->mFixupChangedProtocol = true;
|
2001-12-19 15:58:58 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
}
|
2000-11-08 21:00:37 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// Now we need to check whether "scheme" is something we don't
|
|
|
|
// really know about.
|
|
|
|
nsCOMPtr<nsIProtocolHandler> ourHandler, extHandler;
|
2014-08-06 11:36:27 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
ioService->GetProtocolHandler(scheme.get(), getter_AddRefs(ourHandler));
|
|
|
|
extHandler = do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "default");
|
2014-08-06 11:36:27 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
if (ourHandler != extHandler || !PossiblyHostPortUrl(uriString)) {
|
|
|
|
// Just try to create an URL out of it
|
|
|
|
rv = NS_NewURI(getter_AddRefs(info->mFixedURI), uriString, nullptr);
|
2014-04-24 22:42:00 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
if (!info->mFixedURI && rv != NS_ERROR_MALFORMED_URI) {
|
|
|
|
return rv;
|
2000-11-08 21:00:37 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (info->mFixedURI && ourHandler == extHandler && sFixupKeywords &&
|
|
|
|
(aFixupFlags & FIXUP_FLAG_FIX_SCHEME_TYPOS)) {
|
|
|
|
nsCOMPtr<nsIExternalProtocolService> extProtService =
|
|
|
|
do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID);
|
|
|
|
if (extProtService) {
|
|
|
|
bool handlerExists = false;
|
|
|
|
rv = extProtService->ExternalProtocolHandlerExists(scheme.get(),
|
|
|
|
&handlerExists);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
// This basically means we're dealing with a theoretically valid
|
|
|
|
// URI... but we have no idea how to load it. (e.g. "christmas:humbug")
|
|
|
|
// It's more likely the user wants to search, and so we
|
|
|
|
// chuck this over to their preferred search provider instead:
|
|
|
|
if (!handlerExists) {
|
2015-09-22 15:26:15 +00:00
|
|
|
bool hasUserPassword = HasUserPassword(uriString);
|
|
|
|
if (!hasUserPassword) {
|
|
|
|
TryKeywordFixupForURIInfo(uriString, info, aPostData);
|
|
|
|
} else {
|
|
|
|
// If the given URL has a user:password we can't just pass it to the
|
|
|
|
// external protocol handler; we'll try using it with http instead later
|
|
|
|
info->mFixedURI = nullptr;
|
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-11-08 21:00:37 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
if (info->mFixedURI) {
|
|
|
|
if (!info->mPreferredURI) {
|
|
|
|
if (aFixupFlags & FIXUP_FLAGS_MAKE_ALTERNATE_URI) {
|
2014-07-25 10:46:07 +00:00
|
|
|
info->mFixupCreatedAlternateURI = MakeAlternateURI(info->mFixedURI);
|
2015-02-13 19:36:37 +00:00
|
|
|
}
|
|
|
|
info->mPreferredURI = info->mFixedURI;
|
2001-12-19 15:58:58 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix up protocol string before calling KeywordURIFixup, because
|
|
|
|
// it cares about the hostname of such URIs:
|
|
|
|
nsCOMPtr<nsIURI> uriWithProtocol;
|
|
|
|
bool inputHadDuffProtocol = false;
|
|
|
|
|
|
|
|
// Prune duff protocol schemes
|
|
|
|
//
|
|
|
|
// ://totallybroken.url.com
|
|
|
|
// //shorthand.url.com
|
|
|
|
//
|
|
|
|
if (StringBeginsWith(uriString, NS_LITERAL_CSTRING("://"))) {
|
|
|
|
uriString = StringTail(uriString, uriString.Length() - 3);
|
|
|
|
inputHadDuffProtocol = true;
|
|
|
|
} else if (StringBeginsWith(uriString, NS_LITERAL_CSTRING("//"))) {
|
|
|
|
uriString = StringTail(uriString, uriString.Length() - 2);
|
|
|
|
inputHadDuffProtocol = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NB: this rv gets returned at the end of this method if we never
|
|
|
|
// do a keyword fixup after this (because the pref or the flags passed
|
|
|
|
// might not let us).
|
|
|
|
rv = FixupURIProtocol(uriString, info, getter_AddRefs(uriWithProtocol));
|
|
|
|
if (uriWithProtocol) {
|
|
|
|
info->mFixedURI = uriWithProtocol;
|
|
|
|
}
|
|
|
|
|
|
|
|
// See if it is a keyword
|
|
|
|
// Test whether keywords need to be fixed up
|
|
|
|
if (sFixupKeywords && (aFixupFlags & FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP) &&
|
|
|
|
!inputHadDuffProtocol) {
|
|
|
|
if (NS_SUCCEEDED(KeywordURIFixup(uriString, info, aPostData)) &&
|
|
|
|
info->mPreferredURI) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Did the caller want us to try an alternative URI?
|
|
|
|
// If so, attempt to fixup http://foo into http://www.foo.com
|
|
|
|
|
|
|
|
if (info->mFixedURI && aFixupFlags & FIXUP_FLAGS_MAKE_ALTERNATE_URI) {
|
|
|
|
info->mFixupCreatedAlternateURI = MakeAlternateURI(info->mFixedURI);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info->mFixedURI) {
|
2015-05-28 07:21:58 +00:00
|
|
|
info->mPreferredURI = info->mFixedURI;
|
2015-02-13 19:36:37 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we still haven't been able to construct a valid URI, try to force a
|
|
|
|
// keyword match. This catches search strings with '.' or ':' in them.
|
|
|
|
if (sFixupKeywords && (aFixupFlags & FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP)) {
|
|
|
|
rv = TryKeywordFixupForURIInfo(aStringURI, info, aPostData);
|
|
|
|
}
|
2006-06-15 21:15:28 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
return rv;
|
2000-11-08 21:00:37 +00:00
|
|
|
}
|
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDefaultURIFixup::KeywordToURI(const nsACString& aKeyword,
|
|
|
|
nsIInputStream** aPostData,
|
|
|
|
nsIURIFixupInfo** aInfo)
|
2006-05-16 03:02:28 +00:00
|
|
|
{
|
2015-10-18 05:24:48 +00:00
|
|
|
RefPtr<nsDefaultURIFixupInfo> info = new nsDefaultURIFixupInfo(aKeyword);
|
2015-02-13 19:36:37 +00:00
|
|
|
NS_ADDREF(*aInfo = info);
|
|
|
|
|
|
|
|
if (aPostData) {
|
|
|
|
*aPostData = nullptr;
|
|
|
|
}
|
|
|
|
NS_ENSURE_STATE(Preferences::GetRootBranch());
|
|
|
|
|
|
|
|
// Strip leading "?" and leading/trailing spaces from aKeyword
|
|
|
|
nsAutoCString keyword(aKeyword);
|
|
|
|
if (StringBeginsWith(keyword, NS_LITERAL_CSTRING("?"))) {
|
|
|
|
keyword.Cut(0, 1);
|
|
|
|
}
|
|
|
|
keyword.Trim(" ");
|
|
|
|
|
2015-07-04 01:29:00 +00:00
|
|
|
if (XRE_IsContentProcess()) {
|
2015-02-13 19:36:37 +00:00
|
|
|
dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
|
|
|
|
if (!contentChild) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2013-05-01 11:04:21 +00:00
|
|
|
}
|
2006-05-16 03:02:28 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
ipc::OptionalInputStreamParams postData;
|
|
|
|
ipc::OptionalURIParams uri;
|
|
|
|
nsAutoString providerName;
|
|
|
|
if (!contentChild->SendKeywordToURI(keyword, &providerName, &postData,
|
|
|
|
&uri)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
2010-10-31 20:01:28 +00:00
|
|
|
}
|
2013-08-16 17:59:31 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
CopyUTF8toUTF16(keyword, info->mKeywordAsSent);
|
|
|
|
info->mKeywordProviderName = providerName;
|
2014-03-25 18:37:13 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
if (aPostData) {
|
|
|
|
nsTArray<ipc::FileDescriptor> fds;
|
|
|
|
nsCOMPtr<nsIInputStream> temp = DeserializeInputStream(postData, fds);
|
|
|
|
temp.forget(aPostData);
|
2013-08-16 17:59:31 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
MOZ_ASSERT(fds.IsEmpty());
|
2013-08-16 17:59:31 +00:00
|
|
|
}
|
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
nsCOMPtr<nsIURI> temp = DeserializeURI(uri);
|
|
|
|
info->mPreferredURI = temp.forget();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-09-18 12:42:07 +00:00
|
|
|
#ifdef MOZ_TOOLKIT_SEARCH
|
2015-02-13 19:36:37 +00:00
|
|
|
// Try falling back to the search service's default search engine
|
|
|
|
nsCOMPtr<nsIBrowserSearchService> searchSvc =
|
|
|
|
do_GetService("@mozilla.org/browser/search-service;1");
|
|
|
|
if (searchSvc) {
|
|
|
|
nsCOMPtr<nsISearchEngine> defaultEngine;
|
|
|
|
searchSvc->GetDefaultEngine(getter_AddRefs(defaultEngine));
|
|
|
|
if (defaultEngine) {
|
|
|
|
nsCOMPtr<nsISearchSubmission> submission;
|
|
|
|
nsAutoString responseType;
|
|
|
|
// We allow default search plugins to specify alternate
|
|
|
|
// parameters that are specific to keyword searches.
|
|
|
|
NS_NAMED_LITERAL_STRING(mozKeywordSearch,
|
|
|
|
"application/x-moz-keywordsearch");
|
|
|
|
bool supportsResponseType = false;
|
|
|
|
defaultEngine->SupportsResponseType(mozKeywordSearch,
|
|
|
|
&supportsResponseType);
|
|
|
|
if (supportsResponseType) {
|
|
|
|
responseType.Assign(mozKeywordSearch);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ConvertUTF8toUTF16 keywordW(keyword);
|
|
|
|
defaultEngine->GetSubmission(keywordW,
|
|
|
|
responseType,
|
|
|
|
NS_LITERAL_STRING("keyword"),
|
|
|
|
getter_AddRefs(submission));
|
|
|
|
|
|
|
|
if (submission) {
|
|
|
|
nsCOMPtr<nsIInputStream> postData;
|
|
|
|
submission->GetPostData(getter_AddRefs(postData));
|
|
|
|
if (aPostData) {
|
|
|
|
postData.forget(aPostData);
|
|
|
|
} else if (postData) {
|
|
|
|
// The submission specifies POST data (i.e. the search
|
|
|
|
// engine's "method" is POST), but our caller didn't allow
|
|
|
|
// passing post data back. No point passing back a URL that
|
|
|
|
// won't load properly.
|
|
|
|
return NS_ERROR_FAILURE;
|
2010-08-14 16:15:21 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
|
|
|
|
defaultEngine->GetName(info->mKeywordProviderName);
|
|
|
|
info->mKeywordAsSent = keywordW;
|
|
|
|
return submission->GetUri(getter_AddRefs(info->mPreferredURI));
|
|
|
|
}
|
2010-08-14 16:15:21 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
}
|
2010-09-18 12:42:07 +00:00
|
|
|
#endif
|
2006-05-16 03:02:28 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// out of options
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2006-05-16 03:02:28 +00:00
|
|
|
}
|
2000-11-08 21:00:37 +00:00
|
|
|
|
2014-09-11 13:50:55 +00:00
|
|
|
// Helper to deal with passing around uri fixup stuff
|
|
|
|
nsresult
|
2015-02-13 19:36:37 +00:00
|
|
|
nsDefaultURIFixup::TryKeywordFixupForURIInfo(const nsACString& aURIString,
|
2014-09-11 13:50:55 +00:00
|
|
|
nsDefaultURIFixupInfo* aFixupInfo,
|
2015-02-13 19:36:37 +00:00
|
|
|
nsIInputStream** aPostData)
|
2014-09-11 13:50:55 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
nsCOMPtr<nsIURIFixupInfo> keywordInfo;
|
|
|
|
nsresult rv = KeywordToURI(aURIString, aPostData,
|
|
|
|
getter_AddRefs(keywordInfo));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
keywordInfo->GetKeywordProviderName(aFixupInfo->mKeywordProviderName);
|
|
|
|
keywordInfo->GetKeywordAsSent(aFixupInfo->mKeywordAsSent);
|
|
|
|
keywordInfo->GetPreferredURI(getter_AddRefs(aFixupInfo->mPreferredURI));
|
|
|
|
}
|
|
|
|
return rv;
|
2014-09-11 13:50:55 +00:00
|
|
|
}
|
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
bool
|
|
|
|
nsDefaultURIFixup::MakeAlternateURI(nsIURI* aURI)
|
2001-12-19 15:58:58 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
if (!Preferences::GetRootBranch()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!Preferences::GetBool("browser.fixup.alternate.enabled", true)) {
|
|
|
|
return false;
|
|
|
|
}
|
2002-03-22 14:29:52 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// Code only works for http. Not for any other protocol including https!
|
|
|
|
bool isHttp = false;
|
|
|
|
aURI->SchemeIs("http", &isHttp);
|
|
|
|
if (!isHttp) {
|
|
|
|
return false;
|
|
|
|
}
|
2002-03-22 14:29:52 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// Security - URLs with user / password info should NOT be fixed up
|
|
|
|
nsAutoCString userpass;
|
|
|
|
aURI->GetUserPass(userpass);
|
|
|
|
if (!userpass.IsEmpty()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoCString oldHost;
|
|
|
|
nsAutoCString newHost;
|
|
|
|
aURI->GetHost(oldHost);
|
|
|
|
|
|
|
|
// Count the dots
|
|
|
|
int32_t numDots = 0;
|
|
|
|
nsReadingIterator<char> iter;
|
|
|
|
nsReadingIterator<char> iterEnd;
|
|
|
|
oldHost.BeginReading(iter);
|
|
|
|
oldHost.EndReading(iterEnd);
|
|
|
|
while (iter != iterEnd) {
|
|
|
|
if (*iter == '.') {
|
|
|
|
numDots++;
|
2001-12-19 15:58:58 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
++iter;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the prefix and suffix to stick onto the new hostname. By default these
|
|
|
|
// are www. & .com but they could be any other value, e.g. www. & .org
|
|
|
|
|
|
|
|
nsAutoCString prefix("www.");
|
|
|
|
nsAdoptingCString prefPrefix =
|
|
|
|
Preferences::GetCString("browser.fixup.alternate.prefix");
|
|
|
|
if (prefPrefix) {
|
|
|
|
prefix.Assign(prefPrefix);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoCString suffix(".com");
|
|
|
|
nsAdoptingCString prefSuffix =
|
|
|
|
Preferences::GetCString("browser.fixup.alternate.suffix");
|
|
|
|
if (prefSuffix) {
|
|
|
|
suffix.Assign(prefSuffix);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (numDots == 0) {
|
|
|
|
newHost.Assign(prefix);
|
|
|
|
newHost.Append(oldHost);
|
|
|
|
newHost.Append(suffix);
|
|
|
|
} else if (numDots == 1) {
|
|
|
|
if (!prefix.IsEmpty() &&
|
|
|
|
oldHost.EqualsIgnoreCase(prefix.get(), prefix.Length())) {
|
|
|
|
newHost.Assign(oldHost);
|
|
|
|
newHost.Append(suffix);
|
|
|
|
} else if (!suffix.IsEmpty()) {
|
|
|
|
newHost.Assign(prefix);
|
|
|
|
newHost.Append(oldHost);
|
|
|
|
} else {
|
|
|
|
// Do nothing
|
|
|
|
return false;
|
2001-12-19 15:58:58 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
} else {
|
|
|
|
// Do nothing
|
|
|
|
return false;
|
|
|
|
}
|
2001-12-19 15:58:58 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
if (newHost.IsEmpty()) {
|
|
|
|
return false;
|
|
|
|
}
|
2001-12-19 15:58:58 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// Assign the new host string over the old one
|
|
|
|
aURI->SetHost(newHost);
|
|
|
|
return true;
|
2001-12-19 15:58:58 +00:00
|
|
|
}
|
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
nsresult
|
|
|
|
nsDefaultURIFixup::FileURIFixup(const nsACString& aStringURI, nsIURI** aURI)
|
2000-11-08 21:00:37 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
nsAutoCString uriSpecOut;
|
|
|
|
|
|
|
|
nsresult rv = ConvertFileToStringURI(aStringURI, uriSpecOut);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
// if this is file url, uriSpecOut is already in FS charset
|
|
|
|
if (NS_SUCCEEDED(NS_NewURI(aURI, uriSpecOut.get(), nullptr))) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
2000-11-08 21:00:37 +00:00
|
|
|
}
|
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
nsresult
|
|
|
|
nsDefaultURIFixup::ConvertFileToStringURI(const nsACString& aIn,
|
|
|
|
nsCString& aResult)
|
2000-11-08 21:00:37 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
bool attemptFixup = false;
|
2001-05-17 19:24:42 +00:00
|
|
|
|
2014-02-10 22:57:01 +00:00
|
|
|
#if defined(XP_WIN)
|
2015-02-13 19:36:37 +00:00
|
|
|
// Check for \ in the url-string or just a drive (PC)
|
2015-08-13 22:49:15 +00:00
|
|
|
if (aIn.Contains('\\') ||
|
2015-02-13 19:36:37 +00:00
|
|
|
(aIn.Length() == 2 && (aIn.Last() == ':' || aIn.Last() == '|'))) {
|
|
|
|
attemptFixup = true;
|
|
|
|
}
|
Bug 627277 - Remove (broken) BeOS support. r=biesi,dwitte,gavin,joe,jorendorff,josh,khuey,mfinkle,neil,Pike,roc,shaver,smontagu,taras
2011-02-19 19:10:24 +00:00
|
|
|
#elif defined(XP_UNIX)
|
2015-02-13 19:36:37 +00:00
|
|
|
// Check if it starts with / (UNIX)
|
|
|
|
if (aIn.First() == '/') {
|
|
|
|
attemptFixup = true;
|
|
|
|
}
|
2000-11-08 21:00:37 +00:00
|
|
|
#else
|
2015-02-13 19:36:37 +00:00
|
|
|
// Do nothing (All others for now)
|
2000-11-08 21:00:37 +00:00
|
|
|
#endif
|
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
if (attemptFixup) {
|
|
|
|
// Test if this is a valid path by trying to create a local file
|
|
|
|
// object. The URL of that is returned if successful.
|
2001-06-22 01:28:18 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// NOTE: Please be sure to check that the call to NS_NewLocalFile
|
|
|
|
// rejects bad file paths when using this code on a new
|
|
|
|
// platform.
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFile> filePath;
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
// this is not the real fix but a temporary fix
|
|
|
|
// in order to really fix the problem, we need to change the
|
|
|
|
// nsICmdLineService interface to use wstring to pass paramenters
|
|
|
|
// instead of string since path name and other argument could be
|
|
|
|
// in non ascii.(see bug 87127) Since it is too risky to make interface
|
|
|
|
// change right now, we decide not to do so now.
|
|
|
|
// Therefore, the aIn we receive here maybe already in damage form
|
|
|
|
// (e.g. treat every bytes as ISO-8859-1 and cast up to char16_t
|
|
|
|
// while the real data could be in file system charset )
|
|
|
|
// we choice the following logic which will work for most of the case.
|
|
|
|
// Case will still failed only if it meet ALL the following condiction:
|
|
|
|
// 1. running on CJK, Russian, or Greek system, and
|
|
|
|
// 2. user type it from URL bar
|
|
|
|
// 3. the file name contains character in the range of
|
|
|
|
// U+00A1-U+00FF but encode as different code point in file
|
|
|
|
// system charset (e.g. ACP on window)- this is very rare case
|
|
|
|
// We should remove this logic and convert to File system charset here
|
|
|
|
// once we change nsICmdLineService to use wstring and ensure
|
|
|
|
// all the Unicode data come in is correctly converted.
|
|
|
|
// XXXbz nsICmdLineService doesn't hand back unicode, so in some cases
|
|
|
|
// what we have is actually a "utf8" version of a "utf16" string that's
|
|
|
|
// actually byte-expanded native-encoding data. Someone upstream needs
|
|
|
|
// to stop using AssignWithConversion and do things correctly. See bug
|
|
|
|
// 58866 for what happens if we remove this
|
|
|
|
// PossiblyByteExpandedFileName check.
|
|
|
|
NS_ConvertUTF8toUTF16 in(aIn);
|
|
|
|
if (PossiblyByteExpandedFileName(in)) {
|
|
|
|
// removes high byte
|
|
|
|
rv = NS_NewNativeLocalFile(NS_LossyConvertUTF16toASCII(in), false,
|
|
|
|
getter_AddRefs(filePath));
|
|
|
|
} else {
|
|
|
|
// input is unicode
|
|
|
|
rv = NS_NewLocalFile(in, false, getter_AddRefs(filePath));
|
2000-11-08 21:00:37 +00:00
|
|
|
}
|
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
NS_GetURLSpecFromFile(filePath, aResult);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
2000-11-08 21:00:37 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2014-04-24 22:42:00 +00:00
|
|
|
|
|
|
|
nsresult
|
2015-02-13 19:36:37 +00:00
|
|
|
nsDefaultURIFixup::FixupURIProtocol(const nsACString& aURIString,
|
2014-07-25 10:46:07 +00:00
|
|
|
nsDefaultURIFixupInfo* aFixupInfo,
|
|
|
|
nsIURI** aURI)
|
2014-04-24 22:42:00 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
nsAutoCString uriString(aURIString);
|
|
|
|
*aURI = nullptr;
|
|
|
|
|
|
|
|
// Add ftp:// or http:// to front of url if it has no spec
|
|
|
|
//
|
|
|
|
// Should fix:
|
|
|
|
//
|
|
|
|
// no-scheme.com
|
|
|
|
// ftp.no-scheme.com
|
|
|
|
// ftp4.no-scheme.com
|
|
|
|
// no-scheme.com/query?foo=http://www.foo.com
|
2015-09-22 15:26:15 +00:00
|
|
|
// user:pass@no-scheme.com
|
2015-02-13 19:36:37 +00:00
|
|
|
//
|
|
|
|
int32_t schemeDelim = uriString.Find("://", 0);
|
|
|
|
int32_t firstDelim = uriString.FindCharInSet("/:");
|
|
|
|
if (schemeDelim <= 0 ||
|
|
|
|
(firstDelim != -1 && schemeDelim > firstDelim)) {
|
|
|
|
// find host name
|
|
|
|
int32_t hostPos = uriString.FindCharInSet("/:?#");
|
|
|
|
if (hostPos == -1) {
|
|
|
|
hostPos = uriString.Length();
|
|
|
|
}
|
2014-04-24 22:42:00 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// extract host name
|
|
|
|
nsAutoCString hostSpec;
|
|
|
|
uriString.Left(hostSpec, hostPos);
|
2014-04-24 22:42:00 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// insert url spec corresponding to host name
|
2016-04-28 22:00:00 +00:00
|
|
|
uriString.InsertLiteral("http://", 0);
|
2015-02-13 19:36:37 +00:00
|
|
|
aFixupInfo->mFixupChangedProtocol = true;
|
|
|
|
} // end if checkprotocol
|
2014-04-24 22:42:00 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
return NS_NewURI(aURI, uriString, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsDefaultURIFixup::PossiblyHostPortUrl(const nsACString& aUrl)
|
2001-06-22 01:28:18 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
// Oh dear, the protocol is invalid. Test if the protocol might
|
|
|
|
// actually be a url without a protocol:
|
|
|
|
//
|
|
|
|
// http://www.faqs.org/rfcs/rfc1738.html
|
|
|
|
// http://www.faqs.org/rfcs/rfc2396.html
|
|
|
|
//
|
|
|
|
// e.g. Anything of the form:
|
|
|
|
//
|
|
|
|
// <hostname>:<port> or
|
|
|
|
// <hostname>:<port>/
|
|
|
|
//
|
|
|
|
// Where <hostname> is a string of alphanumeric characters and dashes
|
|
|
|
// separated by dots.
|
|
|
|
// and <port> is a 5 or less digits. This actually breaks the rfc2396
|
|
|
|
// definition of a scheme which allows dots in schemes.
|
|
|
|
//
|
|
|
|
// Note:
|
|
|
|
// People expecting this to work with
|
|
|
|
// <user>:<password>@<host>:<port>/<url-path> will be disappointed!
|
|
|
|
//
|
|
|
|
// Note: Parser could be a lot tighter, tossing out silly hostnames
|
|
|
|
// such as those containing consecutive dots and so on.
|
|
|
|
|
|
|
|
// Read the hostname which should of the form
|
|
|
|
// [a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*:
|
|
|
|
|
|
|
|
nsACString::const_iterator iterBegin;
|
|
|
|
nsACString::const_iterator iterEnd;
|
|
|
|
aUrl.BeginReading(iterBegin);
|
|
|
|
aUrl.EndReading(iterEnd);
|
|
|
|
nsACString::const_iterator iter = iterBegin;
|
|
|
|
|
|
|
|
while (iter != iterEnd) {
|
|
|
|
uint32_t chunkSize = 0;
|
|
|
|
// Parse a chunk of the address
|
|
|
|
while (iter != iterEnd &&
|
|
|
|
(*iter == '-' ||
|
|
|
|
nsCRT::IsAsciiAlpha(*iter) ||
|
|
|
|
nsCRT::IsAsciiDigit(*iter))) {
|
|
|
|
++chunkSize;
|
|
|
|
++iter;
|
2001-06-22 01:28:18 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
if (chunkSize == 0 || iter == iterEnd) {
|
|
|
|
return false;
|
2002-09-30 22:38:31 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
if (*iter == ':') {
|
|
|
|
// Go onto checking the for the digits
|
|
|
|
break;
|
2002-09-30 22:38:31 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
if (*iter != '.') {
|
|
|
|
// Whatever it is, it ain't a hostname!
|
|
|
|
return false;
|
2002-09-30 22:38:31 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
++iter;
|
|
|
|
}
|
|
|
|
if (iter == iterEnd) {
|
|
|
|
// No point continuing since there is no colon
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
++iter;
|
|
|
|
|
|
|
|
// Count the number of digits after the colon and before the
|
|
|
|
// next forward slash (or end of string)
|
|
|
|
|
|
|
|
uint32_t digitCount = 0;
|
|
|
|
while (iter != iterEnd && digitCount <= 5) {
|
|
|
|
if (nsCRT::IsAsciiDigit(*iter)) {
|
|
|
|
digitCount++;
|
|
|
|
} else if (*iter == '/') {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
// Whatever it is, it ain't a port!
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
++iter;
|
|
|
|
}
|
|
|
|
if (digitCount == 0 || digitCount > 5) {
|
|
|
|
// No digits or more digits than a port would have.
|
|
|
|
return false;
|
|
|
|
}
|
2002-09-30 22:38:31 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// Yes, it's possibly a host:port url
|
|
|
|
return true;
|
2002-09-30 22:38:31 +00:00
|
|
|
}
|
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
bool
|
|
|
|
nsDefaultURIFixup::PossiblyByteExpandedFileName(const nsAString& aIn)
|
2002-09-30 22:38:31 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
// XXXXX HACK XXXXX : please don't copy this code.
|
|
|
|
// There are cases where aIn contains the locale byte chars padded to short
|
|
|
|
// (thus the name "ByteExpanded"); whereas other cases
|
|
|
|
// have proper Unicode code points.
|
|
|
|
// This is a temporary fix. Please refer to 58866, 86948
|
|
|
|
|
|
|
|
nsReadingIterator<char16_t> iter;
|
|
|
|
nsReadingIterator<char16_t> iterEnd;
|
|
|
|
aIn.BeginReading(iter);
|
|
|
|
aIn.EndReading(iterEnd);
|
|
|
|
while (iter != iterEnd) {
|
|
|
|
if (*iter >= 0x0080 && *iter <= 0x00FF) {
|
|
|
|
return true;
|
2002-09-30 22:38:31 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
++iter;
|
|
|
|
}
|
|
|
|
return false;
|
2001-06-22 01:28:18 +00:00
|
|
|
}
|
2000-11-08 21:00:37 +00:00
|
|
|
|
2014-09-11 13:50:55 +00:00
|
|
|
nsresult
|
2015-02-13 19:36:37 +00:00
|
|
|
nsDefaultURIFixup::KeywordURIFixup(const nsACString& aURIString,
|
2014-09-11 13:50:55 +00:00
|
|
|
nsDefaultURIFixupInfo* aFixupInfo,
|
2015-02-13 19:36:37 +00:00
|
|
|
nsIInputStream** aPostData)
|
2000-11-08 21:00:37 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
// These are keyword formatted strings
|
|
|
|
// "what is mozilla"
|
|
|
|
// "what is mozilla?"
|
|
|
|
// "docshell site:mozilla.org" - has no dot/colon in the first space-separated substring
|
|
|
|
// "?mozilla" - anything that begins with a question mark
|
|
|
|
// "?site:mozilla.org docshell"
|
|
|
|
// Things that have a quote before the first dot/colon
|
|
|
|
// "mozilla" - checked against a whitelist to see if it's a host or not
|
|
|
|
// ".mozilla", "mozilla." - ditto
|
|
|
|
|
|
|
|
// These are not keyword formatted strings
|
|
|
|
// "www.blah.com" - first space-separated substring contains a dot, doesn't start with "?"
|
|
|
|
// "www.blah.com stuff"
|
|
|
|
// "nonQualifiedHost:80" - first space-separated substring contains a colon, doesn't start with "?"
|
|
|
|
// "nonQualifiedHost:80 args"
|
|
|
|
// "nonQualifiedHost?"
|
|
|
|
// "nonQualifiedHost?args"
|
|
|
|
// "nonQualifiedHost?some args"
|
|
|
|
// "blah.com."
|
|
|
|
|
|
|
|
// Note: uint32_t(kNotFound) is greater than any actual location
|
|
|
|
// in practice. So if we cast all locations to uint32_t, then a <
|
|
|
|
// b guarantees that either b is kNotFound and a is found, or both
|
|
|
|
// are found and a found before b.
|
|
|
|
|
|
|
|
uint32_t firstDotLoc = uint32_t(kNotFound);
|
|
|
|
uint32_t lastDotLoc = uint32_t(kNotFound);
|
|
|
|
uint32_t firstColonLoc = uint32_t(kNotFound);
|
|
|
|
uint32_t firstQuoteLoc = uint32_t(kNotFound);
|
|
|
|
uint32_t firstSpaceLoc = uint32_t(kNotFound);
|
|
|
|
uint32_t firstQMarkLoc = uint32_t(kNotFound);
|
|
|
|
uint32_t lastLSBracketLoc = uint32_t(kNotFound);
|
|
|
|
uint32_t lastSlashLoc = uint32_t(kNotFound);
|
|
|
|
uint32_t pos = 0;
|
|
|
|
uint32_t foundDots = 0;
|
|
|
|
uint32_t foundColons = 0;
|
|
|
|
uint32_t foundDigits = 0;
|
|
|
|
uint32_t foundRSBrackets = 0;
|
|
|
|
bool looksLikeIpv6 = true;
|
|
|
|
bool hasAsciiAlpha = false;
|
|
|
|
|
|
|
|
nsACString::const_iterator iterBegin;
|
|
|
|
nsACString::const_iterator iterEnd;
|
|
|
|
aURIString.BeginReading(iterBegin);
|
|
|
|
aURIString.EndReading(iterEnd);
|
|
|
|
nsACString::const_iterator iter = iterBegin;
|
|
|
|
|
|
|
|
while (iter != iterEnd) {
|
|
|
|
if (pos >= 1 && foundRSBrackets == 0) {
|
|
|
|
if (!(lastLSBracketLoc == 0 &&
|
|
|
|
(*iter == ':' ||
|
|
|
|
*iter == '.' ||
|
|
|
|
*iter == ']' ||
|
|
|
|
(*iter >= 'a' && *iter <= 'f') ||
|
|
|
|
(*iter >= 'A' && *iter <= 'F') ||
|
|
|
|
nsCRT::IsAsciiDigit(*iter)))) {
|
2014-09-10 16:42:00 +00:00
|
|
|
looksLikeIpv6 = false;
|
2015-02-13 19:36:37 +00:00
|
|
|
}
|
2014-09-10 16:42:00 +00:00
|
|
|
}
|
2015-04-18 11:20:42 +00:00
|
|
|
|
|
|
|
// If we're at the end of the string or this is the first slash,
|
|
|
|
// check if the thing before the slash looks like ipv4:
|
2015-05-06 17:57:23 +00:00
|
|
|
if ((iter.size_forward() == 1 ||
|
|
|
|
(lastSlashLoc == uint32_t(kNotFound) && *iter == '/')) &&
|
2015-04-18 11:20:42 +00:00
|
|
|
// Need 2 or 3 dots + only digits
|
|
|
|
(foundDots == 2 || foundDots == 3) &&
|
|
|
|
// and they should be all that came before now:
|
|
|
|
(foundDots + foundDigits == pos ||
|
|
|
|
// or maybe there was also exactly 1 colon that came after the last dot,
|
|
|
|
// and the digits, dots and colon were all that came before now:
|
|
|
|
(foundColons == 1 && firstColonLoc > lastDotLoc &&
|
|
|
|
foundDots + foundDigits + foundColons == pos))) {
|
|
|
|
// Hurray, we got ourselves some ipv4!
|
|
|
|
// At this point, there's no way we will do a keyword lookup, so just bail immediately:
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
if (*iter == '.') {
|
|
|
|
++foundDots;
|
|
|
|
lastDotLoc = pos;
|
|
|
|
if (firstDotLoc == uint32_t(kNotFound)) {
|
|
|
|
firstDotLoc = pos;
|
|
|
|
}
|
|
|
|
} else if (*iter == ':') {
|
|
|
|
++foundColons;
|
|
|
|
if (firstColonLoc == uint32_t(kNotFound)) {
|
|
|
|
firstColonLoc = pos;
|
|
|
|
}
|
|
|
|
} else if (*iter == ' ' && firstSpaceLoc == uint32_t(kNotFound)) {
|
|
|
|
firstSpaceLoc = pos;
|
|
|
|
} else if (*iter == '?' && firstQMarkLoc == uint32_t(kNotFound)) {
|
|
|
|
firstQMarkLoc = pos;
|
|
|
|
} else if ((*iter == '\'' || *iter == '"') &&
|
|
|
|
firstQuoteLoc == uint32_t(kNotFound)) {
|
|
|
|
firstQuoteLoc = pos;
|
|
|
|
} else if (*iter == '[') {
|
|
|
|
lastLSBracketLoc = pos;
|
|
|
|
} else if (*iter == ']') {
|
|
|
|
foundRSBrackets++;
|
|
|
|
} else if (*iter == '/') {
|
|
|
|
lastSlashLoc = pos;
|
|
|
|
} else if (nsCRT::IsAsciiAlpha(*iter)) {
|
|
|
|
hasAsciiAlpha = true;
|
|
|
|
} else if (nsCRT::IsAsciiDigit(*iter)) {
|
|
|
|
++foundDigits;
|
2014-09-16 17:20:00 +00:00
|
|
|
}
|
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
pos++;
|
|
|
|
iter++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lastLSBracketLoc > 0 || foundRSBrackets != 1) {
|
|
|
|
looksLikeIpv6 = false;
|
|
|
|
}
|
|
|
|
|
2015-04-18 11:20:42 +00:00
|
|
|
// If there are only colons and only hexadecimal characters ([a-z][0-9])
|
|
|
|
// enclosed in [], then don't do a keyword lookup
|
|
|
|
if (looksLikeIpv6) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
nsAutoCString asciiHost;
|
|
|
|
nsAutoCString host;
|
|
|
|
|
|
|
|
bool isValidAsciiHost =
|
|
|
|
aFixupInfo->mFixedURI &&
|
|
|
|
NS_SUCCEEDED(aFixupInfo->mFixedURI->GetAsciiHost(asciiHost)) &&
|
|
|
|
!asciiHost.IsEmpty();
|
|
|
|
|
|
|
|
bool isValidHost =
|
|
|
|
aFixupInfo->mFixedURI &&
|
|
|
|
NS_SUCCEEDED(aFixupInfo->mFixedURI->GetHost(host)) &&
|
|
|
|
!host.IsEmpty();
|
|
|
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
// We do keyword lookups if a space or quote preceded the dot, colon
|
|
|
|
// or question mark (or if the latter is not found, or if the input starts
|
|
|
|
// with a question mark)
|
|
|
|
if (((firstSpaceLoc < firstDotLoc || firstQuoteLoc < firstDotLoc) &&
|
|
|
|
(firstSpaceLoc < firstColonLoc || firstQuoteLoc < firstColonLoc) &&
|
|
|
|
(firstSpaceLoc < firstQMarkLoc || firstQuoteLoc < firstQMarkLoc)) ||
|
|
|
|
firstQMarkLoc == 0) {
|
|
|
|
rv = TryKeywordFixupForURIInfo(aFixupInfo->mOriginalInput, aFixupInfo,
|
|
|
|
aPostData);
|
2014-11-16 23:01:59 +00:00
|
|
|
// ... or when the host is the same as asciiHost and there are no
|
|
|
|
// characters from [a-z][A-Z]
|
2015-02-13 19:36:37 +00:00
|
|
|
} else if (isValidAsciiHost && isValidHost && !hasAsciiAlpha &&
|
|
|
|
host.EqualsIgnoreCase(asciiHost.get())) {
|
|
|
|
if (!sDNSFirstForSingleWords) {
|
|
|
|
rv = TryKeywordFixupForURIInfo(aFixupInfo->mOriginalInput, aFixupInfo,
|
|
|
|
aPostData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// ... or if there is no question mark or colon, and there is either no
|
|
|
|
// dot, or exactly 1 and it is the first or last character of the input:
|
|
|
|
else if ((firstDotLoc == uint32_t(kNotFound) ||
|
|
|
|
(foundDots == 1 && (firstDotLoc == 0 ||
|
|
|
|
firstDotLoc == aURIString.Length() - 1))) &&
|
|
|
|
firstColonLoc == uint32_t(kNotFound) &&
|
|
|
|
firstQMarkLoc == uint32_t(kNotFound)) {
|
|
|
|
if (isValidAsciiHost && IsDomainWhitelisted(asciiHost, firstDotLoc)) {
|
|
|
|
return NS_OK;
|
2014-04-24 22:42:00 +00:00
|
|
|
}
|
2014-12-22 00:03:26 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
// ... unless there are no dots, and a slash, and alpha characters, and
|
|
|
|
// this is a valid host:
|
|
|
|
if (firstDotLoc == uint32_t(kNotFound) &&
|
|
|
|
lastSlashLoc != uint32_t(kNotFound) &&
|
|
|
|
hasAsciiAlpha && isValidAsciiHost) {
|
|
|
|
return NS_OK;
|
2004-12-04 22:38:54 +00:00
|
|
|
}
|
2015-02-13 19:36:37 +00:00
|
|
|
|
|
|
|
// If we get here, we don't have a valid URI, or we did but the
|
|
|
|
// host is not whitelisted, so we do a keyword search *anyway*:
|
|
|
|
rv = TryKeywordFixupForURIInfo(aFixupInfo->mOriginalInput, aFixupInfo,
|
|
|
|
aPostData);
|
|
|
|
}
|
|
|
|
return rv;
|
2000-11-08 21:00:37 +00:00
|
|
|
}
|
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
bool
|
2016-03-31 17:16:07 +00:00
|
|
|
nsDefaultURIFixup::IsDomainWhitelisted(const nsACString& aAsciiHost,
|
2015-02-13 19:36:37 +00:00
|
|
|
const uint32_t aDotLoc)
|
2014-08-29 03:25:02 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
if (sDNSFirstForSingleWords) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Check if this domain is whitelisted as an actual
|
|
|
|
// domain (which will prevent a keyword query)
|
|
|
|
// NB: any processing of the host here should stay in sync with
|
|
|
|
// code in the front-end(s) that set the pref.
|
2014-08-29 03:25:02 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
nsAutoCString pref("browser.fixup.domainwhitelist.");
|
2014-08-29 03:25:02 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
if (aDotLoc == aAsciiHost.Length() - 1) {
|
|
|
|
pref.Append(Substring(aAsciiHost, 0, aAsciiHost.Length() - 1));
|
|
|
|
} else {
|
|
|
|
pref.Append(aAsciiHost);
|
|
|
|
}
|
2014-08-29 03:25:02 +00:00
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
return Preferences::GetBool(pref.get(), false);
|
2014-08-29 03:25:02 +00:00
|
|
|
}
|
|
|
|
|
2015-05-28 07:21:58 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDefaultURIFixup::IsDomainWhitelisted(const nsACString& aDomain,
|
|
|
|
const uint32_t aDotLoc,
|
|
|
|
bool* aResult)
|
|
|
|
{
|
2016-03-31 17:16:07 +00:00
|
|
|
*aResult = IsDomainWhitelisted(aDomain, aDotLoc);
|
2015-05-28 07:21:58 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-04-24 22:42:00 +00:00
|
|
|
/* Implementation of nsIURIFixupInfo */
|
|
|
|
NS_IMPL_ISUPPORTS(nsDefaultURIFixupInfo, nsIURIFixupInfo)
|
|
|
|
|
2015-02-13 19:36:37 +00:00
|
|
|
nsDefaultURIFixupInfo::nsDefaultURIFixupInfo(const nsACString& aOriginalInput)
|
|
|
|
: mFixupChangedProtocol(false)
|
|
|
|
, mFixupCreatedAlternateURI(false)
|
2014-04-24 22:42:00 +00:00
|
|
|
{
|
|
|
|
mOriginalInput = aOriginalInput;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsDefaultURIFixupInfo::~nsDefaultURIFixupInfo()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDefaultURIFixupInfo::GetConsumer(nsISupports** aConsumer)
|
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
*aConsumer = mConsumer;
|
|
|
|
NS_IF_ADDREF(*aConsumer);
|
|
|
|
return NS_OK;
|
2014-04-24 22:42:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDefaultURIFixupInfo::SetConsumer(nsISupports* aConsumer)
|
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
mConsumer = aConsumer;
|
|
|
|
return NS_OK;
|
2014-04-24 22:42:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDefaultURIFixupInfo::GetPreferredURI(nsIURI** aPreferredURI)
|
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
*aPreferredURI = mPreferredURI;
|
|
|
|
NS_IF_ADDREF(*aPreferredURI);
|
|
|
|
return NS_OK;
|
2014-04-24 22:42:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDefaultURIFixupInfo::GetFixedURI(nsIURI** aFixedURI)
|
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
*aFixedURI = mFixedURI;
|
|
|
|
NS_IF_ADDREF(*aFixedURI);
|
|
|
|
return NS_OK;
|
2014-04-24 22:42:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-02-13 19:36:37 +00:00
|
|
|
nsDefaultURIFixupInfo::GetKeywordProviderName(nsAString& aResult)
|
2014-09-11 13:50:55 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
aResult = mKeywordProviderName;
|
|
|
|
return NS_OK;
|
2014-09-11 13:50:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-02-13 19:36:37 +00:00
|
|
|
nsDefaultURIFixupInfo::GetKeywordAsSent(nsAString& aResult)
|
2014-04-24 22:42:00 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
aResult = mKeywordAsSent;
|
|
|
|
return NS_OK;
|
2014-04-24 22:42:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-02-13 19:36:37 +00:00
|
|
|
nsDefaultURIFixupInfo::GetFixupChangedProtocol(bool* aResult)
|
2014-04-24 22:42:00 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
*aResult = mFixupChangedProtocol;
|
|
|
|
return NS_OK;
|
2014-04-24 22:42:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-02-13 19:36:37 +00:00
|
|
|
nsDefaultURIFixupInfo::GetFixupCreatedAlternateURI(bool* aResult)
|
2014-04-24 22:42:00 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
*aResult = mFixupCreatedAlternateURI;
|
|
|
|
return NS_OK;
|
2014-04-24 22:42:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-02-13 19:36:37 +00:00
|
|
|
nsDefaultURIFixupInfo::GetOriginalInput(nsACString& aResult)
|
2014-04-24 22:42:00 +00:00
|
|
|
{
|
2015-02-13 19:36:37 +00:00
|
|
|
aResult = mOriginalInput;
|
|
|
|
return NS_OK;
|
2014-04-24 22:42:00 +00:00
|
|
|
}
|