手机unicode编码格式短信解码

本文根据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);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值