update tizen source
[framework/messaging/msg-service.git] / plugin / mms_plugin / MmsPluginContentCodec.cpp
1 /*
2 *
3 * Copyright (c) 2000-2012 Samsung Electronics Co., Ltd. All Rights Reserved.
4 *
5 * This file is part of msg-service.
6 *
7 * Contact: Jaeyun Jeong <jyjeong@samsung.com>
8 *          Sangkoo Kim <sangkoo.kim@samsung.com>
9 *          Seunghwan Lee <sh.cat.lee@samsung.com>
10 *          SoonMin Jung <sm0415.jung@samsung.com>
11 *          Jae-Young Lee <jy4710.lee@samsung.com>
12 *          KeeBum Kim <keebum.kim@samsung.com>
13 *
14 * PROPRIETARY/CONFIDENTIAL
15 *
16 * This software is the confidential and proprietary information of
17 * SAMSUNG ELECTRONICS ("Confidential Information"). You shall not
18 * disclose such Confidential Information and shall use it only in
19 * accordance with the terms of the license agreement you entered
20 * into with SAMSUNG ELECTRONICS.
21 *
22 * SAMSUNG make no representations or warranties about the suitability
23 * of the software, either express or implied, including but not limited
24 * to the implied warranties of merchantability, fitness for a particular
25 * purpose, or non-infringement. SAMSUNG shall not be liable for any
26 * damages suffered by licensee as a result of using, modifying or
27 * distributing this software or its derivatives.
28 *
29 */
30
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include "MsgDebug.h"
34 #include "MmsPluginCodec.h"
35 #include "MmsPluginCodec.h"
36 #include "MmsPluginMIME.h"
37 #include "MmsPluginMessage.h"
38 #include "MmsPluginWmLngPack.h"
39
40 const int MSG_MAX_CH_PER_LINE = 75;
41
42 /* ==================================================================
43  *      Decode/Encode inline base64 string
44  *
45  * base64 : 3*8bit -> 4*6bit & convert the value into A~Z, a~z, 0~9, +, or /
46  * pad(=) is needed when the end of the string is < 24bit.
47  *
48  *     Value Encoding  Value Encoding  Value Encoding  Value Encoding
49  *         0 A            17 R            34 i            51 z
50  *         1 B            18 S            35 j            52 '0'
51  *         2 C            19 T            36 k            53 1
52  *         3 D            20 U            37 l            54 2
53  *         4 E            21 V            38 m            55 3
54  *         5 F            22 W            39 n            56 4
55  *         6 G            23 X            40 o            57 5
56  *         7 H            24 Y            41 p            58 6
57  *         8 I            25 Z            42 q            59 7
58  *         9 J            26 a            43 r            60 8
59  *        10 K            27 b            44 s            61 9
60  *        11 L            28 c            45 t            62 +
61  *        12 M            29 d            46 u            63 /
62  *        13 N            30 e            47 v
63  *        14 O            31 f            48 w         (pad) =
64  *        15 P            32 g            49 x
65  *        16 Q            33 h            50 y
66  *
67  * (1) the final quantum = 24 bits : no "=" padding,
68  * (2) the final quantum = 8 bits : two "=" + two characters
69  * (3) the final quantum = 16 bits : one "=" + three characters
70  * ================================================================== */
71
72 bool _MsgEncodeBase64(void *pSrc, unsigned long srcLen, unsigned long *len, unsigned char *ret)
73 {
74         unsigned char *d = NULL;
75         unsigned char *s = (unsigned char *)pSrc;
76
77         char *v = (char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
78         unsigned long i = ((srcLen + 2) / 3) * 4;
79
80         i += 2 * ((i / 60) + 1);
81         *len = i;
82
83         if (ret == NULL) {
84                 MSG_DEBUG("_MsgEncodeBase64: ret Memory Alloc Fail \n");
85                 return false;
86         }
87         memset(ret, 0, i);
88
89         d = ret;
90
91         /* Convert 3*8bit into 4*6bit */
92         for (i = 0; srcLen > 0; s += 3) {
93                 *d++ = v[s[0] >> 2];                                                                                                                    // byte 1: high 6 bits of character-1
94                 *d++ = v[((s[0] << 4) + (--srcLen ? (s[1] >> 4) : 0)) & 0x3f];                                  // byte 2: low 2 bits of character-1 and high 4 bits of character-2
95                 *d++ = srcLen ? v[((s[1] << 2) + (--srcLen ? (s[2] >> 6) : 0)) & 0x3f] : '=';   // byte 3: low 4 bits of charcter-2 and high 2 bits of character-3
96                 *d++ = srcLen ? v[s[2] & 0x3f] : '=';                                                                                   // byte 4: low 6 bits of character-3
97
98                 if (srcLen)
99                         srcLen--;
100
101                 /* Insert CRLF at every 60 characters */
102                 if ((++i) == 15) {
103                         i = 0;
104                         *d++ = '\015';
105                         *d++ = '\012';
106                 }
107         }
108
109         if (i == 15) {
110                 *d++ = '\015';
111                 *d++ = '\012';
112         }
113         *d = '\0';
114
115         if (((unsigned long)(d - ret)) != *len) {
116                 *len = d - ret;
117                 MSG_DEBUG("base64 encoding length = %d \n", *len);
118         }
119
120         return true;
121 }
122
123
124 void *_MsgDecodeBase64(unsigned char *pSrc, unsigned long srcLen, unsigned long *len)
125 {
126         char c;
127         void *ret = NULL;
128         char *d = NULL;
129         short e = 0;
130
131         ret = malloc((size_t)(*len = 4 + ((srcLen * 3) / 4)));
132         d = (char *)ret;
133
134         if (ret == NULL) {
135                 MSG_DEBUG("_MsgDecodeBase64: ret malloc Fail \n");
136                 return NULL;
137         }
138
139         memset(ret, 0, (size_t)*len);
140         *len = 0;
141
142         while (srcLen-- > 0) {
143                 c = *pSrc++;
144
145                 /* Convert base64 character into original value */
146
147                 if (isupper(c))
148                         c -= 'A';
149                 else if (islower(c))
150                         c -= 'a' - 26;
151                 else if (isdigit(c))
152                         c -= '0' - 52;
153                 else if (c == '+')
154                         c = 62;
155                 else if (c == '/')
156                         c = 63;
157                 else if (c == '=') {
158                         switch (e++) {
159                         case 2:
160                                 if (*pSrc != '=') {
161                                         *len = d - (char *)ret;
162                                         return ret;
163                                 }
164                                 break;
165                         case 3:
166                                 e = 0;
167                                 break;
168                         default:
169                                 *len = d - (char *)ret;
170                                 return ret;
171                         }
172                         continue;
173                 } else
174                         continue;                                       // Actually, never get here
175
176                 /* Pad 4*6bit character into 3*8bit character */
177
178                 switch (e++) {
179                 case 0:
180                         *d = c << 2;                    // byte 1: high 6 bits
181                         break;
182
183                 case 1:
184                         *d++ |= c >> 4;                 // byte 1: low 2 bits
185                         *d = c << 4;                    // byte 2: high 4 bits
186                         break;
187
188                 case 2:
189                         *d++ |= c >> 2;                 // byte 2: low 4 bits
190                         *d = c << 6;                    // byte 3: high 2 bits
191                         break;
192
193                 case 3:
194                         *d++ |= c;                              // byte 3: low 6 bits
195                         e = 0;                                  // Calculate next unit.
196                         break;
197
198                 default:
199                         MSG_DEBUG("_MsgDecodeBase64: Unknown paremeter\n");
200                         break;
201                 }
202         }
203
204         *len = d - (char *)ret;                 // Calculate the size of decoded string.
205
206         return ret;
207 }
208
209
210
211 /* ==========================================
212  *      Decode/Encode inline base64 string
213  *
214  * quoted-printable := ([*(ptext / SPACE / TAB) ptext] ["="] CRLF)
215  *       ; Maximum line length of 76 characters excluding CRLF
216  *
217  * ptext := octet /<any ASCII character except "=", SPACE, or TAB>
218  *       ; characters not listed as "mail-safe" in Appendix B
219  *       ; are also not recommended.
220  *
221  * octet := "=" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F")
222  *       ; octet must be used for characters > 127, =, SPACE, or TAB.
223  *
224  * ==========================================*/
225
226 bool _MsgEncodeQuotePrintable(unsigned char *pSrc, unsigned long srcLen, unsigned long *len, unsigned char *ret)
227 {
228         unsigned long lp = 0;
229         unsigned char *d = ret;
230         char *hex = (char *)"0123456789ABCDEF";
231         unsigned char c;
232
233         if (ret == NULL) {
234                 MSG_DEBUG("_MsgEncodeQuotePrintable: ret malloc Fail \n");
235                 return false;
236         }
237
238         d = ret;
239
240         /*
241          * The type of srcLen is unsigned long
242          * The value of srcLen is decreased by 1 -> We can't check by "srcLen > 0".
243          */
244         while (srcLen-- > 0) {
245                 /* Just copy CRLF */
246                 if (((c = *pSrc++) == '\015') && (*pSrc == '\012') && srcLen) {
247                         *d++ = '\015';
248                         *d++ = *pSrc++;
249                         srcLen--;
250                         lp = 0;
251                 } else {
252                         if (iscntrl(c) || (c == 0x7f) || (c & 0x80) || (c == '=') || ((c == ' ') && (*pSrc == '\015'))) {
253                                 if ((lp += 3) > (unsigned long)MSG_MAX_CH_PER_LINE) {
254                                         *d++ = '=';
255                                         *d++ = '\015';
256                                         *d++ = '\012';
257                                         lp = 3;
258                                 }
259
260                                 *d++ = '=';                             /* quote character */
261                                 *d++ = hex[c >> 4];             /* high order 4 bits */
262                                 *d++ = hex[c & 0xf];    /* low order 4 bits */
263                         } else {
264                                 /* Just copy ASCII character */
265                                 if ((++lp) > (unsigned long)MSG_MAX_CH_PER_LINE) {
266                                         *d++ = '=';
267                                         *d++ = '\015';
268                                         *d++ = '\012';
269                                         lp = 1;
270                                 }
271                                 *d++ = c;
272                         }
273                 }
274         }
275
276         *d = '\0';
277         *len = d - ret;
278
279         return true;
280 }
281
282
283 unsigned char *_MsgDecodeQuotePrintable(unsigned char *pSrc, unsigned long srcLen, unsigned long *len)
284 {
285         unsigned char *ret = NULL;
286         unsigned char *d = NULL;
287         unsigned char *s = NULL;                                        /* last non-blank */
288         unsigned char c;
289         unsigned char e;
290
291         d = s = ret = (unsigned char *)malloc((size_t)srcLen + 1);
292         if (ret == NULL) {
293                 MSG_DEBUG("_MsgDecodeQuotePrintable: ret malloc Fail \n");
294                 return NULL;
295         }
296
297         *len = 0;
298         pSrc[srcLen] = '\0';
299
300         while ((c = *pSrc++)!= '\0') {
301                 switch (c) {
302                 case '=':                                                       /* octet characters (> 127, =, SPACE, or TAB) */
303                         switch (c = *pSrc++) {
304                         case '\0':                                      /* end of string -> postpone to while */
305                                 break;
306
307                         case '\015':                            /* CRLF */
308                                 if (*pSrc == '\012')
309                                         pSrc++;
310                                 break;
311
312                         default:                                        /* two hexes */
313                                 if (!isxdigit(c)) {
314                                         *d = '\0';
315                                         *len = d - ret;
316                                         return ret;
317                                 }
318
319                                 if (isdigit(c))
320                                         e = c - '0';
321                                 else
322                                         e = c - (isupper(c) ? 'A' - 10 : 'a' - 10);
323
324                                 c = *pSrc++;
325                                 if (!isxdigit(c)) {
326                                         *d = '\0';
327                                         *len = d - ret;
328                                         return ret;
329                                 }
330
331                                 if (isdigit(c))
332                                         c -= '0';
333                                 else
334                                         c -= (isupper(c) ? 'A' - 10 : 'a' - 10);
335
336                                 *d++ = c + (e << 4);
337                                 s = d;
338                                 break;
339                         }
340                         break;
341
342                 case ' ':                                                       /* skip the blank */
343                         *d++ = c;
344                         break;
345
346                 case '\015':                                            /* Line Feedback : to last non-blank character */
347                         d = s;
348                         break;
349
350                 default:
351                         *d++ = c;                                               /* ASCII character */
352                         s = d;
353                         break;
354                 }
355         }
356
357         *d = '\0';
358         *len = d - ret;
359
360         return ret;
361 }
362
363
364 /* ========================================
365  * Decode/Encode inline base64 string
366  * Inline base64 has no "\r\n" in it,
367  * and has charset and encoding sign in it
368  * ======================================== */
369 bool _MsgEncode2Base64(void *pSrc, unsigned long srcLen, unsigned long *len, unsigned char *ret)
370 {
371         unsigned char *d = NULL;
372         unsigned char *s = (unsigned char *)pSrc;
373         char *v = (char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
374         unsigned long i = ((srcLen + 2) / 3) * 4;
375
376         i += 2 * ((i / 60) + 1);
377         *len = i;
378
379         if (ret == NULL) {
380                 MSG_DEBUG("_MsgEncode2Base64: ret Memory Alloc Fail \n");
381                 return false;
382         }
383         memset(ret, 0, i);
384
385         d = ret;
386
387         /* Convert 3*8bit into 4*6bit */
388         for (i = 0; srcLen > 0; s += 3) {
389                 *d++ = v[s[0] >> 2];                                                                                                                    // byte 1: high 6 bits of character-1
390                 *d++ = v[((s[0] << 4) + (--srcLen ? (s[1] >> 4) : 0)) & 0x3f];                                  // byte 2: low 2 bits of character-1 and high 4 bits of character-2
391                 *d++ = srcLen ? v[((s[1] << 2) + (--srcLen ? (s[2] >> 6) : 0)) & 0x3f] : '=';   // byte 3: low 4 bits of charcter-2 and high 2 bits of character-3
392                 *d++ = srcLen ? v[s[2] & 0x3f] : '=';                                                                                   // byte 4: low 6 bits of character-3
393
394                 if (srcLen)
395                         srcLen--;
396         }
397
398         *d = '\0';
399
400         if (((unsigned long)(d - ret)) != *len) {
401                 *len = d - ret;
402                 MSG_DEBUG("base64 encoding length = %d \n", *len);
403         }
404
405         return true;
406 }
407
408
409 char *_MsgDecodeText(char *pOri)
410 {
411         MSG_BEGIN();
412
413         int size = 0;
414         int cnt = 0;
415         char *pSrc = NULL;
416         char *pTemp = NULL;
417         char *pRe = NULL;
418         char *pStrEnd = NULL;
419         char *pDecStart = NULL;
420         char *pDecEnd = NULL;
421         char *pDecQ = NULL;
422         char *pDecQ2 = NULL;
423         bool bEncoding = false;
424         int     nCharset = MSG_CHARSET_UTF8;
425         int     nChar = 0;
426         int     nByte = 0;
427         int     nTemp = 0;
428         char *pReturnStr = NULL;
429         char *pConvertedStr = NULL;
430         MCHAR *mszTempStr = NULL;
431
432         MCHAR *pmszOutTextStr = NULL;
433
434         char szTempBuf[MSG_LOCAL_TEMP_BUF_SIZE] = {0};
435
436         // copy original string
437         if (strlen(pOri) >= MSG_LOCAL_TEMP_BUF_SIZE) {
438                 pSrc = MsgStrCopy( pOri );
439         } else {
440                 memset(szTempBuf, 0, MSG_LOCAL_TEMP_BUF_SIZE);
441                 strcpy(szTempBuf, pOri);
442
443                 pSrc = szTempBuf;
444         }
445
446         // it can be one or more encoding methods in a line
447         while (1) {
448                 cnt++;
449
450                 bEncoding = false;
451
452                 /*
453                   (ex) "=?euc-kr?B?Y2NqMjEyMw==?="
454
455                   pDecStart: charset                    (=?euc-kr?B?Y2NqMjEyMw==?=)
456                   pDecQ : Encoding type         (B?Y2NqMjEyMw==?=)
457                   pDecQ2        : Encoded text          (Y2NqMjEyMw==?=)
458                   pDecEnd       : Encoded of text       (?=)
459                  */
460                 if (pSrc == NULL)
461                         goto __CATCH;
462
463                 if (((pDecStart = strstr(pSrc, MSG_STR_DEC_START)) != NULL)     //"=?"
464                      && ((pDecQ = strchr(pDecStart + 2, MSG_CH_QUESTION)) != NULL)      // '?'
465                      && ((pDecQ2 = strchr(pDecQ + 1, MSG_CH_QUESTION))!= NULL)          // '?'
466                      && ((pDecEnd = strstr(pDecQ2 + 1, MSG_STR_DEC_END))!= NULL)) {     //"=?"
467                         bEncoding = true;
468
469                         /* fixme: charset problem
470                          * pDecStart ~ pDecQ : charSet & MSG_CHARSET_USC2 ~ MSG_CHARSET_UTF8 & LATIN
471                          */
472
473                         *pDecQ = '\0';
474                         nCharset = _MsgGetCode(MSG_CHARSET, pDecStart + 2);
475                         *pDecQ = MSG_CH_QUESTION;
476                 }
477
478                 // End of encoding
479                 if (!bEncoding)
480                         goto __RETURN;
481
482                 // find end of string
483                 pStrEnd = pSrc + strlen(pSrc);
484
485                 // Decoding
486                 if ((*(pDecQ2 - 1) == MSG_CH_BASE64_UPPER) ||
487                         (*(pDecQ2 - 1) == MSG_CH_BASE64_LOWER) ||
488                         (*(pDecQ + 1) == MSG_CH_BASE64_UPPER) ||
489                         (*(pDecQ + 1) == MSG_CH_BASE64_LOWER)) {
490                         pTemp = (char *)_MsgDecodeBase64((UCHAR *)(pDecQ2 + 1), (ULONG)(pDecEnd - pDecQ2 - 1), (ULONG *)&size);
491
492                         if (pTemp != NULL) {
493                                 pTemp[size] = MSG_CH_NULL;
494
495                                 if(pRe) {
496                                         free(pRe);
497                                         pRe = NULL;
498                                 }
499
500                                 pRe = (char *)malloc((pDecStart-pSrc) + size + (pStrEnd - (pDecEnd + 2)) + 1);
501                                 if (pRe == NULL) {
502                                         MSG_DEBUG("_MsgDecodeText: pRemalloc fail \n");
503                                         free(pTemp);
504                                         pTemp = NULL;
505
506                                         goto __RETURN;
507                                 }
508
509                                 memcpy(pRe, pSrc, pDecStart - pSrc);
510                                 memcpy(&pRe[pDecStart-pSrc], pTemp, size);
511                                 memcpy(&pRe[(pDecStart - pSrc) + size], pDecEnd + 2, pStrEnd - (pDecEnd + 2));
512                                 pRe[(pDecStart - pSrc) + size + (pStrEnd - (pDecEnd + 2))] = MSG_CH_NULL;
513
514                                 free(pTemp);
515                                 pTemp = NULL;
516
517                                 if (pSrc != NULL && pSrc != szTempBuf) {
518                                         free(pSrc);
519                                         pSrc = NULL;
520                                 }
521                         }
522                 } else if ((*(pDecQ2-1) == MSG_CH_QPRINT_UPPER) ||
523                                 (*(pDecQ2-1) == MSG_CH_QPRINT_LOWER) ||
524                                 (*(pDecQ+1) == MSG_CH_QPRINT_UPPER) ||
525                                 (*(pDecQ+1) == MSG_CH_QPRINT_LOWER)) {
526
527                         pTemp = (char *)_MsgDecodeQuotePrintable((UCHAR *)( pDecQ2 + 1 ), (ULONG)(pDecEnd - pDecQ2 - 1), (ULONG *)&size);
528
529                         if (pTemp != NULL) {
530                                 int i;
531                                 pTemp[size] = MSG_CH_NULL;
532
533                                 for (i = 0; i < size; i++) {
534                                         if (pTemp[i] == MSG_CH_UNDERLINE) {
535                                                 pTemp[i] = MSG_CH_SP;                         // change '_' to ' '
536                                         }
537                                 }
538
539                                 if(pRe) {
540                                         free(pRe);
541                                         pRe = NULL;
542                                 }
543
544                                 pRe = (char *)malloc((pDecStart - pSrc) + size + (pStrEnd - (pDecEnd + 2)) + 1);
545                                 if (pRe == NULL) {
546                                         MSG_DEBUG("_MsgDecodeText: pRemalloc fail \n");
547                                         free(pTemp);
548                                         pTemp = NULL;
549
550                                         goto __RETURN;
551                                 }
552
553                                 memcpy(pRe, pSrc, pDecStart - pSrc);
554                                 memcpy(&pRe[pDecStart - pSrc], pTemp, size);
555                                 memcpy(&pRe[(pDecStart - pSrc) + size], pDecEnd + 2, pStrEnd - (pDecEnd + 2));
556                                 pRe[(pDecStart - pSrc) + size + (pStrEnd - (pDecEnd + 2))] = MSG_CH_NULL;
557
558                                 if (pTemp) {
559                                         free(pTemp);
560                                         pTemp = NULL;
561                                 }
562
563                                 if (pSrc != NULL && pSrc != szTempBuf) {
564                                         free(pSrc);
565                                         pSrc = NULL;
566                                 }
567                         }
568                 } else {
569                         goto __RETURN;
570                 }
571         }
572
573 __RETURN:
574
575         pTemp = pSrc;
576         nTemp = strlen(pSrc);
577
578         switch (nCharset) {
579         case MSG_CHARSET_UTF16:
580         case MSG_CHARSET_USC2:
581
582                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_USC2 \n");
583
584                 if (pTemp) {
585                         // mmf file name display patch
586                         if (((UINT8)pTemp[0] == 0xFF && (UINT8)pTemp[1] == 0xFE) || ((UINT8)pTemp[0] == 0xFE && (UINT8)pTemp[1] == 0xFF)) {
587
588                                 nChar = (nTemp / 2 - 1);
589
590                                 // Re check char-set
591                                 if (MsgIsUTF8String((unsigned char *)pTemp + 2, nTemp - 2)) {
592                                         strncpy(pTemp, pTemp + 2, strlen(pTemp + 2));
593                                         nTemp = nTemp - 2;
594                                         MSG_DEBUG("_MsgDecodeText: real char-set = MSG_CHARSET_UTF8.\n");
595                                         break;
596                                 }
597
598                                 mszTempStr = (unsigned short *)malloc(nChar * sizeof(unsigned short));
599                                 if (mszTempStr == NULL) {
600                                         MSG_DEBUG("_MsgDecodeText: 1. Memory Full !!! \n");
601                                         goto __CATCH;
602                                 }
603
604                                 memcpy(mszTempStr, ((unsigned short *)pTemp + 1), nChar * sizeof(unsigned short));
605
606                                 nByte = MsgGetUnicode2UTFCodeSize(((unsigned short *)pTemp + 1), nChar);
607
608                                 pConvertedStr = (char *)malloc(nByte + 1);
609                                 if (pConvertedStr) {
610                                         MsgUnicode2UTF ((unsigned char *)pConvertedStr, nByte + 1, mszTempStr, nChar);
611                                 }
612                         } else {
613                                 nChar = (nTemp / 2);
614
615                                 if (nChar == 0) {
616                                         nChar = 2;
617                                 }
618
619                                 // Re check char-set
620                                 if (MsgIsUTF8String((unsigned char *)pTemp, nTemp)) {
621                                         MSG_DEBUG("_MsgDecodeText: real char-set = MSG_CHARSET_UTF8.\n");
622                                         break;
623                                 }
624
625                                 mszTempStr = (unsigned short *)malloc(nChar * sizeof(unsigned short));
626                                 if (mszTempStr == NULL) {
627                                         MSG_DEBUG("_MsgDecodeText: 2. Memory Full !!! \n");
628                                         goto __CATCH;
629                                 }
630
631                                 memcpy(mszTempStr, ((unsigned short *)pTemp), nChar * sizeof(unsigned short));
632
633                                 nByte = MsgGetUnicode2UTFCodeSize(((unsigned short *)pTemp), nChar);
634
635                                 pConvertedStr = (char *)malloc(nByte + 1);
636                                 if (pConvertedStr) {
637                                         MsgUnicode2UTF ((unsigned char *)pConvertedStr, nByte + 1, mszTempStr, nChar);
638                                 }
639                         }
640                 }
641
642                 pTemp = pConvertedStr;
643                 nTemp = nByte;
644
645                 break;
646
647         case MSG_CHARSET_US_ASCII:
648
649                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_US_ASCII \n");
650                 break;
651
652         case MSG_CHARSET_UTF8:
653
654                 /* UTF8 is  default charset of Messenger */
655
656                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_UTF8 \n");
657
658                 break;
659
660         case MSG_CHARSET_ISO_8859_1:
661
662                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_ISO_8859_1 \n");
663
664                 nByte = nTemp * 3;
665
666                 pmszOutTextStr = (unsigned short *)malloc(sizeof(MCHAR *) * (nByte + 1));
667                 if (pmszOutTextStr == NULL) {
668                         MSG_DEBUG("_MsgDecodeText : Out Text String null !!! \n");
669                         goto __CATCH;
670                 }
671
672                 pConvertedStr = (char *)malloc(sizeof(char *) * (nByte + 1));
673                 if (pConvertedStr) {
674                         WmConvertLatinCode2PCode(pmszOutTextStr, sizeof(MCHAR *) * (nByte + 1), pTemp);
675                         WmConvert2LCode(pConvertedStr, sizeof(char *) * (nByte + 1), pmszOutTextStr);
676                 }
677
678                 if (pmszOutTextStr) {
679                         free(pmszOutTextStr);
680                         pmszOutTextStr = NULL;
681                 }
682
683                 pTemp = pConvertedStr;
684                 nTemp = nByte;
685
686                 break;
687
688         case MSG_CHARSET_ISO_8859_2:
689
690                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_ISO_8859_2 \n");
691
692                 nByte = nTemp * 3;
693
694                 pmszOutTextStr = (unsigned short *)malloc(sizeof(MCHAR *) * (nByte + 1));
695                 if (pmszOutTextStr == NULL) {
696                         MSG_DEBUG("_MsgDecodeText : Out Text String null !!! \n");
697                         goto __CATCH;
698                 }
699
700                 pConvertedStr =  (char *)malloc(sizeof(char *) * (nByte + 1));
701                 if (pConvertedStr) {
702                         WmConvertLatin2Code2PCode(pmszOutTextStr, sizeof(MCHAR *) * (nByte + 1), pTemp);
703                         WmConvert2LCode(pConvertedStr, sizeof(char *) * (nByte + 1), pmszOutTextStr);
704                 }
705
706                 if (pmszOutTextStr) {
707                         free(pmszOutTextStr);
708                         pmszOutTextStr = NULL;
709                 }
710
711                 pTemp = pConvertedStr;
712                 nTemp = nByte;
713
714                 break;
715
716         case MSG_CHARSET_ISO_8859_3:
717
718                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_ISO_8859_3 \n");
719
720                 nByte = WmGetLatin32UTFCodeSize((unsigned char *)pTemp, nTemp);
721
722                 pmszOutTextStr = (unsigned short *)malloc(sizeof(MCHAR *) * (nByte + 1));
723                 if (pmszOutTextStr == NULL) {
724                         MSG_DEBUG("_MsgDecodeText : Out Text String null !!! \n");
725                         goto __CATCH;
726                 }
727
728                 pConvertedStr = (char *)malloc(sizeof(char *) * (nByte + 1));
729                 if (pConvertedStr) {
730                         WmConvertLatin3Code2PCode(pmszOutTextStr, sizeof(MCHAR *) * (nByte + 1), pTemp);
731                         WmConvert2LCode(pConvertedStr, sizeof(char *) * (nByte + 1), pmszOutTextStr);
732                 }
733
734                 if (pmszOutTextStr) {
735                         free(pmszOutTextStr);
736                         pmszOutTextStr = NULL;
737                 }
738
739                 pTemp = pConvertedStr;
740                 nTemp = nByte;
741
742                 break;
743
744         case MSG_CHARSET_ISO_8859_4:
745
746                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_ISO_8859_4 \n");
747
748                 nByte = WmGetLatin42UTFCodeSize((unsigned char *)pTemp, nTemp);
749
750                 pmszOutTextStr = (unsigned short *)malloc(sizeof(MCHAR *) * (nByte + 1));
751                 if (pmszOutTextStr == NULL) {
752                         MSG_DEBUG("_MsgDecodeText : Out Text String null !!! \n");
753                         goto __CATCH;
754                 }
755
756                 pConvertedStr = (char *)malloc(sizeof(char *) * (nByte + 1));
757                 if (pConvertedStr) {
758                         WmConvertLatin4Code2PCode(pmszOutTextStr, sizeof(MCHAR *) * (nByte + 1), pTemp);
759                         WmConvert2LCode(pConvertedStr, sizeof(char *) * (nByte + 1), pmszOutTextStr);
760                 }
761
762                 if (pmszOutTextStr) {
763                         free(pmszOutTextStr);
764                         pmszOutTextStr = NULL;
765                 }
766
767                 pTemp = pConvertedStr;
768                 nTemp = nByte;
769
770                 break;
771
772         case MSG_CHARSET_ISO_8859_5:
773
774                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_ISO_8859_5 \n");
775
776                 nByte = WmGetLatin52UTFCodeSize((unsigned char *)pTemp, nTemp);
777
778                 pmszOutTextStr = (unsigned short *)malloc(sizeof(MCHAR *) * (nByte + 1));
779                 if (pmszOutTextStr == NULL) {
780                         MSG_DEBUG("_MsgDecodeText : Out Text String null !!! \n");
781                         goto __CATCH;
782                 }
783
784                 pConvertedStr = (char *)malloc(sizeof(char *) * (nByte + 1));
785                 if (pConvertedStr) {
786                         WmConvertLatin5Code2PCode(pmszOutTextStr, sizeof(MCHAR *) * (nByte + 1), pTemp);
787                         WmConvert2LCode(pConvertedStr, sizeof(char *) * (nByte + 1), pmszOutTextStr);
788                 }
789
790                 if (pmszOutTextStr) {
791                         free(pmszOutTextStr);
792                         pmszOutTextStr = NULL;
793                 }
794
795                 pTemp = pConvertedStr;
796                 nTemp = nByte;
797
798                 break;
799
800         case MSG_CHARSET_ISO_8859_7:
801
802                 /* Greek */
803                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_ISO_8859_9 \n");
804
805                 nByte = MsgGetLatin72UTFCodeSize((unsigned char *)pTemp, nTemp);
806                 pConvertedStr = (char *)malloc( nByte + 1);
807                 if (pConvertedStr) {
808                         MsgLatin7code2UTF((unsigned char *)pConvertedStr, nByte + 1 , (unsigned char *)pTemp, nTemp);
809                 }
810
811                 pTemp = pConvertedStr;
812                 nTemp = nByte;
813
814                 break;
815
816         case MSG_CHARSET_ISO_8859_8:
817
818                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_ISO_8859_8 \n");
819
820                 nByte = WmGetLatin82UTFCodeSize((unsigned char *)pTemp, nTemp);
821
822                 pmszOutTextStr = (unsigned short *)malloc(sizeof(MCHAR *) * (nByte + 1));
823                 if (pmszOutTextStr == NULL) {
824                         MSG_DEBUG("_MsgDecodeText : Out Text String null !!! \n");
825                         goto __CATCH;
826                 }
827
828                 pConvertedStr = (char *)malloc(sizeof(char *) * (nByte + 1));
829                 if (pConvertedStr) {
830                         WmConvertLatin8Code2PCode(pmszOutTextStr, sizeof(MCHAR *) * (nByte + 1), pTemp);
831                         WmConvert2LCode(pConvertedStr, sizeof(char *) * (nByte + 1), pmszOutTextStr);
832                 }
833
834                 if (pmszOutTextStr) {
835                         free(pmszOutTextStr);
836                         pmszOutTextStr = NULL;
837                 }
838
839                 pTemp = pConvertedStr;
840                 nTemp = nByte;
841
842                 break;
843
844         case MSG_CHARSET_ISO_8859_9:
845                 /* Turkish */
846
847                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_ISO_8859_9 \n");
848
849                 nByte = MsgGetLatin52UTFCodeSize((unsigned char *)pTemp, nTemp);
850                 pConvertedStr = (char *)malloc(nByte + 1);
851                 if (pConvertedStr) {
852                         MsgLatin5code2UTF((unsigned char *)pConvertedStr, nByte + 1 , (unsigned char *)pTemp, nTemp);
853                 }
854
855                 pTemp = pConvertedStr;
856                 nTemp = nByte;
857
858                 break;
859
860         case MSG_CHARSET_ISO_8859_15:
861
862                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_ISO_8859_15 \n");
863
864                 nByte = WmGetLatin152UTFCodeSize((unsigned char *)pTemp, nTemp);
865
866                 pmszOutTextStr = (unsigned short *)malloc(sizeof(MCHAR *) * (nByte + 1));
867                 if (pmszOutTextStr == NULL) {
868                         MSG_DEBUG("_MsgDecodeText : Out Text String null !!! \n");
869                         goto __CATCH;
870                 }
871
872                 pConvertedStr = (char *)malloc(sizeof(char *) * (nByte + 1));
873                 if (pConvertedStr) {
874                         WmConvertLatin15Code2PCode(pmszOutTextStr, sizeof(MCHAR *) * (nByte + 1), pTemp);
875                         WmConvert2LCode(pConvertedStr, sizeof(char *) * (nByte + 1), pmszOutTextStr);
876                 }
877
878                 if (pmszOutTextStr) {
879                         free(pmszOutTextStr);
880                         pmszOutTextStr = NULL;
881                 }
882
883                 pTemp = pConvertedStr;
884                 nTemp = nByte;
885
886                 break;
887
888         case MSG_CHARSET_WIN1251:
889         case MSG_CHARSET_WINDOW_1251:
890         case MSG_CHARSET_WINDOWS_1251:
891
892                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_WINDOWS_1251 \n");
893
894                 nByte = nTemp * 3;
895
896                 pmszOutTextStr = (unsigned short *)malloc(sizeof(MCHAR *) * (nByte + 1));
897                 if (pmszOutTextStr == NULL) {
898                         MSG_DEBUG("_MsgDecodeText : Out Text String null !!! \n");
899                         goto __CATCH;
900                 }
901
902                 pConvertedStr = (char *)malloc(sizeof(char *) * (nByte + 1));
903                 if (pConvertedStr) {
904                         WmConvertWin1251Code2PCode(pmszOutTextStr, sizeof(MCHAR *) * (nByte + 1), pTemp);
905                         WmConvert2LCode(pConvertedStr, sizeof(char *) * (nByte + 1), pmszOutTextStr);
906                 }
907
908                 if (pmszOutTextStr) {
909                         free(pmszOutTextStr);
910                         pmszOutTextStr = NULL;
911                 }
912
913                 pTemp = pConvertedStr;
914                 nTemp = nByte;
915
916                 break;
917
918         case MSG_CHARSET_KOI8_R:
919
920                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_KOI8_R \n");
921
922                 nByte = nTemp * 3;
923
924                 pmszOutTextStr = (unsigned short *)malloc(sizeof(MCHAR *) * (nByte + 1));
925                 if (pmszOutTextStr == NULL) {
926                         MSG_DEBUG("_MsgDecodeText : Out Text String null !!! \n");
927                         goto __CATCH;
928                 }
929
930                 pConvertedStr = (char *)malloc(sizeof(char *) * (nByte + 1));
931                 if (pConvertedStr) {
932                         WmConvertKoi8rCode2PCode(pmszOutTextStr, sizeof(MCHAR *) * (nByte + 1), pTemp);
933                         WmConvert2LCode(pConvertedStr, sizeof(char *) * (nByte + 1), pmszOutTextStr);
934                 }
935
936                 if (pmszOutTextStr) {
937                         free(pmszOutTextStr);
938                         pmszOutTextStr = NULL;
939                 }
940
941                 pTemp = pConvertedStr;
942                 nTemp = nByte;
943
944                 break;
945
946         case MSG_CHARSET_KOI8_U:
947
948                 MSG_DEBUG("_MsgDecodeText: MSG_CHARSET_KOI8_U \n");
949
950                 nByte = nTemp * 3;
951
952                 pmszOutTextStr = (unsigned short *)malloc(sizeof(MCHAR *) * (nByte + 1));
953                 if (pmszOutTextStr == NULL) {
954                         MSG_DEBUG("_MsgDecodeText : Out Text String null !!! \n");
955                         goto __CATCH;
956                 }
957
958                 pConvertedStr = (char *)malloc(sizeof(char *) * (nByte + 1));
959                 if (pConvertedStr) {
960                         WmConvertKoi8uCode2PCode(pmszOutTextStr, sizeof(MCHAR *) * (nByte + 1), pTemp);
961                         WmConvert2LCode(pConvertedStr, sizeof(char *) * (nByte + 1), pmszOutTextStr);
962                 }
963
964                 if (pmszOutTextStr) {
965                         free(pmszOutTextStr);
966                         pmszOutTextStr = NULL;
967                 }
968
969                 pTemp = pConvertedStr;
970                 nTemp = nByte;
971
972                 break;
973
974         default:
975
976                 MSG_DEBUG("_MsgDecodeText: Other charsets \n");
977
978                 nByte = MsgGetLatin2UTFCodeSize((unsigned char *)pTemp, nTemp);
979                 pConvertedStr = (char *)malloc(nByte + 1);
980                 if (pConvertedStr) {
981                         MsgLatin2UTF((unsigned char *)pConvertedStr, nByte + 1, (unsigned char *)pTemp, nTemp);
982                 }
983
984                 pTemp = pConvertedStr;
985                 nTemp = nByte;
986
987                 break;
988         }
989
990         pReturnStr = (char *)malloc(nTemp + 1);
991         if (pReturnStr == NULL) {
992                 goto __CATCH;
993         }
994         memset(pReturnStr, 0, nTemp + 1);
995
996         if (pTemp)
997                 memcpy(pReturnStr, pTemp, nTemp);
998
999         if (pConvertedStr) {
1000                 free(pConvertedStr);
1001                 pConvertedStr = NULL;
1002         }
1003
1004         if (mszTempStr) {
1005                 free(mszTempStr);
1006                 mszTempStr = NULL;
1007         }
1008
1009         if(pRe) {
1010                 free(pRe);
1011                 pRe = NULL;
1012         }
1013
1014         if (pSrc != NULL && pSrc != szTempBuf) {
1015                 free(pSrc);
1016                 pSrc = NULL;
1017         }
1018
1019         return pReturnStr;
1020
1021 __CATCH:
1022
1023         if (pConvertedStr) {
1024                 free(pConvertedStr);
1025                 pConvertedStr = NULL;
1026         }
1027
1028         if (mszTempStr) {
1029                 free(mszTempStr);
1030                 mszTempStr = NULL;
1031         }
1032
1033         if(pRe) {
1034                 free(pRe);
1035                 pRe = NULL;
1036         }
1037
1038         if (pSrc != NULL && pSrc != szTempBuf) {
1039                 free(pSrc);
1040                 pSrc = NULL;
1041         }
1042
1043         return NULL;
1044 }
1045
1046
1047 char *MsgEncodeText(char *pOri)
1048 {
1049         ULONG nLen = 0;
1050         char *szBuff = NULL;
1051         int length  = 0;
1052
1053         length = (strlen(pOri) * 4) / 3 + 2 + 12 + 1 + 30;
1054         szBuff = (char *)malloc(length + 1);
1055
1056         if (szBuff == NULL) {
1057                 // error handling
1058                 MSG_DEBUG("_MsgEncodeText: szBuff alloc is failed \n");
1059                 goto __CATCH;
1060         }
1061
1062         memset(szBuff, 0 , length + 1);
1063
1064         snprintf(szBuff, length+1, "%s%s%c%c%c", MSG_STR_DEC_START, "utf-8", MSG_CH_QUESTION, MSG_CH_BASE64_LOWER, MSG_CH_QUESTION);
1065
1066         if (_MsgEncode2Base64((unsigned char *)pOri, strlen(pOri), &nLen, (unsigned char *)szBuff + 10) == false) {
1067                 MSG_DEBUG("_MsgEncodeText: MsgEncodeBase64() is failed \n");
1068                 goto __CATCH;
1069         }
1070
1071         strcat(szBuff, MSG_STR_DEC_END);
1072
1073         return szBuff;
1074
1075 __CATCH:
1076         if (szBuff) {
1077                 free(szBuff);
1078         }
1079
1080         return false;
1081 }
1082