Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Protected Member Functions | Protected Attributes | Static Protected Attributes
nsMsgSendPart Class Reference

#include <nsMsgSendPart.h>

Collaboration diagram for nsMsgSendPart:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 nsMsgSendPart (nsIMsgSend *state, const char *part_charset=NULL)
virtual ~nsMsgSendPart ()
virtual int Write ()
virtual int SetFile (nsFileSpec *filename)
const nsFileSpecGetFileSpec ()
virtual int SetBuffer (const char *buffer)
const char * GetBuffer ()
virtual int SetType (const char *type)
const char * GetType ()
const char * GetCharsetName ()
virtual int SetOtherHeaders (const char *other)
const char * SetOtherHeaders ()
virtual int AppendOtherHeaders (const char *moreother)
virtual int SetMimeDeliveryState (nsIMsgSend *state)
int SetEncoderData (MimeEncoderData *data)
MimeEncoderDataGetEncoderData ()
int SetStripSensitiveHeaders (PRBool value)
PRBool GetStripSensitiveHeaders ()
virtual int AddChild (nsMsgSendPart *child)
PRInt32 GetNumChildren ()
nsMsgSendPartGetChild (PRInt32 which)
nsMsgSendPartDetachChild (PRInt32 which)
virtual int SetMainPart (PRBool value)
PRBool IsMainPart ()

Protected Member Functions

int CopyString (char **dest, const char *src)
int PushBody (char *buffer, PRInt32 length)

Protected Attributes

nsCOMPtr< nsIMsgSendm_state
nsMsgSendPartm_parent
nsFileSpecm_filespec
char * m_buffer
char * m_type
char * m_other
char m_charset_name [64+1]
PRBool m_strip_sensitive_headers
MimeEncoderDatam_encoder_data
nsMsgSendPart ** m_children
PRInt32 m_numchildren
PRBool m_firstBlock
PRBool m_needIntlConversion
PRBool m_mainpart
PRBool m_just_hit_CR

Static Protected Attributes

static PRInt32 M_counter = 0

Detailed Description

Definition at line 48 of file nsMsgSendPart.h.


Constructor & Destructor Documentation

nsMsgSendPart::nsMsgSendPart ( nsIMsgSend state,
const char *  part_charset = NULL 
)

Definition at line 61 of file nsMsgSendPart.cpp.

Here is the call graph for this function:

Definition at line 88 of file nsMsgSendPart.cpp.

Here is the call graph for this function:


Member Function Documentation

int nsMsgSendPart::AddChild ( nsMsgSendPart child) [virtual]

Definition at line 197 of file nsMsgSendPart.cpp.

{
  m_numchildren++;
  nsMsgSendPart** tmp = new nsMsgSendPart* [m_numchildren];
  if (tmp == nsnull) return NS_ERROR_OUT_OF_MEMORY;
  for (int i=0 ; i<m_numchildren-1 ; i++) {
    tmp[i] = m_children[i];
  }
  delete [] m_children;
  m_children = tmp;
  m_children[m_numchildren - 1] = child;
  child->m_parent = this;
  return 0;
}

Here is the caller graph for this function:

int nsMsgSendPart::AppendOtherHeaders ( const char *  moreother) [virtual]

Definition at line 164 of file nsMsgSendPart.cpp.

{
  if (!m_other)
    return SetOtherHeaders(more);

  if (!more || !*more)
    return 0;

  char* tmp = (char *) PR_Malloc(sizeof(char) * (PL_strlen(m_other) + PL_strlen(more) + 2));
  if (!tmp)
    return NS_ERROR_OUT_OF_MEMORY;

  PL_strcpy(tmp, m_other);
  PL_strcat(tmp, more);
  PR_FREEIF(m_other);
  m_other = tmp;

  return 0;
}

Here is the call graph for this function:

int nsMsgSendPart::CopyString ( char **  dest,
const char *  src 
) [protected]

