2 * Copyright 2012 Samsung Electronics Co., Ltd
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
8 * http://www.tizenopensource.org/license
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.
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;
27 /* ==================================================================
28 * Decode/Encode inline base64 string
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.
33 * Value Encoding Value Encoding Value Encoding Value Encoding
35 * 1 B 18 S 35 j 52 '0'
48 * 14 O 31 f 48 w (pad) =
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 * ================================================================== */
57 bool _MsgEncodeBase64(void *pSrc, unsigned long srcLen, unsigned long *len, unsigned char *ret)
59 unsigned char *d = NULL;
60 unsigned char *s = (unsigned char *)pSrc;
62 char *v = (char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
63 unsigned long i = ((srcLen + 2) / 3) * 4;
65 i += 2 * ((i / 60) + 1);
69 MSG_DEBUG("_MsgEncodeBase64: ret Memory Alloc Fail \n");
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
86 /* Insert CRLF at every 60 characters */
100 if (((unsigned long)(d - ret)) != *len) {
102 MSG_DEBUG("base64 encoding length = %d \n", *len);
109 void *_MsgDecodeBase64(unsigned char *pSrc, unsigned long srcLen, unsigned long *len)
116 ret = malloc((size_t)(*len = 4 + ((srcLen * 3) / 4)));
120 MSG_DEBUG("_MsgDecodeBase64: ret malloc Fail \n");
124 memset(ret, 0, (size_t)*len);
127 while (srcLen-- > 0) {
130 /* Convert base64 character into original value */
146 *len = d - (char *)ret;
154 *len = d - (char *)ret;
159 continue; // Actually, never get here
161 /* Pad 4*6bit character into 3*8bit character */
165 *d = c << 2; // byte 1: high 6 bits
169 *d++ |= c >> 4; // byte 1: low 2 bits
170 *d = c << 4; // byte 2: high 4 bits
174 *d++ |= c >> 2; // byte 2: low 4 bits
175 *d = c << 6; // byte 3: high 2 bits
179 *d++ |= c; // byte 3: low 6 bits
180 e = 0; // Calculate next unit.
184 MSG_DEBUG("_MsgDecodeBase64: Unknown paremeter\n");
189 *len = d - (char *)ret; // Calculate the size of decoded string.
196 /* ==========================================
197 * Decode/Encode inline base64 string
199 * quoted-printable := ([*(ptext / SPACE / TAB) ptext] ["="] CRLF)
200 * ; Maximum line length of 76 characters excluding CRLF
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.
206 * octet := "=" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F")
207 * ; octet must be used for characters > 127, =, SPACE, or TAB.
209 * ==========================================*/
211 bool _MsgEncodeQuotePrintable(unsigned char *pSrc, unsigned long srcLen, unsigned long *len, unsigned char *ret)
213 unsigned long lp = 0;
214 unsigned char *d = ret;
215 char *hex = (char *)"0123456789ABCDEF";
219 MSG_DEBUG("_MsgEncodeQuotePrintable: ret malloc Fail \n");
226 * The type of srcLen is unsigned long
227 * The value of srcLen is decreased by 1 -> We can't check by "srcLen > 0".
229 while (srcLen-- > 0) {
231 if (((c = *pSrc++) == '\015') && (*pSrc == '\012') && srcLen) {
237 if (iscntrl(c) || (c == 0x7f) || (c & 0x80) || (c == '=') || ((c == ' ') && (*pSrc == '\015'))) {
238 if ((lp += 3) > (unsigned long)MSG_MAX_CH_PER_LINE) {
245 *d++ = '='; /* quote character */
246 *d++ = hex[c >> 4]; /* high order 4 bits */
247 *d++ = hex[c & 0xf]; /* low order 4 bits */
249 /* Just copy ASCII character */
250 if ((++lp) > (unsigned long)MSG_MAX_CH_PER_LINE) {
268 unsigned char *_MsgDecodeQuotePrintable(unsigned char *pSrc, unsigned long srcLen, unsigned long *len)
270 unsigned char *ret = NULL;
271 unsigned char *d = NULL;
272 unsigned char *s = NULL; /* last non-blank */
276 d = s = ret = (unsigned char *)malloc((size_t)srcLen + 1);
278 MSG_DEBUG("_MsgDecodeQuotePrintable: ret malloc Fail \n");
285 while ((c = *pSrc++)!= '\0') {
287 case '=': /* octet characters (> 127, =, SPACE, or TAB) */
288 switch (c = *pSrc++) {
289 case '\0': /* end of string -> postpone to while */
292 case '\015': /* CRLF */
297 default: /* two hexes */
307 e = c - (isupper(c) ? 'A' - 10 : 'a' - 10);
319 c -= (isupper(c) ? 'A' - 10 : 'a' - 10);
327 case ' ': /* skip the blank */
331 case '\015': /* Line Feedback : to last non-blank character */
336 *d++ = c; /* ASCII character */
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)
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;
361 i += 2 * ((i / 60) + 1);
365 MSG_DEBUG("_MsgEncode2Base64: ret Memory Alloc Fail \n");
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
385 if (((unsigned long)(d - ret)) != *len) {
387 MSG_DEBUG("base64 encoding length = %d \n", *len);
394 char *_MsgDecodeText(char *pOri)
403 char *pStrEnd = NULL;
404 char *pDecStart = NULL;
405 char *pDecEnd = NULL;
408 bool bEncoding = false;
409 int nCharset = MSG_CHARSET_UTF8;
411 char *pReturnStr = NULL;
412 char *pConvertedStr = NULL;
414 char szTempBuf[MSG_LOCAL_TEMP_BUF_SIZE] = {0};
416 // copy original string
417 if (strlen(pOri) >= MSG_LOCAL_TEMP_BUF_SIZE) {
418 pSrc = MsgStrCopy( pOri );
420 memset(szTempBuf, 0, MSG_LOCAL_TEMP_BUF_SIZE);
421 strcpy(szTempBuf, pOri);
426 // it can be one or more encoding methods in a line
433 (ex) "=?euc-kr?B?Y2NqMjEyMw==?="
435 pDecStart: charset (=?euc-kr?B?Y2NqMjEyMw==?=)
436 pDecQ : Encoding type (B?Y2NqMjEyMw==?=)
437 pDecQ2 : Encoded text (Y2NqMjEyMw==?=)
438 pDecEnd : Encoded of text (?=)
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)) { //"=?"
449 /* fixme: charset problem
450 * pDecStart ~ pDecQ : charSet & MSG_CHARSET_USC2 ~ MSG_CHARSET_UTF8 & LATIN
454 nCharset = _MsgGetCode(MSG_CHARSET, pDecStart + 2);
455 *pDecQ = MSG_CH_QUESTION;
462 // find end of string
463 pStrEnd = pSrc + strlen(pSrc);
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);
473 pTemp[size] = MSG_CH_NULL;
480 pRe = (char *)malloc((pDecStart-pSrc) + size + (pStrEnd - (pDecEnd + 2)) + 1);
482 MSG_DEBUG("_MsgDecodeText: pRemalloc fail \n");
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;
497 if (pSrc != NULL && pSrc != szTempBuf) {
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)) {
507 pTemp = (char *)_MsgDecodeQuotePrintable((UCHAR *)( pDecQ2 + 1 ), (ULONG)(pDecEnd - pDecQ2 - 1), (ULONG *)&size);
511 pTemp[size] = MSG_CH_NULL;
513 for (i = 0; i < size; i++) {
514 if (pTemp[i] == MSG_CH_UNDERLINE) {
515 pTemp[i] = MSG_CH_SP; // change '_' to ' '
524 pRe = (char *)malloc((pDecStart - pSrc) + size + (pStrEnd - (pDecEnd + 2)) + 1);
526 MSG_DEBUG("_MsgDecodeText: pRemalloc fail \n");
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;
543 if (pSrc != NULL && pSrc != szTempBuf) {
557 pTemp = strdup(pSrc);
558 nTemp = strlen(pSrc);
561 const char *pToCharSet = "UTF-8";
563 UINT16 charset_code = _MmsGetBinaryValue(MmsCodeCharSet, nCharset);
565 const char *pFromCharSet = MmsPluginTextConvertGetCharSet(charset_code);
567 if (pFromCharSet != NULL && strcmp(pFromCharSet, pToCharSet) != 0) {//Not UTF-8
571 if (MmsPluginTextConvert(pToCharSet, pFromCharSet, pTemp, nTemp, &pDest, &destLen) == false) {
572 MSG_DEBUG("MmsPluginTextConvert Fail");
577 pTemp = strdup(pDest);
585 pReturnStr = (char *)malloc(nTemp + 1);
587 if (pReturnStr == NULL) {
591 memset(pReturnStr, 0, nTemp + 1);
594 memcpy(pReturnStr, pTemp, nTemp);
601 pConvertedStr = NULL;
609 if (pSrc != NULL && pSrc != szTempBuf) {
620 pConvertedStr = NULL;
628 if (pSrc != NULL && pSrc != szTempBuf) {
642 char *MsgEncodeText(char *pOri)
648 length = (strlen(pOri) * 4) / 3 + 2 + 12 + 1 + 30;
649 szBuff = (char *)malloc(length + 1);
651 if (szBuff == NULL) {
653 MSG_DEBUG("_MsgEncodeText: szBuff alloc is failed \n");
657 memset(szBuff, 0 , length + 1);
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);
661 if (_MsgEncode2Base64((unsigned char *)pOri, strlen(pOri), &nLen, (unsigned char *)szBuff + 10) == false) {
662 MSG_DEBUG("_MsgEncodeText: MsgEncodeBase64() is failed \n");
666 strcat(szBuff, MSG_STR_DEC_END);