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 <sync_agent.h>
23 #include "encoding_util.h"
25 #ifndef OMADS_AGENT_LOG
27 #define LOG_TAG "ENCODING_UTIL"
30 #define TYPE_CHECK_BUF_SIZE 100 /* temporary definition */
31 #define TEMP_BUFFER_SIZE 1024 /* temporary definition */
34 static char base64_table[65] = {
35 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
36 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
37 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a',
38 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
39 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
40 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',
41 '2', '3', '4', '5', '6', '7', '8', '9', '+',
45 /* Quoted-Printable */
46 static char *_dec_to_hex(int dec);
47 static int _hex_to_dec(char *hex);
50 static int _find_base(char ch);
55 int encode_qp(char *src, int src_len, char **en_src, int *en_src_len)
59 retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n");
66 /*encoded string length is three times longer than existing maximum string length */
67 int full_lenth = src_len * 3 + 1 + (int)(src_len * 3 / 76) * 3;
68 *en_src = (char *)malloc(sizeof(char) * full_lenth);
69 if (*en_src == NULL) {
70 _DEBUG_ERROR("[encoding_util] malloc fail !!\n");
73 memset(*en_src, 0x00, src_len * 3 + 1);
75 _DEBUG_INFO("[encoding_util] src_len : %d\n", src_len);
76 for (i = 0; i < src_len; i++) {
77 /* _DEBUG_INFO("[encoding_util] i : %d\n", i); */
78 if (size_cnt >= QP_SIZE - 3) {
80 (*en_src)[j++] = 0x0A;
83 if ((src[i] >= 33 && src[i] <= 126) || (src[i] == 0x0A)) {
85 en_hex = _dec_to_hex(src[i]);
86 (*en_src)[j++] = 0x3D; /* '=' */
87 (*en_src)[j++] = en_hex[0];
88 (*en_src)[j++] = en_hex[1];
92 (*en_src)[j++] = src[i];
94 } else if (src[i] == 9 || src[i] == 32) {
95 if (src[i + 1] == 0x0A || src[i + 1] == '\0') { /* TAB or WhiteSpace */
96 en_hex = _dec_to_hex(src[i]);
97 (*en_src)[j++] = 0x3D; /* '=' */
98 (*en_src)[j++] = en_hex[0];
99 (*en_src)[j++] = en_hex[1];
103 (*en_src)[j++] = src[i];
106 en_hex = _dec_to_hex(src[i]);
107 (*en_src)[j++] = 0x3D; /* '=' */
108 (*en_src)[j++] = en_hex[0];
109 (*en_src)[j++] = en_hex[1];
110 _DEBUG_INFO("[encoding_util] en_src : %s\n", *en_src);
116 *en_src_len = size_cnt;
122 int decode_qp(char *src, int src_len, char **de_src, int *de_src_len)
126 retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n");
135 *de_src = (char *)malloc(sizeof(char) * (src_len + 1));
136 if (*de_src == NULL) {
137 _DEBUG_ERROR("[encoding_util] malloc is fail !!\n");
140 memset(*de_src, 0x00, sizeof(char) * (src_len + 1));
142 while (src[i] != '\0') {
143 if (src[i] == 0x3D) { /* '=' */
144 /* check whiteSpace */
147 /* '=' skip if next character is a TAB or WhiteSpace */
148 while (ch == 0x09 || ch == 0x20) {
158 /* '=' skip if next character is 3D which means '=' (encoding error case ??) */
168 /* if next character is LF after '=' do doft line break
169 * encoded QP string on one line 76 character is allowed
171 if (ch == 0x0A) { /* LF */
180 dec = _hex_to_dec(hex);
184 /* when error occur, restore the previous encoding message */
185 (*de_src)[j++] = 0x3D; /* '=' */
186 (*de_src)[j++] = hex[0];
187 (*de_src)[j++] = hex[1];
189 (*de_src)[j++] = dec;
191 } else if (src[i] > 0x7E) { /* encoding error */
192 i++; /* ignore that character */
194 (*de_src)[j++] = src[i++];
205 static char *_dec_to_hex(int dec)
213 for (i = 0; i < 2; i++) {
215 ch = (dec & 0xF0) >> 4;
221 hex[i] = 'A' + ch - 10;
229 _DEBUG_TRACE("[encoding_util] hex : %s\n", hex);
235 static int _hex_to_dec(char *hex)
243 for (i = 0; i < 2; i++) {
244 if (hex[i] >= '0' && hex[i] <= '9') {
246 } else if (hex[i] >= 'A' && hex[i] <= 'F') {
247 byte = hex[i] - 'A' + 10;
248 } else if (hex[i] >= 'a' && hex[i] <= 'f') {
249 byte = hex[i] - 'a' + 10;
257 dec += (i == 0) ? byte << 4 : byte;
267 int encode_base64(char *src, int src_len, char **en_src, int *en_src_len)
271 retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n");
279 *en_src = (char *)malloc(sizeof(char) * (src_len * 2));
281 if (*en_src == NULL) {
282 _DEBUG_ERROR("[encoding_util] malloc fail !!\n");
285 memset(*en_src, 0x00, src_len * 2);
292 ch = (src[i] & 0xFC) >> 2;
302 if (i + 1 < src_len) {
303 ch = ((src[i] & 0x03) << 4) | ((src[i + 1] & 0xF0) >> 4);
305 ch = ((src[i] & 0x03) << 4);
317 if (i + 1 < src_len) {
318 ch = ((src[i] & 0x0F) << 2) | ((src[i] & 0xC0) >> 6);
320 ch = ((src[i] & 0x0F) << 2);
332 ch = (src[i] & 0x3F);
343 if (ch >= 0 && ch <= 25) { // Upper Case Alphabet
344 (*en_src)[j++] = 'A' + ch;
345 } else if (ch >= 26 && ch <= 51) { // Lower Case Alphabet
346 (*en_src)[j++] = 'a' + ch - 26;
347 } else if (ch >= 52 && ch <= 61) { // Digit
348 (*en_src)[j++] = '0' + ch - 52;
349 } else if (ch == 62) {
350 (*en_src)[j++] = '+';
351 } else if (ch == 63) {
352 (*en_src)[j++] = '/';
353 } else if (ch == -1) {
354 (*en_src)[j++] = '='; // padding
359 (*en_src)[j++] = base64_table[ch];
361 (*en_src)[j++] = base64_table[64]; /* padding */
367 if (size_cnt == BASE64_SIZE) {
369 (*en_src)[j++] = 0x0A; /* soft line break */
384 int decode_base64(char *src, int src_len, char **de_src, int *de_src_len)
388 retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n");
390 long tmp = 0; /* 4byte (using decoding) */
396 /* de_src is enough for the src_len 3/4 size */
397 *de_src = (char *)malloc(sizeof(char) * (src_len));
399 if (*de_src == NULL) {
400 _DEBUG_ERROR("[encoding_util] malloc is fail !!\n");
403 memset(*de_src, 0x00, src_len);
405 while (src[i] != '\0') {
407 if (isupper(src[i])) {
408 tmp = (tmp << 6) | (src[i] - 'A'); // Upper case : 0 ~ 25
409 } else if (islower(src[i])) {
410 tmp = (tmp << 6) | (src[i] - 'a' + 0x1A); // Lower case : 26(0x1A) ~ 51
411 } else if (isdigit(src[i])) {
412 tmp = (tmp << 6) | (src[i] - '0' + 0x34); // Number : 52(0x34) ~ 61
413 } else if (src[i] == '+') {
414 tmp = (tmp << 6) | 0x3E; // '+' : 62(0x3E)
415 } else if (src[i] == '/') {
416 tmp = (tmp << 6) | 0x3F; // '/' : 63(0x3F)
417 } else if (src[i] == '=') {
419 tmp = (tmp << 6); // '=' : padding
421 tmp = (tmp << 6); // encoding error
422 _DEBUG_INFO("encoding error !! \n");
426 tmp = (tmp << 6) | (_find_base(src[i]));
429 } else if (tmp == -1) {
430 _DEBUG_ERROR("[encoding_util] encoding error \n");
434 (*de_src)[j++] = (char)((tmp & 0x00FF0000) >> 16);
435 (*de_src)[j++] = (char)((tmp & 0x0000FF00) >> 8);
436 (*de_src)[j++] = (char)(tmp & 0x000000FF);
441 if (src[i + 1] == 0x0A) { /* soft line break */
449 (*de_src)[j - pad_cnt] = '\0';
450 *de_src_len = j - pad_cnt;
456 int proc_decoding(const char *src, int src_len, char **de_src, int *de_src_len)
460 retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n");
462 const char *reg_src = NULL;
465 _DEBUG_INFO("[encoding_util] << src >> \n%s\n", src);
467 *de_src = (char *)malloc(sizeof(char) * (src_len + 1));
468 if (*de_src == NULL) {
469 _DEBUG_INFO("[encoding_util] malloc error !! \n");
473 memset(*de_src, 0x00, sizeof(char) * (src_len + 1));
476 char line_breaker[] = "\r\n";
477 char *start_decoding = NULL;
483 char *de_temp = (char *)malloc(sizeof(char) * TEMP_BUFFER_SIZE); /* todo : temporary */
484 if (de_temp == NULL) {
485 _DEBUG_ERROR("[encoding_util] malloc error !!\n");
493 while ((start_decoding = strstr(src, "ENCODING="))) {
494 char *colon_loc = strstr(start_decoding, colon); /* find ':''s location */
495 char *line_breaker_loc = NULL;
496 if (colon_loc != NULL) {
497 line_breaker_loc = strstr(colon_loc, line_breaker); /* find "\r\n"'s location */
508 * if find "ENCODING=" do strcat data until ":" to de_src
510 data_size = (colon_loc + 1) - src; /* colon_loc + 1 ==> Until next character of ':' */
512 char *temp = (char *)malloc(sizeof(char) * (data_size + 1));
514 _DEBUG_ERROR("temp is null");
524 memset(temp, 0x00, sizeof(char) * (data_size + 1));
525 memcpy(temp, src, data_size);
527 len = g_strlcat(*de_src, temp, (src_len + 1));
528 if (len >= (src_len + 1)) {
529 _DEBUG_ERROR("*de_src buffer overflow !!");
546 _DEBUG_INFO("[encoding_util] << *de_src >> \n %s\n", *de_src);
549 * copy data from ":" until "\r\n"(actual encoding stream)
551 data_size = line_breaker_loc - colon_loc; /* from ':' until "\r\n" + '\0' */
552 char *value = (char *)malloc(sizeof(char) * (data_size + 1));
554 _DEBUG_ERROR("[encoding_util] malloc error !!\n");
564 memset(value, 0x00, sizeof(char) * (data_size + 1));
565 memcpy(value, ++colon_loc, data_size); /* from ':' until "\r\n" */
566 value[data_size] = '\0';
569 * Get encoding type using data from "ENCODING=" to ":"
571 char type_check[TYPE_CHECK_BUF_SIZE] = { 0, };
572 int type_check_size = colon_loc - start_decoding;
573 strncpy(type_check, start_decoding, type_check_size);
574 _DEBUG_INFO("[encoding_util] type check : %s\n", type_check);
575 encoding_type_e type = find_encoding_type((const char *)type_check);
578 * Process decoding by passing the actual value and encoding type to decode_value()
581 memset(de_temp, 0x00, sizeof(char) * TEMP_BUFFER_SIZE); /* todo : temporary */
583 res = decode_value(type, value, data_size, &de_temp, &de_temp_len);
586 _DEBUG_ERROR("[encoding_util] decode_value error !!\n");
601 * Append decoded data to de_src
603 _DEBUG_INFO("[encoding_util] de_temp : %s\n", de_temp);
605 len = g_strlcat(*de_src, de_temp, (src_len + 1));
606 if (len >= (src_len + 1)) {
607 _DEBUG_ERROR("*de_src buffer overflow !!");
622 * find "ENCODING=" since "\r\n" agina
624 src = line_breaker_loc;
630 /* Append remain character */
632 len = g_strlcat(*de_src, src, (src_len + 1));
633 if (len >= (src_len + 1)) {
634 _DEBUG_ERROR("*de_src buffer overflow !!");
645 *de_src_len = strlen(*de_src);
646 _DEBUG_INFO("[encoding_util] changed src : \n%s ( %d ) \n", *de_src, *de_src_len);
655 int check_encoding_data(const char *data)
659 if (strstr(data, "ENCODING=") != NULL) {
660 _DEBUG_INFO("[encoding_util] exist encoding data !! \n");
664 _DEBUG_INFO("[encoding_util] not exist encoding data !! \n");
670 encoding_type_e find_encoding_type(const char *data)
674 encoding_type_e type = EN_TYPE_NONE;
675 if (strstr(data, "QUOTED-PRINTABLE") != NULL) {
676 _DEBUG_INFO("[encoding_util] type : QP\n");
677 type = EN_TYPE_QUOTED_PRINTABLE;
678 } else if (strstr(data, "BASE64") != NULL) {
679 _DEBUG_INFO("[encoding_util] type : BASE64\n");
680 type = EN_TYPE_BASE64;
682 _DEBUG_INFO("[encoding_util] not supported type !! \n");
689 int decode_value(encoding_type_e type, const char *value, int value_size, char **decode_str, int *decode_str_len)
693 retvm_if(value == NULL, 0, "[encoding_util] value is NULL\n");
696 const char *start_pos = NULL;
697 const char *cursor = NULL;
702 * ex> value - =EA=B9=80;=EC=B2=A0=EC=88=98;;;\0
707 while (*cursor != '\0') {
708 if ((*cursor != ';') && (*cursor != '\r')) {
711 } else if (*cursor == ';') {
716 data_size = cursor - start_pos;
718 if (data_size == 0) {
722 char *temp = (char *)malloc(sizeof(char) * (value_size + 1));
724 _DEBUG_ERROR("MALLOC failed !!!");
728 memset(temp, 0x00, sizeof(char) * (value_size + 1));
729 memcpy(temp, start_pos, data_size);
731 _DEBUG_INFO("[encoding_util] temp : %s \n", temp);
733 char *decoding = NULL;
734 int decoding_len = 0;
737 case EN_TYPE_QUOTED_PRINTABLE:
738 res = decode_qp(temp, data_size, &decoding, &decoding_len);
741 res = decode_base64(temp, data_size, &decoding, &decoding_len);
750 _DEBUG_INFO("[encoding_util] decoding : %s ( %d )\n", decoding, decoding_len);
753 _DEBUG_ERROR("[encoding_util] decoding error !! \n");
755 if (decoding != NULL)
762 len = g_strlcat(*decode_str, decoding, TEMP_BUFFER_SIZE);
763 if (len >= TEMP_BUFFER_SIZE) {
764 _DEBUG_ERROR("*decode_str buffer overflow !!");
766 if (decoding != NULL)
773 _DEBUG_INFO("[encoding_util] *decode_str : %s\n", *decode_str);
775 if (decoding != NULL)
783 int len = strlen(*decode_str);
784 (*decode_str)[len] = ';';
785 _DEBUG_INFO("[encoding_util] *decode_str : %s ( %d )\n", *decode_str, strlen(*decode_str));
790 *decode_str_len = strlen(*decode_str);
792 _DEBUG_INFO("[encoding_util] *decode_str : %s ( %d )\n", *decode_str, *decode_str_len);
798 static int _find_base(char ch)
803 for (i = 0; i < 65; i++) {
804 if (base64_table[i] == ch) {
805 _DEBUG_INFO("[encoding_util] End !! \n");