Definition at line 105 of file nsMsgSendPart.cpp.

{
  NS_ASSERTION(src, "src null");
  
  PR_FREEIF(*dest);
  if (!src)
    *dest = PL_strdup("");
  else
    *dest = PL_strdup(src);
  
  return *dest? 0 : NS_ERROR_OUT_OF_MEMORY;
}

Here is the caller graph for this function:

Definition at line 212 of file nsMsgSendPart.cpp.

{
  nsMsgSendPart *returnValue = nsnull;
  
  NS_ASSERTION(whichOne >= 0 && whichOne < m_numchildren, "parameter out of range");
  if (whichOne >= 0 && whichOne < m_numchildren) 
  {
    returnValue = m_children[whichOne];
    
    if (m_numchildren > 1)
    {
      nsMsgSendPart** tmp = new nsMsgSendPart* [m_numchildren-1];
      if (tmp != nsnull) 
      {
        // move all the other kids over
        for (int i=0 ; i<m_numchildren-1 ; i++) 
        {
          if (i >= whichOne)
            tmp[i] = m_children[i+1];
          else
            tmp[i] = m_children[i];
        }
        delete [] m_children;
        m_children = tmp;
        m_numchildren--;
      }
    }
    else 
    {
      delete [] m_children;
      m_children = nsnull;
      m_numchildren = 0;
    }
  }
  
  if (returnValue)
    returnValue->m_parent = nsnull;
  
  return returnValue;
}
const char* nsMsgSendPart::GetBuffer ( ) [inline]

Definition at line 60 of file nsMsgSendPart.h.

{return m_buffer;}

Definition at line 65 of file nsMsgSendPart.h.

{return m_charset_name;}

Definition at line 253 of file nsMsgSendPart.cpp.

{
  NS_ASSERTION(which >= 0 && which < m_numchildren, "parameter out of range");
  if (which >= 0 && which < m_numchildren) {
    return m_children[which];
  }
  return nsnull;
}

Here is the caller graph for this function:

Definition at line 78 of file nsMsgSendPart.h.

{return m_encoder_data;}

Definition at line 57 of file nsMsgSendPart.h.

{return m_filespec;}

Definition at line 89 of file nsMsgSendPart.h.

{return m_numchildren;}

Here is the caller graph for this function:

Definition at line 85 of file nsMsgSendPart.h.

const char* nsMsgSendPart::GetType ( void  ) [inline]

Definition at line 63 of file nsMsgSendPart.h.

{return m_type;}

Definition at line 94 of file nsMsgSendPart.h.

                      {
                        return m_mainpart;
                      }
int nsMsgSendPart::PushBody ( char *  buffer,
PRInt32  length 
) [protected]

Definition at line 264 of file nsMsgSendPart.cpp.

