nsresult nsMsgSendLater::BuildHeaders()

in mailnews/compose/src/nsMsgSendLater.cpp [867:1033]


nsresult nsMsgSendLater::BuildHeaders() {
  char* buf = m_headers;
  char* buf_end = buf + m_headersFP;

  PR_FREEIF(m_to);
  PR_FREEIF(m_bcc);
  PR_FREEIF(m_newsgroups);
  PR_FREEIF(m_fcc);
  PR_FREEIF(mIdentityKey);
  PR_FREEIF(mAccountKey);
  m_flags = 0;

  while (buf < buf_end) {
    bool prune_p = false;
    bool do_flags_p = false;
    char* colon = PL_strchr(buf, ':');
    char* end;
    char* value = 0;
    char** header = 0;
    char* header_start = buf;

    if (!colon) break;

    end = colon;
    while (end > buf && (*end == ' ' || *end == '\t')) end--;

    switch (buf[0]) {
      case 'B':
      case 'b':
        if (!PL_strncasecmp("BCC", buf, end - buf)) {
          header = &m_bcc;
        }
        break;
      case 'C':
      case 'c':
        if (!PL_strncasecmp("CC", buf, end - buf))
          header = &m_to;
        else if (!PL_strncasecmp(HEADER_CONTENT_LENGTH, buf, end - buf))
          prune_p = true;
        break;
      case 'F':
      case 'f':
        if (!PL_strncasecmp("FCC", buf, end - buf)) {
          header = &m_fcc;
          prune_p = true;
        }
        break;
      case 'L':
      case 'l':
        if (!PL_strncasecmp("Lines", buf, end - buf)) prune_p = true;
        break;
      case 'M':
      case 'm':
        if (!PL_strncasecmp("Message-ID", buf, end - buf))
          header = &m_messageId;
        break;
      case 'N':
      case 'n':
        if (!PL_strncasecmp("Newsgroups", buf, end - buf))
          header = &m_newsgroups;
        break;
      case 'S':
      case 's':
        if (!PL_strncasecmp("Sender", buf, end - buf)) prune_p = true;
        break;
      case 'T':
      case 't':
        if (!PL_strncasecmp("To", buf, end - buf)) header = &m_to;
        break;
      case 'X':
      case 'x': {
        if (buf + strlen(HEADER_X_MOZILLA_STATUS2) == end &&
            !PL_strncasecmp(HEADER_X_MOZILLA_STATUS2, buf, end - buf))
          prune_p = true;
        else if (buf + strlen(HEADER_X_MOZILLA_STATUS) == end &&
                 !PL_strncasecmp(HEADER_X_MOZILLA_STATUS, buf, end - buf))
          prune_p = do_flags_p = true;
        else if (!PL_strncasecmp(HEADER_X_MOZILLA_DRAFT_INFO, buf, end - buf)) {
          prune_p = true;
          header = &mDraftInfo;
        } else if (!PL_strncasecmp(HEADER_X_MOZILLA_KEYWORDS, buf, end - buf))
          prune_p = true;
        else if (!PL_strncasecmp(HEADER_X_MOZILLA_NEWSHOST, buf, end - buf)) {
          prune_p = true;
        } else if (!PL_strncasecmp(HEADER_X_MOZILLA_IDENTITY_KEY, buf,
                                   end - buf)) {
          prune_p = true;
          header = &mIdentityKey;
        } else if (!PL_strncasecmp(HEADER_X_MOZILLA_ACCOUNT_KEY, buf,
                                   end - buf)) {
          prune_p = true;
          header = &mAccountKey;
        }
        break;
      }
    }

    buf = colon + 1;
    while (*buf == ' ' || *buf == '\t') buf++;

    value = buf;

  SEARCH_NEWLINE:
    while (*buf != 0 && *buf != '\r' && *buf != '\n') 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] == '\r' && buf[1] == '\n') &&
             (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] == '\r' || buf[0] == '\n') &&
             (buf[1] == ' ' || buf[1] == '\t')) {
      buf += 2;
      goto SEARCH_NEWLINE;
    }

    if (header) {
      int L = buf - value;
      if (*header) {
        char* newh = (char*)PR_Realloc((*header), PL_strlen(*header) + L + 10);
        if (!newh) return NS_ERROR_OUT_OF_MEMORY;
        *header = newh;
        newh = (*header) + PL_strlen(*header);
        *newh++ = ',';
        *newh++ = ' ';
        memcpy(newh, value, L);
        newh[L] = 0;
      } else {
        *header = (char*)PR_Malloc(L + 1);
        if (!*header) return NS_ERROR_OUT_OF_MEMORY;
        memcpy((*header), value, L);
        (*header)[L] = 0;
      }
    } else if (do_flags_p) {
      char* s = value;
      PR_ASSERT(*s != ' ' && *s != '\t');
      NS_ASSERTION(MsgIsHex(s, 4), "Expected 4 hex digits for flags.");
      m_flags = MsgUnhex(s, 4);
    }

    if (*buf == '\r' || *buf == '\n') {
      if (*buf == '\r' && buf[1] == '\n') buf++;
      buf++;
    }

    if (prune_p) {
      char* to = header_start;
      char* from = buf;
      while (from < buf_end) *to++ = *from++;
      buf = header_start;
      buf_end = to;
      m_headersFP = buf_end - m_headers;
    }
  }

  m_headers[m_headersFP++] = '\r';
  m_headers[m_headersFP++] = '\n';

  // Now we have parsed out all of the headers we need and we
  // can proceed.
  return NS_OK;
}