len = PL_strlen(begin);
len = nsCRT::strlen(begin);
char * utf8_mime_encode_mail_address(char *charset, const char *src, int maxLineLen){  char *begin, *end;  char *retbuf = NULL, *srcbuf = NULL;  char sep = '\0';  char *sep_p = NULL;  int  retbufsize;  int line_len = 0;  int srclen;  int default_iThreshold;  int iThreshold;         /* how many bytes we can convert from the src */  int iEffectLen;         /* the maximum length we can convert from the src */  PRBool bChop = PR_FALSE;  if (src == NULL)    return NULL;  /* make a copy, so don't need touch original buffer */  srcbuf = PL_strdup(src);  if (srcbuf == NULL)    return NULL;  begin = srcbuf;  default_iThreshold = iEffectLen = ( maxLineLen - PL_strlen(charset) - 7 ) * 3 / 4;  iThreshold = default_iThreshold;  /* allocate enough buffer for conversion, this way it can avoid     do another memory allocation which is expensive   */  retbufsize = PL_strlen(srcbuf) * 3 + kMAX_CSNAME + 8;  retbuf =  (char *) PR_Malloc(retbufsize);  if (retbuf == NULL) {  /* Give up if not enough memory */    PR_Free(srcbuf);    return NULL;  }  *retbuf = '\0';  // loop for separating encoded words by the separators  // the input string is utf-8 at this point  srclen = PL_strlen(srcbuf);convert_and_encode:  while (begin < (srcbuf + srclen))  { /* get block of data between commas (and other separators) */    char *p, *q;    char *buf1, *buf2;    int len, newsize, convlen, retbuflen;    PRBool non_ascii;    retbuflen = PL_strlen(retbuf);    end = NULL;    /* scan for separator, conversion (and encode) happens on 8bit word between separators       we need to exclude RFC822 special characters from encoded word        regardless of the encoding method ('B' or 'Q').     */    if (IS_MAIL_SEPARATOR(begin))    {   /*  skip white spaces and separator */        q = begin;        while ( IS_MAIL_SEPARATOR(q) )          q ++ ;        sep = *(q - 1);        sep_p = (q - 1);        *(q - 1) = '\0';        end = q - 1;    }    else    {      sep = '\0';      /* scan for next separator */      non_ascii = PR_FALSE;      for (q = begin; *q;)      {        if ((unsigned char) *q > 0x7F)          non_ascii = PR_TRUE;        if ( IS_MAIL_SEPARATOR(q) )        {          if ((*q == ' ') && (non_ascii == PR_TRUE))          {            while ((p = intlmime_encode_next8bitword(q)) != NULL)            {              if (p == NULL)                break;              q = p;              if (*p != ' ')                 break;            }          }          sep = *q;          sep_p = q;          *q = '\0';          end = q;          break;        }        q++;  // the string is utf-8 thus no conflict with scanning chars (which is all us-ascii).      }    }    // convert utf-8 to mail charset    /* get the to_be_converted_buffer's len */    len = PL_strlen(begin);    if ( !intlmime_only_ascii_str(begin) )    {      // now the input is utf-8, a character may be more than 2 bytes len      // so we may over estimate (i.e. threshold may be smaller) but wrapping early is no problem, I think.      /*        the 30 lenght is calculated as follows (I think)        total:             30 = 7 + 11 + 8 + 4        --------------------------------------        Mime Part II tags: 7  = "=?...?B?...?="        Charset name:      11 = "iso-2022-jp"        JIS excape seq.    8  = "<ESC>$B" + "<ESC>(B" * 4/3        space for one char 4  = 2 * 4/3 rounded up to nearest 4        Brian Stell 10/97       */      if ( ( maxLineLen - line_len < 30 ) || bChop ) {        /* chop first, then continue */        buf1 = retbuf + retbuflen;        *buf1++ = CR;   *buf1++ = LF; *buf1++ = '\t';        line_len = 0;        retbuflen += 3;        *buf1 = '\0';        bChop = PR_FALSE;        iThreshold = default_iThreshold;      }      // loop for line wrapping: estimate converted/encoded length       // and apply conversion (utf-8 to mail charset)      /* iEffectLen - the max byte-string length of JIS ( converted form S-JIS )         name - such as "iso-2022-jp", the encoding name, MUST be shorter than 23 bytes         7    - is the "=?:?:?="        */      iEffectLen = ( maxLineLen - line_len - PL_strlen(charset) - 7 ) * 3 / 4;      while ( PR_TRUE ) {        int iBufLen;    /* converted buffer's length, not BASE64 */        if ( len > iThreshold )          len = ResetLen(iThreshold, begin);        if ( iThreshold <= 1 )        {          /* Certain trashed mailboxes were causing an          ** infinite loop at this point, so we need a way of          ** getting out of trouble.          **          ** BEFORE:    iThreshold was becoming 1, then 0, and          **            we were looping indefinitely.          ** AFTER:     Now, first there will be          **            an assert in the previous call to ResetLen,          **            then we'll do that again on the repeat pass,          **            then we'll exit more or less gracefully.          **    - bug #83204, an oldie but goodie.          **    - jrm 98/03/25          */          return NULL;        }        // utf-8 to mail charset conversion (or iso-8859-1 in case of us-ascii).        if (MIME_ConvertCharset(PR_FALSE, "utf-8", !PL_strcasecmp(charset, "us-ascii") ? "iso-8859-1" : charset,                                 (const char*) begin, (const PRInt32) len, &buf1, (PRInt32 *) &iBufLen, NULL)) {          PR_FREEIF(srcbuf);          PR_FREEIF(retbuf);          return NULL; //error        }//        buf1 = (char *) cvtfunc(obj, (unsigned char *)begin, len);//        iBufLen = PL_strlen( buf1 );        if (iBufLen <= 0) {          if (NULL == end) {            PR_FREEIF(srcbuf);            PR_FREEIF(retbuf);            return NULL; //error          }          begin = end + 1;          goto convert_and_encode;  // nothing was converted, skip this part        }        /* recal iThreshold each time based on last experience */        iThreshold = len * iEffectLen / iBufLen;        if ( iBufLen > iEffectLen ){          /* the converted buffer is too large, we have to                  1. free the buffer;                  2. redo again based on the new iThreshold          */          bChop = PR_TRUE;           /* append CRLFTAB */          if (buf1 && (buf1 != begin)){            PR_Free(buf1);            buf1 = NULL;          }        } else {          end = begin + len - 1;          break;        }      }      if (bChop && (NULL!=sep_p)) {        *sep_p = sep;   /* we are length limited so we do not need this */        sep = '\0';     /* artifical terminator. So, restore the original character */        sep_p = NULL;      }      if (!buf1)      {        PR_Free(srcbuf);        PR_Free(retbuf);        return NULL;      }      // converted to mail charset, now apply MIME encode      const char *msgHeaderEncoding = intl_message_header_encoding((const char *) charset);      if (!PL_strcasecmp(msgHeaderEncoding, kMsgHeaderBEncoding))      {        /* converts to Base64 Encoding */        buf2 = (char *)intlmime_encode_base64_buf(buf1, PL_strlen(buf1));      }      else      {        /* Converts to Quote Printable Encoding */        buf2 = (char *)intlmime_encode_qp_buf(buf1);      }      if (buf1 && (buf1 != begin))        PR_Free(buf1);      if (buf2 == NULL) /* QUIT if memory allocation failed */      {        PR_Free(srcbuf);        PR_Free(retbuf);        return NULL;      }      /* realloc memory for retbuff if necessary,         7: =?...?B?..?=, 3: CR LF TAB */      convlen = PL_strlen(buf2) + PL_strlen(charset) + 7;      newsize = convlen + retbuflen + 3 + 2;  /* 2:SEP '\0', 3:CRLFTAB */      if (newsize > retbufsize)      {        char *tempbuf;        tempbuf = (char *) PR_Realloc(retbuf, newsize);        if (tempbuf == NULL)  /* QUIT, if not enough memory left */        {          PR_Free(buf2);          PR_Free(srcbuf);          PR_Free(retbuf);          return NULL;        }        retbuf = tempbuf;        retbufsize = newsize;      }      /* buf1 points to end of current retbuf */      buf1 = retbuf + retbuflen;      if ((line_len > 10) &&          ((line_len + convlen) > maxLineLen))      {        *buf1++ = CR;        *buf1++ = LF;        *buf1++ = '\t';        line_len = 0;        iThreshold = default_iThreshold;      }      *buf1 = '\0';      /* Add encoding tag for base64 and QP */      PL_strcat(buf1, "=?");      PL_strcat(buf1, charset );      if (!PL_strcasecmp(msgHeaderEncoding, kMsgHeaderBEncoding))        PL_strcat(buf1, "?B?");      else        PL_strcat(buf1, "?Q?");      PL_strcat(buf1, buf2);      PL_strcat(buf1, "?=");      line_len += convlen + 1;  /* 1: SEP */      PR_Free(buf2);  /* free base64 buffer */    }    else  /* if no 8bit data in the block */  // so no conversion/encode needed    {      newsize = retbuflen + len + 2 + 3; /* 2: ',''\0', 3: CRLFTAB */      if (newsize > retbufsize)      {        char *tempbuf;        tempbuf = (char *) PR_Realloc(retbuf, newsize);        if (tempbuf == NULL)        {          PR_Free(srcbuf);          PR_Free(retbuf);          return NULL;        }        retbuf = tempbuf;        retbufsize = newsize;      }      buf1 = retbuf + retbuflen;      if ((line_len > 10) &&          ((line_len + len) > maxLineLen))      {        *buf1++ = CR;        *buf1++ = LF;        *buf1++ = '\t';        line_len = 0;        iThreshold = default_iThreshold;      }      /* copy buffer from begin to buf1 stripping CRLFTAB */      for (p = begin; *p; p++)      {        if (*p == CR || *p == LF || *p == TAB)          len --;        else          *buf1++ = *p;      }      *buf1 = '\0';      line_len += len + 1;  /* 1: SEP */    }    buf1 = buf1 + PL_strlen(buf1);    if (sep == CR || sep == LF || sep == TAB) /* strip CR,LF,TAB */      *buf1 = '\0';    else    {      *buf1 = sep;      *(buf1+1) = '\0';    }    if (end == NULL)      break;    begin = end + 1;  }  if (srcbuf)    PR_Free(srcbuf);  return retbuf;}