Exemple #1
0
  bool
  ParseHeader(nsACString::const_iterator& aStart,
              nsACString::const_iterator& aEnd,
              bool* aWasEmptyHeader)
  {
    nsAutoCString headerName, headerValue;
    if (!FetchUtil::ExtractHeader(aStart, aEnd,
                                  headerName, headerValue,
                                  aWasEmptyHeader)) {
      return false;
    }
    if (*aWasEmptyHeader) {
      return true;
    }

    if (headerName.LowerCaseEqualsLiteral("content-disposition")) {
      nsCCharSeparatedTokenizer tokenizer(headerValue, ';');
      bool seenFormData = false;
      while (tokenizer.hasMoreTokens()) {
        const nsDependentCSubstring& token = tokenizer.nextToken();
        if (token.IsEmpty()) {
          continue;
        }

        if (token.EqualsLiteral("form-data")) {
          seenFormData = true;
          continue;
        }

        if (seenFormData &&
            StringBeginsWith(token, NS_LITERAL_CSTRING("name="))) {
          mName = StringTail(token, token.Length() - 5);
          mName.Trim(" \"");
          continue;
        }

        if (seenFormData &&
            StringBeginsWith(token, NS_LITERAL_CSTRING("filename="))) {
          mFilename = StringTail(token, token.Length() - 9);
          mFilename.Trim(" \"");
          continue;
        }
      }

      if (mName.IsVoid()) {
        // Could not parse a valid entry name.
        return false;
      }
    } else if (headerName.LowerCaseEqualsLiteral("content-type")) {
      mContentType = headerValue;
    }

    return true;
  }
