nsresult nsMailtoUrl::ParseUrl() { nsresult rv = NS_OK; // we can get the path from the simple url..... nsCAutoString aPath; m_baseURL->GetPath(aPath); m_toPart.Assign(aPath); PRInt32 startOfSearchPart = m_toPart.FindChar('?'); if (startOfSearchPart >= 0) { // now parse out the search field... nsCAutoString searchPart; PRUint32 numExtraChars = m_toPart.Right(searchPart, m_toPart.Length() - startOfSearchPart); if (!searchPart.IsEmpty()) { // now we need to strip off the search part from the // to part.... m_toPart.Cut(startOfSearchPart, numExtraChars); ParseMailtoUrl(searchPart.BeginWriting()); } } else if (!m_toPart.IsEmpty()) { nsUnescape(m_toPart.BeginWriting()); } return rv; }
NS_IMETHODIMP nsSmtpUrl::SetRecipients(const char * aRecipientsList) { NS_ENSURE_ARG(aRecipientsList); m_toPart = aRecipientsList; if (!m_toPart.IsEmpty()) nsUnescape(m_toPart.BeginWriting()); return NS_OK; }
//---------------------------------------------------------------------------------------- void nsSimpleCharString::Unescape() //---------------------------------------------------------------------------------------- { if (!mData) return; ReallocData(mData->mLength); if (!mData) return; nsUnescape(mData->mString); mData->mLength = strlen(mData->mString); } // nsSimpleCharString::Unescape
// percent-decode a value // returns false on failure bool PercentDecode(nsACString& aValue) { char *c = (char *) nsMemory::Alloc(aValue.Length() + 1); if (!c) { return false; } strcpy(c, PromiseFlatCString(aValue).get()); nsUnescape(c); aValue.Assign(c); nsMemory::Free(c); return true; }
NS_IMETHODIMP nsTextToSubURI::UnEscapeAndConvert( const char *charset, const char *text, PRUnichar **_retval) { if(nullptr == _retval) return NS_ERROR_NULL_POINTER; if(nullptr == text) { // set empty string instead of returning error // due to compatibility for old version text = ""; } *_retval = nullptr; nsresult rv = NS_OK; // unescape the string, unescape changes the input char *unescaped = NS_strdup(text); if (nullptr == unescaped) return NS_ERROR_OUT_OF_MEMORY; unescaped = nsUnescape(unescaped); NS_ASSERTION(unescaped, "nsUnescape returned null"); // Convert from the charset to unicode nsCOMPtr<nsICharsetConverterManager> ccm = do_GetService(kCharsetConverterManagerCID, &rv); if (NS_SUCCEEDED(rv)) { nsIUnicodeDecoder *decoder; rv = ccm->GetUnicodeDecoder(charset, &decoder); if (NS_SUCCEEDED(rv)) { PRUnichar *pBuf = nullptr; int32_t len = strlen(unescaped); int32_t outlen = 0; if (NS_SUCCEEDED(rv = decoder->GetMaxLength(unescaped, len, &outlen))) { pBuf = (PRUnichar *) NS_Alloc((outlen+1)*sizeof(PRUnichar)); if (nullptr == pBuf) rv = NS_ERROR_OUT_OF_MEMORY; else { if (NS_SUCCEEDED(rv = decoder->Convert(unescaped, &len, pBuf, &outlen))) { pBuf[outlen] = 0; *_retval = pBuf; } else NS_Free(pBuf); } } NS_RELEASE(decoder); } } NS_Free(unescaped); return rv; }
// combine segments into a single string, returning the allocated string // (or NULL) while emptying the list char *combineContinuations(nsTArray<Continuation>& aArray) { // Sanity check if (aArray.Length() == 0) return NULL; // Get an upper bound for the length PRUint32 length = 0; for (PRUint32 i = 0; i < aArray.Length(); i++) { length += aArray[i].length; } // Allocate char *result = (char *) nsMemory::Alloc(length + 1); // Concatenate if (result) { *result = '\0'; for (PRUint32 i = 0; i < aArray.Length(); i++) { Continuation cont = aArray[i]; if (! cont.value) break; char *c = result + strlen(result); strncat(result, cont.value, cont.length); if (cont.needsPercentDecoding) { nsUnescape(c); } if (cont.wasQuotedString) { RemoveQuotedStringEscapes(c); } } // return null if empty value if (*result == '\0') { nsMemory::Free(result); result = NULL; } } else { // Handle OOM NS_WARNING("Out of memory\n"); } return result; }
// nsIStreamListener implementation NS_IMETHODIMP nsFTPDirListingConv::OnDataAvailable(nsIRequest* request, nsISupports *ctxt, nsIInputStream *inStr, uint32_t sourceOffset, uint32_t count) { NS_ASSERTION(request, "FTP dir listing stream converter needs a request"); nsresult rv; nsCOMPtr<nsIChannel> channel = do_QueryInterface(request, &rv); NS_ENSURE_SUCCESS(rv, rv); uint32_t read, streamLen; uint64_t streamLen64; rv = inStr->Available(&streamLen64); NS_ENSURE_SUCCESS(rv, rv); streamLen = (uint32_t)NS_MIN(streamLen64, uint64_t(PR_UINT32_MAX - 1)); nsAutoArrayPtr<char> buffer(new char[streamLen + 1]); NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY); rv = inStr->Read(buffer, streamLen, &read); NS_ENSURE_SUCCESS(rv, rv); // the dir listings are ascii text, null terminate this sucker. buffer[streamLen] = '\0'; PR_LOG(gFTPDirListConvLog, PR_LOG_DEBUG, ("nsFTPDirListingConv::OnData(request = %x, ctxt = %x, inStr = %x, sourceOffset = %d, count = %d)\n", request, ctxt, inStr, sourceOffset, count)); if (!mBuffer.IsEmpty()) { // we have data left over from a previous OnDataAvailable() call. // combine the buffers so we don't lose any data. mBuffer.Append(buffer); buffer = new char[mBuffer.Length()+1]; NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY); strncpy(buffer, mBuffer.get(), mBuffer.Length()+1); mBuffer.Truncate(); } #ifndef DEBUG_dougt PR_LOG(gFTPDirListConvLog, PR_LOG_DEBUG, ("::OnData() received the following %d bytes...\n\n%s\n\n", streamLen, buffer.get()) ); #else printf("::OnData() received the following %d bytes...\n\n%s\n\n", streamLen, buffer); #endif // DEBUG_dougt nsCAutoString indexFormat; if (!mSentHeading) { // build up the 300: line nsCOMPtr<nsIURI> uri; rv = channel->GetURI(getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); rv = GetHeaders(indexFormat, uri); NS_ENSURE_SUCCESS(rv, rv); mSentHeading = true; } char *line = buffer; line = DigestBufferLines(line, indexFormat); #ifndef DEBUG_dougt PR_LOG(gFTPDirListConvLog, PR_LOG_DEBUG, ("::OnData() sending the following %d bytes...\n\n%s\n\n", indexFormat.Length(), indexFormat.get()) ); #else char *unescData = ToNewCString(indexFormat); NS_ENSURE_TRUE(unescData, NS_ERROR_OUT_OF_MEMORY); nsUnescape(unescData); printf("::OnData() sending the following %d bytes...\n\n%s\n\n", indexFormat.Length(), unescData); nsMemory::Free(unescData); #endif // DEBUG_dougt // if there's any data left over, buffer it. if (line && *line) { mBuffer.Append(line); PR_LOG(gFTPDirListConvLog, PR_LOG_DEBUG, ("::OnData() buffering the following %d bytes...\n\n%s\n\n", PL_strlen(line), line) ); } // send the converted data out. nsCOMPtr<nsIInputStream> inputData; rv = NS_NewCStringInputStream(getter_AddRefs(inputData), indexFormat); NS_ENSURE_SUCCESS(rv, rv); rv = mFinalListener->OnDataAvailable(request, ctxt, inputData, 0, indexFormat.Length()); return rv; }
nsresult nsMIMEHeaderParamImpl::DoParameterInternal(const char *aHeaderValue, const char *aParamName, ParamDecoding aDecoding, char **aCharset, char **aLang, char **aResult) { if (!aHeaderValue || !*aHeaderValue || !aResult) return NS_ERROR_INVALID_ARG; *aResult = nullptr; if (aCharset) *aCharset = nullptr; if (aLang) *aLang = nullptr; nsCAutoString charset; bool acceptContinuations = (aDecoding != RFC_5987_DECODING); const char *str = aHeaderValue; // skip leading white space. for (; *str && nsCRT::IsAsciiSpace(*str); ++str) ; const char *start = str; // aParamName is empty. return the first (possibly) _unnamed_ 'parameter' // For instance, return 'inline' in the following case: // Content-Disposition: inline; filename=..... if (!aParamName || !*aParamName) { for (; *str && *str != ';' && !nsCRT::IsAsciiSpace(*str); ++str) ; if (str == start) return NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY; *aResult = (char *) nsMemory::Clone(start, (str - start) + 1); NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); (*aResult)[str - start] = '\0'; // null-terminate return NS_OK; } /* Skip forward to first ';' */ for (; *str && *str != ';' && *str != ','; ++str) ; if (*str) str++; /* Skip over following whitespace */ for (; *str && nsCRT::IsAsciiSpace(*str); ++str) ; // Some broken http servers just specify parameters // like 'filename' without specifying disposition // method. Rewind to the first non-white-space // character. if (!*str) str = start; // RFC2231 - The legitimate parm format can be: // A. title=ThisIsTitle // B. title*=us-ascii'en-us'This%20is%20wierd. // C. title*0*=us-ascii'en'This%20is%20wierd.%20We // title*1*=have%20to%20support%20this. // title*2="Else..." // D. title*0="Hey, what you think you are doing?" // title*1="There is no charset and lang info." // RFC5987: only A and B // collect results for the different algorithms (plain filename, // RFC5987/2231-encoded filename, + continuations) separately and decide // which to use at the end char *caseAResult = NULL; char *caseBResult = NULL; char *caseCDResult = NULL; // collect continuation segments nsTArray<Continuation> segments; // our copies of the charset parameter, kept separately as they might // differ for the two formats nsDependentCSubstring charsetB, charsetCD; nsDependentCSubstring lang; PRInt32 paramLen = strlen(aParamName); while (*str) { // find name/value const char *nameStart = str; const char *nameEnd = NULL; const char *valueStart = str; const char *valueEnd = NULL; bool isQuotedString = false; NS_ASSERTION(!nsCRT::IsAsciiSpace(*str), "should be after whitespace."); // Skip forward to the end of this token. for (; *str && !nsCRT::IsAsciiSpace(*str) && *str != '=' && *str != ';'; str++) ; nameEnd = str; PRInt32 nameLen = nameEnd - nameStart; // Skip over whitespace, '=', and whitespace while (nsCRT::IsAsciiSpace(*str)) ++str; if (!*str) { break; } if (*str++ != '=') { // don't accept parameters without "=" goto increment_str; } while (nsCRT::IsAsciiSpace(*str)) ++str; if (*str != '"') { // The value is a token, not a quoted string. valueStart = str; for (valueEnd = str; *valueEnd && !nsCRT::IsAsciiSpace (*valueEnd) && *valueEnd != ';'; valueEnd++) ; str = valueEnd; } else { isQuotedString = true; ++str; valueStart = str; for (valueEnd = str; *valueEnd; ++valueEnd) { if (*valueEnd == '\\') ++valueEnd; else if (*valueEnd == '"') break; } str = valueEnd; // *valueEnd != null means that *valueEnd is quote character. if (*valueEnd) str++; } // See if this is the simplest case (case A above), // a 'single' line value with no charset and lang. // If so, copy it and return. if (nameLen == paramLen && !nsCRT::strncasecmp(nameStart, aParamName, paramLen)) { if (caseAResult) { // we already have one caseA result, ignore subsequent ones goto increment_str; } // if the parameter spans across multiple lines we have to strip out the // line continuation -- jht 4/29/98 nsCAutoString tempStr(valueStart, valueEnd - valueStart); tempStr.StripChars("\r\n"); char *res = ToNewCString(tempStr); NS_ENSURE_TRUE(res, NS_ERROR_OUT_OF_MEMORY); if (isQuotedString) RemoveQuotedStringEscapes(res); caseAResult = res; // keep going, we may find a RFC 2231/5987 encoded alternative } // case B, C, and D else if (nameLen > paramLen && !nsCRT::strncasecmp(nameStart, aParamName, paramLen) && *(nameStart + paramLen) == '*') { // 1st char past '*' const char *cp = nameStart + paramLen + 1; // if param name ends in "*" we need do to RFC5987 "ext-value" decoding bool needExtDecoding = *(nameEnd - 1) == '*'; bool caseB = nameLen == paramLen + 1; bool caseCStart = (*cp == '0') && needExtDecoding; // parse the segment number PRInt32 segmentNumber = -1; if (!caseB) { PRInt32 segLen = (nameEnd - cp) - (needExtDecoding ? 1 : 0); segmentNumber = parseSegmentNumber(cp, segLen); if (segmentNumber == -1) { acceptContinuations = false; goto increment_str; } } // CaseB and start of CaseC: requires charset and optional language // in quotes (quotes required even if lang is blank) if (caseB || (caseCStart && acceptContinuations)) { // look for single quotation mark(') const char *sQuote1 = PL_strchr(valueStart, 0x27); const char *sQuote2 = sQuote1 ? PL_strchr(sQuote1 + 1, 0x27) : nullptr; // Two single quotation marks must be present even in // absence of charset and lang. if (!sQuote1 || !sQuote2) { NS_WARNING("Mandatory two single quotes are missing in header parameter\n"); } const char *charsetStart = NULL; PRInt32 charsetLength = 0; const char *langStart = NULL; PRInt32 langLength = 0; const char *rawValStart = NULL; PRInt32 rawValLength = 0; if (sQuote2 && sQuote1) { // both delimiters present: charSet'lang'rawVal rawValStart = sQuote2 + 1; rawValLength = valueEnd - rawValStart; langStart = sQuote1 + 1; langLength = sQuote2 - langStart; charsetStart = valueStart; charsetLength = sQuote1 - charsetStart; } else if (sQuote1) { // one delimiter; assume charset'rawVal rawValStart = sQuote1 + 1; rawValLength = valueEnd - rawValStart; charsetStart = valueStart; charsetLength = sQuote1 - valueStart; } else { // no delimiter: just rawVal rawValStart = valueStart; rawValLength = valueEnd - valueStart; } if (langLength != 0) { lang.Assign(langStart, langLength); } // keep the charset for later if (caseB) { charsetB.Assign(charsetStart, charsetLength); } else { // if caseCorD charsetCD.Assign(charsetStart, charsetLength); } // non-empty value part if (rawValLength > 0) { if (!caseBResult && caseB) { // allocate buffer for the raw value char *tmpResult = (char *) nsMemory::Clone(rawValStart, rawValLength + 1); if (!tmpResult) { goto increment_str; } *(tmpResult + rawValLength) = 0; nsUnescape(tmpResult); caseBResult = tmpResult; } else { // caseC bool added = addContinuation(segments, 0, rawValStart, rawValLength, needExtDecoding, isQuotedString); if (!added) { // continuation not added, stop processing them acceptContinuations = false; } } } } // end of if-block : title*0*= or title*= // caseD: a line of multiline param with no need for unescaping : title*[0-9]= // or 2nd or later lines of a caseC param : title*[1-9]*= else if (acceptContinuations && segmentNumber != -1) { PRUint32 valueLength = valueEnd - valueStart; bool added = addContinuation(segments, segmentNumber, valueStart, valueLength, needExtDecoding, isQuotedString); if (!added) { // continuation not added, stop processing them acceptContinuations = false; } } // end of if-block : title*[0-9]= or title*[1-9]*= } // str now points after the end of the value. // skip over whitespace, ';', whitespace. increment_str: while (nsCRT::IsAsciiSpace(*str)) ++str; if (*str == ';') { ++str; } else { // stop processing the header field; either we are done or the // separator was missing break; } while (nsCRT::IsAsciiSpace(*str)) ++str; } caseCDResult = combineContinuations(segments); if (caseBResult && !charsetB.IsEmpty()) { // check that the 2231/5987 result decodes properly given the // specified character set if (!IsValidOctetSequenceForCharset(charsetB, caseBResult)) caseBResult = NULL; } if (caseCDResult && !charsetCD.IsEmpty()) { // check that the 2231/5987 result decodes properly given the // specified character set if (!IsValidOctetSequenceForCharset(charsetCD, caseCDResult)) caseCDResult = NULL; } if (caseBResult) { // prefer simple 5987 format over 2231 with continuations *aResult = caseBResult; caseBResult = NULL; charset.Assign(charsetB); } else if (caseCDResult) { // prefer 2231/5987 with or without continuations over plain format *aResult = caseCDResult; caseCDResult = NULL; charset.Assign(charsetCD); } else if (caseAResult) { *aResult = caseAResult; caseAResult = NULL; } // free unused stuff nsMemory::Free(caseAResult); nsMemory::Free(caseBResult); nsMemory::Free(caseCDResult); // if we have a result if (*aResult) { // then return charset and lang as well if (aLang && !lang.IsEmpty()) { PRUint32 len = lang.Length(); *aLang = (char *) nsMemory::Clone(lang.BeginReading(), len + 1); if (*aLang) { *(*aLang + len) = 0; } } if (aCharset && !charset.IsEmpty()) { PRUint32 len = charset.Length(); *aCharset = (char *) nsMemory::Clone(charset.BeginReading(), len + 1); if (*aCharset) { *(*aCharset + len) = 0; } } } return *aResult ? NS_OK : NS_ERROR_INVALID_ARG; }
nsresult nsMIMEHeaderParamImpl::DoParameterInternal(const char *aHeaderValue, const char *aParamName, ParamDecoding aDecoding, char **aCharset, char **aLang, char **aResult) { if (!aHeaderValue || !*aHeaderValue || !aResult) return NS_ERROR_INVALID_ARG; *aResult = nsnull; if (aCharset) *aCharset = nsnull; if (aLang) *aLang = nsnull; const char *str = aHeaderValue; // skip leading white space. for (; *str && nsCRT::IsAsciiSpace(*str); ++str) ; const char *start = str; // aParamName is empty. return the first (possibly) _unnamed_ 'parameter' // For instance, return 'inline' in the following case: // Content-Disposition: inline; filename=..... if (!aParamName || !*aParamName) { for (; *str && *str != ';' && !nsCRT::IsAsciiSpace(*str); ++str) ; if (str == start) return NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY; *aResult = (char *) nsMemory::Clone(start, (str - start) + 1); NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); (*aResult)[str - start] = '\0'; // null-terminate return NS_OK; } /* Skip forward to first ';' */ for (; *str && *str != ';' && *str != ','; ++str) ; if (*str) str++; /* Skip over following whitespace */ for (; *str && nsCRT::IsAsciiSpace(*str); ++str) ; // Some broken http servers just specify parameters // like 'filename' without specifying disposition // method. Rewind to the first non-white-space // character. if (!*str) str = start; // RFC2231 - The legitimate parm format can be: // A. title=ThisIsTitle // B. title*=us-ascii'en-us'This%20is%20wierd. // C. title*0*=us-ascii'en'This%20is%20wierd.%20We // title*1*=have%20to%20support%20this. // title*2="Else..." // D. title*0="Hey, what you think you are doing?" // title*1="There is no charset and lang info." // RFC5987: only A and B PRInt32 paramLen = strlen(aParamName); bool haveCaseAValue = false; PRInt32 nextContinuation = 0; // next value in series, or -1 if error while (*str) { const char *tokenStart = str; const char *tokenEnd = 0; const char *valueStart = str; const char *valueEnd = 0; bool seenEquals = false; NS_ASSERTION(!nsCRT::IsAsciiSpace(*str), "should be after whitespace."); // Skip forward to the end of this token. for (; *str && !nsCRT::IsAsciiSpace(*str) && *str != '=' && *str != ';'; str++) ; tokenEnd = str; // Skip over whitespace, '=', and whitespace while (nsCRT::IsAsciiSpace(*str)) ++str; if (*str == '=') { ++str; seenEquals = true; } while (nsCRT::IsAsciiSpace(*str)) ++str; bool needUnquote = false; if (*str != '"') { // The value is a token, not a quoted string. valueStart = str; for (valueEnd = str; *valueEnd && !nsCRT::IsAsciiSpace (*valueEnd) && *valueEnd != ';'; valueEnd++) ; str = valueEnd; } else { // The value is a quoted string. needUnquote = true; ++str; valueStart = str; for (valueEnd = str; *valueEnd; ++valueEnd) { if (*valueEnd == '\\') ++valueEnd; else if (*valueEnd == '"') break; } str = valueEnd + 1; } // See if this is the simplest case (case A above), // a 'single' line value with no charset and lang. // If so, copy it and return. if (tokenEnd - tokenStart == paramLen && seenEquals && !nsCRT::strncasecmp(tokenStart, aParamName, paramLen)) { if (*aResult) { // either seen earlier caseA value already--we prefer first--or caseA // came after a continuation: either way, prefer other value goto increment_str; } // if the parameter spans across multiple lines we have to strip out the // line continuation -- jht 4/29/98 nsCAutoString tempStr(valueStart, valueEnd - valueStart); tempStr.StripChars("\r\n"); char *res = ToNewCString(tempStr); NS_ENSURE_TRUE(res, NS_ERROR_OUT_OF_MEMORY); if (needUnquote) RemoveQuotedStringEscapes(res); *aResult = res; haveCaseAValue = true; // keep going, we may find a RFC 2231/5987 encoded alternative } // case B, C, and D else if (tokenEnd - tokenStart > paramLen && !nsCRT::strncasecmp(tokenStart, aParamName, paramLen) && seenEquals && *(tokenStart + paramLen) == '*') { const char *cp = tokenStart + paramLen + 1; // 1st char past '*' bool needUnescape = *(tokenEnd - 1) == '*'; bool caseB = (tokenEnd - tokenStart) == paramLen + 1; bool caseCorDStart = (*cp == '0') && needUnescape; bool acceptContinuations = (aDecoding != RFC_5987_DECODING); // CaseB and start of CaseC: requires charset and optional language // in quotes (quotes required even if lang is blank) if (caseB || (caseCorDStart && acceptContinuations)) { if (caseCorDStart) { if (nextContinuation++ != 0) { // error: already started a continuation. Skip future // continuations and return whatever initial parts were in order. nextContinuation = -1; goto increment_str; } } // look for single quotation mark(') const char *sQuote1 = PL_strchr(valueStart, 0x27); const char *sQuote2 = (char *) (sQuote1 ? PL_strchr(sQuote1 + 1, 0x27) : nsnull); // Two single quotation marks must be present even in // absence of charset and lang. if (!sQuote1 || !sQuote2) { // log the warning and skip to next parameter NS_WARNING("Mandatory two single quotes are missing in header parameter, parameter ignored\n"); goto increment_str; } // charset part is required if (! (sQuote1 > valueStart && sQuote1 < valueEnd)) { // log the warning and skip to next parameter NS_WARNING("Mandatory charset part missing in header parameter, parameter ignored\n"); goto increment_str; } if (aCharset) { *aCharset = (char *) nsMemory::Clone(valueStart, sQuote1 - valueStart + 1); if (*aCharset) *(*aCharset + (sQuote1 - valueStart)) = 0; } if (aLang && sQuote2 > sQuote1 + 1 && sQuote2 < valueEnd) { *aLang = (char *) nsMemory::Clone(sQuote1 + 1, sQuote2 - (sQuote1 + 1) + 1); if (*aLang) *(*aLang + (sQuote2 - (sQuote1 + 1))) = 0; } if (sQuote2 + 1 < valueEnd) { if (*aResult) { // caseA value already read, or caseC/D value already read // but we're now reading caseB: either way, drop old value nsMemory::Free(*aResult); haveCaseAValue = false; } *aResult = (char *) nsMemory::Alloc(valueEnd - (sQuote2 + 1) + 1); if (*aResult) { memcpy(*aResult, sQuote2 + 1, valueEnd - (sQuote2 + 1)); *(*aResult + (valueEnd - (sQuote2 + 1))) = 0; if (needUnescape) { nsUnescape(*aResult); if (caseB) return NS_OK; // caseB wins over everything else } } } } // end of if-block : title*0*= or title*= // caseD: a line of multiline param with no need for unescaping : title*[0-9]= // or 2nd or later lines of a caseC param : title*[1-9]*= else if (acceptContinuations && nsCRT::IsAsciiDigit(PRUnichar(*cp))) { PRInt32 nextSegment = atoi(cp); // no leading zeros allowed except for ... position 0 bool broken = nextSegment > 0 && *cp == '0'; if (broken || nextSegment != nextContinuation++) { // error: gap in continuation or unneccessary leading 0. // Skip future continuations and return whatever initial parts were // in order. nextContinuation = -1; goto increment_str; } if (haveCaseAValue && *aResult) { // drop caseA value nsMemory::Free(*aResult); *aResult = 0; haveCaseAValue = false; } PRInt32 len = 0; if (*aResult) // 2nd or later lines of multiline parameter { len = strlen(*aResult); char *ns = (char *) nsMemory::Realloc(*aResult, len + (valueEnd - valueStart) + 1); if (!ns) { nsMemory::Free(*aResult); } *aResult = ns; } else { NS_ASSERTION(*cp == '0', "Not first value in continuation"); // must be; 1st line : title*0= *aResult = (char *) nsMemory::Alloc(valueEnd - valueStart + 1); } if (*aResult) { // append a partial value memcpy(*aResult + len, valueStart, valueEnd - valueStart); *(*aResult + len + (valueEnd - valueStart)) = 0; if (needUnescape) nsUnescape(*aResult + len); } else return NS_ERROR_OUT_OF_MEMORY; } // end of if-block : title*[0-9]= or title*[1-9]*= } // str now points after the end of the value. // skip over whitespace, ';', whitespace. increment_str: while (nsCRT::IsAsciiSpace(*str)) ++str; if (*str == ';') ++str; while (nsCRT::IsAsciiSpace(*str)) ++str; } if (*aResult) return NS_OK; else return NS_ERROR_INVALID_ARG; // aParameter not found !! }
nsresult nsMsgAttachmentHandler::UrlExit(nsresult status, const PRUnichar* aMsg) { NS_ASSERTION(m_mime_delivery_state != nsnull, "not-null m_mime_delivery_state"); // Close the file, but don't delete the disk file (or the file spec.) if (mOutFile) { mOutFile->Close(); mOutFile = nsnull; } // this silliness is because Windows nsILocalFile caches its file size // so if an output stream writes to it, it will still return the original // cached size. if (mTmpFile) { nsCOMPtr <nsIFile> tmpFile; mTmpFile->Clone(getter_AddRefs(tmpFile)); mTmpFile = do_QueryInterface(tmpFile); } mRequest = nsnull; // First things first, we are now going to see if this is an HTML // Doc and if it is, we need to see if we can determine the charset // for this part by sniffing the HTML file. // This is needed only when the charset is not set already. // (e.g. a charset may be specified in HTTP header) // if ( (m_type) && (*m_type) && (!m_charset || !(*m_charset)) ) { if (PL_strcasecmp(m_type, TEXT_HTML) == 0) { char *tmpCharset = (char *)nsMsgI18NParseMetaCharset(mTmpFile); if (tmpCharset[0] != '\0') { PR_Free(m_charset); m_charset = PL_strdup(tmpCharset); } } } nsresult mimeDeliveryStatus; m_mime_delivery_state->GetStatus(&mimeDeliveryStatus); if (mimeDeliveryStatus == NS_ERROR_ABORT) status = NS_ERROR_ABORT; if (NS_FAILED(status) && status != NS_ERROR_ABORT && NS_SUCCEEDED(mimeDeliveryStatus)) { // At this point, we should probably ask a question to the user // if we should continue without this attachment. // PRBool keepOnGoing = PR_TRUE; nsCString turl; nsString msg; PRUnichar *printfString = nsnull; nsresult rv; nsCOMPtr<nsIStringBundleService> bundleService(do_GetService("@mozilla.org/intl/stringbundle;1", &rv)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIStringBundle> bundle; rv = bundleService->CreateBundle("chrome://messenger/locale/messengercompose/composeMsgs.properties", getter_AddRefs(bundle)); NS_ENSURE_SUCCESS(rv, rv); nsMsgDeliverMode mode = nsIMsgSend::nsMsgDeliverNow; m_mime_delivery_state->GetDeliveryMode(&mode); if (mode == nsIMsgSend::nsMsgSaveAsDraft || mode == nsIMsgSend::nsMsgSaveAsTemplate) bundle->GetStringFromID(NS_MSG_FAILURE_ON_OBJ_EMBED_WHILE_SAVING, getter_Copies(msg)); else bundle->GetStringFromID(NS_MSG_FAILURE_ON_OBJ_EMBED_WHILE_SENDING, getter_Copies(msg)); if (m_real_name && *m_real_name) printfString = nsTextFormatter::smprintf(msg.get(), m_real_name); else if (NS_SUCCEEDED(mURL->GetSpec(turl)) && !turl.IsEmpty()) { nsCAutoString unescapeUrl(turl); nsUnescape(unescapeUrl.BeginWriting()); if (unescapeUrl.IsEmpty()) printfString = nsTextFormatter::smprintf(msg.get(), turl.get()); else printfString = nsTextFormatter::smprintf(msg.get(), unescapeUrl.get()); } else printfString = nsTextFormatter::smprintf(msg.get(), "?"); nsCOMPtr<nsIPrompt> aPrompt; if (m_mime_delivery_state) m_mime_delivery_state->GetDefaultPrompt(getter_AddRefs(aPrompt)); nsMsgAskBooleanQuestionByString(aPrompt, printfString, &keepOnGoing); PR_FREEIF(printfString); if (keepOnGoing) { status = 0; m_bogus_attachment = PR_TRUE; //That will cause this attachment to be ignored. } else { status = NS_ERROR_ABORT; m_mime_delivery_state->SetStatus(status); nsresult ignoreMe; m_mime_delivery_state->Fail(status, nsnull, &ignoreMe); m_mime_delivery_state->NotifyListenerOnStopSending(nsnull, status, 0, nsnull); SetMimeDeliveryState(nsnull); return status; } } m_done = PR_TRUE; // // Ok, now that we have the file here on disk, we need to see if there was // a need to do conversion to plain text...if so, the magic happens here, // otherwise, just move on to other attachments... // if (NS_SUCCEEDED(status) && m_type && PL_strcasecmp(m_type, TEXT_PLAIN) ) { if (m_desired_type && !PL_strcasecmp(m_desired_type, TEXT_PLAIN) ) { // // Conversion to plain text desired. // PRInt32 width = 72; nsCOMPtr<nsIPrefBranch> pPrefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID)); if (pPrefBranch) pPrefBranch->GetIntPref("mailnews.wraplength", &width); // Let sanity reign! if (width == 0) width = 72; else if (width < 10) width = 10; else if (width > 30000) width = 30000; // // Now use the converter service here to do the right // thing and convert this data to plain text for us! // nsAutoString conData; if (NS_SUCCEEDED(LoadDataFromFile(mTmpFile, conData, PR_TRUE))) { if (NS_SUCCEEDED(ConvertBufToPlainText(conData, UseFormatFlowed(m_charset)))) { if (mDeleteFile) mTmpFile->Remove(PR_FALSE); nsCOMPtr<nsIOutputStream> outputStream; nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), mTmpFile, PR_WRONLY | PR_CREATE_FILE, 00600); if (NS_SUCCEEDED(rv)) { nsCAutoString tData; if (NS_FAILED(ConvertFromUnicode(m_charset, conData, tData))) LossyCopyUTF16toASCII(conData, tData); if (!tData.IsEmpty()) { PRUint32 bytesWritten; (void) outputStream->Write(tData.get(), tData.Length(), &bytesWritten); } outputStream->Close(); // this silliness is because Windows nsILocalFile caches its file size // so if an output stream writes to it, it will still return the original // cached size. if (mTmpFile) { nsCOMPtr <nsIFile> tmpFile; mTmpFile->Clone(getter_AddRefs(tmpFile)); mTmpFile = do_QueryInterface(tmpFile); } } } } PR_FREEIF(m_type); m_type = m_desired_type; m_desired_type = nsnull; PR_FREEIF(m_encoding); m_encoding = nsnull; } } PRUint32 pendingAttachmentCount = 0; m_mime_delivery_state->GetPendingAttachmentCount(&pendingAttachmentCount); NS_ASSERTION (pendingAttachmentCount > 0, "no more pending attachment"); m_mime_delivery_state->SetPendingAttachmentCount(pendingAttachmentCount - 1); PRBool processAttachmentsSynchronously = PR_FALSE; m_mime_delivery_state->GetProcessAttachmentsSynchronously(&processAttachmentsSynchronously); if (NS_SUCCEEDED(status) && processAttachmentsSynchronously) { /* Find the next attachment which has not yet been loaded, if any, and start it going. */ PRUint32 i; nsMsgAttachmentHandler *next = 0; nsMsgAttachmentHandler *attachments = nsnull; PRUint32 attachmentCount = 0; m_mime_delivery_state->GetAttachmentCount(&attachmentCount); if (attachmentCount) m_mime_delivery_state->GetAttachmentHandlers(&attachments); for (i = 0; i < attachmentCount; i++) { if (!attachments[i].m_done) { next = &attachments[i]; // // rhp: We need to get a little more understanding to failed URL // requests. So, at this point if most of next is NULL, then we // should just mark it fetched and move on! We probably ignored // this earlier on in the send process. // if ( (!next->mURL) && (!next->m_uri) ) { attachments[i].m_done = PR_TRUE; m_mime_delivery_state->GetPendingAttachmentCount(&pendingAttachmentCount); m_mime_delivery_state->SetPendingAttachmentCount(pendingAttachmentCount - 1); next->mPartUserOmissionOverride = PR_TRUE; next = nsnull; continue; } break; } } if (next) { int status = next->SnarfAttachment(mCompFields); if (NS_FAILED(status)) { nsresult ignoreMe; m_mime_delivery_state->Fail(status, nsnull, &ignoreMe); m_mime_delivery_state->NotifyListenerOnStopSending(nsnull, status, 0, nsnull); SetMimeDeliveryState(nsnull); return NS_ERROR_UNEXPECTED; } } } m_mime_delivery_state->GetPendingAttachmentCount(&pendingAttachmentCount); if (pendingAttachmentCount == 0) { // If this is the last attachment, then either complete the // delivery (if successful) or report the error by calling // the exit routine and terminating the delivery. if (NS_FAILED(status)) { nsresult ignoreMe; m_mime_delivery_state->Fail(status, aMsg, &ignoreMe); m_mime_delivery_state->NotifyListenerOnStopSending(nsnull, status, aMsg, nsnull); SetMimeDeliveryState(nsnull); return NS_ERROR_UNEXPECTED; } else { status = m_mime_delivery_state->GatherMimeAttachments (); if (NS_FAILED(status)) { nsresult ignoreMe; m_mime_delivery_state->Fail(status, aMsg, &ignoreMe); m_mime_delivery_state->NotifyListenerOnStopSending(nsnull, status, aMsg, nsnull); SetMimeDeliveryState(nsnull); return NS_ERROR_UNEXPECTED; } } } else { // If this is not the last attachment, but it got an error, // then report that error and continue if (NS_FAILED(status)) { nsresult ignoreMe; m_mime_delivery_state->Fail(status, aMsg, &ignoreMe); } } SetMimeDeliveryState(nsnull); return NS_OK; }
nsresult nsDirIndexParser::ParseData(nsIDirIndex *aIdx, char* aDataStr) { // Parse a "201" data line, using the field ordering specified in // mFormat. if (!mFormat) { // Ignore if we haven't seen a format yet. return NS_OK; } nsresult rv = NS_OK; nsCAutoString filename; for (PRInt32 i = 0; mFormat[i] != -1; ++i) { // If we've exhausted the data before we run out of fields, just // bail. if (! *aDataStr) break; while (*aDataStr && nsCRT::IsAsciiSpace(*aDataStr)) ++aDataStr; char *value = aDataStr; if (*aDataStr == '"' || *aDataStr == '\'') { // it's a quoted string. snarf everything up to the next quote character const char quotechar = *(aDataStr++); ++value; while (*aDataStr && *aDataStr != quotechar) ++aDataStr; *aDataStr++ = '\0'; if (! aDataStr) { NS_WARNING("quoted value not terminated"); } } else { // it's unquoted. snarf until we see whitespace. value = aDataStr; while (*aDataStr && (!nsCRT::IsAsciiSpace(*aDataStr))) ++aDataStr; *aDataStr++ = '\0'; } fieldType t = fieldType(mFormat[i]); switch (t) { case FIELD_FILENAME: { // don't unescape at this point, so that UnEscapeAndConvert() can filename = value; PRBool success = PR_FALSE; nsAutoString entryuri; if (gTextToSubURI) { PRUnichar *result = nsnull; if (NS_SUCCEEDED(rv = gTextToSubURI->UnEscapeAndConvert(mEncoding.get(), filename.get(), &result)) && (result)) { if (*result) { aIdx->SetLocation(filename.get()); if (!mHasDescription) aIdx->SetDescription(result); success = PR_TRUE; } NS_Free(result); } else { NS_WARNING("UnEscapeAndConvert error"); } } if (!success) { // if unsuccessfully at charset conversion, then // just fallback to unescape'ing in-place // XXX - this shouldn't be using UTF8, should it? // when can we fail to get the service, anyway? - bbaetz aIdx->SetLocation(filename.get()); if (!mHasDescription) { aIdx->SetDescription(NS_ConvertUTF8toUTF16(value).get()); } } } break; case FIELD_DESCRIPTION: nsUnescape(value); aIdx->SetDescription(NS_ConvertUTF8toUTF16(value).get()); break; case FIELD_CONTENTLENGTH: { PRInt64 len; PRInt32 status = PR_sscanf(value, "%lld", &len); if (status == 1) aIdx->SetSize(len); else aIdx->SetSize(LL_MAXUINT); // LL_MAXUINT means unknown } break; case FIELD_LASTMODIFIED: { PRTime tm; nsUnescape(value); if (PR_ParseTimeString(value, PR_FALSE, &tm) == PR_SUCCESS) { aIdx->SetLastModified(tm); } } break; case FIELD_CONTENTTYPE: aIdx->SetContentType(value); break; case FIELD_FILETYPE: // unescape in-place nsUnescape(value); if (!nsCRT::strcasecmp(value, "directory")) { aIdx->SetType(nsIDirIndex::TYPE_DIRECTORY); } else if (!nsCRT::strcasecmp(value, "file")) { aIdx->SetType(nsIDirIndex::TYPE_FILE); } else if (!nsCRT::strcasecmp(value, "symbolic-link")) { aIdx->SetType(nsIDirIndex::TYPE_SYMLINK); } else { aIdx->SetType(nsIDirIndex::TYPE_UNKNOWN); } break; case FIELD_UNKNOWN: // ignore break; } } return NS_OK; }
nsresult nsImapURI2Path(const char* rootURI, const char* uriStr, nsILocalFile **pathResult) { nsresult rv; nsCOMPtr<nsIURL> url; url = do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; nsCAutoString uri(uriStr); if (uri.Find(rootURI) != 0) // if doesn't start with rootURI return NS_ERROR_FAILURE; if ((PL_strcmp(rootURI, kImapRootURI) != 0) && (PL_strcmp(rootURI, kImapMessageRootURI) != 0)) { *pathResult = nsnull; rv = NS_ERROR_FAILURE; } // Set our url to the string given rv = url->SetSpec(nsDependentCString(uriStr)); if (NS_FAILED(rv)) return rv; // Set the folder to the url path nsCAutoString folder; rv = url->GetPath(folder); // can't have leading '/' in path if (folder.CharAt(0) == '/') folder.Cut(0, 1); const char *curPos = uriStr + PL_strlen(rootURI); nsCAutoString newPath(""); if (curPos) { // advance past hostname while (*curPos && (*curPos)!='/') curPos++; char *unescaped = NS_strdup(curPos); if (unescaped) { nsUnescape(unescaped); NS_MsgCreatePathStringFromFolderURI(unescaped, newPath); NS_Free(unescaped); } else NS_MsgCreatePathStringFromFolderURI(curPos, newPath); } // Now find the server from the URL nsCOMPtr<nsIMsgIncomingServer> server; nsCOMPtr<nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv); if(NS_FAILED(rv)) return rv; rv = accountManager->FindServerByURI(url, PR_FALSE, getter_AddRefs(server)); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsILocalFile> localPath; if (server) { rv = server->GetLocalPath(getter_AddRefs(localPath)); NS_ENSURE_SUCCESS(rv, rv); // This forces the creation of the parent server directory // so that we don't get imapservername.sbd instead // when the host directory has been deleted. See bug 210683 localPath->Create(nsIFile::DIRECTORY_TYPE, 0700); } if (NS_FAILED(rv)) { pathResult = nsnull; return rv; } localPath->AppendRelativeNativePath(newPath); NS_IF_ADDREF(*pathResult = localPath); return NS_OK; }
nsresult nsMailtoUrl::ParseMailtoUrl(char * searchPart) { char *rest = searchPart; nsCAutoString inReplyToPart; // okay, first, free up all of our old search part state..... CleanupMailtoState(); if (rest && *rest == '?') { /* start past the '?' */ rest++; } if (rest) { char *token = nsCRT::strtok(rest, "&", &rest); while (token && *token) { char *value = 0; char *eq = PL_strchr(token, '='); if (eq) { value = eq+1; *eq = 0; } switch (nsCRT::ToUpper(*token)) { /* DO NOT support attachment= in mailto urls. This poses a security fire hole!!! case 'A': if (!nsCRT::strcasecmp (token, "attachment")) m_attachmentPart = value; break; */ case 'B': if (!nsCRT::strcasecmp (token, "bcc")) { if (!m_bccPart.IsEmpty()) { m_bccPart += ", "; m_bccPart += value; } else m_bccPart = value; } else if (!nsCRT::strcasecmp (token, "body")) { if (!m_bodyPart.IsEmpty()) { m_bodyPart +="\n"; m_bodyPart += value; } else m_bodyPart = value; } break; case 'C': if (!nsCRT::strcasecmp (token, "cc")) { if (!m_ccPart.IsEmpty()) { m_ccPart += ", "; m_ccPart += value; } else m_ccPart = value; } break; case 'F': if (!nsCRT::strcasecmp (token, "followup-to")) m_followUpToPart = value; else if (!nsCRT::strcasecmp (token, "from")) m_fromPart = value; break; case 'H': if (!nsCRT::strcasecmp(token, "html-part") || !nsCRT::strcasecmp (token, "html-body")) { // m_htmlPart holds the body for both html-part and html-body. m_htmlPart = value; mFormat = nsIMsgCompFormat::HTML; } break; case 'I': if (!nsCRT::strcasecmp (token, "in-reply-to")) inReplyToPart = value; break; case 'N': if (!nsCRT::strcasecmp (token, "newsgroups")) m_newsgroupPart = value; else if (!nsCRT::strcasecmp (token, "newshost")) m_newsHostPart = value; break; case 'O': if (!nsCRT::strcasecmp (token, "organization")) m_organizationPart = value; break; case 'R': if (!nsCRT::strcasecmp (token, "references")) m_referencePart = value; else if (!nsCRT::strcasecmp (token, "reply-to")) m_replyToPart = value; break; case 'S': if(!nsCRT::strcasecmp (token, "subject")) m_subjectPart = value; break; case 'P': if (!nsCRT::strcasecmp (token, "priority")) m_priorityPart = PL_strdup(value); break; case 'T': if (!nsCRT::strcasecmp (token, "to")) { if (!m_toPart.IsEmpty()) { m_toPart += ", "; m_toPart += value; } else m_toPart = value; } break; default: break; } // end of switch statement... if (eq) *eq = '='; /* put it back */ token = nsCRT::strtok(rest, "&", &rest); } // while we still have part of the url to parse... } // if rest && *rest // Ensure that References and In-Reply-To are consistent... if (!inReplyToPart.IsEmpty()) { if (m_referencePart.IsEmpty()) m_referencePart = inReplyToPart; else { const char * lastRef = strrchr(m_referencePart.get(), '<'); nsCAutoString lastReference; lastReference = lastRef ? lastRef : m_referencePart.get(); if (lastReference != inReplyToPart) { m_referencePart += " "; m_referencePart += inReplyToPart; } } } nsCOMPtr<nsIMimeConverter> mimeConverter = do_GetService(NS_MIME_CONVERTER_CONTRACTID); char *decodedString; // Now unescape any fields that need escaped... if (!m_toPart.IsEmpty()) { nsUnescape(m_toPart.BeginWriting()); if (mimeConverter) { if (NS_SUCCEEDED(mimeConverter->DecodeMimeHeader(m_toPart.get(), &decodedString, "UTF-8", PR_FALSE)) && decodedString) m_toPart.Adopt(decodedString); } } if (!m_ccPart.IsEmpty()) { nsUnescape(m_ccPart.BeginWriting()); if (mimeConverter) { if (NS_SUCCEEDED(mimeConverter->DecodeMimeHeader(m_ccPart.get(), &decodedString, "UTF-8", PR_FALSE)) && decodedString) m_ccPart.Adopt(decodedString); } } if (!m_subjectPart.IsEmpty()) { nsUnescape(m_subjectPart.BeginWriting()); if (mimeConverter) { if (NS_SUCCEEDED(mimeConverter->DecodeMimeHeader(m_subjectPart.get(), &decodedString, "UTF-8", PR_FALSE)) && decodedString) m_subjectPart.Adopt(decodedString); } } if (!m_newsgroupPart.IsEmpty()) nsUnescape(m_newsgroupPart.BeginWriting()); if (!m_referencePart.IsEmpty()) nsUnescape(m_referencePart.BeginWriting()); if (!m_bodyPart.IsEmpty()) { nsUnescape(m_bodyPart.BeginWriting()); if (mimeConverter) { if (NS_SUCCEEDED(mimeConverter->DecodeMimeHeader(m_bodyPart.get(), &decodedString, "UTF-8", PR_FALSE, PR_FALSE)) && decodedString) m_bodyPart.Adopt(decodedString); } } if (!m_newsHostPart.IsEmpty()) nsUnescape(m_newsHostPart.BeginWriting()); return NS_OK; }
nsresult nsMsgAttachmentHandler::SnarfAttachment(nsMsgCompFields *compFields) { NS_ASSERTION (! m_done, "Already done"); if (!mURL) return SnarfMsgAttachment(compFields); mCompFields = compFields; // First, get as file spec and create the stream for the // temp file where we will save this data nsCOMPtr <nsIFile> tmpFile; nsresult rv = nsMsgCreateTempFile("nsmail.tmp", getter_AddRefs(tmpFile)); NS_ENSURE_SUCCESS(rv, rv); mTmpFile = do_QueryInterface(tmpFile); mDeleteFile = PR_TRUE; nsCOMPtr<nsIOutputStream> outputStream; rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), mTmpFile, -1, 00600); if (NS_FAILED(rv) || !outputStream) { if (m_mime_delivery_state) { nsCOMPtr<nsIMsgSendReport> sendReport; m_mime_delivery_state->GetSendReport(getter_AddRefs(sendReport)); if (sendReport) { nsAutoString error_msg; nsAutoString path; mTmpFile->GetPath(path); nsMsgBuildErrorMessageByID(NS_MSG_UNABLE_TO_OPEN_TMP_FILE, error_msg, &path, nsnull); sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), PR_FALSE); } } mTmpFile->Remove(PR_FALSE); mTmpFile = nsnull; return NS_MSG_UNABLE_TO_OPEN_TMP_FILE; } mOutFile = do_QueryInterface(outputStream); nsCString sourceURISpec; mURL->GetSpec(sourceURISpec); #ifdef XP_MACOSX if (!m_bogus_attachment && StringBeginsWith(sourceURISpec, NS_LITERAL_CSTRING("file://"))) { // Unescape the path (i.e. un-URLify it) before making a FSSpec nsCAutoString filePath; filePath.Adopt(nsMsgGetLocalFileFromURL(sourceURISpec.get())); nsUnescape(filePath.BeginWriting()); nsCOMPtr<nsILocalFile> sourceFile; NS_NewNativeLocalFile(filePath, PR_TRUE, getter_AddRefs(sourceFile)); if (!sourceFile) return NS_ERROR_FAILURE; // check if it is a bundle. if it is, we'll zip it. // if not, we'll apple encode it (applesingle or appledouble) nsCOMPtr<nsILocalFileMac> macFile(do_QueryInterface(sourceFile)); PRBool isPackage; macFile->IsPackage(&isPackage); if (isPackage) rv = ConvertToZipFile(macFile); else rv = ConvertToAppleEncoding(sourceURISpec, filePath, macFile); NS_ENSURE_SUCCESS(rv, rv); } #endif /* XP_MACOSX */ // // Ok, here we are, we need to fire the URL off and get the data // in the temp file // // Create a fetcher for the URL attachment... nsCOMPtr<nsIURLFetcher> fetcher = do_CreateInstance(NS_URLFETCHER_CONTRACTID, &rv); if (NS_FAILED(rv) || !fetcher) { if (NS_SUCCEEDED(rv)) return NS_ERROR_UNEXPECTED; else return rv; } return fetcher->FireURLRequest(mURL, mTmpFile, mOutFile, FetcherURLDoneCallback, this); }
nsresult nsDirIndexParser::ProcessData(nsIRequest *aRequest, nsISupports *aCtxt) { if (!mListener) return NS_ERROR_FAILURE; PRInt32 numItems = 0; while(PR_TRUE) { ++numItems; PRInt32 eol = mBuf.FindCharInSet("\n\r", mLineStart); if (eol < 0) break; mBuf.SetCharAt(PRUnichar('\0'), eol); const char *line = mBuf.get() + mLineStart; PRInt32 lineLen = eol - mLineStart; mLineStart = eol + 1; if (lineLen >= 4) { nsresult rv; const char *buf = line; if (buf[0] == '1') { if (buf[1] == '0') { if (buf[2] == '0' && buf[3] == ':') { // 100. Human-readable comment line. Ignore } else if (buf[2] == '1' && buf[3] == ':') { // 101. Human-readable information line. mComment.Append(buf + 4); char *value = ((char *)buf) + 4; nsUnescape(value); mListener->OnInformationAvailable(aRequest, aCtxt, NS_ConvertUTF8toUTF16(value)); } else if (buf[2] == '2' && buf[3] == ':') { // 102. Human-readable information line, HTML. mComment.Append(buf + 4); } } } else if (buf[0] == '2') { if (buf[1] == '0') { if (buf[2] == '0' && buf[3] == ':') { // 200. Define field names rv = ParseFormat(buf + 4); if (NS_FAILED(rv)) { return rv; } } else if (buf[2] == '1' && buf[3] == ':') { // 201. Field data nsCOMPtr<nsIDirIndex> idx = do_CreateInstance("@mozilla.org/dirIndex;1",&rv); if (NS_FAILED(rv)) return rv; rv = ParseData(idx, ((char *)buf) + 4); if (NS_FAILED(rv)) { return rv; } mListener->OnIndexAvailable(aRequest, aCtxt, idx); } } } else if (buf[0] == '3') { if (buf[1] == '0') { if (buf[2] == '0' && buf[3] == ':') { // 300. Self-referring URL } else if (buf[2] == '1' && buf[3] == ':') { // 301. OUR EXTENSION - encoding int i = 4; while (buf[i] && nsCRT::IsAsciiSpace(buf[i])) ++i; if (buf[i]) SetEncoding(buf+i); } } } } } return NS_OK; }
// moved almost verbatim from mimehdrs.cpp // char * // MimeHeaders_get_parameter (const char *header_value, const char *parm_name, // char **charset, char **language) // // The format of these header lines is // <token> [ ';' <token> '=' <token-or-quoted-string> ]* NS_IMETHODIMP nsMIMEHeaderParamImpl::GetParameterInternal(const char *aHeaderValue, const char *aParamName, char **aCharset, char **aLang, char **aResult) { if (!aHeaderValue || !*aHeaderValue || !aResult) return NS_ERROR_INVALID_ARG; *aResult = nsnull; if (aCharset) *aCharset = nsnull; if (aLang) *aLang = nsnull; const char *str = aHeaderValue; // skip leading white space. for (; *str && nsCRT::IsAsciiSpace(*str); ++str) ; const char *start = str; // aParamName is empty. return the first (possibly) _unnamed_ 'parameter' // For instance, return 'inline' in the following case: // Content-Disposition: inline; filename=..... if (!aParamName || !*aParamName) { for (; *str && *str != ';' && !nsCRT::IsAsciiSpace(*str); ++str) ; if (str == start) return NS_ERROR_UNEXPECTED; *aResult = (char *) nsMemory::Clone(start, (str - start) + 1); NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); (*aResult)[str - start] = '\0'; // null-terminate return NS_OK; } /* Skip forward to first ';' */ for (; *str && *str != ';' && *str != ','; ++str) ; if (*str) str++; /* Skip over following whitespace */ for (; *str && nsCRT::IsAsciiSpace(*str); ++str) ; // Some broken http servers just specify parameters // like 'filename' without specifying disposition // method. Rewind to the first non-white-space // character. if (!*str) str = start; // RFC2231 - The legitimate parm format can be: // A. title=ThisIsTitle // B. title*=us-ascii'en-us'This%20is%20wierd. // C. title*0*=us-ascii'en'This%20is%20wierd.%20We // title*1*=have%20to%20support%20this. // title*2="Else..." // D. title*0="Hey, what you think you are doing?" // title*1="There is no charset and lang info." PRInt32 paramLen = strlen(aParamName); while (*str) { const char *tokenStart = str; const char *tokenEnd = 0; const char *valueStart = str; const char *valueEnd = 0; NS_ASSERTION(!nsCRT::IsAsciiSpace(*str), "should be after whitespace."); // Skip forward to the end of this token. for (; *str && !nsCRT::IsAsciiSpace(*str) && *str != '=' && *str != ';'; str++) ; tokenEnd = str; // Skip over whitespace, '=', and whitespace while (nsCRT::IsAsciiSpace(*str)) ++str; if (*str == '=') ++str; while (nsCRT::IsAsciiSpace(*str)) ++str; if (*str != '"') { // The value is a token, not a quoted string. valueStart = str; for (valueEnd = str; *valueEnd && !nsCRT::IsAsciiSpace (*valueEnd) && *valueEnd != ';'; valueEnd++) ; str = valueEnd; } else { // The value is a quoted string. ++str; valueStart = str; for (valueEnd = str; *valueEnd; ++valueEnd) { if (*valueEnd == '\\') ++valueEnd; else if (*valueEnd == '"') break; } str = valueEnd + 1; } // See if this is the simplest case (case A above), // a 'single' line value with no charset and lang. // If so, copy it and return. if (tokenEnd - tokenStart == paramLen && !nsCRT::strncasecmp(tokenStart, aParamName, paramLen)) { // if the parameter spans across multiple lines we have to strip out the // line continuation -- jht 4/29/98 nsCAutoString tempStr(valueStart, valueEnd - valueStart); tempStr.StripChars("\r\n"); *aResult = ToNewCString(tempStr); NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); return NS_OK; } // case B, C, and D else if (tokenEnd - tokenStart > paramLen && !nsCRT::strncasecmp(tokenStart, aParamName, paramLen) && *(tokenStart + paramLen) == '*') { const char *cp = tokenStart + paramLen + 1; // 1st char pass '*' PRBool needUnescape = *(tokenEnd - 1) == '*'; // the 1st line of a multi-line parameter or a single line that needs // unescaping. ( title*0*= or title*= ) if ((*cp == '0' && needUnescape) || (tokenEnd - tokenStart == paramLen + 1)) { // look for single quotation mark(') const char *sQuote1 = PL_strchr(valueStart, 0x27); const char *sQuote2 = (char *) (sQuote1 ? PL_strchr(sQuote1 + 1, 0x27) : nsnull); // Two single quotation marks must be present even in // absence of charset and lang. if (!sQuote1 || !sQuote2) NS_WARNING("Mandatory two single quotes are missing in header parameter\n"); if (aCharset && sQuote1 > valueStart && sQuote1 < valueEnd) { *aCharset = (char *) nsMemory::Clone(valueStart, sQuote1 - valueStart + 1); if (*aCharset) *(*aCharset + (sQuote1 - valueStart)) = 0; } if (aLang && sQuote1 && sQuote2 && sQuote2 > sQuote1 + 1 && sQuote2 < valueEnd) { *aLang = (char *) nsMemory::Clone(sQuote1 + 1, sQuote2 - (sQuote1 + 1) + 1); if (*aLang) *(*aLang + (sQuote2 - (sQuote1 + 1))) = 0; } // Be generous and handle gracefully when required // single quotes are absent. if (sQuote1) { if(!sQuote2) sQuote2 = sQuote1; } else sQuote2 = valueStart - 1; if (sQuote2 && sQuote2 + 1 < valueEnd) { NS_ASSERTION(!*aResult, "This is the 1st line. result buffer should be null."); *aResult = (char *) nsMemory::Alloc(valueEnd - (sQuote2 + 1) + 1); if (*aResult) { memcpy(*aResult, sQuote2 + 1, valueEnd - (sQuote2 + 1)); *(*aResult + (valueEnd - (sQuote2 + 1))) = 0; if (needUnescape) { nsUnescape(*aResult); if (tokenEnd - tokenStart == paramLen + 1) // we're done; this is case B return NS_OK; } } } } // end of if-block : title*0*= or title*= // a line of multiline param with no need for unescaping : title*[0-9]= // or 2nd or later lines of a multiline param : title*[1-9]*= else if (nsCRT::IsAsciiDigit(PRUnichar(*cp))) { PRInt32 len = 0; if (*aResult) // 2nd or later lines of multiline parameter { len = strlen(*aResult); char *ns = (char *) nsMemory::Realloc(*aResult, len + (valueEnd - valueStart) + 1); if (!ns) { nsMemory::Free(*aResult); } *aResult = ns; } else if (*cp == '0') // must be; 1st line : title*0= { *aResult = (char *) nsMemory::Alloc(valueEnd - valueStart + 1); } // else {} something is really wrong; out of memory if (*aResult) { // append a partial value memcpy(*aResult + len, valueStart, valueEnd - valueStart); *(*aResult + len + (valueEnd - valueStart)) = 0; if (needUnescape) nsUnescape(*aResult + len); } else return NS_ERROR_OUT_OF_MEMORY; } // end of if-block : title*[0-9]= or title*[1-9]*= } // str now points after the end of the value. // skip over whitespace, ';', whitespace. while (nsCRT::IsAsciiSpace(*str)) ++str; if (*str == ';') ++str; while (nsCRT::IsAsciiSpace(*str)) ++str; } if (*aResult) return NS_OK; else return NS_ERROR_INVALID_ARG; // aParameter not found !! }
// if the main document URL specified URLs for any content areas, start them loading void nsWebShellWindow::LoadContentAreas() { nsAutoString searchSpec; // fetch the chrome document URL nsCOMPtr<nsIContentViewer> contentViewer; // yes, it's possible for the docshell to be null even this early // see bug 57514. if (mDocShell) mDocShell->GetContentViewer(getter_AddRefs(contentViewer)); if (contentViewer) { nsIDocument* doc = contentViewer->GetDocument(); if (doc) { nsIURI* mainURL = doc->GetDocumentURI(); nsCOMPtr<nsIURL> url = do_QueryInterface(mainURL); if (url) { nsCAutoString search; url->GetQuery(search); AppendUTF8toUTF16(search, searchSpec); } } } // content URLs are specified in the search part of the URL // as <contentareaID>=<escapedURL>[;(repeat)] if (!searchSpec.IsEmpty()) { PRInt32 begPos, eqPos, endPos; nsString contentAreaID, contentURL; char *urlChar; nsresult rv; for (endPos = 0; endPos < (PRInt32)searchSpec.Length(); ) { // extract contentAreaID and URL substrings begPos = endPos; eqPos = searchSpec.FindChar('=', begPos); if (eqPos < 0) break; endPos = searchSpec.FindChar(';', eqPos); if (endPos < 0) endPos = searchSpec.Length(); searchSpec.Mid(contentAreaID, begPos, eqPos-begPos); searchSpec.Mid(contentURL, eqPos+1, endPos-eqPos-1); endPos++; // see if we have a docshell with a matching contentAreaID nsCOMPtr<nsIDocShellTreeItem> content; rv = GetContentShellById(contentAreaID.get(), getter_AddRefs(content)); if (NS_SUCCEEDED(rv) && content) { nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(content)); if (webNav) { urlChar = ToNewCString(contentURL); if (urlChar) { nsUnescape(urlChar); contentURL.AssignWithConversion(urlChar); webNav->LoadURI(contentURL.get(), nsIWebNavigation::LOAD_FLAGS_NONE, nsnull, nsnull, nsnull); nsMemory::Free(urlChar); } } } } } }