Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
michael@0 | 2 | * |
michael@0 | 3 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #include "nsNetUtil.h" |
michael@0 | 8 | #include "nsCRT.h" |
michael@0 | 9 | |
michael@0 | 10 | #include "nsIFile.h" |
michael@0 | 11 | #include <algorithm> |
michael@0 | 12 | |
michael@0 | 13 | #ifdef MOZ_TOOLKIT_SEARCH |
michael@0 | 14 | #include "nsIBrowserSearchService.h" |
michael@0 | 15 | #endif |
michael@0 | 16 | |
michael@0 | 17 | #include "nsIURIFixup.h" |
michael@0 | 18 | #include "nsDefaultURIFixup.h" |
michael@0 | 19 | #include "mozilla/Preferences.h" |
michael@0 | 20 | #include "mozilla/dom/ContentChild.h" |
michael@0 | 21 | #include "mozilla/ipc/InputStreamUtils.h" |
michael@0 | 22 | #include "mozilla/ipc/URIUtils.h" |
michael@0 | 23 | #include "nsIObserverService.h" |
michael@0 | 24 | #include "nsXULAppAPI.h" |
michael@0 | 25 | |
michael@0 | 26 | using namespace mozilla; |
michael@0 | 27 | |
michael@0 | 28 | /* Implementation file */ |
michael@0 | 29 | NS_IMPL_ISUPPORTS(nsDefaultURIFixup, nsIURIFixup) |
michael@0 | 30 | |
michael@0 | 31 | static bool sInitializedPrefCaches = false; |
michael@0 | 32 | static bool sFixTypos = true; |
michael@0 | 33 | |
michael@0 | 34 | nsDefaultURIFixup::nsDefaultURIFixup() |
michael@0 | 35 | { |
michael@0 | 36 | /* member initializers and constructor code */ |
michael@0 | 37 | } |
michael@0 | 38 | |
michael@0 | 39 | |
michael@0 | 40 | nsDefaultURIFixup::~nsDefaultURIFixup() |
michael@0 | 41 | { |
michael@0 | 42 | /* destructor code */ |
michael@0 | 43 | } |
michael@0 | 44 | |
michael@0 | 45 | /* nsIURI createExposableURI (in nsIURI aURI); */ |
michael@0 | 46 | NS_IMETHODIMP |
michael@0 | 47 | nsDefaultURIFixup::CreateExposableURI(nsIURI *aURI, nsIURI **aReturn) |
michael@0 | 48 | { |
michael@0 | 49 | NS_ENSURE_ARG_POINTER(aURI); |
michael@0 | 50 | NS_ENSURE_ARG_POINTER(aReturn); |
michael@0 | 51 | |
michael@0 | 52 | bool isWyciwyg = false; |
michael@0 | 53 | aURI->SchemeIs("wyciwyg", &isWyciwyg); |
michael@0 | 54 | |
michael@0 | 55 | nsAutoCString userPass; |
michael@0 | 56 | aURI->GetUserPass(userPass); |
michael@0 | 57 | |
michael@0 | 58 | // most of the time we can just AddRef and return |
michael@0 | 59 | if (!isWyciwyg && userPass.IsEmpty()) |
michael@0 | 60 | { |
michael@0 | 61 | *aReturn = aURI; |
michael@0 | 62 | NS_ADDREF(*aReturn); |
michael@0 | 63 | return NS_OK; |
michael@0 | 64 | } |
michael@0 | 65 | |
michael@0 | 66 | // Rats, we have to massage the URI |
michael@0 | 67 | nsCOMPtr<nsIURI> uri; |
michael@0 | 68 | if (isWyciwyg) |
michael@0 | 69 | { |
michael@0 | 70 | nsAutoCString path; |
michael@0 | 71 | nsresult rv = aURI->GetPath(path); |
michael@0 | 72 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 73 | |
michael@0 | 74 | uint32_t pathLength = path.Length(); |
michael@0 | 75 | if (pathLength <= 2) |
michael@0 | 76 | { |
michael@0 | 77 | return NS_ERROR_FAILURE; |
michael@0 | 78 | } |
michael@0 | 79 | |
michael@0 | 80 | // Path is of the form "//123/http://foo/bar", with a variable number of digits. |
michael@0 | 81 | // To figure out where the "real" URL starts, search path for a '/', starting at |
michael@0 | 82 | // the third character. |
michael@0 | 83 | int32_t slashIndex = path.FindChar('/', 2); |
michael@0 | 84 | if (slashIndex == kNotFound) |
michael@0 | 85 | { |
michael@0 | 86 | return NS_ERROR_FAILURE; |
michael@0 | 87 | } |
michael@0 | 88 | |
michael@0 | 89 | // Get the charset of the original URI so we can pass it to our fixed up URI. |
michael@0 | 90 | nsAutoCString charset; |
michael@0 | 91 | aURI->GetOriginCharset(charset); |
michael@0 | 92 | |
michael@0 | 93 | rv = NS_NewURI(getter_AddRefs(uri), |
michael@0 | 94 | Substring(path, slashIndex + 1, pathLength - slashIndex - 1), |
michael@0 | 95 | charset.get()); |
michael@0 | 96 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 97 | } |
michael@0 | 98 | else |
michael@0 | 99 | { |
michael@0 | 100 | // clone the URI so zapping user:pass doesn't change the original |
michael@0 | 101 | nsresult rv = aURI->Clone(getter_AddRefs(uri)); |
michael@0 | 102 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 103 | } |
michael@0 | 104 | |
michael@0 | 105 | // hide user:pass unless overridden by pref |
michael@0 | 106 | if (Preferences::GetBool("browser.fixup.hide_user_pass", true)) |
michael@0 | 107 | { |
michael@0 | 108 | uri->SetUserPass(EmptyCString()); |
michael@0 | 109 | } |
michael@0 | 110 | |
michael@0 | 111 | // return the fixed-up URI |
michael@0 | 112 | *aReturn = uri; |
michael@0 | 113 | NS_ADDREF(*aReturn); |
michael@0 | 114 | return NS_OK; |
michael@0 | 115 | } |
michael@0 | 116 | |
michael@0 | 117 | /* nsIURI createFixupURI (in nsAUTF8String aURIText, in unsigned long aFixupFlags); */ |
michael@0 | 118 | NS_IMETHODIMP |
michael@0 | 119 | nsDefaultURIFixup::CreateFixupURI(const nsACString& aStringURI, uint32_t aFixupFlags, |
michael@0 | 120 | nsIInputStream **aPostData, nsIURI **aURI) |
michael@0 | 121 | { |
michael@0 | 122 | NS_ENSURE_ARG(!aStringURI.IsEmpty()); |
michael@0 | 123 | NS_ENSURE_ARG_POINTER(aURI); |
michael@0 | 124 | |
michael@0 | 125 | nsresult rv; |
michael@0 | 126 | *aURI = nullptr; |
michael@0 | 127 | |
michael@0 | 128 | nsAutoCString uriString(aStringURI); |
michael@0 | 129 | uriString.Trim(" "); // Cleanup the empty spaces that might be on each end. |
michael@0 | 130 | |
michael@0 | 131 | // Eliminate embedded newlines, which single-line text fields now allow: |
michael@0 | 132 | uriString.StripChars("\r\n"); |
michael@0 | 133 | |
michael@0 | 134 | NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE); |
michael@0 | 135 | |
michael@0 | 136 | nsCOMPtr<nsIIOService> ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv); |
michael@0 | 137 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 138 | nsAutoCString scheme; |
michael@0 | 139 | ioService->ExtractScheme(aStringURI, scheme); |
michael@0 | 140 | |
michael@0 | 141 | // View-source is a pseudo scheme. We're interested in fixing up the stuff |
michael@0 | 142 | // after it. The easiest way to do that is to call this method again with the |
michael@0 | 143 | // "view-source:" lopped off and then prepend it again afterwards. |
michael@0 | 144 | |
michael@0 | 145 | if (scheme.LowerCaseEqualsLiteral("view-source")) |
michael@0 | 146 | { |
michael@0 | 147 | nsCOMPtr<nsIURI> uri; |
michael@0 | 148 | uint32_t newFixupFlags = aFixupFlags & ~FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP; |
michael@0 | 149 | |
michael@0 | 150 | rv = CreateFixupURI(Substring(uriString, |
michael@0 | 151 | sizeof("view-source:") - 1, |
michael@0 | 152 | uriString.Length() - |
michael@0 | 153 | (sizeof("view-source:") - 1)), |
michael@0 | 154 | newFixupFlags, aPostData, getter_AddRefs(uri)); |
michael@0 | 155 | if (NS_FAILED(rv)) |
michael@0 | 156 | return NS_ERROR_FAILURE; |
michael@0 | 157 | nsAutoCString spec; |
michael@0 | 158 | uri->GetSpec(spec); |
michael@0 | 159 | uriString.Assign(NS_LITERAL_CSTRING("view-source:") + spec); |
michael@0 | 160 | } |
michael@0 | 161 | else { |
michael@0 | 162 | // Check for if it is a file URL |
michael@0 | 163 | FileURIFixup(uriString, aURI); |
michael@0 | 164 | if(*aURI) |
michael@0 | 165 | return NS_OK; |
michael@0 | 166 | |
michael@0 | 167 | #if defined(XP_WIN) |
michael@0 | 168 | // Not a file URL, so translate '\' to '/' for convenience in the common protocols |
michael@0 | 169 | // e.g. catch |
michael@0 | 170 | // |
michael@0 | 171 | // http:\\broken.com\address |
michael@0 | 172 | // http:\\broken.com/blah |
michael@0 | 173 | // broken.com\blah |
michael@0 | 174 | // |
michael@0 | 175 | // Code will also do partial fix up the following urls |
michael@0 | 176 | // |
michael@0 | 177 | // http:\\broken.com\address/somewhere\image.jpg (stops at first forward slash) |
michael@0 | 178 | // http:\\broken.com\blah?arg=somearg\foo.jpg (stops at question mark) |
michael@0 | 179 | // http:\\broken.com#odd\ref (stops at hash) |
michael@0 | 180 | // |
michael@0 | 181 | if (scheme.IsEmpty() || |
michael@0 | 182 | scheme.LowerCaseEqualsLiteral("http") || |
michael@0 | 183 | scheme.LowerCaseEqualsLiteral("https") || |
michael@0 | 184 | scheme.LowerCaseEqualsLiteral("ftp")) |
michael@0 | 185 | { |
michael@0 | 186 | // Walk the string replacing backslashes with forward slashes until |
michael@0 | 187 | // the end is reached, or a question mark, or a hash, or a forward |
michael@0 | 188 | // slash. The forward slash test is to stop before trampling over |
michael@0 | 189 | // URIs which legitimately contain a mix of both forward and |
michael@0 | 190 | // backward slashes. |
michael@0 | 191 | nsAutoCString::iterator start; |
michael@0 | 192 | nsAutoCString::iterator end; |
michael@0 | 193 | uriString.BeginWriting(start); |
michael@0 | 194 | uriString.EndWriting(end); |
michael@0 | 195 | while (start != end) { |
michael@0 | 196 | if (*start == '?' || *start == '#' || *start == '/') |
michael@0 | 197 | break; |
michael@0 | 198 | if (*start == '\\') |
michael@0 | 199 | *start = '/'; |
michael@0 | 200 | ++start; |
michael@0 | 201 | } |
michael@0 | 202 | } |
michael@0 | 203 | #endif |
michael@0 | 204 | } |
michael@0 | 205 | |
michael@0 | 206 | if (!sInitializedPrefCaches) { |
michael@0 | 207 | // Check if we want to fix up common scheme typos. |
michael@0 | 208 | rv = Preferences::AddBoolVarCache(&sFixTypos, |
michael@0 | 209 | "browser.fixup.typo.scheme", |
michael@0 | 210 | sFixTypos); |
michael@0 | 211 | MOZ_ASSERT(NS_SUCCEEDED(rv), |
michael@0 | 212 | "Failed to observe \"browser.fixup.typo.scheme\""); |
michael@0 | 213 | sInitializedPrefCaches = true; |
michael@0 | 214 | } |
michael@0 | 215 | |
michael@0 | 216 | // Fix up common scheme typos. |
michael@0 | 217 | if (sFixTypos && (aFixupFlags & FIXUP_FLAG_FIX_SCHEME_TYPOS)) { |
michael@0 | 218 | |
michael@0 | 219 | // Fast-path for common cases. |
michael@0 | 220 | if (scheme.IsEmpty() || |
michael@0 | 221 | scheme.LowerCaseEqualsLiteral("http") || |
michael@0 | 222 | scheme.LowerCaseEqualsLiteral("https") || |
michael@0 | 223 | scheme.LowerCaseEqualsLiteral("ftp") || |
michael@0 | 224 | scheme.LowerCaseEqualsLiteral("file")) { |
michael@0 | 225 | // Do nothing. |
michael@0 | 226 | } else if (scheme.LowerCaseEqualsLiteral("ttp")) { |
michael@0 | 227 | // ttp -> http. |
michael@0 | 228 | uriString.Replace(0, 3, "http"); |
michael@0 | 229 | scheme.AssignLiteral("http"); |
michael@0 | 230 | } else if (scheme.LowerCaseEqualsLiteral("ttps")) { |
michael@0 | 231 | // ttps -> https. |
michael@0 | 232 | uriString.Replace(0, 4, "https"); |
michael@0 | 233 | scheme.AssignLiteral("https"); |
michael@0 | 234 | } else if (scheme.LowerCaseEqualsLiteral("tps")) { |
michael@0 | 235 | // tps -> https. |
michael@0 | 236 | uriString.Replace(0, 3, "https"); |
michael@0 | 237 | scheme.AssignLiteral("https"); |
michael@0 | 238 | } else if (scheme.LowerCaseEqualsLiteral("ps")) { |
michael@0 | 239 | // ps -> https. |
michael@0 | 240 | uriString.Replace(0, 2, "https"); |
michael@0 | 241 | scheme.AssignLiteral("https"); |
michael@0 | 242 | } else if (scheme.LowerCaseEqualsLiteral("ile")) { |
michael@0 | 243 | // ile -> file. |
michael@0 | 244 | uriString.Replace(0, 3, "file"); |
michael@0 | 245 | scheme.AssignLiteral("file"); |
michael@0 | 246 | } else if (scheme.LowerCaseEqualsLiteral("le")) { |
michael@0 | 247 | // le -> file. |
michael@0 | 248 | uriString.Replace(0, 2, "file"); |
michael@0 | 249 | scheme.AssignLiteral("file"); |
michael@0 | 250 | } |
michael@0 | 251 | } |
michael@0 | 252 | |
michael@0 | 253 | // Now we need to check whether "scheme" is something we don't |
michael@0 | 254 | // really know about. |
michael@0 | 255 | nsCOMPtr<nsIProtocolHandler> ourHandler, extHandler; |
michael@0 | 256 | |
michael@0 | 257 | ioService->GetProtocolHandler(scheme.get(), getter_AddRefs(ourHandler)); |
michael@0 | 258 | extHandler = do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"default"); |
michael@0 | 259 | |
michael@0 | 260 | if (ourHandler != extHandler || !PossiblyHostPortUrl(uriString)) { |
michael@0 | 261 | // Just try to create an URL out of it |
michael@0 | 262 | rv = NS_NewURI(aURI, uriString, nullptr); |
michael@0 | 263 | |
michael@0 | 264 | if (!*aURI && rv != NS_ERROR_MALFORMED_URI) { |
michael@0 | 265 | return rv; |
michael@0 | 266 | } |
michael@0 | 267 | } |
michael@0 | 268 | |
michael@0 | 269 | if (*aURI) { |
michael@0 | 270 | if (aFixupFlags & FIXUP_FLAGS_MAKE_ALTERNATE_URI) |
michael@0 | 271 | MakeAlternateURI(*aURI); |
michael@0 | 272 | return NS_OK; |
michael@0 | 273 | } |
michael@0 | 274 | |
michael@0 | 275 | // See if it is a keyword |
michael@0 | 276 | // Test whether keywords need to be fixed up |
michael@0 | 277 | bool fixupKeywords = false; |
michael@0 | 278 | if (aFixupFlags & FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP) { |
michael@0 | 279 | nsresult rv = Preferences::GetBool("keyword.enabled", &fixupKeywords); |
michael@0 | 280 | NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); |
michael@0 | 281 | if (fixupKeywords) |
michael@0 | 282 | { |
michael@0 | 283 | KeywordURIFixup(uriString, aPostData, aURI); |
michael@0 | 284 | if(*aURI) |
michael@0 | 285 | return NS_OK; |
michael@0 | 286 | } |
michael@0 | 287 | } |
michael@0 | 288 | |
michael@0 | 289 | // Prune duff protocol schemes |
michael@0 | 290 | // |
michael@0 | 291 | // ://totallybroken.url.com |
michael@0 | 292 | // //shorthand.url.com |
michael@0 | 293 | // |
michael@0 | 294 | if (StringBeginsWith(uriString, NS_LITERAL_CSTRING("://"))) |
michael@0 | 295 | { |
michael@0 | 296 | uriString = StringTail(uriString, uriString.Length() - 3); |
michael@0 | 297 | } |
michael@0 | 298 | else if (StringBeginsWith(uriString, NS_LITERAL_CSTRING("//"))) |
michael@0 | 299 | { |
michael@0 | 300 | uriString = StringTail(uriString, uriString.Length() - 2); |
michael@0 | 301 | } |
michael@0 | 302 | |
michael@0 | 303 | // Add ftp:// or http:// to front of url if it has no spec |
michael@0 | 304 | // |
michael@0 | 305 | // Should fix: |
michael@0 | 306 | // |
michael@0 | 307 | // no-scheme.com |
michael@0 | 308 | // ftp.no-scheme.com |
michael@0 | 309 | // ftp4.no-scheme.com |
michael@0 | 310 | // no-scheme.com/query?foo=http://www.foo.com |
michael@0 | 311 | // |
michael@0 | 312 | int32_t schemeDelim = uriString.Find("://",0); |
michael@0 | 313 | int32_t firstDelim = uriString.FindCharInSet("/:"); |
michael@0 | 314 | if (schemeDelim <= 0 || |
michael@0 | 315 | (firstDelim != -1 && schemeDelim > firstDelim)) { |
michael@0 | 316 | // find host name |
michael@0 | 317 | int32_t hostPos = uriString.FindCharInSet("/:?#"); |
michael@0 | 318 | if (hostPos == -1) |
michael@0 | 319 | hostPos = uriString.Length(); |
michael@0 | 320 | |
michael@0 | 321 | // extract host name |
michael@0 | 322 | nsAutoCString hostSpec; |
michael@0 | 323 | uriString.Left(hostSpec, hostPos); |
michael@0 | 324 | |
michael@0 | 325 | // insert url spec corresponding to host name |
michael@0 | 326 | if (IsLikelyFTP(hostSpec)) |
michael@0 | 327 | uriString.Assign(NS_LITERAL_CSTRING("ftp://") + uriString); |
michael@0 | 328 | else |
michael@0 | 329 | uriString.Assign(NS_LITERAL_CSTRING("http://") + uriString); |
michael@0 | 330 | } // end if checkprotocol |
michael@0 | 331 | |
michael@0 | 332 | rv = NS_NewURI(aURI, uriString, nullptr); |
michael@0 | 333 | |
michael@0 | 334 | // Did the caller want us to try an alternative URI? |
michael@0 | 335 | // If so, attempt to fixup http://foo into http://www.foo.com |
michael@0 | 336 | |
michael@0 | 337 | if (*aURI && aFixupFlags & FIXUP_FLAGS_MAKE_ALTERNATE_URI) { |
michael@0 | 338 | MakeAlternateURI(*aURI); |
michael@0 | 339 | } |
michael@0 | 340 | |
michael@0 | 341 | // If we still haven't been able to construct a valid URI, try to force a |
michael@0 | 342 | // keyword match. This catches search strings with '.' or ':' in them. |
michael@0 | 343 | if (!*aURI && fixupKeywords) |
michael@0 | 344 | { |
michael@0 | 345 | KeywordToURI(aStringURI, aPostData, aURI); |
michael@0 | 346 | if(*aURI) |
michael@0 | 347 | return NS_OK; |
michael@0 | 348 | } |
michael@0 | 349 | |
michael@0 | 350 | return rv; |
michael@0 | 351 | } |
michael@0 | 352 | |
michael@0 | 353 | NS_IMETHODIMP nsDefaultURIFixup::KeywordToURI(const nsACString& aKeyword, |
michael@0 | 354 | nsIInputStream **aPostData, |
michael@0 | 355 | nsIURI **aURI) |
michael@0 | 356 | { |
michael@0 | 357 | *aURI = nullptr; |
michael@0 | 358 | if (aPostData) { |
michael@0 | 359 | *aPostData = nullptr; |
michael@0 | 360 | } |
michael@0 | 361 | NS_ENSURE_STATE(Preferences::GetRootBranch()); |
michael@0 | 362 | |
michael@0 | 363 | // Strip leading "?" and leading/trailing spaces from aKeyword |
michael@0 | 364 | nsAutoCString keyword(aKeyword); |
michael@0 | 365 | if (StringBeginsWith(keyword, NS_LITERAL_CSTRING("?"))) { |
michael@0 | 366 | keyword.Cut(0, 1); |
michael@0 | 367 | } |
michael@0 | 368 | keyword.Trim(" "); |
michael@0 | 369 | |
michael@0 | 370 | if (XRE_GetProcessType() == GeckoProcessType_Content) { |
michael@0 | 371 | dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); |
michael@0 | 372 | if (!contentChild) { |
michael@0 | 373 | return NS_ERROR_NOT_AVAILABLE; |
michael@0 | 374 | } |
michael@0 | 375 | |
michael@0 | 376 | ipc::OptionalInputStreamParams postData; |
michael@0 | 377 | ipc::OptionalURIParams uri; |
michael@0 | 378 | if (!contentChild->SendKeywordToURI(keyword, &postData, &uri)) { |
michael@0 | 379 | return NS_ERROR_FAILURE; |
michael@0 | 380 | } |
michael@0 | 381 | |
michael@0 | 382 | if (aPostData) { |
michael@0 | 383 | nsTArray<ipc::FileDescriptor> fds; |
michael@0 | 384 | nsCOMPtr<nsIInputStream> temp = DeserializeInputStream(postData, fds); |
michael@0 | 385 | temp.forget(aPostData); |
michael@0 | 386 | |
michael@0 | 387 | MOZ_ASSERT(fds.IsEmpty()); |
michael@0 | 388 | } |
michael@0 | 389 | |
michael@0 | 390 | nsCOMPtr<nsIURI> temp = DeserializeURI(uri); |
michael@0 | 391 | temp.forget(aURI); |
michael@0 | 392 | return NS_OK; |
michael@0 | 393 | } |
michael@0 | 394 | |
michael@0 | 395 | #ifdef MOZ_TOOLKIT_SEARCH |
michael@0 | 396 | // Try falling back to the search service's default search engine |
michael@0 | 397 | nsCOMPtr<nsIBrowserSearchService> searchSvc = do_GetService("@mozilla.org/browser/search-service;1"); |
michael@0 | 398 | if (searchSvc) { |
michael@0 | 399 | nsCOMPtr<nsISearchEngine> defaultEngine; |
michael@0 | 400 | searchSvc->GetDefaultEngine(getter_AddRefs(defaultEngine)); |
michael@0 | 401 | if (defaultEngine) { |
michael@0 | 402 | nsCOMPtr<nsISearchSubmission> submission; |
michael@0 | 403 | // We allow default search plugins to specify alternate |
michael@0 | 404 | // parameters that are specific to keyword searches. |
michael@0 | 405 | NS_NAMED_LITERAL_STRING(mozKeywordSearch, "application/x-moz-keywordsearch"); |
michael@0 | 406 | bool supportsResponseType = false; |
michael@0 | 407 | defaultEngine->SupportsResponseType(mozKeywordSearch, &supportsResponseType); |
michael@0 | 408 | if (supportsResponseType) |
michael@0 | 409 | defaultEngine->GetSubmission(NS_ConvertUTF8toUTF16(keyword), |
michael@0 | 410 | mozKeywordSearch, |
michael@0 | 411 | NS_LITERAL_STRING("keyword"), |
michael@0 | 412 | getter_AddRefs(submission)); |
michael@0 | 413 | else |
michael@0 | 414 | defaultEngine->GetSubmission(NS_ConvertUTF8toUTF16(keyword), |
michael@0 | 415 | EmptyString(), |
michael@0 | 416 | NS_LITERAL_STRING("keyword"), |
michael@0 | 417 | getter_AddRefs(submission)); |
michael@0 | 418 | if (submission) { |
michael@0 | 419 | nsCOMPtr<nsIInputStream> postData; |
michael@0 | 420 | submission->GetPostData(getter_AddRefs(postData)); |
michael@0 | 421 | if (aPostData) { |
michael@0 | 422 | postData.forget(aPostData); |
michael@0 | 423 | } else if (postData) { |
michael@0 | 424 | // The submission specifies POST data (i.e. the search |
michael@0 | 425 | // engine's "method" is POST), but our caller didn't allow |
michael@0 | 426 | // passing post data back. No point passing back a URL that |
michael@0 | 427 | // won't load properly. |
michael@0 | 428 | return NS_ERROR_FAILURE; |
michael@0 | 429 | } |
michael@0 | 430 | |
michael@0 | 431 | // This notification is meant for Firefox Health Report so it |
michael@0 | 432 | // can increment counts from the search engine. The assumption |
michael@0 | 433 | // here is that this keyword/submission will eventually result |
michael@0 | 434 | // in a search. Since we only generate a URI here, there is the |
michael@0 | 435 | // possibility we'll increment the counter without actually |
michael@0 | 436 | // incurring a search. A robust solution would involve currying |
michael@0 | 437 | // the search engine's name through various function calls. |
michael@0 | 438 | nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService(); |
michael@0 | 439 | if (obsSvc) { |
michael@0 | 440 | // Note that "keyword-search" refers to a search via the url |
michael@0 | 441 | // bar, not a bookmarks keyword search. |
michael@0 | 442 | obsSvc->NotifyObservers(defaultEngine, "keyword-search", NS_ConvertUTF8toUTF16(keyword).get()); |
michael@0 | 443 | } |
michael@0 | 444 | |
michael@0 | 445 | return submission->GetUri(aURI); |
michael@0 | 446 | } |
michael@0 | 447 | } |
michael@0 | 448 | } |
michael@0 | 449 | #endif |
michael@0 | 450 | |
michael@0 | 451 | // out of options |
michael@0 | 452 | return NS_ERROR_NOT_AVAILABLE; |
michael@0 | 453 | } |
michael@0 | 454 | |
michael@0 | 455 | bool nsDefaultURIFixup::MakeAlternateURI(nsIURI *aURI) |
michael@0 | 456 | { |
michael@0 | 457 | if (!Preferences::GetRootBranch()) |
michael@0 | 458 | { |
michael@0 | 459 | return false; |
michael@0 | 460 | } |
michael@0 | 461 | if (!Preferences::GetBool("browser.fixup.alternate.enabled", true)) |
michael@0 | 462 | { |
michael@0 | 463 | return false; |
michael@0 | 464 | } |
michael@0 | 465 | |
michael@0 | 466 | // Code only works for http. Not for any other protocol including https! |
michael@0 | 467 | bool isHttp = false; |
michael@0 | 468 | aURI->SchemeIs("http", &isHttp); |
michael@0 | 469 | if (!isHttp) { |
michael@0 | 470 | return false; |
michael@0 | 471 | } |
michael@0 | 472 | |
michael@0 | 473 | // Security - URLs with user / password info should NOT be fixed up |
michael@0 | 474 | nsAutoCString userpass; |
michael@0 | 475 | aURI->GetUserPass(userpass); |
michael@0 | 476 | if (!userpass.IsEmpty()) { |
michael@0 | 477 | return false; |
michael@0 | 478 | } |
michael@0 | 479 | |
michael@0 | 480 | nsAutoCString oldHost; |
michael@0 | 481 | nsAutoCString newHost; |
michael@0 | 482 | aURI->GetHost(oldHost); |
michael@0 | 483 | |
michael@0 | 484 | // Count the dots |
michael@0 | 485 | int32_t numDots = 0; |
michael@0 | 486 | nsReadingIterator<char> iter; |
michael@0 | 487 | nsReadingIterator<char> iterEnd; |
michael@0 | 488 | oldHost.BeginReading(iter); |
michael@0 | 489 | oldHost.EndReading(iterEnd); |
michael@0 | 490 | while (iter != iterEnd) { |
michael@0 | 491 | if (*iter == '.') |
michael@0 | 492 | numDots++; |
michael@0 | 493 | ++iter; |
michael@0 | 494 | } |
michael@0 | 495 | |
michael@0 | 496 | |
michael@0 | 497 | // Get the prefix and suffix to stick onto the new hostname. By default these |
michael@0 | 498 | // are www. & .com but they could be any other value, e.g. www. & .org |
michael@0 | 499 | |
michael@0 | 500 | nsAutoCString prefix("www."); |
michael@0 | 501 | nsAdoptingCString prefPrefix = |
michael@0 | 502 | Preferences::GetCString("browser.fixup.alternate.prefix"); |
michael@0 | 503 | if (prefPrefix) |
michael@0 | 504 | { |
michael@0 | 505 | prefix.Assign(prefPrefix); |
michael@0 | 506 | } |
michael@0 | 507 | |
michael@0 | 508 | nsAutoCString suffix(".com"); |
michael@0 | 509 | nsAdoptingCString prefSuffix = |
michael@0 | 510 | Preferences::GetCString("browser.fixup.alternate.suffix"); |
michael@0 | 511 | if (prefSuffix) |
michael@0 | 512 | { |
michael@0 | 513 | suffix.Assign(prefSuffix); |
michael@0 | 514 | } |
michael@0 | 515 | |
michael@0 | 516 | if (numDots == 0) |
michael@0 | 517 | { |
michael@0 | 518 | newHost.Assign(prefix); |
michael@0 | 519 | newHost.Append(oldHost); |
michael@0 | 520 | newHost.Append(suffix); |
michael@0 | 521 | } |
michael@0 | 522 | else if (numDots == 1) |
michael@0 | 523 | { |
michael@0 | 524 | if (!prefix.IsEmpty() && |
michael@0 | 525 | oldHost.EqualsIgnoreCase(prefix.get(), prefix.Length())) { |
michael@0 | 526 | newHost.Assign(oldHost); |
michael@0 | 527 | newHost.Append(suffix); |
michael@0 | 528 | } |
michael@0 | 529 | else if (!suffix.IsEmpty()) { |
michael@0 | 530 | newHost.Assign(prefix); |
michael@0 | 531 | newHost.Append(oldHost); |
michael@0 | 532 | } |
michael@0 | 533 | else |
michael@0 | 534 | { |
michael@0 | 535 | // Do nothing |
michael@0 | 536 | return false; |
michael@0 | 537 | } |
michael@0 | 538 | } |
michael@0 | 539 | else |
michael@0 | 540 | { |
michael@0 | 541 | // Do nothing |
michael@0 | 542 | return false; |
michael@0 | 543 | } |
michael@0 | 544 | |
michael@0 | 545 | if (newHost.IsEmpty()) { |
michael@0 | 546 | return false; |
michael@0 | 547 | } |
michael@0 | 548 | |
michael@0 | 549 | // Assign the new host string over the old one |
michael@0 | 550 | aURI->SetHost(newHost); |
michael@0 | 551 | return true; |
michael@0 | 552 | } |
michael@0 | 553 | |
michael@0 | 554 | /** |
michael@0 | 555 | * Check if the host name starts with ftp\d*\. and it's not directly followed |
michael@0 | 556 | * by the tld. |
michael@0 | 557 | */ |
michael@0 | 558 | bool nsDefaultURIFixup::IsLikelyFTP(const nsCString &aHostSpec) |
michael@0 | 559 | { |
michael@0 | 560 | bool likelyFTP = false; |
michael@0 | 561 | if (aHostSpec.EqualsIgnoreCase("ftp", 3)) { |
michael@0 | 562 | nsACString::const_iterator iter; |
michael@0 | 563 | nsACString::const_iterator end; |
michael@0 | 564 | aHostSpec.BeginReading(iter); |
michael@0 | 565 | aHostSpec.EndReading(end); |
michael@0 | 566 | iter.advance(3); // move past the "ftp" part |
michael@0 | 567 | |
michael@0 | 568 | while (iter != end) |
michael@0 | 569 | { |
michael@0 | 570 | if (*iter == '.') { |
michael@0 | 571 | // now make sure the name has at least one more dot in it |
michael@0 | 572 | ++iter; |
michael@0 | 573 | while (iter != end) |
michael@0 | 574 | { |
michael@0 | 575 | if (*iter == '.') { |
michael@0 | 576 | likelyFTP = true; |
michael@0 | 577 | break; |
michael@0 | 578 | } |
michael@0 | 579 | ++iter; |
michael@0 | 580 | } |
michael@0 | 581 | break; |
michael@0 | 582 | } |
michael@0 | 583 | else if (!nsCRT::IsAsciiDigit(*iter)) { |
michael@0 | 584 | break; |
michael@0 | 585 | } |
michael@0 | 586 | ++iter; |
michael@0 | 587 | } |
michael@0 | 588 | } |
michael@0 | 589 | return likelyFTP; |
michael@0 | 590 | } |
michael@0 | 591 | |
michael@0 | 592 | nsresult nsDefaultURIFixup::FileURIFixup(const nsACString& aStringURI, |
michael@0 | 593 | nsIURI** aURI) |
michael@0 | 594 | { |
michael@0 | 595 | nsAutoCString uriSpecOut; |
michael@0 | 596 | |
michael@0 | 597 | nsresult rv = ConvertFileToStringURI(aStringURI, uriSpecOut); |
michael@0 | 598 | if (NS_SUCCEEDED(rv)) |
michael@0 | 599 | { |
michael@0 | 600 | // if this is file url, uriSpecOut is already in FS charset |
michael@0 | 601 | if(NS_SUCCEEDED(NS_NewURI(aURI, uriSpecOut.get(), nullptr))) |
michael@0 | 602 | return NS_OK; |
michael@0 | 603 | } |
michael@0 | 604 | return NS_ERROR_FAILURE; |
michael@0 | 605 | } |
michael@0 | 606 | |
michael@0 | 607 | nsresult nsDefaultURIFixup::ConvertFileToStringURI(const nsACString& aIn, |
michael@0 | 608 | nsCString& aOut) |
michael@0 | 609 | { |
michael@0 | 610 | bool attemptFixup = false; |
michael@0 | 611 | |
michael@0 | 612 | #if defined(XP_WIN) |
michael@0 | 613 | // Check for \ in the url-string or just a drive (PC) |
michael@0 | 614 | if(kNotFound != aIn.FindChar('\\') || |
michael@0 | 615 | (aIn.Length() == 2 && (aIn.Last() == ':' || aIn.Last() == '|'))) |
michael@0 | 616 | { |
michael@0 | 617 | attemptFixup = true; |
michael@0 | 618 | } |
michael@0 | 619 | #elif defined(XP_UNIX) |
michael@0 | 620 | // Check if it starts with / (UNIX) |
michael@0 | 621 | if(aIn.First() == '/') |
michael@0 | 622 | { |
michael@0 | 623 | attemptFixup = true; |
michael@0 | 624 | } |
michael@0 | 625 | #else |
michael@0 | 626 | // Do nothing (All others for now) |
michael@0 | 627 | #endif |
michael@0 | 628 | |
michael@0 | 629 | if (attemptFixup) |
michael@0 | 630 | { |
michael@0 | 631 | // Test if this is a valid path by trying to create a local file |
michael@0 | 632 | // object. The URL of that is returned if successful. |
michael@0 | 633 | |
michael@0 | 634 | // NOTE: Please be sure to check that the call to NS_NewLocalFile |
michael@0 | 635 | // rejects bad file paths when using this code on a new |
michael@0 | 636 | // platform. |
michael@0 | 637 | |
michael@0 | 638 | nsCOMPtr<nsIFile> filePath; |
michael@0 | 639 | nsresult rv; |
michael@0 | 640 | |
michael@0 | 641 | // this is not the real fix but a temporary fix |
michael@0 | 642 | // in order to really fix the problem, we need to change the |
michael@0 | 643 | // nsICmdLineService interface to use wstring to pass paramenters |
michael@0 | 644 | // instead of string since path name and other argument could be |
michael@0 | 645 | // in non ascii.(see bug 87127) Since it is too risky to make interface change right |
michael@0 | 646 | // now, we decide not to do so now. |
michael@0 | 647 | // Therefore, the aIn we receive here maybe already in damage form |
michael@0 | 648 | // (e.g. treat every bytes as ISO-8859-1 and cast up to char16_t |
michael@0 | 649 | // while the real data could be in file system charset ) |
michael@0 | 650 | // we choice the following logic which will work for most of the case. |
michael@0 | 651 | // Case will still failed only if it meet ALL the following condiction: |
michael@0 | 652 | // 1. running on CJK, Russian, or Greek system, and |
michael@0 | 653 | // 2. user type it from URL bar |
michael@0 | 654 | // 3. the file name contains character in the range of |
michael@0 | 655 | // U+00A1-U+00FF but encode as different code point in file |
michael@0 | 656 | // system charset (e.g. ACP on window)- this is very rare case |
michael@0 | 657 | // We should remove this logic and convert to File system charset here |
michael@0 | 658 | // once we change nsICmdLineService to use wstring and ensure |
michael@0 | 659 | // all the Unicode data come in is correctly converted. |
michael@0 | 660 | // XXXbz nsICmdLineService doesn't hand back unicode, so in some cases |
michael@0 | 661 | // what we have is actually a "utf8" version of a "utf16" string that's |
michael@0 | 662 | // actually byte-expanded native-encoding data. Someone upstream needs |
michael@0 | 663 | // to stop using AssignWithConversion and do things correctly. See bug |
michael@0 | 664 | // 58866 for what happens if we remove this |
michael@0 | 665 | // PossiblyByteExpandedFileName check. |
michael@0 | 666 | NS_ConvertUTF8toUTF16 in(aIn); |
michael@0 | 667 | if (PossiblyByteExpandedFileName(in)) { |
michael@0 | 668 | // removes high byte |
michael@0 | 669 | rv = NS_NewNativeLocalFile(NS_LossyConvertUTF16toASCII(in), false, getter_AddRefs(filePath)); |
michael@0 | 670 | } |
michael@0 | 671 | else { |
michael@0 | 672 | // input is unicode |
michael@0 | 673 | rv = NS_NewLocalFile(in, false, getter_AddRefs(filePath)); |
michael@0 | 674 | } |
michael@0 | 675 | |
michael@0 | 676 | if (NS_SUCCEEDED(rv)) |
michael@0 | 677 | { |
michael@0 | 678 | NS_GetURLSpecFromFile(filePath, aOut); |
michael@0 | 679 | return NS_OK; |
michael@0 | 680 | } |
michael@0 | 681 | } |
michael@0 | 682 | |
michael@0 | 683 | return NS_ERROR_FAILURE; |
michael@0 | 684 | } |
michael@0 | 685 | |
michael@0 | 686 | bool nsDefaultURIFixup::PossiblyHostPortUrl(const nsACString &aUrl) |
michael@0 | 687 | { |
michael@0 | 688 | // Oh dear, the protocol is invalid. Test if the protocol might |
michael@0 | 689 | // actually be a url without a protocol: |
michael@0 | 690 | // |
michael@0 | 691 | // http://www.faqs.org/rfcs/rfc1738.html |
michael@0 | 692 | // http://www.faqs.org/rfcs/rfc2396.html |
michael@0 | 693 | // |
michael@0 | 694 | // e.g. Anything of the form: |
michael@0 | 695 | // |
michael@0 | 696 | // <hostname>:<port> or |
michael@0 | 697 | // <hostname>:<port>/ |
michael@0 | 698 | // |
michael@0 | 699 | // Where <hostname> is a string of alphanumeric characters and dashes |
michael@0 | 700 | // separated by dots. |
michael@0 | 701 | // and <port> is a 5 or less digits. This actually breaks the rfc2396 |
michael@0 | 702 | // definition of a scheme which allows dots in schemes. |
michael@0 | 703 | // |
michael@0 | 704 | // Note: |
michael@0 | 705 | // People expecting this to work with |
michael@0 | 706 | // <user>:<password>@<host>:<port>/<url-path> will be disappointed! |
michael@0 | 707 | // |
michael@0 | 708 | // Note: Parser could be a lot tighter, tossing out silly hostnames |
michael@0 | 709 | // such as those containing consecutive dots and so on. |
michael@0 | 710 | |
michael@0 | 711 | // Read the hostname which should of the form |
michael@0 | 712 | // [a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*: |
michael@0 | 713 | |
michael@0 | 714 | nsACString::const_iterator iterBegin; |
michael@0 | 715 | nsACString::const_iterator iterEnd; |
michael@0 | 716 | aUrl.BeginReading(iterBegin); |
michael@0 | 717 | aUrl.EndReading(iterEnd); |
michael@0 | 718 | nsACString::const_iterator iter = iterBegin; |
michael@0 | 719 | |
michael@0 | 720 | while (iter != iterEnd) |
michael@0 | 721 | { |
michael@0 | 722 | uint32_t chunkSize = 0; |
michael@0 | 723 | // Parse a chunk of the address |
michael@0 | 724 | while (iter != iterEnd && |
michael@0 | 725 | (*iter == '-' || |
michael@0 | 726 | nsCRT::IsAsciiAlpha(*iter) || |
michael@0 | 727 | nsCRT::IsAsciiDigit(*iter))) |
michael@0 | 728 | { |
michael@0 | 729 | ++chunkSize; |
michael@0 | 730 | ++iter; |
michael@0 | 731 | } |
michael@0 | 732 | if (chunkSize == 0 || iter == iterEnd) |
michael@0 | 733 | { |
michael@0 | 734 | return false; |
michael@0 | 735 | } |
michael@0 | 736 | if (*iter == ':') |
michael@0 | 737 | { |
michael@0 | 738 | // Go onto checking the for the digits |
michael@0 | 739 | break; |
michael@0 | 740 | } |
michael@0 | 741 | if (*iter != '.') |
michael@0 | 742 | { |
michael@0 | 743 | // Whatever it is, it ain't a hostname! |
michael@0 | 744 | return false; |
michael@0 | 745 | } |
michael@0 | 746 | ++iter; |
michael@0 | 747 | } |
michael@0 | 748 | if (iter == iterEnd) |
michael@0 | 749 | { |
michael@0 | 750 | // No point continuing since there is no colon |
michael@0 | 751 | return false; |
michael@0 | 752 | } |
michael@0 | 753 | ++iter; |
michael@0 | 754 | |
michael@0 | 755 | // Count the number of digits after the colon and before the |
michael@0 | 756 | // next forward slash (or end of string) |
michael@0 | 757 | |
michael@0 | 758 | uint32_t digitCount = 0; |
michael@0 | 759 | while (iter != iterEnd && digitCount <= 5) |
michael@0 | 760 | { |
michael@0 | 761 | if (nsCRT::IsAsciiDigit(*iter)) |
michael@0 | 762 | { |
michael@0 | 763 | digitCount++; |
michael@0 | 764 | } |
michael@0 | 765 | else if (*iter == '/') |
michael@0 | 766 | { |
michael@0 | 767 | break; |
michael@0 | 768 | } |
michael@0 | 769 | else |
michael@0 | 770 | { |
michael@0 | 771 | // Whatever it is, it ain't a port! |
michael@0 | 772 | return false; |
michael@0 | 773 | } |
michael@0 | 774 | ++iter; |
michael@0 | 775 | } |
michael@0 | 776 | if (digitCount == 0 || digitCount > 5) |
michael@0 | 777 | { |
michael@0 | 778 | // No digits or more digits than a port would have. |
michael@0 | 779 | return false; |
michael@0 | 780 | } |
michael@0 | 781 | |
michael@0 | 782 | // Yes, it's possibly a host:port url |
michael@0 | 783 | return true; |
michael@0 | 784 | } |
michael@0 | 785 | |
michael@0 | 786 | bool nsDefaultURIFixup::PossiblyByteExpandedFileName(const nsAString& aIn) |
michael@0 | 787 | { |
michael@0 | 788 | // XXXXX HACK XXXXX : please don't copy this code. |
michael@0 | 789 | // There are cases where aIn contains the locale byte chars padded to short |
michael@0 | 790 | // (thus the name "ByteExpanded"); whereas other cases |
michael@0 | 791 | // have proper Unicode code points. |
michael@0 | 792 | // This is a temporary fix. Please refer to 58866, 86948 |
michael@0 | 793 | |
michael@0 | 794 | nsReadingIterator<char16_t> iter; |
michael@0 | 795 | nsReadingIterator<char16_t> iterEnd; |
michael@0 | 796 | aIn.BeginReading(iter); |
michael@0 | 797 | aIn.EndReading(iterEnd); |
michael@0 | 798 | while (iter != iterEnd) |
michael@0 | 799 | { |
michael@0 | 800 | if (*iter >= 0x0080 && *iter <= 0x00FF) |
michael@0 | 801 | return true; |
michael@0 | 802 | ++iter; |
michael@0 | 803 | } |
michael@0 | 804 | return false; |
michael@0 | 805 | } |
michael@0 | 806 | |
michael@0 | 807 | void nsDefaultURIFixup::KeywordURIFixup(const nsACString & aURIString, |
michael@0 | 808 | nsIInputStream **aPostData, |
michael@0 | 809 | nsIURI** aURI) |
michael@0 | 810 | { |
michael@0 | 811 | // These are keyword formatted strings |
michael@0 | 812 | // "what is mozilla" |
michael@0 | 813 | // "what is mozilla?" |
michael@0 | 814 | // "docshell site:mozilla.org" - has no dot/colon in the first space-separated substring |
michael@0 | 815 | // "?mozilla" - anything that begins with a question mark |
michael@0 | 816 | // "?site:mozilla.org docshell" |
michael@0 | 817 | // Things that have a quote before the first dot/colon |
michael@0 | 818 | |
michael@0 | 819 | // These are not keyword formatted strings |
michael@0 | 820 | // "www.blah.com" - first space-separated substring contains a dot, doesn't start with "?" |
michael@0 | 821 | // "www.blah.com stuff" |
michael@0 | 822 | // "nonQualifiedHost:80" - first space-separated substring contains a colon, doesn't start with "?" |
michael@0 | 823 | // "nonQualifiedHost:80 args" |
michael@0 | 824 | // "nonQualifiedHost?" |
michael@0 | 825 | // "nonQualifiedHost?args" |
michael@0 | 826 | // "nonQualifiedHost?some args" |
michael@0 | 827 | |
michael@0 | 828 | // Note: uint32_t(kNotFound) is greater than any actual location |
michael@0 | 829 | // in practice. So if we cast all locations to uint32_t, then a < |
michael@0 | 830 | // b guarantees that either b is kNotFound and a is found, or both |
michael@0 | 831 | // are found and a found before b. |
michael@0 | 832 | uint32_t dotLoc = uint32_t(aURIString.FindChar('.')); |
michael@0 | 833 | uint32_t colonLoc = uint32_t(aURIString.FindChar(':')); |
michael@0 | 834 | uint32_t spaceLoc = uint32_t(aURIString.FindChar(' ')); |
michael@0 | 835 | if (spaceLoc == 0) { |
michael@0 | 836 | // Treat this as not found |
michael@0 | 837 | spaceLoc = uint32_t(kNotFound); |
michael@0 | 838 | } |
michael@0 | 839 | uint32_t qMarkLoc = uint32_t(aURIString.FindChar('?')); |
michael@0 | 840 | uint32_t quoteLoc = std::min(uint32_t(aURIString.FindChar('"')), |
michael@0 | 841 | uint32_t(aURIString.FindChar('\''))); |
michael@0 | 842 | |
michael@0 | 843 | if (((spaceLoc < dotLoc || quoteLoc < dotLoc) && |
michael@0 | 844 | (spaceLoc < colonLoc || quoteLoc < colonLoc) && |
michael@0 | 845 | (spaceLoc < qMarkLoc || quoteLoc < qMarkLoc)) || |
michael@0 | 846 | qMarkLoc == 0) |
michael@0 | 847 | { |
michael@0 | 848 | KeywordToURI(aURIString, aPostData, aURI); |
michael@0 | 849 | } |
michael@0 | 850 | } |
michael@0 | 851 | |
michael@0 | 852 | |
michael@0 | 853 | nsresult NS_NewURIFixup(nsIURIFixup **aURIFixup) |
michael@0 | 854 | { |
michael@0 | 855 | nsDefaultURIFixup *fixup = new nsDefaultURIFixup; |
michael@0 | 856 | if (fixup == nullptr) |
michael@0 | 857 | { |
michael@0 | 858 | return NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 859 | } |
michael@0 | 860 | return fixup->QueryInterface(NS_GET_IID(nsIURIFixup), (void **) aURIFixup); |
michael@0 | 861 | } |
michael@0 | 862 |