Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Functions | Variables
comi18n.cpp File Reference
#include "nsICharsetConverterManager.h"
#include "nsICharsetAlias.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "prtypes.h"
#include "prmem.h"
#include "prlog.h"
#include "prprf.h"
#include "plstr.h"
#include "nsCRT.h"
#include "comi18n.h"
#include "nsIServiceManager.h"
#include "nsIStringCharsetDetector.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsMsgUtils.h"
#include "mimebuf.h"
#include "nsMsgI18N.h"
#include "nsMimeTypes.h"
#include "nsISaveAsCharset.h"
#include "nsHankakuToZenkakuCID.h"
#include "nsReadableUtils.h"
#include "mimehdrs.h"
#include "nsIMIMEHeaderParam.h"
#include "nsNetCID.h"

Go to the source code of this file.

Classes

struct  _RFC822AddressList

Defines

#define NO_Q_ENCODING_NEEDED(ch)
#define IS_UTF8_HEADER(s, h)   ((*(s) & (~(~(h) >> 1))) == (h))
#define IS_UTF8_SUBBYTE(s)   ((*(s) & 0xC0) == 0x80)
#define PUBLIC

Typedefs

typedef struct _RFC822AddressList RFC822AddressList

Functions

static PRInt32 intlmime_encode_q (const unsigned char *src, PRInt32 srcsize, char *out)
static void encodeChunk (const unsigned char *chunk, char *output)
static PRInt32 intlmime_encode_b (const unsigned char *input, PRInt32 inlen, char *output)
static PRBool intlmime_only_ascii_str (const char *s)
static unsigned char * utf8_nextchar (unsigned char *str)
static PRInt32 generate_encodedwords (char *pUTF8, const char *charset, char method, char *output, PRInt32 outlen, PRInt32 output_carryoverlen, PRInt32 foldlen, PRBool foldingonly)
static void destroy_addresslist (RFC822AddressList *p)
static RFC822AddressListconstruct_addresslist (char *s)
static char * apply_rfc2047_encoding (const char *_src, PRBool structured, const char *charset, PRInt32 cursor, PRInt32 foldlen)
char * MIME_DecodeMimeHeader (const char *header, const char *default_charset, PRBool override_charset, PRBool eatContinuations)
 Decode MIME header to UTF-8.
char * MIME_EncodeMimePartIIStr (const char *header, PRBool structured, const char *mailCharset, const PRInt32 fieldNameLen, const PRInt32 encodedWordSize)
 Encode an input string into RFC 2047 form.
char * NextChar_UTF8 (char *str)
 Get a next character position in an UTF-8 string.
nsresult MIME_detect_charset (const char *aBuf, PRInt32 aLength, const char **aCharset)
nsresult MIME_get_unicode_decoder (const char *aInputCharset, nsIUnicodeDecoder **aDecoder)
nsresult MIME_get_unicode_encoder (const char *aOutputCharset, nsIUnicodeEncoder **aEncoder)

Variables

static char basis_64 [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
static const char hexdigits [] = "0123456789ABCDEF"

Class Documentation

struct _RFC822AddressList

Definition at line 457 of file comi18n.cpp.

Collaboration diagram for _RFC822AddressList:
Class Members
char * addrspec
PRBool asciionly
char * displayname
struct _RFC822AddressList * next

Define Documentation

#define IS_UTF8_HEADER (   s,
 
)    ((*(s) & (~(~(h) >> 1))) == (h))

Definition at line 172 of file comi18n.cpp.

#define IS_UTF8_SUBBYTE (   s)    ((*(s) & 0xC0) == 0x80)

Definition at line 173 of file comi18n.cpp.