Exemple #2
0
BOOL CMapiMessage::AddHeader( nsCString& str, ULONG tag, const char *pPrefix)
{
  nsCString value;
  LPSPropValue pVal = CMapiApi::GetMapiProperty( m_lpMsg, tag);
  if (CMapiApi::GetStringFromProp( pVal, value) && !value.IsEmpty()) {
    str.Trim( kWhitespace, PR_FALSE, PR_TRUE);
    if (!str.IsEmpty())
      str += "\x0D\x0A";
    str += pPrefix;
    str += value;
    return( TRUE);
  }

  return( FALSE);
}
Exemple #3
0
void CMapiMessage::AddDate( nsCString& str)
{
  LPSPropValue pVal = CMapiApi::GetMapiProperty( m_lpMsg, PR_MESSAGE_DELIVERY_TIME);
  if (!pVal)
    pVal = CMapiApi::GetMapiProperty( m_lpMsg, PR_CREATION_TIME);
  if (pVal) {
    SYSTEMTIME st;
    ::FileTimeToSystemTime( &(pVal->Value.ft), &st);
    CMapiApi::MAPIFreeBuffer( pVal);
    str.Trim( kWhitespace, PR_FALSE, PR_TRUE);
    if (!str.IsEmpty())
      str += "\x0D\x0A";
    str += "Date: ";
    FormatDateTime( st, str);
  }
}
static nsresult MangleKeywordIntoURI(const char *aKeyword, const char *aURL,
                                     nsCString& query)
{
    query = (*aKeyword == '?') ? (aKeyword + 1) : aKeyword;
    query.Trim(" "); // pull leading/trailing spaces.

    // encode
    char * encQuery = nsEscape(query.get(), url_XPAlphas);
    if (!encQuery) return NS_ERROR_OUT_OF_MEMORY;
    query.Adopt(encQuery);

    // prepend the query with the keyword url
    // XXX this url should come from somewhere else
    query.Insert(aURL, 0);
    return NS_OK;
}
Exemple #5
0
nsresult
ParseNextRecord(nsILineInputStream* aLineInputStream,
                const nsCString& aPrefix,
                nsCString& aResult,
                bool& aMoreLines)
{
  nsAutoCString record;
  nsresult rv = aLineInputStream->ReadLine(record, &aMoreLines);
  if (NS_FAILED(rv)) {
    return rv;
  }

  if (record.Length() <= aPrefix.Length() ||
      !Substring(record, 0, aPrefix.Length()).Equals(aPrefix)) {
    return NS_ERROR_FAILURE;
  }

  aResult = Substring(record, aPrefix.Length());
  aResult.Trim("\b\t\r\n ");

  return NS_OK;
}
Exemple #6
0
  bool
  ParseHeader(nsACString::const_iterator& aStart,
              nsACString::const_iterator& aEnd,
              bool* aWasEmptyHeader)
  {
    MOZ_ASSERT(aWasEmptyHeader);
    // Set it to a valid value here so we don't forget later.
    *aWasEmptyHeader = false;

    const char* beginning = aStart.get();
    nsACString::const_iterator end(aEnd);
    if (!FindCRLF(aStart, end)) {
      return false;
    }

    if (aStart.get() == beginning) {
      *aWasEmptyHeader = true;
      return true;
    }

    nsAutoCString header(beginning, aStart.get() - beginning);

    nsACString::const_iterator headerStart, headerEnd;
    header.BeginReading(headerStart);
    header.EndReading(headerEnd);
    if (!FindCharInReadable(':', headerStart, headerEnd)) {
      return false;
    }

    nsAutoCString headerName(StringHead(header, headerStart.size_backward()));
    headerName.CompressWhitespace();
    if (!NS_IsValidHTTPToken(headerName)) {
      return false;
    }

    nsAutoCString headerValue(Substring(++headerStart, headerEnd));
    if (!NS_IsReasonableHTTPHeaderValue(headerValue)) {
      return false;
    }
    headerValue.CompressWhitespace();

    if (headerName.LowerCaseEqualsLiteral("content-disposition")) {
      nsCCharSeparatedTokenizer tokenizer(headerValue, ';');
      bool seenFormData = false;
      while (tokenizer.hasMoreTokens()) {
        const nsDependentCSubstring& token = tokenizer.nextToken();
        if (token.IsEmpty()) {
          continue;
        }

        if (token.EqualsLiteral("form-data")) {
          seenFormData = true;
          continue;
        }

        if (seenFormData &&
            StringBeginsWith(token, NS_LITERAL_CSTRING("name="))) {
          mName = StringTail(token, token.Length() - 5);
          mName.Trim(" \"");
          continue;
        }

        if (seenFormData &&
            StringBeginsWith(token, NS_LITERAL_CSTRING("filename="))) {
          mFilename = StringTail(token, token.Length() - 9);
          mFilename.Trim(" \"");
          continue;
        }
      }

      if (mName.IsVoid()) {
        // Could not parse a valid entry name.
        return false;
      }
    } else if (headerName.LowerCaseEqualsLiteral("content-type")) {
      mContentType = headerValue;
    }

    return true;
  }
