diff --git a/netwerk/base/src/nsStandardURL.cpp b/netwerk/base/src/nsStandardURL.cpp index fb286cbef36..fc01ab7c0fe 100644 --- a/netwerk/base/src/nsStandardURL.cpp +++ b/netwerk/base/src/nsStandardURL.cpp @@ -170,8 +170,10 @@ PRInt32 nsStandardURL:: nsSegmentEncoder::EncodeSegmentCount(const char *str, const URLSegment &seg, PRInt16 mask, - nsAFlatCString &result) + nsAFlatCString &result, + PRBool &appended) { + appended = PR_FALSE; if (!str) return 0; PRInt32 len = 0; @@ -203,11 +205,14 @@ nsSegmentEncoder::EncodeSegmentCount(const char *str, PRUint32 initLen = result.Length(); // now perform any required escaping - if (NS_EscapeURL(str + pos, len, mask | escapeFlags, result)) + if (NS_EscapeURL(str + pos, len, mask | escapeFlags, result)) { len = result.Length() - initLen; + appended = PR_TRUE; + } else if (str == encBuf.get()) { result += encBuf; // append only!! len = encBuf.Length(); + appended = PR_TRUE; } } return len; @@ -219,13 +224,11 @@ nsSegmentEncoder::EncodeSegment(const nsASingleFragmentCString &str, nsAFlatCString &result) { const char *text; - PRUint32 resultLen = result.Length(); - EncodeSegmentCount(str.BeginReading(text), URLSegment(0, str.Length()), mask, result); - // since EncodeSegmentCount appends to result, we must check whether its length grew - if (result.Length() > resultLen) + PRBool encoded; + EncodeSegmentCount(str.BeginReading(text), URLSegment(0, str.Length()), mask, result, encoded); + if (encoded) return result; - else - return str; + return str; } PRBool nsStandardURL:: @@ -395,14 +398,14 @@ nsStandardURL::NormalizeIDN(const nsCSubstring &host, nsCString &result) PRBool isACE; if (gIDN && NS_SUCCEEDED(gIDN->IsACE(host, &isACE)) && isACE && - NS_SUCCEEDED(ACEtoUTF8(host, result))) { + NS_SUCCEEDED(ACEtoDisplayIDN(host, result))) { mHostEncoding = eEncoding_UTF8; return PR_TRUE; } } else { mHostEncoding = eEncoding_UTF8; - if (gIDN && NS_SUCCEEDED(NormalizeUTF8(host, result))) { + if (gIDN && NS_SUCCEEDED(UTF8toDisplayIDN(host, result))) { // normalization could result in an ASCII only hostname if (IsASCII(result)) mHostEncoding = eEncoding_ASCII; @@ -429,10 +432,10 @@ nsStandardURL::CoalescePath(netCoalesceFlags coalesceFlag, char *path) } PRUint32 -nsStandardURL::AppendSegmentToBuf(char *buf, PRUint32 i, const char *str, URLSegment &seg, const nsCString *escapedStr) +nsStandardURL::AppendSegmentToBuf(char *buf, PRUint32 i, const char *str, URLSegment &seg, const nsCString *escapedStr, PRBool useEscaped) { if (seg.mLen > 0) { - if (escapedStr && !escapedStr->IsEmpty()) { + if (useEscaped) { seg.mLen = escapedStr->Length(); memcpy(buf + i, escapedStr->get(), seg.mLen); } @@ -464,16 +467,10 @@ nsStandardURL::BuildNormalizedSpec(const char *spec) // buffers for holding escaped url segments (these will remain empty unless // escaping is required). - nsCAutoString encUsername; - nsCAutoString encPassword; - nsCAutoString encHost; - PRBool useEncHost; - nsCAutoString encDirectory; - nsCAutoString encBasename; - nsCAutoString encExtension; - nsCAutoString encParam; - nsCAutoString encQuery; - nsCAutoString encRef; + nsCAutoString encUsername, encPassword, encHost, encDirectory, + encBasename, encExtension, encParam, encQuery, encRef; + PRBool useEncUsername, useEncPassword, useEncHost, useEncDirectory, + useEncBasename, useEncExtension, useEncParam, useEncQuery, useEncRef; // // escape each URL segment, if necessary, and calculate approximate normalized @@ -490,14 +487,14 @@ nsStandardURL::BuildNormalizedSpec(const char *spec) // appropriate encoding. { GET_SEGMENT_ENCODER(encoder); - approxLen += encoder.EncodeSegmentCount(spec, mUsername, esc_Username, encUsername); - approxLen += encoder.EncodeSegmentCount(spec, mPassword, esc_Password, encPassword); - approxLen += encoder.EncodeSegmentCount(spec, mDirectory, esc_Directory, encDirectory); - approxLen += encoder.EncodeSegmentCount(spec, mBasename, esc_FileBaseName, encBasename); - approxLen += encoder.EncodeSegmentCount(spec, mExtension, esc_FileExtension, encExtension); - approxLen += encoder.EncodeSegmentCount(spec, mParam, esc_Param, encParam); - approxLen += encoder.EncodeSegmentCount(spec, mQuery, esc_Query, encQuery); - approxLen += encoder.EncodeSegmentCount(spec, mRef, esc_Ref, encRef); + approxLen += encoder.EncodeSegmentCount(spec, mUsername, esc_Username, encUsername, useEncUsername); + approxLen += encoder.EncodeSegmentCount(spec, mPassword, esc_Password, encPassword, useEncPassword); + approxLen += encoder.EncodeSegmentCount(spec, mDirectory, esc_Directory, encDirectory, useEncDirectory); + approxLen += encoder.EncodeSegmentCount(spec, mBasename, esc_FileBaseName, encBasename, useEncBasename); + approxLen += encoder.EncodeSegmentCount(spec, mExtension, esc_FileExtension, encExtension, useEncExtension); + approxLen += encoder.EncodeSegmentCount(spec, mParam, esc_Param, encParam, useEncParam); + approxLen += encoder.EncodeSegmentCount(spec, mQuery, esc_Query, encQuery, useEncQuery); + approxLen += encoder.EncodeSegmentCount(spec, mRef, esc_Ref, encRef, useEncRef); } // do not escape the hostname, if IPv6 address literal, mHost will @@ -532,21 +529,15 @@ nsStandardURL::BuildNormalizedSpec(const char *spec) // append authority if (mUsername.mLen > 0) { - i = AppendSegmentToBuf(buf, i, spec, mUsername, &encUsername); + i = AppendSegmentToBuf(buf, i, spec, mUsername, &encUsername, useEncUsername); if (mPassword.mLen >= 0) { buf[i++] = ':'; - i = AppendSegmentToBuf(buf, i, spec, mPassword, &encPassword); + i = AppendSegmentToBuf(buf, i, spec, mPassword, &encPassword, useEncPassword); } buf[i++] = '@'; } if (mHost.mLen > 0) { - if (useEncHost) { - mHost.mPos = i; - mHost.mLen = encHost.Length(); - i = AppendToBuf(buf, i, encHost.get(), mHost.mLen); - } - else - i = AppendSegmentToBuf(buf, i, spec, mHost); + i = AppendSegmentToBuf(buf, i, spec, mHost, &encHost, useEncHost); net_ToLowerCase(buf + mHost.mPos, mHost.mLen); if (mPort != -1 && mPort != mDefaultPort) { nsCAutoString portbuf; @@ -580,7 +571,7 @@ nsStandardURL::BuildNormalizedSpec(const char *spec) // record corrected (file)path starting position mPath.mPos = mFilepath.mPos = i - leadingSlash; - i = AppendSegmentToBuf(buf, i, spec, mDirectory, &encDirectory); + i = AppendSegmentToBuf(buf, i, spec, mDirectory, &encDirectory, useEncDirectory); // the directory must end with a '/' if (buf[i-1] != '/') { @@ -588,7 +579,7 @@ nsStandardURL::BuildNormalizedSpec(const char *spec) mDirectory.mLen++; } - i = AppendSegmentToBuf(buf, i, spec, mBasename, &encBasename); + i = AppendSegmentToBuf(buf, i, spec, mBasename, &encBasename, useEncBasename); // make corrections to directory segment if leadingSlash if (leadingSlash) { @@ -601,22 +592,22 @@ nsStandardURL::BuildNormalizedSpec(const char *spec) if (mExtension.mLen >= 0) { buf[i++] = '.'; - i = AppendSegmentToBuf(buf, i, spec, mExtension, &encExtension); + i = AppendSegmentToBuf(buf, i, spec, mExtension, &encExtension, useEncExtension); } // calculate corrected filepath length mFilepath.mLen = i - mFilepath.mPos; if (mParam.mLen >= 0) { buf[i++] = ';'; - i = AppendSegmentToBuf(buf, i, spec, mParam, &encParam); + i = AppendSegmentToBuf(buf, i, spec, mParam, &encParam, useEncParam); } if (mQuery.mLen >= 0) { buf[i++] = '?'; - i = AppendSegmentToBuf(buf, i, spec, mQuery, &encQuery); + i = AppendSegmentToBuf(buf, i, spec, mQuery, &encQuery, useEncQuery); } if (mRef.mLen >= 0) { buf[i++] = '#'; - i = AppendSegmentToBuf(buf, i, spec, mRef, &encRef); + i = AppendSegmentToBuf(buf, i, spec, mRef, &encRef, useEncRef); } // calculate corrected path length mPath.mLen = i - mPath.mPos; @@ -859,7 +850,7 @@ nsStandardURL::PrefsChanged(nsIPrefBranch *prefs, const char *pref) } /* static */ nsresult -nsStandardURL::ACEtoUTF8(const nsCSubstring &host, nsCString &result) +nsStandardURL::ACEtoDisplayIDN(const nsCSubstring &host, nsCString &result) { if (gShowPunycode || !IsInWhitelist(host)) { result = host; @@ -870,7 +861,7 @@ nsStandardURL::ACEtoUTF8(const nsCSubstring &host, nsCString &result) } /* static */ nsresult -nsStandardURL::NormalizeUTF8(const nsCSubstring &host, nsCString &result) +nsStandardURL::UTF8toDisplayIDN(const nsCSubstring &host, nsCString &result) { if (gShowPunycode || !IsInWhitelist(host)) return gIDN->ConvertUTF8toACE(host, result); @@ -1221,18 +1212,20 @@ nsStandardURL::SetUserPass(const nsACString &input) nsCAutoString buf; if (usernameLen > 0) { GET_SEGMENT_ENCODER(encoder); + PRBool ignoredOut; usernameLen = encoder.EncodeSegmentCount(userpass.get(), URLSegment(usernamePos, usernameLen), esc_Username | esc_AlwaysCopy, - buf); + buf, ignoredOut); if (passwordLen >= 0) { buf.Append(':'); passwordLen = encoder.EncodeSegmentCount(userpass.get(), URLSegment(passwordPos, passwordLen), esc_Password | - esc_AlwaysCopy, buf); + esc_AlwaysCopy, buf, + ignoredOut); } if (mUsername.mLen < 0) buf.Append('@'); @@ -2183,9 +2176,11 @@ nsStandardURL::SetQuery(const nsACString &input) // encode query if necessary nsCAutoString buf; + PRBool encoded; GET_SEGMENT_ENCODER(encoder); - encoder.EncodeSegmentCount(query, URLSegment(0, queryLen), esc_Query, buf); - if (!buf.IsEmpty()) { + encoder.EncodeSegmentCount(query, URLSegment(0, queryLen), esc_Query, + buf, encoded); + if (encoded) { query = buf.get(); queryLen = buf.Length(); } @@ -2241,9 +2236,11 @@ nsStandardURL::SetRef(const nsACString &input) // encode ref if necessary nsCAutoString buf; + PRBool encoded; GET_SEGMENT_ENCODER(encoder); - encoder.EncodeSegmentCount(ref, URLSegment(0, refLen), esc_Ref, buf); - if (!buf.IsEmpty()) { + encoder.EncodeSegmentCount(ref, URLSegment(0, refLen), esc_Ref, + buf, encoded); + if (encoded) { ref = buf.get(); refLen = buf.Length(); } @@ -2311,17 +2308,20 @@ nsStandardURL::SetFileName(const nsACString &input) } else { nsCAutoString newFilename; + PRBool ignoredOut; GET_SEGMENT_ENCODER(encoder); basename.mLen = encoder.EncodeSegmentCount(filename, basename, esc_FileBaseName | esc_AlwaysCopy, - newFilename); + newFilename, + ignoredOut); if (extension.mLen >= 0) { newFilename.Append('.'); extension.mLen = encoder.EncodeSegmentCount(filename, extension, esc_FileExtension | esc_AlwaysCopy, - newFilename); + newFilename, + ignoredOut); } if (mBasename.mLen < 0) { diff --git a/netwerk/base/src/nsStandardURL.h b/netwerk/base/src/nsStandardURL.h index 6ab40f14126..e13959ec6c1 100644 --- a/netwerk/base/src/nsStandardURL.h +++ b/netwerk/base/src/nsStandardURL.h @@ -124,7 +124,8 @@ public: /* internal -- HPUX compiler can't handle this being private */ PRInt32 EncodeSegmentCount(const char *str, const URLSegment &segment, PRInt16 mask, - nsAFlatCString &buf); + nsAFlatCString &buf, + PRBool& appended); // Encode the given string if necessary, and return a reference to // the encoded string. Returns a reference to |buf| if encoding @@ -159,7 +160,7 @@ private: PRBool NormalizeIDN(const nsCSubstring &host, nsCString &result); void CoalescePath(netCoalesceFlags coalesceFlag, char *path); - PRUint32 AppendSegmentToBuf(char *, PRUint32, const char *, URLSegment &, const nsCString *esc=nsnull); + PRUint32 AppendSegmentToBuf(char *, PRUint32, const char *, URLSegment &, const nsCString *esc=nsnull, PRBool useEsc = PR_FALSE); PRUint32 AppendToBuf(char *, PRUint32, const char *, PRUint32); nsresult BuildNormalizedSpec(const char *spec); @@ -219,8 +220,8 @@ private: static void PrefsChanged(nsIPrefBranch *prefs, const char *pref); // IDN routines - static nsresult ACEtoUTF8(const nsCSubstring &in, nsCString &out); - static nsresult NormalizeUTF8(const nsCSubstring &in, nsCString &out); + static nsresult ACEtoDisplayIDN(const nsCSubstring &in, nsCString &out); + static nsresult UTF8toDisplayIDN(const nsCSubstring &in, nsCString &out); static PRBool IsInWhitelist(const nsCSubstring &host); // mSpec contains the normalized version of the URL spec (UTF-8 encoded).