Value:
(((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z') || \
   ((ch) >= '0' && (ch) <= '9') ||  (ch) == '!' || (ch) == '*' ||  \
    (ch) == '+' || (ch) == '-' || (ch) == '/')

Definition at line 76 of file comi18n.cpp.

Definition at line 742 of file comi18n.cpp.


Typedef Documentation


Function Documentation

static char* apply_rfc2047_encoding ( const char *  _src,
PRBool  structured,
const char *  charset,
PRInt32  cursor,
PRInt32  foldlen 
) [static]

Definition at line 602 of file comi18n.cpp.

{
  RFC822AddressList  *listhead, *list;
  PRInt32   outputlen, usedlen;
  char  *src, *src_head, *output, *outputtail;
  char  method = nsMsgI18Nmultibyte_charset(charset) ? 'B' : 'Q';

  if (!_src)
    return nsnull;

  //<TAB>=?<charset>?<B/Q>?...?=<CRLF>
  PRInt32 perLineOverhead = strlen(charset) + 10;

  if (perLineOverhead > foldlen || (src = src_head = nsCRT::strdup(_src)) == nsnull)
    return nsnull;

  /* allocate enough buffer for conversion, this way it can avoid
     do another memory allocation which is expensive
   */
  PRInt32 charsPerLine = (foldlen - perLineOverhead) / 4;
  PRInt32 maxNumLines = (strlen(src) / charsPerLine) + 1;
  outputlen = strlen(src) * 4 + (maxNumLines * perLineOverhead) + 20 /* fudge */;
  if ((outputtail = output = (char *)PR_Malloc(outputlen)) == nsnull) {
    PR_Free(src_head);
    return nsnull;
  }

  if (structured) {
    listhead = list = construct_addresslist(src);
    if (!list) {
      PR_Free(output);
      output = nsnull;
    }
    else {
      for (; list && (outputlen > 0); list = list->next) {
        if (list->displayname) {
          if (list->asciionly && list->addrspec) {
            PRInt32 len = cursor + strlen(list->displayname) + strlen(list->addrspec);
            if (foldlen < len && len < 998) { /* see RFC 2822 for magic number 998 */
              PR_snprintf(outputtail, outputlen - 1, (list == listhead || cursor == 1) ? "%s %s%s" : "\r\n %s %s%s", list->displayname, list->addrspec, list->next ? ",\r\n " : "");
              usedlen = strlen(outputtail);
              outputtail += usedlen;
              outputlen -= usedlen;
              cursor = 1;
              continue;
            }
          }
          cursor = generate_encodedwords(list->displayname, charset, method, outputtail, outputlen, cursor, foldlen, list->asciionly);
          if (cursor < 0) {
            PR_Free(output);
            output = nsnull;
            break;
          }
          usedlen = strlen(outputtail);
          outputtail += usedlen;
          outputlen -= usedlen;
        }
        if (list->addrspec) {
          usedlen = strlen(list->addrspec);
          if (cursor + usedlen > foldlen) {
            if (PR_snprintf(outputtail, outputlen - 1, "\r\n %s", list->addrspec) < 0) {
              PR_Free(output);
              destroy_addresslist(listhead);
              return nsnull;
            }
            usedlen += 3;         /* FWS + addr-spec */
            cursor = usedlen - 2; /* \r\n */
          }
          else {
            if (PR_snprintf(outputtail, outputlen - 1, list->displayname ? " %s" : "%s", list->addrspec) < 0) {
              PR_Free(output);
              destroy_addresslist(listhead);
              return nsnull;
            }
            if (list->displayname)
              usedlen++;
            cursor += usedlen;
          }
          outputtail += usedlen;
          outputlen -= usedlen;
        }
        else {
          PR_Free(output);
          output = nsnull;
          break;
        }
        if (list->next) {
          PL_strncpyz(outputtail, ", ", outputlen);
          cursor += 2;
          outputtail += 2;
          outputlen -= 2;
        }
      }
      destroy_addresslist(listhead);
    }
  }
  else {
    char *spacepos = nsnull, *org_output = output;
    /* show some mercy to stupid ML systems which don't know 
       how to respect MIME encoded subject */
    for (char *p = src; *p && !(*p & 0x80); p++) {
      if (*p == 0x20 || *p == TAB)
        spacepos = p;
    }
    if (spacepos) {
      char head[kMAX_CSNAME+4+1];
      PRInt32  overhead, skiplen;
      if (PR_snprintf(head, sizeof(head) - 1, "=?%s?%c?", charset, method) < 0) {
        PR_Free(output);
        return nsnull;
      }
      overhead = strlen(head) + 2 + 4; // 2 : "?=", 4 : a B-encoded chunk
      skiplen = spacepos + 1 - src;
      if (cursor + skiplen + overhead < foldlen) {
        char tmp = *(spacepos + 1);
        *(spacepos + 1) = '\0';
        PL_strncpyz(output, src, outputlen);
        output += skiplen;
        outputlen -= skiplen;
        cursor += skiplen;
        src += skiplen;
        *src = tmp;
      }
    }
    PRBool asciionly = intlmime_only_ascii_str(src);
    if (generate_encodedwords(src, charset, method, output, outputlen, cursor, foldlen, asciionly) < 0) {
      PR_Free(org_output);
      org_output = nsnull;
    }
    output = org_output;
  }

  PR_Free(src_head);

  return output;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static RFC822AddressList* construct_addresslist ( char *  s) [static]

Definition at line 476 of file comi18n.cpp.

{
  PRBool  quoted = PR_FALSE, angle_addr = PR_FALSE;
  PRInt32  comment = 0;
  char *displayname = nsnull, *addrspec = nsnull;
  static RFC822AddressList  listinit;
  RFC822AddressList  *listhead = (RFC822AddressList *)PR_Malloc(sizeof(RFC822AddressList));
  RFC822AddressList  *list = listhead;

  if (!list)
    return nsnull;

  while (*s == ' ' || *s == TAB)
    ++s;

  for (*list = listinit; *s; ++s) {
    if (*s == '\\') {
      if (quoted || comment) {
        ++s;
        continue;
      }
    }
    else if (*s == '(' || *s == ')') {
      if (!quoted) {
        if (*s == '(') {
          if (comment++ == 0)
            displayname = s + 1;
        }
        else {
          if (--comment == 0) {
            *s = '\0';
            PR_FREEIF(list->displayname);
            list->displayname = nsCRT::strdup(displayname);
            list->asciionly = intlmime_only_ascii_str(displayname);
            *s = ')';
          }
        }
        continue;
      }
    }
    else if (*s == '"') {
      if (!comment && !angle_addr) {
        quoted = !quoted;
        if (quoted)
          displayname = s;
        else {
          char tmp = *(s+1);
          *(s+1) = '\0';
          PR_FREEIF(list->displayname);
          list->displayname = nsCRT::strdup(displayname);
          list->asciionly = intlmime_only_ascii_str(displayname);
          *(s+1) = tmp;
        }
        continue;
      }
    }
    else if (*s == '<' || *s == '>') {
      if (!quoted && !comment) {
        if (*s == '<') {
          angle_addr = PR_TRUE;
          addrspec = s;
          if (displayname) {
            char *e = s - 1, tmp;
            while (*e == TAB || *e == ' ')
              --e;
            tmp = *++e;
            *e = '\0';
            PR_FREEIF(list->displayname);
            list->displayname = nsCRT::strdup(displayname);
            list->asciionly = intlmime_only_ascii_str(displayname);
            *e = tmp;
          }
        }
        else {
          char tmp;
          angle_addr = PR_FALSE;
          tmp = *(s+1);
          *(s+1) = '\0';
          PR_FREEIF(list->addrspec);
          list->addrspec = nsCRT::strdup(addrspec);
          *(s+1) = tmp;
        }
        continue;
      }
    }
    if (!quoted && !comment && !angle_addr) {
      /* address-list separator. end of this address */
      if (*s == ',') {
        /* deal with addr-spec only address */
        if (!addrspec && displayname) {
          *s = '\0';
          list->addrspec = nsCRT::strdup(displayname);
          /* and don't forget to free the display name in the list, in that case it's bogus */
          PR_FREEIF(list->displayname);
        }
        /* prepare for next address */
        addrspec = displayname = nsnull;
        list->next = (RFC822AddressList *)PR_Malloc(sizeof(RFC822AddressList));
        list = list->next;
        *list = listinit;
        /* eat spaces */
        ++s;
        while (*s == ' ' || *s == TAB)
          ++s;
        if (*s == '\r' && *(s+1) == '\n' && (*(s+2) == ' ' || *(s+2) == TAB))
          s += 2;
        else
          --s;
      }
      else if (!displayname && *s != ' ' && *s != TAB)
        displayname = s;
    }
  }

  /* deal with addr-spec only address comes at last */
  if (!addrspec && displayname)
  {
    list->addrspec = nsCRT::strdup(displayname);
    /* and don't forget to free the display name in the list, in that case it's bogus */
    PR_FREEIF(list->displayname);
  }

  return listhead;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void destroy_addresslist ( RFC822AddressList p) [static]

Definition at line 465 of file comi18n.cpp.

Here is the caller graph for this function:

static void encodeChunk ( const unsigned char *  chunk,
char *  output 
) [static]

Definition at line 108 of file comi18n.cpp.

{
  register PRInt32 offset;

  offset = *chunk >> 2;
  *output++ = basis_64[offset];

  offset = ((*chunk << 4) & 0x30) + (*(chunk+1) >> 4);
  *output++ = basis_64[offset];

  if (*(chunk+1)) {
    offset = ((*(chunk+1) & 0x0f) << 2) + ((*(chunk+2) & 0xc0) >> 6);
    *output++ = basis_64[offset];
  }
  else
    *output++ = '=';

  if (*(chunk+2)) {
    offset = *(chunk+2) & 0x3f;
    *output++ = basis_64[offset];
  }
  else
    *output++ = '=';
}

Here is the caller graph for this function:

static PRInt32 generate_encodedwords ( char *  pUTF8,
const char *  charset,
char  method,
char *  output,
PRInt32  outlen,
PRInt32  output_carryoverlen,
PRInt32  foldlen,
PRBool  foldingonly 
) [static]

Definition at line 199 of file comi18n.cpp.

{
  NS_ASSERTION(output_carryoverlen > 0, "output_carryoverlen must be > 0"); 

  nsCOMPtr <nsISaveAsCharset> conv;
  PRUnichar *_pUCS2 = nsnull, *pUCS2 = nsnull, *pUCS2Head = nsnull, cUCS2Tmp = 0;
  char  *ibuf, *o = output;
  char  encodedword_head[kMAX_CSNAME+4+1];
  nsCAutoString _charset;
  char  *pUTF8Head = nsnull, cUTF8Tmp = 0;
  PRInt32   olen = 0, obufsize = outlen, offset, linelen = output_carryoverlen, convlen = 0;
  PRInt32   encodedword_headlen = 0, encodedword_taillen = foldingonly ? 0 : 2; // "?="
  nsresult rv;

  encodedword_head[0] = 0;

  if (!foldingonly) {

    // Deal with UCS2 pointer
    pUCS2 = _pUCS2 = ToNewUnicode(NS_ConvertUTF8toUCS2(pUTF8));
    if (!pUCS2)
      return -1;

    // Resolve charset alias
    {
      nsCOMPtr <nsICharsetAlias> calias = do_GetService(NS_CHARSETALIAS_CONTRACTID, &rv);
      nsCOMPtr <nsIAtom> charsetAtom;
      charset = !nsCRT::strcasecmp(charset, "us-ascii") ? "ISO-8859-1" : charset;
      rv = calias->GetPreferred(nsDependentCString(charset),
                                _charset);
      if (NS_FAILED(rv)) {
        if (_pUCS2)
          nsMemory::Free(_pUCS2);
        return -1;
      }

      // this is so nasty, but _charset won't be going away..
      charset = _charset.get();
    }

    // Prepare MIME encoded-word head with official charset name
    if (PR_snprintf(encodedword_head, sizeof(encodedword_head)-1, "=?%s?%c?", charset, method) < 0) {
      if (_pUCS2)
        nsMemory::Free(_pUCS2);
      return -1;
    }
    encodedword_headlen = strlen(encodedword_head);

    // Load HANKAKU-KANA prefrence and cache it.
    if (!nsCRT::strcasecmp("ISO-2022-JP", charset)) {
      static PRInt32  conv_kana = -1;
      if (conv_kana < 0) {
        nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
        if (NS_SUCCEEDED(rv)) {
          PRBool val = PR_FALSE; // no pref means need the mapping
          prefBranch->GetBoolPref("mailnews.send_hankaku_kana", &val);
          conv_kana = val ? 0 : 1;
        }
      }
      // Do nsITextTransform if needed
      if (conv_kana > 0) {
        nsCOMPtr <nsITextTransform> textTransform =
            do_CreateInstance(NS_HANKAKUTOZENKAKU_CONTRACTID, &rv);
        if (NS_SUCCEEDED(rv)) {
          nsString text(pUCS2), result;
          rv = textTransform->Change(pUCS2, nsCRT::strlen(pUCS2), result);
          if (NS_SUCCEEDED(rv)) {
            if (_pUCS2)
              nsMemory::Free(_pUCS2);
            pUCS2 = _pUCS2 = ToNewUnicode(result);
            if (!pUCS2)
              return -1;
          }
        }
      }
    }

    // Create an instance of charset converter and initialize it
    conv = do_CreateInstance(NS_SAVEASCHARSET_CONTRACTID, &rv);
    if(NS_SUCCEEDED(rv)) {
      rv = conv->Init(charset, 
                       nsISaveAsCharset::attr_FallbackQuestionMark + nsISaveAsCharset::attr_EntityAfterCharsetConv, 
                       nsIEntityConverter::transliterate);
    }
    if (NS_FAILED(rv)) {
      if (_pUCS2)
        nsMemory::Free(_pUCS2);
      return -1;
    }
  } // if (!foldingonly)

  /*
     See if folding needs to happen.
     If carried over length is already too long to hold
     encoded-word header and trailer length, it's too obvious
     that we need to fold.  So, don't waste time for calculation.
  */
  if (linelen + encodedword_headlen + encodedword_taillen < foldlen) {
    if (foldingonly) {
      offset = strlen(pUTF8Head = pUTF8);
      pUTF8 += offset;
    }
    else {
      rv = conv->Convert(pUCS2, &ibuf);
      if (NS_FAILED(rv) || ibuf == nsnull) {
        if (_pUCS2)
          nsMemory::Free(_pUCS2);
        return -1; //error
      }
      if (method == 'B') {
        /* 4 / 3 = B encoding multiplier */
        offset = strlen(ibuf) * 4 / 3;
      }
      else {
        /* 3 = Q encoding multiplier */
        offset = 0;
        for (PRInt32 i = 0; *(ibuf+i); i++)
          offset += NO_Q_ENCODING_NEEDED(*(ibuf+i)) ? 1 : 3;
      }
    }
    if (linelen + encodedword_headlen + offset + encodedword_taillen > foldlen) {
      /* folding has to happen */
      if (foldingonly) {
        pUTF8 = pUTF8Head;
        pUTF8Head = nsnull;
      }
      else
        PR_Free(ibuf);
    }
    else {
      /* no folding needed, let's fall thru */
      PL_strncpyz(o, encodedword_head, obufsize);
      olen += encodedword_headlen;
      linelen += encodedword_headlen;
      obufsize -= encodedword_headlen;
      o += encodedword_headlen;
      if (!foldingonly)
        *pUCS2 = 0;
    }
  }
  else {
    PL_strncpyz(o, "\r\n ", obufsize);
    olen += 3;
    o += 3;
    obufsize -= 3;
    linelen = 1;
  }

  /*
    Let's do the nasty RFC-2047 & folding stuff
  */

  while ((foldingonly ? *pUTF8 : *pUCS2) && (olen < outlen)) {
    PL_strncpyz(o, encodedword_head, obufsize);
    olen += encodedword_headlen;
    linelen += encodedword_headlen;
    obufsize -= encodedword_headlen;
    o += encodedword_headlen;
    olen += encodedword_taillen;
    if (foldingonly)
      pUTF8Head = pUTF8;
    else
      pUCS2Head = pUCS2;

    while ((foldingonly ? *pUTF8 : *pUCS2) && (olen < outlen)) {
      if (foldingonly) {
        ++pUTF8;
        for (;;) {
          if (*pUTF8 == ' ' || *pUTF8 == TAB || !*pUTF8) {
            offset = pUTF8 - pUTF8Head;
            cUTF8Tmp = *pUTF8;
            *pUTF8 = 0;
            break;
          }
          ++pUTF8;
        }
      }
      else {
        convlen = ++pUCS2 - pUCS2Head;
        cUCS2Tmp = *(pUCS2Head + convlen);
        *(pUCS2Head + convlen) = 0;
        rv = conv->Convert(pUCS2Head, &ibuf);
        *(pUCS2Head + convlen) = cUCS2Tmp;
        if (NS_FAILED(rv) || ibuf == nsnull) {
          if (_pUCS2)
            nsMemory::Free(_pUCS2);
          return -1; //error
        }
        if (method == 'B') {
          /* 4 / 3 = B encoding multiplier */
          offset = strlen(ibuf) * 4 / 3;
        }
        else {
          /* 3 = Q encoding multiplier */
          offset = 0;
          for (PRInt32 i = 0; *(ibuf+i); i++)
            offset += NO_Q_ENCODING_NEEDED(*(ibuf+i)) ? 1 : 3;
        }
      }
      if (linelen + offset > foldlen) {
process_lastline:
        PRInt32 enclen;
        if (foldingonly) {
          PL_strncpyz(o, pUTF8Head, obufsize);
          enclen = strlen(o);
          obufsize -= enclen;
          o += enclen;
          *pUTF8 = cUTF8Tmp;
        }
        else {
          if (method == 'B')
            enclen = intlmime_encode_b((const unsigned char *)ibuf, strlen(ibuf), o);
          else
            enclen = intlmime_encode_q((const unsigned char *)ibuf, strlen(ibuf), o);
          PR_Free(ibuf);
          o += enclen;
          obufsize -= enclen;
          PL_strncpyz(o, "?=", obufsize);
        }
        o += encodedword_taillen;
        obufsize -= encodedword_taillen;
        olen += enclen;
        if (foldingonly ? *pUTF8 : *pUCS2) { /* not last line */
          PL_strncpyz(o, "\r\n ", obufsize);
          obufsize -= 3;
          o += 3;
          olen += 3;
          linelen = 1;
          if (foldingonly) {
            pUTF8Head = nsnull;
            if (*pUTF8 == ' ' || *pUTF8 == TAB) {
              ++pUTF8;
              if (!*pUTF8)
                return 0;
            }
          }
        }
        else {
          if (_pUCS2)
            nsMemory::Free(_pUCS2);
          return linelen + enclen + encodedword_taillen;
        }
        break;
      }
      else {
        if (foldingonly)
          *pUTF8 = cUTF8Tmp;
        else {
          if (*pUCS2)
            PR_Free(ibuf);
        }
      }
    }
  }

  goto process_lastline;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRInt32 intlmime_encode_b ( const unsigned char *  input,
PRInt32  inlen,
char *  output 
) [static]

Definition at line 134 of file comi18n.cpp.

{
  unsigned char  chunk[3];
  PRInt32   i, len;
  char *head = output;

  for (len = 0; inlen >=3 ; inlen -= 3) {
    for (i = 0; i < 3; i++)
      chunk[i] = *input++;
    encodeChunk(chunk, output);
    output += 4;
    len += 4;
  }

  if (inlen > 0) {
    for (i = 0; i < inlen; i++)
      chunk[i] = *input++;
    for (; i < 3; i++)
      chunk[i] = 0;
    encodeChunk(chunk, output);
    output += 4;
  }

  *output = 0;
  return (output - head);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRInt32 intlmime_encode_q ( const unsigned char *  src,
PRInt32  srcsize,
char *  out 
) [static]

Definition at line 84 of file comi18n.cpp.

{
  const unsigned char *in = (unsigned char *) src;
  const unsigned char *end = in + srcsize;
  char *head = out;

  for (; in < end; in++) {
    if (NO_Q_ENCODING_NEEDED(*in)) {
      *out++ = *in;
    }
    else if (*in == ' ') {
      *out++ = '_';
    }
    else {
      *out++ = '=';
      *out++ = hexdigits[*in >> 4];
      *out++ = hexdigits[*in & 0xF];
    }
  }
  *out = '\0';
  return (out - head);
}

Here is the caller graph for this function:

static PRBool intlmime_only_ascii_str ( const char *  s) [static]

Definition at line 163 of file comi18n.cpp.

{
  for(; *s; s++)
    if(*s & 0x80)
      return PR_FALSE;
  return PR_TRUE;
}

Here is the caller graph for this function:

char* MIME_DecodeMimeHeader ( const char *  header,
const char *  default_charset,
PRBool  override_charset,
PRBool  eatContinuations 
)

Decode MIME header to UTF-8.

Uses MIME_ConvertCharset if the decoded string needs a conversion.

Parameters:
header[IN] A header to decode.
default_charset[IN] Default charset to apply to ulabeled non-UTF-8 8bit data
override_charset[IN] If PR_TRUE, default_charset used instead of any charset labeling other than UTF-8
eatContinuations[IN] If PR_TRUE, unfold headers
Returns:
Decoded buffer (in C string) or return NULL if the header needs no conversion

Definition at line 745 of file comi18n.cpp.

{
  nsresult rv;
  nsCOMPtr <nsIMIMEHeaderParam> mimehdrpar = do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv);
  if (NS_FAILED(rv))
    return nsnull;
  nsCAutoString result;
  rv = mimehdrpar->DecodeRFC2047Header(header, default_charset, override_charset, 
                                       eatContinuations, result);
  if (NS_SUCCEEDED(rv))
    return nsCRT::strdup(result.get());
  return nsnull;
}  

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult MIME_detect_charset ( const char *  aBuf,
PRInt32  aLength,
const char **  aCharset 
)

Definition at line 776 of file comi18n.cpp.

{
  nsresult res = NS_ERROR_UNEXPECTED;
  nsXPIDLString detector_name;
  *aCharset = nsnull;

  NS_GetLocalizedUnicharPreferenceWithDefault(nsnull, "intl.charset.detector", EmptyString(), detector_name);

  if (!detector_name.IsEmpty()) {
    nsCAutoString detector_contractid;
    detector_contractid.AssignLiteral(NS_STRCDETECTOR_CONTRACTID_BASE);

    AppendUTF16toUTF8(detector_name, detector_contractid);
    nsCOMPtr<nsIStringCharsetDetector> detector = do_CreateInstance(detector_contractid.get(), &res);
    if (NS_SUCCEEDED(res)) {
      nsDetectionConfident oConfident;
      res = detector->DoIt(aBuf, aLength, aCharset, oConfident);
      if (NS_SUCCEEDED(res) && (eBestAnswer == oConfident || eSureAnswer == oConfident)) {
        return NS_OK;
      }
    }
  }
  return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* MIME_EncodeMimePartIIStr ( const char *  header,
PRBool  structured,
const char *  mailCharset,
const PRInt32  fieldNameLen,
const PRInt32  encodedWordSize 
)

Encode an input string into RFC 2047 form.

This is a replacement for INTL_EncodeMimePartIIStr. Unlike INTL_EncodeMimePartIIStr, this does not apply any charset conversion. Use MIME_ConvertCharset in advance if the encoding string needs a conversion.

Parameters:
header[IN] A header to encode (utf-8 Cstring).
structured[IN] A boolean to swtich between structured field body and non-structured field body.
mailCharset[IN] Charset name (in C string) to convert.
fieldNameLen[IN] Header field name length (e.g. "From: " -> 6)
encodedWordSize[IN] Byte length limit of the output, ususally 72 (use kMIME_ENCODED_WORD_SIZE).
Returns:
Encoded buffer (in C string) or NULL in case of error.

Definition at line 762 of file comi18n.cpp.

{
  return apply_rfc2047_encoding(header, structured, mailCharset, fieldNameLen, encodedWordSize);
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult MIME_get_unicode_decoder ( const char *  aInputCharset,
nsIUnicodeDecoder **  aDecoder 
)

Definition at line 803 of file comi18n.cpp.

{
  nsresult res;

  // get charset converters.
  nsCOMPtr<nsICharsetConverterManager> ccm = 
           do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &res); 
  if (NS_SUCCEEDED(res)) {

    // create a decoder (conv to unicode), ok if failed if we do auto detection
    if (!*aInputCharset || !nsCRT::strcasecmp("us-ascii", aInputCharset))
      res = ccm->GetUnicodeDecoderRaw("ISO-8859-1", aDecoder);
    else
      res = ccm->GetUnicodeDecoder(aInputCharset, aDecoder);
  }
   
  return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult MIME_get_unicode_encoder ( const char *  aOutputCharset,
nsIUnicodeEncoder **  aEncoder 
)

Definition at line 824 of file comi18n.cpp.

{
  nsresult res;

  // get charset converters.
  nsCOMPtr<nsICharsetConverterManager> ccm = 
           do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &res); 
  if (NS_SUCCEEDED(res) && *aOutputCharset) {
      // create a encoder (conv from unicode)
      res = ccm->GetUnicodeEncoder(aOutputCharset, aEncoder);
  }
   
  return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* NextChar_UTF8 ( char *  str)

Get a next character position in an UTF-8 string.

Example: s = NextChar_UTF8(s); // get a pointer for the next character

Parameters:
str[IN] An input C string (UTF-8).
Returns:
A pointer to the next character.

Definition at line 769 of file comi18n.cpp.

{
  return (char *) utf8_nextchar((unsigned char *) str);
}

Here is the call graph for this function:

static unsigned char* utf8_nextchar ( unsigned char *  str) [static]

Definition at line 174 of file comi18n.cpp.

{
  if (*str < 0x80)
    return (str + 1);
  if (IS_UTF8_HEADER(str, 0xC0) &&
      IS_UTF8_SUBBYTE(str + 1))
    return (str + 2);
  if (IS_UTF8_HEADER(str, 0xE0) &&
      IS_UTF8_SUBBYTE(str + 1) &&
      IS_UTF8_SUBBYTE(str + 2) )
    return (str + 3);
  if (IS_UTF8_HEADER(str, 0xF0) &&
      IS_UTF8_SUBBYTE(str + 1) &&
      IS_UTF8_SUBBYTE(str + 2) &&
      IS_UTF8_SUBBYTE(str + 3) )
    return (str + 4);
  // error, return + 1 to avoid infinite loop
  return (str + 1); 
}

Here is the caller graph for this function:


Variable Documentation

char basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" [static]

Definition at line 73 of file comi18n.cpp.

const char hexdigits[] = "0123456789ABCDEF" [static]

Definition at line 81 of file comi18n.cpp.