LCOV - code coverage report
Current view: directory - docshell/base - nsDefaultURIFixup.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 324 76 23.5 %
Date: 2012-06-02 Functions: 19 10 52.6 %

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

Generated by: LCOV version 1.7