Back to index

lightning-sunbird  0.9+nobinonly
Defines | Functions | Variables
mimetext.cpp File Reference
#include "mimetext.h"
#include "mimebuf.h"
#include "mimethtm.h"
#include "comi18n.h"
#include "mimemoz2.h"
#include "prlog.h"
#include "prmem.h"
#include "plstr.h"
#include "nsCRT.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsIServiceManager.h"
#include "nsIPrefLocalizedString.h"
#include "nsMsgUtils.h"
#include "nsMimeTypes.h"
#include "nsReadableUtils.h"

Go to the source code of this file.

Defines

#define MIME_SUPERCLASS   mimeLeafClass
#define MimeInlineText_grow_cbuffer(text, desired_size)

Functions

 MimeDefClass (MimeInlineText, MimeInlineTextClass, mimeInlineTextClass,&MIME_SUPERCLASS)
static int MimeInlineText_initialize (MimeObject *)
static void MimeInlineText_finalize (MimeObject *)
static int MimeInlineText_rot13_line (MimeObject *, char *line, PRInt32 length)
static int MimeInlineText_parse_eof (MimeObject *obj, PRBool abort_p)
static int MimeInlineText_parse_end (MimeObject *, PRBool)
static int MimeInlineText_parse_decoded_buffer (const char *, PRInt32, MimeObject *)
static int MimeInlineText_rotate_convert_and_parse_line (char *, PRInt32, MimeObject *)
static int MimeInlineText_open_dam (char *line, PRInt32 length, MimeObject *obj)
static int MimeInlineText_initializeCharset (MimeObject *obj)
static int MimeInlineTextClassInitialize (MimeInlineTextClass *clazz)
static int MimeInlineText_convert_and_parse_line (char *line, PRInt32 length, MimeObject *obj)

Variables

static const unsigned char MimeInlineText_rot13_table [256]

Define Documentation

Definition at line 63 of file mimetext.cpp.

#define MimeInlineText_grow_cbuffer (   text,
  desired_size 
)
Value:
(((desired_size) >= (text)->cbuffer_size) ? \
   mime_GrowBuffer ((desired_size), sizeof(char), 100, \
                               &(text)->cbuffer, &(text)->cbuffer_size) \
   : 0)

Definition at line 363 of file mimetext.cpp.


Function Documentation

MimeDefClass ( MimeInlineText  ,
MimeInlineTextClass  ,
mimeInlineTextClass  ,
MIME_SUPERCLASS 
)
static int MimeInlineText_convert_and_parse_line ( char *  line,
PRInt32  length,
MimeObject obj 
) [static]

Definition at line 370 of file mimetext.cpp.

