Example #1
0
int
MimeHeaders_parse_line (const char *buffer, int32_t size, MimeHeaders *hdrs)
{
  int status = 0;
  int desired_size;

  NS_ASSERTION(hdrs, "1.22 <*****@*****.**> 22 Aug 1999 08:48");
  if (!hdrs) return -1;

  /* Don't try and feed me more data after having fed me a blank line... */
  NS_ASSERTION(!hdrs->done_p, "1.22 <*****@*****.**> 22 Aug 1999 08:48");
  if (hdrs->done_p) return -1;

  if (!buffer || size == 0 || *buffer == '\r' || *buffer == '\n')
  {
    /* If this is a blank line, we're done.
     */
    hdrs->done_p = true;
    return MimeHeaders_build_heads_list(hdrs);
  }

  /* Tack this data on to the end of our copy.
   */
  desired_size = hdrs->all_headers_fp + size + 1;
  if (desired_size >= hdrs->all_headers_size)
  {
    status = mime_GrowBuffer (desired_size, sizeof(char), 255,
                 &hdrs->all_headers, &hdrs->all_headers_size);
    if (status < 0) return status;
  }
  memcpy(hdrs->all_headers+hdrs->all_headers_fp, buffer, size);
  hdrs->all_headers_fp += size;

  return 0;
}
Example #2
0
/* The opposite of mime_LineBuffer(): takes small buffers and packs them
   up into bigger buffers before passing them along.

   Pass in a desired_buffer_size 0 to tell it to flush (for example, in
   in the very last call to this function.)
 */
extern "C" int
mime_ReBuffer (const char *net_buffer, PRInt32 net_buffer_size,
        PRUint32 desired_buffer_size,
        char **bufferP, PRInt32 *buffer_sizeP, PRUint32 *buffer_fpP,
        PRInt32 (*per_buffer_fn) (char *buffer, PRUint32 buffer_size,
                    void *closure),
        void *closure)
{
  int status = 0;

  if (desired_buffer_size >= (PRUint32) (*buffer_sizeP))
  {
    status = mime_GrowBuffer (desired_buffer_size, sizeof(char), 1024,
                 bufferP, buffer_sizeP);
    if (status < 0) return status;
  }

  do
  {
    PRInt32 size = *buffer_sizeP - *buffer_fpP;
    if (size > net_buffer_size)
    size = net_buffer_size;
    if (size > 0)
    {
      memcpy ((*bufferP) + (*buffer_fpP), net_buffer, size);
      (*buffer_fpP) += size;
      net_buffer += size;
      net_buffer_size -= size;
    }

    if (*buffer_fpP > 0 &&
      *buffer_fpP >= desired_buffer_size)
    {
      status = (*per_buffer_fn) ((*bufferP), (*buffer_fpP), closure);
      *buffer_fpP = 0;
      if (status < 0) return status;
    }
  }
  while (net_buffer_size > 0);

  return 0;
}
Example #3
0
/* This function has this clunky interface because it needs to be called
   from outside this module (no MimeObject, etc.)
 */
