Make URI fixup work with UTF8 strings, mostly... Bug 211181, r=adamlock, sr=darin

This commit is contained in:
bzbarsky%mit.edu 2003-07-02 00:39:51 +00:00
parent ff56070f4a
commit f06faf1267
6 changed files with 68 additions and 57 deletions

View File

@ -97,9 +97,9 @@ nsDefaultURIFixup::CreateExposableURI(nsIURI *aURI, nsIURI **aReturn)
return NS_OK; return NS_OK;
} }
/* nsIURI createFixupURI (in wstring aURIText, in unsigned long aFixupFlags); */ /* nsIURI createFixupURI (in nsAUTF8String aURIText, in unsigned long aFixupFlags); */
NS_IMETHODIMP NS_IMETHODIMP
nsDefaultURIFixup::CreateFixupURI(const nsAString& aStringURI, PRUint32 aFixupFlags, nsIURI **aURI) nsDefaultURIFixup::CreateFixupURI(const nsACString& aStringURI, PRUint32 aFixupFlags, nsIURI **aURI)
{ {
NS_ENSURE_ARG(!aStringURI.IsEmpty()); NS_ENSURE_ARG(!aStringURI.IsEmpty());
NS_ENSURE_ARG_POINTER(aURI); NS_ENSURE_ARG_POINTER(aURI);
@ -107,7 +107,7 @@ nsDefaultURIFixup::CreateFixupURI(const nsAString& aStringURI, PRUint32 aFixupFl
nsresult rv; nsresult rv;
*aURI = nsnull; *aURI = nsnull;
nsAutoString uriString(aStringURI); nsCAutoString uriString(aStringURI);
uriString.Trim(" "); // Cleanup the empty spaces that might be on each end. uriString.Trim(" "); // Cleanup the empty spaces that might be on each end.
// Eliminate embedded newlines, which single-line text fields now allow: // Eliminate embedded newlines, which single-line text fields now allow:
@ -115,22 +115,30 @@ nsDefaultURIFixup::CreateFixupURI(const nsAString& aStringURI, PRUint32 aFixupFl
NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE); NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE);
nsCOMPtr<nsIIOService> ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString scheme;
ioService->ExtractScheme(aStringURI, scheme);
// View-source is a pseudo scheme. We're interested in fixing up the stuff // 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 // 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. // "view-source:" lopped off and then prepend it again afterwards.
if (uriString.EqualsIgnoreCase("view-source:", 12)) if (scheme.EqualsIgnoreCase("view-source"))
{ {
nsCOMPtr<nsIURI> uri; nsCOMPtr<nsIURI> uri;
PRUint32 newFixupFlags = aFixupFlags & ~FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP; PRUint32 newFixupFlags = aFixupFlags & ~FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
rv = CreateFixupURI(Substring(uriString, 12, uriString.Length() - 12), rv = CreateFixupURI(Substring(uriString,
sizeof("view-source:") - 1,
uriString.Length() -
(sizeof("view-source:") - 1)),
newFixupFlags, getter_AddRefs(uri)); newFixupFlags, getter_AddRefs(uri));
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
nsCAutoString spec; nsCAutoString spec;
uri->GetSpec(spec); uri->GetSpec(spec);
uriString.Assign(NS_LITERAL_STRING("view-source:") + NS_ConvertUTF8toUCS2(spec)); uriString.Assign(NS_LITERAL_CSTRING("view-source:") + spec);
} }
else { else {
// Check for if it is a file URL // Check for if it is a file URL
@ -152,18 +160,18 @@ nsDefaultURIFixup::CreateFixupURI(const nsAString& aStringURI, PRUint32 aFixupFl
// http:\\broken.com\blah?arg=somearg\foo.jpg (stops at question mark) // http:\\broken.com\blah?arg=somearg\foo.jpg (stops at question mark)
// http:\\broken.com#odd\ref (stops at hash) // http:\\broken.com#odd\ref (stops at hash)
// //
if (uriString.FindChar(':') == -1 || if (scheme.IsEmpty() ||
uriString.EqualsIgnoreCase("http:", 5) || scheme.EqualsIgnoreCase("http") ||
uriString.EqualsIgnoreCase("https:", 6) || scheme.EqualsIgnoreCase("https") ||
uriString.EqualsIgnoreCase("ftp:", 4)) scheme.EqualsIgnoreCase("ftp"))
{ {
// Walk the string replacing backslashes with forward slashes until // Walk the string replacing backslashes with forward slashes until
// the end is reached, or a question mark, or a hash, or a forward // the end is reached, or a question mark, or a hash, or a forward
// slash. The forward slash test is to stop before trampling over // slash. The forward slash test is to stop before trampling over
// URIs which legitimately contain a mix of both forward and // URIs which legitimately contain a mix of both forward and
// backward slashes. // backward slashes.
nsAFlatString::iterator start; nsCAutoString::iterator start;
nsAFlatString::iterator end; nsCAutoString::iterator end;
uriString.BeginWriting(start); uriString.BeginWriting(start);
uriString.EndWriting(end); uriString.EndWriting(end);
while (start != end) { while (start != end) {
@ -182,29 +190,25 @@ nsDefaultURIFixup::CreateFixupURI(const nsAString& aStringURI, PRUint32 aFixupFl
PRBool bAsciiURI = IsASCII(uriString); PRBool bAsciiURI = IsASCII(uriString);
PRBool bUseNonDefaultCharsetForURI = PRBool bUseNonDefaultCharsetForURI =
!bAsciiURI && !bAsciiURI &&
(uriString.FindChar(':') == kNotFound || (scheme.IsEmpty() ||
uriString.EqualsIgnoreCase("http:", 5) || scheme.EqualsIgnoreCase("http") ||
uriString.EqualsIgnoreCase("https:", 6) || scheme.EqualsIgnoreCase("https") ||
uriString.EqualsIgnoreCase("ftp:", 4) || scheme.EqualsIgnoreCase("ftp") ||
uriString.EqualsIgnoreCase("file:", 5)); scheme.EqualsIgnoreCase("file"));
// Check the scheme... // Now we need to check whether "scheme" is something we don't
NS_LossyConvertUCS2toASCII asciiURI(uriString); // really know about.
nsCOMPtr<nsIIOService> ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString scheme;
ioService->ExtractScheme(asciiURI, scheme);
nsCOMPtr<nsIProtocolHandler> ourHandler, extHandler; nsCOMPtr<nsIProtocolHandler> ourHandler, extHandler;
ioService->GetProtocolHandler(scheme.get(), getter_AddRefs(ourHandler)); ioService->GetProtocolHandler(scheme.get(), getter_AddRefs(ourHandler));
extHandler = do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"default"); extHandler = do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"default");
if (ourHandler != extHandler || !PossiblyHostPortUrl(uriString)) { if (ourHandler != extHandler || !PossiblyHostPortUrl(uriString)) {
// Just try to create an URL out of it // Just try to create an URL out of it
rv = NS_NewURI(aURI, uriString, rv = NS_NewURI(aURI, uriString,
bUseNonDefaultCharsetForURI ? GetCharsetForUrlBar() : nsnull); bUseNonDefaultCharsetForURI ? GetCharsetForUrlBar() : nsnull);
} }
if (*aURI) { if (*aURI) {
if (aFixupFlags & FIXUP_FLAGS_MAKE_ALTERNATE_URI) if (aFixupFlags & FIXUP_FLAGS_MAKE_ALTERNATE_URI)
MakeAlternateURI(*aURI); MakeAlternateURI(*aURI);
@ -234,13 +238,13 @@ nsDefaultURIFixup::CreateFixupURI(const nsAString& aStringURI, PRUint32 aFixupFl
// //
if (uriString.EqualsIgnoreCase("://", 3)) if (uriString.EqualsIgnoreCase("://", 3))
{ {
nsAutoString newUriString; nsCAutoString newUriString;
uriString.Mid(newUriString, 3, uriString.Length() - 3); uriString.Mid(newUriString, 3, uriString.Length() - 3);
uriString = newUriString; uriString = newUriString;
} }
else if (uriString.EqualsIgnoreCase("//", 2)) else if (uriString.EqualsIgnoreCase("//", 2))
{ {
nsAutoString newUriString; nsCAutoString newUriString;
uriString.Mid(newUriString, 2, uriString.Length() - 2); uriString.Mid(newUriString, 2, uriString.Length() - 2);
uriString = newUriString; uriString = newUriString;
} }
@ -264,14 +268,14 @@ nsDefaultURIFixup::CreateFixupURI(const nsAString& aStringURI, PRUint32 aFixupFl
hostPos = uriString.Length(); hostPos = uriString.Length();
// extract host name // extract host name
nsAutoString hostSpec; nsCAutoString hostSpec;
uriString.Left(hostSpec, hostPos); uriString.Left(hostSpec, hostPos);
// insert url spec corresponding to host name // insert url spec corresponding to host name
if (hostSpec.EqualsIgnoreCase("ftp", 3)) if (hostSpec.EqualsIgnoreCase("ftp", 3))
uriString.Assign(NS_LITERAL_STRING("ftp://") + uriString); uriString.Assign(NS_LITERAL_CSTRING("ftp://") + uriString);
else else
uriString.Assign(NS_LITERAL_STRING("http://") + uriString); uriString.Assign(NS_LITERAL_CSTRING("http://") + uriString);
// For ftp & http, we want to use system charset. // For ftp & http, we want to use system charset.
if (!bAsciiURI) if (!bAsciiURI)
@ -394,7 +398,7 @@ PRBool nsDefaultURIFixup::MakeAlternateURI(nsIURI *aURI)
return PR_TRUE; return PR_TRUE;
} }
nsresult nsDefaultURIFixup::FileURIFixup(const nsAString& aStringURI, nsresult nsDefaultURIFixup::FileURIFixup(const nsACString& aStringURI,
nsIURI** aURI) nsIURI** aURI)
{ {
nsCAutoString uriSpecOut; nsCAutoString uriSpecOut;
@ -409,20 +413,21 @@ nsresult nsDefaultURIFixup::FileURIFixup(const nsAString& aStringURI,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
nsresult nsDefaultURIFixup::ConvertFileToStringURI(const nsAString& aIn, nsresult nsDefaultURIFixup::ConvertFileToStringURI(const nsACString& aIn,
nsCString& aOut) nsCString& aOut)
{ {
PRBool attemptFixup = PR_FALSE; PRBool attemptFixup = PR_FALSE;
#if defined(XP_WIN) || defined(XP_OS2) #if defined(XP_WIN) || defined(XP_OS2)
// Check for \ in the url-string or just a drive (PC) // Check for \ in the url-string or just a drive (PC)
if(kNotFound != aIn.FindChar(PRUnichar('\\')) || ((aIn.Length() == 2 ) && (aIn.Last() == PRUnichar(':') || aIn.Last() == PRUnichar('|')))) if(kNotFound != aIn.FindChar('\\') ||
(aIn.Length() == 2 && (aIn.Last() == ':' || aIn.Last() == '|')))
{ {
attemptFixup = PR_TRUE; attemptFixup = PR_TRUE;
} }
#elif XP_UNIX #elif XP_UNIX
// Check if it starts with / (UNIX) // Check if it starts with / (UNIX)
if(aIn.First() == PRUnichar('/')) if(aIn.First() == '/')
{ {
attemptFixup = PR_TRUE; attemptFixup = PR_TRUE;
} }
@ -460,14 +465,21 @@ nsresult nsDefaultURIFixup::ConvertFileToStringURI(const nsAString& aIn,
// system charset (e.g. ACP on window)- this is very rare case // system charset (e.g. ACP on window)- this is very rare case
// We should remove this logic and convert to File system charset here // We should remove this logic and convert to File system charset here
// once we change nsICmdLineService to use wstring and ensure // once we change nsICmdLineService to use wstring and ensure
// all the Unicode data come in is correctly converted. // all the Unicode data come in is correctly converted.
if (PossiblyByteExpandedFileName(aIn)) { // 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_ConvertUTF8toUCS2 in(aIn);
if (PossiblyByteExpandedFileName(in)) {
// removes high byte // removes high byte
rv = NS_NewNativeLocalFile(NS_LossyConvertUCS2toASCII(aIn), PR_FALSE, getter_AddRefs(filePath)); rv = NS_NewNativeLocalFile(NS_LossyConvertUCS2toASCII(in), PR_FALSE, getter_AddRefs(filePath));
} }
else { else {
// input is unicode // input is unicode
rv = NS_NewLocalFile(aIn, PR_FALSE, getter_AddRefs(filePath)); rv = NS_NewLocalFile(in, PR_FALSE, getter_AddRefs(filePath));
} }
if (NS_SUCCEEDED(rv)) if (NS_SUCCEEDED(rv))
@ -480,7 +492,7 @@ nsresult nsDefaultURIFixup::ConvertFileToStringURI(const nsAString& aIn,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
PRBool nsDefaultURIFixup::PossiblyHostPortUrl(const nsAString &aUrl) PRBool nsDefaultURIFixup::PossiblyHostPortUrl(const nsACString &aUrl)
{ {
// Oh dear, the protocol is invalid. Test if the protocol might // Oh dear, the protocol is invalid. Test if the protocol might
// actually be a url without a protocol: // actually be a url without a protocol:
@ -508,18 +520,18 @@ PRBool nsDefaultURIFixup::PossiblyHostPortUrl(const nsAString &aUrl)
// Read the hostname which should of the form // Read the hostname which should of the form
// [a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*: // [a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*:
nsReadingIterator<PRUnichar> iterBegin; nsACString::const_iterator iterBegin;
nsReadingIterator<PRUnichar> iterEnd; nsACString::const_iterator iterEnd;
aUrl.BeginReading(iterBegin); aUrl.BeginReading(iterBegin);
aUrl.EndReading(iterEnd); aUrl.EndReading(iterEnd);
nsReadingIterator<PRUnichar> iter = iterBegin; nsACString::const_iterator iter = iterBegin;
while (iter != iterEnd) while (iter != iterEnd)
{ {
PRUint32 chunkSize = 0; PRUint32 chunkSize = 0;
// Parse a chunk of the address // Parse a chunk of the address
while (iter != iterEnd && while (iter != iterEnd &&
(*iter == PRUnichar('-') || (*iter == '-' ||
nsCRT::IsAsciiAlpha(*iter) || nsCRT::IsAsciiAlpha(*iter) ||
nsCRT::IsAsciiDigit(*iter))) nsCRT::IsAsciiDigit(*iter)))
{ {
@ -530,12 +542,12 @@ PRBool nsDefaultURIFixup::PossiblyHostPortUrl(const nsAString &aUrl)
{ {
return PR_FALSE; return PR_FALSE;
} }
if (*iter == PRUnichar(':')) if (*iter == ':')
{ {
// Go onto checking the for the digits // Go onto checking the for the digits
break; break;
} }
if (*iter != PRUnichar('.')) if (*iter != '.')
{ {
// Whatever it is, it ain't a hostname! // Whatever it is, it ain't a hostname!
return PR_FALSE; return PR_FALSE;
@ -559,7 +571,7 @@ PRBool nsDefaultURIFixup::PossiblyHostPortUrl(const nsAString &aUrl)
{ {
digitCount++; digitCount++;
} }
else if (*iter == PRUnichar('/')) else if (*iter == '/')
{ {
break; break;
} }
@ -636,7 +648,7 @@ const char * nsDefaultURIFixup::GetCharsetForUrlBar()
return charset; return charset;
} }
nsresult nsDefaultURIFixup::KeywordURIFixup(const nsAString & aURIString, nsresult nsDefaultURIFixup::KeywordURIFixup(const nsACString & aURIString,
nsIURI** aURI) nsIURI** aURI)
{ {
// These are keyword formatted strings // These are keyword formatted strings
@ -666,7 +678,7 @@ nsresult nsDefaultURIFixup::KeywordURIFixup(const nsAString & aURIString,
if(keyword) if(keyword)
{ {
nsCAutoString keywordSpec("keyword:"); nsCAutoString keywordSpec("keyword:");
char *utf8Spec = ToNewUTF8String(aURIString); char *utf8Spec = ToNewCString(aURIString); // aURIString is UTF-8
if(utf8Spec) if(utf8Spec)
{ {
char* escapedUTF8Spec = nsEscape(utf8Spec, url_Path); char* escapedUTF8Spec = nsEscape(utf8Spec, url_Path);

View File

@ -44,11 +44,11 @@ protected:
private: private:
/* additional members */ /* additional members */
nsresult FileURIFixup(const nsAString &aStringURI, nsIURI** aURI); nsresult FileURIFixup(const nsACString &aStringURI, nsIURI** aURI);
nsresult ConvertFileToStringURI(const nsAString& aIn, nsCString& aOut); nsresult ConvertFileToStringURI(const nsACString& aIn, nsCString& aOut);
nsresult KeywordURIFixup(const nsAString &aStringURI, nsIURI** aURI); nsresult KeywordURIFixup(const nsACString &aStringURI, nsIURI** aURI);
PRBool PossiblyByteExpandedFileName(const nsAString& aIn); PRBool PossiblyByteExpandedFileName(const nsAString& aIn);
PRBool PossiblyHostPortUrl(const nsAString& aUrl); PRBool PossiblyHostPortUrl(const nsACString& aUrl);
PRBool MakeAlternateURI(nsIURI *aURI); PRBool MakeAlternateURI(nsIURI *aURI);
const char * GetFileSystemCharset(); const char * GetFileSystemCharset();
const char * GetCharsetForUrlBar(); const char * GetCharsetForUrlBar();

View File

@ -2462,7 +2462,7 @@ nsDocShell::LoadURI(const PRUnichar * aURI,
} }
if (mURIFixup) { if (mURIFixup) {
// Call the fixup object // Call the fixup object
rv = mURIFixup->CreateFixupURI(nsDependentString(aURI), rv = mURIFixup->CreateFixupURI(NS_ConvertUCS2toUTF8(aURI),
nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP, nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP,
getter_AddRefs(uri)); getter_AddRefs(uri));
} }

View File

@ -66,6 +66,6 @@ interface nsIURIFixup : nsISupports
* @param aURIText Candidate URI. * @param aURIText Candidate URI.
* @param aFixupFlags Flags that govern ways the URI may be fixed up. * @param aFixupFlags Flags that govern ways the URI may be fixed up.
*/ */
nsIURI createFixupURI(in AString aURIText, in unsigned long aFixupFlags); nsIURI createFixupURI(in AUTF8String aURIText, in unsigned long aFixupFlags);
}; };

View File

@ -932,7 +932,7 @@ nsresult nsWebShell::EndPageLoad(nsIWebProgress *aProgress,
if (doCreateAlternate) if (doCreateAlternate)
{ {
newURI = nsnull; newURI = nsnull;
mURIFixup->CreateFixupURI(NS_ConvertUTF8toUCS2(oldSpec), mURIFixup->CreateFixupURI(oldSpec,
nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI, getter_AddRefs(newURI)); nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI, getter_AddRefs(newURI));
} }
} }

View File

@ -626,8 +626,7 @@ EmbedPrivate::SaveURI(char *aURI, char *fname)
{ {
nsIURI* uri; nsIURI* uri;
nsCString u(aURI); mFixup->CreateFixupURI(nsDependentCString(aURI), 0, &(uri));
mFixup->CreateFixupURI(ToNewUnicode(u), 0, &(uri));
return (mWindow->SaveURI(uri, fname)); return (mWindow->SaveURI(uri, fname));
} }
#endif #endif