{
  int status = 0;
  char* encoded_data = buffer;
  
  if (m_encoder_data) 
  {
    status = MIME_EncoderWrite(m_encoder_data, encoded_data, length);
  } 
  else 
  {
    // Merely translate all linebreaks to CRLF.
    const char *in = encoded_data;
    const char *end = in + length;
    char *buffer, *out;
    
    
    buffer = mime_get_stream_write_buffer();
    if (!buffer) return NS_ERROR_OUT_OF_MEMORY;
    
    NS_ASSERTION(encoded_data != buffer, "encoded_data == buffer");
    out = buffer;
    
    for (; in < end; in++) {
      if (m_just_hit_CR) {
        m_just_hit_CR = PR_FALSE;
        if (*in == nsCRT::LF) {
          // The last thing we wrote was a CRLF from hitting a CR.
          // So, we don't want to do anything from a following LF;
          // we want to ignore it.
          continue;
        }
      }
      if (*in == nsCRT::CR || *in == nsCRT::LF) {
        /* Write out the newline. */
        *out++ = nsCRT::CR;
        *out++ = nsCRT::LF;
        
        status = mime_write_message_body(m_state, buffer,
          out - buffer);
        if (status < 0) return status;
        out = buffer;
        
        if (*in == nsCRT::CR) {
          m_just_hit_CR = PR_TRUE;
        }
        
        out = buffer;
      } else {
        
      /*  Fix for bug #95985. We can't assume that all lines are shorter
      than 4096 chars (MIME_BUFFER_SIZE), so we need to test
      for this here. sfraser.
        */
        if (out - buffer >= MIME_BUFFER_SIZE)
        {
          status = mime_write_message_body(m_state, buffer, out - buffer);
          if (status < 0) return status;
          
          out = buffer;
        }
        
        *out++ = *in;
      }
    }
    
    /* Flush the last line. */
    if (out > buffer) {
      status = mime_write_message_body(m_state, buffer, out - buffer);
      if (status < 0) return status;
      out = buffer;
    }
  }
  
  if (encoded_data && encoded_data != buffer) {
    PR_Free(encoded_data);
  }
  
  return status;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nsMsgSendPart::SetBuffer ( const char *  buffer) [virtual]

Definition at line 129 of file nsMsgSendPart.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 185 of file nsMsgSendPart.cpp.

{
  m_encoder_data = data;
  return 0;
}

Here is the caller graph for this function:

int nsMsgSendPart::SetFile ( nsFileSpec filename) [virtual]

Definition at line 119 of file nsMsgSendPart.cpp.

{
  m_filespec = new nsFileSpec(*filename);
  if (!m_filespec)
    return NS_ERROR_OUT_OF_MEMORY;
  else
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nsMsgSendPart::SetMainPart ( PRBool  value) [virtual]

Definition at line 191 of file nsMsgSendPart.cpp.

{
  m_mainpart = value;
  return 0;
}

Definition at line 149 of file nsMsgSendPart.cpp.

{
  m_state = state;
  if (GetNumChildren() > 0)
  {
    for (int i = 0; i < GetNumChildren(); i++)
    {
      nsMsgSendPart *part = GetChild(i);
      if (part) 
        part->SetMimeDeliveryState(state);
    }
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nsMsgSendPart::SetOtherHeaders ( const char *  other) [virtual]

Definition at line 144 of file nsMsgSendPart.cpp.

{
  return CopyString(&m_other, other);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 68 of file nsMsgSendPart.h.

{return m_other;}

Here is the caller graph for this function:

Definition at line 80 of file nsMsgSendPart.h.

                      {
                                  m_strip_sensitive_headers = value;
                                  return 0;
                           }

Here is the caller graph for this function:

int nsMsgSendPart::SetType ( const char *  type) [virtual]

Definition at line 136 of file nsMsgSendPart.cpp.

Here is the caller graph for this function:

int nsMsgSendPart::Write ( ) [virtual]

Definition at line 474 of file nsMsgSendPart.cpp.

{
  int     status = 0;
  char    *separator = nsnull;
  PRBool  needToWriteCRLFAfterEncodedBody  = PR_FALSE;

#define PUSHLEN(str, length)                  \
  do {                            \
    status = mime_write_message_body(m_state, str, length); \
    if (status < 0) goto FAIL;                \
  } while (0)                         \

#define PUSH(str) PUSHLEN(str, PL_strlen(str))

  // rhp: Suppress the output of parts that are empty!
  if ( (m_parent) &&
       (m_numchildren == 0) &&
       ( (!m_buffer) || (!*m_buffer) ) &&
       (!m_filespec) &&
       (!m_mainpart) )
    return SKIP_EMPTY_PART;

  if (m_mainpart && m_type && PL_strcmp(m_type, TEXT_HTML) == 0) 
  {     
    if (m_filespec) 
    {
      // The "insert HTML links" code requires a memory buffer,
      // so read the file into memory.
      NS_ASSERTION(m_buffer == nsnull, "not-null buffer");
      PRInt32           length = 0;
      
      if (m_filespec->Valid())
        length = m_filespec->GetFileSize();
      
      m_buffer = (char *) PR_Malloc(sizeof(char) * (length + 1));
      if (m_buffer) 
      {
        nsInputFileStream file(*m_filespec);
        if (file.is_open()) 
        {
          length = file.read(m_buffer, length);
          file.close();
          m_buffer[length] = '\0';
        }
        else 
          PR_Free(m_buffer);
      }
    }
  }
  
  if (m_parent && m_parent->m_type &&
        !PL_strcasecmp(m_parent->m_type, MULTIPART_DIGEST) &&
        m_type &&
        (!PL_strcasecmp(m_type, MESSAGE_RFC822) ||
        !PL_strcasecmp(m_type, MESSAGE_NEWS))) 
  {
    // If we're in a multipart/digest, and this document is of type
    // message/rfc822, then it's appropriate to emit no headers.
    //
  }
  else 
  {
    char *message_headers = 0;
    char *content_headers = 0;
    char *content_type_header = 0;
    status = divide_content_headers(m_other,
                                    &message_headers,
                                    &content_headers,
                                    &content_type_header);
    if (status < 0)
      goto FAIL;
    
      /* First, write out all of the headers that refer to the message
      itself (From, Subject, MIME-Version, etc.)
    */
    if (message_headers) 
    {
      PUSH(message_headers);
      PR_Free(message_headers);
      message_headers = 0;
    }

    /* Now allow the crypto library to (potentially) insert some text
       (it may want to wrap the body in an envelope.)           */
    if (!m_parent) {
      status = m_state->BeginCryptoEncapsulation();
      if (status < 0) goto FAIL;
    }
          
    /* Now make sure there's a Content-Type header.
    */
    if (!content_type_header) 
    {
      NS_ASSERTION(m_type && *m_type, "null ptr");
      PRBool needsCharset = mime_type_needs_charset(m_type ? m_type : TEXT_PLAIN);
      if (needsCharset) 
      {
        content_type_header = PR_smprintf("Content-Type: %s; charset=%s" CRLF,
                                          (m_type ? m_type : TEXT_PLAIN), m_charset_name);
      }
      else
        content_type_header = PR_smprintf("Content-Type: %s" CRLF,
                                          (m_type ? m_type : TEXT_PLAIN));
      if (!content_type_header) 
      {
        if (content_headers)
          PR_Free(content_headers);
        status = NS_ERROR_OUT_OF_MEMORY;
        goto FAIL;
      }
    }
    
    /* If this is a compound object, tack a boundary string onto the
    Content-Type header. this
    */
    if (m_numchildren > 0)
    {
      int L;
      char *ct2;
      NS_ASSERTION(m_type, "null ptr");

      if (!separator)
      {
        separator = mime_make_separator("");
        if (!separator)
        {
          status = NS_ERROR_OUT_OF_MEMORY;
          goto FAIL;
        }
      }

      L = PL_strlen(content_type_header);
      
      if (content_type_header[L-1] == nsCRT::LF)
        content_type_header[--L] = 0;
      if (content_type_header[L-1] == nsCRT::CR)
        content_type_header[--L] = 0;
      
      ct2 = PR_smprintf("%s;\r\n boundary=\"%s\"" CRLF, content_type_header, separator);
      PR_Free(content_type_header);
      if (!ct2) 
      {
        if (content_headers)
          PR_Free(content_headers);
        status = NS_ERROR_OUT_OF_MEMORY;
        goto FAIL;
      }
      
      content_type_header = ct2;
    }
    
    // Now write out the Content-Type header...
    NS_ASSERTION(content_type_header && *content_type_header, "null ptr");
    PUSH(content_type_header);
    PR_Free(content_type_header);
    content_type_header = 0;
    
    /* ...followed by all of the other headers that refer to the body of
    the message (Content-Transfer-Encoding, Content-Dispositon, etc.)
    */
    if (content_headers) 
    {
      PUSH(content_headers);
      PR_Free(content_headers);
      content_headers = 0;
    }
  }

  PUSH(CRLF);         // A blank line, to mark the end of headers.

  m_firstBlock = PR_TRUE;
  /* only convert if we need to tag charset */
  m_needIntlConversion = mime_type_needs_charset(m_type);
  
  if (m_buffer) 
  {
    status = PushBody(m_buffer, PL_strlen(m_buffer));
    if (status < 0)
      goto FAIL;
  }
  else if (m_filespec) 
  {
    nsInputFileStream   myStream(*m_filespec);

    if (!myStream.is_open())
    {
      // mysteriously disappearing?
      nsCOMPtr<nsIMsgSendReport> sendReport;
      m_state->GetSendReport(getter_AddRefs(sendReport));
      if (sendReport)
      {
        nsAutoString error_msg;
        nsAutoString path;
        NS_CopyNativeToUnicode(
          nsDependentCString(m_filespec->GetNativePathCString()), path);
        nsMsgBuildErrorMessageByID(NS_MSG_UNABLE_TO_OPEN_TMP_FILE, error_msg, &path, nsnull);
        sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), PR_FALSE);
      }
      status = NS_MSG_UNABLE_TO_OPEN_TMP_FILE;
      goto FAIL;
    }
    /* Kludge to avoid having to allocate memory on the toy computers... */
    if (!mime_mailto_stream_read_buffer) 
    {
      mime_mailto_stream_read_buffer = (char *) PR_Malloc(MIME_BUFFER_SIZE);
      if (!mime_mailto_stream_read_buffer) 
      {
        status = NS_ERROR_OUT_OF_MEMORY;
        goto FAIL;
      }
    }

    char    *buffer = mime_mailto_stream_read_buffer;
    if (m_strip_sensitive_headers) 
    {
      // We are attaching a message, so we should be careful to
      // strip out certain sensitive internal header fields.
      PRBool skipping = PR_FALSE;

      while (1) 
      {
        char *line;

        if (myStream.eof())
          line = nsnull;
        else
        {
          buffer[0] = '\0';
          myStream.readline(buffer, MIME_BUFFER_SIZE-3);
          line = buffer;
        }
      
        if (!line)
          break;  /* EOF */
        
        if (skipping) {
          if (*line == ' ' || *line == '\t')
            continue;
          else
            skipping = PR_FALSE;
        }
        
        int hdrLen = PL_strlen(buffer);
        if ((hdrLen < 2) || (buffer[hdrLen-2] != nsCRT::CR)) { // if the line doesn't end with CRLF,
          // ... make it end with CRLF.
          if ( (hdrLen == 0) || ((buffer[hdrLen-1] != nsCRT::CR) && (buffer[hdrLen-1] != nsCRT::LF)) )
            hdrLen++;
          buffer[hdrLen-1] = '\015';
          buffer[hdrLen] = '\012';
          buffer[hdrLen+1] = '\0';
        }
        
        if (!PL_strncasecmp(line, "From -", 6) ||
            !PL_strncasecmp(line, "BCC:", 4) ||
            !PL_strncasecmp(line, "FCC:", 4) ||
            !PL_strncasecmp(line, CONTENT_LENGTH ":", CONTENT_LENGTH_LEN+1) ||
            !PL_strncasecmp(line, "Lines:", 6) ||
            !PL_strncasecmp(line, "Status:", 7) ||
            !PL_strncasecmp(line, X_MOZILLA_STATUS ":", X_MOZILLA_STATUS_LEN+1) ||
            !PL_strncasecmp(line, X_MOZILLA_STATUS2 ":", X_MOZILLA_STATUS2_LEN+1) ||
            !PL_strncasecmp(line, X_MOZILLA_DRAFT_INFO ":", X_MOZILLA_DRAFT_INFO_LEN+1) ||
            !PL_strncasecmp(line, X_MOZILLA_NEWSHOST ":", X_MOZILLA_NEWSHOST_LEN+1) ||
            !PL_strncasecmp(line, X_UIDL ":", X_UIDL_LEN+1) ||
            !PL_strncasecmp(line, "X-VM-", 5)) /* hi Kyle */
        {
          skipping = PR_TRUE;
          continue;
        }
        
        PUSH(line);
        
        if (*line == nsCRT::CR || *line == nsCRT::LF) {
          break;  // Now can do normal reads for the body.
        }
      }
    }
        
    while (!myStream.eof()) 
    {
      if ((status = myStream.read(buffer, MIME_BUFFER_SIZE)) < 0)
      {  
        nsCOMPtr<nsIMsgSendReport> sendReport;
        m_state->GetSendReport(getter_AddRefs(sendReport));
        if (sendReport)
        {
          nsAutoString error_msg;
          nsAutoString path;
          NS_CopyNativeToUnicode(nsDependentCString(m_filespec->GetNativePathCString()), path);
          nsMsgBuildErrorMessageByID(NS_MSG_UNABLE_TO_OPEN_FILE, error_msg, &path, nsnull);
          sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), PR_FALSE);
          status = NS_MSG_UNABLE_TO_OPEN_FILE;
          goto FAIL;
        }
      }
      status = PushBody(buffer, status);
      if (status < 0)
        goto FAIL;
    }
  }
  
  if (m_encoder_data) 
  {
    status = MIME_EncoderDestroy(m_encoder_data, PR_FALSE);
    m_encoder_data = nsnull;
    needToWriteCRLFAfterEncodedBody = !m_parent;
    if (status < 0)
      goto FAIL;
  }
  
  // 
  // Ok, from here we loop and drive the the output of all children 
  // for this message.
  //
  if (m_numchildren > 0) 
  {
    PRBool  writeSeparator = PR_TRUE;

    for (int i = 0 ; i < m_numchildren ; i ++) 
    {
      if (writeSeparator)
      {
        PUSH(CRLF);
        PUSH("--");

        PUSH(separator);
        PUSH(CRLF);
      }

      status = m_children[i]->Write();
      if (status < 0)
        goto FAIL;

      if (status == SKIP_EMPTY_PART)
        writeSeparator = PR_FALSE;
      else
        writeSeparator = PR_TRUE;
    }

    PUSH(CRLF);
    PUSH("--");
    PUSH(separator);
    PUSH("--");
    PUSH(CRLF);
  }
  else if (needToWriteCRLFAfterEncodedBody)
    PUSH(CRLF);
  
FAIL:
  PR_FREEIF(separator);
  return status;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

char* nsMsgSendPart::m_buffer [protected]

Definition at line 105 of file nsMsgSendPart.h.

char nsMsgSendPart::m_charset_name[64+1] [protected]

Definition at line 108 of file nsMsgSendPart.h.

Definition at line 112 of file nsMsgSendPart.h.

PRInt32 nsMsgSendPart::M_counter = 0 [static, protected]

Definition at line 123 of file nsMsgSendPart.h.

Definition at line 110 of file nsMsgSendPart.h.

Definition at line 104 of file nsMsgSendPart.h.

Definition at line 116 of file nsMsgSendPart.h.

Definition at line 121 of file nsMsgSendPart.h.

Definition at line 119 of file nsMsgSendPart.h.

Definition at line 117 of file nsMsgSendPart.h.

Definition at line 113 of file nsMsgSendPart.h.

char* nsMsgSendPart::m_other [protected]

Definition at line 107 of file nsMsgSendPart.h.

Definition at line 103 of file nsMsgSendPart.h.

Definition at line 102 of file nsMsgSendPart.h.

Definition at line 109 of file nsMsgSendPart.h.

char* nsMsgSendPart::m_type [protected]

Definition at line 106 of file nsMsgSendPart.h.


The documentation for this class was generated from the following files: