Back to index

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

#include <nsParseMailbox.h>

Inheritance diagram for nsParseMailMessageState:
Inheritance graph
[legend]
Collaboration diagram for nsParseMailMessageState:
Collaboration graph
[legend]

List of all members.

Public Member Functions

NS_DECL_ISUPPORTS
NS_DECL_NSIMSGPARSEMAILMSGSTATE 
nsParseMailMessageState ()
virtual ~nsParseMailMessageState ()
void Init (PRUint32 fileposition)
virtual PRInt32 ParseFolderLine (const char *line, PRUint32 lineLength)
virtual int StartNewEnvelope (const char *line, PRUint32 lineLength)
int ParseHeaders ()
int FinalizeHeaders ()
int ParseEnvelope (const char *line, PRUint32 line_size)
int InternSubject (struct message_header *header)
nsresult InternRfc822 (struct message_header *header, char **ret_name)
struct message_headerGetNextHeaderInAggregate (nsVoidArray &list)
void GetAggregateHeader (nsVoidArray &list, struct message_header *)
void ClearAggregateHeader (nsVoidArray &list)
void SetMailDB (in nsIMsgDatabase aDatabase)
void setDBFolderStream (in nsIOFileStream fileStream)
void Clear ()
void ParseAFolderLine (in string line, in unsigned long lineLength)
nsIMsgDBHdr GetNewMsgHdr ()
void FinishHeader ()
long GetAllHeaders (out string headers)

Static Public Member Functions

static PRBool IsEnvelopeLine (const char *buf, PRInt32 buf_size)
static int msg_UnHex (char C)

Public Attributes

nsCOMPtr< nsIMsgHeaderParserm_HeaderAddressParser
nsCOMPtr< nsIMsgDBHdrm_newMsgHdr
nsCOMPtr< nsIMsgDatabasem_mailDB
nsMailboxParseState m_state
PRUint32 m_position
PRUint32 m_envelope_pos
PRUint32 m_headerstartpos
nsByteArray m_headers
nsByteArray m_envelope
nsVoidArray m_toList
nsVoidArray m_ccList
PRTime m_receivedTime
PRUint16 m_body_lines
PRBool m_IgnoreXMozillaStatus
PRBool m_useReceivedDate
nsCStringArray m_customDBHeaders
struct message_headerm_customDBHeaderValues
attribute unsigned long envelopePos
readonly attribute string headers
attribute nsMailboxParseState state
const long ParseEnvelopeState = 0
const long ParseHeadersState = 1
const long ParseBodyState = 2

Protected Attributes

nsCOMPtr< nsIMsgStringServicemStringService

Detailed Description

Definition at line 85 of file nsParseMailbox.h.


Constructor & Destructor Documentation

Definition at line 474 of file nsParseMailbox.cpp.

{
  m_position = 0;
  m_IgnoreXMozillaStatus = PR_FALSE;
  m_useReceivedDate = PR_FALSE;
  m_state = nsIMsgParseMailMsgState::ParseBodyState;

  // setup handling of custom db headers, headers that are added to .msf files
  // as properties of the nsMsgHdr objects, controlled by the 
  // pref mailnews.customDBHeaders, a space-delimited list of headers.
  // E.g., if mailnews.customDBHeaders is "X-Spam-Score", and we're parsing
  // a mail message with the X-Spam-Score header, we'll set the 
  // "x-spam-score" property of nsMsgHdr to the value of the header.
  m_customDBHeaderValues = nsnull;
  nsXPIDLCString customDBHeaders;
  nsCOMPtr<nsIPrefBranch> pPrefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
  if (pPrefBranch)
  {
     pPrefBranch->GetCharPref("mailnews.customDBHeaders",  getter_Copies(customDBHeaders));
     ToLowerCase(customDBHeaders);
     m_customDBHeaders.ParseString(customDBHeaders, " ");
     if (m_customDBHeaders.Count())
     {
       m_customDBHeaderValues = new struct message_header [m_customDBHeaders.Count()];
       if (!m_customDBHeaderValues)
         m_customDBHeaders.Clear();
     }
     pPrefBranch->GetBoolPref("mailnews.use_received_date", &m_useReceivedDate);
  }
  Clear();

  m_HeaderAddressParser = do_GetService(NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID);
}

Here is the call graph for this function:

Definition at line 508 of file nsParseMailbox.cpp.

Here is the call graph for this function:


Member Function Documentation

Here is the caller graph for this function:

Definition at line 850 of file nsParseMailbox.cpp.

{
  // Reset the aggregate headers. Free only the message_header struct since 
  // we don't own the value pointer
  
  for (int i = 0; i < list.Count(); i++)
    PR_Free ((struct message_header*) list.ElementAt(i));
  list.Clear();
}

Here is the caller graph for this function:

Definition at line 1186 of file nsParseMailbox.cpp.

