RSA sync with private
[platform/core/messaging/msg-service.git] / plugin / mms_plugin / MmsPluginContentCodec.cpp
1 /*
2 * Copyright 2012  Samsung Electronics Co., Ltd
3 *
4 * Licensed under the Flora License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *    http://www.tizenopensource.org/license
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdlib.h>
18 #include <ctype.h>
19 #include "MsgDebug.h"
20 #include "MmsPluginCodec.h"
21 #include "MmsPluginTextConvert.h"
22 #include "MmsPluginMIME.h"
23 #include "MmsPluginMessage.h"
24 #include "MmsPluginUtil.h"
25 const int MSG_MAX_CH_PER_LINE = 75;
26
27 /* ==================================================================
28  *      Decode/Encode inline base64 string
29  *
30  * base64 : 3*8bit -> 4*6bit & convert the value into A~Z, a~z, 0~9, +, or /
31  * pad(=) is needed when the end of the string is < 24bit.
32  *
33  *     Value Encoding  Value Encoding  Value Encoding  Value Encoding
34  *         0 A            17 R            34 i            51 z
35  *         1 B            18 S            35 j            52 '0'
36  *         2 C            19 T            36 k            53 1
37  *         3 D            20 U            37 l            54 2
38  *         4 E            21 V            38 m            55 3
39  *         5 F            22 W            39 n            56 4
40  *         6 G            23 X            40 o            57 5
41  *         7 H            24 Y            41 p            58 6
42  *         8 I            25 Z            42 q            59 7
43  *         9 J            26 a            43 r            60 8
44  *        10 K            27 b            44 s            61 9
45  *        11 L            28 c            45 t            62 +
46  *        12 M            29 d            46 u            63 /
47  *        13 N            30 e            47 v
48  *        14 O            31 f            48 w         (pad) =
49  *        15 P            32 g            49 x
50  *        16 Q            33 h            50 y
51  *
52  * (1) the final quantum = 24 bits : no "=" padding,
53  * (2) the final quantum = 8 bits : two "=" + two characters
54  * (3) the final quantum = 16 bits : one "=" + three characters
55  * ================================================================== */
56
57 bool _MsgEncodeBase64(void *pSrc, unsigned long srcLen, unsigned long *len, unsigned char *ret)
58 {
59         unsigned char *d = NULL;
60         unsigned char *s = (unsigned char *)pSrc;
61
62         char *v = (char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
63         unsigned long i = ((srcLen + 2) / 3) * 4;
64
65         i += 2 * ((i / 60) + 1);
66         *len = i;
67
68         if (ret == NULL) {
69                 MSG_DEBUG("_MsgEncodeBase64: ret Memory Alloc Fail \n");
70                 return false;
71         }
72         memset(ret, 0, i);
73
74         d = ret;
75
76         /* Convert 3*8bit into 4*6bit */
77         for (i = 0; srcLen > 0; s += 3) {
78                 *d++ = v[s[0] >> 2];                                                                                                                    // byte 1: high 6 bits of character-1
79                 *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
80                 *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
81                 *d++ = srcLen ? v[s[2] & 0x3f] : '=';                                                                                   // byte 4: low 6 bits of character-3
82
83                 if (srcLen)
84                         srcLen--;
85
86                 /* Insert CRLF at every 60 characters */
87                 if ((++i) == 15) {
88                         i = 0;
89                         *d++ = '\015';
90                         *d++ = '\012';
91                 }
92         }
93
94         if (i == 15) {
95                 *d++ = '\015';
96                 *d++ = '\012';
97         }
98         *d = '\0';
99
100         if (((unsigned long)(d - ret)) != *len) {
101                 *len = d - ret;
102                 MSG_DEBUG("base64 encoding length = %d \n", *len);
103         }
104
105         return true;
106 }
107
108
109 void *_MsgDecodeBase64(unsigned char *pSrc, unsigned long srcLen, unsigned long *len)
110 {
111         char c;
112         void *ret = NULL;
113         char *d = NULL;
114         short e = 0;
115
116         ret = malloc((size_t)(*len = 4 + ((srcLen * 3) / 4)));
117         d = (char *)ret;
118
119         if (ret == NULL) {
120                 MSG_DEBUG("_MsgDecodeBase64: ret malloc Fail \n");
121                 return NULL;
122         }
123
124         memset(ret, 0, (size_t)*len);
125         *len = 0;
126
127         while (srcLen-- > 0) {
128                 c = *pSrc++;
129
130                 /* Convert base64 character into original value */
131
132                 if (isupper(c))
133                         c -= 'A';
134                 else if (islower(c))
135                         c -= 'a' - 26;
136                 else if (isdigit(c))
137                         c -= '0' - 52;
138                 else if (c == '+')
139                         c = 62;
140                 else if (c == '/')
141                         c = 63;
142                 else if (c == '=') {
143                         switch (e++) {
144                         case 2:
145                                 if (*pSrc != '=') {
146                                         *len = d - (char *)ret;
147                                         return ret;
148                                 }
149                                 break;
150                         case 3:
151                                 e = 0;
152                                 break;
153                         default:
154                                 *len = d - (char *)ret;
155                                 return ret;
156                         }
157                         continue;
158                 } else
159                         continue;                                       // Actually, never get here
160
161                 /* Pad 4*6bit character into 3*8bit character */
162
163                 switch (e++) {
164                 case 0:
165                         *d = c << 2;                    // byte 1: high 6 bits
166                         break;
167
168                 case 1:
169                         *d++ |= c >> 4;                 // byte 1: low 2 bits
170                         *d = c << 4;                    // byte 2: high 4 bits
171                         break;
172
173                 case 2:
174                         *d++ |= c >> 2;                 // byte 2: low 4 bits
175                         *d = c << 6;                    // byte 3: high 2 bits
176                         break;
177
178                 case 3:
179                         *d++ |= c;                              // byte 3: low 6 bits
180                         e = 0;                                  // Calculate next unit.
181                         break;
182
183                 default:
184                         MSG_DEBUG("_MsgDecodeBase64: Unknown paremeter\n");
185                         break;
186                 }
187         }
188
189         *len = d - (char *)ret;                 // Calculate the size of decoded string.
190
191         return ret;
192 }
193
194
195
196 /* ==========================================
197  *      Decode/Encode inline base64 string
198  *
199  * quoted-printable := ([*(ptext / SPACE / TAB) ptext] ["="] CRLF)
200  *       ; Maximum line length of 76 characters excluding CRLF
201  *
202  * ptext := octet /<any ASCII character except "=", SPACE, or TAB>
203  *       ; characters not listed as "mail-safe" in Appendix B
204  *       ; are also not recommended.
205  *
206  * octet := "=" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F")
207  *       ; octet must be used for characters > 127, =, SPACE, or TAB.
208  *
209  * ==========================================*/
210
211 bool _MsgEncodeQuotePrintable(unsigned char *pSrc, unsigned long srcLen, unsigned long *len, unsigned char *ret)
212 {
213         unsigned long lp = 0;
214         unsigned char *d = ret;
215         char *hex = (char *)"0123456789ABCDEF";
216         unsigned char c;
217
218         if (ret == NULL) {
219                 MSG_DEBUG("_MsgEncodeQuotePrintable: ret malloc Fail \n");
220                 return false;
221         }
222
223         d = ret;
224
225         /*
226          * The type of srcLen is unsigned long
227          * The value of srcLen is decreased by 1 -> We can't check by "srcLen > 0".
228          */
229         while (srcLen-- > 0) {
230                 /* Just copy CRLF */
231                 if (((c = *pSrc++) == '\015') && (*pSrc == '\012') && srcLen) {
232                         *d++ = '\015';
233                         *d++ = *pSrc++;
234                         srcLen--;
235                         lp = 0;
236                 } else {
237                         if (iscntrl(c) || (c == 0x7f) || (c & 0x80) || (c == '=') || ((c == ' ') && (*pSrc == '\015'))) {
238                                 if ((lp += 3) > (unsigned long)MSG_MAX_CH_PER_LINE) {
239                                         *d++ = '=';
240                                         *d++ = '\015';
241                                         *d++ = '\012';
242                                         lp = 3;
243                                 }
244
245                                 *d++ = '=';                             /* quote character */
246                                 *d++ = hex[c >> 4];             /* high order 4 bits */
247                                 *d++ = hex[c & 0xf];    /* low order 4 bits */
248                         } else {
249                                 /* Just copy ASCII character */
250                                 if ((++lp) > (unsigned long)MSG_MAX_CH_PER_LINE) {
251                                         *d++ = '=';
252                                         *d++ = '\015';
253                                         *d++ = '\012';
254                                         lp = 1;
255                                 }
256                                 *d++ = c;
257                         }
258                 }
259         }
260
261         *d = '\0';
262         *len = d - ret;
263
264         return true;
265 }
266
267
268 unsigned char *_MsgDecodeQuotePrintable(unsigned char *pSrc, unsigned long srcLen, unsigned long *len)
269 {
270         unsigned char *ret = NULL;
271         unsigned char *d = NULL;
272         unsigned char *s = NULL;                                        /* last non-blank */
273         unsigned char c;
274         unsigned char e;
275
276         d = s = ret = (unsigned char *)malloc((size_t)srcLen + 1);
277         if (ret == NULL) {
278                 MSG_DEBUG("_MsgDecodeQuotePrintable: ret malloc Fail \n");
279                 return NULL;
280         }
281
282         *len = 0;
283         pSrc[srcLen] = '\0';
284
285         while ((c = *pSrc++)!= '\0') {
286                 switch (c) {
287                 case '=':                                                       /* octet characters (> 127, =, SPACE, or TAB) */
288                         switch (c = *pSrc++) {
289                         case '\0':                                      /* end of string -> postpone to while */
290                                 break;
291
292                         case '\015':                            /* CRLF */
293                                 if (*pSrc == '\012')
294                                         pSrc++;
295                                 break;
296
297                         default:                                        /* two hexes */
298                                 if (!isxdigit(c)) {
299                                         *d = '\0';
300                                         *len = d - ret;
301                                         return ret;
302                                 }
303
304                                 if (isdigit(c))
305                                         e = c - '0';
306                                 else
307                                         e = c - (isupper(c) ? 'A' - 10 : 'a' - 10);
308
309                                 c = *pSrc++;
310                                 if (!isxdigit(c)) {
311                                         *d = '\0';
312                                         *len = d - ret;
313                                         return ret;
314                                 }
315
316                                 if (isdigit(c))
317                                         c -= '0';
318                                 else
319                                         c -= (isupper(c) ? 'A' - 10 : 'a' - 10);
320
321                                 *d++ = c + (e << 4);
322                                 s = d;
323                                 break;
324                         }
325                         break;
326
327                 case ' ':                                                       /* skip the blank */
328                         *d++ = c;
329                         break;
330
331                 case '\015':                                            /* Line Feedback : to last non-blank character */
332                         d = s;
333                         break;
334
335                 default:
336                         *d++ = c;                                               /* ASCII character */
337                         s = d;
338                         break;
339                 }
340         }
341
342         *d = '\0';
343         *len = d - ret;
344
345         return ret;
346 }
347
348
349 /* ========================================
350  * Decode/Encode inline base64 string
351  * Inline base64 has no "\r\n" in it,
352  * and has charset and encoding sign in it
353  * ======================================== */
354 bool _MsgEncode2Base64(void *pSrc, unsigned long srcLen, unsigned long *len, unsigned char *ret)
355 {
356         unsigned char *d = NULL;
357         unsigned char *s = (unsigned char *)pSrc;
358         char *v = (char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
359         unsigned long i = ((srcLen + 2) / 3) * 4;
360
361         i += 2 * ((i / 60) + 1);
362         *len = i;
363
364         if (ret == NULL) {
365                 MSG_DEBUG("_MsgEncode2Base64: ret Memory Alloc Fail \n");
366                 return false;
367         }
368         memset(ret, 0, i);
369
370         d = ret;
371
372         /* Convert 3*8bit into 4*6bit */
373         for (i = 0; srcLen > 0; s += 3) {
374                 *d++ = v[s[0] >> 2];                                                                                                                    // byte 1: high 6 bits of character-1
375                 *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
376                 *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
377                 *d++ = srcLen ? v[s[2] & 0x3f] : '=';                                                                                   // byte 4: low 6 bits of character-3
378
379                 if (srcLen)
380                         srcLen--;
381         }
382
383         *d = '\0';
384
385         if (((unsigned long)(d - ret)) != *len) {
386                 *len = d - ret;
387                 MSG_DEBUG("base64 encoding length = %d \n", *len);
388         }
389
390         return true;
391 }
392
393
394 char *_MsgDecodeText(char *pOri)
395 {
396         MSG_BEGIN();
397
398         int size = 0;
399         int cnt = 0;
400         char *pSrc = NULL;
401         char *pTemp = NULL;
402         char *pRe = NULL;
403         char *pStrEnd = NULL;
404         char *pDecStart = NULL;
405         char *pDecEnd = NULL;
406         char *pDecQ = NULL;
407         char *pDecQ2 = NULL;
408         bool bEncoding = false;
409         int     nCharset = MSG_CHARSET_UTF8;
410         int     nTemp = 0;
411         char *pReturnStr = NULL;
412         char *pConvertedStr = NULL;
413
414         char szTempBuf[MSG_LOCAL_TEMP_BUF_SIZE] = {0};
415
416         // copy original string
417         if (strlen(pOri) >= MSG_LOCAL_TEMP_BUF_SIZE) {
418                 pSrc = MsgStrCopy( pOri );
419         } else {
420                 memset(szTempBuf, 0, MSG_LOCAL_TEMP_BUF_SIZE);
421                 strcpy(szTempBuf, pOri);
422
423                 pSrc = szTempBuf;
424         }
425
426         // it can be one or more encoding methods in a line
427         while (1) {
428                 cnt++;
429
430                 bEncoding = false;
431
432                 /*
433                   (ex) "=?euc-kr?B?Y2NqMjEyMw==?="
434
435                   pDecStart: charset                    (=?euc-kr?B?Y2NqMjEyMw==?=)
436                   pDecQ : Encoding type         (B?Y2NqMjEyMw==?=)
437                   pDecQ2        : Encoded text          (Y2NqMjEyMw==?=)
438                   pDecEnd       : Encoded of text       (?=)
439                  */
440                 if (pSrc == NULL)
441                         goto __CATCH;
442
443                 if (((pDecStart = strstr(pSrc, MSG_STR_DEC_START)) != NULL)     //"=?"
444                      && ((pDecQ = strchr(pDecStart + 2, MSG_CH_QUESTION)) != NULL)      // '?'
445                      && ((pDecQ2 = strchr(pDecQ + 1, MSG_CH_QUESTION))!= NULL)          // '?'
446                      && ((pDecEnd = strstr(pDecQ2 + 1, MSG_STR_DEC_END))!= NULL)) {     //"=?"
447                         bEncoding = true;
448
449                         /* fixme: charset problem
450                          * pDecStart ~ pDecQ : charSet & MSG_CHARSET_USC2 ~ MSG_CHARSET_UTF8 & LATIN
451                          */
452
453                         *pDecQ = '\0';
454                         nCharset = _MsgGetCode(MSG_CHARSET, pDecStart + 2);
455                         *pDecQ = MSG_CH_QUESTION;
456                 }
457
458                 // End of encoding
459                 if (!bEncoding)
460                         goto __RETURN;
461
462                 // find end of string
463                 pStrEnd = pSrc + strlen(pSrc);
464
465                 // Decoding
466                 if ((*(pDecQ2 - 1) == MSG_CH_BASE64_UPPER) ||
467                         (*(pDecQ2 - 1) == MSG_CH_BASE64_LOWER) ||
468                         (*(pDecQ + 1) == MSG_CH_BASE64_UPPER) ||
469                         (*(pDecQ + 1) == MSG_CH_BASE64_LOWER)) {
470                         pTemp = (char *)_MsgDecodeBase64((UCHAR *)(pDecQ2 + 1), (ULONG)(pDecEnd - pDecQ2 - 1), (ULONG *)&size);
471
472                         if (pTemp != NULL) {
473                                 pTemp[size] = MSG_CH_NULL;
474
475                                 if(pRe) {
476                                         free(pRe);
477                                         pRe = NULL;
478                                 }
479
480                                 pRe = (char *)malloc((pDecStart-pSrc) + size + (pStrEnd - (pDecEnd + 2)) + 1);
481                                 if (pRe == NULL) {
482                                         MSG_DEBUG("_MsgDecodeText: pRemalloc fail \n");
483                                         free(pTemp);
484                                         pTemp = NULL;
485
486                                         goto __RETURN;
487                                 }
488
489                                 memcpy(pRe, pSrc, pDecStart - pSrc);
490                                 memcpy(&pRe[pDecStart-pSrc], pTemp, size);
491                                 memcpy(&pRe[(pDecStart - pSrc) + size], pDecEnd + 2, pStrEnd - (pDecEnd + 2));
492                                 pRe[(pDecStart - pSrc) + size + (pStrEnd - (pDecEnd + 2))] = MSG_CH_NULL;
493
494                                 free(pTemp);
495                                 pTemp = NULL;
496
497                                 if (pSrc != NULL && pSrc != szTempBuf) {
498                                         free(pSrc);
499                                         pSrc = NULL;
500                                 }
501                         }
502                 } else if ((*(pDecQ2-1) == MSG_CH_QPRINT_UPPER) ||
503                                 (*(pDecQ2-1) == MSG_CH_QPRINT_LOWER) ||
504                                 (*(pDecQ+1) == MSG_CH_QPRINT_UPPER) ||
505                                 (*(pDecQ+1) == MSG_CH_QPRINT_LOWER)) {
506
507                         pTemp = (char *)_MsgDecodeQuotePrintable((UCHAR *)( pDecQ2 + 1 ), (ULONG)(pDecEnd - pDecQ2 - 1), (ULONG *)&size);
508
509                         if (pTemp != NULL) {
510                                 int i;
511                                 pTemp[size] = MSG_CH_NULL;
512
513                                 for (i = 0; i < size; i++) {
514                                         if (pTemp[i] == MSG_CH_UNDERLINE) {
515                                                 pTemp[i] = MSG_CH_SP;                         // change '_' to ' '
516                                         }
517                                 }
518
519                                 if(pRe) {
520                                         free(pRe);
521                                         pRe = NULL;
522                                 }
523
524                                 pRe = (char *)malloc((pDecStart - pSrc) + size + (pStrEnd - (pDecEnd + 2)) + 1);
525                                 if (pRe == NULL) {
526                                         MSG_DEBUG("_MsgDecodeText: pRemalloc fail \n");
527                                         free(pTemp);
528                                         pTemp = NULL;
529
530                                         goto __RETURN;
531                                 }
532
533                                 memcpy(pRe, pSrc, pDecStart - pSrc);
534                                 memcpy(&pRe[pDecStart - pSrc], pTemp, size);
535                                 memcpy(&pRe[(pDecStart - pSrc) + size], pDecEnd + 2, pStrEnd - (pDecEnd + 2));
536                                 pRe[(pDecStart - pSrc) + size + (pStrEnd - (pDecEnd + 2))] = MSG_CH_NULL;
537
538                                 if (pTemp) {
539                                         free(pTemp);
540                                         pTemp = NULL;
541                                 }
542
543                                 if (pSrc != NULL && pSrc != szTempBuf) {
544                                         free(pSrc);
545                                         pSrc = NULL;
546                                 }
547                         }
548                 } else {
549                         goto __RETURN;
550                 }
551         }
552
553
554
555 __RETURN:
556
557         pTemp = strdup(pSrc);
558         nTemp = strlen(pSrc);
559
560         {//temp brace;
561                 const char *pToCharSet = "UTF-8";
562
563                 UINT16 charset_code =  _MmsGetBinaryValue(MmsCodeCharSet, nCharset);
564
565                 const char *pFromCharSet = MmsPluginTextConvertGetCharSet(charset_code);
566
567                 if (pFromCharSet != NULL && strcmp(pFromCharSet, pToCharSet) != 0) {//Not UTF-8
568                         char *pDest = NULL;
569                         int destLen = 0;
570
571                         if (MmsPluginTextConvert(pToCharSet, pFromCharSet, pTemp, nTemp, &pDest, &destLen) == false) {
572                                 MSG_DEBUG("MmsPluginTextConvert Fail");
573                         }
574
575                         if (pDest) {
576                                 free(pTemp);
577                                 pTemp = strdup(pDest);
578                                 nTemp = destLen;
579                                 free(pDest);
580                         }
581                 }
582
583         }
584
585         pReturnStr = (char *)malloc(nTemp + 1);
586
587         if (pReturnStr == NULL) {
588                 goto __CATCH;
589         }
590
591         memset(pReturnStr, 0, nTemp + 1);
592
593         if (pTemp) {
594                 memcpy(pReturnStr, pTemp, nTemp);
595                 free(pTemp);
596                 pTemp = NULL;
597         }
598
599         if (pConvertedStr) {
600                 free(pConvertedStr);
601                 pConvertedStr = NULL;
602         }
603
604         if(pRe) {
605                 free(pRe);
606                 pRe = NULL;
607         }
608
609         if (pSrc != NULL && pSrc != szTempBuf) {
610                 free(pSrc);
611                 pSrc = NULL;
612         }
613
614         return pReturnStr;
615
616 __CATCH:
617
618         if (pConvertedStr) {
619                 free(pConvertedStr);
620                 pConvertedStr = NULL;
621         }
622
623         if(pRe) {
624                 free(pRe);
625                 pRe = NULL;
626         }
627
628         if (pSrc != NULL && pSrc != szTempBuf) {
629                 free(pSrc);
630                 pSrc = NULL;
631         }
632
633         if (pTemp) {
634                 free(pTemp);
635                 pTemp = NULL;
636         }
637
638         return NULL;
639 }
640
641
642 char *MsgEncodeText(char *pOri)
643 {
644         ULONG nLen = 0;
645         char *szBuff = NULL;
646         int length  = 0;
647
648         length = (strlen(pOri) * 4) / 3 + 2 + 12 + 1 + 30;
649         szBuff = (char *)malloc(length + 1);
650
651         if (szBuff == NULL) {
652                 // error handling
653                 MSG_DEBUG("_MsgEncodeText: szBuff alloc is failed \n");
654                 goto __CATCH;
655         }
656
657         memset(szBuff, 0 , length + 1);
658
659         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);
660
661         if (_MsgEncode2Base64((unsigned char *)pOri, strlen(pOri), &nLen, (unsigned char *)szBuff + 10) == false) {
662                 MSG_DEBUG("_MsgEncodeText: MsgEncodeBase64() is failed \n");
663                 goto __CATCH;
664         }
665
666         strcat(szBuff, MSG_STR_DEC_END);
667
668         return szBuff;
669
670 __CATCH:
671         if (szBuff) {
672                 free(szBuff);
673         }
674
675         return false;
676 }
677