Exemple #7
0
PRBool nsTextAddress::GetField( const char *pLine, PRInt32 maxLen, PRInt32 index, nsCString& field, char delim)
{
    PRBool result = PR_FALSE;
    const char *pChar = pLine;
    PRInt32        len = 0;
    char        tab = 9;

    field.Truncate();

    if (delim == tab)
        tab = 0;

    while (index && (len < maxLen)) {
        while (((*pChar == ' ') || (*pChar == tab)) && (len < maxLen)) {
            pChar++;
            len++;
        }
        if (len >= maxLen)
            break;
        if (*pChar == '"') {
            len = -1;
            do {
                len++;
                pChar++;
                if (((len + 1) < maxLen) && (*pChar == '"') && (*(pChar + 1) == '"')) {
                    len += 2;
                    pChar += 2;
                }
            } while ((len < maxLen) && (*pChar != '"'));
            if (len < maxLen) {
                pChar++;
                len++;
            }
        }
        if (len >= maxLen)
            break;
        
        while ((len < maxLen) && (*pChar != delim)) {
            len++;
            pChar++;
        }
        
        if (len >= maxLen)
            break;

        index--;
        pChar++;
        len++;
    }

    if (len >= maxLen) {
        return( result);
    }

    result = PR_TRUE;

    while ((len < maxLen) && ((*pChar == ' ') || (*pChar == tab))) {
        len++;
        pChar++;
    }

    const char *pStart = pChar;
    PRInt32        fLen = 0;
    PRBool        quoted = PR_FALSE;
    if (*pChar == '"') {
        pStart++;
        fLen = -1;
        do {
            pChar++;
            len++;
            fLen++;
            if (((len + 1) < maxLen) && (*pChar == '"') && (*(pChar + 1) == '"')) {
                quoted = PR_TRUE;
                len += 2;
                pChar += 2;
                fLen += 2;
            }
        } while ((len < maxLen) && (*pChar != '"'));
    }
    else {
        while ((len < maxLen) && (*pChar != delim)) {
            pChar++;
            len++;
            fLen++;
        }
    }

    if (!fLen) {
        return( result);
    }

    field.Append( pStart, fLen);
    field.Trim( kWhitespace);

    if (quoted) {
        field.ReplaceSubstring( "\"\"", "\"");
    }

    return( result);
}
Exemple #8
0
bool nsTextAddress::GetField( const char *pLine, PRInt32 maxLen, PRInt32 index, nsCString& field, char delim)
{
    bool result = false;
    const char *pChar = pLine;
    PRInt32        len = 0;
    char        tab = 9;

    field.Truncate();

    if (delim == tab)
        tab = 0;

    while (index && (len < maxLen)) {
        while (((*pChar == ' ') || (*pChar == tab)) && (len < maxLen)) {
            pChar++;
            len++;
        }
        if (len >= maxLen)
            break;
        if (*pChar == '"') {
            len = -1;
            do {
                len++;
                pChar++;
                if (((len + 1) < maxLen) && (*pChar == '"') && (*(pChar + 1) == '"')) {
                    len += 2;
                    pChar += 2;
                }
            } while ((len < maxLen) && (*pChar != '"'));
            if (len < maxLen) {
                pChar++;
                len++;
            }
        }
        if (len >= maxLen)
            break;

        while ((len < maxLen) && (*pChar != delim)) {
            len++;
            pChar++;
        }

        if (len >= maxLen)
            break;

        index--;
        pChar++;
        len++;
    }

    if (len >= maxLen) {
        return( result);
    }

    result = true;

    while ((len < maxLen) && ((*pChar == ' ') || (*pChar == tab))) {
        len++;
        pChar++;
    }

    const char *pStart = pChar;
    PRInt32        fLen = 0;
    bool          quoted = false;
    if (*pChar == '"') {
        pStart++;
        fLen = -1;
        do {
            pChar++;
            len++;
            fLen++;
            if (((len + 1) < maxLen) && (*pChar == '"') && (*(pChar + 1) == '"')) {
                quoted = true;
                len += 2;
                pChar += 2;
                fLen += 2;
            }
        } while ((len < maxLen) && (*pChar != '"'));
    }
    else {
        while ((len < maxLen) && (*pChar != delim)) {
            pChar++;
            len++;
            fLen++;
        }
    }

    if (!fLen) {
        return( result);
    }

    field.Append( pStart, fLen);
    field.Trim( kWhitespace);

    if (quoted) {
      PRInt32 offset = field.Find(NS_LITERAL_CSTRING("\"\""));
      while (offset != -1) {
        field.Cut(offset, 1);
        offset = field.Find(NS_LITERAL_CSTRING("\"\""), offset + 1);
      }
    }

    return( result);
}
PRBool CAliasData::Process( const char *pLine, PRInt32 len)
{
  // Extract any comments first!
  nsCString  str;

  const char *pStart = pLine;
  PRInt32    tCnt = 0;
  PRInt32    cnt = 0;
  PRInt32    max = len;
  PRBool    endCollect = PR_FALSE;

    // Keep track of the full entry without any processing for potential alias
    // nickname resolution. Previously alias resolution was done with m_email,
    // but unfortunately that doesn't work for nicknames with spaces.
    // For example for the nickname "Joe Smith", "Smith" was being interpreted
    // as the potential email address and placed in m_email, but routines like
    // ResolveAlias were failing because "Smith" is not the full nickname.
    // Now we just stash the full entry for nickname resolution before processing
    // the line as a potential entry in its own right.
    m_fullEntry.Append(pLine, len);

  while (max) {
    if (*pLine == '"') {
      if (tCnt && !endCollect) {
        str.Trim( kWhitespace);
        if (!str.IsEmpty())
          str.Append( " ", 1);
        str.Append( pStart, tCnt);
      }
      cnt = nsEudoraAddress::CountQuote( pLine, max);
      if ((cnt > 2) && m_realName.IsEmpty()) {
        m_realName.Append( pLine + 1, cnt - 2);
      }
      pLine += cnt;
      max -= cnt;
      pStart = pLine;
      tCnt = 0;
    }
    else if (*pLine == '<') {
      if (tCnt && !endCollect) {
        str.Trim( kWhitespace);
        if (!str.IsEmpty())
          str.Append( " ", 1);
        str.Append( pStart, tCnt);
      }
      cnt = nsEudoraAddress::CountAngle( pLine, max);
      if ((cnt > 2) && m_email.IsEmpty()) {
        m_email.Append( pLine + 1, cnt - 2);
      }
      pLine += cnt;
      max -= cnt;
      pStart = pLine;
      tCnt = 0;
      endCollect = PR_TRUE;
    }
    else if (*pLine == '(') {
      if (tCnt && !endCollect) {
        str.Trim( kWhitespace);
        if (!str.IsEmpty())
          str.Append( " ", 1);
        str.Append( pStart, tCnt);
      }
      cnt = nsEudoraAddress::CountComment( pLine, max);
      if (cnt > 2) {
        if (!m_realName.IsEmpty() && m_nickName.IsEmpty())
          m_nickName = m_realName;
        m_realName.Truncate();
        m_realName.Append( pLine + 1, cnt - 2);
      }
      pLine += cnt;
      max -= cnt;
      pStart = pLine;
      tCnt = 0;
    }
    else {
      tCnt++;
      pLine++;
      max--;
    }
  }

  if (tCnt) {
    str.Trim( kWhitespace);
    if (!str.IsEmpty())
      str.Append( " ", 1);
    str.Append( pStart, tCnt);
  }

  str.Trim( kWhitespace);

  if (!m_realName.IsEmpty() && !m_email.IsEmpty())
    return( PR_TRUE);

  // now we should have a string with any remaining non-delimitted text
  // we assume that the last token is the email
  // anything before that is realName
  if (!m_email.IsEmpty()) {
    m_realName = str;
    return( PR_TRUE);
  }

  tCnt = str.RFindChar( ' ');
  if (tCnt == -1) {
    if (!str.IsEmpty()) {
      m_email = str;
      return( PR_TRUE);
    }
    return( PR_FALSE);
  }

  str.Right( m_email, str.Length() - tCnt - 1);
  str.Left( m_realName, tCnt);
  m_realName.Trim( kWhitespace);
  m_email.Trim( kWhitespace);

  return( !m_email.IsEmpty());
}
PRBool CAliasData::Process( const char *pLine, PRInt32 len)
{
	// Extract any comments first!
	nsCString	str;
	
	const char *pStart = pLine;
	PRInt32		tCnt = 0;
	PRInt32		cnt = 0;
	PRInt32		max = len;
	PRBool		endCollect = PR_FALSE;
	
	while (max) {
		if (*pLine == '"') {
			if (tCnt && !endCollect) {
				str.Trim( kWhitespace);
				if (!str.IsEmpty())
					str.Append( " ", 1);
				str.Append( pStart, tCnt);
			}
			cnt = nsEudoraAddress::CountQuote( pLine, max);
			if ((cnt > 2) && m_realName.IsEmpty()) {
				m_realName.Append( pLine + 1, cnt - 2);
			}
			pLine += cnt;
			max -= cnt;
			pStart = pLine;
			tCnt = 0;
		}
		else if (*pLine == '<') {
			if (tCnt && !endCollect) {
				str.Trim( kWhitespace);
				if (!str.IsEmpty())
					str.Append( " ", 1);
				str.Append( pStart, tCnt);
			}
			cnt = nsEudoraAddress::CountAngle( pLine, max);
			if ((cnt > 2) && m_email.IsEmpty()) {
				m_email.Append( pLine + 1, cnt - 2);
			}
			pLine += cnt;
			max -= cnt;
			pStart = pLine;
			tCnt = 0;
			endCollect = PR_TRUE;
		}
		else if (*pLine == '(') {
			if (tCnt && !endCollect) {
				str.Trim( kWhitespace);
				if (!str.IsEmpty())
					str.Append( " ", 1);
				str.Append( pStart, tCnt);
			}
			cnt = nsEudoraAddress::CountComment( pLine, max);
			if (cnt > 2) {
				if (!m_realName.IsEmpty() && m_nickName.IsEmpty())
					m_nickName = m_realName;
				m_realName.Truncate();
				m_realName.Append( pLine + 1, cnt - 2);
			}
			pLine += cnt;
			max -= cnt;
			pStart = pLine;
			tCnt = 0;
		}
		else {
			tCnt++;
			pLine++;
			max--;
		}
	}
	
	if (tCnt) {
		str.Trim( kWhitespace);
		if (!str.IsEmpty())
			str.Append( " ", 1);
		str.Append( pStart, tCnt);
	}
	
	str.Trim( kWhitespace);
	
	if (!m_realName.IsEmpty() && !m_email.IsEmpty())
		return( PR_TRUE);
	
	// now we should have a string with any remaining non-delimitted text
	// we assume that the last token is the email
	// anything before that is realName
	if (!m_email.IsEmpty()) {
		m_realName = str;
		return( PR_TRUE);
	}
	
	tCnt = str.RFindChar( ' ');
	if (tCnt == -1) {
		if (!str.IsEmpty()) {
			m_email = str;
			return( PR_TRUE);
		}
		return( PR_FALSE);
	}
	
	str.Right( m_email, str.Length() - tCnt - 1);
	str.Left( m_realName, tCnt);
	m_realName.Trim( kWhitespace);
	m_email.Trim( kWhitespace);
	
	return( !m_email.IsEmpty());
}
void nsEudoraCompose::GetHeaderValue( const char *pData, PRInt32 dataLen, const char *pHeader, nsCString& val, PRBool unwrap)
{
  val.Truncate();
  if (!pData)
    return;

  PRInt32  start = 0;
  PRInt32 len = strlen( pHeader);
  const char *pChar = pData;
  if (!PL_strncasecmp( pHeader, pData, len)) {
    start = len;
  }
  else {
    while (start < dataLen) {
      while ((start < dataLen) && (*pChar != 0x0D) && (*pChar != 0x0A)) {
        start++;
        pChar++;
      }
      while ((start < dataLen) && ((*pChar == 0x0D) || (*pChar == 0x0A))) {
        start++;
        pChar++;
      }
      if ((start < dataLen) && !PL_strncasecmp( pChar, pHeader, len))
        break;
    }
    if (start < dataLen)
      start += len;
  }

  if (start >= dataLen)
    return;

  PRInt32 end = start;
  PRInt32 lineEnd;
  const char * pStart;

  pChar = pData + start;

  while (end < dataLen) {
    while ((end < dataLen) && (*pChar != 0x0D) && (*pChar != 0x0A)) {
      end++;
      pChar++;
    }
    if (end > start) {
      val.Append( pData + start, end - start);
    }

    lineEnd = end;
    pStart = pChar;
    while ((end < dataLen) && ((*pChar == 0x0D) || (*pChar == 0x0A))) {
      end++;
      pChar++;
    }

    start = end;

    while ((end < dataLen) && ((*pChar == ' ') || (*pChar == '\t'))) {
      end++;
      pChar++;
    }

    if (start == end)
      break;

    if (unwrap)
      val.Append( ' ');
    else {
      val.Append( pStart, end - lineEnd);
    }

    start = end;
  }

  val.Trim( kWhitespace);
}
void nsEudoraCompose::GetNthHeader( const char *pData, PRInt32 dataLen, PRInt32 n, nsCString& header, nsCString& val, PRBool unwrap)
{
  header.Truncate();
  val.Truncate();
  if (!pData)
    return;

  PRInt32 index = 0;
  PRInt32 len;
  PRInt32 start = 0;
  const char *pChar = pData;
  const char *pStart;
  if (n == 0) {
    pStart = pChar;
    len = 0;
    while ((start < dataLen) && (*pChar != ':')) {
      start++;
      len++;
      pChar++;
    }
    header.Append( pStart, len);
    header.Trim( kWhitespace);
    start++;
    pChar++;
  }
  else {
    while (start < dataLen) {
      if ((*pChar != ' ') && (*pChar != 9)) {
        if (n == index) {
          pStart = pChar;
          len = 0;
          while ((start < dataLen) && (*pChar != ':')) {
            start++;
            len++;
            pChar++;
          }
          header.Append( pStart, len);
          header.Trim( kWhitespace);
          start++;
          pChar++;
          break;
        }
        else
          index++;
      }

      while ((start < dataLen) && (*pChar != 0x0D) && (*pChar != 0x0A)) {
        start++;
        pChar++;
      }
      while ((start < dataLen) && ((*pChar == 0x0D) || (*pChar == 0x0A))) {
        start++;
        pChar++;
      }
    }
  }

  if (start >= dataLen)
    return;

  PRInt32 lineEnd;
  PRInt32 end = start;
  while (end < dataLen) {
    while ((end < dataLen) && (*pChar != 0x0D) && (*pChar != 0x0A)) {
      end++;
      pChar++;
    }
    if (end > start) {
      val.Append( pData + start, end - start);
    }

    lineEnd = end;
    pStart = pChar;
    while ((end < dataLen) && ((*pChar == 0x0D) || (*pChar == 0x0A))) {
      end++;
      pChar++;
    }

    start = end;

    while ((end < dataLen) && ((*pChar == ' ') || (*pChar == '\t'))) {
      end++;
      pChar++;
    }

    if (start == end)
      break;

    if (unwrap)
      val.Append( ' ');
    else {
      val.Append( pStart, end - lineEnd);
    }

    start = end;
  }

  val.Trim( kWhitespace);
}
Exemple #13
0
void nsEudoraCompose::GetHeaderValue(const char *pData,
                                     int32_t dataLen,
                                     const char *pHeader,
                                     nsCString& val,
                                     bool unwrap)
{
  val.Truncate();
  if (!pData)
    return;

  int32_t  start = 0;
  int32_t len = strlen(pHeader);
  const char *pChar = pData;
  if (!PL_strncasecmp(pHeader, pData, len)) {
    start = len;
  }
  else {
    while (start < dataLen) {
      // Skip to next end of line.
      while ((start < dataLen) &&
             (*pChar != nsCRT::CR) && (*pChar != nsCRT::LF)) {
        start++;
        pChar++;
      }
      // Skip over end of line(s).
      while ((start < dataLen) &&
             ((*pChar == nsCRT::CR) || (*pChar == nsCRT::LF))) {
        start++;
        pChar++;
      }

      if ((start < dataLen) && !PL_strncasecmp(pChar, pHeader, len))
        break;
    }
    if (start < dataLen)
      start += len;
  }

  if (start >= dataLen)
    return;

  int32_t end = start;
  int32_t lineEnd;
  const char * pStart;

  pChar = pData + start;

  while (end < dataLen) {
    // Skip to next end of line.
    while ((end < dataLen) && (*pChar != nsCRT::CR) && (*pChar != nsCRT::LF)) {
      end++;
      pChar++;
    }

    if (end > start)
      val.Append(pData + start, end - start);

    lineEnd = end;
    pStart = pChar;

    // Skip over the end of line(s).
    while ((end < dataLen) &&
           ((*pChar == nsCRT::CR) || (*pChar == nsCRT::LF))) {
      end++;
      pChar++;
    }

    start = end;

    // Skip over space(s) and tab(s).
    while ((end < dataLen) && ((*pChar == ' ') || (*pChar == '\t'))) {
      end++;
      pChar++;
    }

    if (start == end)
      break;

    if (unwrap)
      val.Append(' ');
    else {
      val.Append(pStart, end - lineEnd);
    }

    start = end;
  }

  val.Trim(kWhitespace);
}
Exemple #14
0
void nsEudoraCompose::GetNthHeader(const char *pData,
                                   int32_t dataLen,
                                   int32_t n,
                                   nsCString& header,
                                   nsCString& val,
                                   bool unwrap)
{
  header.Truncate();
  val.Truncate();
  if (!pData)
    return;

  int32_t index = 0;
  int32_t len;
  int32_t start = 0;
  const char *pChar = pData;
  const char *pStart;
  if (n == 0) {
    pStart = pChar;
    len = 0;
    while ((start < dataLen) && (*pChar != ':')) {
      start++;
      len++;
      pChar++;
    }
    header.Append(pStart, len);
    header.Trim(kWhitespace);
    start++;
    pChar++;
  }
  else {
    while (start < dataLen) {
      if ((*pChar != ' ') && (*pChar != '\t')) {
        if (n == index) {
          pStart = pChar;
          len = 0;
          while ((start < dataLen) && (*pChar != ':')) {
            start++;
            len++;
            pChar++;
          }
          header.Append(pStart, len);
          header.Trim(kWhitespace);
          start++;
          pChar++;
          break;
        }
        else
          index++;
      }

      // Skip to next end of line.
      while ((start < dataLen) &&
             (*pChar != nsCRT::CR) && (*pChar != nsCRT::LF)) {
        start++;
        pChar++;
      }
      // Skip over end of line(s).
      while ((start < dataLen) &&
             ((*pChar == nsCRT::CR) || (*pChar == nsCRT::LF))) {
        start++;
        pChar++;
      }
    }
  }

  if (start >= dataLen)
    return;

  int32_t lineEnd;
  int32_t end = start;
  while (end < dataLen) {
    // Skip to next end of line.
    while ((end < dataLen) && (*pChar != nsCRT::CR) && (*pChar != nsCRT::LF)) {
      end++;
      pChar++;
    }

    if (end > start) {
      val.Append(pData + start, end - start);
    }

    lineEnd = end;
    pStart = pChar;

    // Skip over end of line(s).
    while ((end < dataLen) &&
           ((*pChar == nsCRT::CR) || (*pChar == nsCRT::LF))) {
      end++;
      pChar++;
    }

    start = end;

    // Skip over space(s) and tab(s).
    while ((end < dataLen) && ((*pChar == ' ') || (*pChar == '\t'))) {
      end++;
      pChar++;
    }

    if (start == end)
      break;

    if (unwrap)
      val.Append(' ');
    else {
      val.Append(pStart, end - lineEnd);
    }

    start = end;
  }

  val.Trim(kWhitespace);
}