nsresult nsEudoraCompose::CopyComposedMessage( nsCString& fromLine, nsIFile *pSrc, nsIOutputStream *pDst, SimpleBufferTonyRCopiedOnce& copy)
{
  copy.m_bytesInBuf = 0;
  copy.m_writeOffset = 0;
  ReadFileState  state;
  state.pFile = pSrc;
  state.offset = 0;
  state.size = 0;

  pSrc->GetFileSize( &state.size);
  if (!state.size) {
    IMPORT_LOG0( "*** Error, unexpected zero file size for composed message\n");
    return( NS_ERROR_FAILURE);
  }

        nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(state.pInputStream), pSrc);

  if (NS_FAILED( rv)) {
    IMPORT_LOG0( "*** Error, unable to open composed message file\n");
    return( NS_ERROR_FAILURE);
  }

  PRUint32 written;
  rv = pDst->Write( fromLine.get(), fromLine.Length(), &written);

  // well, isn't this a hoot!
  // Read the headers from the new message, get the ones we like
  // and write out only the headers we want from the new message,
  // along with all of the other headers from the "old" message!
  if (NS_SUCCEEDED( rv))
    rv = FillMailBuffer( &state, copy);
  if (NS_SUCCEEDED( rv))
    rv = ReadHeaders( &state, copy, m_readHeaders);

  if (NS_SUCCEEDED( rv)) {
    rv = WriteHeaders( pDst, m_readHeaders);
  }

  // We need to go ahead and write out the rest of the copy buffer
  // so that the following will properly copy the rest of the body
  char lastChar = 0;

  rv = EscapeFromSpaceLine(pDst, copy.m_pBuffer + copy.m_writeOffset, copy.m_pBuffer+copy.m_bytesInBuf);
  if (copy.m_bytesInBuf)
    lastChar = copy.m_pBuffer[copy.m_bytesInBuf - 1];
  if (NS_SUCCEEDED(rv))
    copy.m_writeOffset = copy.m_bytesInBuf;

  while ((state.offset < state.size) && NS_SUCCEEDED( rv)) {
    rv = FillMailBuffer( &state, copy);
    if (NS_SUCCEEDED( rv)) {
      rv = EscapeFromSpaceLine(pDst, copy.m_pBuffer + copy.m_writeOffset, copy.m_pBuffer+copy.m_bytesInBuf);
      lastChar = copy.m_pBuffer[copy.m_bytesInBuf - 1];
      if (NS_SUCCEEDED( rv))
        copy.m_writeOffset = copy.m_bytesInBuf;
      else
        IMPORT_LOG0( "*** Error writing to destination mailbox\n");
    }
  }

  state.pInputStream->Close();

  if ((lastChar != 0x0A) && NS_SUCCEEDED( rv)) {
    rv = pDst->Write( "\x0D\x0A", 2, &written);
    if (written != 2)
      rv = NS_ERROR_FAILURE;
  }

  return( rv);
}
Esempio n. 2
0
nsresult nsOE5File::ImportMailbox( PRUint32 *pBytesDone, PRBool *pAbort, nsString& name, nsIFile *inFile, nsIFile *pDestination, PRUint32 *pCount)
{
  nsresult  rv;
  PRInt32    msgCount = 0;
  if (pCount)
    *pCount = 0;

  nsCOMPtr <nsIInputStream> inputStream;
  rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), inFile);
  if (NS_FAILED( rv)) return( rv);
  nsCOMPtr <nsIOutputStream> outputStream;
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), pDestination, -1, 0600);
  if (NS_FAILED( rv))
    return( rv);

  PRUint32 *  pIndex;
  PRUint32  indexSize;

  if (!ReadIndex( inputStream, &pIndex, &indexSize)) {
    IMPORT_LOG1( "No messages found in mailbox: %S\n", name.get());
    return( NS_OK);
  }

  char *  pBuffer = new char[kMailboxBufferSize];
  if (!(*pAbort))
    ConvertIndex( inputStream, pBuffer, pIndex, indexSize);

  PRUint32  block[4];
  PRInt32   sepLen = (PRInt32) strlen( m_pFromLineSep);
  PRUint32   written;

  /*
      Each block is:
      marker - matches file offset
      block length
      text length in block
      pointer to next block. (0 if end)

      Each message is made up of a linked list of block data.
      So what we do for each message is:
      1. Read the first block data.
      2. Write out the From message separator if the message doesn't already
      start with one.
      3. If the block of data doesn't end with CRLF then a line is broken into two blocks,
      so save the incomplete line for later process when we read the next block. Then
      write out the block excluding the partial line at the end of the block (if exists).
      4. If there's next block of data then read next data block. Otherwise we're done.
      If we found a partial line in step #3 then find the rest of the line from the
      current block and write out this line separately.
      5. Reset some of the control variables and repeat step #3.
  */

  PRUint32  didBytes = 0;
  PRUint32  next, size;
  char *pStart, *pEnd, *partialLineStart;
  nsCAutoString partialLine, tempLine;
  rv = NS_OK;

  for (PRUint32 i = 0; (i < indexSize) && !(*pAbort); i++)
  {
    if (! pIndex[i])
      continue;

    if (ReadBytes( inputStream, block, pIndex[i], 16) && (block[0] == pIndex[i]) &&
      (block[2] < kMailboxBufferSize) && (ReadBytes( inputStream, pBuffer, kDontSeek, block[2])))
    {
      // block[2] contains the chars in the buffer (ie, buf content size).
      // block[3] contains offset to the next block of data (0 means no more data).
      size = block[2];
      pStart = pBuffer;
      pEnd = pStart + size;

      // write out the from separator.
      if (IsFromLine( pBuffer, size))
      {
        char *pChar = pStart;
        while ((pChar < pEnd) && (*pChar != '\r') && (*(pChar+1) != '\n'))
          pChar++;

        if (pChar < pEnd)
        {
          // Get the "From " line so write it out.
          rv = outputStream->Write(pStart, pChar-pStart+2, &written);
          NS_ENSURE_SUCCESS(rv,rv);
          // Now buffer starts from the 2nd line.
          pStart = pChar + 2;
        }
      }
      else
      {
        // Write out the default from line since there is none in the msg.
        rv = outputStream->Write( m_pFromLineSep, sepLen, &written);
        // FIXME: Do I need to check the return value of written???
        if (NS_FAILED( rv))
          break;
      }

      char statusLine[50];
      PRUint32 msgFlags = 0; // need to convert from OE flags to mozilla flags
      PR_snprintf(statusLine, sizeof(statusLine), X_MOZILLA_STATUS_FORMAT MSG_LINEBREAK, msgFlags & 0xFFFF);
      rv = outputStream->Write(statusLine, strlen(statusLine), &written);
      NS_ENSURE_SUCCESS(rv,rv);
      PR_snprintf(statusLine, sizeof(statusLine), X_MOZILLA_STATUS2_FORMAT MSG_LINEBREAK, msgFlags & 0xFFFF0000);
      rv = outputStream->Write(statusLine, strlen(statusLine), &written);
      NS_ENSURE_SUCCESS(rv,rv);

      do
      {
        partialLine.Truncate();
        partialLineStart = pEnd;

        // If the buffer doesn't end with CRLF then a line is broken into two blocks,
        // so save the incomplete line for later process when we read the next block.
        if ( (size > 1) && !(*(pEnd - 2) == '\r' && *(pEnd - 1) == '\n') )
        {
          partialLineStart -= 2;
          while ((partialLineStart >= pStart) && (*partialLineStart != '\r') && (*(partialLineStart+1) != '\n'))
            partialLineStart--;
          if (partialLineStart != (pEnd - 2))
            partialLineStart += 2; // skip over CRLF if we find them.
          partialLine.Assign(partialLineStart, pEnd - partialLineStart);
        }

        // Now process the block of data which ends with CRLF.
        rv = EscapeFromSpaceLine(outputStream, pStart, partialLineStart);
        if (NS_FAILED(rv))
          break;

        didBytes += block[2];

        next = block[3];
        if (! next)
        {
          // OK, we're done so flush out the partial line if it's not empty.
          if (partialLine.Length())
            rv = EscapeFromSpaceLine(outputStream, (char *)partialLine.get(), (partialLine.get()+partialLine.Length()));
        }
        else
          if (ReadBytes(inputStream, block, next, 16) && (block[0] == next) &&
            (block[2] < kMailboxBufferSize) && (ReadBytes(inputStream, pBuffer, kDontSeek, block[2])))
          {
            // See if we have a partial line from previous block. If so then build a complete
            // line (ie, take the remaining chars from this block) and process this line. Need
            // to adjust where data start and size in this case.
            size = block[2];
            pStart = pBuffer;
            pEnd = pStart + size;
            if (partialLine.Length())
            {
              while ((pStart < pEnd) && (*pStart != '\r') && (*(pStart+1) != '\n'))
                pStart++;
              if (pStart < pEnd)  // if we found a CRLF ..
                pStart += 2;      // .. then copy that too.
              tempLine.Assign(pBuffer, pStart - pBuffer);
              partialLine.Append(tempLine);
              rv = EscapeFromSpaceLine(outputStream, (char *)partialLine.get(), (partialLine.get()+partialLine.Length()));
              if (NS_FAILED(rv))
                break;

              // Adjust where data start and size (since some of the data has been processed).
              size -= (pStart - pBuffer);
            }
          }
          else
          {
            IMPORT_LOG2( "Error reading message from %S at 0x%lx\n", name.get(), pIndex[i]);
            rv = outputStream->Write( "\x0D\x0A", 2, &written);
            next = 0;
          }
      } while (next);

      // Always end a msg with CRLF. This will make sure that OE msgs without body is
      // correctly recognized as msgs. Otherwise, we'll end up with the following in
      // the msg folder where the 2nd msg starts right after the headers of the 1st msg:
      //
      // From - Jan 1965 00:00:00     <<<--- 1st msg starts here
      // Subject: Test msg
      // . . . (more headers)
      // To: <*****@*****.**>
      // From - Jan 1965 00:00:00     <<<--- 2nd msg starts here
      // Subject: How are you
      // . . .(more headers)
      //
      // In this case, the 1st msg is not recognized as a msg (it's skipped)
      // when you open the folder.
      rv = outputStream->Write( "\x0D\x0A", 2, &written);

      if (NS_FAILED(rv))
        break;

      msgCount++;
      if (pCount)
        *pCount = msgCount;
      if (pBytesDone)
        *pBytesDone = didBytes;
    }
    else {
      // Error reading message, should this be logged???
      IMPORT_LOG2( "Error reading message from %S at 0x%lx\n", name.get(), pIndex[i]);
      *pAbort = PR_TRUE;
    }
  }

  delete [] pBuffer;

  if (NS_FAILED(rv))
    *pAbort = PR_TRUE;

  return( rv);
}
Esempio n. 3
0
BOOL nsOutlookMail::WriteMessage( nsIOutputStream *pDest, CMapiMessage *pMsg, int& attachCount, BOOL *pTerminate)
{
  BOOL    bResult = TRUE;
  const char *pData;
  int      len;
  BOOL    checkStart = FALSE;

  *pTerminate = FALSE;

  pData = pMsg->GetFromLine( len);
  if (pData) {
    bResult = WriteData( pDest, pData, len);
    checkStart = TRUE;
  }

  nsCOMPtr<nsIOutputStream> outStream = pDest;

  pData = pMsg->GetHeaders( len);
  if (pData && len) {
    if (checkStart)
      bResult = (EscapeFromSpaceLine(outStream, (char *)pData, pData+len) == NS_OK);
    else
      bResult = (EscapeFromSpaceLine(outStream, (char *)(pData+1), pData+len-1) == NS_OK);
  }

  // Do we need to add any mime headers???
  //  Is the message multipart?
  //    If so, then we are OK, but need to make sure we add mime
  //    header info to the body of the message
  //  If not AND we have attachments, then we need to add mime headers.

  BOOL needsMimeHeaders = pMsg->IsMultipart();
  if (!needsMimeHeaders && attachCount) {
    // if the message already has mime headers
    // that aren't multipart then we are in trouble!
    // in that case, ditch the attachments...  alternatively, we could
    // massage the headers and replace the existing mime headers
    // with our own but I think this case is likely not to occur.
    if (pMsg->HasContentHeader())
      attachCount = 0;
    else {
      if (bResult)
        bResult = WriteMimeMsgHeader( pDest, pMsg);
      needsMimeHeaders = TRUE;
    }
  }

  if (bResult)
    bResult = WriteStr( pDest, "\x0D\x0A");

  if (needsMimeHeaders) {
    if (bResult)
      bResult = WriteStr( pDest, "This is a MIME formatted message.\x0D\x0A");
    if (bResult)
      bResult = WriteStr( pDest, "\x0D\x0A");
    if (bResult)
      bResult = WriteMimeBoundary( pDest, pMsg, FALSE);
    if (pMsg->BodyIsHtml()) {
      if (bResult)
        bResult = WriteStr( pDest, "Content-type: text/html\x0D\x0A");
    }
    else {
      if (bResult)
        bResult = WriteStr( pDest, "Content-type: text/plain\x0D\x0A");
    }

    if (bResult)
      bResult = WriteStr( pDest, "\x0D\x0A");
  }

  pData = pMsg->GetBody( len);
  if (pData && len) {
    if (bResult)
      bResult = (EscapeFromSpaceLine(outStream, (char *)pData, pData+len) == NS_OK);
    if ((len < 2) || (pData[len - 1] != 0x0A) || (pData[len - 2] != 0x0D))
      bResult = WriteStr( pDest, "\x0D\x0A");
  }

  *pTerminate = needsMimeHeaders;

  return( bResult);
}