bool AppendUTF8toUTF16( const nsACString& aSource, nsAString& aDest, const mozilla::fallible_t& ) { nsACString::const_iterator source_start, source_end; CalculateUTF8Length calculator; copy_string(aSource.BeginReading(source_start), aSource.EndReading(source_end), calculator); uint32_t count = calculator.Length(); // Avoid making the string mutable if we're appending an empty string if (count) { uint32_t old_dest_length = aDest.Length(); // Grow the buffer if we need to. if (!aDest.SetLength(old_dest_length + count, mozilla::fallible_t())) { return false; } // All ready? Time to convert ConvertUTF8toUTF16 converter(aDest.BeginWriting() + old_dest_length); copy_string(aSource.BeginReading(source_start), aSource.EndReading(source_end), converter); NS_ASSERTION(converter.ErrorEncountered() || converter.Length() == count, "CalculateUTF8Length produced the wrong length"); if (converter.ErrorEncountered()) { NS_ERROR("Input wasn't UTF8 or incorrect length was calculated"); aDest.SetLength(old_dest_length); } } return true; }
void URLParams::ParseInput(const nsACString& aInput) { // Remove all the existing data before parsing a new input. DeleteAll(); nsACString::const_iterator start, end; aInput.BeginReading(start); aInput.EndReading(end); nsACString::const_iterator iter(start); while (start != end) { nsAutoCString string; if (FindCharInReadable('&', iter, end)) { string.Assign(Substring(start, iter)); start = ++iter; } else { string.Assign(Substring(start, end)); start = end; } if (string.IsEmpty()) { continue; } nsACString::const_iterator eqStart, eqEnd; string.BeginReading(eqStart); string.EndReading(eqEnd); nsACString::const_iterator eqIter(eqStart); nsAutoCString name; nsAutoCString value; if (FindCharInReadable('=', eqIter, eqEnd)) { name.Assign(Substring(eqStart, eqIter)); ++eqIter; value.Assign(Substring(eqIter, eqEnd)); } else { name.Assign(string); } nsAutoString decodedName; DecodeString(name, decodedName); nsAutoString decodedValue; DecodeString(value, decodedValue); Append(decodedName, decodedValue); } }
void URLSearchParams::DecodeString(const nsACString& aInput, nsACString& aOutput) { nsACString::const_iterator start, end; aInput.BeginReading(start); aInput.EndReading(end); while (start != end) { // replace '+' with U+0020 if (*start == '+') { aOutput.Append(' '); ++start; continue; } // Percent decode algorithm if (*start == '%') { nsACString::const_iterator first(start); ++first; nsACString::const_iterator second(first); ++second; #define ASCII_HEX_DIGIT( x ) \ ((x >= 0x41 && x <= 0x46) || \ (x >= 0x61 && x <= 0x66) || \ (x >= 0x30 && x <= 0x39)) #define HEX_DIGIT( x ) \ (*x >= 0x30 && *x <= 0x39 \ ? *x - 0x30 \ : (*x >= 0x41 && *x <= 0x46 \ ? *x - 0x37 \ : *x - 0x57)) if (first != end && second != end && ASCII_HEX_DIGIT(*first) && ASCII_HEX_DIGIT(*second)) { aOutput.Append(HEX_DIGIT(first) * 16 + HEX_DIGIT(second)); start = ++second; continue; } else { aOutput.Append('%'); ++start; continue; } } aOutput.Append(*start); ++start; } }
void ReverseString(const nsACString& aSource, nsACString& aResult) { nsACString::const_iterator sourceBegin, sourceEnd; aSource.BeginReading(sourceBegin); aSource.EndReading(sourceEnd); aResult.SetLength(aSource.Length()); auto destEnd = aResult.EndWriting(); while (sourceBegin != sourceEnd) { *(--destEnd) = *sourceBegin; ++sourceBegin; } }
NS_IMETHODIMP nsLocalFile::SetRelativeDescriptor(nsIFile* aFromFile, const nsACString& aRelativeDesc) { NS_NAMED_LITERAL_CSTRING(kParentDirStr, "../"); nsCOMPtr<nsIFile> targetFile; nsresult rv = aFromFile->Clone(getter_AddRefs(targetFile)); if (NS_FAILED(rv)) { return rv; } // // aRelativeDesc is UTF-8 encoded // nsCString::const_iterator strBegin, strEnd; aRelativeDesc.BeginReading(strBegin); aRelativeDesc.EndReading(strEnd); nsCString::const_iterator nodeBegin(strBegin), nodeEnd(strEnd); nsCString::const_iterator pos(strBegin); nsCOMPtr<nsIFile> parentDir; while (FindInReadable(kParentDirStr, nodeBegin, nodeEnd)) { rv = targetFile->GetParent(getter_AddRefs(parentDir)); if (NS_FAILED(rv)) { return rv; } if (!parentDir) { return NS_ERROR_FILE_UNRECOGNIZED_PATH; } targetFile = parentDir; nodeBegin = nodeEnd; pos = nodeEnd; nodeEnd = strEnd; } nodeBegin = nodeEnd = pos; while (nodeEnd != strEnd) { FindCharInReadable('/', nodeEnd, strEnd); targetFile->Append(NS_ConvertUTF8toUTF16(Substring(nodeBegin, nodeEnd))); if (nodeEnd != strEnd) { // If there's more left in the string, inc over the '/' nodeEnd is on. ++nodeEnd; } nodeBegin = nodeEnd; } return InitWithFile(targetFile); }
// copy aSource strings into contiguous storage provided in aDest1, // providing terminating nulls for each destination string. static inline void StrBlockCopy(const nsACString &aSource1, const nsACString &aSource2, const nsACString &aSource3, const nsACString &aSource4, char *&aDest1, char *&aDest2, char *&aDest3, char *&aDest4, char *&aDestEnd) { char *toBegin = aDest1; nsACString::const_iterator fromBegin, fromEnd; *copy_string(aSource1.BeginReading(fromBegin), aSource1.EndReading(fromEnd), toBegin) = char(0); aDest2 = ++toBegin; *copy_string(aSource2.BeginReading(fromBegin), aSource2.EndReading(fromEnd), toBegin) = char(0); aDest3 = ++toBegin; *copy_string(aSource3.BeginReading(fromBegin), aSource3.EndReading(fromEnd), toBegin) = char(0); aDest4 = ++toBegin; *copy_string(aSource4.BeginReading(fromBegin), aSource4.EndReading(fromEnd), toBegin) = char(0); aDestEnd = toBegin; }
nsresult nsIDNService::ACEtoUTF8(const nsACString & input, nsACString & _retval, stringPrepFlag flag) { // RFC 3490 - 4.2 ToUnicode // ToUnicode never fails. If any step fails, then the original input // sequence is returned immediately in that step. // // Note that this refers to the decoding of a single label. // ACEtoUTF8 may be called with a sequence of labels separated by dots; // this test applies individually to each label. uint32_t len = 0, offset = 0; nsAutoCString decodedBuf; nsACString::const_iterator start, end; input.BeginReading(start); input.EndReading(end); _retval.Truncate(); // loop and decode nodes while (start != end) { len++; if (*start++ == '.') { nsDependentCSubstring origLabel(input, offset, len - 1); if (NS_FAILED(decodeACE(origLabel, decodedBuf, flag))) { // If decoding failed, use the original input sequence // for this label. _retval.Append(origLabel); } else { _retval.Append(decodedBuf); } _retval.Append('.'); offset += len; len = 0; } } // decode the last node if (len) { nsDependentCSubstring origLabel(input, offset, len); if (NS_FAILED(decodeACE(origLabel, decodedBuf, flag))) { _retval.Append(origLabel); } else { _retval.Append(decodedBuf); } } return NS_OK; }
nsresult SubstitutingProtocolHandler::NewURI(const nsACString &aSpec, const char *aCharset, nsIURI *aBaseURI, nsIURI **result) { nsresult rv; RefPtr<SubstitutingURL> url = new SubstitutingURL(); if (!url) return NS_ERROR_OUT_OF_MEMORY; // unescape any %2f and %2e to make sure nsStandardURL coalesces them. // Later net_GetFileFromURLSpec() will do a full unescape and we want to // treat them the same way the file system will. (bugs 380994, 394075) nsAutoCString spec; const char *src = aSpec.BeginReading(); const char *end = aSpec.EndReading(); const char *last = src; spec.SetCapacity(aSpec.Length()+1); for ( ; src < end; ++src) { if (*src == '%' && (src < end-2) && *(src+1) == '2') { char ch = '\0'; if (*(src+2) == 'f' || *(src+2) == 'F') { ch = '/'; } else if (*(src+2) == 'e' || *(src+2) == 'E') { ch = '.'; } if (ch) { if (last < src) { spec.Append(last, src-last); } spec.Append(ch); src += 2; last = src+1; // src will be incremented by the loop } } } if (last < src) spec.Append(last, src-last); rv = url->Init(nsIStandardURL::URLTYPE_STANDARD, -1, spec, aCharset, aBaseURI); if (NS_SUCCEEDED(rv)) { url.forget(result); } return rv; }
NS_IMETHODIMP nsResProtocolHandler::NewURI(const nsACString &aSpec, const char *aCharset, nsIURI *aBaseURI, nsIURI **result) { nsresult rv; nsResURL *resURL = new nsResURL(); if (!resURL) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(resURL); // unescape any %2f and %2e to make sure nsStandardURL coalesces them. // Later net_GetFileFromURLSpec() will do a full unescape and we want to // treat them the same way the file system will. (bugs 380994, 394075) nsCAutoString spec; const char *src = aSpec.BeginReading(); const char *end = aSpec.EndReading(); const char *last = src; spec.SetCapacity(aSpec.Length()+1); for ( ; src < end; ++src) { if (*src == '%' && (src < end-2) && *(src+1) == '2') { char ch = '\0'; if (*(src+2) == 'f' || *(src+2) == 'F') ch = '/'; else if (*(src+2) == 'e' || *(src+2) == 'E') ch = '.'; if (ch) { if (last < src) spec.Append(last, src-last); spec.Append(ch); src += 2; last = src+1; // src will be incremented by the loop } } } if (last < src) spec.Append(last, src-last); rv = resURL->Init(nsIStandardURL::URLTYPE_STANDARD, -1, spec, aCharset, aBaseURI); if (NS_SUCCEEDED(rv)) rv = CallQueryInterface(resURL, result); NS_RELEASE(resURL); return rv; }
// static bool nsHttp::IsReasonableHeaderValue(const nsACString &s) { // Header values MUST NOT contain line-breaks. RFC 2616 technically // permits CTL characters, including CR and LF, in header values provided // they are quoted. However, this can lead to problems if servers do not // interpret quoted strings properly. Disallowing CR and LF here seems // reasonable and keeps things simple. We also disallow a null byte. const nsACString::char_type* end = s.EndReading(); for (const nsACString::char_type* i = s.BeginReading(); i != end; ++i) { if (*i == '\r' || *i == '\n' || *i == '\0') { return false; } } return true; }
static bool pathBeginsWithVolName(const nsACString& path, nsACString& firstPathComponent) { // Return whether the 1st path component in path (escaped) is equal to the name // of a mounted volume. Return the 1st path component (unescaped) in any case. // This needs to be done as quickly as possible, so we cache a list of volume names. // XXX Register an event handler to detect drives being mounted/unmounted? if (!gVolumeList) { gVolumeList = new nsTArray<nsCString>; if (!gVolumeList) { return false; // out of memory } } // Cache a list of volume names if (!gVolumeList->Length()) { OSErr err; ItemCount volumeIndex = 1; do { HFSUniStr255 volName; FSRef rootDirectory; err = ::FSGetVolumeInfo(0, volumeIndex, NULL, kFSVolInfoNone, NULL, &volName, &rootDirectory); if (err == noErr) { NS_ConvertUTF16toUTF8 volNameStr(Substring((PRUnichar *)volName.unicode, (PRUnichar *)volName.unicode + volName.length)); gVolumeList->AppendElement(volNameStr); volumeIndex++; } } while (err == noErr); } // Extract the first component of the path nsACString::const_iterator start; path.BeginReading(start); start.advance(1); // path begins with '/' nsACString::const_iterator directory_end; path.EndReading(directory_end); nsACString::const_iterator component_end(start); FindCharInReadable('/', component_end, directory_end); nsCAutoString flatComponent((Substring(start, component_end))); NS_UnescapeURL(flatComponent); PRInt32 foundIndex = gVolumeList->IndexOf(flatComponent); firstPathComponent = flatComponent; return (foundIndex != -1); }
nsresult nsIDNService::ACEtoUTF8(const nsACString & input, nsACString & _retval, bool allowUnassigned) { // RFC 3490 - 4.2 ToUnicode // ToUnicode never fails. If any step fails, then the original input // sequence is returned immediately in that step. if (!IsASCII(input)) { _retval.Assign(input); return NS_OK; } uint32_t len = 0, offset = 0; nsAutoCString decodedBuf; nsACString::const_iterator start, end; input.BeginReading(start); input.EndReading(end); _retval.Truncate(); // loop and decode nodes while (start != end) { len++; if (*start++ == '.') { if (NS_FAILED(decodeACE(Substring(input, offset, len - 1), decodedBuf, allowUnassigned))) { _retval.Assign(input); return NS_OK; } _retval.Append(decodedBuf); _retval.Append('.'); offset += len; len = 0; } } // decode the last node if (len) { if (NS_FAILED(decodeACE(Substring(input, offset, len), decodedBuf, allowUnassigned))) _retval.Assign(input); else _retval.Append(decodedBuf); } return NS_OK; }
static void SplitTables(const nsACString& str, nsTArray<nsCString>& tables) { tables.Clear(); nsACString::const_iterator begin, iter, end; str.BeginReading(begin); str.EndReading(end); while (begin != end) { iter = begin; FindCharInReadable(',', iter, end); tables.AppendElement(Substring(begin, iter)); begin = iter; if (begin != end) begin++; } }
bool nsPicoService::GetVoiceFileLanguage(const nsACString& aFileName, nsAString& aLang) { nsACString::const_iterator start, end; aFileName.BeginReading(start); aFileName.EndReading(end); // The lingware filename syntax is language_(ta/sg).bin, // we extract the language prefix here. if (FindInReadable(NS_LITERAL_CSTRING("_"), start, end)) { end = start; aFileName.BeginReading(start); aLang.Assign(NS_ConvertUTF8toUTF16(Substring(start, end))); return true; } return false; }
uint32_t CountCharInReadable(const nsACString& aStr, char aChar) { uint32_t count = 0; nsACString::const_iterator begin, end; aStr.BeginReading(begin); aStr.EndReading(end); while (begin != end) { if (*begin == aChar) { ++count; } ++begin; } return count; }
void AppendASCIItoUTF16( const nsACString& aSource, nsAString& aDest ) { uint32_t old_dest_length = aDest.Length(); aDest.SetLength(old_dest_length + aSource.Length()); nsACString::const_iterator fromBegin, fromEnd; nsAString::iterator dest; aDest.BeginWriting(dest); dest.advance(old_dest_length); // right now, this won't work on multi-fragment destinations LossyConvertEncoding8to16 converter(dest.get()); copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter); }
/** * Determines whether or not a string exists as the root element in an XML data * string buffer. * @param dataString * The data being sniffed * @param substring * The substring being tested for existence and root-ness. * @returns true if the substring exists and is the documentElement, false * otherwise. */ static bool ContainsTopLevelSubstring(nsACString& dataString, const char *substring) { nsACString::const_iterator start, end; dataString.BeginReading(start); dataString.EndReading(end); if (!FindInReadable(nsCString(substring), start, end)){ return false; } auto offset = start.get() - dataString.Data(); const char *begin = dataString.BeginReading(); // Only do the validation when we find the substring. return IsDocumentElement(begin, begin + offset); }
/* static */ nsresult LookupCache::GetKey(const nsACString& aSpec, Completion* aHash, nsCOMPtr<nsICryptoHash>& aCryptoHash) { nsACString::const_iterator begin, end, iter; aSpec.BeginReading(begin); aSpec.EndReading(end); iter = begin; if (!FindCharInReadable('/', iter, end)) { return NS_OK; } const nsCSubstring& host = Substring(begin, iter); if (IsCanonicalizedIP(host)) { nsAutoCString key; key.Assign(host); key.Append('/'); return aHash->FromPlaintext(key, aCryptoHash); } nsTArray<nsCString> hostComponents; ParseString(PromiseFlatCString(host), '.', hostComponents); if (hostComponents.Length() < 2) return NS_ERROR_FAILURE; int32_t last = int32_t(hostComponents.Length()) - 1; nsAutoCString lookupHost; if (hostComponents.Length() > 2) { lookupHost.Append(hostComponents[last - 2]); lookupHost.Append('.'); } lookupHost.Append(hostComponents[last - 1]); lookupHost.Append('.'); lookupHost.Append(hostComponents[last]); lookupHost.Append('/'); return aHash->FromPlaintext(lookupHost, aCryptoHash); }
static bool HostIgnoredByProxy(const nsACString& aIgnore, const nsACString& aHost) { if (aIgnore.Equals(aHost, nsCaseInsensitiveCStringComparator())) return true; if (aIgnore.First() == '*' && StringEndsWith(aHost, nsDependentCSubstring(aIgnore, 1), nsCaseInsensitiveCStringComparator())) return true; int32_t mask = 128; nsReadingIterator<char> start; nsReadingIterator<char> slash; nsReadingIterator<char> end; aIgnore.BeginReading(start); aIgnore.BeginReading(slash); aIgnore.EndReading(end); if (FindCharInReadable('/', slash, end)) { ++slash; nsDependentCSubstring maskStr(slash, end); nsAutoCString maskStr2(maskStr); nsresult err; mask = maskStr2.ToInteger(&err); if (NS_FAILED(err)) { mask = 128; } --slash; } else { slash = end; } nsDependentCSubstring ignoreStripped(start, slash); PRIPv6Addr ignoreAddr, hostAddr; if (!ConvertToIPV6Addr(ignoreStripped, &ignoreAddr, &mask) || !ConvertToIPV6Addr(aHost, &hostAddr, nullptr)) return false; proxy_MaskIPv6Addr(ignoreAddr, mask); proxy_MaskIPv6Addr(hostAddr, mask); return memcmp(&ignoreAddr, &hostAddr, sizeof(PRIPv6Addr)) == 0; }
static PRBool GConfIgnoreHost(const nsACString& aIgnore, const nsACString& aHost) { if (aIgnore.Equals(aHost, nsCaseInsensitiveCStringComparator())) return PR_TRUE; if (aIgnore.First() == '*' && StringEndsWith(aHost, nsDependentCSubstring(aIgnore, 1), nsCaseInsensitiveCStringComparator())) return PR_TRUE; PRInt32 mask = 128; nsReadingIterator<char> start; nsReadingIterator<char> slash; nsReadingIterator<char> end; aIgnore.BeginReading(start); aIgnore.BeginReading(slash); aIgnore.EndReading(end); if (FindCharInReadable('/', slash, end)) { ++slash; nsDependentCSubstring maskStr(slash, end); nsCAutoString maskStr2(maskStr); PRInt32 err; mask = maskStr2.ToInteger(&err); if (err != 0) { mask = 128; } --slash; } else { slash = end; } PRIPv6Addr ignoreAddr, hostAddr; if (!ConvertToIPV6Addr(aIgnore, &ignoreAddr) || !ConvertToIPV6Addr(aHost, &hostAddr)) return PR_FALSE; proxy_MaskIPv6Addr(ignoreAddr, mask); proxy_MaskIPv6Addr(hostAddr, mask); return memcmp(&ignoreAddr, &hostAddr, sizeof(PRIPv6Addr)) == 0; }
bool net_IsAbsoluteURL(const nsACString& uri) { nsACString::const_iterator start, end; uri.BeginReading(start); uri.EndReading(end); // Strip C0 and space from begining while (start != end) { if ((uint8_t) *start > 0x20) { break; } start++; } Tokenizer p(Substring(start, end), "\r\n\t"); // First char must be alpha if (!p.CheckChar(isAsciiAlpha)) { return false; } while (p.CheckChar(net_IsValidSchemeChar) || p.CheckWhite()) { // Skip valid scheme characters or \r\n\t } if (!p.CheckChar(':')) { return false; } p.SkipWhites(); if (!p.CheckChar('/')) { return false; } p.SkipWhites(); if (p.CheckChar('/')) { // aSpec is really absolute. Ignore aBaseURI in this case return true; } return false; }
PRBool nsNodeInfo::QualifiedNameEqualsInternal(const nsACString& aQualifiedName) const { NS_PRECONDITION(mInner.mPrefix, "Must have prefix"); nsACString::const_iterator start; aQualifiedName.BeginReading(start); nsACString::const_iterator colon(start); const char* prefix; mInner.mPrefix->GetUTF8String(&prefix); PRUint32 len = strlen(prefix); if (len >= aQualifiedName.Length()) { return PR_FALSE; } colon.advance(len); // If the character at the prefix length index is not a colon, // aQualifiedName is not equal to this string. if (*colon != ':') { return PR_FALSE; } // Compare the prefix to the string from the start to the colon if (!mInner.mPrefix->EqualsUTF8(Substring(start, colon))) return PR_FALSE; ++colon; // Skip the ':' nsACString::const_iterator end; aQualifiedName.EndReading(end); // Compare the local name to the string between the colon and the // end of aQualifiedName return mInner.mName->EqualsUTF8(Substring(colon, end)); }
NS_IMETHODIMP nsMailboxService::NewURI(const nsACString &aSpec, const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval) { nsresult rv = NS_OK; nsACString::const_iterator b, e; if (FindInReadable(NS_LITERAL_CSTRING("?uidl="), aSpec.BeginReading(b), aSpec.EndReading(e)) || FindInReadable(NS_LITERAL_CSTRING("&uidl="), aSpec.BeginReading(b), aSpec.EndReading(e))) { nsCOMPtr<nsIProtocolHandler> handler = do_GetService(kCPop3ServiceCID, &rv); if (NS_SUCCEEDED(rv)) rv = handler->NewURI(aSpec, aOriginCharset, aBaseURI, _retval); } else { nsCOMPtr<nsIURI> aMsgUri = do_CreateInstance(kCMailboxUrl, &rv); if (NS_SUCCEEDED(rv)) { if (aBaseURI) { nsCAutoString newSpec; rv = aBaseURI->Resolve(aSpec, newSpec); if (NS_FAILED(rv)) return rv; aMsgUri->SetSpec(newSpec); } else { aMsgUri->SetSpec(aSpec); } NS_ADDREF(*_retval = aMsgUri); } } return rv; }
bool IsASCII( const nsACString& aString ) { static const char NOT_ASCII = char(~0x7F); // Don't want to use |copy_string| for this task, since we can stop at the first non-ASCII character nsACString::const_iterator iter, done_reading; aString.BeginReading(iter); aString.EndReading(done_reading); const char* c = iter.get(); const char* end = done_reading.get(); while ( c < end ) { if ( *c++ & NOT_ASCII ) return false; } return true; }
/* static */ bool MatchAutoCompleteFunction::findBeginning(const nsDependentCSubstring &aToken, const nsACString &aSourceString) { NS_PRECONDITION(!aToken.IsEmpty(), "Don't search for an empty token!"); // We can't use StringBeginsWith here, unfortunately. Although it will // happily take a case-insensitive UTF8 comparator, it eventually calls // nsACString::Equals, which checks that the two strings contain the same // number of bytes before calling the comparator. Two characters may be // case-insensitively equal while taking up different numbers of bytes, so // this is not what we want. const_char_iterator tokenStart(aToken.BeginReading()), tokenEnd(aToken.EndReading()), sourceStart(aSourceString.BeginReading()), sourceEnd(aSourceString.EndReading()); bool dummy; while (sourceStart < sourceEnd && CaseInsensitiveUTF8CharsEqual(sourceStart, tokenStart, sourceEnd, tokenEnd, &sourceStart, &tokenStart, &dummy)) { // We found the token! if (tokenStart >= tokenEnd) { return true; } } // We don't need to check CaseInsensitiveUTF8CharsEqual's error condition // (stored in |dummy|), since the function will return false if it // encounters an error. return false; }
bool AppendASCIItoUTF16(const nsACString& aSource, nsAString& aDest, const mozilla::fallible_t&) { uint32_t old_dest_length = aDest.Length(); if (!aDest.SetLength(old_dest_length + aSource.Length(), mozilla::fallible_t())) { return false; } nsACString::const_iterator fromBegin, fromEnd; nsAString::iterator dest; aDest.BeginWriting(dest); dest.advance(old_dest_length); // right now, this won't work on multi-fragment destinations LossyConvertEncoding8to16 converter(dest.get()); copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter); return true; }
nsresult ClientIDFromCacheKey(const nsACString& key, char ** result) { nsresult rv = NS_OK; *result = nullptr; nsReadingIterator<char> colon; key.BeginReading(colon); nsReadingIterator<char> start; key.BeginReading(start); nsReadingIterator<char> end; key.EndReading(end); if (FindCharInReadable(':', colon, end)) { *result = ToNewCString( Substring(start, colon)); if (!*result) rv = NS_ERROR_OUT_OF_MEMORY; } else { NS_ASSERTION(false, "FindCharInRead failed to find ':'"); rv = NS_ERROR_UNEXPECTED; } return rv; }
nsresult nsDefaultURIFixup::KeywordURIFixup(const nsACString & aURIString, nsDefaultURIFixupInfo* aFixupInfo, nsIInputStream **aPostData) { // These are keyword formatted strings // "what is mozilla" // "what is mozilla?" // "docshell site:mozilla.org" - has no dot/colon in the first space-separated substring // "?mozilla" - anything that begins with a question mark // "?site:mozilla.org docshell" // Things that have a quote before the first dot/colon // "mozilla" - checked against a whitelist to see if it's a host or not // ".mozilla", "mozilla." - ditto // These are not keyword formatted strings // "www.blah.com" - first space-separated substring contains a dot, doesn't start with "?" // "www.blah.com stuff" // "nonQualifiedHost:80" - first space-separated substring contains a colon, doesn't start with "?" // "nonQualifiedHost:80 args" // "nonQualifiedHost?" // "nonQualifiedHost?args" // "nonQualifiedHost?some args" // "blah.com." // Note: uint32_t(kNotFound) is greater than any actual location // in practice. So if we cast all locations to uint32_t, then a < // b guarantees that either b is kNotFound and a is found, or both // are found and a found before b. uint32_t firstDotLoc = uint32_t(kNotFound); uint32_t lastDotLoc = uint32_t(kNotFound); uint32_t firstColonLoc = uint32_t(kNotFound); uint32_t firstQuoteLoc = uint32_t(kNotFound); uint32_t firstSpaceLoc = uint32_t(kNotFound); uint32_t firstQMarkLoc = uint32_t(kNotFound); uint32_t lastLSBracketLoc = uint32_t(kNotFound); uint32_t lastSlashLoc = uint32_t(kNotFound); uint32_t pos = 0; uint32_t foundDots = 0; uint32_t foundColons = 0; uint32_t foundDigits = 0; uint32_t foundRSBrackets = 0; bool looksLikeIpv6 = true; bool hasAsciiAlpha = false; nsACString::const_iterator iterBegin; nsACString::const_iterator iterEnd; aURIString.BeginReading(iterBegin); aURIString.EndReading(iterEnd); nsACString::const_iterator iter = iterBegin; while (iter != iterEnd) { if (pos >= 1 && foundRSBrackets == 0) { if (!(lastLSBracketLoc == 0 && (*iter == ':' || *iter == '.' || *iter == ']' || (*iter >= 'a' && *iter <= 'f') || (*iter >= 'A' && *iter <= 'F') || nsCRT::IsAsciiDigit(*iter)))) { looksLikeIpv6 = false; } } if (*iter == '.') { ++foundDots; lastDotLoc = pos; if (firstDotLoc == uint32_t(kNotFound)) { firstDotLoc = pos; } } else if (*iter == ':') { ++foundColons; if (firstColonLoc == uint32_t(kNotFound)) { firstColonLoc = pos; } } else if (*iter == ' ' && firstSpaceLoc == uint32_t(kNotFound)) { firstSpaceLoc = pos; } else if (*iter == '?' && firstQMarkLoc == uint32_t(kNotFound)) { firstQMarkLoc = pos; } else if ((*iter == '\'' || *iter == '"') && firstQuoteLoc == uint32_t(kNotFound)) { firstQuoteLoc = pos; } else if (*iter == '[') { lastLSBracketLoc = pos; } else if (*iter == ']') { foundRSBrackets++; } else if (*iter == '/') { lastSlashLoc = pos; } else if (nsCRT::IsAsciiAlpha(*iter)) { hasAsciiAlpha = true; } else if (nsCRT::IsAsciiDigit(*iter)) { ++foundDigits; } pos++; iter++; } if (lastLSBracketLoc > 0 || foundRSBrackets != 1) { looksLikeIpv6 = false; } nsAutoCString asciiHost; nsAutoCString host; bool isValidAsciiHost = aFixupInfo->mFixedURI && NS_SUCCEEDED(aFixupInfo->mFixedURI->GetAsciiHost(asciiHost)) && !asciiHost.IsEmpty(); bool isValidHost = aFixupInfo->mFixedURI && NS_SUCCEEDED(aFixupInfo->mFixedURI->GetHost(host)) && !host.IsEmpty(); // If there are 2 dots and only numbers between them, an optional port number // and a trailing slash, then don't do a keyword lookup if (foundDots == 2 && lastSlashLoc == pos - 1 && ((foundDots + foundDigits == pos - 1) || (foundColons == 1 && firstColonLoc > lastDotLoc && foundDots + foundDigits + foundColons == pos - 1))) { return NS_OK; } uint32_t posWithNoTrailingSlash = pos; if (lastSlashLoc == pos - 1) { posWithNoTrailingSlash -= 1; } // If there are 3 dots and only numbers between them, an optional port number // and an optional trailling slash, then don't do a keyword lookup (ipv4) if (foundDots == 3 && ((foundDots + foundDigits == posWithNoTrailingSlash) || (foundColons == 1 && firstColonLoc > lastDotLoc && foundDots + foundDigits + foundColons == posWithNoTrailingSlash))) { return NS_OK; } // If there are only colons and only hexadecimal characters ([a-z][0-9]) // enclosed in [], then don't do a keyword lookup if (looksLikeIpv6) { return NS_OK; } nsresult rv = NS_OK; // We do keyword lookups if a space or quote preceded the dot, colon // or question mark (or if the latter is not found, or if the input starts with a question mark) if (((firstSpaceLoc < firstDotLoc || firstQuoteLoc < firstDotLoc) && (firstSpaceLoc < firstColonLoc || firstQuoteLoc < firstColonLoc) && (firstSpaceLoc < firstQMarkLoc || firstQuoteLoc < firstQMarkLoc)) || firstQMarkLoc == 0) { rv = TryKeywordFixupForURIInfo(aFixupInfo->mOriginalInput, aFixupInfo, aPostData); // ... or when the host is the same as asciiHost and there are no // characters from [a-z][A-Z] } else if (isValidAsciiHost && isValidHost && !hasAsciiAlpha && host.EqualsIgnoreCase(asciiHost.get())) { if (!sDNSFirstForSingleWords) { rv = TryKeywordFixupForURIInfo(aFixupInfo->mOriginalInput, aFixupInfo, aPostData); } } // ... or if there is no question mark or colon, and there is either no // dot, or exactly 1 and it is the first or last character of the input: else if ((firstDotLoc == uint32_t(kNotFound) || (foundDots == 1 && (firstDotLoc == 0 || firstDotLoc == aURIString.Length() - 1))) && firstColonLoc == uint32_t(kNotFound) && firstQMarkLoc == uint32_t(kNotFound)) { if (isValidAsciiHost && IsDomainWhitelisted(asciiHost, firstDotLoc)) { return NS_OK; } // ... unless there are no dots, and a slash, and alpha characters, and this is a valid host: if (firstDotLoc == uint32_t(kNotFound) && lastSlashLoc != uint32_t(kNotFound) && hasAsciiAlpha && isValidAsciiHost) { return NS_OK; } // If we get here, we don't have a valid URI, or we did but the // host is not whitelisted, so we do a keyword search *anyway*: rv = TryKeywordFixupForURIInfo(aFixupInfo->mOriginalInput, aFixupInfo, aPostData); } return rv; }
bool nsDefaultURIFixup::PossiblyHostPortUrl(const nsACString &aUrl) { // Oh dear, the protocol is invalid. Test if the protocol might // actually be a url without a protocol: // // http://www.faqs.org/rfcs/rfc1738.html // http://www.faqs.org/rfcs/rfc2396.html // // e.g. Anything of the form: // // <hostname>:<port> or // <hostname>:<port>/ // // Where <hostname> is a string of alphanumeric characters and dashes // separated by dots. // and <port> is a 5 or less digits. This actually breaks the rfc2396 // definition of a scheme which allows dots in schemes. // // Note: // People expecting this to work with // <user>:<password>@<host>:<port>/<url-path> will be disappointed! // // Note: Parser could be a lot tighter, tossing out silly hostnames // such as those containing consecutive dots and so on. // Read the hostname which should of the form // [a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*: nsACString::const_iterator iterBegin; nsACString::const_iterator iterEnd; aUrl.BeginReading(iterBegin); aUrl.EndReading(iterEnd); nsACString::const_iterator iter = iterBegin; while (iter != iterEnd) { uint32_t chunkSize = 0; // Parse a chunk of the address while (iter != iterEnd && (*iter == '-' || nsCRT::IsAsciiAlpha(*iter) || nsCRT::IsAsciiDigit(*iter))) { ++chunkSize; ++iter; } if (chunkSize == 0 || iter == iterEnd) { return false; } if (*iter == ':') { // Go onto checking the for the digits break; } if (*iter != '.') { // Whatever it is, it ain't a hostname! return false; } ++iter; } if (iter == iterEnd) { // No point continuing since there is no colon return false; } ++iter; // Count the number of digits after the colon and before the // next forward slash (or end of string) uint32_t digitCount = 0; while (iter != iterEnd && digitCount <= 5) { if (nsCRT::IsAsciiDigit(*iter)) { digitCount++; } else if (*iter == '/') { break; } else { // Whatever it is, it ain't a port! return false; } ++iter; } if (digitCount == 0 || digitCount > 5) { // No digits or more digits than a port would have. return false; } // Yes, it's possibly a host:port url return true; }
nsresult net_ResolveRelativePath(const nsACString &relativePath, const nsACString &basePath, nsACString &result) { nsCAutoString name; nsCAutoString path(basePath); bool needsDelim = false; if ( !path.IsEmpty() ) { PRUnichar last = path.Last(); needsDelim = !(last == '/'); } nsACString::const_iterator beg, end; relativePath.BeginReading(beg); relativePath.EndReading(end); bool stop = false; char c; for (; !stop; ++beg) { c = (beg == end) ? '\0' : *beg; //printf("%c [name=%s] [path=%s]\n", c, name.get(), path.get()); switch (c) { case '\0': case '#': case '?': stop = true; // fall through... case '/': // delimiter found if (name.EqualsLiteral("..")) { // pop path // If we already have the delim at end, then // skip over that when searching for next one to the left PRInt32 offset = path.Length() - (needsDelim ? 1 : 2); // First check for errors if (offset < 0 ) return NS_ERROR_MALFORMED_URI; PRInt32 pos = path.RFind("/", false, offset); if (pos >= 0) path.Truncate(pos + 1); else path.Truncate(); } else if (name.IsEmpty() || name.EqualsLiteral(".")) { // do nothing } else { // append name to path if (needsDelim) path += '/'; path += name; needsDelim = true; } name.Truncate(); break; default: // append char to name name += c; } } // append anything left on relativePath (e.g. #..., ;..., ?...) if (c != '\0') path += Substring(--beg, end); result = path; return NS_OK; }