12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- static char sccsid[] = "$TOG: RFCMIME.c /main/11 1999/06/30 12:08:55 mgreess $";
- /*
- * COMPONENT_NAME: desktop
- *
- * FUNCTIONS: CvtStr
- * DtXlateOpToStdLocale
- * DtXlateStdToOpLocale
- * _converter_
- * base64size
- * crlf
- * getCharSet
- * getEncodingType
- * mbisspace
- * md5PlainText
- * rfc1522cpy
- * targetTagName
- * writeBase64
- * writeContentHeaders
- * writeQPrint
- *
- * ORIGINS: 119
- *
- * OBJECT CODE ONLY SOURCE MATERIALS
- */
- #include <stdio.h>
- #include <errno.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
- #include <md5.h>
- #define _ILS_MACROS
- #include <ctype.h>
- #include <assert.h>
- #include <RFCMIME.h>
- #include <iconv.h>
- #include <EUSCompat.h>
- #include <locale.h>
- #include <LocaleXlate.h>
- #ifdef ICONV_INBUF_CONST
- # define ICONV_INBUF_TYPE const char **
- #else
- # define ICONV_INBUF_TYPE char **
- #endif
- #define WORKSIZE 1024*10
- /*
- * The following escape sequence is defined as "To ASCII".
- * But is it correct regardless of ISO-2022-XX ???
- */
- #define ToASCII_NUM 3
- static char ToASCII[ToASCII_NUM] = { 0x1b, 0x28, 0x42 };
- /*
- * _i18nwork1[] is used to convert the passed string with CD iconv.
- * in _converter_().
- *
- */
- static void *_i18nwork1 = NULL;
- static unsigned long _i18nsize1 = 0;
- static int shouldAlloc1 = ~0;
- /*
- * _i18nwork2[] is used to convert the passed string with CD iconv.
- * in CvtStr().
- *
- */
- static void *_i18nwork2 = NULL;
- static unsigned long _i18nsize2 = 0;
- static int shouldAlloc2 = ~0;
- /*
- * Forward declarations
- */
- extern void writeBase64(char * buf, const char * bp, const unsigned long len);
- static const char *DfltStdCharset = "us-ascii";
- static const char *DfltStdLang = "C";
- static void crlf(char *buf)
- {
- strcat(buf,"\n");
- }
- /******************************************************************************
- * Function: int DtXlateOpToStdLocale (char *operation, char *opLocale,
- * char **ret_stdLocale, char **ret_stdLang, char **ret_stdSet)
- *
- * Parameters:
- * operation Operation associated with the locale value
- * opLocale An operation-specific locale string
- * ret_locale Returns the std locale
- * Caller must free this string.
- * ret_stdLang Returns the std language & territory string.
- * Caller must free this string.
- * ret_stdSet Returns the std code set string.
- * Caller must free this string.
- *
- * Return Value:
- *
- * Purpose: Gets the standard locale given an operation and its locale
- *
- *****************************************************************************/
- void
- DtXlateOpToStdLocale (
- char *operation,
- char *opLocale,
- char **ret_stdLocale,
- char **ret_stdLang,
- char **ret_stdSet)
- {
- _DtXlateDb MyDb = NULL;
- char MyPlatform[_DtPLATFORM_MAX_LEN + 1];
- int ExecVer;
- int CompVer;
- if (_DtLcxOpenAllDbs(&MyDb) == 0 &&
- _DtXlateGetXlateEnv(MyDb,MyPlatform,&ExecVer,&CompVer) != 0)
- {
- _DtLcxCloseDb(&MyDb);
- MyDb = NULL;
- }
- if (MyDb != NULL)
- {
- (void) _DtLcxXlateOpToStd(MyDb, MyPlatform, ExecVer,
- operation,opLocale,
- ret_stdLocale, ret_stdLang, ret_stdSet, NULL);
- }
- /* if failed, give default values */
- if (ret_stdLocale != NULL && *ret_stdLocale == NULL)
- {
- *ret_stdLocale = (char *)malloc(strlen(DfltStdLang)+strlen(DfltStdCharset)+3);
- sprintf(*ret_stdLocale,"%s.%s",DfltStdLang,DfltStdCharset);
- }
- if (ret_stdLang != NULL && *ret_stdLang == NULL)
- *ret_stdLang = (char *)strdup(DfltStdLang);
- if (ret_stdSet != NULL && *ret_stdSet == NULL)
- *ret_stdSet = (char *)strdup(DfltStdCharset);
- }
- /******************************************************************************
- * Function: int DtXlateStdToOpLocale ( char *operation, char *stdLocale,
- * char *stdLang, char *stdCodeSet,
- * char *dflt_opLocale, char **ret_opLocale)
- *
- * Parameters:
- * operation operation whose locale value will be retrieved
- * stdLocale standard locale value
- * stdLang standard Lang/Territory Value
- * stdCodeSet standard CodeSet Value
- * dflt_opLocale operation-specific locale-value
- * This is the default value used in error case
- * ret_opLocale operation-specific locale-value placed here
- * Caller must free this string.
- *
- * Return Value:
- *
- * Purpose: Gets an operation-specific locale string given the standard string
- *
- *****************************************************************************/
- void
- DtXlateStdToOpLocale (
- char *operation,
- char *stdLocale,
- char *stdLang,
- char *stdCodeSet,
- char *dflt_opLocale,
- char **ret_opLocale)
- {
- _DtXlateDb MyDb = NULL;
- char MyPlatform[_DtPLATFORM_MAX_LEN + 1];
- int ExecVer;
- int CompVer;
- if (_DtLcxOpenAllDbs(&MyDb) == 0 &&
- _DtXlateGetXlateEnv(MyDb,MyPlatform,&ExecVer,&CompVer) != 0)
- {
- _DtLcxCloseDb(&MyDb);
- MyDb = NULL;
- }
- if (MyDb != NULL)
- {
- (void) _DtLcxXlateStdToOp(MyDb, MyPlatform, ExecVer,
- operation, stdLocale, stdLang, stdCodeSet, NULL,
- ret_opLocale);
- }
- /* if translation fails, use a default value */
- if (ret_opLocale && *ret_opLocale == NULL)
- {
- if (dflt_opLocale) *ret_opLocale = (char *)strdup(dflt_opLocale);
- else if (stdLocale) *ret_opLocale = (char *)strdup(stdLocale);
- }
- }
- char *
- targetTagName(void)
- {
- char *ret_locale = NULL;
- char *ret_lang = NULL;
- char *ret_codeset = NULL;
- char *ret_target = NULL;
- DtXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,
- setlocale(LC_CTYPE, NULL),
- &ret_locale,
- &ret_lang,
- &ret_codeset);
- DtXlateStdToOpLocale(DtLCX_OPER_INTERCHANGE_CODESET,
- NULL,
- NULL,
- ret_codeset,
- NULL,
- &ret_target);
- DtXlateStdToOpLocale(DtLCX_OPER_MIME,
- NULL,
- NULL,
- ret_target,
- NULL,
- &ret_codeset);
- free(ret_locale);
- free(ret_target);
- free(ret_lang);
- return ret_codeset;
- }
- void
- getCharSet(char * charset)
- {
- char *mimeCS = NULL;
- mimeCS = targetTagName();
- if (mimeCS) {
- strcpy(charset, mimeCS);
- free(mimeCS);
- } else {
- strcpy(charset, "us-ascii"); /* default MIME codeset */
- }
- }
- void
- md5PlainText(const char * bp, const unsigned long len, unsigned char * digest)
- {
- /* We need to compute the md5 signature based on a message that has
- // the CRLF line terminator. Most of our buffers don't so we will need
- // to scan the body and do some magic. The approach will be to sum
- // one line at a time. If the buffer doesn't have CRLF we will do that
- // independently.
- */
- MD5_CTX context;
- unsigned char * local_crlf = (unsigned char *)"\r\n";
- const char * last = bp;
- const char * cur;
- MD5Init(&context);
- for (cur = bp; cur < (bp + len); cur++) {
- if (*cur == '\n') {
- if (cur == bp || *(cur - 1) == '\r') {
- MD5Update(&context, (unsigned char *)last,
- cur - last + 1);
- }
- else {
- MD5Update(&context, (unsigned char *)last,
- cur - last);
- MD5Update(&context, local_crlf, 2);
- }
- last = cur + 1;
- }
- }
- if (bp[len - 1] != '\n') {
- /* Need to sum the trailing fraction with a CRLF. */
- MD5Update(&context, (unsigned char *)last,
- cur - last);
- MD5Update(&context, local_crlf, 2);
- }
- MD5Final(digest, &context);
- }
- static void _converter_( iconv_t CD,
- void *from, unsigned long from_len,
- void **to, unsigned long *to_len )
- {
- char *InBuf;
- size_t InBytesLeft;
- char *OutBuf = NULL;
- size_t OutBytesLeft = 0;
- size_t _OutBytesLeft = 0;
- size_t iconv_ret;
- size_t converted_num = 0;
- *to = NULL;
- *to_len = 0;
- if ( shouldAlloc1 ) {
- /* Obtain work area */
- _i18nwork1 = (size_t *)malloc( WORKSIZE );
- if ( !_i18nwork1 ) {
- _i18nwork1 = NULL;
- return;
- }
- _i18nsize1 = WORKSIZE;
- shouldAlloc1 = 0;
- }
- InBuf = (char *)from;
- InBytesLeft = from_len;
- OutBytesLeft = _i18nsize1;
- OutBuf = (char *)_i18nwork1;
- /*
- * Need to place iconv state to the initial one by
- * setting inbuf to NULL of iconv().
- */
- iconv( CD, (ICONV_INBUF_TYPE)NULL, 0, NULL, 0 );
- while( 1 ) {
- /*
- * InBuf
- * v
- * +----------------------------+
- * | | | |
- * +----------------------------+
- * <-------------------------->
- * InBytesLeft
- *
- * |
- * | iconv()
- * V
- * (_i18nwork1)
- * OutBuf
- * v
- * +----------------------------+
- * | | | |
- * +----------------------------+
- * <-------------------------->
- * InBytesLeft
- */
- iconv_ret = iconv( CD, (ICONV_INBUF_TYPE)&InBuf, &InBytesLeft,
- &OutBuf, &OutBytesLeft );
- if ( iconv_ret == 0 ) {
- /* iconv done
- * InBuf
- * v
- * +----------------------------+
- * |XXXXXXXXXXXXXXXXXXXXXXXXXXXX|
- * +----------------------------+
- *
- * InBytesLeft=0
- *
- * (_i18nwork1)
- * | OutBuf
- * V v
- * +----------------------------+
- * |XXXXXXXXXXXXXXXXX| | | |
- * +----------------------------+
- * <---------------> <-------->
- * converted_num OutBytesLeft
- */
- converted_num = (unsigned long)((char *)OutBuf-(char *)_i18nwork1);
- *to = (void *)_i18nwork1;
- *to_len = (unsigned long)converted_num;
- break;
- } else {
- if ( errno == E2BIG ) {
- /* Overflow. still data is left.
- * InBuf
- * v
- * +----------------------------+
- * |XXXXXXXXXXXXXX| | | |
- * +----------------------------+
- * <----------->
- * InBytesLeft
- *
- * (_i18nwork1)
- * | OutBuf
- * V v
- * +----------------------------+
- * |XXXXXXXXXXXXXXXXXXXXXXXXXXX |
- * +----------------------------+
- * <------------------------->
- * converted_num OutBytesLeft=?
- */
- void *_p;
- /* Check how many converted already.
- */
- converted_num =
- (unsigned long)((char *)OutBuf - (char *)_i18nwork1);
- _i18nsize1 += WORKSIZE;
- _p = realloc( _i18nwork1, _i18nsize1 );
- if ( !_p ) {
- *to = NULL;
- *to_len = 0;
- free( _i18nwork1 );
- _i18nwork1 = NULL;
- _i18nsize1 = 0;
- shouldAlloc1 = ~0;
- break;
- } else {
- _i18nwork1 = _p;
- OutBuf = (char *)((char*)_i18nwork1 + converted_num);
- OutBytesLeft += WORKSIZE;
- }
- } else {
- *to = NULL;
- *to_len = 0;
- break;
- }
- }
- }
- }
- int
- CvtStr( char *charSet, void *from, unsigned long from_len,
- void **to, unsigned long *to_len, Direction dir )
- {
- char *ret_locale = NULL;
- char *ret_lang = NULL;
- char *ret_codeset = NULL;
- char *from_codeset = NULL;
- char *to_codeset = NULL;
- char *CuStdCodeSet = NULL;
- char *InterChCodeSet = NULL;
- char *StdCodeSet = NULL;
- iconv_t CD;
- int isASCII=~0;
- int isStopASCII = ~0;
- unsigned long converted_num = 0;
- /* Get CuStdCodeSet */
- DtXlateOpToStdLocale( DtLCX_OPER_SETLOCALE,
- setlocale( LC_CTYPE, NULL ),
- &ret_locale,
- &ret_lang,
- &CuStdCodeSet );
- /*
- * If charSet is NULL, it means the passed string's charset in *from is
- * unknown by dtmail. In this case, this converter assumes that
- * when dir = CURRENT_TO_INTERNET,
- * *from's encoding is the current locale's one.
- * when dir = INTERNET_TO_CURRENT,
- * *from's encoding is the current locale's Internet Message's one.
- *
- * Example.
- * dtmail is running under ja_JP locale.
- * dir : CURRENT_TO_INTERNET
- * *from = IBM-eucJP
- * *to = ISO-2022-JP
- * dir : INTERNET_TO_CURRENT
- * *from = ISO-2022-JP
- * *to = IBM-eucJP
- */
- /*
- * ISO-2022-JP can be converted to either EUC-JP or IBM-932 practically.
- * But the current AIX.lcx says
- * StdCodeSet InterchangeCodeset
- * EUC-JP <--> ISO-2022-JP
- * IBM-932 ---> ISO-2022-JP
- * HP-SJIS ---> ISO-2022-JP
- * HP-KANA8 ---> ISO-2022-JP
- * therefore DtXlateOpToStdLocale() can convert ISO-2022-JP to EUC-JP only.
- * To fix this, we hard-code'ed this situation with the CDE Standard Name
- *
- * ???? Is it correct ???
- */
- if ( dir == INTERNET_TO_CURRENT ) {
- /*
- * As for from_codeset
- */
- if ( ( charSet == NULL ) || ( *charSet == '\0' ) ) {
- /* Convert CuStdCodeSet to StdInterChangeCodeSet */
- DtXlateStdToOpLocale( DtLCX_OPER_INTERCHANGE_CODESET,
- NULL,
- NULL,
- CuStdCodeSet,
- NULL,
- &InterChCodeSet );
- } else {
- /* Convert charSet to StdInterChangeCodeSet */
- free(ret_locale);
- free(ret_lang);
- free(ret_codeset);
- ret_locale = ret_lang = ret_codeset = NULL;
- DtXlateOpToStdLocale( DtLCX_OPER_MIME,
- charSet,
- &ret_locale,
- &ret_lang,
- &InterChCodeSet );
- }
- /* Convert StdInterChangeCodeSet to OpIVONC3 codeset */
- DtXlateStdToOpLocale( DtLCX_OPER_ICONV3,
- NULL,
- NULL,
- InterChCodeSet,
- NULL,
- &from_codeset );
- /*
- * As for to_codeset
- */
- if ( ( charSet == NULL ) || ( *charSet == '\0' ) ) {
- /* Convert CuStdCodeSet to OpIVONC3 codeset */
- DtXlateStdToOpLocale( DtLCX_OPER_ICONV3,
- NULL,
- NULL,
- CuStdCodeSet,
- NULL,
- &to_codeset );
- } else {
- #ifdef _AIX
- if ( (!strncasecmp(InterChCodeSet,"ISO-2022-JP",11) &&
- !strncasecmp(CuStdCodeSet,"IBM-932",7) ) ||
- (!strncasecmp(InterChCodeSet,"ISO-2022-JP",11) &&
- !strncasecmp(CuStdCodeSet,"EUC-JP",6) ) ) {
- ret_codeset = CuStdCodeSet;
- } else
- #endif /* _AIX */
- {
- /* Convert InterChCodeSet to StdCodeSet */
- free(ret_locale);
- free(ret_lang);
- free(ret_codeset);
- ret_locale = ret_lang = ret_codeset = NULL;
- DtXlateOpToStdLocale( DtLCX_OPER_INTERCHANGE_CODESET,
- InterChCodeSet,
- &ret_locale,
- &ret_lang,
- &ret_codeset );
- }
- DtXlateStdToOpLocale( DtLCX_OPER_ICONV3,
- NULL,
- NULL,
- ret_codeset,
- NULL,
- &to_codeset );
- }
- } else { /* dir == CURRENT_TO_INTERNET */
- /*
- * As for from_codeset
- */
- if ( ( charSet == NULL ) || ( *charSet == '\0' ) ) {
- /* Convert CuStdCodeSet to OpICONV3 codeset */
- DtXlateStdToOpLocale( DtLCX_OPER_ICONV3,
- NULL,
- NULL,
- CuStdCodeSet,
- NULL,
- &from_codeset );
- } else {
- /* Convert charSet to StdInterChangeCodeSet */
- free(ret_locale);
- free(ret_lang);
- free(ret_codeset);
- ret_locale = ret_lang = ret_codeset = NULL;
- DtXlateOpToStdLocale( DtLCX_OPER_MIME,
- charSet,
- &ret_locale,
- &ret_lang,
- &ret_codeset );
- /* Convert StdInterChangeCodeSet to OpIVONC3 codeset */
- DtXlateStdToOpLocale( DtLCX_OPER_ICONV3,
- NULL,
- NULL,
- ret_codeset,
- NULL,
- &from_codeset );
- }
- /*
- * As for to_codeset
- */
- if ( ( charSet == NULL ) || ( *charSet == '\0' ) ) {
- /* Convert CuStdCodeSet to StdInterChangeCodeSet */
- DtXlateStdToOpLocale( DtLCX_OPER_INTERCHANGE_CODESET,
- NULL,
- NULL,
- CuStdCodeSet,
- NULL,
- &InterChCodeSet );
- } else {
- /* Convert charSet to StdInterChangeCodeSet */
- free(ret_locale);
- free(ret_lang);
- free(ret_codeset);
- ret_locale = ret_lang = ret_codeset = NULL;
- DtXlateOpToStdLocale( DtLCX_OPER_MIME,
- charSet,
- &ret_locale,
- &ret_lang,
- &InterChCodeSet );
- }
- /* Convert StdInterChangeCodeSet to OpIVONC3 codeset */
- DtXlateStdToOpLocale( DtLCX_OPER_ICONV3,
- NULL,
- NULL,
- InterChCodeSet,
- NULL,
- &to_codeset );
- }
- free(ret_locale);
- free(ret_lang);
- free(ret_codeset);
- *to = NULL;
- *to_len = 0;
- if ( shouldAlloc2 ) {
- /* Obtain work area */
- _i18nwork2 = (size_t *)malloc( WORKSIZE );
- if ( !_i18nwork2 ) {
- _i18nwork2 = NULL;
- return( isASCII );
- }
- _i18nsize2 = WORKSIZE;
- shouldAlloc2 = 0;
- }
- if (NULL == to_codeset || NULL == from_codeset)
- return( isASCII );
- if ( ( CD = iconv_open( to_codeset, from_codeset ) ) != (iconv_t)-1 ) {
- /*
- * According to several RFCs( 822, 1468, 1557, ..... )
- * the escape sequence to switch to ASCII is needed just before
- * '\n'. IBM-eucJP/IBM-932 <--> fold 7 does while the other doesn't.
- * Therefore CvtStr() does take care of this here.
- */
- if ( dir == INTERNET_TO_CURRENT ) {
- _converter_( CD, from, from_len, to, to_len );
- } else {
- void *new_from = from;
- unsigned long new_from_len = from_len;
- unsigned long _passed = 0;
- size_t clen;
- void *_tmp = NULL;
- unsigned long _tmp_len = 0;
- while ( _passed < from_len ) {
- /*
- * Find \n or \0
- */
- for ( ; _passed < from_len; _passed += clen ) {
- clen = mblen(&(((char *)from)[_passed]), MB_CUR_MAX);
- if ( clen < 0 )
- break;
- if ( ( clen > 1 ) || !isascii( ((char*)from)[_passed] ) ){
- /* Here, maybe MB or non-ASCII */
- isASCII = 0;
- isStopASCII = 0;
- } else {
- if ( ( ((char*)from)[_passed] != '\n' ) &&
- ( ((char*)from)[_passed] != '\0' ) ) {
- isStopASCII = ~0;
- }
- }
- if ( ((char*)from)[_passed] == '\n' ||
- ((char*)from)[_passed] == '\0' )
- break;
- }
- new_from_len = &(((char *)from)[_passed])-(char *)new_from;
- if ( ( _passed < from_len ) && ( clen == 1 ) &&
- ( ((char*)from)[_passed] == '\n' ) ) {
- new_from_len++;
- }
- /*
- * new_from from[_passed]
- * V V
- * +------------------------+--+------.................+
- * | | |\n| | |
- * +------------------------+--+------.................+
- * <-------------------------> $
- * new_from_len next new_from
- * <------------------------------------------------->
- * $ from_len
- * from
- */
- /*
- * ********** DO 1 LINE CONVERSION **********
- */
- _tmp = NULL; _tmp_len = 0;
- _converter_( CD, new_from, new_from_len, &_tmp, &_tmp_len );
- if ( ( _tmp == NULL ) && ( _tmp_len == 0 ) ) {
- /* Conversion fail */
- *to = NULL;
- *to_len = 0;
- break;
- }
- /*
- * _i18nwork2 _tmp
- * V V
- * +-----------------------+ +-------------+
- * |XXXXXXXX | + | |
- * +-----------------------+ +-------------+
- * <------>
- * converted_num
- * <---------------------> <----------->
- * _18nsize2 _tmp_len
- */
- /* Append _tmp to target */
- if ( converted_num + _tmp_len > _i18nsize2 ) {
- /* Need much memory..... */
- void *_i18n = NULL;
- _i18nsize2 += WORKSIZE;
- _i18n = realloc( _i18nwork2, _i18nsize2 );
- if ( !_i18n ) {
- *to = NULL;
- *to_len = 0;
- _i18nwork2 = NULL;
- _i18nsize2 = 0;
- shouldAlloc2 = ~0;
- break;
- } else {
- _i18nwork2 = _i18n;
- }
- }
- /*
- * _i18nwork2 _tmp
- * V v
- * +---------------------------+
- * |XXXXXXXXXXX(COPIED)XX |
- * +---------------------------+
- * <---------><-------->
- * (old)conv. _tmp_len
- * <------------------->
- * (new)converted_num
- * <-------------------------->
- * _i18nsize2
- */
- strncpy( (char *)_i18nwork2 + converted_num,
- (char *)_tmp, _tmp_len );
- converted_num += _tmp_len;
- *to = (void *)_i18nwork2;
- *to_len = converted_num;
- new_from = &(((char *)from)[_passed]) + 1;
- _passed++;
- /*
- * According to RFC1468, if the line is ended with non-ASCII
- * char, but not not switch to ASCII before the end of line,
- * we must switch to ASCII just before the end of the line.
- *
- * _i18nwork2 ToASCII
- * V ??? V
- * +---------------------------+ +------+
- * |XXXXXXXXXXXXXXXXXXXXX | + |1b2842|
- * +---------------------------+ +------+
- * <-------------------> <---->
- * converted_num ToASCII_NUM
- * <------------------------->
- * _i18nsize2
- * ========
- * 1b 28 42 ??
- *
- */
- if ( !isStopASCII ) {
- if ( (((char *)_i18nwork2)[converted_num-1] == '\n') ||
- (((char *)_i18nwork2)[converted_num-1] == '\0') ) {
- char _p = ((char *)_i18nwork2)[converted_num-1];
- if (!((converted_num >=3+1 ) &&
- !memcmp((void *)((char *)_i18nwork2+converted_num-3-1),
- ToASCII, ToASCII_NUM )) ){
- /* if not ToASCII there, then */
- /* Append ToASCII */
- if ( converted_num + ToASCII_NUM > _i18nsize2 ) {
- /* Need much memory..... */
- void *_i18n = NULL;
- _i18nsize2 += WORKSIZE;
- _i18n=realloc(_i18nwork2,_i18nsize2);
- if ( !_i18n ) {
- *to = NULL;
- *to_len = 0;
- shouldAlloc2 = ~0;
- break;
- } else {
- _i18nwork2 = _i18n;
- }
- }
- strncpy( (char *)_i18nwork2+converted_num-1,
- ToASCII, ToASCII_NUM );
- converted_num += ToASCII_NUM;
- ((char *)_i18nwork2)[converted_num-1] = _p;
- *to = _i18nwork2;
- *to_len = converted_num;
- isStopASCII = ~0;
- }
- } else {
- if (!((converted_num >=3 ) &&
- !memcmp((void *)((char *)_i18nwork2+converted_num-3),
- ToASCII, ToASCII_NUM )) ){
- /*
- // if not ToASCII there, then
- // Append ToASCII
- */
- if ( converted_num + ToASCII_NUM > _i18nsize2 ) {
- void *_i18n = NULL;
- _i18nsize2 += WORKSIZE;
- _i18n=realloc(_i18nwork2,_i18nsize2);
- if ( !_i18n ) {
- *to = NULL;
- *to_len = 0;
- shouldAlloc2 = ~0;
- break;
- } else {
- _i18nwork2 = _i18n;
- }
- }
- strncpy( (char *)_i18nwork2+converted_num,
- ToASCII, ToASCII_NUM );
- converted_num += ToASCII_NUM;
- *to = _i18nwork2;
- *to_len = converted_num;
- isStopASCII = ~0;
- }
- }
- }
- }
- /*
- * Again........
- */
- if( ( *to != NULL ) && ( *to_len != 0 ) ) {
- if ( !isStopASCII ) {
- if ( (((char *)_i18nwork2)[converted_num-1] == '\n') ||
- (((char *)_i18nwork2)[converted_num-1] == '\0') ) {
- char _p = ((char *)_i18nwork2)[converted_num-1];
- if (!((converted_num >=3+1 ) &&
- !memcmp((void *)((char *)_i18nwork2+converted_num-3-1),
- ToASCII, ToASCII_NUM )) ){
- /* if not ToASCII there, then
- // Append ToASCII
- */
- if ( converted_num + ToASCII_NUM > _i18nsize2 ) {
- void *_i18n = NULL;
- _i18nsize2 += WORKSIZE;
- _i18n=realloc(_i18nwork2,_i18nsize2);
- if ( !_i18n ) {
- *to = NULL;
- *to_len = 0;
- shouldAlloc2 = ~0;
- } else {
- _i18nwork2 = _i18n;
- }
- }
- strncpy( (char *)_i18nwork2+converted_num-1,
- ToASCII, ToASCII_NUM );
- converted_num += ToASCII_NUM;
- ((char *)_i18nwork2)[converted_num-1] = _p;
- *to = _i18nwork2;
- *to_len = converted_num;
- isStopASCII = ~0;
- }
- } else {
- if (!((converted_num >=3 ) &&
- !memcmp((void *)((char *)_i18nwork2+converted_num-3),
- ToASCII, ToASCII_NUM )) ){
- /* if not ToASCII there, then
- // Append ToASCII
- */
- if ( converted_num + ToASCII_NUM > _i18nsize2 ) {
- void *_i18n = NULL;
- _i18nsize2 += WORKSIZE;
- _i18n=realloc(_i18nwork2,_i18nsize2);
- if ( !_i18n ) {
- *to = NULL;
- *to_len = 0;
- shouldAlloc2 = ~0;
- } else {
- _i18nwork2 = _i18n;
- }
- }
- strncpy( (char *)_i18nwork2+converted_num,
- ToASCII, ToASCII_NUM );
- converted_num += ToASCII_NUM;
- *to = _i18nwork2;
- *to_len = converted_num;
- isStopASCII = ~0;
- }
- }
- }
- }
- /*
- * If InterChCodeSet is either ISO-2022-JP/ISO-2022-KR/ISO-2022-TW
- * ISO-2022-CN, strip MSB here since iconv'ed UDC has MSB set to 1
- */
- if ( !strncasecmp( InterChCodeSet, "ISO-2022-JP", 11 ) ||
- !strncasecmp( InterChCodeSet, "ISO-2022-KR", 11 ) ||
- !strncasecmp( InterChCodeSet, "ISO-2022-TW", 11 ) ||
- !strncasecmp( InterChCodeSet, "ISO-2022-CN", 11 ) ) {
- int _i;
- for ( _i = 0; _i < *to_len; _i++ ) {
- ((unsigned char *)(*to))[_i] &= (unsigned char)0x7f;
- }
- }
- }
- iconv_close( CD );
- }
- return( isASCII );
- }
- unsigned int
- base64size(const unsigned long len)
- {
- int b_len = len + (len / 3);
- b_len += (b_len / 72 * 2) + 4;
- return(b_len);
- }
- getEncodingType(const char * body,
- const unsigned int len,
- boolean_t strict_mime)
- {
- /*
- // Our goal here is to produce the most readable, safe encoding.
- // We have a couple of parameters that will guide our
- // choices:
- //
- // 1) RFC822 allows lines to be a minimum of 1000 characters,
- // but MIME encourages mailers to keep lines to <76 characters
- // and use quoted-printable if necessary to achieve this.
- //
- // 2) The base64 encoding will grow the body size by 33%, and
- // also render it unreadable by humans. We don't want to use
- // it unless really necessary.
- //
- // Given the above 2 rules, we want to scan the body part and
- // select an encoding. The 3 choices will be decided by:
- //
- // 1) If the text is 7 bit clean, and all lines are <76 chars,
- // then no encoding will be applied.
- //
- //
- // 2) If the text is not 7 bit clean, or there are lines >76 chars,
- // and the quoted-printable size is less than the base64 size,
- // then quoted-printable will be done.
- //
- // 3) If 1 & 2 are not true, then base64 will be applied.
- //
- // If "strict_mime" is false we will only encode if the message
- // is not 7 bit clean.
- */
- int base64_growth = base64size(len) - len;
- int qprint_growth = 0;
- boolean_t eight_bit = B_FALSE;
- boolean_t base64 = B_FALSE;
- boolean_t encode = B_FALSE;
- Encoding enc;
- const char * last_nl = body;
- const char * cur;
- if (body == NULL || len == 0) {
- return(MIME_7BIT);
- }
- if (strncmp(body, "From ", 5) == 0) {
- qprint_growth += 2;
- }
- for (cur = body; cur < (body + len); cur++) {
- if (*cur != (*cur & 0x7f)) {
- eight_bit = B_TRUE;
- encode = B_TRUE;
- qprint_growth += 2;
- } else if (*cur == '=' || *cur == 0) {
- /*
- // These characters don't force encoding, but will be
- // encoded if we end up encoding.
- qprint_growth += 2;
- */
- }
- if (*cur == '\n') {
- if ((cur - last_nl) > 76) {
- encode = B_TRUE;
- qprint_growth += 2;
- }
- if ((cur != body && (*(cur - 1) == ' ' || *(cur - 1) == '\t'))) {
- encode = B_TRUE;
- qprint_growth += 2;
- }
- if ((cur + 6) < (body + len) &&
- strncmp((cur + 1), "From ", 5) == 0) {
- encode = B_TRUE;
- qprint_growth += 2;
- }
- last_nl = cur + 1;
- }
- if (encode && (qprint_growth > base64_growth)) {
- base64 = B_TRUE;
- break;
- }
- }
- /* Deal with buffers that don't end with a new line. */
- if ((cur - last_nl) > 76) {
- encode = B_TRUE;
- qprint_growth += 2;
- }
- enc = MIME_7BIT;
- if (!strict_mime && !eight_bit) {
- /* If strict_mime is off we only encode if we have 8 bit data */
- enc = MIME_7BIT;
- } else if (encode) {
- /* strict_mime is TRUE and we have reason to encode. */
- if (base64) {
- enc = MIME_BASE64;
- } else {
- enc = MIME_QPRINT;
- }
- }
- return(enc);
- }
- void
- writeContentHeaders(char * hdr_buf,
- const char * type,
- const Encoding enc,
- const char * digest,
- int isAllASCII)
- {
- char default_charset[64];
- strcat(hdr_buf,"Content-Type: ");
- strcat(hdr_buf,type);
- if (isAllASCII)
- strcpy(default_charset,"US-ASCII");
- else
- getCharSet(default_charset);
- strcat(hdr_buf,"; charset=");
- strcat(hdr_buf,default_charset);
- crlf(hdr_buf);
- strcat(hdr_buf,"Content-Transfer-Encoding: ");
- switch (enc) {
- case MIME_7BIT:
- strcat(hdr_buf,"7bit\n");
- break;
- case MIME_8BIT:
- default: /* Assume the worst. */
- strcat(hdr_buf,"8bit\n");
- break;
- case MIME_QPRINT:
- strcat(hdr_buf,"quoted-printable\n");
- break;
- case MIME_BASE64:
- strcat(hdr_buf,"base64\n");
- break;
- }
- strcat(hdr_buf,"Content-MD5: ");
- writeBase64(hdr_buf, digest, 16);
- }
- /*
- //
- // Base64 Alphabet (65-character subset of US-ASCII as per RFC1521)
- //
- */
- static const char base64_chars[] =
- {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
- 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a',
- 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
- 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
- '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
- };
- void
- writeBase64(char * buf, const char * bp, const unsigned long len)
- {
- /* The length has to be a multiple of 3. We will need to pad
- // any extra. Let's just work on the main body and save the
- // fractional stuff for the end.
- */
- unsigned long main_len = len - (len % 3);
- const unsigned char * ubp = (const unsigned char *)bp;
- char line[80];
- unsigned int enc_char;
- int lf = 0;
- int block;
- if (bp == NULL || len == 0) {
- crlf(buf);
- return;
- }
- for (block = 0; block < main_len; block += 3) {
- enc_char = (ubp[block] >> 2) & 0x3f;
- line[lf++] = base64_chars[enc_char];
- enc_char = ((ubp[block] & 0x3) << 4) | ((ubp[block+1] >> 4) & 0xf);
- line[lf++] = base64_chars[enc_char];
- enc_char = ((ubp[block + 1] & 0xf) << 2) | ((ubp[block + 2] >> 6) & 0x3);
- line[lf++] = base64_chars[enc_char];
- enc_char = ubp[block + 2] & 0x3f;
- line[lf++] = base64_chars[enc_char];
- if (lf == 72) {
- strncat(buf,line,lf);
- crlf(buf);
- lf = 0;
- }
- }
- if (lf > 0) {
- strncat(buf, line,lf);
- }
- if (((lf + 4) % 72) == 0) {
- crlf(buf);
- }
- switch(len % 3) {
- case 1:
- enc_char = (ubp[block] >> 2) & 0x3f ;
- strncat(buf, &base64_chars[enc_char], 1);
- enc_char = ((ubp[block] & 0x3) << 4);
- strncat(buf, &base64_chars[enc_char], 1);
- strncat(buf,"==", 2);
- break;
- case 2:
- enc_char = (ubp[block] >> 2) & 0x3f;
- strncat(buf,&base64_chars[enc_char], 1);
- enc_char = ((ubp[block] & 0x3) << 4) | ((ubp[block+1] >> 4) & 0xf);
- strncat(buf,&base64_chars[enc_char], 1);
- enc_char = ((ubp[block + 1] & 0xf) << 2);
- strncat(buf,&base64_chars[enc_char], 1);
- strncat(buf,"=", 1);
- }
- /* crlf(buf); */
- }
- void
- writeQPrint(char *buf, const char * bp, const unsigned long bp_len,
- int is_Special )
- {
- int last_nl = 0;
- int off = 0;
- char line_buf[80];
- const char * start;
- const char * cur;
- const char * white;
- const char * nw;
- int line_len;
- const char *cp_w;
- char prev;
- char tmpbuf[20];
- if (bp == NULL || bp_len == 0) {
- crlf(buf);
- return;
- }
- /*
- // A line buffer for improving formatting performance. Note that
- // QP requires all lines to be < 72 characters plus CRLF. So, a
- // fixed size 80 character buffer is safe.
- */
- /* There are probably more elegant ways to deal with a message that
- // begins with "From ", but we will simply due it this more simplistic
- // way.
- */
- if (strncmp(bp, "From ", 5) == 0) {
- memcpy(&line_buf[off], "=46", 3);
- start = bp + 1;
- off += 3;
- }
- else {
- start = bp;
- }
- /* This loop will apply the encodings, following the rules identified
- // in RFC1521 (though not necessarily in the order presented.
- */
- for (cur = start; cur < (bp + bp_len); cur++) {
- /* Rule #5: Part 1! We will try to break at white space
- // if possible, but it may not be possible. In any case,
- // we want to force the lines to be less than 76 characters.
- */
- if (off > 72) {
- line_buf[off++] = '=';
- strncat(buf,line_buf, off);
- crlf(buf);
- last_nl = 0;
- off = 0;
- }
- /* Rule #1: Any octet, except those indicating a line break
- // according to the newline convention mabe represented by
- // an = followed by a two digit hexadecimal representation
- // of the octet's value. We will represent any non-7bit
- // data this way, but let the rest slide. We do wrap "="
- // just to be safe.
- */
- if (*cur != (*cur & 0x7f) || *cur == '=') {
- char tmp[20];
- sprintf(tmp, "=%02X", (int)(unsigned char)*cur);
- memcpy(&line_buf[off], tmp, 3);
- off += 3;
- continue;
- }
- if ( is_Special ){
- /*
- * Under ISO-2022-XX codeset, several escape sequence may be in
- * From, Subject field. To pass them, writeQPrint() also accept
- * such kind of character.
- */
- if ( *cur == (char)0x1b ) {
- /* Only 0x1b ????? */
- char tmp[3];
- sprintf(tmp, "=%02X", (int)(unsigned char)*cur);
- memcpy(&line_buf[off], tmp, 3);
- off += 3;
- continue;
- }
- }
- /* Rule #2: Octets with decimal values of 33 through 60
- // inclusive and 62 through 126, inclusive, MAY be represented
- // as the ASCII characters which correspond to those octets.
- */
- if ((*cur >= 33 && *cur <= 60) ||
- (*cur >= 62 && *cur <= 126)) {
- line_buf[off++] = *cur;
- continue;
- }
- /* Rule #5: The q-p encoding REQUIRES that encoded lines be
- // no more than 76 characters long. If longer, an equal sign
- // as the last character n the line indicates a soft line break.
- //
- // This is tricky if you want to leave it reasonably readable
- // (why else do this?). We only want to break on white space.
- // At each white gap, we need to count forward to the next
- // white gap and see if we exceed the 76 character limit.
- // We will cheat a few characters to allow us some room
- // for arithmetic.
- */
- if (*cur == ' ' || *cur == '\t') {
- /* Find the end of this clump of white space.
- */
- for (nw = cur;
- nw < (bp + bp_len) && *nw && *nw != '\n'; nw++) {
- if (!isspace(*nw)) {
- break;
- }
- }
- /* Find the end of the next non-white region.
- */
- for (white = nw;
- white < (bp + bp_len) && *white && !isspace(*white);
- white++) {
- continue;
- }
- line_len = (off - last_nl) + (white - cur);
- if (line_len > 72) {
- /* Need a soft line break. Lets put it after the
- // current clump of white space. We will break
- // at 72 characters, even if we arent at the end
- // of the white space. This prevents buffer overruns.
- */
- for (cp_w = cur; cp_w < nw; cp_w++) {
- line_buf[off++] = *cp_w;
- if (off > 72) {
- line_buf[off++] = '=';
- strncat(buf,line_buf, off);
- crlf(buf);
- off = 0;
- last_nl = 0;
- }
- }
- /* There is an edge case that we may have written the last
- // white space character in the for loop above. This will
- // prevent us from spitting an extra continuation line.
- */
- if (off) {
- line_buf[off++] = '=';
- strncat(buf,line_buf, off);
- crlf(buf);
- last_nl = 0;
- off = 0;
- }
- /* If we created a "From " at the front we need to wrap
- // it to protect from parsers.
- */
- if ((nw + 5) < (bp + bp_len) && strncmp(nw, "From ", 5) == 0) {
- memcpy(&line_buf[off], "=46", 3);
- off += 3;
- cur = nw + 1;
- }
- else {
- cur = nw - 1;
- }
- }
- else {
- line_buf[off++] = *cur;
- }
- continue;
- }
- /* Rule 3: Octets with values of 9 and 32 MAY be represented
- // as ASCII TAB and SPACE but MUST NOT be represented at the
- // end of an encoded line. We solve this be encoding the last
- // white space before a new line (except a new line) using
- // Rule #1.
- */
- if (*cur == '\n') {
- if (cur == start) {
- crlf(buf);
- }
- else {
- last_nl = off + 1;
-
- prev = *(cur - 1);
- if ((prev == ' ' || prev == '\t') && prev != '\n') {
- off = off ? off - 1 : off;
-
- sprintf(tmpbuf, "=%02X", *(cur - 1));
- memcpy(&line_buf[off], tmpbuf, 3);
- off += 3;
- }
- strncat(buf,line_buf, off);
- last_nl = 0;
- off = 0;
- if (*(cur - 1) == '\r') {
- strncat(buf,cur, 1);
- }
- /*
- else {
- crlf(buf);
- }
- */
- }
- /* We need to munge a line that starts with "From " to it
- // protect from parsers. The simplest way is to encode the
- // "F" using rule #1.
- */
- if ((cur + 5) < (bp + bp_len) && strncmp((cur + 1), "From ", 5) == 0) {
- memcpy(&line_buf[off], "=46", 3);
- off += 3;
- cur += 1;
- }
- continue;
- }
- }
- if (off > 0) {
- strncat(buf,line_buf, off);
- }
- /*
- if (*(cur - 1) != '\n') {
- crlf(buf);
- }
- */
- }
- static int
- mbisspace(int c)
- {
- return((c & 0x7f) == c && isspace(c));
- }
- void
- rfc1522cpy(char * buf, const char * value)
- {
- const char * cur;
- const char * scan_c;
- boolean_t eight_bit = B_FALSE;
- char charset[64];
- char *ret_locale = NULL;
- char *ret_lang = NULL;
- char *ret_codeset = NULL;
- char tmp[1024];
- char *NewBuf = NULL;
- unsigned long _len = 0;
- /*
- // We are going to encode 8 bit data, one word at a time. This may
- // not be the best possible algorithm, but it will get the correct
- // information in the header.
- */
- for (cur = value; *cur; cur++) {
- if (mbisspace(*cur)) {
- strncat(buf,cur, 1);
- continue;
- }
- for (scan_c = cur; *scan_c && !mbisspace(*scan_c); scan_c++) {
- if (*scan_c != (*scan_c & 0x7f)) {
- eight_bit = B_TRUE;
- }
- }
- if (eight_bit == B_FALSE) {
- /* Simple! Copy the chars to the output. */
- strncat(buf,cur,scan_c - cur);
- cur = scan_c - 1;
- }
- else {
- getCharSet( charset );
- /* Convert default_charset to InterchangeCodeset name. */
- DtXlateOpToStdLocale( DtLCX_OPER_MIME,
- charset,
- &ret_locale,
- &ret_lang,
- &ret_codeset );
- /* We have a word here. It has 8 bit data, so we will put
- // it out as RFC1522 chunk.
- */
- if ( !strncasecmp( ret_codeset, "ISO-2022-KR", 11 ) ) {
- /*
- * According to RFC1557, in the Header Field, we don't use
- * ISO-2022-KR encoding char.
- */
- char *_tmp1_;
- char *_tmp2_;
- free(ret_locale);
- free(ret_lang);
- ret_locale = ret_lang = _tmp1_ = NULL;
- DtXlateOpToStdLocale( DtLCX_OPER_INTERCHANGE_CODESET,
- ret_codeset,
- &ret_locale,
- &ret_lang,
- &_tmp1_ );
- _tmp2_ = NULL;
- DtXlateStdToOpLocale( DtLCX_OPER_MIME,
- NULL,
- NULL,
- _tmp1_,
- NULL,
- &_tmp2_ );
- strncat(buf,"=?", 2);
- strncat(buf,_tmp2_, strlen(_tmp2_));
- strncat(buf,"?q?", 3);
- free(_tmp1_);
- free(_tmp2_);
- } else if ( !strncasecmp( ret_codeset, "ISO-2022-JP", 11 ) ) {
- /*
- * According to RFC1468, in the Header Field, we should use
- * B-encoding
- */
- strncat(buf,"=?", 2);
- strncat(buf,charset, strlen(charset));
- strncat(buf,"?b?", 3);
- } else {
- strncat(buf,"=?", 2);
- strncat(buf,charset, strlen(charset));
- strncat(buf,"?q?", 3);
- }
- /*
- * According to RFC1557, in the Header Field, we don't use
- * ISO-2022-KR encoding char. Also in us-ascci, we don't have to
- * call converter.
- */
- memset(tmp, '\0', 1024);
- if (!( !strncasecmp( ret_codeset, "ISO-2022-KR", 11 ) ||
- !strncasecmp( charset, "us-ascii", 8 ) ) )
- (void)CvtStr( (char *)NULL, (void *)cur, scan_c - cur,
- (void **)&NewBuf, &_len, CURRENT_TO_INTERNET );
- if ( ( NewBuf != NULL ) && ( _len != 0 ) ) {
- /*
- * if ret_codeset == ISO-2022-KR, we don't come here.
- */
- /*
- * According to RFC1468, we should use B-encoding.
- */
- if ( !strncasecmp( ret_codeset, "ISO-2022-JP", 11 ) ) {
- writeBase64( tmp, NewBuf, _len );
- } else {
- writeQPrint( tmp, NewBuf, _len,
- (!strncasecmp( ret_codeset, "ISO-2022-TW", 11 ) ||
- !strncasecmp( ret_codeset, "ISO-2022-CN", 11 ) ));
- }
- } else
- writeQPrint( tmp, cur, scan_c - cur, 0 );
- strncat(buf,tmp,strlen(tmp));
- strcat(buf,"?=");
- cur = scan_c - 1;
- }
- }
- free(ret_codeset);
- free(ret_locale);
- free(ret_lang);
- crlf(buf);
- }
|