{
  int status = 0;
  struct message_header *sender;
  struct message_header *recipient;
  struct message_header *subject;
  struct message_header *id;
  struct message_header *inReplyTo;
  struct message_header *replyTo;
  struct message_header *references;
  struct message_header *date;
  struct message_header *statush;
  struct message_header *mozstatus;
  struct message_header *mozstatus2;
  struct message_header *priority;
  struct message_header *keywords;
  struct message_header *account_key;
  struct message_header *ccList;
  struct message_header *mdn_dnt;
  struct message_header md5_header;
  struct message_header *content_type;
  char md5_data [50];
  
  const char *s;
  PRUint32 flags = 0;
  PRUint32 delta = 0;
  nsMsgPriorityValue priorityFlags = nsMsgPriority::notSet;
  PRUint32 labelFlags = 0;
  
  if (!m_mailDB)            // if we don't have a valid db, skip the header.
    return 0;
  
  struct message_header to;
  GetAggregateHeader (m_toList, &to);
  struct message_header cc;
  GetAggregateHeader (m_ccList, &cc);
  
  sender     = (m_from.length          ? &m_from :
  m_sender.length        ? &m_sender :
  m_envelope_from.length ? &m_envelope_from :
  0);
  recipient  = (to.length         ? &to :
  cc.length         ? &cc :
  m_newsgroups.length ? &m_newsgroups :
  sender);
  ccList         = (cc.length ? &cc : 0);
  subject    = (m_subject.length    ? &m_subject    : 0);
  id         = (m_message_id.length ? &m_message_id : 0);
  references = (m_references.length ? &m_references : 0);
  statush    = (m_status.length     ? &m_status     : 0);
  mozstatus  = (m_mozstatus.length  ? &m_mozstatus  : 0);
  mozstatus2 = (m_mozstatus2.length  ? &m_mozstatus2  : 0);
  date       = (m_date.length       ? &m_date :
  m_envelope_date.length ? &m_envelope_date :
  0);
  priority   = (m_priority.length   ? &m_priority   : 0);
  keywords   =  (m_keywords.length   ? &m_keywords  : 0);
  mdn_dnt        = (m_mdn_dnt.length        ? &m_mdn_dnt         : 0);
  inReplyTo = (m_in_reply_to.length ? &m_in_reply_to : 0);
  replyTo = (m_replyTo.length ? &m_replyTo : 0);
  content_type = (m_content_type.length ? &m_content_type : 0);
  account_key = (m_account_key.length ? &m_account_key :0);
  
  if (mozstatus) 
  {
    if (strlen(mozstatus->value) == 4) 
    {
      int i;
      for (i=0,s=mozstatus->value ; i<4 ; i++,s++) 
      {
        flags = (flags << 4) | msg_UnHex(*s);
      }
      // strip off and remember priority bits.
      flags &= ~MSG_FLAG_RUNTIME_ONLY;
      priorityFlags = (nsMsgPriorityValue) ((flags & MSG_FLAG_PRIORITIES) >> 13);
      flags &= ~MSG_FLAG_PRIORITIES;
    }
    delta = (m_headerstartpos +
      (mozstatus->value - m_headers.GetBuffer()) -
      (2 + X_MOZILLA_STATUS_LEN)          /* 2 extra bytes for ": ". */
      ) - m_envelope_pos;
  }
  
  if (mozstatus2)
  {
    PRUint32 flags2 = 0;
    sscanf(mozstatus2->value, " %x ", &flags2);
    flags |= flags2;
  }
  
  if (!(flags & MSG_FLAG_EXPUNGED))       // message was deleted, don't bother creating a hdr.
  {
    nsresult ret = m_mailDB->CreateNewHdr(m_envelope_pos, getter_AddRefs(m_newMsgHdr));
    if (NS_SUCCEEDED(ret) && m_newMsgHdr)
    {
      PRUint32 origFlags;
      (void)m_newMsgHdr->GetFlags(&origFlags);
      if (origFlags & MSG_FLAG_HAS_RE)
        flags |= MSG_FLAG_HAS_RE;
      else
        flags &= ~MSG_FLAG_HAS_RE;
      
      flags &= ~MSG_FLAG_OFFLINE; // don't keep MSG_FLAG_OFFLINE for local msgs
      if (mdn_dnt && !(origFlags & MSG_FLAG_READ) &&
          !(origFlags & MSG_FLAG_MDN_REPORT_SENT) &&
          !(flags & MSG_FLAG_MDN_REPORT_SENT))
        flags |= MSG_FLAG_MDN_REPORT_NEEDED;
      
      m_newMsgHdr->SetFlags(flags);
      if (priorityFlags != nsMsgPriority::notSet)
        m_newMsgHdr->SetPriority(priorityFlags);
  
      // if we have a reply to header, and it's different from the from: header,
      // set the "replyTo" attribute on the msg hdr.
      if (replyTo && (!sender || replyTo->length != sender->length || strncmp(replyTo->value, sender->value, sender->length)))
        m_newMsgHdr->SetStringProperty("replyTo", replyTo->value);
      // convert the flag values (0xE000000) to label values (0-5)
      if (mozstatus2) // only do this if we have a mozstatus2 header
      {
        labelFlags = ((flags & MSG_FLAG_LABELS) >> 25);
        m_newMsgHdr->SetLabel(labelFlags);
      }
      if (delta < 0xffff) 
      {              /* Only use if fits in 16 bits. */
        m_newMsgHdr->SetStatusOffset((PRUint16) delta);
        if (!m_IgnoreXMozillaStatus) {    // imap doesn't care about X-MozillaStatus
          PRUint32 offset;
          (void)m_newMsgHdr->GetStatusOffset(&offset);
          NS_ASSERTION(offset < 10000, "invalid status offset"); /* ### Debugging hack */
        }
      }
      if (sender)
        m_newMsgHdr->SetAuthor(sender->value);
      if (recipient == &m_newsgroups)
      {
      /* In the case where the recipient is a newsgroup, truncate the string
      at the first comma.  This is used only for presenting the thread list,
      and newsgroup lines tend to be long and non-shared, and tend to bloat
      the string table.  So, by only showing the first newsgroup, we can
      reduce memory and file usage at the expense of only showing the one
      group in the summary list, and only being able to sort on the first
        group rather than the whole list.  It's worth it. */
        char * ch;
        NS_ASSERTION (recipient->length == (PRUint16) strlen(recipient->value), "invalid recipient");
        ch = PL_strchr(recipient->value, ',');
        if (ch)
        {
          /* generate a new string that terminates before the , */
          nsCAutoString firstGroup;
          firstGroup.Assign(recipient->value, ch - recipient->value);
          m_newMsgHdr->SetRecipients(firstGroup.get());
        }
        m_newMsgHdr->SetRecipients(recipient->value);
      }
      else if (recipient)
      {
        // note that we're now setting the whole recipient list,
        // not just the pretty name of the first recipient.
        PRUint32 numAddresses;
        char  *names;
        char  *addresses;
        
        ret = m_HeaderAddressParser->ParseHeaderAddresses (nsnull, recipient->value, &names, &addresses, &numAddresses);
        if (ret == NS_OK)
        {
          m_newMsgHdr->SetRecipientsArray(names, addresses, numAddresses);
          PR_Free(addresses);
          PR_Free(names);
        }
        else {       // hmm, should we just use the original string?
          m_newMsgHdr->SetRecipients(recipient->value);
        }
      }
      if (ccList)
      {
        PRUint32 numAddresses;
        char  *names;
        char  *addresses;
        
        ret = m_HeaderAddressParser->ParseHeaderAddresses (nsnull, ccList->value, &names, &addresses, &numAddresses);
        if (ret == NS_OK)
        {
          m_newMsgHdr->SetCCListArray(names, addresses, numAddresses);
          PR_Free(addresses);
          PR_Free(names);
        }
        else  // hmm, should we just use the original string?
          m_newMsgHdr->SetCcList(ccList->value);
      }
      status = InternSubject (subject);
      if (status >= 0)
      {
        if (! id)
        {
          // what to do about this? we used to do a hash of all the headers...
          nsCAutoString hash;
          const char *md5_bin = "dummy message id";
          nsresult rv;
          nsCOMPtr<nsICryptoHash> hasher = do_CreateInstance("@mozilla.org/security/hash;1", &rv);
          if (NS_SUCCEEDED(rv))
          {
            if (NS_SUCCEEDED(hasher->Init(nsICryptoHash::MD5)) && 
              NS_SUCCEEDED(hasher->Update((const PRUint8*) m_headers.GetBuffer(), m_headers.GetSize())) &&
              NS_SUCCEEDED(hasher->Finish(PR_FALSE, hash)))
                  md5_bin = hash.get();
          }
          PR_snprintf (md5_data, sizeof(md5_data),
            "<md5:"
            "%02X%02X%02X%02X%02X%02X%02X%02X"
            "%02X%02X%02X%02X%02X%02X%02X%02X"
            ">",
            md5_bin[0], md5_bin[1], md5_bin[2], md5_bin[3],
            md5_bin[4], md5_bin[5], md5_bin[6], md5_bin[7],
            md5_bin[8], md5_bin[9], md5_bin[10],md5_bin[11],
            md5_bin[12],md5_bin[13],md5_bin[14],md5_bin[15]);
          md5_header.value = md5_data;
          md5_header.length = strlen(md5_data);
          id = &md5_header;
        }
        
        /* Take off <> around message ID. */
        if (id->value[0] == '<')
          id->value++, id->length--;

        if (id->value[id->length-1] == '>') {
          /* generate a new null-terminated string without the final > */
          nsCAutoString rawMsgId;
          rawMsgId.Assign(id->value, id->length - 1);
          m_newMsgHdr->SetMessageId(rawMsgId.get());
        } else {
          m_newMsgHdr->SetMessageId(id->value);
        }

        if (!mozstatus && statush)
        {
          /* Parse a little bit of the Berkeley Mail status header. */
          for (s = statush->value; *s; s++) {
            PRUint32 msgFlags = 0;
            (void)m_newMsgHdr->GetFlags(&msgFlags);
            switch (*s)
            {
            case 'R': case 'r':
              m_newMsgHdr->SetFlags(msgFlags | MSG_FLAG_READ);
              break;
            case 'D': case 'd':
              /* msg->flags |= MSG_FLAG_EXPUNGED;  ### Is this reasonable? */
              break;
            case 'N': case 'n':
            case 'U': case 'u':
              m_newMsgHdr->SetFlags(msgFlags & ~MSG_FLAG_READ);
              break;
            }
          }
        }
  
        if (account_key != nsnull)
          m_newMsgHdr->SetAccountKey(account_key->value);
        // use in-reply-to header as references, if there's no references header
        if (references != nsnull)
          m_newMsgHdr->SetReferences(references->value);
        else if (inReplyTo != nsnull)
          m_newMsgHdr->SetReferences(inReplyTo->value);
        
        if (!LL_IS_ZERO(m_receivedTime) && (!date || m_useReceivedDate))
          m_newMsgHdr->SetDate(m_receivedTime);
        else
        {
          // if there's no date, or it's mal-formed, use now as the time.
          // PR_ParseTimeString won't touch resultTime unless it succeeds.
          // (this doesn't affect local messages, because we use the envelope
          // date if there's no Date: header, but it would affect IMAP msgs
          // w/o a Date: hdr or Received: headers)
          PRTime resultTime = PR_Now();
          if (date)
            PR_ParseTimeString (date->value, PR_FALSE, &resultTime);
          m_newMsgHdr->SetDate(resultTime);
        }

        if (priority)
          m_newMsgHdr->SetPriorityString(priority->value);
        else if (priorityFlags == nsMsgPriority::notSet)
          m_newMsgHdr->SetPriority(nsMsgPriority::none);
        if (keywords)
          m_newMsgHdr->SetStringProperty("keywords", keywords->value);
        for (PRInt32 i = 0; i < m_customDBHeaders.Count(); i++)
        {
          if (m_customDBHeaderValues[i].length)
            m_newMsgHdr->SetStringProperty((m_customDBHeaders[i])->get(), m_customDBHeaderValues[i].value);
        }
        if (content_type)
        {
          char *substring = PL_strstr(content_type->value, "charset");
          if (substring)
          {
            char *charset = PL_strchr (substring, '=');
            if (charset)
            {
              charset++;
              /* strip leading whitespace and double-quote */
              while (*charset && (IS_SPACE (*charset) || '\"' == *charset))
                charset++;
              /* strip trailing whitespace and double-quote */
              char *end = charset;
              while (*end && !IS_SPACE (*end) && '\"' != *end && ';' != *end)
                end++;
              if (*charset)
              {
                if (*end != '\0') {
                  // if we're not at the very end of the line, we need
                  // to generate a new string without the trailing crud
                  nsCAutoString rawCharSet;
                  rawCharSet.Assign(charset, end - charset);
                  m_newMsgHdr->SetCharset(rawCharSet.get());
                } else {
                  m_newMsgHdr->SetCharset(charset);
                }
              }
            }
          }
          substring = PL_strcasestr(content_type->value, "multipart/mixed");
          if (substring)
          {
            PRUint32 newFlags;
            m_newMsgHdr->OrFlags(MSG_FLAG_ATTACHMENT, &newFlags);
          }
        }
      }
    } 
    else
    {
      NS_ASSERTION(PR_FALSE, "error creating message header");
      status = NS_ERROR_OUT_OF_MEMORY;    
    }
  }
  else
    status = 0;

  //### why is this stuff const?
  char *tmp = (char*) to.value;
  PR_Free(tmp);
  tmp = (char*) cc.value;
  PR_Free(tmp);

  return status;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Here is the caller graph for this function:

Definition at line 806 of file nsParseMailbox.cpp.

{
  // When parsing a message with multiple To or CC header lines, we're storing each line in a 
  // list, where the list represents the "aggregate" total of all the header. Here we combine
  // all the lines together, as though they were really all found on the same line
  
  struct message_header *header = nsnull;
  int length = 0;
  int i;
  
  // Count up the bytes required to allocate the aggregated header
  for (i = 0; i < list.Count(); i++)
  {
    header = (struct message_header*) list.ElementAt(i);
    length += (header->length + 1); //+ for ","
    NS_ASSERTION(header->length == (PRInt32)strlen(header->value), "header corrupted");
  }
  
  if (length > 0)
  {
    char *value = (char*) PR_MALLOC (length + 1); //+1 for null term
    if (value)
    {
      // Catenate all the To lines together, separated by commas
      value[0] = '\0';
      int size = list.Count();
      for (i = 0; i < size; i++)
      {
        header = (struct message_header*) list.ElementAt(i);
        PL_strcat (value, header->value);
        if (i + 1 < size)
          PL_strcat (value, ",");
      }
      outHeader->length = length;
      outHeader->value = value;
    }
  }
  else
  {
    outHeader->length = 0;
    outHeader->value = nsnull;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 795 of file nsParseMailbox.cpp.

{
  // When parsing a message with multiple To or CC header lines, we're storing each line in a 
  // list, where the list represents the "aggregate" total of all the header. Here we get a new
  // line for the list
  
  struct message_header *header = (struct message_header*) PR_Calloc (1, sizeof(struct message_header));
  list.AppendElement (header);
  return header;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsParseMailMessageState::InternRfc822 ( struct message_header header,
char **  ret_name 
)

Definition at line 1161 of file nsParseMailbox.cpp.

{
  char *s;
  nsresult ret=NS_OK;
  
  if (!header || header->length == 0)
    return NS_OK;
  
  NS_ASSERTION (header->length == (short) strlen (header->value), "invalid message_header");
  NS_ASSERTION (ret_name != nsnull, "null ret_name");
  
  if (m_HeaderAddressParser)
  {
    ret = m_HeaderAddressParser->ExtractHeaderAddressName (nsnull, header->value, &s);
    if (! s)
      return NS_ERROR_OUT_OF_MEMORY;
    
    *ret_name = s;
  }
  return ret;
}

Definition at line 1110 of file nsParseMailbox.cpp.

{
  char *key;
  PRUint32 L;
  
  if (!header || header->length == 0)
  {
    m_newMsgHdr->SetSubject("");
    return 0;
  }
  
  NS_ASSERTION (header->length == (short) strlen(header->value), "subject corrupt while parsing message");
  
  key = (char *) header->value;  /* #### const evilness */
  
  L = header->length;
  
  
  PRUint32 flags;
  (void)m_newMsgHdr->GetFlags(&flags);
  /* strip "Re: " */
  /* We trust the X-Mozilla-Status line to be the smartest in almost
        all things.  One exception, however, is the HAS_RE flag.  Since
         we just parsed the subject header anyway, we expect that parsing
         to be smartest.  (After all, what if someone just went in and
        edited the subject line by hand?) */
  nsXPIDLCString modifiedSubject;
  if (NS_MsgStripRE((const char **) &key, &L, getter_Copies(modifiedSubject)))
    flags |= MSG_FLAG_HAS_RE;
  else
    flags &= ~MSG_FLAG_HAS_RE;
  m_newMsgHdr->SetFlags(flags); // this *does not* update the mozilla-status header in the local folder
  
  //  if (!*key) return 0; /* To catch a subject of "Re:" */
  
  // Condense the subject text into as few MIME-2 encoded words as possible.
#ifdef WE_CONDENSE_MIME_STRINGS
  char *condensedKey = msg_condense_mime2_string(modifiedSubject.IsEmpty() ? key : modifiedSubject.get());
#else
  char *condensedKey = nsnull;
#endif
  m_newMsgHdr->SetSubject(condensedKey ? condensedKey : 
  (modifiedSubject.IsEmpty() ? key : modifiedSubject.get()));
  PR_FREEIF(condensedKey);
  
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool nsParseMailMessageState::IsEnvelopeLine ( const char *  buf,
PRInt32  buf_size 
) [static]

Definition at line 660 of file nsParseMailbox.cpp.

{
#ifdef STRICT_ENVELOPE
  /* The required format is
          From jwz  Fri Jul  1 09:13:09 1994
        But we should also allow at least:
          From jwz  Fri, Jul 01 09:13:09 1994
          From jwz  Fri Jul  1 09:13:09 1994 PST
          From jwz  Fri Jul  1 09:13:09 1994 (+0700)

        We can't easily call XP_ParseTimeString() because the string is not
        null terminated (ok, we could copy it after a quick check...) but
        XP_ParseTimeString() may be too lenient for our purposes.

        DANGER!!  The released version of 2.0b1 was (on some systems,
        some Unix, some NT, possibly others) writing out envelope lines
        like "From - 10/13/95 11:22:33" which STRICT_ENVELOPE will reject!
   */
  const char *date, *end;

  if (buf_size < 29) return PR_FALSE;
  if (*buf != 'F') return PR_FALSE;
  if (strncmp(buf, "From ", 5)) return PR_FALSE;

  end = buf + buf_size;
  date = buf + 5;

  /* Skip horizontal whitespace between "From " and user name. */
  while ((*date == ' ' || *date == '\t') && date < end)
       date++;

  /* If at the end, it doesn't match. */
  if (IS_SPACE(*date) || date == end)
       return PR_FALSE;

  /* Skip over user name. */
  while (!IS_SPACE(*date) && date < end)
       date++;

  /* Skip horizontal whitespace between user name and date. */
  while ((*date == ' ' || *date == '\t') && date < end)
       date++;

  /* Don't want this to be localized. */
# define TMP_ISALPHA(x) (((x) >= 'A' && (x) <= 'Z') || \
                                           ((x) >= 'a' && (x) <= 'z'))

  /* take off day-of-the-week. */
  if (date >= end - 3)
       return PR_FALSE;
  if (!TMP_ISALPHA(date[0]) || !TMP_ISALPHA(date[1]) || !TMP_ISALPHA(date[2]))
       return PR_FALSE;
  date += 3;
  /* Skip horizontal whitespace (and commas) between dotw and month. */
  if (*date != ' ' && *date != '\t' && *date != ',')
       return PR_FALSE;
  while ((*date == ' ' || *date == '\t' || *date == ',') && date < end)
       date++;

  /* take off month. */
  if (date >= end - 3)
       return PR_FALSE;
  if (!TMP_ISALPHA(date[0]) || !TMP_ISALPHA(date[1]) || !TMP_ISALPHA(date[2]))
       return PR_FALSE;
  date += 3;
  /* Skip horizontal whitespace between month and dotm. */
  if (date == end || (*date != ' ' && *date != '\t'))
       return PR_FALSE;
  while ((*date == ' ' || *date == '\t') && date < end)
       date++;

  /* Skip over digits and whitespace. */
  while (((*date >= '0' && *date <= '9') || *date == ' ' || *date == '\t') &&
               date < end)
       date++;
  /* Next character should be a colon. */
  if (date >= end || *date != ':')
       return PR_FALSE;

  /* Ok, that ought to be enough... */

# undef TMP_ISALPHA

#else  /* !STRICT_ENVELOPE */

  if (buf_size < 5) return PR_FALSE;
  if (*buf != 'F') return PR_FALSE;
  if (strncmp(buf, "From ", 5)) return PR_FALSE;

#endif /* !STRICT_ENVELOPE */

  return PR_TRUE;
}

Here is the caller graph for this function:

int nsParseMailMessageState::msg_UnHex ( char  C) [inline, static]

Definition at line 167 of file nsParseMailbox.h.

{
       return ((C >= '0' && C <= '9') ? C - '0' :
              ((C >= 'A' && C <= 'F') ? C - 'A' + 10 :
               ((C >= 'a' && C <= 'f') ? C - 'a' + 10 : 0)));
}

Here is the caller graph for this function:

void nsIMsgParseMailMsgState::ParseAFolderLine ( in string  line,
in unsigned long  lineLength 
) [inherited]
int nsParseMailMessageState::ParseEnvelope ( const char *  line,
PRUint32  line_size 
)

Definition at line 1066 of file nsParseMailbox.cpp.

{
  const char *end;
  char *s;
  
  m_envelope.AppendBuffer(line, line_size);
  end = m_envelope.GetBuffer() + line_size;
  s = m_envelope.GetBuffer() + 5;
  
  while (s < end && IS_SPACE (*s))
    s++;
  m_envelope_from.value = s;
  while (s < end && !IS_SPACE (*s))
    s++;
  m_envelope_from.length = s - m_envelope_from.value;
  
  while (s < end && IS_SPACE (*s))
    s++;
  m_envelope_date.value = s;
  m_envelope_date.length = (PRUint16) (line_size - (s - m_envelope.GetBuffer()));
  while (IS_SPACE (m_envelope_date.value [m_envelope_date.length - 1]))
    m_envelope_date.length--;
  
  /* #### short-circuit const */
  ((char *) m_envelope_from.value) [m_envelope_from.length] = 0;
  ((char *) m_envelope_date.value) [m_envelope_date.length] = 0;
  
  return 0;
}

Here is the caller graph for this function:

PRInt32 nsParseMailMessageState::ParseFolderLine ( const char *  line,
PRUint32  lineLength 
) [virtual]

Definition at line 605 of file nsParseMailbox.cpp.

{
  int status = 0;
  
  if (m_state == nsIMsgParseMailMsgState::ParseHeadersState)
  {
    if (EMPTY_MESSAGE_LINE(line))
    {
      /* End of headers.  Now parse them. */
      status = ParseHeaders();
      NS_ASSERTION(status >= 0, "error parsing headers parsing mailbox");
      if (status < 0)
        return status;
      
      status = FinalizeHeaders();
      NS_ASSERTION(status >= 0, "error finalizing headers parsing mailbox");
      if (status < 0)
        return status;
      m_state = nsIMsgParseMailMsgState::ParseBodyState;
    }
    else
    {
      /* Otherwise, this line belongs to a header.  So append it to the
         header data, and stay in MBOX `MIME_PARSE_HEADERS' state.
      */
      m_headers.AppendBuffer(line, lineLength);
    }
  }
  else if ( m_state == nsIMsgParseMailMsgState::ParseBodyState)
  {
    m_body_lines++;
  }
  
  m_position += lineLength;
  
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 872 of file nsParseMailbox.cpp.

{
  char *buf = m_headers.GetBuffer();
  char *buf_end = buf + m_headers.GetBufferPos();
  while (buf < buf_end)
  {
    char *colon = PL_strchr (buf, ':');
    char *end;
    char *value = 0;
    struct message_header *header = 0;
    struct message_header receivedBy;
    
    if (! colon)
      break;
    
    end = colon;
    while (end > buf && (*end == ' ' || *end == '\t'))
      end--;
    
    switch (buf [0])
    {
    case 'C': case 'c':
      if (!nsCRT::strncasecmp ("CC", buf, end - buf))
        header = GetNextHeaderInAggregate(m_ccList);
      else if (!nsCRT::strncasecmp ("Content-Type", buf, end - buf))
        header = &m_content_type;
      break;
    case 'D': case 'd':
      if (!nsCRT::strncasecmp ("Date", buf, end - buf))
        header = &m_date;
      else if (!nsCRT::strncasecmp("Disposition-Notification-To", buf, end - buf))
        header = &m_mdn_dnt;
      break;
    case 'F': case 'f':
      if (!nsCRT::strncasecmp ("From", buf, end - buf))
        header = &m_from;
      break;
    case 'I' : case 'i':
      if (!nsCRT::strncasecmp ("In-Reply-To", buf, end - buf))
        header = &m_in_reply_to;
      break;
    case 'M': case 'm':
      if (!nsCRT::strncasecmp ("Message-ID", buf, end - buf))
        header = &m_message_id;
      break;
    case 'N': case 'n':
      if (!nsCRT::strncasecmp ("Newsgroups", buf, end - buf))
        header = &m_newsgroups;
      break;
    case 'O': case 'o':
      if (!nsCRT::strncasecmp ("Original-Recipient", buf, end - buf))
        header = &m_mdn_original_recipient;
      break;
    case 'R': case 'r':
      if (!nsCRT::strncasecmp ("References", buf, end - buf))
        header = &m_references;
      else if (!nsCRT::strncasecmp ("Return-Path", buf, end - buf))
        header = &m_return_path;
      // treat conventional Return-Receipt-To as MDN
      // Disposition-Notification-To
      else if (!nsCRT::strncasecmp ("Return-Receipt-To", buf, end - buf))
        header = &m_mdn_dnt;
      else if (!nsCRT::strncasecmp("Reply-To", buf, end - buf))
        header = &m_replyTo;
      else if (!PL_strncasecmp("Received", buf, end - buf))
      {
        header = &receivedBy;
        header->length = 0;
      }
      break;
    case 'S': case 's':
      if (!nsCRT::strncasecmp ("Subject", buf, end - buf))
        header = &m_subject;
      else if (!nsCRT::strncasecmp ("Sender", buf, end - buf))
        header = &m_sender;
      else if (!nsCRT::strncasecmp ("Status", buf, end - buf))
        header = &m_status;
      break;
    case 'T': case 't':
      if (!nsCRT::strncasecmp ("To", buf, end - buf))
        header = GetNextHeaderInAggregate(m_toList);
      break;
    case 'X':
      if (X_MOZILLA_STATUS2_LEN == end - buf &&
        !nsCRT::strncasecmp(X_MOZILLA_STATUS2, buf, end - buf) &&
        !m_IgnoreXMozillaStatus && !m_mozstatus2.length)
        header = &m_mozstatus2;
      else if ( X_MOZILLA_STATUS_LEN == end - buf &&
        !nsCRT::strncasecmp(X_MOZILLA_STATUS, buf, end - buf) && !m_IgnoreXMozillaStatus
        && !m_mozstatus.length)
        header = &m_mozstatus;
      else if (!nsCRT::strncasecmp(HEADER_X_MOZILLA_ACCOUNT_KEY, buf, end - buf)
        && !m_account_key.length)
        header = &m_account_key;
      // we could very well care what the priority header was when we 
      // remember its value. If so, need to remember it here. Also, 
      // different priority headers can appear in the same message, 
      // but we only rememeber the last one that we see.
      else if (!nsCRT::strncasecmp("X-Priority", buf, end - buf)
        || !nsCRT::strncasecmp("Priority", buf, end - buf))
        header = &m_priority;
      else if (!nsCRT::strncasecmp(HEADER_X_MOZILLA_KEYWORDS, buf, end - buf)
        && !m_keywords.length)
        header = &m_keywords;
      break;
    }
    if (!header && m_customDBHeaders.Count())
    {
      nsDependentCSubstring headerStr(buf, end);

      ToLowerCase(headerStr);
      PRInt32 customHeaderIndex = m_customDBHeaders.IndexOf(headerStr);
      if (customHeaderIndex != kNotFound)
        header = & m_customDBHeaderValues[customHeaderIndex];
    }
    
    buf = colon + 1;
    while (*buf == ' ' || *buf == '\t')
      buf++;
    
    value = buf;
    if (header)
      header->value = value;
    else
    {
    }
    
SEARCH_NEWLINE:
    while (*buf != 0 && *buf != nsCRT::CR && *buf != nsCRT::LF)
      buf++;
    
    if (buf+1 >= buf_end)
      ;
    /* If "\r\n " or "\r\n\t" is next, that doesn't terminate the header. */
    else if (buf+2 < buf_end &&
                        (buf[0] == nsCRT::CR  && buf[1] == nsCRT::LF) &&
                           (buf[2] == ' ' || buf[2] == '\t'))
    {
      buf += 3;
      goto SEARCH_NEWLINE;
    }
    /* If "\r " or "\r\t" or "\n " or "\n\t" is next, that doesn't terminate
    the header either. */
    else if ((buf[0] == nsCRT::CR  || buf[0] == nsCRT::LF) &&
                        (buf[1] == ' ' || buf[1] == '\t'))
    {
      buf += 2;
      goto SEARCH_NEWLINE;
    }
    
    if (header)
      header->length = buf - header->value;
    
    if (*buf == nsCRT::CR || *buf == nsCRT::LF)
    {
      char *last = buf;
      if (*buf == nsCRT::CR && buf[1] == nsCRT::LF)
        buf++;
      buf++;
      *last = 0;     /* short-circuit const, and null-terminate header. */
    }
    
    if (header)
    {
      /* More const short-circuitry... */
      /* strip leading whitespace */
      while (IS_SPACE (*header->value))
        header->value++, header->length--;
      /* strip trailing whitespace */
      while (header->length > 0 &&
        IS_SPACE (header->value [header->length - 1]))
        ((char *) header->value) [--header->length] = 0;
      if (header == &receivedBy && LL_IS_ZERO(m_receivedTime))
      {
        // parse Received: header for date.
        // We trust the first header as that is closest to recipient,
        // and less likely to be spoofed.
        nsCAutoString receivedHdr(header->value, header->length);
        PRInt32 lastSemicolon = receivedHdr.RFindChar(';');
        if (lastSemicolon != kNotFound)
        {
          nsCAutoString receivedDate;
          receivedHdr.Right(receivedDate, receivedHdr.Length() - lastSemicolon - 1);
          receivedDate.Trim(" \t\b\r\n");
          PRTime resultTime;
          if (PR_ParseTimeString (receivedDate.get(), PR_FALSE, &resultTime) == PR_SUCCESS)
            m_receivedTime = resultTime;
        }
      }
    }
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Here is the caller graph for this function:

int nsParseMailMessageState::StartNewEnvelope ( const char *  line,
PRUint32  lineLength 
) [virtual]

Definition at line 861 of file nsParseMailbox.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 54 of file nsIMsgParseMailMsgState.idl.

Definition at line 64 of file nsIMsgParseMailMsgState.idl.

Definition at line 152 of file nsParseMailbox.h.

Definition at line 136 of file nsParseMailbox.h.

Definition at line 159 of file nsParseMailbox.h.

Definition at line 160 of file nsParseMailbox.h.

Definition at line 118 of file nsParseMailbox.h.

Definition at line 113 of file nsParseMailbox.h.

Definition at line 106 of file nsParseMailbox.h.

Definition at line 116 of file nsParseMailbox.h.

Definition at line 114 of file nsParseMailbox.h.

Definition at line 154 of file nsParseMailbox.h.

Definition at line 109 of file nsParseMailbox.h.

Definition at line 108 of file nsParseMailbox.h.

Definition at line 112 of file nsParseMailbox.h.

Definition at line 151 of file nsParseMailbox.h.

Definition at line 111 of file nsParseMailbox.h.

Definition at line 135 of file nsParseMailbox.h.

Definition at line 155 of file nsParseMailbox.h.

Definition at line 162 of file nsParseMailbox.h.

Definition at line 69 of file nsIMsgParseMailMsgState.idl.

Definition at line 67 of file nsIMsgParseMailMsgState.idl.

Definition at line 68 of file nsIMsgParseMailMsgState.idl.

Definition at line 65 of file nsIMsgParseMailMsgState.idl.


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