int
MimeRichtextConvert (const char *line, PRInt32 length,
           int (*output_fn) (const char *buf, PRInt32 size, void *closure),
           void *closure,
           char **obufferP,
           PRInt32 *obuffer_sizeP,
           PRBool enriched_p)
{
  /* RFC 1341 (the original MIME spec) defined text/richtext.
   RFC 1563 superceded text/richtext with text/enriched.
   The changes from text/richtext to text/enriched are:
    - CRLF semantics are different
    - << maps to <
    - These tags were added:
       <VERBATIM>, <NOFILL>, <PARAM>, <FLUSHBOTH>
    - These tags were removed:
       <COMMENT>, <OUTDENT>, <OUTDENTRIGHT>, <SAMEPAGE>, <SUBSCRIPT>,
         <SUPERSCRIPT>, <HEADING>, <FOOTING>, <PARAGRAPH>, <SIGNATURE>,
       <LT>, <NL>, <NP>
   This method implements them both.

   draft-resnick-text-enriched-03.txt is a proposed update to 1563.
    - These tags were added:
      <FONTFAMILY>, <COLOR>, <PARAINDENT>, <LANG>.
    However, all of these rely on the magic <PARAM> tag, which we
    don't implement, so we're ignoring all of these.
   Interesting fact: it's by Peter W. Resnick from Qualcomm (Eudora).
   And it also says "It is fully expected that other text formatting
   standards like HTML and SGML will supplant text/enriched in
   Internet mail."
   */
  int status = 0;
  char *out;
  const char *data_end;
  const char *last_end;
  const char *this_start;
  const char *this_end;
  unsigned int desired_size;

  // The code below must never expand the input by more than 5x;
  // if it does, the desired_size multiplier (5) below must be changed too
#define BGROWTH 5
  if ( (PRUint32)length >= ( (PRUint32) 0xfffffffe)/BGROWTH )
      return -1;
  desired_size = (length * BGROWTH) + 1;
#undef BGROWTH  
  if (desired_size >= (PRUint32) *obuffer_sizeP)
  status = mime_GrowBuffer (desired_size, sizeof(char), 1024,
               obufferP, obuffer_sizeP);
  if (status < 0) return status;

  if (enriched_p)
  {
    for (this_start = line; this_start < line + length; this_start++)
    if (!IS_SPACE (*this_start)) break;
    if (this_start >= line + length) /* blank line */
    {
      PL_strncpyz (*obufferP, "<BR>", *obuffer_sizeP);
      return output_fn (*obufferP, strlen(*obufferP), closure);
    }
  }

  PRUint32 outlen = (PRUint32) *obuffer_sizeP;
  out = *obufferP;
  *out = 0;

  data_end = line + length;
  last_end = line;
  this_start = last_end;
  this_end = this_start;
  PRUint32 addedlen = 0;
  while (this_end < data_end)
  {
    /* Skip forward to next special character. */
    while (this_start < data_end &&
       *this_start != '<' && *this_start != '>' &&
       *this_start != '&')
    this_start++;

    this_end = this_start;

    /* Skip to the end of the tag. */
    if (this_start < data_end && *this_start == '<')
    {
      this_end++;
      while (this_end < data_end &&
         !IS_SPACE(*this_end) &&
         *this_end != '<' && *this_end != '>' &&
         *this_end != '&')
      this_end++;
    }

    this_end++;

    /* Push out the text preceeding the tag. */
    if (last_end && last_end != this_start)
    {
      memcpy (out, last_end, this_start - last_end);
      out += this_start - last_end;
      *out = 0;
      outlen -= (this_start - last_end);
    }

    if (this_start >= data_end)
    break;
    else if (*this_start == '&')
    {
      PL_strncpyz (out, "&amp;", outlen); 
      addedlen = strlen(out);
      outlen -= addedlen; 
      out += addedlen;
    }
    else if (*this_start == '>')
    {
      PL_strncpyz (out, "&gt;", outlen); 
      addedlen = strlen(out); 
      outlen -= addedlen; 
      out += addedlen;
    }
    else if (enriched_p &&
         this_start < data_end + 1 &&
         this_start[0] == '<' &&
         this_start[1] == '<')
    {
      PL_strncpyz (out, "&lt;", outlen); 
      addedlen = strlen(out); 
      outlen -= addedlen; 
      out += addedlen;
    }
    else if (this_start != this_end)
    {
      /* Push out this ID. */
      const char *old = this_start + 1;
      const char *tag_open  = 0;
      const char *tag_close = 0;
      if (*old == '/')
      {
        /* This is </tag> */
        old++;
      }

      switch (*old)
      {
      case 'b': case 'B':
        if (!PL_strncasecmp ("BIGGER>", old, 7))
        tag_open = "<FONT SIZE=\"+1\">", tag_close = "</FONT>";
        else if (!PL_strncasecmp ("BLINK>", old, 5))
        /* Of course, both text/richtext and text/enriched must be
           enhanced *somehow*...  Or else what would people think. */
        tag_open = "<BLINK>", tag_close = "</BLINK>";
        else if (!PL_strncasecmp ("BOLD>", old, 5))
        tag_open = "<B>", tag_close = "</B>";
        break;
      case 'c': case 'C':
        if (!PL_strncasecmp ("CENTER>", old, 7))
        tag_open = "<CENTER>", tag_close = "</CENTER>";
        else if (!enriched_p &&
             !PL_strncasecmp ("COMMENT>", old, 8))
        tag_open = "<!-- ", tag_close = " -->";
        break;
      case 'e': case 'E':
        if (!PL_strncasecmp ("EXCERPT>", old, 8))
        tag_open = "<BLOCKQUOTE>", tag_close = "</BLOCKQUOTE>";
        break;
      case 'f': case 'F':
        if (!PL_strncasecmp ("FIXED>", old, 6))
        tag_open = "<TT>", tag_close = "</TT>";
        else if (enriched_p &&
             !PL_strncasecmp ("FLUSHBOTH>", old, 10))
        tag_open = "<P ALIGN=LEFT>", tag_close = "</P>";
        else if (!PL_strncasecmp ("FLUSHLEFT>", old, 10))
        tag_open = "<P ALIGN=LEFT>", tag_close = "</P>";
        else if (!PL_strncasecmp ("FLUSHRIGHT>", old, 11))
        tag_open = "<P ALIGN=RIGHT>", tag_close = "</P>";
        else if (!enriched_p &&
             !PL_strncasecmp ("FOOTING>", old, 8))
        tag_open = "<H6>", tag_close = "</H6>";
        break;
      case 'h': case 'H':
        if (!enriched_p &&
          !PL_strncasecmp ("HEADING>", old, 8))
        tag_open = "<H6>", tag_close = "</H6>";
        break;
      case 'i': case 'I':
        if (!PL_strncasecmp ("INDENT>", old, 7))
        tag_open = "<UL>", tag_close = "</UL>";
        else if (!PL_strncasecmp ("INDENTRIGHT>", old, 12))
        tag_open = 0, tag_close = 0;
/*        else if (!enriched_p &&
               !PL_strncasecmp ("ISO-8859-", old, 9))
        tag_open = 0, tag_close = 0; */
        else if (!PL_strncasecmp ("ITALIC>", old, 7))
        tag_open = "<I>", tag_close = "</I>";
        break;
      case 'l': case 'L':
        if (!enriched_p &&
          !PL_strncasecmp ("LT>", old, 3))
        tag_open = "&lt;", tag_close = 0;
        break;
      case 'n': case 'N':
        if (!enriched_p &&
          !PL_strncasecmp ("NL>", old, 3))
        tag_open = "<BR>", tag_close = 0;
        if (enriched_p &&
          !PL_strncasecmp ("NOFILL>", old, 7))
        tag_open = "<NOBR>", tag_close = "</NOBR>";
/*        else if (!enriched_p &&
               !PL_strncasecmp ("NO-OP>", old, 6))
        tag_open = 0, tag_close = 0; */
/*        else if (!enriched_p &&
               !PL_strncasecmp ("NP>", old, 3))
        tag_open = 0, tag_close = 0; */
        break;
      case 'o': case 'O':
        if (!enriched_p &&
          !PL_strncasecmp ("OUTDENT>", old, 8))
        tag_open = 0, tag_close = 0;
        else if (!enriched_p &&
             !PL_strncasecmp ("OUTDENTRIGHT>", old, 13))
        tag_open = 0, tag_close = 0;
        break;
      case 'p': case 'P':
        if (enriched_p &&
          !PL_strncasecmp ("PARAM>", old, 6))
        tag_open = "<!-- ", tag_close = " -->";
        else if (!enriched_p &&
             !PL_strncasecmp ("PARAGRAPH>", old, 10))
        tag_open = "<P>", tag_close = 0;
        break;
      case 's': case 'S':
        if (!enriched_p &&
          !PL_strncasecmp ("SAMEPAGE>", old, 9))
        tag_open = 0, tag_close = 0;
        else if (!enriched_p &&
             !PL_strncasecmp ("SIGNATURE>", old, 10))
        tag_open = "<I><FONT SIZE=\"-1\">", tag_close = "</FONT></I>";
        else if (!PL_strncasecmp ("SMALLER>", old, 8))
        tag_open = "<FONT SIZE=\"-1\">", tag_close = "</FONT>";
        else if (!enriched_p &&
             !PL_strncasecmp ("SUBSCRIPT>", old, 10))
        tag_open = "<SUB>", tag_close = "</SUB>";
        else if (!enriched_p &&
             !PL_strncasecmp ("SUPERSCRIPT>", old, 12))
        tag_open = "<SUP>", tag_close = "</SUP>";
        break;
      case 'u': case 'U':
        if (!PL_strncasecmp ("UNDERLINE>", old, 10))
        tag_open = "<U>", tag_close = "</U>";
/*        else if (!enriched_p &&
             !PL_strncasecmp ("US-ASCII>", old, 10))
        tag_open = 0, tag_close = 0; */
        break;
      case 'v': case 'V':
        if (enriched_p &&
          !PL_strncasecmp ("VERBATIM>", old, 9))
        tag_open = "<PRE>", tag_close = "</PRE>";
        break;
      }

      if (this_start[1] == '/')
      {
        if (tag_close) PL_strncpyz (out, tag_close, outlen);
        addedlen = strlen (out);
        outlen -= addedlen;
        out += addedlen;
      }
      else
      {
        if (tag_open) PL_strncpyz (out, tag_open, outlen);
        addedlen = strlen (out);
        outlen -= addedlen;
        out += addedlen;
      }
    }

    /* now go around again */
    last_end = this_end;
    this_start = last_end;
  }
  *out = 0;

  return output_fn (*obufferP, out - *obufferP, closure);
}
Example #4
0
extern "C" int
mime_LineBuffer (const char *net_buffer, PRInt32 net_buffer_size,
        char **bufferP, PRInt32 *buffer_sizeP, PRUint32 *buffer_fpP,
        bool convert_newlines_p,
        PRInt32 (* per_line_fn) (char *line, PRUint32 line_length,
                    void *closure),
        void *closure)
{
  int status = 0;
  if (*buffer_fpP > 0 && *bufferP && (*bufferP)[*buffer_fpP - 1] == '\r' &&
    net_buffer_size > 0 && net_buffer[0] != '\n') {
  /* The last buffer ended with a CR.  The new buffer does not start
     with a LF.  This old buffer should be shipped out and discarded. */
  NS_ASSERTION((PRUint32) *buffer_sizeP > *buffer_fpP, "1.1 <*****@*****.**> 19 Mar 1999 12:00");
  if ((PRUint32) *buffer_sizeP <= *buffer_fpP) return -1;
  status = convert_and_send_buffer(*bufferP, *buffer_fpP,
                     convert_newlines_p,
                     per_line_fn, closure);
  if (status < 0) return status;
  *buffer_fpP = 0;
  }
  while (net_buffer_size > 0)
  {
    const char *net_buffer_end = net_buffer + net_buffer_size;
    const char *newline = 0;
    const char *s;


    for (s = net_buffer; s < net_buffer_end; s++)
    {
      /* Move forward in the buffer until the first newline.
       Stop when we see CRLF, CR, or LF, or the end of the buffer.
       *But*, if we see a lone CR at the *very end* of the buffer,
       treat this as if we had reached the end of the buffer without
       seeing a line terminator.  This is to catch the case of the
       buffers splitting a CRLF pair, as in "FOO\r\nBAR\r" "\nBAZ\r\n".
       */
      if (*s == '\r' || *s == '\n')
      {
        newline = s;
        if (newline[0] == '\r')
        {
          if (s == net_buffer_end - 1)
          {
            /* CR at end - wait for the next character. */
            newline = 0;
            break;
          }
          else if (newline[1] == '\n')
          /* CRLF seen; swallow both. */
          newline++;
        }
        newline++;
        break;
      }
    }

    /* Ensure room in the net_buffer and append some or all of the current
     chunk of data to it. */
    {
    const char *end = (newline ? newline : net_buffer_end);
    PRUint32 desired_size = (end - net_buffer) + (*buffer_fpP) + 1;

    if (desired_size >= (PRUint32) (*buffer_sizeP))
      {
      status = mime_GrowBuffer (desired_size, sizeof(char), 1024,
                   bufferP, buffer_sizeP);
      if (status < 0) return status;
      }
    memcpy ((*bufferP) + (*buffer_fpP), net_buffer, (end - net_buffer));
    (*buffer_fpP) += (end - net_buffer);
        (*bufferP)[*buffer_fpP] = '\0';
    }

    /* Now *bufferP contains either a complete line, or as complete
     a line as we have read so far.

     If we have a line, process it, and then remove it from `*bufferP'.
     Then go around the loop again, until we drain the incoming data.
     */
    if (!newline)
    return 0;

    status = convert_and_send_buffer(*bufferP, *buffer_fpP,
                       convert_newlines_p,
                       per_line_fn, closure);
    if (status < 0)
      return status;

    net_buffer_size -= (newline - net_buffer);
    net_buffer = newline;
    (*buffer_fpP) = 0;
  }
  return 0;
}