3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the License);
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #include <glib/gprintf.h>
21 #include "encoding_util.h"
24 #include "utility/sync_util.h"
26 #ifndef SYNC_AGENT_LOG
28 #define LOG_TAG "ENCODING_UTIL"
31 #define TYPE_CHECK_BUF_SIZE 100 /* temporary definition */
32 #define TEMP_BUFFER_SIZE 1024 /* temporary definition */
35 static char base64_table[65] = {
36 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
37 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
38 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a',
39 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
40 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
41 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',
42 '2', '3', '4', '5', '6', '7', '8', '9', '+',
46 /* Quoted-Printable */
47 static char *_dec_to_hex(int dec);
48 static int _hex_to_dec(char *hex);
51 static int _find_base(char ch);
56 int encode_qp(char *src, int src_len, char **en_src, int *en_src_len)
60 retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n");
68 _DEBUG_ERROR("[encoding_util] src is NULL\n");
72 /*encoded string length is three times longer than existing maximum string length */
73 int full_lenth = src_len * 3 + 1 + (int)(src_len * 3 / 76) * 3;
74 *en_src = (char *)malloc(sizeof(char) * full_lenth);
75 if (*en_src == NULL) {
76 _DEBUG_ERROR("[encoding_util] malloc fail !!\n");
79 memset(*en_src, 0x00, src_len * 3 + 1);
81 _DEBUG_INFO("[encoding_util] src_len : %d\n", src_len);
82 for (i = 0; i < src_len; i++) {
83 /* _DEBUG_INFO("[encoding_util] i : %d\n", i); */
84 if (size_cnt >= QP_SIZE - 3) {
86 (*en_src)[j++] = 0x3D;
87 (*en_src)[j++] = 0x0D;
88 (*en_src)[j++] = 0x0A;
91 if ((src[i] >= 33 && src[i] <= 126) || (src[i] == 0x0A) || (src[i] == 0x0D)) {
92 if (src[i] == 61 || src[i] == 0x0A || src[i] == 0x0D) {
93 en_hex = _dec_to_hex(src[i]);
94 (*en_src)[j++] = 0x3D; /* '=' */
95 (*en_src)[j++] = en_hex[0];
96 (*en_src)[j++] = en_hex[1];
100 (*en_src)[j++] = src[i];
102 } else if (src[i] == 9 || src[i] == 32) {
103 if (src[i + 1] == 0x0A || src[i + 1] == '\0') { /* TAB or WhiteSpace */
104 en_hex = _dec_to_hex(src[i]);
105 (*en_src)[j++] = 0x3D; /* '=' */
106 (*en_src)[j++] = en_hex[0];
107 (*en_src)[j++] = en_hex[1];
111 (*en_src)[j++] = src[i];
114 en_hex = _dec_to_hex(src[i]);
115 (*en_src)[j++] = 0x3D; /* '=' */
116 (*en_src)[j++] = en_hex[0];
117 (*en_src)[j++] = en_hex[1];
118 _DEBUG_INFO("[encoding_util] en_src : %s\n", *en_src);
124 *en_src_len = size_cnt;
131 int decode_qp(char *src, int src_len, char **de_src, int *de_src_len)
135 retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n");
146 _DEBUG_ERROR("[encoding_util] src is NULL\n");
150 *de_src = (char *)malloc(sizeof(char) * (src_len + 1));
151 if (*de_src == NULL) {
152 _DEBUG_ERROR("[encoding_util] malloc is fail !!\n");
155 memset(*de_src, 0x00, sizeof(char) * (src_len + 1));
157 while (src[i] != '\0') {
158 if (src[i] == 0x3D) { /* '=' */
159 /* check whiteSpace */
162 /* '=' skip if next character is a TAB or WhiteSpace */
163 while (ch == 0x09 || ch == 0x20) {
174 /* '=' skip if next character is 3D which means '=' (encoding error case ??) */
190 /* if next character is LF after '=' do doft line break
191 * encoded QP string on one line 76 character is allowed
193 if (ch == 0x0D) { /* LF */
205 dec = _hex_to_dec(hex);
209 /* when error occur, restore the previous encoding message */
210 (*de_src)[j++] = 0x3D; /* '=' */
211 (*de_src)[j++] = hex[0];
212 (*de_src)[j++] = hex[1];
214 (*de_src)[j++] = dec;
217 } else if (src[i] > 0x7E) { /* encoding error */
218 i++; /* ignore that character */
221 (*de_src)[j++] = src[i++];
226 (*de_src)[j++] = 0x3D;
237 static char *_dec_to_hex(int dec)
245 for (i = 0; i < 2; i++) {
247 ch = (dec & 0xF0) >> 4;
253 hex[i] = 'A' + ch - 10;
261 _DEBUG_TRACE("[encoding_util] hex : %s\n", hex);
268 static int _hex_to_dec(char *hex)
276 for (i = 0; i < 2; i++) {
277 if (hex[i] >= '0' && hex[i] <= '9') {
279 } else if (hex[i] >= 'A' && hex[i] <= 'F') {
280 byte = hex[i] - 'A' + 10;
281 } else if (hex[i] >= 'a' && hex[i] <= 'f') {
282 byte = hex[i] - 'a' + 10;
290 dec += (i == 0) ? byte << 4 : byte;
301 int encode_base64(char *src, int src_len, char **en_src, int *en_src_len)
305 retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n");
314 _DEBUG_ERROR("[encoding_util] src is NULL\n");
318 *en_src = (char *)malloc(sizeof(char) * (src_len * 2));
320 if (*en_src == NULL) {
321 _DEBUG_ERROR("[encoding_util] malloc fail !!\n");
324 memset(*en_src, 0x00, src_len * 2);
331 ch = (src[i] & 0xFC) >> 2;
341 if (i + 1 < src_len) {
342 ch = ((src[i] & 0x03) << 4) | ((src[i + 1] & 0xF0) >> 4);
344 ch = ((src[i] & 0x03) << 4);
356 if (i + 1 < src_len) {
357 ch = ((src[i] & 0x0F) << 2) | ((src[i] & 0xC0) >> 6);
359 ch = ((src[i] & 0x0F) << 2);
371 ch = (src[i] & 0x3F);
382 if (ch >= 0 && ch <= 25) { // Upper Case Alphabet
383 (*en_src)[j++] = 'A' + ch;
384 } else if (ch >= 26 && ch <= 51) { // Lower Case Alphabet
385 (*en_src)[j++] = 'a' + ch - 26;
386 } else if (ch >= 52 && ch <= 61) { // Digit
387 (*en_src)[j++] = '0' + ch - 52;
388 } else if (ch == 62) {
389 (*en_src)[j++] = '+';
390 } else if (ch == 63) {
391 (*en_src)[j++] = '/';
392 } else if (ch == -1) {
393 (*en_src)[j++] = '='; // padding
397 if ((ch != -1) && (ch >= 0 && ch <= 64)) {
398 (*en_src)[j++] = base64_table[ch];
400 (*en_src)[j++] = base64_table[64]; /* padding */
406 if (size_cnt == BASE64_SIZE) {
408 (*en_src)[j++] = 0x0A; /* soft line break */
424 int decode_base64(char *src, int src_len, char **de_src, int *de_src_len)
428 retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n");
430 long tmp = 0; /* 4byte (using decoding) */
437 _DEBUG_ERROR("[encoding_util] src is NULL\n");
441 /* de_src is enough for the src_len 3/4 size */
442 *de_src = (char *)malloc(sizeof(char) * (src_len));
443 if (*de_src == NULL) {
444 _DEBUG_ERROR("malloc error !!");
447 memset(*de_src, 0x00, src_len);
449 if (*de_src == NULL) {
450 _DEBUG_ERROR("[encoding_util] malloc is fail !!\n");
454 while (src[i] != '\0') {
456 if (isupper(src[i])) {
457 tmp = (tmp << 6) | (src[i] - 'A'); // Upper case : 0 ~ 25
458 } else if (islower(src[i])) {
459 tmp = (tmp << 6) | (src[i] - 'a' + 0x1A); // Lower case : 26(0x1A) ~ 51
460 } else if (isdigit(src[i])) {
461 tmp = (tmp << 6) | (src[i] - '0' + 0x34); // Number : 52(0x34) ~ 61
462 } else if (src[i] == '+') {
463 tmp = (tmp << 6) | 0x3E; // '+' : 62(0x3E)
464 } else if (src[i] == '/') {
465 tmp = (tmp << 6) | 0x3F; // '/' : 63(0x3F)
466 } else if (src[i] == '=') {
468 tmp = (tmp << 6); // '=' : padding
470 tmp = (tmp << 6); // encoding error
471 f_DEBUG_INFO(stdout, "encoding error !! \n");
475 tmp = (tmp << 6) | (_find_base(src[i]));
478 } else if (tmp == -1) {
479 _DEBUG_ERROR("[encoding_util] encoding error \n");
483 (*de_src)[j++] = (char)((tmp & 0x00FF0000) >> 16);
484 (*de_src)[j++] = (char)((tmp & 0x0000FF00) >> 8);
485 (*de_src)[j++] = (char)(tmp & 0x000000FF);
490 if (src[i + 1] == 0x0A) { /* soft line break */
498 (*de_src)[j - pad_cnt] = '\0';
499 *de_src_len = j - pad_cnt;
506 int proc_decoding(const char *src, int src_len, char **de_src, int *de_src_len)
510 retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n");
512 const char *reg_src = NULL;
515 _DEBUG_INFO("[encoding_util] << src >> \n%s\n", src);
517 *de_src = (char *)malloc(sizeof(char) * (src_len + 1));
518 if (*de_src == NULL) {
519 _DEBUG_INFO("[encoding_util] malloc error !! \n");
523 memset(*de_src, 0x00, sizeof(char) * (src_len + 1));
526 char line_breaker[] = "\r\n";
527 char *start_decoding = NULL;
533 char *de_temp = (char *)malloc(sizeof(char) * TEMP_BUFFER_SIZE); /* todo : temporary */
534 if (de_temp == NULL) {
535 _DEBUG_ERROR("[encoding_util] malloc error !!\n");
543 while ((start_decoding = strstr(src, "ENCODING="))) {
544 char *charset_loc = strstr(src, "CHARSET=");
545 char *colon_loc = strstr(start_decoding, colon); /* find ':''s location */
546 char *line_breaker_loc = 0;
548 /*edited code for line beaker */
549 char *colon_loc_temp = colon_loc;
550 while (line_breaker_loc == NULL) {
551 line_breaker_loc = strstr(colon_loc_temp, line_breaker); /* find "\r\n"'s location */
552 if (line_breaker_loc > colon_loc_temp && !strncmp(line_breaker_loc - 1, "=", 1)) {
553 colon_loc_temp = line_breaker_loc + 1;
554 line_breaker_loc = 0;
559 * if find "ENCODING=" do strcat data until ":" to de_src
561 if (charset_loc != NULL) {
562 if (start_decoding > charset_loc) { /* CHARSET=UTF-8;ENCODING=abcxx: */
563 data_size = (charset_loc - 1) - src;
564 } else { /* ENCODING=abcxxx;CHARSET=UTF-8: */
565 data_size = (start_decoding - 1) - src;
568 data_size = (start_decoding - 1) - src;
571 char *temp = (char *)malloc(sizeof(char) * (data_size + 1));
573 _DEBUG_ERROR("[encoding_util] malloc error !!");
583 memset(temp, 0x00, sizeof(char) * (data_size + 1));
584 memcpy(temp, src, data_size);
586 len = g_strlcat(*de_src, temp, (src_len + 1));
587 if (len >= (src_len + 1)) {
588 _DEBUG_ERROR("*de_src buffer overflow !!");
602 (*de_src)[strlen(*de_src)] = ':';
606 _DEBUG_INFO("[encoding_util] << *de_src >> \n %s\n", *de_src);
609 * copy data from ":" until "\r\n"(actual encoding stream)
611 data_size = line_breaker_loc - colon_loc; /* from ':' until "\r\n" + '\0' */
612 char *value = (char *)malloc(sizeof(char) * (data_size + 1));
614 _DEBUG_ERROR("[encoding_util] malloc error !!\n");
624 memset(value, 0x00, sizeof(char) * (data_size + 1));
625 memcpy(value, ++colon_loc, data_size); /* from ':' until "\r\n" */
626 value[data_size] = '\0';
627 _DEBUG_INFO("[encoding_util] data len is [%d] and value is [%s]\n\n", data_size, value);
629 * Get encoding type using data from "ENCODING=" to ":"
631 char type_check[TYPE_CHECK_BUF_SIZE] = { 0, };
632 int type_check_size = colon_loc - start_decoding;
633 strncpy(type_check, start_decoding, type_check_size);
634 _DEBUG_INFO("[encoding_util] type check : %s\n", type_check);
635 encoding_type_e type = find_encoding_type((const char *)type_check);
638 * Process decoding by passing the actual value and encoding type to decode_value()
641 memset(de_temp, 0x00, sizeof(char) * TEMP_BUFFER_SIZE); /* todo : temporary */
643 res = decode_value(type, value, data_size, &de_temp, &de_temp_len);
646 _DEBUG_ERROR("[encoding_util] decode_value error !!\n");
661 * Append decoded data to de_src
663 _DEBUG_INFO("[encoding_util] de_temp : %s\n", de_temp);
665 len = g_strlcat(*de_src, de_temp, (src_len + 1));
666 if (len >= (src_len + 1)) {
667 _DEBUG_ERROR("*de_src buffer overflow !!");
682 * find "ENCODING=" since "\r\n" agina
684 src = line_breaker_loc;
691 len = g_strlcat(*de_src, src, (src_len + 1));
692 if (len >= (src_len + 1)) {
693 _DEBUG_ERROR("*de_src buffer overflow !!");
704 *de_src_len = strlen(*de_src);
705 _DEBUG_INFO("[encoding_util] changed src : \n%s ( %d ) \n", *de_src, *de_src_len);
710 _DEBUG_INFO("[encoding_util] End \n");
717 int check_encoding_data(const char *data)
721 if (strstr(data, "ENCODING=") != NULL) {
722 _DEBUG_INFO("[encoding_util] exist encoding data !! \n");
726 _DEBUG_INFO("[encoding_util] not exist encoding data !! \n");
732 encoding_type_e find_encoding_type(const char *data)
736 _DEBUG_INFO("[encoding_util] Start !! \n");
738 encoding_type_e type = EN_TYPE_NONE;
739 if (strstr(data, "QUOTED-PRINTABLE") != NULL) {
740 _DEBUG_INFO("[encoding_util] type : QP\n");
741 type = EN_TYPE_QUOTED_PRINTABLE;
742 } else if (strstr(data, "BASE64") != NULL) {
743 _DEBUG_INFO("[encoding_util] type : BASE64\n");
744 type = EN_TYPE_BASE64;
746 _DEBUG_INFO("[encoding_util] not supported type !! \n");
749 _DEBUG_INFO("[encoding_util] End !! \n");
756 int decode_value(encoding_type_e type, const char *value, int value_size, char **decode_str, int *decode_str_len)
760 retvm_if(value == NULL, 0, "[encoding_util] value is NULL\n");
763 const char *start_pos = NULL;
764 const char *cursor = NULL;
769 * ex> value - =EA=B9=80;=EC=B2=A0=EC=88=98;;;\0
774 while (*cursor != '\0') {
775 if ((*cursor != ';') && (*(cursor + 1) != '\0')) {
778 } else if (*cursor == ';') {
784 data_size = cursor - start_pos;
785 else /* case of [*(cursor+1)=='\0'] */
786 data_size = cursor + 1 - start_pos;
788 if (data_size == 0) {
792 char *temp = (char *)malloc(sizeof(char) * (value_size + 1));
794 _DEBUG_ERROR("[encoding_util] malloc error !!");
797 memset(temp, 0x00, sizeof(char) * (value_size + 1));
798 memcpy(temp, start_pos, data_size);
800 _DEBUG_INFO("[encoding_util] temp : %s \n", temp);
803 int decoding_len = 0;
806 case EN_TYPE_QUOTED_PRINTABLE:
807 res = decode_qp(temp, data_size, &decoding, &decoding_len);
810 res = decode_base64(temp, data_size, &decoding, &decoding_len);
819 _DEBUG_INFO("[encoding_util] decoding : %s ( %d )\n", decoding, decoding_len);
822 _DEBUG_ERROR("[encoding_util] decoding error !! \n");
824 if (decoding != NULL)
831 len = g_strlcat(*decode_str, decoding, TEMP_BUFFER_SIZE);
832 if (len >= TEMP_BUFFER_SIZE) {
833 _DEBUG_ERROR("*decode_str buffer overflow !!");
835 if (decoding != NULL)
842 _DEBUG_INFO("[encoding_util] *decode_str : %s\n", *decode_str);
844 if (decoding != NULL)
852 int len = strlen(*decode_str);
853 (*decode_str)[len] = ';';
854 _DEBUG_INFO("[encoding_util] *decode_str : %s ( %d )\n", *decode_str, strlen(*decode_str));
859 *decode_str_len = strlen(*decode_str);
861 _DEBUG_INFO("[encoding_util] *decode_str : %s ( %d )\n", *decode_str, *decode_str_len);
863 _DEBUG_INFO("[encoding_util] End !! \n");
870 static int _find_base(char ch)
875 for (i = 0; i < 65; i++) {
876 if (base64_table[i] == ch) {
877 _DEBUG_TRACE("[encoding_util] End !! \n");