blob: 20cf88e4569790a8d5f79579a660dafbf84a6ad1 [file] [log] [blame]
//
// 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];
#define MIN(a, b) ((a) < (b) ? (a) : (b))
// 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:
kal_int32 utf8_len = 0;
kal_uint8* binary_data = NULL;
kal_char* utf8_buffer = NULL;
// 分配二进制缓冲区
binary_data = malloc(data_len);
if (!binary_data) {
LOGE("Memory allocation failed for 8bit data");
return MDAPI_RET_ERROR;
}
// 将十六进制PDU转换为二进制数据
kal_int32 bin_index = 0;
for (i = 0; i < data_len; i++) {
kal_int32 hex_val = internal_mdapi_hex2int(ptr);
if (hex_val < 0 || hex_val > 255) {
free(binary_data);
LOGE("Invalid hex value in 8bit PDU at position %d", i);
return MDAPI_RET_ERROR;
}
binary_data[bin_index++] = (kal_uint8)hex_val;
ptr += 2;
}
// 分配UTF-8缓冲区(最大可能大小)
utf8_buffer = malloc(data_len * 3 + 1);
if (!utf8_buffer) {
free(binary_data);
LOGE("Memory allocation failed for UTF-8 buffer");
return MDAPI_RET_ERROR;
}
// 转换二进制数据到UTF-8
kal_int32 buf_pos = 0;
for (i = 0; i < data_len; i++) {
kal_uint8 tmp[2] = {binary_data[i], 0};
kal_int32 converted = kal_ext_ascii_to_utf8(
(UTF8*)(utf8_buffer + buf_pos),
tmp,
(data_len * 3) - buf_pos
);
if (converted <= 0) {
LOGE("Character conversion failed at position %d", i);
break;
}
buf_pos += converted;
}
utf8_buffer[buf_pos] = '\0';
utf8_len = buf_pos;
// 复制到输出缓冲区
kal_int32 copy_size = MIN(utf8_len, *record_size - 1);
memcpy(sms->msg_content, utf8_buffer, copy_size);
sms->msg_content[copy_size] = '\0';
*record_size = copy_size;
// 清理临时内存
free(binary_data);
free(utf8_buffer);
LOGE("8bit msg decoded: len=%d, content=%.*s",
copy_size, copy_size > 50 ? 50 : copy_size, sms->msg_content);
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, out_len);
*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;
}