diff options
Diffstat (limited to 'src/plugins/ds-public/xcalllog/src/encoding_util.c')
-rwxr-xr-x | src/plugins/ds-public/xcalllog/src/encoding_util.c | 812 |
1 files changed, 812 insertions, 0 deletions
diff --git a/src/plugins/ds-public/xcalllog/src/encoding_util.c b/src/plugins/ds-public/xcalllog/src/encoding_util.c new file mode 100755 index 0000000..d7823cb --- /dev/null +++ b/src/plugins/ds-public/xcalllog/src/encoding_util.c @@ -0,0 +1,812 @@ +/* + * oma-ds-agent + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <glib.h> +#include <glib/gprintf.h> + +#include <sync_agent.h> + +#include "encoding_util.h" + +#ifndef OMADS_AGENT_LOG +#undef LOG_TAG +#define LOG_TAG "ENCODING_UTIL" +#endif + +#define TYPE_CHECK_BUF_SIZE 100 /* temporary definition */ +#define TEMP_BUFFER_SIZE 1024 /* temporary definition */ + +/* BASE64 TABLE */ +static char base64_table[65] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', + 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', + 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', + '2', '3', '4', '5', '6', '7', '8', '9', '+', + '/', '=' +}; + +/* Quoted-Printable */ +static char *_dec_to_hex(int dec); +static int _hex_to_dec(char *hex); + +/* Base64 */ +static int _find_base(char ch); + +/* + * Quoted-Printable + */ +int encode_qp(char *src, int src_len, char **en_src, int *en_src_len) +{ + _EXTERN_FUNC_ENTER; + + retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n"); + + char *en_hex; + int i = 0; + int j = 0; + int size_cnt = 0; + + /*encoded string length is three times longer than existing maximum string length */ + int full_lenth = src_len * 3 + 1 + (int)(src_len * 3 / 76) * 3; + *en_src = (char *)malloc(sizeof(char) * full_lenth); + if (*en_src == NULL) { + _DEBUG_ERROR("[encoding_util] malloc fail !!\n"); + return 0; + } + memset(*en_src, 0x00, src_len * 3 + 1); + + _DEBUG_INFO("[encoding_util] src_len : %d\n", src_len); + for (i = 0; i < src_len; i++) { + /* _DEBUG_INFO("[encoding_util] i : %d\n", i); */ + if (size_cnt >= QP_SIZE - 3) { + size_cnt = 0; + (*en_src)[j++] = 0x0A; + } + + if ((src[i] >= 33 && src[i] <= 126) || (src[i] == 0x0A)) { + if (src[i] == 61) { + en_hex = _dec_to_hex(src[i]); + (*en_src)[j++] = 0x3D; /* '=' */ + (*en_src)[j++] = en_hex[0]; + (*en_src)[j++] = en_hex[1]; + size_cnt += 3; + } else { + size_cnt++; + (*en_src)[j++] = src[i]; + } + } else if (src[i] == 9 || src[i] == 32) { + if (src[i + 1] == 0x0A || src[i + 1] == '\0') { /* TAB or WhiteSpace */ + en_hex = _dec_to_hex(src[i]); + (*en_src)[j++] = 0x3D; /* '=' */ + (*en_src)[j++] = en_hex[0]; + (*en_src)[j++] = en_hex[1]; + size_cnt += 3; + } else { + size_cnt++; + (*en_src)[j++] = src[i]; + } + } else { + en_hex = _dec_to_hex(src[i]); + (*en_src)[j++] = 0x3D; /* '=' */ + (*en_src)[j++] = en_hex[0]; + (*en_src)[j++] = en_hex[1]; + _DEBUG_INFO("[encoding_util] en_src : %s\n", *en_src); + size_cnt += 3; + } + } + + (*en_src)[j] = 0x00; + *en_src_len = size_cnt; + + _EXTERN_FUNC_EXIT; + return 1; +} + +int decode_qp(char *src, int src_len, char **de_src, int *de_src_len) +{ + _EXTERN_FUNC_ENTER; + + retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n"); + + char hex[3]; + char ch; + int dec = 0; + int is_space = 0; + int i = 0; + int j = 0; + + *de_src = (char *)malloc(sizeof(char) * (src_len + 1)); + if (*de_src == NULL) { + _DEBUG_ERROR("[encoding_util] malloc is fail !!\n"); + return 0; + } + memset(*de_src, 0x00, sizeof(char) * (src_len + 1)); + + while (src[i] != '\0') { + if (src[i] == 0x3D) { /* '=' */ + /* check whiteSpace */ + ch = src[++i]; + + /* '=' skip if next character is a TAB or WhiteSpace */ + while (ch == 0x09 || ch == 0x20) { + is_space = 1; + ch = src[++i]; + + if (is_space == 1) { + is_space = 0; + continue; + } + } + + /* '=' skip if next character is 3D which means '=' (encoding error case ??) */ + while (ch == '3') { + ch = src[++i]; + + if (ch == 'D') { + ch = src[++i]; + continue; + } + } + + /* if next character is LF after '=' do doft line break + * encoded QP string on one line 76 character is allowed + */ + if (ch == 0x0A) { /* LF */ + i++; + continue; + } + + hex[0] = src[i++]; + hex[1] = src[i++]; + hex[2] = '\0'; + + dec = _hex_to_dec(hex); + + /* decoding error */ + if (dec < 0) { + /* when error occur, restore the previous encoding message */ + (*de_src)[j++] = 0x3D; /* '=' */ + (*de_src)[j++] = hex[0]; + (*de_src)[j++] = hex[1]; + } else { + (*de_src)[j++] = dec; + } + } else if (src[i] > 0x7E) { /* encoding error */ + i++; /* ignore that character */ + } else { + (*de_src)[j++] = src[i++]; + } + } + + (*de_src)[j] = '\0'; + *de_src_len = j; + + _EXTERN_FUNC_EXIT; + return 1; +} + +static char *_dec_to_hex(int dec) +{ + _INNER_FUNC_ENTER; + + static char hex[3]; + int i; + int ch; + + for (i = 0; i < 2; i++) { + if (i == 0) { + ch = (dec & 0xF0) >> 4; + } else if (i == 1) { + ch = (dec & 0x0F); + } + + if (ch >= 10) { + hex[i] = 'A' + ch - 10; + } else { + hex[i] = '0' + ch; + } + } + + hex[i] = 0x00; + + _DEBUG_TRACE("[encoding_util] hex : %s\n", hex); + + _INNER_FUNC_EXIT; + return &hex[0]; +} + +static int _hex_to_dec(char *hex) +{ + _INNER_FUNC_ENTER; + + int dec = 0; + int byte; + int i = 0; + + for (i = 0; i < 2; i++) { + if (hex[i] >= '0' && hex[i] <= '9') { + byte = hex[i] - '0'; + } else if (hex[i] >= 'A' && hex[i] <= 'F') { + byte = hex[i] - 'A' + 10; + } else if (hex[i] >= 'a' && hex[i] <= 'f') { + byte = hex[i] - 'a' + 10; + } else { + byte = -1; + } + + if (byte < 0) + return -1; + + dec += (i == 0) ? byte << 4 : byte; + } + + _INNER_FUNC_EXIT; + return dec; +} + +/* + * Base64 + */ +int encode_base64(char *src, int src_len, char **en_src, int *en_src_len) +{ + _EXTERN_FUNC_ENTER; + + retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n"); + + int i = 0; + int j = 0; + int cnt = 0; + int ch = 0; + int size_cnt = 0; + + *en_src = (char *)malloc(sizeof(char) * (src_len * 2)); + + if (*en_src == NULL) { + _DEBUG_ERROR("[encoding_util] malloc fail !!\n"); + return 0; + } + memset(*en_src, 0x00, src_len * 2); + + while (1) { + switch (cnt++) { + case 0: + { + if (i < src_len) { + ch = (src[i] & 0xFC) >> 2; + } else { + ch = -1; + } + } + break; + + case 1: + { + if (i < src_len) { + if (i + 1 < src_len) { + ch = ((src[i] & 0x03) << 4) | ((src[i + 1] & 0xF0) >> 4); + } else { + ch = ((src[i] & 0x03) << 4); + } + } else { + ch = -1; + } + i++; + break; + } + + case 2: + { + if (i < src_len) { + if (i + 1 < src_len) { + ch = ((src[i] & 0x0F) << 2) | ((src[i] & 0xC0) >> 6); + } else { + ch = ((src[i] & 0x0F) << 2); + } + } else { + ch = -1; + } + i++; + } + break; + + case 3: + { + if (i < src_len) { + ch = (src[i] & 0x3F); + } else { + ch = -1; + } + i++; + cnt = 0; + } + break; + } + + /* + if (ch >= 0 && ch <= 25) { // Upper Case Alphabet + (*en_src)[j++] = 'A' + ch; + } else if (ch >= 26 && ch <= 51) { // Lower Case Alphabet + (*en_src)[j++] = 'a' + ch - 26; + } else if (ch >= 52 && ch <= 61) { // Digit + (*en_src)[j++] = '0' + ch - 52; + } else if (ch == 62) { + (*en_src)[j++] = '+'; + } else if (ch == 63) { + (*en_src)[j++] = '/'; + } else if (ch == -1) { + (*en_src)[j++] = '='; // padding + } + */ + + if (ch != -1) { + (*en_src)[j++] = base64_table[ch]; + } else { + (*en_src)[j++] = base64_table[64]; /* padding */ + } + + size_cnt++; + + if (j % 4 == 0) { + if (size_cnt == BASE64_SIZE) { + size_cnt = 0; + (*en_src)[j++] = 0x0A; /* soft line break */ + } + + if (i >= src_len) + break; + } + } + + (*en_src)[j] = 0x00; + *en_src_len = j; + + _EXTERN_FUNC_EXIT; + return 1; +} + +int decode_base64(char *src, int src_len, char **de_src, int *de_src_len) +{ + _EXTERN_FUNC_ENTER; + + retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n"); + + long tmp = 0; /* 4byte (using decoding) */ + int i = 0; + int j = 0; + int cnt = 0; + int pad_cnt = 0; + + /* de_src is enough for the src_len 3/4 size */ + *de_src = (char *)malloc(sizeof(char) * (src_len)); + + if (*de_src == NULL) { + _DEBUG_ERROR("[encoding_util] malloc is fail !!\n"); + return 0; + } + memset(*de_src, 0x00, src_len); + + while (src[i] != '\0') { + /* + if (isupper(src[i])) { + tmp = (tmp << 6) | (src[i] - 'A'); // Upper case : 0 ~ 25 + } else if (islower(src[i])) { + tmp = (tmp << 6) | (src[i] - 'a' + 0x1A); // Lower case : 26(0x1A) ~ 51 + } else if (isdigit(src[i])) { + tmp = (tmp << 6) | (src[i] - '0' + 0x34); // Number : 52(0x34) ~ 61 + } else if (src[i] == '+') { + tmp = (tmp << 6) | 0x3E; // '+' : 62(0x3E) + } else if (src[i] == '/') { + tmp = (tmp << 6) | 0x3F; // '/' : 63(0x3F) + } else if (src[i] == '=') { + pad_cnt++; + tmp = (tmp << 6); // '=' : padding + } else { + tmp = (tmp << 6); // encoding error + _DEBUG_INFO("encoding error !! \n"); + } + */ + + tmp = (tmp << 6) | (_find_base(src[i])); + if (tmp == 64) { + pad_cnt++; + } else if (tmp == -1) { + _DEBUG_ERROR("[encoding_util] encoding error \n"); + } + + if (++cnt >= 4) { + (*de_src)[j++] = (char)((tmp & 0x00FF0000) >> 16); + (*de_src)[j++] = (char)((tmp & 0x0000FF00) >> 8); + (*de_src)[j++] = (char)(tmp & 0x000000FF); + + cnt = 0; + tmp = 0; + + if (src[i + 1] == 0x0A) { /* soft line break */ + i++; + } + } + + i++; + } + + (*de_src)[j - pad_cnt] = '\0'; + *de_src_len = j - pad_cnt; + + _EXTERN_FUNC_EXIT; + return 1; +} + +int proc_decoding(const char *src, int src_len, char **de_src, int *de_src_len) +{ + _EXTERN_FUNC_ENTER; + + retvm_if(src == NULL, 0, "[encoding_util] src is NULL\n"); + + const char *reg_src = NULL; + reg_src = src; + + _DEBUG_INFO("[encoding_util] << src >> \n%s\n", src); + + *de_src = (char *)malloc(sizeof(char) * (src_len + 1)); + if (*de_src == NULL) { + _DEBUG_INFO("[encoding_util] malloc error !! \n"); + + return 0; + } + memset(*de_src, 0x00, sizeof(char) * (src_len + 1)); + + char colon[] = ":"; + char line_breaker[] = "\r\n"; + char *start_decoding = NULL; + int data_size = 0; + int res = 0; + int de_temp_len = 0; + int len = 0; + + char *de_temp = (char *)malloc(sizeof(char) * TEMP_BUFFER_SIZE); /* todo : temporary */ + if (de_temp == NULL) { + _DEBUG_ERROR("[encoding_util] malloc error !!\n"); + + if (*de_src != NULL) + free(*de_src); + + return 0; + } + + while ((start_decoding = strstr(src, "ENCODING="))) { + char *colon_loc = strstr(start_decoding, colon); /* find ':''s location */ + char *line_breaker_loc = NULL; + if (colon_loc != NULL) { + line_breaker_loc = strstr(colon_loc, line_breaker); /* find "\r\n"'s location */ + } else { + if (*de_src != NULL) + free(*de_src); + + if (de_temp != NULL) + free(de_temp); + return 0; + } + + /* + * if find "ENCODING=" do strcat data until ":" to de_src + */ + data_size = (colon_loc + 1) - src; /* colon_loc + 1 ==> Until next character of ':' */ + + char *temp = (char *)malloc(sizeof(char) * (data_size + 1)); + if (temp == NULL) { + _DEBUG_ERROR("temp is null"); + if (*de_src != NULL) + free(*de_src); + + /* for prevent */ + if (de_temp != NULL) + free(de_temp); + + return 0; + } + memset(temp, 0x00, sizeof(char) * (data_size + 1)); + memcpy(temp, src, data_size); + + len = g_strlcat(*de_src, temp, (src_len + 1)); + if (len >= (src_len + 1)) { + _DEBUG_ERROR("*de_src buffer overflow !!"); + + if (*de_src != NULL) + free(*de_src); + + if (de_temp != NULL) + free(de_temp); + + if (temp != NULL) + free(temp); + + return 0; + } + + if (temp != NULL) + free(temp); + + _DEBUG_INFO("[encoding_util] << *de_src >> \n %s\n", *de_src); + + /* + * copy data from ":" until "\r\n"(actual encoding stream) + */ + data_size = line_breaker_loc - colon_loc; /* from ':' until "\r\n" + '\0' */ + char *value = (char *)malloc(sizeof(char) * (data_size + 1)); + if (value == NULL) { + _DEBUG_ERROR("[encoding_util] malloc error !!\n"); + + if (*de_src != NULL) + free(*de_src); + + if (de_temp != NULL) + free(de_temp); + + return 0; + } + memset(value, 0x00, sizeof(char) * (data_size + 1)); + memcpy(value, ++colon_loc, data_size); /* from ':' until "\r\n" */ + value[data_size] = '\0'; + + /* + * Get encoding type using data from "ENCODING=" to ":" + */ + char type_check[TYPE_CHECK_BUF_SIZE] = { 0, }; + int type_check_size = colon_loc - start_decoding; + strncpy(type_check, start_decoding, type_check_size); + _DEBUG_INFO("[encoding_util] type check : %s\n", type_check); + encoding_type_e type = find_encoding_type((const char *)type_check); + + /* + * Process decoding by passing the actual value and encoding type to decode_value() + */ + de_temp_len = 0; + memset(de_temp, 0x00, sizeof(char) * TEMP_BUFFER_SIZE); /* todo : temporary */ + + res = decode_value(type, value, data_size, &de_temp, &de_temp_len); + + if (res != 1) { + _DEBUG_ERROR("[encoding_util] decode_value error !!\n"); + + if (*de_src != NULL) + free(*de_src); + + if (de_temp != NULL) + free(de_temp); + + if (value != NULL) + free(value); + + return 0; + } + + /* + * Append decoded data to de_src + */ + _DEBUG_INFO("[encoding_util] de_temp : %s\n", de_temp); + len = 0; + len = g_strlcat(*de_src, de_temp, (src_len + 1)); + if (len >= (src_len + 1)) { + _DEBUG_ERROR("*de_src buffer overflow !!"); + + if (*de_src != NULL) + free(*de_src); + + if (de_temp != NULL) + free(de_temp); + + if (value != NULL) + free(value); + + return 0; + } + + /* + * find "ENCODING=" since "\r\n" agina + */ + src = line_breaker_loc; + + if (value != NULL) + free(value); + } + + /* Append remain character */ + len = 0; + len = g_strlcat(*de_src, src, (src_len + 1)); + if (len >= (src_len + 1)) { + _DEBUG_ERROR("*de_src buffer overflow !!"); + + if (*de_src != NULL) + free(*de_src); + + if (de_temp != NULL) + free(de_temp); + + return 0; + } + + *de_src_len = strlen(*de_src); + _DEBUG_INFO("[encoding_util] changed src : \n%s ( %d ) \n", *de_src, *de_src_len); + + if (de_temp != NULL) + free(de_temp); + + _EXTERN_FUNC_EXIT; + return 1; +} + +int check_encoding_data(const char *data) +{ + _EXTERN_FUNC_ENTER; + + if (strstr(data, "ENCODING=") != NULL) { + _DEBUG_INFO("[encoding_util] exist encoding data !! \n"); + _EXTERN_FUNC_EXIT; + return 1; + } else { + _DEBUG_INFO("[encoding_util] not exist encoding data !! \n"); + _EXTERN_FUNC_EXIT; + return 0; + } +} + +encoding_type_e find_encoding_type(const char *data) +{ + _EXTERN_FUNC_ENTER; + + encoding_type_e type = EN_TYPE_NONE; + if (strstr(data, "QUOTED-PRINTABLE") != NULL) { + _DEBUG_INFO("[encoding_util] type : QP\n"); + type = EN_TYPE_QUOTED_PRINTABLE; + } else if (strstr(data, "BASE64") != NULL) { + _DEBUG_INFO("[encoding_util] type : BASE64\n"); + type = EN_TYPE_BASE64; + } else { + _DEBUG_INFO("[encoding_util] not supported type !! \n"); + } + + _EXTERN_FUNC_EXIT; + return type; +} + +int decode_value(encoding_type_e type, const char *value, int value_size, char **decode_str, int *decode_str_len) +{ + _EXTERN_FUNC_ENTER; + + retvm_if(value == NULL, 0, "[encoding_util] value is NULL\n"); + + int res = 1; + const char *start_pos = NULL; + const char *cursor = NULL; + int semi_cnt = 0; + int len = 0; + + /* + * ex> value - =EA=B9=80;=EC=B2=A0=EC=88=98;;;\0 + */ + cursor = value; + start_pos = value; + + while (*cursor != '\0') { + if ((*cursor != ';') && (*cursor != '\r')) { + cursor++; + continue; + } else if (*cursor == ';') { + semi_cnt++; + } + + int data_size = 0; + data_size = cursor - start_pos; + + if (data_size == 0) { + cursor++; + start_pos++; + } else { + char *temp = (char *)malloc(sizeof(char) * (value_size + 1)); + if (temp == NULL) { + _DEBUG_ERROR("MALLOC failed !!!"); + res = 0; + return res; + } + memset(temp, 0x00, sizeof(char) * (value_size + 1)); + memcpy(temp, start_pos, data_size); + + _DEBUG_INFO("[encoding_util] temp : %s \n", temp); + + char *decoding = NULL; + int decoding_len = 0; + + switch (type) { + case EN_TYPE_QUOTED_PRINTABLE: + res = decode_qp(temp, data_size, &decoding, &decoding_len); + break; + case EN_TYPE_BASE64: + res = decode_base64(temp, data_size, &decoding, &decoding_len); + break; + default: + break; + } + + if (temp != NULL) + free(temp); + + _DEBUG_INFO("[encoding_util] decoding : %s ( %d )\n", decoding, decoding_len); + + if (res != 1) { + _DEBUG_ERROR("[encoding_util] decoding error !! \n"); + + if (decoding != NULL) + free(decoding); + + res = 0; + return res; + } + + len = g_strlcat(*decode_str, decoding, TEMP_BUFFER_SIZE); + if (len >= TEMP_BUFFER_SIZE) { + _DEBUG_ERROR("*decode_str buffer overflow !!"); + + if (decoding != NULL) + free(decoding); + + res = 0; + return res; + } + + _DEBUG_INFO("[encoding_util] *decode_str : %s\n", *decode_str); + + if (decoding != NULL) + free(decoding); + + cursor++; + start_pos = cursor; + } + + if (semi_cnt > 0) { + int len = strlen(*decode_str); + (*decode_str)[len] = ';'; + _DEBUG_INFO("[encoding_util] *decode_str : %s ( %d )\n", *decode_str, strlen(*decode_str)); + semi_cnt--; + } + } + + *decode_str_len = strlen(*decode_str); + + _DEBUG_INFO("[encoding_util] *decode_str : %s ( %d )\n", *decode_str, *decode_str_len); + + _EXTERN_FUNC_EXIT; + return res; +} + +static int _find_base(char ch) +{ + _EXTERN_FUNC_ENTER; + + int i = 0; + for (i = 0; i < 65; i++) { + if (base64_table[i] == ch) { + _DEBUG_INFO("[encoding_util] End !! \n"); + return i; + } + } + + _EXTERN_FUNC_EXIT; + return -1; +} |