| // | |
| // Created by hitmoon on 15-12-9. | |
| // | |
| #include <stddef.h> | |
| #include <stdlib.h> | |
| #include <stdio.h> | |
| #include <sys/timeb.h> | |
| #include <sys/time.h> | |
| #include <time.h> | |
| #include <arpa/inet.h> | |
| #include <ctype.h> | |
| #include "mbtk_pdu_sms.h" | |
| #include "mbtk_alphabet.h" | |
| #include "mbtk_log.h" | |
| #define SUB_STR_SIZE 512 | |
| char temp[SUB_STR_SIZE]; | |
| // some constant | |
| //长短信信息元素参考号 | |
| enum EnumCSMIEI mCSMIEI; | |
| // 服务中心地址 | |
| char *mSCA; | |
| // 请求状态报告 | |
| bool mSRR; | |
| // 拒绝副本 | |
| bool mRD; | |
| // 短信有效期 | |
| char *mVP; | |
| // 长短信信息元素消息参考号 | |
| int mCSMMR; | |
| // initialize PDU constants | |
| void sms_init() | |
| { | |
| mCSMMR = 0; | |
| mRD = false; | |
| mSRR = false; | |
| mSCA = ""; | |
| mVP = ""; | |
| mCSMIEI = BIT8MIEI; | |
| } | |
| char *sub_str(const char *str, int start, int size) { | |
| memset(temp, '\0', SUB_STR_SIZE); | |
| if (size > 0) | |
| strncpy(temp, str + start, size); | |
| else if (size < 0) | |
| strcpy(temp, str + start); | |
| return temp; | |
| } | |
| struct SMS_Struct PDUDecoding(const char *data) { | |
| struct SMS_Struct sms; | |
| int end_index; | |
| int PDUType; | |
| // 短信中心 | |
| sms.SCA = SCADecoding(data, &end_index); | |
| // 协议数据单元类型 | |
| PDUType = strtol(sub_str(data, end_index, 2), NULL, 16); | |
| end_index += 2; | |
| sms.RP = PDUType & (1 << 7) ? true : false; // 应答路径 | |
| sms.UDHI = PDUType & (1 << 6) ? true : false; // 用户数据头标识 | |
| sms.SRI = PDUType & (1 << 5) ? true : false; // 状态报告指示 | |
| sms.MMS = PDUType & (1 << 2) ? false : true; // 更多信息发送 | |
| sms.MTI = PDUType & 3; // 信息类型指示 | |
| // 发送方SME的地址 | |
| sms.OA = OADecoding(data, end_index, &end_index); | |
| // 协议标识 | |
| sms.PID = strtol(sub_str(data, end_index, 2), NULL, 16); | |
| end_index += 2; | |
| // 数据编码方案 | |
| int DCSType = strtol(sub_str(data, end_index, 2), NULL, 16); | |
| end_index += 2; | |
| // 文本压缩指示 | |
| sms.TC = DCSType & (1 << 5); | |
| // 编码字符集 | |
| sms.DCS = (enum EnumDCS) ((DCSType >> 2) & 3); | |
| if (DCSType & (1 << 4)) { | |
| // 信息类型信息 0:立即显示 1:移动设备特定类型 2:SIM特定类型 3:终端设备特定类型 | |
| sms.MC = DCSType & 3; | |
| } | |
| else { | |
| // 不含信息类型信息 | |
| sms.MC = -1; | |
| } | |
| // 服务中心时间戳(BCD编码) | |
| sms.SCTS = SCTSDecoding(data, end_index); | |
| end_index += 14; | |
| // 用户数据头 | |
| if (sms.UDHI) { | |
| sms.UDH = UDHDecoding(data, end_index + 2); | |
| } | |
| else { | |
| sms.UDH = NULL; | |
| } | |
| // 用户数据 | |
| sms.UD = UserDataDecoding(data, end_index, sms.UDHI, sms.DCS); | |
| return sms; | |
| } | |
| char *SCADecoding(const char *data, int *EndIndex) { | |
| int len; | |
| char *result; | |
| char *buf; | |
| int i = 0; | |
| len = strtol(sub_str(data, 0, 2), NULL, 16); | |
| if (len == 0) { | |
| *EndIndex = 2; | |
| return NULL; | |
| } | |
| *EndIndex = (len + 1) * 2; | |
| result = (char *) malloc(sizeof(char) * len * 2); | |
| //wmemset(result, '0', sizeof(char) * (len * 2 + 1)); | |
| buf = result; | |
| len *= 2; | |
| // 服务中心地址类型 | |
| if (strncmp(data + 2, "91", 2) == 0) { | |
| sprintf(buf++, "+"); | |
| } | |
| // 服务中心地 | |
| for (i = 4; i < *EndIndex; i += 2) { | |
| sprintf(buf++, "%c", data[i + 1]); | |
| sprintf(buf++, "%c", data[i]); | |
| } | |
| // 去掉填充的 'F' | |
| if (result[strlen(result) - 1] == L'F') { | |
| result[strlen(result) - 1] = L'\0'; | |
| } | |
| return result; | |
| } | |
| char *OADecoding(const char *data, int index, int *EndIndex) { | |
| int len; | |
| char *result, *buf; | |
| len = strtol(sub_str(data, index, 2), NULL, 16); | |
| if (len == 0) { | |
| *EndIndex = index + 2; | |
| return NULL; | |
| } | |
| *EndIndex = index + 4 + len; | |
| result = (char *) malloc(sizeof(char) * (len + 2)); | |
| //wmemset(result, 0, sizeof(char) * (len + 1)); | |
| buf = result; | |
| if (strncmp(data + index + 2, "91", 2) == 0) { | |
| sprintf(buf++, "+"); | |
| } | |
| // 电话号码 | |
| int i = 0; | |
| for (i = 0; i < len; i += 2) { | |
| sprintf(buf++, "%c", data[index + i + 5]); | |
| sprintf(buf++, "%c", data[index + i + 4]); | |
| } | |
| if (len % 2 != 0) { | |
| result[strlen(result) - 1] = '\0'; | |
| (*EndIndex)++; | |
| } | |
| return result; | |
| } | |
| char *SCTSDecoding(const char *data, int index) { | |
| char *result; | |
| result = (char *) malloc(sizeof(char) * 32); | |
| sprintf(result, "20%02d-%02d-%02d %02d:%02d:%02d", | |
| BCDDecoding(data, index, 0), // 年 | |
| BCDDecoding(data, index + 2, 0), // 月 | |
| BCDDecoding(data, index + 4, 0), // 日 | |
| BCDDecoding(data, index + 6, 0), // 时 | |
| BCDDecoding(data, index + 8, 0), // 分 | |
| BCDDecoding(data, index + 10, 0) // 秒 | |
| ); | |
| return result; | |
| } | |
| int BCDDecoding(const char *data, int index, bool isMSB) { | |
| int n1, n10; | |
| n1 = strtol(sub_str(data, index, 1), NULL, 10); | |
| n10 = strtol(sub_str(data, index + 1, 1), NULL, 10); | |
| if (isMSB) { | |
| if (n10 >= 8) | |
| return -((n10 - 8) * 10 + n1); // 负值 | |
| else | |
| return n10 * 10 + n1; | |
| } | |
| else { | |
| return n10 * 10 + n1; | |
| } | |
| } | |
| struct UDHS *UDHDecoding(const char *data, int index) { | |
| int len; | |
| struct UDHS *result; | |
| len = strtol(sub_str(data, index, 2), NULL, 16); | |
| index += 2; | |
| int i = 0; | |
| result = (struct UDHS *) malloc(sizeof(struct UDHS)); | |
| result->UDH = (struct PDUUDH *) malloc(sizeof(struct PDUUDH) * len); | |
| result->count = 0; | |
| memset(result->UDH, 0, sizeof(struct PDUUDH) * len); | |
| while (i < len) { | |
| // 信息元素标识(Information Element Identifier | |
| char IEI = strtol(sub_str(data, index, 2), NULL, 16); | |
| index += 2; | |
| // 信息元素数据长度(Length of Information Element) | |
| int IEDL = strtol(sub_str(data, index, 2), NULL, 16); | |
| index += 2; | |
| // 信息元素数据(Information Element Data) | |
| char *IED = (char *) malloc(sizeof(char) * (IEDL + 1)); | |
| int j = 0; | |
| for (j = 0; j < IEDL; j++) { | |
| IED[j] = strtol(sub_str(data, index, 2), NULL, 16); | |
| index += 2; | |
| } | |
| result->UDH[result->count].IEI = IEI; | |
| result->UDH[result->count].IED = IED; | |
| result->count++; | |
| i += IEDL + 2; | |
| } | |
| return result; | |
| } | |
| char *UserDataDecoding(const char *data, int index, bool UDHI, enum EnumDCS dcs) { | |
| char *result = NULL; | |
| char *buf; | |
| // 用户数据区长度 | |
| int UDL = strtol(sub_str(data, index, 2), NULL, 16); | |
| index += 2; | |
| // 跳过用户数据头 | |
| int UDHL = 0; | |
| if (UDHI) { | |
| // 用户数据头长度 | |
| UDHL = strtol(sub_str(data, index, 2), NULL, 16); | |
| UDHL++; | |
| index += UDHL << 1; | |
| } | |
| // 获取用户数据 | |
| if (dcs == UCS2) { | |
| int len = (UDL - UDHL) >> 1; | |
| int utf8_len; | |
| result = (char *) malloc(sizeof(char) * (len * 3)); | |
| buf = result; | |
| u_int32_t code[2]; | |
| int i = 0; | |
| for (i = 0; i < len; i++) { | |
| code[0] = strtol(sub_str(data, (i << 2) + index, 4), NULL, 16); | |
| code[1] = 0; | |
| utf32toutf8((wchar_t*)code, (unsigned char*)buf, len * 3, &utf8_len); | |
| buf += utf8_len; | |
| } | |
| buf[0] = '\0'; | |
| return result; | |
| } | |
| else if (dcs == BIT7) { | |
| int Septets = UDL - (UDHL * 8 + 6) / 7; // 7-Bit编码字符数 | |
| int FillBits = (UDHL * 8 + 6) / 7 * 7 - UDHL * 8; // 填充位数 | |
| return BIT7Decoding(BIT7Unpack(data, index, Septets, FillBits), Septets); | |
| } | |
| else {// 8Bit编码 | |
| // 获取数据长度 | |
| UDL -= UDHL; | |
| result = (char *) malloc(sizeof(char) * (UDL + 1)); | |
| int i = 0; | |
| for (i = 0; i < UDL; i++) { | |
| result[i] = strtol(sub_str(data, (i << 1) + index, 2), NULL, 16); | |
| } | |
| return result; | |
| } | |
| return "Error!"; | |
| } | |
| char *BIT7Unpack(const char *data, int index, int Septets, int FillBits) { | |
| char *result; | |
| result = (char *) malloc(sizeof(char) * (Septets + 1)); | |
| // 每8个7-Bit编码字符存放到7个字节 | |
| int PackLen = (Septets * 7 + FillBits + 7) / 8; | |
| int n = 0; | |
| int left = 0; | |
| // printf("Unapck data = %s\n", data + index); | |
| // printf("Septets = %d\n", Septets); | |
| // printf("pack len = %d\n", PackLen); | |
| // printf("fillbits = %d\n", FillBits); | |
| int i = 0; | |
| for (i = 0; i < PackLen; i++) { | |
| int Order = (i + (7 - FillBits)) % 7; | |
| int Value = strtol(sub_str(data, (i << 1) + index, 2), NULL, 16); | |
| if (i != 0 || FillBits == 0) { | |
| result[n++] = ((Value << Order) + left) & 0x7F; | |
| } | |
| // printf("left = %d, i = %d, order = %d, value = %d\n", left, i, Order, Value); | |
| // printf("result[%d] = %d\n", n - 1, result[n - 1]); | |
| left = Value >> (7 - Order); | |
| if (Order == 6) { | |
| if (n == Septets) | |
| break; | |
| result[n++] = left; | |
| //printf("result[%d] = %d\n", n - 1, result[n - 1]); | |
| left = 0; | |
| } | |
| } | |
| return result; | |
| } | |
| char *BIT7Decoding(char *BIT7Data, unsigned int size) | |
| { | |
| char *result, *buf; | |
| result = (char *) malloc(sizeof(char) * (size + 1)); | |
| buf = result; | |
| int i = 0; | |
| for (i = 0; i < size; i++) { | |
| u_int16_t key = BIT7Data[i]; | |
| if (isBIT7Same(key)) { | |
| sprintf(buf++, "%c", key); | |
| } | |
| else if (map_get_value(BIT7ToUCS2, map_size(BIT7ToUCS2), key) >= 0) { | |
| u_int16_t value; | |
| if (key == 0x1B) { // 转义字符 | |
| value = map_get_value(BIT7EToUCS2, map_size(BIT7EToUCS2), BIT7Data[i + 1]); | |
| if (i < size - 1 && value > 0) { | |
| sprintf(buf++, "%c", value); | |
| i++; | |
| } | |
| else { | |
| value = map_get_value(BIT7ToUCS2, map_size(BIT7ToUCS2), key); | |
| sprintf(buf++, "%c", value); | |
| } | |
| } | |
| else { | |
| //printf("go b\n"); | |
| value = map_get_value(BIT7ToUCS2, map_size(BIT7ToUCS2), key); | |
| //printf("value = %u\n", value); | |
| sprintf(buf++, "%c", value); | |
| } | |
| } | |
| else {// 异常数据 | |
| sprintf(buf++, "?"); | |
| } | |
| } | |
| return result; | |
| } | |
| int isBIT7Same(u_int16_t UCS2) { | |
| if ((UCS2 >= 0x61 && UCS2 <= 0x7A) || | |
| (UCS2 >= 0x41 && UCS2 <= 0x5A) || | |
| (UCS2 >= 0x25 && UCS2 <= 0x3F) || | |
| (UCS2 >= 0x20 && UCS2 <= 0x23) || | |
| UCS2 == 0x0A || UCS2 == 0x0D) { | |
| return 1; | |
| } | |
| return 0; | |
| } | |
| struct PDUS *PDUEncoding(char *SCA, char *DA, char *UDC, struct UDHS *udhs) { | |
| enum EnumDCS DCS; | |
| sms_init(); | |
| // if (isGSMString(UDC)) | |
| // DCS = BIT7; | |
| // else | |
| DCS = UCS2; | |
| return PDUDoEncoding(SCA, DA, UDC, udhs, DCS); | |
| } | |
| struct PDUS *PDUDoEncoding(char *SCA, char *DA, char *UDC, struct UDHS *udhs, enum EnumDCS DCS) { | |
| // 短信拆分 | |
| struct UDS *uds = UDCSplit(UDC, udhs, DCS); | |
| struct PDUS *pdus; | |
| if (uds == NULL) | |
| return NULL; | |
| pdus = (struct PDUS *) malloc(sizeof(struct PDUS)); | |
| pdus->count = 0; | |
| pdus->PDU = (char **) malloc(sizeof(char *) * uds->total); | |
| if (uds->total > 1) { | |
| // 长短信 | |
| int CSMMR = mCSMMR; | |
| if (++mCSMMR > 0xFFFF) | |
| mCSMMR = 0; | |
| // 生成短信编码序列 | |
| int i = 0; | |
| for (i = 0; i < uds->total; i++) { | |
| // 更新用户数据头 | |
| struct UDHS *CSMUDH = UpdateUDH(udhs, CSMMR, uds->total, i); | |
| pdus->PDU[i] = SoloPDUEncoding(SCA, DA, uds->Data[i], CSMUDH, DCS); | |
| pdus->count++; | |
| } | |
| } | |
| else { // 单条短信 | |
| pdus->PDU[0] = SoloPDUEncoding(SCA, DA, uds->Data[0], udhs, DCS); | |
| pdus->count = 1; | |
| } | |
| return pdus; | |
| } | |
| int isGSMString(char *Data) { | |
| if (Data == NULL || strcmp(Data, "") == 0) | |
| return 1; | |
| if (is_acsii((unsigned char*)Data) == 0) { | |
| int len; | |
| len = utf8len((unsigned char *) Data); | |
| u_int16_t *code = (u_int16_t *) malloc(sizeof(u_int16_t) * len); | |
| utf8toutf16((unsigned char *) Data, code, len, &len); | |
| while (*code) { | |
| if (!(isBIT7Same(*code) || map_get_value(UCS2ToBIT7, map_size(UCS2ToBIT7), *code) >= 0)) | |
| return 0; | |
| code++; | |
| } | |
| return 1; | |
| } | |
| else | |
| return 1; | |
| } | |
| struct UDS *UDCSplit(char *UDC, struct UDHS *udhs, enum EnumDCS DCS) { | |
| int UDHL = getUDHL(udhs); | |
| struct UDS *result; | |
| if (DCS == BIT7) { | |
| // 7-Bit编码 | |
| // 计算剩余房间数 | |
| int room = BIT7UDL - (UDHL * 8 + 6) / 7; | |
| if (room < 1) { | |
| if (UDC == NULL || strcmp(UDC, "") == 0) { | |
| result = (struct UDS *) malloc(sizeof(struct UDS)); | |
| result->Data = (char **)malloc(sizeof(char *)); | |
| result->total = 1; | |
| result->Data[0] = UDC; | |
| return result; | |
| } | |
| else | |
| return NULL; | |
| } | |
| // 不需要拆分 | |
| if (SeptetsLength(UDC) <= room) { | |
| result = (struct UDS *) malloc(sizeof(struct UDS)); | |
| result->Data = (char **)malloc(sizeof(char *)); | |
| result->total = 1; | |
| result->Data[0] = UDC; | |
| return result; | |
| } | |
| else // 拆分短信 | |
| { | |
| if (UDHL == 0) | |
| UDHL++; | |
| if (mCSMIEI == BIT8MIEI) | |
| UDHL += 5; // 1字节消息参考号 | |
| else | |
| UDHL += 6; // 2字节消息参考号 | |
| // 更新剩余房间数 | |
| room = BIT7UDL - (UDHL * 8 + 6) / 7; | |
| if (room < 1) | |
| return NULL; | |
| int i = 0; | |
| int len = strlen(UDC); | |
| result = (struct UDS *) malloc(sizeof(struct UDS)); | |
| result->total = 0; | |
| result->Data = (char **) malloc(MAX_SMS_NR * sizeof(char *)); | |
| while (i < len) { | |
| int step = SeptetsToChars(UDC, i, room); | |
| if (i + step < len) { | |
| result->Data[result->total] = (char *) malloc(sizeof(char) * (step + 1)); | |
| strcpy(result->Data[result->total++], sub_str(UDC, i, step)); | |
| } | |
| else { | |
| result->Data[result->total] = (char *) malloc(sizeof(char) * (len - i + 1)); | |
| strcpy(result->Data[result->total++], sub_str(UDC, i, -1)); | |
| } | |
| i += step; | |
| } | |
| return result; | |
| } | |
| } | |
| else { // UCS2编码 | |
| // 计算剩余房间数 | |
| int room = (BIT8UDL - UDHL) >> 1; | |
| if (room < 1) { | |
| if (UDC == NULL || strcmp(UDC, "") == 0) { | |
| result = (struct UDS *) malloc(sizeof(struct UDS)); | |
| result->Data = (char **)malloc(sizeof(char *)); | |
| result->total = 1; | |
| result->Data[0] = UDC; | |
| return result; | |
| } | |
| else | |
| return NULL; | |
| } | |
| if (UDC == NULL || utf8len((unsigned char *)UDC) <= room) { | |
| result = (struct UDS *) malloc(sizeof(struct UDS)); | |
| result->Data = (char **)malloc(sizeof(char *)); | |
| result->total = 1; | |
| result->Data[0] = UDC; | |
| return result; | |
| } | |
| else // 需要拆分成多条短信 | |
| { | |
| if (UDHL == 0) | |
| UDHL++; | |
| if (mCSMIEI == BIT8MIEI) | |
| UDHL += 5; // 1字节消息参考号 | |
| else | |
| UDHL += 6; // 2字节消息参考号 | |
| // 更新剩余房间数 | |
| room = (BIT8UDL - UDHL) >> 1; | |
| if (room < 1) | |
| return NULL; | |
| int len = utf8len((unsigned char *)UDC); | |
| result = (struct UDS *) malloc(sizeof(struct UDS)); | |
| result->total = 0; | |
| result->Data = (char **) malloc(MAX_SMS_NR * sizeof(char *)); | |
| int index = 0; | |
| int i = 0; | |
| for (i = 0; i < len; i += room) { | |
| int real_size; | |
| if (i + room < len) { | |
| real_size = utf8_get_size((unsigned char *)UDC + index, room); | |
| result->Data[result->total] = (char*)malloc(sizeof(char) * (real_size + 1)); | |
| strcpy(result->Data[result->total++],sub_str(UDC, index, real_size)); | |
| } | |
| else { | |
| real_size = utf8_get_size((unsigned char *)UDC + index, len - i); | |
| result->Data[result->total] = (char*)malloc(sizeof(char) * (real_size + 1)); | |
| strcpy(result->Data[result->total++], sub_str(UDC, index, -1)); | |
| } | |
| index += real_size; | |
| } | |
| return result; | |
| } | |
| } | |
| } | |
| int getUDHL(struct UDHS *udhs) { | |
| //在编码处添加用户数据头长度 | |
| //if (udhs == NULL) | |
| return 0; | |
| // 加上1字节的用户数据头长度 | |
| int UDHL = 1; | |
| int i = 0; | |
| for (i = 0; i < udhs->count; i++) { | |
| UDHL += strlen(udhs->UDH[i].IED) + 2; | |
| } | |
| return UDHL; | |
| } | |
| int SeptetsLength(char *source) { | |
| if (source == NULL || strcmp(source, "") == 0) { | |
| return 0; | |
| } | |
| int len = strlen(source); | |
| while (*source) { | |
| u_int16_t code = (u_int16_t) *source; | |
| if (map_get_value(UCS2ToBIT7, map_size(UCS2ToBIT7), code) > 0xFF) { | |
| len++; | |
| } | |
| source++; | |
| } | |
| return len; | |
| } | |
| int SeptetsToChars(char *source, int index, int septets) { | |
| if (source == NULL || strcmp(source, "") == 0) | |
| return 0; | |
| int count = 0; | |
| int i; | |
| for (i = index; i < strlen(source); i++) { | |
| u_int16_t code = (u_int16_t) source[i]; | |
| if (map_get_value(UCS2ToBIT7, map_size(UCS2ToBIT7), code) > 0xFF) | |
| count++; | |
| if (++count >= septets) { | |
| if (count == septets) | |
| i++; | |
| break; | |
| } | |
| } | |
| return i - index; | |
| } | |
| struct UDHS *UpdateUDH(struct UDHS *udhs, int CSMMR, int total, int index) { | |
| struct UDHS *result; | |
| result = (struct UDHS *) malloc(sizeof(struct UDHS)); | |
| if (udhs == NULL || udhs->count == 0) { | |
| result->UDH = (struct PDUUDH *) malloc(sizeof(struct PDUUDH)); | |
| result->count = 1; | |
| } | |
| else { | |
| result->UDH = (struct PDUUDH *) malloc(sizeof(struct PDUUDH) * (udhs->count + 1)); | |
| result->count = udhs->count + 1; | |
| // 复制 UDH | |
| memcpy(&result->UDH[1], udhs->UDH, sizeof(struct PDUUDH) * udhs->count); | |
| } | |
| // 插入第一个位置 | |
| if (mCSMIEI == BIT8MIEI) { | |
| result->UDH[0].IED = (char *) malloc(sizeof(char) * 3); | |
| result->UDH[0].count = 3; | |
| result->UDH[0].IED[0] = CSMMR & 0xFF; | |
| result->UDH[0].IED[1] = total; | |
| result->UDH[0].IED[2] = index + 1; | |
| result->UDH[0].IEI = 0; | |
| } | |
| else { | |
| result->UDH[0].IED = (char *) malloc(sizeof(char) * 4); | |
| result->UDH[0].count = 4; | |
| result->UDH[0].IED[0] = (CSMMR >> 8) & 0xFF; | |
| result->UDH[0].IED[1] = CSMMR & 0xFF; | |
| result->UDH[0].IED[2] = total; | |
| result->UDH[0].IED[3] = index + 1; | |
| result->UDH[0].IEI = 8; | |
| } | |
| return result; | |
| } | |
| char *SoloPDUEncoding(char *SCA, char *DA, char *UC, struct UDHS *udhs, enum EnumDCS DCS) { | |
| char *result; | |
| char *buf, *ret; | |
| result = (char *) malloc(sizeof(char) * 400); | |
| buf = result; | |
| /* // 短信中心 | |
| ret = SCAEncoding(SCA); | |
| index = strlen(ret); | |
| sprintf(buf, "%s", ret); | |
| printf("buf:%s\n",buf); | |
| buf += index; | |
| */ | |
| // 协议数据单元类型 | |
| if (udhs == NULL || udhs->count == 0) { | |
| ret = PDUTypeEncoding(false); | |
| sprintf(buf, "%s", ret); | |
| buf += strlen(ret); | |
| } | |
| else { | |
| ret = PDUTypeEncoding(true); | |
| sprintf(buf, "%s", ret); | |
| buf += strlen(ret); | |
| } | |
| // 消息参考值 | |
| ret = MREncoding(); | |
| sprintf(buf, "%s", ret); | |
| buf += strlen(ret); | |
| // 接收方SME地址 | |
| ret = DAEncoding(DA); | |
| sprintf(buf, "%s", ret); | |
| buf += strlen(ret); | |
| // 协议标识 | |
| ret = PIDEncoding(); | |
| sprintf(buf, "%s", ret); | |
| buf += strlen(ret); | |
| // 编码方案 | |
| ret = DCSEncoding(UC, DCS); | |
| sprintf(buf, "%s", ret); | |
| buf += strlen(ret); | |
| // 有效期 | |
| sprintf(buf, "%s", mVP); | |
| buf += strlen(mVP); | |
| // 用户数据长度及内容 | |
| ret = UDEncoding(UC, udhs, DCS); | |
| sprintf(buf, "%s", ret); | |
| return result; | |
| } | |
| char *SCAEncoding(char *SCA) { | |
| if (SCA == NULL || strcmp(SCA, "") == 0) { | |
| // 表示使用SIM卡内部的设置值,该值通过AT+CSCA指令设置 | |
| return "00"; | |
| } | |
| char *result; | |
| char *buf; | |
| int len; | |
| len = strlen(SCA); | |
| result = (char *) malloc((len + 5) * sizeof(char)); | |
| buf = result; | |
| int index = 0; | |
| if (SCA[0] == '+') { | |
| // 国际号码 | |
| sprintf(buf, "%02X", len / 2 + 1); | |
| buf += 2; | |
| sprintf(buf, "91"); | |
| buf += 2; | |
| index = 1; | |
| } | |
| else { | |
| // 国内号码 | |
| sprintf(buf, "%02X", len / 2 + 1); | |
| buf += 2; | |
| sprintf(buf, "81"); | |
| buf += 2; | |
| } | |
| // SCA地址编码 | |
| for (; index < len; index += 2) { | |
| if (index == len - 1) { | |
| // 补“F”凑成偶数个 | |
| sprintf(buf++, "F"); | |
| sprintf(buf++, "%c", SCA[index]); | |
| } | |
| else { | |
| sprintf(buf++, "%c", SCA[index + 1]); | |
| sprintf(buf++, "%c", SCA[index]); | |
| } | |
| } | |
| return result; | |
| } | |
| char *PDUTypeEncoding(bool UDH) { | |
| // 信息类型指示(Message Type Indicator) | |
| // 01 SMS-SUBMIT(MS -> SMSC) | |
| int PDUType = 0x11; // 508TLC change | |
| // int PDUType = 0x01; | |
| char *result; | |
| result = (char *) malloc(3 * sizeof(char)); | |
| // 用户数据头标识(User Data Header Indicator) | |
| if (UDH) { | |
| PDUType |= 0x40; | |
| } | |
| // 有效期格式(Validity Period Format) | |
| if (strlen(mVP) == 2) { | |
| // VP段以整型形式提供(相对的) | |
| PDUType |= 0x10; | |
| } | |
| else if (strlen(mVP) == 14) { | |
| // VP段以8位组的一半(semi-octet)形式提供(绝对的) | |
| PDUType |= 0x18; | |
| } | |
| // 请求状态报告(Status Report Request) | |
| if (mSRR) { | |
| // 请求状态报告 | |
| PDUType |= 0x20; | |
| } | |
| // 拒绝复本(Reject Duplicate) | |
| if (mRD) { | |
| PDUType |= 0x04; | |
| } | |
| sprintf(result, "%02X", PDUType); | |
| return result; | |
| } | |
| char *MREncoding() { | |
| // 由手机设置 | |
| return "00"; | |
| } | |
| char *DAEncoding(char *DA) { | |
| if (DA == NULL || strcmp(DA, "") == 0) { | |
| // 地址长度0,地址类型未知 | |
| return "0080"; | |
| } | |
| char *result, *buf; | |
| int len = strlen(DA); | |
| int index = 0; | |
| result = (char *) malloc(sizeof(char) * (len + 5)); | |
| buf = result; | |
| if (DA[0] == '+') { | |
| // 国际号码 | |
| // 地址长度编码 | |
| sprintf(buf, "%02X", len - 1); | |
| buf += 2; | |
| // 地址类型 | |
| sprintf(buf, "91"); | |
| buf += 2; | |
| index = 1; | |
| } | |
| else { | |
| // 国内号码 | |
| // 地址长度编码 | |
| sprintf(buf, "%02X", len); | |
| buf += 2; | |
| // 地址类型 | |
| sprintf(buf, "81"); | |
| buf += 2; | |
| } | |
| for (; index < len; index += 2) { | |
| // 号码部分奇偶位对调 | |
| if (index == len - 1) { | |
| sprintf(buf++, "F"); | |
| sprintf(buf++, "%c", DA[index]); | |
| } | |
| else { | |
| sprintf(buf++, "%c", DA[index + 1]); | |
| sprintf(buf++, "%c", DA[index]); | |
| } | |
| } | |
| return result; | |
| } | |
| char *PIDEncoding() { | |
| return "00"; | |
| } | |
| char *DCSEncoding(char *UD, enum EnumDCS DCS) { | |
| if (DCS == BIT7) { | |
| // 7-Bit编码 | |
| return "00"; | |
| } | |
| else { | |
| // UCS2编码 | |
| return "0800"; | |
| } | |
| } | |
| char *UDEncoding(char *UD, struct UDHS *udhs, enum EnumDCS DCS) { | |
| int UDHL = 0; | |
| char *result; | |
| // 用户数据头编码 | |
| char *header = UDHEncoding(udhs, &UDHL); | |
| // 用户数据内容编码 | |
| int UDCL; | |
| char *body; | |
| body = UDCEncoding(UD, &UDCL, UDHL, DCS); | |
| // 用户数据区长度 | |
| int UDL = 0; | |
| if (DCS == BIT7) { | |
| // 7-Bit编码 | |
| UDL = (UDHL * 8 + 6) / 7 + UDCL; | |
| } | |
| else { | |
| // UCS2编码或者8-Bit编码 | |
| UDL = UDHL + UDCL; | |
| } | |
| int len = strlen(header) + strlen(body) + 2; | |
| result = (char *) malloc(sizeof(char) * (len + 1)); | |
| sprintf(result, "%02X%s%s", UDL, header, body); | |
| return result; | |
| } | |
| char *UDHEncoding(struct UDHS *udhs, int *UDHL) { | |
| int i = 0; | |
| if (udhs == NULL || udhs->count == 0) | |
| return ""; | |
| #if 1 | |
| *UDHL = 5; | |
| #else | |
| *UDHL = 0; | |
| for (i = 0; i < udhs->count; i++) { | |
| *UDHL += udhs->UDH[i].count + 2; | |
| } | |
| #endif | |
| char *result; | |
| char *buf; | |
| result = (char *) malloc(sizeof(char) * ((*UDHL + 1) * 2 + 1)); | |
| buf = result; | |
| sprintf(buf, "%02X", *UDHL); | |
| buf += 2; | |
| for (i = 0; i < udhs->count; i++) { | |
| if (i == 0) | |
| { | |
| // 信息元素标识1字节 | |
| sprintf(buf, "%02X", udhs->UDH[i].IEI); | |
| buf += 2; | |
| // 信息元素长度1字节 | |
| sprintf(buf, "%02X", udhs->UDH[i].count); | |
| buf += 2; | |
| } | |
| // 信息元素数据 | |
| int j = 0; | |
| for (j = 0; j < udhs->UDH[i].count; j++) { | |
| sprintf(buf, "%02X", udhs->UDH[i].IED[j]); | |
| buf += 2; | |
| } | |
| } | |
| // 加上1字节的用户数据头长度 | |
| (*UDHL)++; | |
| return result; | |
| } | |
| char *UDCEncoding(char *UDC, int *UDCL, int UDHL, enum EnumDCS DCS) { | |
| if (UDC == NULL || strcmp(UDC, "") == 0) { | |
| *UDCL = 0; | |
| return ""; | |
| } | |
| if (DCS == BIT7) { | |
| // 7-Bit编码,需要参考用户数据头长度,已保证7-Bit边界对齐 | |
| return BIT7Pack(BIT7Encoding(UDC, UDCL), UDHL); | |
| } | |
| else { | |
| // UCS2编码 | |
| int len = utf8len((unsigned char*)UDC); | |
| int len2; | |
| unsigned short *code; | |
| code = (unsigned short*)malloc(sizeof(unsigned short) * len); | |
| utf8toutf16((unsigned char*)UDC, code, len, &len2); | |
| *UDCL = len * 2; | |
| char *result = (char *) malloc(sizeof(char) * (*UDCL * 2 + 1)); | |
| char *buf = result; | |
| int i = 0; | |
| for (i = 0; i < len; i++) { | |
| sprintf(buf, "%04X", code[i]); | |
| buf += 4; | |
| } | |
| free(code); | |
| return result; | |
| } | |
| } | |
| struct ByteArray *BIT7Encoding(char *UDC, int *Septets) { | |
| struct ByteArray *result; | |
| int len = strlen(UDC); | |
| result = (struct ByteArray *) malloc(sizeof(struct ByteArray)); | |
| result->len = 0; | |
| result->array = (char *) malloc(sizeof(char) * (len * 2 + 1)); | |
| *Septets = 0; | |
| int i = 0; | |
| for (i = 0; i < len; i++) { | |
| u_int16_t code = (u_int16_t) UDC[i]; | |
| if (isBIT7Same(code)) { | |
| // 编码不变 | |
| result->array[(*Septets)++] = code; | |
| } | |
| else { | |
| u_int16_t value = map_get_value(UCS2ToBIT7, map_size(UCS2ToBIT7), code); | |
| if (value >= 0) { | |
| if (value > 0xFF) { | |
| // 转义序列 | |
| result->array[(*Septets)++] = value >> 8; | |
| result->array[(*Septets)++] = value & 0xFF; | |
| } | |
| else { | |
| result->array[(*Septets)++] = value; | |
| } | |
| } | |
| else { | |
| // 未知字符 | |
| result->array[(*Septets)++] = (u_int16_t) '?'; | |
| } | |
| } | |
| } | |
| // 重新调整大小 | |
| result->len = *Septets; | |
| return result; | |
| } | |
| char *BIT7Pack(struct ByteArray *Bit7Array, int UDHL) { | |
| // 7Bit对齐需要的填充位 | |
| int fillBits = (UDHL * 8 + 6) / 7 * 7 - (UDHL * 8); | |
| // 压缩字节数 | |
| int len = Bit7Array->len; | |
| int packLen = (len * 7 + fillBits + 7) / 8; | |
| char *result; | |
| char *buf; | |
| result = (char *) malloc(sizeof(char) * (packLen * 2 + 1)); | |
| buf = result; | |
| int left = 0; | |
| int i = 0; | |
| for (i = 0; i < len; i++) { | |
| // 每8个字节压缩成7个字节 | |
| int32_t Value = Bit7Array->array[i]; | |
| int32_t index = (i + 8 - fillBits) % 8; | |
| if (index == 0) { | |
| left = Value; | |
| } | |
| else { | |
| int32_t n = ((Value << (8 - index)) | left) & 0xFF; | |
| sprintf(buf, "%02X", n); | |
| buf += 2; | |
| left = Value >> index; | |
| } | |
| } | |
| if ((len * 7 + fillBits) % 8 != 0) { | |
| // 写入剩余数据 | |
| sprintf(buf, "%02X", left); | |
| buf += 2; | |
| } | |
| buf[0] = '\0'; | |
| return result; | |
| } | |
| #define NOP ('_') | |
| static kal_uint8 latin1_to_gsm_table[] = | |
| { | |
| //0x00 -, -, -, -, -, -, -, -, | |
| NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, | |
| //0x08 -, -, LF, -, -, CR, -, -, | |
| NOP, NOP, 10, NOP, NOP, 13, NOP, NOP, | |
| //0x10 -, -, -, -, -, -, -, -, | |
| NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, | |
| //0x18 -, -, -, -, -, -, -, -, | |
| NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, | |
| //0x20 ' ', '!', '"', '#', -, '%', '&', ''', | |
| ' ', '!', '"', '#', 0x2, '%', '&', '\'', | |
| //0x28 '(', ')', '*', '+', ',', '-', '.', '/', | |
| '(', ')', '*', '+', ',', '-', '.', '/', | |
| //0x30 '0', '1', '2', '3', '4', '5', '6', '7', | |
| '0', '1', '2', '3', '4', '5', '6', '7', | |
| //0x38 '8', '9', ':', ';', '<', '=', '>', '?', | |
| '8', '9', ':', ';', '<', '=', '>', '?', | |
| //0x40 -, 'A', 'B', 'C', 'D', 'E', 'F', 'G', | |
| 0x0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', | |
| //0x48 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', | |
| 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', | |
| //0x50 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', | |
| 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', | |
| //0x58 'X', 'Y', 'Z', -, -, -, -, -, | |
| 'X', 'Y', 'Z', NOP, NOP, NOP, NOP,0x11, | |
| //0x60 -, 'a', 'b', 'c', 'd', 'e', 'f', 'g', | |
| NOP, 'a', 'b', 'c', 'd', 'e', 'f', 'g', | |
| //0x68 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', | |
| 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', | |
| //0x70 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', | |
| 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', | |
| //0x78 'x', 'y', 'z', -, -, -, -, -, | |
| 'x', 'y', 'z', NOP, NOP, NOP, NOP, NOP, | |
| //0x80 -, -, -, -, -, -, -, -, | |
| NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, | |
| //0x88 -, -, -, -, -, -, -, -, | |
| NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, | |
| //0x90 -, -, -, -, -, -, -, -, | |
| NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, | |
| //0x98 -, -, -, -, -, -, -, -, | |
| NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, | |
| //0xA0 -, -, -, -, -, -, -, -, | |
| NOP, 0x40,NOP, 0x1, 0x24,0x3, NOP,0x5F, | |
| //0xA8 -, -, -, -, -, -, -, -, | |
| NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, | |
| //0xB0 -, -, -, -, -, -, -, -, | |
| NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, | |
| //0xB8 -, -, -, -, -, -, -, -, | |
| NOP, NOP, NOP, NOP, NOP, NOP, NOP,0x60, | |
| //0xC0 'A', 'A', 'A', 'A', -, -, -, -, | |
| 'A', 'A', 'A', 'A', 0x5B,0xE, 0x1C,0x9, | |
| //0xC8 'E', -, 'E', 'E', 'I', 'I', 'I', 'I', | |
| 'E',0x1F, 'E', 'E', 'I', 'I', 'I', 'I', | |
| //0xD0 -, -, 'O', 'O', 'O', 'O', -, -, | |
| NOP,0x5D, 'O', 'O', 'O', 'O',0x5C, NOP, | |
| //0xD8 -, 'U', 'U', 'U', -, -, 'Y', -, | |
| 0x0B,'U', 'U', 'U',0x5E, 'Y', NOP,0x1E, | |
| //0xE0 -, 'a', 'a', 'a', -, -, -, -, | |
| 0x7F,'a', 'a', 'a',0x7B, 0xF,0x1D, 0x9, | |
| //0xE8 -, -, 'e', 'e', -, 'i', 'i', 'i', | |
| 0x4, 0x5, 'e', 'e', 0x7, 'i', 'i', 'i', | |
| //0xF0 -, -, -, 'o', 'o', 'o', -, -, | |
| NOP,0x7D, 0x8, 'o', 'o', 'o',0x7C, NOP, | |
| //0xF8 -, -, 'u', 'u', -, 'y', -, 'y', | |
| 0xC, 0x6, 'u', 'u',0x7E, 'y', NOP, 'y' | |
| }; | |
| static Latin1_to_Gsm_ExTable latin1_to_gsm_tableEx[]= | |
| { | |
| {'^', 0x14,}, | |
| {'{', 0x28,}, | |
| {'}', 0x29,}, | |
| {'\\',0x2f,}, | |
| {'[', 0x3C,}, | |
| {'~', 0x3d,}, | |
| {']', 0x3e,}, | |
| {'|', 0x40,}, | |
| {0,0x00,}, | |
| }; | |
| static kal_uint8 gsm_to_latin1_table[] = | |
| { | |
| //0x00 '@', -, '$', -, -, -, -, -, | |
| '@', 163, '$', 165, 232, 233, 249, 236, | |
| //0x08 -, -, LF, -, -, CR, -, -, | |
| 242, 199, 10, 216, 248, 13, 197, 229, | |
| //0x10 -, '_', -, -, -, -, -, -, | |
| NOP, '_', NOP, NOP, NOP, NOP, NOP, NOP, | |
| //0x18 -, -, -, -, -, -, -, -, | |
| NOP, NOP, NOP, NOP, 198, 230, 223, 201, | |
| //0x20 ' ', '!', '"', '#', '?, '%', '&', ''', | |
| ' ', '!', '"', '#', 164, '%', '&', '\'', | |
| //0x28 '(', ')', '*', '+', ',', '-', '.', '/', | |
| '(', ')', '*', '+', ',', '-', '.', '/', | |
| //0x30 '0', '1', '2', '3', '4', '5', '6', '7', | |
| '0', '1', '2', '3', '4', '5', '6', '7', | |
| //0x38 '8', '9', ':', ';', '<', '=', '>', '?', | |
| '8', '9', ':', ';', '<', '=', '>', '?', | |
| //0x40 -, 'A', 'B', 'C', 'D', 'E', 'F', 'G', | |
| 161, 'A', 'B', 'C', 'D', 'E', 'F', 'G', | |
| //0x48 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', | |
| 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', | |
| //0x50 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', | |
| 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', | |
| //0x58 'X', 'Y', 'Z', -, -, -, -, -, | |
| 'X', 'Y', 'Z', 196, 214, 209, 220, 167, | |
| //0x60 -, 'a', 'b', 'c', 'd', 'e', 'f', 'g', | |
| 191, 'a', 'b', 'c', 'd', 'e', 'f', 'g', | |
| //0x68 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', | |
| 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', | |
| //0x70 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', | |
| 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', | |
| //0x78 'x', 'y', 'z', -, -, -, -, -, | |
| 'x', 'y', 'z', 228, 246, 241, 252, 224 | |
| }; | |
| int hexChar_To_Int(char c) | |
| { | |
| if (c >= '0' && c <= '9') | |
| return (c - '0'); | |
| if (c >= 'A' && c <= 'F') | |
| return (c - 'A' + 10); | |
| if (c >= 'a' && c <= 'f') | |
| return (c - 'a' + 10); | |
| return 0; | |
| } | |
| void hexString_To_Bytes(char *in, int inLength, char *out) | |
| { | |
| int i; | |
| if (in == NULL || out == NULL) | |
| { | |
| return; | |
| } | |
| for (i = 0 ; i < inLength ; i += 2) | |
| { | |
| out[i/2] = (char)((hexChar_To_Int(in[i]) << 4) | |
| | hexChar_To_Int(in[i+1])); | |
| } | |
| } | |
| /* RFC3629 chapter 4. Syntax of UTF-8 Byte Sequences */ | |
| static kal_int32 is_legal_utf8(const UTF8 *start, kal_int32 len) | |
| { | |
| UTF8 tmp = 0; | |
| const UTF8 *ptr = start + len; | |
| switch (len) { | |
| default: | |
| return FALSE; | |
| case 4: | |
| tmp = *--ptr; | |
| if (tmp < 0x80 || tmp > 0xBF) { | |
| return FALSE; | |
| } | |
| case 3: | |
| tmp = *--ptr; | |
| if (tmp < 0x80 || tmp > 0xBF) { | |
| return FALSE; | |
| } | |
| case 2: | |
| tmp = *--ptr; | |
| if (tmp > 0xBF) { | |
| return FALSE; | |
| } | |
| switch (*start) { | |
| case 0xE0: | |
| if (tmp < 0xA0) { | |
| return FALSE; | |
| } | |
| break; | |
| case 0xED: | |
| if (tmp > 0x9F) { | |
| return FALSE; | |
| } | |
| break; | |
| case 0xF0: | |
| if (tmp < 0x90) { | |
| return FALSE; | |
| } | |
| break; | |
| case 0xF4: | |
| if (tmp > 0x8F) { | |
| return FALSE; | |
| } | |
| break; | |
| default: | |
| if (tmp < 0x80) { | |
| return FALSE; | |
| } | |
| break; | |
| } | |
| case 1: | |
| if (*start >= 0x80 && *start < 0xC2) { | |
| return FALSE; | |
| } | |
| } | |
| if (*start > 0xF4) { | |
| return FALSE; | |
| } | |
| return TRUE; | |
| } | |
| kal_int32 kal_utf16_to_utf8(UTF8 *dest, const UTF16 *src, kal_int32 size) | |
| { | |
| kal_int32 result = STATUS_SUCCESS; | |
| const UTF16 *start = src; | |
| const UTF16 *end = src; | |
| const UTF32 TAIL_MASK = 0xBF; | |
| const UTF32 TAIL_MARK = 0x80; | |
| UTF8 *target = dest; | |
| if (!src) { return STATUS_NULL_POINTER; } | |
| while (*end) { | |
| end++; | |
| } | |
| while (start < end) { | |
| UTF32 tmp = 0; | |
| unsigned long bytes = 0; | |
| tmp = *start++; | |
| //LOGE("tmp = [%X]\n", tmp); | |
| /* */ | |
| if (tmp >= SUR_HIGH_START && tmp <= SUR_HIGH_END) { | |
| if (start < end) { | |
| UTF32 tmp2 = *start; | |
| if (tmp2 >= SUR_LOW_START && tmp2 <= SUR_LOW_END) { | |
| tmp = ((tmp - SUR_HIGH_START) << UTF16_HALF_SHIFT) | |
| + (tmp2 - SUR_LOW_START) + UTF16_HALF_BASE; | |
| start++; | |
| } else { | |
| result = STATUS_ILLEGAL_UTF16; | |
| break; | |
| } | |
| } else { | |
| result = STATUS_MEM_EXHAUSTED; | |
| break; | |
| } | |
| } else if (tmp >= SUR_LOW_START && tmp <= SUR_LOW_END) { | |
| result = STATUS_ILLEGAL_UTF16; | |
| break; | |
| } | |
| if (tmp < (UTF32)0x80) { | |
| bytes = 1; | |
| } else if (tmp < (UTF32)0x800) { | |
| bytes = 2; | |
| } else if (tmp < (UTF32)0x10000) { | |
| bytes = 3; | |
| } else if (tmp < (UTF32)0x110000) { | |
| bytes = 4; | |
| } else { | |
| result = STATUS_ILLEGAL_UTF16; | |
| break; | |
| } | |
| if (target && size > 0) { | |
| size -= bytes; | |
| if (0 >= size) { | |
| break; | |
| } | |
| switch (bytes) { | |
| case 4: | |
| *(target + 3) = (UTF8)((tmp | TAIL_MARK) & TAIL_MASK); | |
| tmp >>= 6; | |
| case 3: | |
| *(target + 2) = (UTF8)((tmp | TAIL_MARK) & TAIL_MASK); | |
| tmp >>= 6; | |
| case 2: | |
| *(target + 1) = (UTF8)((tmp | TAIL_MARK) & TAIL_MASK); | |
| tmp >>= 6; | |
| case 1: | |
| *target = (UTF8)(tmp | first_byte_mark[bytes]); | |
| } | |
| target += bytes; | |
| } | |
| result += bytes; | |
| } | |
| if (target) | |
| *target = 0; | |
| return result; | |
| } | |
| kal_int32 kal_ext_ascii_to_utf8(UTF8 *dest, const kal_uint8 *src, kal_int32 size) | |
| { | |
| kal_int32 result = STATUS_SUCCESS; | |
| const kal_uint8 *start = src, *end = src; | |
| const UTF32 TAIL_MASK = 0xBF; | |
| const UTF32 TAIL_MARK = 0x80; | |
| UTF8 *target = dest; | |
| if (!src) { return STATUS_NULL_POINTER; } | |
| while (*end) { | |
| end++; | |
| } | |
| while (start < end) { | |
| UTF32 tmp = 0; | |
| unsigned long bytes = 0; | |
| tmp = *start++; | |
| if (tmp < (UTF32)0x80) { | |
| bytes = 1; | |
| } else { | |
| bytes = 2; | |
| } | |
| if (target && size > 0) { | |
| size -= bytes; | |
| if (size <= 0) { | |
| break; | |
| } | |
| switch (bytes) { | |
| case 2: | |
| *(target + 1) = (UTF8)((tmp | TAIL_MARK) & TAIL_MASK); | |
| tmp >>= 6; | |
| case 1: | |
| *target = (UTF8)(tmp | first_byte_mark[bytes]); | |
| } | |
| target += bytes; | |
| } | |
| result += bytes; | |
| } | |
| if (target) { | |
| *target = 0; | |
| } | |
| return result; | |
| } | |
| kal_int32 kal_utf8_to_utf16(UTF16 *dest, | |
| const UTF8 *src, | |
| kal_int32 size) | |
| { | |
| kal_int32 result = STATUS_SUCCESS; | |
| const UTF8 *start = src; | |
| const UTF8 *end = src; | |
| UTF16 *target = dest; | |
| while(*end) { | |
| end++; | |
| } | |
| while (start < end) { | |
| unsigned long tmp = 0; | |
| unsigned int extra_bytes = utf8_tailing_bytes[*start]; | |
| //UTF8 *next = start + extra_bytes + 1; | |
| if (target && target >= dest + size) { | |
| result = STATUS_MEM_EXHAUSTED; | |
| break; | |
| } | |
| if (start + extra_bytes >= end) { | |
| result = STATUS_MEM_EXHAUSTED; | |
| break; | |
| } | |
| if (!is_legal_utf8(start, extra_bytes + 1)) { | |
| result = STATUS_ILLEGAL_UTF8; | |
| break; | |
| } | |
| switch (extra_bytes) { | |
| case 5: | |
| tmp += *start++; | |
| tmp <<= 6; /* illegal UTF8 */ | |
| case 4: | |
| tmp += *start++; | |
| tmp <<= 6; /* illegal UTF8 */ | |
| case 3: | |
| tmp += *start++; | |
| tmp <<= 6; | |
| case 2: | |
| tmp += *start++; | |
| tmp <<= 6; | |
| case 1: | |
| tmp += *start++; | |
| tmp <<= 6; | |
| case 0: | |
| tmp += *start++; | |
| } | |
| tmp -= utf8_offsets[extra_bytes]; | |
| if (tmp <= MAX_UNI_BMP) { | |
| if (tmp >= SUR_HIGH_START && tmp <= SUR_LOW_END) { | |
| result = STATUS_ILLEGAL_UTF8; | |
| break; | |
| } else { | |
| if (target) { | |
| *target++ = (UTF16)tmp; | |
| } | |
| result++; | |
| } | |
| } else if (tmp > MAX_UTF16) { | |
| result = STATUS_ILLEGAL_UTF8; | |
| break; | |
| } else { | |
| if (target && target + 1 >= dest + size) { | |
| result = STATUS_MEM_EXHAUSTED; | |
| break; | |
| } | |
| tmp -= UTF16_HALF_BASE; | |
| if (target) { | |
| *target++ = (UTF16)((tmp >> UTF16_HALF_SHIFT) + SUR_HIGH_START); | |
| *target++ = (UTF16)((tmp & UTF16_HALF_MASK) + SUR_LOW_START); | |
| } | |
| result += 2; | |
| } | |
| } | |
| if (target) { | |
| *target = 0; | |
| } | |
| return result; | |
| } | |
| static kal_int32 _mdapi_sms_set_timestamp(mdapi_sms_record_t *sms) | |
| { | |
| struct tm *p; | |
| kal_int32 y = 0; | |
| struct timeval tv; | |
| struct timezone tz; | |
| gettimeofday (&tv, &tz); | |
| sms->time[6] = tz.tz_minuteswest; | |
| p = localtime(&tv.tv_sec); | |
| y = 1900 + p->tm_year; | |
| sms->time[0] = y % 100; | |
| sms->time[1] = 1 + p->tm_mon; | |
| sms->time[2] = p->tm_mday; | |
| sms->time[3] = p->tm_hour; | |
| sms->time[4] = p->tm_min; | |
| sms->time[5] = p->tm_sec; | |
| LOGE("sms time: %d-%02d-%02d %02d:%02d:%02d\n", y, sms->time[1],sms->time[2],sms->time[3],sms->time[4], sms->time[5]); | |
| LOGE("timezone = %d\n", sms->time[6]); | |
| return MDAPI_RET_SUCCESS; | |
| } | |
| kal_uint8 lookup_latin1_to_gsm_ex_table(kal_int8 character) | |
| { | |
| int i; | |
| for( i=0; latin1_to_gsm_tableEx[i].symbol != 0; i++) { | |
| if (character == latin1_to_gsm_tableEx[i].symbol) | |
| return latin1_to_gsm_tableEx[i].value; | |
| } | |
| return 255; | |
| } | |
| void _smsbuf_byte_align(smsbuf_t *buf) | |
| { | |
| if (buf->curbyte > buf->finalbyte) { | |
| return; | |
| } | |
| if (buf->curbit != 0) { | |
| buf->curbit = 0; | |
| buf->curbyte++; | |
| } | |
| } | |
| void _smsbuf_init(smsbuf_t *buf) | |
| { | |
| buf->curbyte = buf->smsbuf; | |
| buf->curbit = 0; | |
| memset(buf->smsbuf, 0, sizeof(buf->smsbuf)); | |
| buf->finalbyte = buf->curbyte + sizeof(buf->smsbuf); | |
| } | |
| void _smsbuf_set1bit(smsbuf_t *buf, kal_uint8 b) | |
| { | |
| if (buf->curbyte > buf->finalbyte) | |
| return; | |
| if (b != 0) | |
| *buf->curbyte |= (1 << buf->curbit); | |
| buf->curbit++; | |
| if (buf->curbit == 8) { | |
| buf->curbit = 0; | |
| buf->curbyte++; | |
| } | |
| } | |
| void _smsbuf_set_multi_bits(smsbuf_t *buf, kal_uint32 value, kal_uint8 bit_num) | |
| { | |
| kal_int32 i = 0; | |
| for (i = 0; i < bit_num; i++) { | |
| _smsbuf_set1bit(buf, (value & (1 << i)) != 0); | |
| } | |
| } | |
| void _smsbuf_set_octet(smsbuf_t *buf, kal_uint8 c) | |
| { | |
| _smsbuf_byte_align(buf); | |
| *(buf->curbyte) = c; | |
| buf->curbyte++; | |
| } | |
| void _smsbuf_septet_align(smsbuf_t *buf) | |
| { | |
| if (buf->curbyte > buf->finalbyte) | |
| return; | |
| while (((buf->curbyte - buf->septet_start) * 8 + buf->curbit) % 7 != 0) | |
| _smsbuf_set1bit(buf, 0); | |
| } | |
| void _smsbuf_set_septet_start(smsbuf_t *buf) | |
| { | |
| _smsbuf_byte_align(buf); | |
| buf->septet_start = buf->curbyte; | |
| } | |
| void _smsbuf_set_string(smsbuf_t *buf, kal_int8 *str, kal_int32 size) | |
| { | |
| kal_int32 i = 0; | |
| _smsbuf_septet_align(buf); | |
| //LOGE("%s, %s, %d. string is:[%s],size is:[%d]", __FILE__, __FUNCTION__, __LINE__, (char*)str, size); | |
| while (*str && size) { | |
| /* change the iso8859latin1 charactor to gsm support charactor */ | |
| //LOGE("%s, %s, %d. character is:[%d]-[0x%x]", __FILE__, __FUNCTION__, __LINE__, (int)*str,*str); | |
| kal_uint8 c = lookup_latin1_to_gsm_ex_table(*str); | |
| if(c != 255) | |
| { | |
| //LOGE("extent table!"); | |
| for (i = 0; i < 7; i++) { | |
| _smsbuf_set1bit(buf, ((1 << i) & 0x1b) != 0); | |
| } | |
| size--; | |
| } else { | |
| c = latin1_to_gsm_table[(kal_uint8)*str]; | |
| } | |
| //LOGE("%s, %s, %d. character is:[%d]-[0x%x]", __FILE__, __FUNCTION__, __LINE__, (int)c,c); | |
| str++; | |
| size--; | |
| for (i = 0; i < 7; i++) { | |
| _smsbuf_set1bit(buf, ((1 << i) & c) != 0); | |
| //LOGE(KAL_LOG_INFO, LOG_TAG, "curbit = [%d] curbyte=[%X]", buf->curbit, *buf->curbyte); | |
| } | |
| //LOGE(KAL_LOG_INFO, LOG_TAG, "size = [%d] c = [%c]", size, c); | |
| } | |
| } | |
| void _smsbuf_set_addr(smsbuf_t *buf, kal_int8 *str) | |
| { | |
| _smsbuf_byte_align(buf); | |
| while (*str) { | |
| kal_uint8 c = *str; | |
| if (*str == '*') { | |
| c = 0xa; | |
| } else if (*str == '#') { | |
| c = 0xb; | |
| } else if (*str == 'p') { | |
| c = 0xc; | |
| } else if (*str == 'w') { | |
| c = 0xd; | |
| } else if (*str == '+') { | |
| c = 0xe; | |
| } else { | |
| c = *str - '0'; | |
| } | |
| if (buf->curbit == 0) { | |
| *buf->curbyte = c; | |
| buf->curbit = 4; | |
| } else { | |
| *buf->curbyte |= (c << 4); | |
| buf->curbyte++; | |
| buf->curbit = 0; | |
| } | |
| str++; | |
| } | |
| if (buf->curbit == 4) { | |
| *buf->curbyte |= 0xF0; | |
| buf->curbyte++; | |
| buf->curbit = 0; | |
| } | |
| } | |
| kal_int32 _smsbuf_hex_string(smsbuf_t *buf, kal_int8 *output, kal_int32 size) | |
| { | |
| kal_int32 len = 0; | |
| kal_uint8 *str = buf->smsbuf; | |
| _smsbuf_byte_align(buf); | |
| while (str != buf->curbyte && (size - len) > 3) { | |
| len += snprintf(output + len, size - len, "%02X", *str); | |
| str++; | |
| } | |
| return len; | |
| } | |
| kal_int32 _mdapi_sms_get_msg_num(const char *msg, int charset, kal_int32 *msg_num, kal_int32 *msg_len) | |
| { | |
| LOGE("%s, %s, %d, send sms content = [%s]",__FILE__, __FUNCTION__, __LINE__, msg); | |
| *msg_num = 0; | |
| *msg_len = 0; | |
| kal_int32 max_len = 0; | |
| if (charset == MDAPI_SMS_CHARSET_GSM_7BIT) { | |
| *msg_len = strlen(msg); | |
| //special char | |
| kal_int32 extenSize =0; | |
| kal_char* point = (kal_char*)msg; | |
| kal_int32 size = *msg_len; | |
| while (*point && size) { | |
| kal_uint8 c = lookup_latin1_to_gsm_ex_table((kal_int8)*point); | |
| if(c != 255) | |
| extenSize++; | |
| point++; | |
| size--; | |
| } | |
| //special char | |
| if (*msg_len + extenSize > 160) { | |
| *msg_num = (*msg_len + extenSize + MAX_7BIT_MSG_LEN - 1) / MAX_7BIT_MSG_LEN; | |
| max_len = MAX_7BIT_MSG_LEN; | |
| } else { | |
| *msg_num = 1; | |
| } | |
| if (*msg_num > MAX_CONCATENATED_MSG) { | |
| LOGE("message is too long. msg_len[%d], msg_num[%d], max_len[%d]", *msg_len, *msg_num, max_len); | |
| return MDAPI_RET_ERROR; | |
| } | |
| LOGE("%s, %s, %d, 7bit msg_len = [%d] ,msg_num=[%d]", __FILE__, __FUNCTION__, __LINE__, *msg_len, *msg_num); | |
| } else if (charset == MDAPI_SMS_CHARSET_UCS2) { | |
| //UTF16 *dest = NULL; | |
| *msg_len = kal_utf8_to_utf16(NULL, (const UTF8 *)msg, 0); | |
| if (*msg_len > 70) { | |
| *msg_num = (*msg_len + MAX_UCS2_MSG_LEN - 1) / MAX_UCS2_MSG_LEN; | |
| max_len = MAX_UCS2_MSG_LEN * 2; | |
| } else { | |
| *msg_num = 1; | |
| } | |
| if (*msg_num > MAX_CONCATENATED_MSG) { | |
| LOGE("message is too long. msg_len[%d], msg_num[%d], max_len[%d]", msg_len, msg_num, max_len); | |
| return MDAPI_RET_ERROR; | |
| } | |
| } else if (charset == MDAPI_SMS_CHARSET_GSM_8BIT) { | |
| *msg_len = strlen(msg); | |
| if(*msg_len > (140 * 2)) | |
| { | |
| *msg_num = (*msg_len + MAX_8BIT_MSG_LEN - 1) / MAX_8BIT_MSG_LEN; | |
| max_len = MAX_8BIT_MSG_LEN; | |
| if (*msg_num > MAX_CONCATENATED_MSG) { | |
| LOGE("message is too long. msg_len[%d], msg_num[%d], max_len[%d]", *msg_len, *msg_num, max_len); | |
| return MDAPI_RET_ERROR; | |
| } | |
| } | |
| else { | |
| *msg_num = 1; | |
| } | |
| } else{ | |
| LOGE("Not support charset"); | |
| return MDAPI_RET_ERROR; | |
| } | |
| return MDAPI_RET_SUCCESS; | |
| } | |
| kal_int32 _mdapi_sms_encode_addr(smsbuf_t *buf, kal_int8 *smsc, kal_int32 type) | |
| { | |
| kal_int32 len = strlen(smsc); | |
| kal_int8 *str = smsc; | |
| kal_uint8 addr_plane = SMS_NP_ISDNTEL; | |
| kal_uint8 addr_type = SMS_TON_UNKNOWN; | |
| if (len <= 0) { | |
| /* use default sca for sms message */ | |
| _smsbuf_set_octet(buf, 0); | |
| return 1;; | |
| } | |
| if (len > 255) { | |
| LOGE("input number is too long. len[%d] smsc[%s] ", len, smsc); | |
| return 0; | |
| } | |
| /* check the type of address */ | |
| while (*str) { | |
| if (!isdigit(*str) && *str != '+' && *str != '*' | |
| && *str != '#' && *str != 'p' && *str != 'w') | |
| addr_type = SMS_TON_ALPHANUMERIC; | |
| str++; | |
| } | |
| if (smsc[0] == '+' && addr_type != SMS_TON_ALPHANUMERIC) { | |
| addr_type = SMS_TON_INTERNATIONAL; | |
| /* */ | |
| str = &smsc[1]; | |
| len--; | |
| } else { | |
| str = smsc; | |
| } | |
| /* set len */ | |
| if (type == SMS_ENCODE_SCA) | |
| _smsbuf_set_octet(buf, len / 2 + len % 2 + 1); | |
| else { | |
| _smsbuf_set_octet(buf, len); | |
| } | |
| LOGE("%02X, %d ", *(buf->curbyte), buf->curbyte - buf->smsbuf); | |
| _smsbuf_set_multi_bits(buf, addr_plane, 4); | |
| _smsbuf_set_multi_bits(buf, addr_type, 3); | |
| _smsbuf_set1bit(buf, 1); | |
| LOGE("%02X, %d ", *(buf->curbyte), buf->curbyte - buf->smsbuf); | |
| if (addr_type == SMS_TON_ALPHANUMERIC) { | |
| _smsbuf_set_septet_start(buf); | |
| _smsbuf_set_string(buf, str, len); | |
| } else { | |
| _smsbuf_set_addr(buf, str); | |
| } | |
| _smsbuf_byte_align(buf); | |
| return buf->curbyte - buf->smsbuf; | |
| } | |
| kal_int32 _mdapi_sms_encode_pdu(mdapi_sms_record_t *sms, | |
| kal_int8 *smsc, | |
| mdapi_sms_settings_t *settings, | |
| kal_char *start, | |
| kal_int32 send_size, | |
| kal_uint8 *udh, | |
| kal_char *output, | |
| kal_int32 out_len, | |
| kal_int32 *sca_out_len) | |
| { | |
| smsbuf_t smsbuf; | |
| kal_int32 udh_len = 0; | |
| kal_int32 len = 0; | |
| kal_int32 sca_len = 0; | |
| if (udh) { | |
| udh_len = udh[0]; | |
| } else { | |
| udh_len = 0; | |
| } | |
| memset(&smsbuf, 0, sizeof(smsbuf)); | |
| _smsbuf_init(&smsbuf); | |
| /* SMSC */ | |
| sca_len = _mdapi_sms_encode_addr(&smsbuf, smsc, SMS_ENCODE_SCA); | |
| /* Encode PDU Type */ | |
| { | |
| _smsbuf_byte_align(&smsbuf); | |
| /* Message Type Indicator */ | |
| _smsbuf_set_multi_bits(&smsbuf, SMS_SUBMIT, 2); | |
| //LOGE(KAL_LOG_INFO, LOG_TAG, "curbit = [%d] curbyte=[%02X]", smsbuf.curbit, *smsbuf.curbyte); | |
| /* Reject Duplicate */ | |
| _smsbuf_set1bit(&smsbuf, 0); | |
| //LOGE(KAL_LOG_INFO, LOG_TAG, "curbit = [%d] curbyte=[%02X]", smsbuf.curbit, *smsbuf.curbyte); | |
| /* Validity Period Format */ | |
| _smsbuf_set_multi_bits(&smsbuf, settings->vpf, 2); | |
| //LOGE(KAL_LOG_INFO, LOG_TAG, "curbit = [%d] curbyte=[%02X]", smsbuf.curbit, *smsbuf.curbyte); | |
| /* Status Report Request */ | |
| if (settings->srr) | |
| _smsbuf_set1bit(&smsbuf, 1); | |
| else | |
| _smsbuf_set1bit(&smsbuf, 0); | |
| //LOGE(KAL_LOG_INFO, LOG_TAG, "curbit = [%d] curbyte=[%02X]", smsbuf.curbit, *smsbuf.curbyte); | |
| /* User Data Header Indicator */ | |
| if (udh_len) | |
| _smsbuf_set1bit(&smsbuf, 1); | |
| else | |
| _smsbuf_set1bit(&smsbuf, 0); | |
| //LOGE(KAL_LOG_INFO, LOG_TAG, "curbit = [%d] curbyte=[%02X]", smsbuf.curbit, *smsbuf.curbyte); | |
| /* Replay Path */ | |
| _smsbuf_set1bit(&smsbuf, settings->rp); | |
| //LOGE(KAL_LOG_INFO, LOG_TAG, "curbit = [%d] curbyte=[%02X]", smsbuf.curbit, *smsbuf.curbyte); | |
| } | |
| /* Encode MR */ | |
| { | |
| /* Message Reference Count, Long Message should use this */ | |
| _smsbuf_set_octet(&smsbuf, 0); | |
| } | |
| /* Encode OA/DA */ | |
| _mdapi_sms_encode_addr(&smsbuf, sms->phone_number, SMS_ENCODE_OADA); | |
| /* Encode Protocol Identifier */ | |
| _smsbuf_set_octet(&smsbuf, 0x00); | |
| /* Encode DCS */ | |
| { | |
| /* Bit 0,1, Class */ | |
| _smsbuf_set_multi_bits(&smsbuf, sms->sms_class, 2); | |
| /* Bit 2,3, Class */ | |
| _smsbuf_set_multi_bits(&smsbuf, sms->charset, 2); | |
| /* Bit 4 */ | |
| _smsbuf_set1bit(&smsbuf, 0); | |
| /* Bit 5 */ | |
| /* No text compressed */ | |
| _smsbuf_set1bit(&smsbuf, 0); | |
| /* Bit 6, 7 */ | |
| _smsbuf_set_multi_bits(&smsbuf, 0, 0); | |
| } | |
| //_smsbuf_byte_align(&smsbuf); | |
| /* Validity Period */ | |
| { | |
| if (settings->vpf == SMS_VPF_ABSOLUTE) { | |
| // TODO: add absolute validity period | |
| } else if (settings->vpf == SMS_VPF_RELATIVE) { | |
| // TODO: add validity period support | |
| kal_uint8 validity_period = 0xAA; | |
| _smsbuf_set_octet(&smsbuf, validity_period); | |
| } | |
| } | |
| /* User Data Header */ | |
| { | |
| if (udh_len) { | |
| kal_int32 i = 0; | |
| if (sms->charset == MDAPI_SMS_CHARSET_UCS2) { | |
| _smsbuf_set_octet(&smsbuf, 1 + udh_len + send_size); | |
| } else if (sms->charset == MDAPI_SMS_CHARSET_GSM_7BIT) { | |
| _smsbuf_set_octet(&smsbuf, (((1 + udh_len) * 8 + 6) / 7) + send_size); | |
| } else if (sms->charset == MDAPI_SMS_CHARSET_GSM_8BIT) { | |
| _smsbuf_set_octet(&smsbuf, 1 + udh_len + send_size/2); | |
| } | |
| /* set the start byte of septet(7bits) align */ | |
| _smsbuf_set_septet_start(&smsbuf); | |
| for (i = 0; i < udh_len + 1; i++) { | |
| _smsbuf_set_octet(&smsbuf, udh[i]); | |
| } | |
| } else { | |
| if(sms->charset == MDAPI_SMS_CHARSET_GSM_8BIT) | |
| { | |
| _smsbuf_set_octet(&smsbuf, send_size/2); | |
| } | |
| else | |
| { | |
| _smsbuf_set_octet(&smsbuf, send_size); | |
| } | |
| /* set the start byte of septet(7bits) align */ | |
| _smsbuf_set_septet_start(&smsbuf); | |
| } | |
| } | |
| /* Get the Hex String */ | |
| len = _smsbuf_hex_string(&smsbuf, output, out_len); | |
| LOGE("encoded pdu = (%s), len = (%d) ", output, len); | |
| /* Set User Data */ | |
| if (sms->charset == MDAPI_SMS_CHARSET_GSM_7BIT) { | |
| //_sms_iso8859latin1_to_gsm(start, gsm, *size + 1); | |
| _smsbuf_set_string(&smsbuf, start, send_size); | |
| } else if(sms->charset == MDAPI_SMS_CHARSET_GSM_8BIT) { | |
| kal_int32 i = 0; | |
| char outhex[MAX_PDU_SIZE] = {0}; | |
| hexString_To_Bytes(start, send_size, outhex); | |
| for (i = 0; i < send_size/2; i++) { | |
| _smsbuf_set_octet(&smsbuf, outhex[i]); | |
| } | |
| } else { | |
| kal_int32 i = 0; | |
| for (i = 0; i < send_size; i += 2) { | |
| kal_uint16 tmp = 0; | |
| kal_uint8 *ptr = (kal_uint8 *)&tmp; | |
| *ptr = *(start + i); | |
| *(ptr + 1) = *(start + i + 1); | |
| tmp = htons(tmp); | |
| _smsbuf_set_octet(&smsbuf, *(ptr)); | |
| _smsbuf_set_octet(&smsbuf, *(ptr + 1)); | |
| } | |
| } | |
| /* Get the Hex String */ | |
| len = _smsbuf_hex_string(&smsbuf, output, out_len); | |
| *sca_out_len = sca_len * 2; | |
| LOGE("start = [%p] size = [%d] encoded pdu = (%s), len = (%d)", start, send_size, output, len); | |
| return len; | |
| } | |
| int smsPduEncode(const char *smsc, const char *da_num, const char *msg, int charset, | |
| char *smsc_pdu, char **pdu) | |
| { | |
| mdapi_sms_record_t record; | |
| mdapi_sms_settings_t sms_settings; | |
| //kal_int32 status = MDAPI_RET_ERROR; | |
| kal_int32 msg_num = 0; | |
| kal_int32 msg_len = 0; | |
| kal_int32 max_len = 0; | |
| kal_char *msg_content = NULL; | |
| kal_int32 out_len = 0; | |
| kal_int8 output[MAX_PDU_SIZE] = {0}; | |
| kal_int32 sca_out_len; | |
| mdapi_sms_record_t *sms = &record; | |
| memset(sms, 0, sizeof(mdapi_sms_record_t)); | |
| snprintf(sms->phone_number, sizeof(sms->phone_number), "%s", da_num); | |
| sms->msg_content = (kal_char *)msg; | |
| sms->charset = charset; | |
| sms_settings.rd = 1; | |
| sms_settings.vpf = SMS_VPF_RELATIVE; | |
| sms_settings.srr = 1; | |
| sms_settings.rp = 0; | |
| sms_settings.validity_period = 0; | |
| // status = _mdapi_sms_get_msg_num(msg, charset, &msg_num, &msg_len); | |
| /*if (sms->charset == MDAPI_SMS_CHARSET_GSM_7BIT) { | |
| msg_content = sms->msg_content; | |
| } else if (sms->charset == MDAPI_SMS_CHARSET_UCS2) { | |
| UTF16 *dest = NULL; | |
| msg_content = (kal_char *)malloc((msg_len + 1) * sizeof(UTF16)); | |
| dest = (UTF16 *)msg_content; | |
| msg_len = kal_utf8_to_utf16(dest, (const UTF8 *)sms->msg_content, (msg_len + 1) * sizeof(UTF16)); | |
| if (msg_len <= 0) { | |
| free(msg_content); | |
| msg_content = NULL; | |
| return MDAPI_RET_ERROR; | |
| } | |
| msg_len *= 2; | |
| LOGE("ucs2 msg_len = [%d] ,msg_num=[%d] ", msg_len,msg_num); | |
| }else { | |
| LOGE("Not support charset"); | |
| return MDAPI_RET_ERROR; | |
| }*/ | |
| if (sms->charset == MDAPI_SMS_CHARSET_GSM_7BIT) { | |
| msg_len = strlen(sms->msg_content); | |
| //for special char | |
| kal_int32 extenTotalSize =0; | |
| //kal_int32 i = 0; | |
| kal_char* point = sms->msg_content; | |
| LOGE("XXX msg len %d \n",msg_len); | |
| kal_int32 size = msg_len; | |
| while (*point && size) { | |
| kal_uint8 c = lookup_latin1_to_gsm_ex_table((kal_int8)*point); | |
| if(c != 255){ | |
| extenTotalSize++; | |
| } | |
| point++; | |
| size--; | |
| } | |
| //for specail char | |
| msg_len += extenTotalSize; | |
| LOGE("XXX msg_len %d extenTotalSize %d \n",msg_len,extenTotalSize); | |
| if (msg_len > 160) { | |
| msg_num = (msg_len + MAX_7BIT_MSG_LEN - 1) / MAX_7BIT_MSG_LEN; | |
| max_len = MAX_7BIT_MSG_LEN; | |
| } else { | |
| msg_num = 1; | |
| } | |
| if (msg_num > MAX_CONCATENATED_MSG) { | |
| LOGE("message is too long. msg_len[%d], msg_num[%d]", msg_len, msg_num); | |
| return MDAPI_RET_ERROR; | |
| } | |
| LOGE("7bit msg_len = [%d] ,msg_num=[%d]", msg_len,msg_num); | |
| msg_content = sms->msg_content; | |
| } else if (sms->charset == MDAPI_SMS_CHARSET_UCS2) { | |
| UTF16 *dest = NULL; | |
| msg_len = kal_utf8_to_utf16(NULL, (const UTF8 *)sms->msg_content, 0); | |
| if (msg_len > 70) { | |
| msg_num = (msg_len + MAX_UCS2_MSG_LEN - 1) / MAX_UCS2_MSG_LEN; | |
| max_len = MAX_UCS2_MSG_LEN * 2; | |
| } else { | |
| msg_num = 1; | |
| } | |
| if (msg_num > MAX_CONCATENATED_MSG) { | |
| LOGE("message is too long. msg_len[%d], msg_num[%d]", msg_len, msg_num); | |
| return MDAPI_RET_ERROR; | |
| } | |
| msg_content = (kal_char *)malloc((msg_len + 1) * sizeof(UTF16)); | |
| dest = (UTF16 *)msg_content; | |
| msg_len = kal_utf8_to_utf16(dest, (const UTF8 *)sms->msg_content, (msg_len + 1) * sizeof(UTF16)); | |
| if (msg_len <= 0) { | |
| free(msg_content); | |
| msg_content = NULL; | |
| return MDAPI_RET_ERROR; | |
| } | |
| msg_len *= 2; | |
| LOGE("ucs2 msg_len = [%d] ,msg_num=[%d] ", msg_len,msg_num); | |
| } else if (sms->charset == MDAPI_SMS_CHARSET_GSM_8BIT) { | |
| msg_len = strlen(sms->msg_content); | |
| msg_content = sms->msg_content; | |
| if (msg_len > (140 * 2)) { | |
| msg_num = (msg_len + MAX_8BIT_MSG_LEN - 1) / MAX_8BIT_MSG_LEN; | |
| max_len = MAX_8BIT_MSG_LEN; | |
| } else { | |
| msg_num = 1; | |
| } | |
| if (msg_num > MAX_CONCATENATED_MSG) { | |
| LOGE("message is too long. msg_len[%d], msg_num[%d]", msg_len, msg_num); | |
| return MDAPI_RET_ERROR; | |
| } | |
| LOGE("8bit msg_len = [%d] ,msg_num=[%d] ", msg_len,msg_num); | |
| }else { | |
| LOGE("Not support charset"); | |
| return MDAPI_RET_ERROR; | |
| } | |
| // set sms record | |
| _mdapi_sms_set_timestamp(sms); | |
| if (msg_num == 1) { | |
| out_len = _mdapi_sms_encode_pdu(sms, (kal_int8 *)smsc, &sms_settings, msg_content, msg_len, NULL, output, sizeof(output), &sca_out_len); | |
| memcpy(smsc_pdu, output, sca_out_len); | |
| //LOGE("%s, %s, %d, returned encoded smsc_pdu:%s", __FILE__, __FUNCTION__, __LINE__, smsc_pdu); | |
| //LOGE("%s, %s, %d, output + sca_out_len:%s, out_len - sca_out_len: %d", __FILE__, __FUNCTION__, __LINE__, output + sca_out_len, out_len - sca_out_len); | |
| //LOGE("%s, %s, %d, pdu:%s sizeof(pdu[0])=%d", __FILE__, __FUNCTION__, __LINE__, pdu[0], sizeof(pdu[0])); | |
| memset(pdu[0], 0, MAX_PDU_SIZE); | |
| LOGE("%s, %s, %d, pdu:%s", __FILE__, __FUNCTION__, __LINE__, pdu[0]); | |
| strncpy(pdu[0], output + sca_out_len, out_len - sca_out_len); | |
| LOGE("%s, %s, %d, returned encoded pdu:%s\n, len=%d", __FILE__, __FUNCTION__, __LINE__, pdu[0], strlen(pdu[0])); | |
| } else { | |
| // send long sms | |
| kal_int32 index = 0; | |
| kal_int32 offset = 0; | |
| static kal_uint8 concat_msgid; | |
| concat_msgid += (rand() + 1) % 256; | |
| LOGE("start send one long msg, total has %d part msg", msg_num); | |
| for (index = 0; index < msg_num; index++) { | |
| kal_uint8 udh[] = {5, 0, 3, concat_msgid, msg_num, index + 1}; | |
| kal_uint32 size = 0; | |
| kal_int8 *start = NULL; | |
| size = msg_len > max_len ? max_len : msg_len; | |
| msg_len -= size; | |
| start = msg_content + offset; | |
| int exterSize = 0; | |
| if (sms->charset == MDAPI_SMS_CHARSET_GSM_7BIT){ | |
| char* point = start; | |
| int calsize = size; | |
| while (*point && calsize) { | |
| kal_uint8 c = lookup_latin1_to_gsm_ex_table((kal_int8)*point); | |
| if(c != 255){ | |
| exterSize++; | |
| calsize--; | |
| } | |
| point++; | |
| calsize--; | |
| } | |
| } | |
| offset = offset + size - exterSize; | |
| //calculate offset | |
| LOGE(" msg_len %d size %d offset %d exterSize %d", msg_len,size ,offset,exterSize); | |
| out_len = _mdapi_sms_encode_pdu(sms, (kal_int8 *)smsc, &sms_settings, start, size, udh, output, sizeof(output), &sca_out_len); | |
| memcpy(smsc_pdu, output, sca_out_len); | |
| memset(pdu[index], 0, MAX_PDU_SIZE); | |
| memcpy(pdu[index], output + sca_out_len, out_len - sca_out_len); | |
| } | |
| } | |
| if (sms->charset == MDAPI_SMS_CHARSET_UCS2) { | |
| if(msg_content != NULL) | |
| free(msg_content); | |
| } | |
| return MDAPI_RET_SUCCESS; | |
| } | |
| //decode | |
| static unsigned char | |
| internal_mdapi_hex2int(char *s) { | |
| int ret = 0; | |
| int len = 2, i = 0; | |
| while (i < len) { | |
| if (s[i] == 0) { | |
| return -1; | |
| } else if (s[i] >= 'a' && s[i] <= 'f') { | |
| ret = (s[i] - 'a' + 10) + (ret << 4); | |
| } else if (s[i] >= 'A' && s[i] <= 'F') { | |
| ret = (s[i] - 'A' + 10) + (ret << 4); | |
| } else if (s[i] >= '0' && s[i] <= '9') { | |
| ret = (s[i] - '0') + (ret << 4); | |
| } else { | |
| return -1; | |
| } | |
| i++; | |
| } | |
| return ret; | |
| } | |
| int internal_mdapi_sms_7bit_decode(char * message, char * output, int output_size, int padding_bits, int octect) | |
| { | |
| int i = 0, len = 0; | |
| char * ptr = message; | |
| int output_len = 0; | |
| int cur_val = 0; | |
| int val = 0; | |
| int last_val = 0;//used to save last 1 octet | |
| int offset; | |
| if( padding_bits < 0||padding_bits > 6 ) | |
| { | |
| return 0; | |
| } | |
| //Calc how many octets are there | |
| len = strlen(message) >> 1; | |
| for(i = 0; i < len - 1; i++){ | |
| offset = i % 0x7; | |
| //Add padding bit, realign to septets. | |
| cur_val = ((internal_mdapi_hex2int(ptr)>>padding_bits)&0xFF)+((internal_mdapi_hex2int(ptr+2)<<(8-padding_bits))&0xFF); | |
| val = ((cur_val << offset) & 0x7F)+((last_val >> (8 - offset))&0xFF); | |
| last_val = cur_val; | |
| //printf("val raw = 0x%X, val = 0x%X\n", val, gsm_to_latin1_table[(kal_uint8)(val & 0xFF)]); | |
| output[output_len++] = (char)gsm_to_latin1_table[(kal_uint8)(val & 0xFF)]; | |
| if (output_len == output_size - 1) { | |
| output[output_len] = 0; | |
| return output_len; | |
| } | |
| if(offset == 6){ | |
| val = ((cur_val>>1)&0x7F) ; | |
| //printf("val raw = 0x%X, val = 0x%X\n", val, gsm_to_latin1_table[(kal_uint8)(val & 0xFF)]); | |
| output[output_len++] = (char)gsm_to_latin1_table[(kal_uint8)(val & 0xFF)]; | |
| if (output_len == output_size - 1) { | |
| output[output_len] = 0; | |
| return output_len; | |
| } | |
| } | |
| ptr += 2; | |
| } | |
| /* decode the last octet */ | |
| cur_val = (internal_mdapi_hex2int(ptr) >> padding_bits) & 0xFF; | |
| offset = i % 7; | |
| val = ((cur_val << offset) & 0x7F)+((last_val >> (8 - offset))&0xFF); | |
| //printf("val raw = 0x%X, val = 0x%X\n", val, gsm_to_latin1_table[(kal_uint8)(val & 0xFF)]); | |
| output[output_len++] = (char)gsm_to_latin1_table[(kal_uint8)(val & 0xFF)]; | |
| if (output_len == output_size - 1) { | |
| output[output_len] = 0; | |
| return output_len; | |
| } | |
| //printf("output = [%s], output_len = [%d]\n", output, output_len); | |
| if(offset == 6){ | |
| val = ((cur_val >> 1) & 0x7F); | |
| //printf("val raw = 0x%X, val = 0x%X\n", val, gsm_to_latin1_table[(kal_uint8)(val & 0xFF)]); | |
| if (val || octect) { | |
| output[output_len++] = (char)gsm_to_latin1_table[(kal_uint8)(val & 0xFF)]; | |
| if (output_len == output_size - 1) { | |
| output[output_len] = 0; | |
| return output_len; | |
| } | |
| } | |
| } | |
| output[output_len] = 0; | |
| return output_len; | |
| } | |
| int internal_mdapi_address_decode(char *number, char *output, int output_size, int type) { | |
| // 81 90 21 43 65 87 --> 0912345678 | |
| LOGE("%s, %s, %d", __FILE__, __FUNCTION__, __LINE__); | |
| int len = 0; | |
| int output_len = 0; | |
| int val = 0; | |
| char *ptr = number; | |
| int padding_bit = 0;//To identify the number is even or odd | |
| //LOGE("before internal_mdapi_hex2int(ptr), ptr :%s",ptr); | |
| // Length | |
| len = internal_mdapi_hex2int(ptr); | |
| //LOGE("after internal_mdapi_hex2int(ptr), ptr :%s",ptr); | |
| ptr += 2; | |
| //LOGE("after +=2, ptr :%s",ptr); | |
| if (len == 0) { | |
| return 2; | |
| } else if (len < 0) { | |
| return -1; | |
| } | |
| if (type) { | |
| len = (len) << 1; | |
| } else { | |
| len += 2; | |
| } | |
| LOGE("Address length = %d ", len); | |
| // Type-of-address | |
| val = internal_mdapi_hex2int(ptr); | |
| ptr += 2; | |
| len -= 2; | |
| if (val == 0x91) { | |
| // international number | |
| output_len += snprintf(output+output_len, output_size-output_len-1, "+"); | |
| } else if (val == 0x81) { | |
| // national number | |
| } else if ((val & 0x50) == 0x50 ){ | |
| // alphabet number | |
| } else { | |
| LOGE("Invalid type-of-address : %02X " , val); | |
| } | |
| // decode alphabet number | |
| if (0x50 == (val & 0x50)) { | |
| kal_int32 octect = (((len * 4) / 7 ) % 8 == 0) ? 1 : 0; | |
| kal_char * tmp = (kal_char * )malloc(len + 1); | |
| if (!tmp) { | |
| LOGE("Invalid type-of-address : %02X ", val); | |
| return -1; | |
| } | |
| memcpy(tmp, ptr, len); | |
| tmp[len] = 0; | |
| output_len += internal_mdapi_sms_7bit_decode(tmp, output, output_size - output_len - 1, 0, octect); | |
| free(tmp); | |
| tmp = NULL; | |
| } else { | |
| do { | |
| if (len > 1) { | |
| if (*ptr == 'F') { | |
| output_len += snprintf(output + output_len, output_size - output_len - 1, "%c", *(ptr + 1)); | |
| } else { | |
| output_len += snprintf(output + output_len, output_size - output_len - 1, "%c%c", *(ptr + 1), *(ptr)); | |
| } | |
| len -= 2; | |
| ptr += 2; | |
| } else { | |
| output_len += snprintf(output + output_len, output_size - output_len - 1, "%c", *(ptr + 1)); | |
| len -= 1; | |
| ptr += 1; | |
| padding_bit = 1; | |
| } | |
| } while (len > 0); | |
| } | |
| return (ptr-number+padding_bit); | |
| } | |
| static kal_int32 _mdapi_sms_decode_pdu(mdapi_sms_record_t *sms, | |
| kal_int8 *smsc, | |
| kal_int8 *content, | |
| kal_int32 content_size, | |
| kal_int32 *record_size, | |
| kal_int32 *curr_pack, | |
| kal_int32 *total_pack) | |
| { | |
| kal_int32 ret = 0; | |
| kal_int8 *ptr = content; | |
| kal_int32 udh = 0; | |
| /* | |
| * Service Centre address informaction element | |
| */ | |
| LOGE("%s, %s, %d, ptr_len: %d, ptr: %s\n", __FILE__,__FUNCTION__, __LINE__, content_size, ptr); | |
| ret = internal_mdapi_address_decode(ptr, smsc, 512, 1); | |
| if (ret <= 0) { | |
| LOGE("can't get SMSC address"); | |
| return MDAPI_RET_ERROR; | |
| } | |
| ptr += ret; | |
| LOGE("SMSC = [%s]\n", smsc); | |
| /* Protocol Data Unit Type(PDU Type) */ | |
| { | |
| kal_int32 pdu_type = internal_mdapi_hex2int(ptr); | |
| if ((pdu_type & 0x03) == SMS_DELIVER) { | |
| sms->msg_type = MDAPI_SMS_NORMAL_MSG; | |
| } else if ((pdu_type & 0x03) == SMS_STATUS_REPORT){ | |
| sms->msg_type = MDAPI_SMS_MSG_REPORT; | |
| } else { | |
| LOGE("unkown PDU type = %02X(%02X), content = %s", pdu_type, pdu_type & 0x03, content); | |
| return MDAPI_RET_ERROR; | |
| } | |
| if ((pdu_type & 0x40) == 0x40) { | |
| udh = 1; /* find UDH header */ | |
| } | |
| LOGE("PDU Type = [%d]\n", pdu_type); | |
| } | |
| ptr += 2; | |
| /* decode originator address(OA) destination address(DA)*/ | |
| ret = internal_mdapi_address_decode(ptr, sms->phone_number, sizeof(sms->phone_number), 0); | |
| if (ret <= 0) { | |
| LOGE("can't get sender address"); | |
| return MDAPI_RET_ERROR; | |
| } | |
| ptr += ret; | |
| LOGE("sender = [%s]\n", sms->phone_number); | |
| /* protocol identifiler(PID) */ | |
| ptr += 2; | |
| /* Data Coding Scheme (DCS) */ | |
| { | |
| //kal_int32 text_compressed = 0; | |
| kal_int32 dcs = 0; | |
| dcs = internal_mdapi_hex2int(ptr); | |
| if (dcs < 0) { | |
| LOGE("can't get the DCS\n"); | |
| return MDAPI_RET_ERROR; | |
| } | |
| if ( (dcs & 0xC0) == 0x00) { | |
| /* General Data Coding indication */ | |
| if (dcs & 0x20) { | |
| //text_compressed = 1; | |
| } | |
| if (dcs & 0x10) { | |
| sms->sms_class = dcs & 0xF; | |
| } | |
| if (dcs & 0x04) { | |
| sms->charset = MDAPI_SMS_CHARSET_GSM_8BIT; | |
| } else if (dcs & 0x08) { | |
| sms->charset = MDAPI_SMS_CHARSET_UCS2; | |
| } else { | |
| sms->charset = MDAPI_SMS_CHARSET_GSM_7BIT; | |
| } | |
| } else { | |
| LOGE("un-supported dcs type\n"); | |
| return MDAPI_RET_ERROR; | |
| } | |
| ptr += 2; | |
| } | |
| /* Time */ | |
| { | |
| kal_int32 i = 0; | |
| kal_int8 tmp[4] = {0}; | |
| kal_uint8 time[7] = {0}; | |
| char temp_buff[64] = {0}; | |
| for (i = 0; i < 7; i++) { | |
| tmp[0] = *(ptr + 1); | |
| tmp[1] = *ptr; | |
| tmp[2] = 0; | |
| time[i] = strtoul(tmp, 0, 10); | |
| ptr += 2; | |
| } | |
| if (time[0] < 80) { | |
| time[0] += 100; | |
| } | |
| memset(temp_buff, 0, sizeof(temp_buff)); | |
| snprintf(temp_buff, sizeof(temp_buff), "%04u-%02u-%02u %02u:%02u:%02u",time[0] + 1900, time[1], time[2], time[3], time[4], time[5]); | |
| strncpy(sms->time, temp_buff, sizeof(sms->time)); | |
| //snprintf(sms->time, sizeof(sms->time), "%04u-%02u-%02u %02u:%02u:%02u", time[0] + 1900, time[1], time[2], time[3], time[4], time[5]); | |
| LOGE("sms time = [%s]\n", sms->time); | |
| } | |
| { | |
| kal_int32 i = 0; | |
| kal_int32 udh_len = 0; | |
| kal_int32 data_len = 0; | |
| kal_int32 buf_len = 0; | |
| kal_int32 octect = 0; | |
| data_len = internal_mdapi_hex2int(ptr); | |
| ptr += 2; | |
| /* parse UDH header, to parse log SMS header */ | |
| if (udh) { | |
| kal_int8 *ptr_udh = NULL; | |
| udh_len = internal_mdapi_hex2int(ptr); | |
| ptr += 2; | |
| ptr_udh = ptr; | |
| while (i < udh_len) { | |
| kal_int32 iei = 0; | |
| kal_int32 iei_len = 0; | |
| iei = internal_mdapi_hex2int(ptr); | |
| ptr += 2; | |
| iei_len = internal_mdapi_hex2int(ptr); | |
| ptr += 2; | |
| if (iei != 0x00 && iei != 0x08) { | |
| ptr += (iei_len) * 2; | |
| i += 2 + iei_len; | |
| continue; | |
| } | |
| if (iei == 0x00) { | |
| sms->ref_num = internal_mdapi_hex2int(ptr); | |
| ptr += 2; | |
| } else { | |
| sms->ref_num = ((internal_mdapi_hex2int(ptr) & 0xFF) << 8) | |
| | (internal_mdapi_hex2int(ptr + 2) & 0xFF); | |
| ptr += 4; | |
| } | |
| /*lei modify for gsw 2022/5/12*/ | |
| sms->total_pack = internal_mdapi_hex2int(ptr); | |
| LOGE("sms->total_pack = [%d]", sms->curr_pack); | |
| *total_pack = sms->total_pack; | |
| sms->curr_pack = internal_mdapi_hex2int(ptr+2); | |
| LOGE("sms->curr_pack = [%d]", sms->curr_pack); | |
| *curr_pack = sms->curr_pack; | |
| /*lei modify for gsw 2022/5/12*/ | |
| break; | |
| } | |
| ptr = ptr_udh + (udh_len) * 2; | |
| } | |
| LOGE("sms->charset = [%d] \n", sms->charset); | |
| switch (sms->charset) { | |
| case MDAPI_SMS_CHARSET_GSM_7BIT: | |
| octect = (data_len % 8 == 0) ? 1 : 0; | |
| // decode 7bit | |
| if (1 == udh) { | |
| kal_int32 padding_bits = ((udh_len + 1) * 8) % 7; | |
| if (padding_bits) { | |
| padding_bits = 7 - padding_bits; | |
| } | |
| data_len = internal_mdapi_sms_7bit_decode(ptr, sms->msg_content, content_size, padding_bits, octect); | |
| } else { | |
| data_len = internal_mdapi_sms_7bit_decode(ptr, sms->msg_content, content_size, 0, octect); | |
| } | |
| *(sms->msg_content + data_len++) = '\0'; | |
| *(sms->msg_content + data_len++) = '\0'; | |
| *record_size = data_len; | |
| break; | |
| case MDAPI_SMS_CHARSET_GSM_8BIT: | |
| sms->msg_content = ptr; | |
| content_size = strlen(sms->msg_content); | |
| #if 0 | |
| if( 1 == udh ) { | |
| data_len -= (udh_len + 1); | |
| } | |
| if (data_len >= *record_size - 2) { | |
| data_len = *record_size - 2; | |
| } | |
| sms->msg_content[0] = '\0'; | |
| for (i = 0 ; i < data_len ; i++) { | |
| kal_uint8 tmp[2] = {0, 0}; | |
| tmp[0] = internal_mdapi_hex2int(ptr); | |
| ptr += 2; | |
| buf_len += kal_ext_ascii_to_utf8((UTF8 *)(sms->msg_content + buf_len), tmp, *record_size - buf_len); | |
| if (*record_size - buf_len < 0) { | |
| return MDAPI_RET_ERROR; | |
| } | |
| } | |
| *(sms->msg_content + buf_len++) = '\0'; | |
| *(sms->msg_content + buf_len++) = '\0'; | |
| *record_size = buf_len; | |
| //LOGE(KAL_LOG_INFO, LOG_TAG, "is utf8 = [%d]", is_utf8_sequence((UTF8 *)sms->msg_content, (UTF8 *)sms->msg_content + data_len - 2)); | |
| #endif | |
| break; | |
| case MDAPI_SMS_CHARSET_UCS2: | |
| buf_len = 0; | |
| if( 1 == udh ) { | |
| data_len -= (udh_len + 1); | |
| } | |
| sms->msg_content[0] = '\0'; | |
| for (i=0 ; i < data_len ; i = i + 2) { | |
| UTF16 tmp[2] = {0, 0}; | |
| kal_uint8 *tmp_ptr = (kal_uint8 *)tmp; | |
| tmp_ptr[0] = internal_mdapi_hex2int(ptr); | |
| ptr += 2; | |
| tmp_ptr[1] = internal_mdapi_hex2int(ptr); | |
| ptr += 2; | |
| tmp[0] = ntohs(tmp[0]); | |
| //LOGE(KAL_LOG_INFO, LOG_TAG, "tmp = [%04X]", tmp); | |
| buf_len += kal_utf16_to_utf8((UTF8 *)(sms->msg_content + buf_len), tmp, *record_size - buf_len); | |
| if (*record_size - buf_len < 0) { | |
| return MDAPI_RET_ERROR; | |
| } | |
| } | |
| *(sms->msg_content + buf_len++) = '\0'; | |
| *(sms->msg_content + buf_len++) = '\0'; | |
| *record_size = buf_len; | |
| break; | |
| default: | |
| return MDAPI_RET_ERROR; | |
| } | |
| } | |
| sms->position = MDAPI_SMS_POS_INBOX; | |
| return MDAPI_RET_SUCCESS; | |
| } | |
| int smsPduDecode(const char *pdu_str, int pdu_len, | |
| char *da_num, char *smsc, char *msg, int *charset, int *curr_pack, int *total_pack, char *date) | |
| { | |
| kal_char msg_tmp[MAX_PDU_SIZE] = {0}; | |
| mdapi_sms_record_t record; | |
| kal_int32 status = MDAPI_RET_ERROR; | |
| kal_int32 out_len = 210; | |
| LOGE("%s\n",__FILE__); | |
| LOGE("%s\n",__FUNCTION__); | |
| LOGE("%d\n",__LINE__); | |
| LOGE("%d\n",pdu_len); | |
| LOGE("%s\n",pdu_str); | |
| record.msg_content = msg_tmp; | |
| /*lei modify for gsw 2022/5/11*/ | |
| status = _mdapi_sms_decode_pdu(&record, smsc, (kal_int8 *)pdu_str, | |
| pdu_len, &out_len, curr_pack, total_pack); | |
| /*lei modify for gsw 2022/5/11*/ | |
| if(status == MDAPI_RET_SUCCESS) { | |
| memcpy(da_num, record.phone_number, strlen(record.phone_number)); | |
| memcpy(msg, record.msg_content, strlen(record.msg_content)); | |
| *charset = record.charset; | |
| memcpy(date, record.time, strlen(record.time)); | |
| #if 0 | |
| /*lei modify for gsw 2022/5/11*/ | |
| *curr_pack = record.curr_pack; | |
| *total_pack = record.total_pack; | |
| /*lei modify for gsw 2022/5/11*/ | |
| #endif | |
| } else { | |
| LOGE("PDU decode error"); | |
| } | |
| return status; | |
| } | |
| void ArrayToStr(unsigned char *Buff, unsigned int BuffLen, char *OutputStr) | |
| { | |
| int i = 0; | |
| char TempBuff[1024 * 2 +1] = {0}; | |
| char strBuff[1024 * 2 +1] = {0}; | |
| for(i = 0; i<BuffLen;i++) | |
| { | |
| sprintf(TempBuff,"%02x",(unsigned char)Buff[i]); | |
| strncat(strBuff,TempBuff,BuffLen*2); | |
| } | |
| strncpy(OutputStr, strBuff, BuffLen*2); | |
| return; | |
| } |