Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
//----------------------------------------------------------------------------------------
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 !!
}
Beispiel #10
0
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;
}
Beispiel #13
0
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;
}
Beispiel #14
0
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 !!
}
Beispiel #17
0
// 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);
          }
        }
      }
    }
  }
}