4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Ja-young Gu <jygu@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
30 #include "sat_manager.h"
33 #define tabGsmUniMax2 9
34 #define tabGsmUniMax 42
36 static gboolean _find_gsm_code_exception_table(unsigned short src);
37 static int _get_gsm_code_size(unsigned short* src, int src_len);
38 static gboolean _convert_gsm_to_unicode(unsigned short *dest, int dest_len, unsigned char *src, unsigned int src_len);
39 static int _convert_gsm_to_ucs2(unsigned short* dest, unsigned char* src, unsigned int src_len);
40 static void _convert_gsm_to_utf8(unsigned char *dest, unsigned short *dest_len, unsigned char *src, unsigned int src_len);
41 static gboolean _convert_unicode_to_gsm(unsigned char* dest, int dest_len, unsigned short* src, int src_len);
42 static char* _convert_ucs_to_utf8(unsigned char *src, int src_len);
43 static int _convert_ucs2_to_gsm(unsigned char* dest, unsigned short* src, unsigned int src_len);
44 static int _convert_ucs2_to_utf8(char *out, unsigned short *out_len, char *in, unsigned short in_len);
45 static void _convert_alpha_field_ucs2_to_utf8(unsigned char *out, unsigned short *out_len, unsigned char *in, unsigned short in_len);
46 static int _convert_utf8_to_unicode(unsigned short* dest, unsigned char* src, unsigned int src_len);
50 unsigned short unicode;
53 const GsmUniTable gsm_unicode2_table[] = {
54 { 0x14, 0x005E }, { 0x28, 0x007B }, { 0x29, 0x007D }, { 0x2F, 0x005C },
55 { 0x3C, 0x005B }, { 0x3D, 0x007E }, { 0x3E, 0x005D }, { 0x40, 0x007C },
58 const GsmUniTable gsm_unicode_table[] = {
59 { 0x00, 0x0040 }, { 0x01, 0x00A3 }, { 0x02, 0x0024 }, { 0x03, 0x00A5 },
60 { 0x04, 0x00E8 }, { 0x05, 0x00E9 }, { 0x06, 0x00F9 }, { 0x07, 0x00EC }, { 0x08, 0x00F2 },
61 { 0x09, 0x00E7 }, { 0x0B, 0x00D8 }, { 0x0C, 0x00F8 }, { 0x0E, 0x00C5 }, { 0x0F, 0x00E5 },
62 { 0x10, 0x0394 }, { 0x11, 0x005F }, { 0x12, 0x03A6 }, { 0x13, 0x0393 }, { 0x14, 0x039B },
63 { 0x15, 0x03A9 }, { 0x16, 0x03A0 }, { 0x17, 0x03A8 }, { 0x18, 0x03A3 }, { 0x19, 0x0398 },
64 { 0x1A, 0x039E }, { 0x1C, 0x00C6 }, { 0x1D, 0x00E6 }, { 0x1E, 0x00DF }, { 0x1F, 0x00C9 },
65 { 0x24, 0x00A4 }, { 0x40, 0x00A1 }, { 0x5B, 0x00C4 }, { 0x5C, 0x00D6 }, { 0x5D, 0x00D1 },
66 { 0x5E, 0x00DC }, { 0x5F, 0x00A7 }, { 0x60, 0x00BF }, { 0x7B, 0x00E4 }, { 0x7C, 0x00F6 },
67 { 0x7D, 0x00F1 }, { 0x7E, 0x00FC }, { 0x7F, 0x00E0 }, };
71 static gboolean _find_gsm_code_exception_table(unsigned short src)
73 if ((src >= 0x0020 && src <= 0x0023)
74 || (src >= 0x0025 && src <= 0x003F)
75 || (src >= 0x0041 && src <= 0x005A)
76 || (src >= 0x0061 && src <= 0x007A)
77 || src == 0x000A || src == 0x000D)
82 static int _get_gsm_code_size(unsigned short* src, int src_len)
84 gboolean in_table = FALSE;
85 gboolean in_sec_table = FALSE;
89 dbg( "INPUT PARAM was NULL");
93 for (; src_len > 0 && src; src_len--) {
94 if (_find_gsm_code_exception_table(*src) == TRUE) {
100 for (i = 0; i < tabGsmUniMax; i++) {
101 if (*src == gsm_unicode_table[i].unicode) {
108 if (in_table == FALSE) {
109 in_sec_table = FALSE;
110 for (i = 0; i < tabGsmUniMax2; i++) {/* second table */
111 if (*src == gsm_unicode2_table[i].unicode) {
119 if (in_sec_table == FALSE) {/* second*/
120 if (_find_gsm_code_exception_table(*src) == FALSE) {
121 dbg( "GSM Char[%d], gsm_len[%d]", *src, gsm_len);
132 static gboolean _convert_gsm_to_unicode(unsigned short *dest, int dest_len, unsigned char *src, unsigned int src_len)
137 dbg( "[SAT] dest(%p) or src(%p) is null",dest, src);
146 dbg("[SAT] source string (%s) len(%d)", src, src_len);
148 for(index = 0; index < (int)src_len; index++){
149 if(src[index] == 0x1B)
152 dbg("[SAT] strlen excluding escape character (%d)", src_len);
154 tmp_len = _convert_gsm_to_ucs2(dest, src, src_len);
155 dest[tmp_len] = '\0';
160 static int _convert_gsm_to_ucs2(unsigned short* dest, unsigned char* src, unsigned int src_len)
167 for(index=0; index < (int)src_len; index++){
169 gboolean b_tabled = FALSE;
172 * if the first byte is 0x1B, it is the escape character.
173 * The byte value shoulbe be changed to unicode.
176 src++; index++;//move to next byte
177 for(table_index=0; table_index < tabGsmUniMax2; table_index++){
178 if(*src == gsm_unicode2_table[table_index].gsm){
179 *dest = gsm_unicode2_table[table_index].unicode;
185 //if matched data is not in table, it should be changed to NULL;
191 for(table_index=0; table_index < tabGsmUniMax; table_index++){
192 if(*src == gsm_unicode_table[table_index].gsm){
193 *dest = gsm_unicode_table[table_index].unicode;
199 //if matched data is not in table, it is using original value;
205 //move to next position
209 dbg("[SAT] cvt sr(%s), the size of data (%d) ", org, dest - org);
213 static void _convert_gsm_to_utf8(unsigned char* dest, unsigned short* dest_len, unsigned char* src, unsigned int src_len)
216 char *target_tmp = NULL;
217 unsigned char *raw_unicode = NULL;
218 unsigned short tmp_dest[SAT_TEXT_STRING_LEN_MAX];
220 memset(tmp_dest, 0 , SAT_TEXT_STRING_LEN_MAX);
222 _convert_gsm_to_unicode(tmp_dest, SAT_TEXT_STRING_LEN_MAX, src, src_len);
223 while(tmp_dest[tmp_len] != '\0')
225 tmp_len++; // add null character
227 tmp_len = tmp_len*2; //for byte align
228 raw_unicode = (unsigned char*)malloc(tmp_len);
229 memset(raw_unicode, 0, tmp_len);
231 memcpy(raw_unicode, (unsigned char*)tmp_dest, tmp_len);
234 target_tmp = _convert_ucs_to_utf8(raw_unicode, tmp_len);
241 memcpy(dest, target_tmp, strlen((const char*)target_tmp));
242 dbg("final utf8 str (%s), length (%d)", dest, tmp_len);
249 static gboolean _convert_unicode_to_gsm(unsigned char* dest, int dest_len, unsigned short* src, int src_len)
254 if ((NULL == dest) || (NULL == src)) {
255 dbg( "INPUT PARAM was NULL");
262 gc_len = _get_gsm_code_size(src, src_len);
264 dbg( "Warning: Error[%d] while finding the GSM Code Size", gc_len);
268 if (dest_len < gc_len) {
269 if (dest_len == sizeof(void*)) {
270 dbg( "Out buffer size seems to be small (%s)", dest);
272 dbg("Buffer size is too small (%s): dest_len(%d), gc_len(%d)", dest, dest_len, gc_len);
277 tmp_str = calloc(1, (unsigned short) gc_len);
278 if (tmp_str == NULL) {
279 dbg( "Memory Allocation Failed!");
283 gc_len = _convert_ucs2_to_gsm((unsigned char*) tmp_str, src, src_len);
285 memcpy((char*) dest, (char*) tmp_str, gc_len);
294 static char* _convert_ucs_to_utf8(unsigned char* src, int src_len)
296 char* utf_str = NULL;
304 char* out_buf = NULL;
311 ileft = src_len * 2;//over allocate as utf-8 may occupy 3 bytes
312 oleft = src_len * 3;//over allocate as utf-8 may occupy 3 bytes
313 pIn = in_buf = (char*) malloc(ileft + 2);
314 utf_str = out_buf = (char *) malloc(oleft + 1);
316 memset(in_buf, 0x00, ileft + 2);
317 memset(out_buf, 0x00, oleft + 1);
318 memcpy(in_buf, src, ileft);
320 in_buf[ileft] = '\0';
322 cd = iconv_open("UTF-8", "UCS-2");
323 err = iconv(cd, (char**) &in_buf, &ileft, &out_buf, &oleft);
325 utf_str[src_len * 2 - ileft] = '\0';
331 static int _convert_ucs2_to_gsm(unsigned char* dest, unsigned short* src, unsigned int src_len)
333 unsigned char* rear = NULL;
336 gboolean in_table = FALSE;
337 gboolean in_sec_table = FALSE;
340 if ((!dest) || (!src) || (0x00 == src_len)) {
341 dbg( "Warning: Wrong Input");
348 for (; src_len > 0 && p; src_len--) {
350 for (i = 0; i < tabGsmUniMax; i++) { /* is in table */
351 if (*p == gsm_unicode_table[i].unicode) {
352 temp = (unsigned char) (gsm_unicode_table[i].gsm);
361 if (in_table == FALSE) {
362 in_sec_table = FALSE;
363 for (i = 0; i < tabGsmUniMax2; i++) { /* second table*/
364 if (*p == gsm_unicode2_table[i].unicode) {
367 temp = (unsigned char) (gsm_unicode2_table[i].gsm);
377 if (in_sec_table == FALSE) { /* second */
378 if (_find_gsm_code_exception_table(*p) == FALSE)
380 temp = (unsigned char) (*p); /* isn't in table */
392 static int _convert_ucs2_to_utf8(char *out, unsigned short *out_len, char *in, unsigned short in_len)
395 size_t src_len = in_len;
396 size_t dest_len = in_len*3;
398 iconv_t cd = iconv_open("UTF-8", "UCS2");
399 if (cd == (iconv_t) (-1)) {
400 perror("iconv_open");
406 dbg("expected input bytes:%d dest_len:%d\n", src_len, dest_len);
408 if (iconv(cd, &in, &src_len, &p_o, &dest_len) == (size_t)(-1)) {
409 dbg("failed to iconv errno:%d", errno);
411 dbg("remained input bytes:%d processed bytes:%d", src_len, in_len*3-dest_len);
412 out[in_len*3-dest_len] = '\0';
414 *out_len = in_len*3-dest_len;
415 dbg("out_len[%d], output[%s]", *out_len, out);
420 static void _convert_alpha_field_ucs2_to_utf8(unsigned char *out, unsigned short *out_len, unsigned char *in, unsigned short in_len)
423 dbg("[UCS2] prefix case:[0x%02x]", in[0]);
427 unsigned char num = in_len/2; //number of characters
429 int data_loc = 1; //starting location of data
430 unsigned short* in_buf = NULL;
432 in_buf = (unsigned short*)malloc(num * sizeof(unsigned short));
434 for(i=0; i<num; i++,data_loc++) {
435 in_buf[i] = ((unsigned short)in[data_loc]<<8) + (unsigned short)in[data_loc+1];
437 dbg("[UCS2]in_buf[%d]=0x%04x", i, in_buf[i]);
439 _convert_ucs2_to_utf8((char*)out, out_len, (char*) in_buf, num*2);
440 if(in_buf!=NULL) free(in_buf);
444 unsigned char num = in[1]; //number of characters
445 unsigned short base = (unsigned short) in[2] << 7; //base pointer for UCS2 type
447 int data_loc = 3; //starting location of data
448 unsigned short* in_buf = NULL;
450 in_buf = (unsigned short*)malloc(num * sizeof(unsigned short));
452 for(i=0; i<num; i++,data_loc++) {
453 if(in[data_loc]<0x80) { // if the MSB is zero (0x80 => 1000b), then remaining 7 bits are GSM default character.
454 _convert_gsm_to_ucs2(&in_buf[i], (unsigned char *)&in[data_loc], 1);
455 dbg("[UCS2]in_buf[%d]=0x%04x", i, in_buf[i]);
456 } else { // if the MSB is 1 then the remaining 7 bits are offset value added to Base Pointer which the result defines the UCS2 character.
457 in_buf[i] = base + ((unsigned short)(in[data_loc]) & 0x7F);
458 dbg("[UCS2]in_buf[%d]=0x%04x", i, in_buf[i]);
461 _convert_ucs2_to_utf8((char*)out, out_len, (char*) in_buf, num*2);
462 if(in_buf!=NULL) free(in_buf);
467 unsigned char num = in[1]; //number of characters
468 unsigned short base = ((unsigned short) in[2] << 8) | (unsigned short) in[3]; //base pointer for UCS2 type
470 int data_loc = 4; //starting location of data
471 unsigned short* in_buf = NULL;
473 in_buf = (unsigned short*)malloc(num * sizeof(unsigned short));
475 for(i=0; i<num; i++,data_loc++) {
476 if(in[data_loc]<0x80) {
477 _convert_gsm_to_ucs2(&in_buf[i], (unsigned char *)&in[data_loc], (unsigned int)1);
478 dbg("[UCS2]in_buf[%d]=0x%04x", i, in_buf[i]);
480 in_buf[i] = base + ((unsigned short)(in[data_loc]) & 0x7F);
481 dbg("[UCS2]in_buf[%d]=0x%04x", i, in_buf[i]);
484 _convert_ucs2_to_utf8((char*)out, out_len, (char*) in_buf, num*2);
485 if(in_buf!=NULL) free(in_buf);
490 for(i=0; i<in_len; i++) {
491 dbg("[UCS2]in[%d]=0x%02x", i, in[i]);
493 _convert_ucs2_to_utf8((char*)out, out_len, (char*)in, in_len);
498 static int _convert_utf8_to_unicode(unsigned short* dest, unsigned char* src, unsigned int src_len)
500 unsigned short* org = NULL;
501 unsigned char hi = 0;
502 unsigned char mid = 0;
503 unsigned char low = 0;
505 if ((NULL == dest) || (NULL == src)) {
506 dbg( "[SAT] INPUT PARAM NULL");
512 while (src_len > 0 && (*src != '\0')) {
514 *dest = (*src & 0x7F);
518 } else if (((0xC0 <= *src) && (*src < 0xE0)) && (*(src + 1) >= 0x80)) {
520 low = *(src+1) & 0x3F;
521 *dest = (hi << 6) | low;
525 } else if ((*src >= 0xE0) && (*(src + 1) >= 0x80) && (*(src + 2) >= 0x80)) {
527 mid = *(src+1) & 0x3F;
528 low = *(src+2) & 0x3F;
529 *dest = (hi << 12) | (mid << 6) | low;
534 *dest = (*src & 0x7F);
538 dbg( "[SAT] utf8 incorrect range");
545 void sat_mgr_convert_utf8_to_gsm(unsigned char *dest, int *dest_len, unsigned char* src, unsigned int src_len)
547 unsigned short *uc = NULL;
550 gboolean ret = FALSE;
552 if (src == NULL || src_len == 0) {
553 dbg( "WARNING: Invalid Parameter");
557 uc = (unsigned short*) calloc(src_len + 1, sizeof(unsigned short));
559 dbg( "WARNING: calloc Failed");
563 /*Converting from UTF8 => UNICODE*/
564 uc_len = _convert_utf8_to_unicode(uc, src, src_len);
565 dbg( "uc_len:[%d]", uc_len);
567 dbg( "_convert_utf8_to_unicode returns false!");
572 /*Finding the GSMCode Size*/
573 gc_len = _get_gsm_code_size(uc, uc_len);
574 dbg( "gc_len:[%d]", gc_len);
576 dbg( "SM- DATA is not in GSM7BIT Character Set & Error:[%d]", gc_len);
582 /*Converting from UNICODE ==> GSM CODE */
583 ret = _convert_unicode_to_gsm((unsigned char*) dest, *dest_len, uc, uc_len);
585 dbg( "_convert_unicode_to_gsm Failed");
595 void sat_mgr_convert_utf8_to_ucs2(unsigned char* dest, int* dest_len, unsigned char* src, int src_len)
597 gsize byte_converted = 0;
599 gchar* str_converted = NULL;
600 GError *error = NULL;
604 if (dest == NULL || dest_len == NULL || src == NULL) {
605 dbg( "Invalid Input Parameter");
609 /*Converting from UTF8 => UCS-2 using the g_convert*/
610 str_converted = (gchar*) g_convert((gchar*) src, (gsize) src_len,
611 (gchar*) "UCS-2", (gchar*) "UTF8",
612 (gsize*) &byte_read, (gsize*) &byte_converted,
614 if (str_converted == NULL) {
615 dbg( "str_converted is NULL");
617 dbg( "Problem while conversion UTF8 => UCS2, ErrorCode[%d]", error->code);
622 dbg( "src_len[%u], byte_read[%u], byte_converted[%u]", src_len, byte_read, byte_converted);
623 *dest_len = (int) byte_converted;
625 if (byte_converted % 2 != 0) {
626 dbg( "string length is wrong!");
628 for (i = 0; i < (int)byte_converted; i++) {
630 tmp_char = str_converted[i];
631 str_converted[i] = str_converted[i + 1];
632 str_converted[i + 1] = tmp_char;
636 memcpy((unsigned char*) dest, (unsigned char*) str_converted, byte_converted);
637 g_free(str_converted);
641 gboolean sat_mgr_convert_string(unsigned char *dest, unsigned short *dest_len,
642 enum alphabet_format dcs, const unsigned char *src, unsigned short src_len)
644 dbg("[SAT] dcs=[0x%02x]", dcs );
645 dbg("[SAT] src=[%s], src_len=[%d]", src, src_len);
647 if(src==NULL || src_len==0) {
648 err("[SAT] src is NULL or src_len is 0");
653 case ALPHABET_FORMAT_SMS_DEFAULT: {
654 unsigned char* tmp_dest_str = NULL;
655 dbg( "[SAT] alphabetFormat : [ALPHABET_FORMAT_SMS_DEFAULT]");
656 tmp_dest_str = (unsigned char*)tcore_util_unpack_gsm7bit((const unsigned char *)src, src_len);
659 err("temp_dest_str is NULL");
662 _convert_gsm_to_utf8(dest, dest_len, tmp_dest_str, strlen((const char*)tmp_dest_str));
668 case ALPHABET_FORMAT_8BIT_DATA: { //GSM7bit with bit 8 set to 0
670 unsigned char *src_buf = NULL;
671 src_buf = (unsigned char*)malloc(src_len);
672 memcpy(src_buf, src, src_len);
674 /*get string length*/
675 /* 0xFF is the end of string */
676 while (src[tmp_str_len] != 0xFF && tmp_str_len < src_len) {
679 /* last space character must be deleted */
680 while (src[tmp_str_len - 1] == 0x20 && tmp_str_len > 0) {
683 dbg( "[SAT] alphabetFormat : [ALPHABET_FORMAT_8BIT_DATA]");
684 dbg( "[SAT] tmp_str_len[%d]", tmp_str_len);
686 _convert_gsm_to_utf8(dest, dest_len, src_buf, tmp_str_len);
687 if(src_buf != NULL) free(src_buf);
690 case ALPHABET_FORMAT_UCS2: {
691 unsigned char *src_buf = NULL;
692 src_buf = (unsigned char*)malloc(src_len);
693 memcpy(src_buf, src, src_len);
694 dbg( "[SAT] alphabetFormat : [ALPHABET_FORMAT_UCS2]");
695 _convert_alpha_field_ucs2_to_utf8(dest, dest_len, src_buf, src_len);
696 if(src_buf != NULL) free(src_buf);
700 dbg("[SAT] not handled alpha format[0x%02x]", dcs);
707 void swap_byte_order(unsigned short* dest, const unsigned short* src, int src_len)
711 for (i = 0; i < src_len; i++) {
712 dest[i] = (src[i] << 8) + (src[i] >> 8);