{
  int status;
  char *converted = 0;
  PRInt32 converted_len = 0;
  
  MimeInlineText *text = (MimeInlineText *) obj;

  //in case of charset autodetection, charset can be override by meta charset
  if (text->charsetOverridable) {
    if (mime_typep(obj, (MimeObjectClass *) &mimeInlineTextHTMLClass))
    {
      MimeInlineTextHTML  *textHTML = (MimeInlineTextHTML *) obj;
      if (textHTML->charset && 
          *textHTML->charset &&
          nsCRT::strcmp(textHTML->charset, text->charset))
      {
        //if meta tag specified charset is different from our detected result, use meta charset.
        //but we don't want to redo previous lines
        MIME_get_unicode_decoder(textHTML->charset, getter_AddRefs(text->inputDecoder));
        PR_FREEIF(text->charset);
        text->charset = nsCRT::strdup(textHTML->charset);

        //update MsgWindow charset if we are instructed to do so
        if (text->needUpdateMsgWinCharset && *text->charset)
          SetMailCharacterSetToMsgWindow(obj, text->charset);
      }
    }
  }

  //initiate decoder if not yet
  if (text->inputDecoder == nsnull)
    MIME_get_unicode_decoder(text->charset, getter_AddRefs(text->inputDecoder));
  // If no decoder found, use ""UTF-8"", that will map most non-US-ASCII chars as invalid
  // A pure-ASCII only decoder would be better, but there is none
  if (text->inputDecoder == nsnull)
    MIME_get_unicode_decoder("UTF-8", getter_AddRefs(text->inputDecoder));
  if (text->utf8Encoder == nsnull)
    MIME_get_unicode_encoder("UTF-8", getter_AddRefs(text->utf8Encoder));

  PRBool useInputCharsetConverter = obj->options->m_inputCharsetToUnicodeDecoder && !nsCRT::strcasecmp(text->charset, obj->options->charsetForCachedInputDecoder.get());

  if (useInputCharsetConverter)
    status = obj->options->charset_conversion_fn(line, length,
                         text->charset,
                                                                                     "UTF-8",
                                                                                     &converted,
                                                                                     &converted_len,
                         obj->options->stream_closure, obj->options->m_inputCharsetToUnicodeDecoder,
                       obj->options->m_unicodeToUTF8Encoder);
  else
    status = obj->options->charset_conversion_fn(line, length,
                         text->charset,
                                                                                     "UTF-8",
                                                                                     &converted,
                                                                                     &converted_len,
                         obj->options->stream_closure, (nsIUnicodeDecoder*)text->inputDecoder,
                         (nsIUnicodeEncoder*)text->utf8Encoder);

  if (status < 0)
  {
    PR_FREEIF(converted);
    return status;
  }

  if (converted)
  {
    line = converted;
    length = converted_len;
  }

  /* Now that the line has been converted, call the subclass's parse_line
        method with the decoded data. */
  status = obj->clazz->parse_line(line, length, obj);
  PR_FREEIF(converted);

  return status;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void MimeInlineText_finalize ( MimeObject obj) [static]

Definition at line 206 of file mimetext.cpp.

{
  MimeInlineText *text = (MimeInlineText *) obj;

  obj->clazz->parse_eof (obj, PR_FALSE);
  obj->clazz->parse_end (obj, PR_FALSE);

  text->inputDecoder = nsnull;
  text->utf8Encoder = nsnull;
  PR_FREEIF(text->charset);

  /* Should have been freed by parse_eof, but just in case... */
  PR_ASSERT(!text->cbuffer);
  PR_FREEIF (text->cbuffer);

  if (text->inputAutodetect) {
    PR_FREEIF(text->lineDamBuffer);
    PR_FREEIF(text->lineDamPtrs);
    text->inputAutodetect = PR_FALSE;
  }

  ((MimeObjectClass*)&MIME_SUPERCLASS)->finalize (obj);
}

Here is the caller graph for this function:

static int MimeInlineText_initialize ( MimeObject obj) [static]

Definition at line 95 of file mimetext.cpp.

{
  /* This is an abstract class; it shouldn't be directly instantiated. */
  PR_ASSERT(obj->clazz != (MimeObjectClass *) &mimeInlineTextClass);

  ((MimeInlineText *) obj)->initializeCharset = PR_FALSE;
  ((MimeInlineText *) obj)->needUpdateMsgWinCharset = PR_FALSE;
  return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(obj);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int MimeInlineText_initializeCharset ( MimeObject obj) [static]

Definition at line 105 of file mimetext.cpp.

{
  MimeInlineText  *text = (MimeInlineText *) obj;

  text->inputAutodetect = PR_FALSE;
  text->charsetOverridable = PR_FALSE;
  
  /* Figure out an appropriate charset for this object.
  */
  if (!text->charset && obj->headers)
  {
    if (obj->options && obj->options->override_charset)
    {
      text->charset = nsCRT::strdup(obj->options->default_charset);
    }
    else
    {
      char *ct = MimeHeaders_get (obj->headers, HEADER_CONTENT_TYPE,
                                  PR_FALSE, PR_FALSE);
      if (ct)
      {
        text->charset = MimeHeaders_get_parameter (ct, "charset", NULL, NULL);
        PR_Free(ct);
      }
    
      if (!text->charset)
      {
        /* If we didn't find "Content-Type: ...; charset=XX" then look
           for "X-Sun-Charset: XX" instead.  (Maybe this should be done
           in MimeSunAttachmentClass, but it's harder there than here.)
         */
        text->charset = MimeHeaders_get (obj->headers,
                                          HEADER_X_SUN_CHARSET,
                                          PR_FALSE, PR_FALSE);
      }

      /* iMIP entities without an explicit charset parameter default to
       US-ASCII (RFC 2447, section 2.4). However, Microsoft Outlook generates
       UTF-8 but omits the charset parameter.
       When no charset is defined by the container (e.g. iMIP), iCalendar
       files default to UTF-8 (RFC 2445, section 4.1.4).
       */
      if (!text->charset &&
          obj->content_type &&
          !PL_strcasecmp(obj->content_type, TEXT_CALENDAR))
        text->charset = strdup("UTF-8");

      if (!text->charset)
      {
        nsresult res;
        
        text->charsetOverridable = PR_TRUE;

        nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &res)); 
        if (NS_SUCCEEDED(res))
        {
          nsCOMPtr<nsIPrefLocalizedString> str;
          if (NS_SUCCEEDED(prefBranch->GetComplexValue("intl.charset.detector", NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(str)))) {
            //only if we can get autodetector name correctly, do we set this to true
            text->inputAutodetect = PR_TRUE;
          }
        }
        
        if (obj->options && obj->options->default_charset)
          text->charset = nsCRT::strdup(obj->options->default_charset);
        else
        {
          if (NS_SUCCEEDED(res))
          {
            nsXPIDLString value;
            NS_GetLocalizedUnicharPreferenceWithDefault(prefBranch, "mailnews.view_default_charset", EmptyString(), value);
            text->charset = ToNewUTF8String(value);
          }
          else
            text->charset = nsCRT::strdup("");
        }
      } 
    }
  }
  
  if (text->inputAutodetect)
  {
    //we need to prepare lineDam for charset detection
    text->lineDamBuffer = (char*)PR_Malloc(DAM_MAX_BUFFER_SIZE);
    text->lineDamPtrs = (char**)PR_Malloc(DAM_MAX_LINES*sizeof(char*));
    text->curDamOffset = 0;
    text->lastLineInDam = 0;
    if (!text->lineDamBuffer || !text->lineDamPtrs)
    {
      text->inputAutodetect = PR_FALSE;
      PR_FREEIF(text->lineDamBuffer);
      PR_FREEIF(text->lineDamPtrs);
    }
  }

  text->initializeCharset = PR_TRUE;

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int MimeInlineText_open_dam ( char *  line,
PRInt32  length,
MimeObject obj 
) [static]

Definition at line 452 of file mimetext.cpp.

{
  MimeInlineText *text = (MimeInlineText *) obj;
  const char* detectedCharset = nsnull;
  nsresult res = NS_OK;
  int status = 0;
  PRInt32 i;

  if (text->curDamOffset <= 0) {
    //there is nothing in dam, use current line for detection
    if (length > 0) {
      res = MIME_detect_charset(line, length, &detectedCharset);  
    }
  } else {
    //we have stuff in dam, use the one 
    res = MIME_detect_charset(text->lineDamBuffer, text->curDamOffset, &detectedCharset);  
  }

  //set the charset for this obj
  if (NS_SUCCEEDED(res) && detectedCharset && *detectedCharset)  {
    PR_FREEIF(text->charset);
    text->charset = nsCRT::strdup(detectedCharset);

    //update MsgWindow charset if we are instructed to do so
    if (text->needUpdateMsgWinCharset && *text->charset)
      SetMailCharacterSetToMsgWindow(obj, text->charset);
  }

  //process dam and line using the charset
  if (text->curDamOffset) {
    for (i = 0; i < text->lastLineInDam-1; i++)
    {
      status = MimeInlineText_convert_and_parse_line(
                text->lineDamPtrs[i],  
                text->lineDamPtrs[i+1] - text->lineDamPtrs[i],
                obj  );
    }
    status = MimeInlineText_convert_and_parse_line(
                text->lineDamPtrs[i],
                text->lineDamBuffer + text->curDamOffset - text->lineDamPtrs[i],
                obj );
  }

  if (length)
    status = MimeInlineText_convert_and_parse_line(line, length, obj);

  PR_Free(text->lineDamPtrs);
  PR_Free(text->lineDamBuffer);
  text->lineDamPtrs = nsnull;
  text->lineDamBuffer = nsnull;
  text->inputAutodetect = PR_FALSE;

  return status;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int MimeInlineText_parse_decoded_buffer ( const char *  buf,
PRInt32  size,
MimeObject obj 
) [static]

Definition at line 335 of file mimetext.cpp.

{
  PR_ASSERT(!obj->closed_p);
  if (obj->closed_p) return -1;

  /* MimeLeaf takes care of this. */
  PR_ASSERT(obj->output_p && obj->options && obj->options->output_fn);
  if (!obj->options) return -1;

  /* If we're supposed to write this object, but aren't supposed to convert
        it to HTML, simply pass it through unaltered. */
  if (!obj->options->write_html_p && obj->options->format_out != nsMimeOutput::nsMimeMessageAttach)
       return MimeObject_write(obj, buf, size, PR_TRUE);

  /* This is just like the parse_decoded_buffer method we inherit from the
        MimeLeaf class, except that we line-buffer to our own wrapper on the
        `parse_line' method instead of calling the `parse_line' method directly.
   */
  return mime_LineBuffer (buf, size,
                                           &obj->ibuffer, &obj->ibuffer_size, &obj->ibuffer_fp,
                                           PR_TRUE,
                                           ((int (*PR_CALLBACK) (char *, PRInt32, void *))
                                            /* This cast is to turn void into MimeObject */
                                            MimeInlineText_rotate_convert_and_parse_line),
                                           obj);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int MimeInlineText_parse_end ( MimeObject obj,
PRBool  abort_p 
) [static]

Definition at line 278 of file mimetext.cpp.

{
  MimeInlineText *text = (MimeInlineText *) obj;

  if (obj->parsed_p)
       {
         PR_ASSERT(obj->closed_p);
         return 0;
       }

  /* We won't be needing this buffer any more; nuke it. */
  PR_FREEIF(text->cbuffer);
  text->cbuffer_size = 0;

  return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_end (obj, abort_p);
}

Here is the caller graph for this function:

static int MimeInlineText_parse_eof ( MimeObject obj,
PRBool  abort_p 
) [static]

Definition at line 232 of file mimetext.cpp.

{
  int status;

  if (obj->closed_p) return 0;
  NS_ASSERTION(!obj->parsed_p, "obj already parsed");

  MimeInlineText *text = (MimeInlineText *) obj;

  /* Flush any buffered data from the MimeLeaf's decoder */
  status = ((MimeLeafClass*)&MIME_SUPERCLASS)->close_decoder(obj);
  if (status < 0) return status;

  /* If there is still data in the ibuffer, that means that the last
   line of this part didn't end in a newline; so push it out anyway
   (this means that the parse_line method will be called with a string
   with no trailing newline, which isn't the usual case).  We do this
   here, rather than in MimeObject_parse_eof, because MimeObject isn't
   aware of the rotating-and-converting / charset detection we need to
   do first.
  */
  if (!abort_p && obj->ibuffer_fp > 0)
  {
    status = MimeInlineText_rotate_convert_and_parse_line (obj->ibuffer,
                                                           obj->ibuffer_fp,
                                                           obj);
    obj->ibuffer_fp = 0;
    if (status < 0)
    {
      //we haven't find charset yet? Do it before return
      if (text->inputAutodetect)
        status = MimeInlineText_open_dam(nsnull, 0, obj);

      obj->closed_p = PR_TRUE;
      return status;
    }
  }

  //we haven't find charset yet? now its the time
  if (text->inputAutodetect)
     status = MimeInlineText_open_dam(nsnull, 0, obj);
 
  return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof (obj, abort_p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int MimeInlineText_rot13_line ( MimeObject obj,
char *  line,
PRInt32  length 
) [static]

Definition at line 318 of file mimetext.cpp.

{
  unsigned char *s, *end;
  PR_ASSERT(line);
  if (!line) return -1;
  s = (unsigned char *) line;
  end = s + length;
  while (s < end)
       {
         *s = MimeInlineText_rot13_table[*s];
         s++;
       }
  return 0;
}

Here is the caller graph for this function:

static int MimeInlineText_rotate_convert_and_parse_line ( char *  line,
PRInt32  length,
MimeObject obj 
) [static]

Definition at line 509 of file mimetext.cpp.

{
  int status = 0;
  MimeInlineTextClass *textc = (MimeInlineTextClass *) obj->clazz;

  PR_ASSERT(!obj->closed_p);
  if (obj->closed_p) return -1;

  /* Rotate the line, if desired (this happens on the raw data, before any
        charset conversion.) */
  if (obj->options && obj->options->rot13_p)
       {
         status = textc->rot13_line(obj, line, length);
         if (status < 0) return status;
       }

  // Now convert to the canonical charset, if desired.
  //
  PRBool  doConvert = PR_TRUE;
  // Don't convert vCard data
  if ( ( (obj->content_type) && (!PL_strcasecmp(obj->content_type, TEXT_VCARD)) ) ||
       (obj->options->format_out == nsMimeOutput::nsMimeMessageSaveAs)
       || obj->options->format_out == nsMimeOutput::nsMimeMessageAttach)
    doConvert = PR_FALSE;
    
  // Only convert if the user prefs is false 
  if ( (obj->options && obj->options->charset_conversion_fn) &&
       (!obj->options->force_user_charset) &&
       (doConvert)       
     )
       {
    MimeInlineText  *text = (MimeInlineText *) obj;

    if (!text->initializeCharset)
    {
      MimeInlineText_initializeCharset(obj);
      //update MsgWindow charset if we are instructed to do so
      if (text->needUpdateMsgWinCharset && *text->charset)
        SetMailCharacterSetToMsgWindow(obj, text->charset);
    }

    //if autodetect is on, push line to dam
    if (text->inputAutodetect)
    {
      //see if we reach the lineDam buffer limit, if so, there is no need to keep buffering
      if (text->lastLineInDam >= DAM_MAX_LINES ||
          DAM_MAX_BUFFER_SIZE - text->curDamOffset <= length) {
        //we let open dam process this line as well as thing that already in Dam
        //In case there is nothing in dam because this line is too big, we need to 
        //perform autodetect on this line
        status = MimeInlineText_open_dam(line, length, obj);
      }
      else {
        //buffering current line
        text->lineDamPtrs[text->lastLineInDam] = text->lineDamBuffer + text->curDamOffset;
        memcpy(text->lineDamPtrs[text->lastLineInDam], line, length);
        text->lastLineInDam++;
        text->curDamOffset += length;
      }
    }
    else 
      status = MimeInlineText_convert_and_parse_line(line, length, obj);
       }
  else
    status = obj->clazz->parse_line(line, length, obj);

  return status;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

const unsigned char MimeInlineText_rot13_table[256] [static]
Initial value:
 {
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
  21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
  40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
  59, 60, 61, 62, 63, 64, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
  65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 91, 92, 93, 94, 95, 96,
  110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 97, 98,
  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 123, 124, 125, 126,
  127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
  142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
  157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
  172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
  187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
  202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
  217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
  232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
  247, 248, 249, 250, 251, 252, 253, 254, 255 }

Definition at line 299 of file mimetext.cpp.