本文根据http://blog.csdn.net/yangfeiyang/article/details/5526649处的C#代码用C重写而来,只对ucs2的解码部分进行了重写,在VC上进行过模拟测试,目标机上没有经过测试,需要童鞋的可以自己在真机上测试下,不对之处欢迎拍砖!
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#define NUMBER_MAX_LEN 21
#define TIMESTAMP_MAX_LEN 10
#define SMS_MAX_DATA_LEN 256
typedef struct
{
unsigned int year;
unsigned int month;
unsigned int day;
unsigned int hour;
unsigned int minute;
unsigned int second;
}DateTimeStru;
typedef struct
{
/// <summary>
/// 短消息中心号码
/// SMS center address
/// </summary>
char SCA[NUMBER_MAX_LEN];
/// <summary>
/// 目标号码或回复号码
/// TP-DA或TP-RA
/// </summary>
char TPA[NUMBER_MAX_LEN];
/// <summary>
/// 时间戳字符串
/// </summary>
char TP_SCTS[TIMESTAMP_MAX_LEN];
/// <summary>
/// 用户数据,短消息内容
/// 接收时使用
/// </summary>
char TP_UD[SMS_MAX_DATA_LEN];
/// <summary>
/// 时间戳
/// </summary>
DateTimeStru TimeStamp;
}STPDUParam;
// 调用此函数,参数sub申请的buffer一定大于sub_len+1,并且buffer初始化为0
int getSubStringByStartAndLen(char* str,char* sub, unsigned int start, unsigned int sub_len)
{
unsigned int str_len =0;
if(str!=NULL&&sub!=NULL)
{
str_len = strlen(str);
if(str_len>=start+sub_len)
{
int i, cnt;
for(i=start,cnt=0; cnt<sub_len && i<str_len ; i++,cnt++)
{
sub[cnt]=str[i];
}
return cnt;
}
return -1;
}
return -1;
}
int ParseDecString2Int(char* str)
{
int result=0;
if(str!=NULL)
{
int i;
int len = strlen(str);
int multiple=1;
for(i=len-1; i>=0; i--)
{
if(str[i]>='0'&&str[i]<='9')
{
result=result+(str[i]-'0')*multiple;
}
else
{
return -1;
}
multiple *=10;
}
return result;
}
else
{
return -1;
}
}
int ParseHexString2Int(char* str)
{
int result=0;
if(str!=NULL)
{
int i;
int len = strlen(str);
int multiple=1;
for(i=len-1; i>=0; i--)
{
if(str[i]>='0'&&str[i]<='9')
{
result=result+(str[i]-'0')*multiple;
}
else if(str[i]>='A'&&str[i]<='F' )
{
result=result+(str[i]-'A'+10)*multiple;
}
else if(str[i]>='a'&&str[i]<='f' )
{
result=result+(str[i]-'a'+10)*multiple;
}
else
{
return -1;
}
multiple *=0x10;
}
return result;
}
else
{
return -1;
}
}
int BuildUnInvertNumber(char * numberArray, char *numberStrb)
{
int len;
char tempArray[3];
// 编码后号码长度均为偶数,如果不是偶数说明错误
len = strlen(numberArray);
if(len%2!=0)
{
return -1;
}
memset((void*)numberStrb,0, sizeof(numberStrb));
for (int i = 0; i < len; i += 2)
{
memset((void*)tempArray,0, sizeof(tempArray));
tempArray[0] = numberArray[i + 1];
tempArray[1] = numberArray[i];
if (tempArray[1] != 'F')
{
strcat(numberStrb,tempArray);
}
else
{
strncat(numberStrb,tempArray,1);
}
}
return 0;
}
/// <summary>
/// 将字符串数组反向
/// </summary>
/// <param name="MobileNum"></param>
/// <returns></returns>
char * InvertCharArray(char* src, char *dst)
{
int length = strlen(src);
for (int i = 0; i < length; i += 2)
{
if (i + 1 < length)
{
dst[i] = src[i + 1];
dst[i + 1] = src[i];
}
else
{
dst[i] = src[i];
}
}
return dst;
}
#define SHXMalloc(x) malloc((x))
#define SHXFree(x) {\
free((void*)x);\
x = NULL;\
}
int GetUnicodeUserData(char *userDataSrc, int userDataLen, char* res)
{
int len = userDataLen;
char test;
char * resByte = res;
int i,j;
char sub[3];
int sub_real_len;
for (i = 0, j = 0; i < len; i += 2, j++)
{
int bytTmp = 0;
memset((void*)sub, 0, sizeof(sub));
sub_real_len = getSubStringByStartAndLen(userDataSrc,sub,i, 2);
if(sub_real_len!=2)
{
return -1;
}
if((bytTmp = (unsigned char)ParseHexString2Int(sub))<0)
{
return -2;
}
resByte[j] = (char)bytTmp;
}
for (int p = 0; p < j; p += 2)
{
test = resByte[p];
resByte[p] = resByte[p + 1];
resByte[p + 1] = test;
}
return 0;
}
static unsigned char Decoding(char * pduBody, STPDUParam * pduDecoding)
{
int sub_real_len;
int currentIndex = 0;
int codingProtocol;
//处理短信中心...开始
int scaLength = 0;
{
char sub[3];
int bytscaLength;
memset((void*)sub, 0, sizeof(sub));
sub_real_len = getSubStringByStartAndLen(pduBody,sub,currentIndex, 2);
if(sub_real_len==2)
{
char scaSrc[(NUMBER_MAX_LEN+1)*2];
if((bytscaLength = ParseHexString2Int(sub))<0)
{
return -1;
}
scaLength = (int)bytscaLength * 2;
// 由于短消息中心中包含91
// 所以索引多加2,长度减2
currentIndex += 4;
scaLength -= 2;
memset((void*)scaSrc,0, sizeof(scaSrc));
sub_real_len = getSubStringByStartAndLen(pduBody,scaSrc,currentIndex, scaLength);
if(sub_real_len == scaLength)
{
if(BuildUnInvertNumber(scaSrc, pduDecoding->SCA)<0)
{
return -2;
}
currentIndex += scaLength;
}
else
{
return -3;
}
}
}
//处理短信中心...结束
//处理TP-MTI/MMS/RP...开始
// 这个信息在字符串中占2个字符
currentIndex += 2;
//处理TP-MTI/MMS/RP...结束
//处理短消息号码...开始
{
int numberLength = 0;
int bytNumberLength = 0;
char sub[3];
memset((void*)sub,0,sizeof(sub));
sub_real_len = getSubStringByStartAndLen(pduBody,sub,currentIndex, 2);
if(sub_real_len==2)
{
char numberSrc[(NUMBER_MAX_LEN+1)*2];
if((bytNumberLength = ParseHexString2Int(sub))<0)
{
return -4;
}
currentIndex += 2;
numberLength = bytNumberLength;
currentIndex += 2;
if (numberLength%2 != 0)
{
numberLength++;
}
memset((void*)numberSrc,0,sizeof(numberSrc));
sub_real_len = getSubStringByStartAndLen(pduBody,numberSrc,currentIndex, numberLength);
if(sub_real_len == numberLength)
{
if(BuildUnInvertNumber(numberSrc, pduDecoding->TPA)<0)
{
return -5;
}
currentIndex += numberLength;
}
}
else
{
return -6;
}
//处理协议标识与编码协议...开始
// 协议标识占2个字符
currentIndex += 2;
{
// 取编码方式
int bytCodingProtocol = 0;
char sub[3];
memset((void*)sub,0,sizeof(sub));
sub_real_len = getSubStringByStartAndLen(pduBody,sub,currentIndex, 2);
if(sub_real_len==2)
{
char numberSrc[(NUMBER_MAX_LEN+1)*2];
if((bytCodingProtocol = ParseHexString2Int(sub))<0)
{
return -7;
}
codingProtocol = (int) bytCodingProtocol;
currentIndex += 2;
}
}
//处理协议标识与编码协议...结束
}
//处理短消息号码...结束
//处理时间戳...开始
{
int year, month, day, hour, minute, second;
char yearStr[5], monthStr[3], dayStr[3], hourStr[3], minuteStr[3], secondStr[3], timeAreaStr[8];
char timeStampReversal[15];
char timeStamp[15];
int timeStampIndex = 0;
memset((void*)timeStampReversal,0,sizeof(timeStampReversal));
sub_real_len = getSubStringByStartAndLen(pduBody,timeStampReversal,currentIndex, 14);
if(sub_real_len==14)
{
memset((void*)timeStamp,0,sizeof(timeStamp));
InvertCharArray(timeStampReversal,timeStamp);
timeStampIndex = 0;
memset((void*)yearStr,0, sizeof(yearStr));
sub_real_len = getSubStringByStartAndLen(timeStamp,yearStr,timeStampIndex, 2);
timeStampIndex += 2;
if(sub_real_len!=2)
{
return -8;
}
if((year = ParseDecString2Int(yearStr))<0)
{
return -9;
}
year +=2000;
memset((void*)monthStr,0, sizeof(monthStr));
sub_real_len = getSubStringByStartAndLen(timeStamp,monthStr,timeStampIndex, 2);
timeStampIndex += 2;
if(sub_real_len!=2)
{
return -10;
}
if((month = ParseDecString2Int(yearStr))<0)
{
return -11;
}
memset((void*)dayStr,0, sizeof(dayStr));
sub_real_len = getSubStringByStartAndLen(timeStamp,dayStr,timeStampIndex, 2);
timeStampIndex += 2;
if(sub_real_len!=2)
{
return -10;
}
if((day = ParseDecString2Int(dayStr))<0)
{
return -11;
}
memset((void*)hourStr,0, sizeof(hourStr));
sub_real_len = getSubStringByStartAndLen(timeStamp,hourStr,timeStampIndex, 2);
timeStampIndex += 2;
if(sub_real_len!=2)
{
return -12;
}
if((hour = ParseDecString2Int(dayStr))<0)
{
return -13;
}
memset((void*)minuteStr,0, sizeof(minuteStr));
sub_real_len = getSubStringByStartAndLen(timeStamp,minuteStr,timeStampIndex, 2);
timeStampIndex += 2;
if(sub_real_len!=2)
{
return -14;
}
if((minute = ParseDecString2Int(minuteStr))<0)
{
return -15;
}
memset((void*)secondStr,0, sizeof(secondStr));
sub_real_len = getSubStringByStartAndLen(timeStamp,secondStr,timeStampIndex, 2);
timeStampIndex += 2;
if(sub_real_len!=2)
{
return -16;
}
if((second = ParseDecString2Int(secondStr))<0)
{
return -17;
}
pduDecoding->TimeStamp.year = year;
pduDecoding->TimeStamp.month = month;
pduDecoding->TimeStamp.day = day;
pduDecoding->TimeStamp.hour = hour;
pduDecoding->TimeStamp.minute = minute;
pduDecoding->TimeStamp.second = second;
currentIndex += 14;
}
else
{
return -18;
}
}
//处理时间戳...结束
//处理用户数据...开始
{
int bytUserDataLength = 0;
char realUserData[SMS_MAX_DATA_LEN+1];
int userDataLength;
char sub[3];
memset((void*)sub, 0, sizeof(sub));
sub_real_len = getSubStringByStartAndLen(pduBody,sub,currentIndex, 2);
if(sub_real_len==2)
{
if((bytUserDataLength=ParseHexString2Int(sub))>=0)
{
char userDataSrc[SMS_MAX_DATA_LEN+1];
userDataLength = bytUserDataLength;
if (userDataLength % 2 != 0)
{
return -19;
}
currentIndex += 2;
memset((void*)userDataSrc,0,sizeof(userDataSrc));
sub_real_len = getSubStringByStartAndLen(pduBody,userDataSrc,currentIndex, userDataLength*2);
if(sub_real_len!=userDataLength*2)
{
return -20;
}
memset((void*)pduDecoding->TP_UD,0,sizeof(pduDecoding->TP_UD));
switch (codingProtocol)
{
case 0:
// 0标识7bit编码
//realUserData = Get7BitUserData(userDataSrc);
break;
case 8:
// 8标识Unicode编码
GetUnicodeUserData(userDataSrc,userDataLength*2,pduDecoding->TP_UD);
break;
}
}
}
else
{
return -23;
}
}
//处理用户数据...结束
}
void main(void)
{
STPDUParam pduDecoding;
memset((void*)&pduDecoding,0,sizeof(pduDecoding));
char tmp[] = "0891683108200505F0840D91683196032930F0000830302180635480064F60597D0021";
Decoding(tmp, &pduDecoding);
}