type TdumpSMS=record //接收到的短信包
lpID:string; //短信编号
lpStatus:string; //1表示接收,2表示未发信息
lpLen:string; //信息总容量(长度)
lpSMSCL:string; //短信息中心地址(号码)长度
lpSMSCTpye:string; //短信息中心号码类型,91是TON/NPI
lpSMSC:string; //短消息业务中心地址
lpPDUType:string; //PDU类型,文件头字节。
lpScrPhoneLen:string; //主叫号码长度
lpScrPhoneType:string; //主叫号码类型
lpScrPhone:string; //源地址
lpPID:string; //协议标识
lpDCS:string; //数据编码
lpSCTS:string; //短消息到达业务中心的时间
lpUDL:string; //数据长度
lpUD:string; //数据
end;
function dumpSMS(s:string;var ret:TdumpSMS):boolean;
const
TypeOfAddress='91';
TpId='00';
TpDcs='08';//"00" is 7 bit encode "08" is 8 bit encode;
var i:integer;
begin
result:=false;
try
if (pos('+CMGL:',UpperCase(s))=0)and(pos('+CMGR:',UpperCase(s))=0) then exit;
with ret do
begin
lpID:=GetHTMLlabel(s,':',','); //短信编号
i:=pos(',',s);
delete(s,1,i);
lpStatus:=GetHTMLlabel(s,',',','); //1表示接收,2表示未发信息
i:=pos(',',s);
delete(s,1,i);
lpLen:=GetHTMLlabel(s,',',#13); //信息总容量(长度)
i:=pos(#13#10,s);
if i>0 then inc(i);
delete(s,1,i);
lpSMSCL :=copy(s,1,2); //短信息中心地址(号码)长度
lpSMSCTpye :=copy(s,3,2); //短信息中心号码类型,91是TON/NPI
delete(s,1,4);
lpSMSC :=ReverseStr(copy(s,1,14)); //短消息业务中心地址
i:=length(lpSMSC);
if copy(lpSMSC,i,1)='F' then
delete(lpSMSC,i,1);
delete(s,1,14);
lpPDUType:=copy(s,1,2); //PDU类型,文件头字节。
delete(s,1,2);
lpScrPhoneLen:=copy(s,1,2); //主叫号码长度
lpScrPhoneType:=copy(s,3,2); //主叫号码类型
delete(s,1,4);
i:=strtoint('$'+lpScrPhoneLen);
if odd(i) then //奇数
inc(i);
lpScrPhone:=ReverseStr(copy(s,1,i)); //源地址
i:=length(lpScrPhone);
if copy(lpScrPhone,i,1)='F' then
delete(lpScrPhone,i,1);
delete(s,1,i);
lpPID:=copy(s,1,2); //协议标识
lpDCS:=copy(s,3,2); //数据编码
delete(s,1,4);
lpSCTS:=ReverseStr(copy(s,1,14)); //短消息到达业务中心的时间
lpSCTS:='20'+lpSCTS[1]+lpSCTS[2]+'/'+lpSCTS[3]+lpSCTS[4]+'/'+lpSCTS[5]+lpSCTS[6]+' '+
lpSCTS[7]+lpSCTS[8]+':'+lpSCTS[9]+lpSCTS[10]+':'+lpSCTS[11]+lpSCTS[12]+'.'+lpSCTS[13]+lpSCTS[14];
delete(s,1,12);
lpUDL:=inttostr(strtoint('$'+copy(s,1,2))+strtoint('$'+copy(s,3,2))); //数据长度
delete(s,1,4);
i:=pos(#13#10,s)-1;
if i>0 then
s:=copy(s,1,i);
if lpDCS=TpDcs then
lpUD:=UniCode2GB(s) //数据
else
lpUD:=DecodeSMS7Bit(s);
end;
except
end;
result:=true;
end;
function GsmToString(s : string) : string; //解码
var
maskValue : byte;
subStr,tStr : string;
sLen,subLen,count,i,j : integer;
begin
Result := '';
sLen := Length (s);
count := sLen div 7;
if sLen mod 7 <> 0 then
Inc (count);
for i := 1 to count do
begin
subStr := Copy (s,(i - 1) * 7 + 1,7);
subLen := Length (subStr);
SetLength (tStr,subLen + 1);
for j := 1 to subLen + 1 do
tStr[j] := #0;
maskValue := $7f;
for j := 1 to subLen do
begin
tStr[j] := Chr ((Ord (subStr[j]) and maskValue) shl (j-1)+Ord (tStr[j]));
tStr[j + 1] := Chr (Ord (subStr[j]) and (not maskValue) shr (8 - j));
maskValue := maskValue shr 1;
end;
Result := Result + tStr;
end;
if sLen mod 7 <> 0 then
Delete (Result,Length (Result),1);
end;
function HexCharToInt(HexToken : char):Integer;
begin
//if HexToken>#97 then HexToken:=Chr(Ord(HexToken)-32);
{ 将小写字母转换成大写 }
Result:=0;
if (HexToken>#47) and (HexToken<#58) then { chars 0....9 }
Result:=Ord(HexToken)-48
else if (HexToken>#64) and (HexToken<#71) then { chars A....F }
Result:=Ord(HexToken)-65 + 10;
end;
function HexCharToBin(HexToken : char): string;
var DivLeft : integer;
begin
DivLeft:=HexCharToInt(HexToken); { first HexChar->Int }
Result:='';
{ Use reverse dividing }
repeat { Trick; divide by 2 }
if Odd(DivLeft) then { result = odd ? then bit = 1 }
Result:='1'+Result { result = even ? then bit = 0 }
else
Result:='0'+Result;
DivLeft:=DivLeft div 2; { keep dividing till 0 left and length = 4 }
until (DivLeft=0) and (length(Result)=4); { 1 token = nibble = 4 bits }
end;
function HexToBin(HexNr : string): string;
{ only stringsize is limit of binnr }
var Counter : integer;
begin
Result:='';
for Counter:=1 to length(HexNr) do
Result:=Result+HexCharToBin(HexNr[Counter]);
end;
function pow(base, power: integer): integer; //指数base^power
var counter : integer;
begin
Result:=1;
for counter:=1 to power do
Result:=Result*base;
end;
function BinStrToInt(BinStr : string) : integer;
var counter : integer;
begin
if length(BinStr)>16 then
raise ERangeError.Create(#13+BinStr+#13+
'不是一个有效的16Bit二进制单元'+#13);
Result:=0;
for counter:=1 to length(BinStr) do
if BinStr[Counter]='1' then
Result:=Result+pow(2,length(BinStr)-counter);
end;
function DecodeSMS7Bit(PDU : string):string;
var OctetStr : string;
OctetBin : string;
Charbin : string;
PrevOctet: string;
Counter : integer;
Counter2 : integer;
begin
PrevOctet:='';
Result:='';
for Counter:=1 to length(PDU) do
begin
if length(PrevOctet)>=7 then { if 7 Bit overflow on previous }
begin
if BinStrToInt(PrevOctet)<>0 then
Result:=Result+Chr(BinStrToInt(PrevOctet))
else
Result:=Result+' ';
PrevOctet:='';
end;
if Odd(Counter) then { only take two nibbles at a time }
begin
OctetStr:=Copy(PDU,Counter,2);
OctetBin:=HexToBin(OctetStr);
Charbin:='';
for Counter2:=1 to length(PrevOctet) do
Charbin:=Charbin+PrevOctet[Counter2];
for Counter2:=1 to 7-length(PrevOctet) do
Charbin:=OctetBin[8-Counter2+1]+Charbin;
if BinStrToInt(Charbin)<>0 then
Result:=Result+Chr(BinStrToInt(CharBin))
else
Result:=Result+' ';
PrevOctet:=Copy(OctetBin,1,length(PrevOctet)+1);
end;
end;
end;
function ReverseStr(SourceStr : string) : string;//调换两个字符位置
var i: integer;
begin
Result:='';
i:=1;
while i<length(SourceStr) do
begin
Result:=Result+(SourceStr[i+1]+SourceStr);
inc(i,2);
end;
end;
function GB2UniCode(GB:string):string;
var
s: string;
i, j, k: integer;
a: array [1..160] of char;
begin
s:='';
StringToWideChar(GB, @(a[1]), 500);
i:=1;
while ((a<>#0) or (a[i+1]<>#0)) do
begin
j:=Integer(a);
k:=Integer(a[i+1]);
s:=s+Copy(Format('%X ',[k*$100+j+$10000]) ,2,4);
//S := S + Char(k)+Char(j);
i:=i+2;
end;
Result:=s;
end;
function UniCode2GB(S : String):String;
Var I: Integer;
begin
I := Length(S);
while I >=4 do
begin
try
Result :=WideChar(StrToInt('$'+S[I-3]+S[I-2]+S[I-1]+S))+ Result;
except
end;
I := I - 4;
end;
end;
//提取字符串间的字符
function GetHTMLlabel(lpText,lpStart,lpEnd:string):string;
var i:integer;
begin
result:='';
i:=pos(lowercase(lpStart),lowercase(lpText)); //开始字符
if i=0 then exit;
delete(lpText,1,i+length(lpStart)-1);
i:=pos(lowercase(lpEnd),lowercase(lpText)); //结束字符
if i<2 then exit;
result:=trim(copy(lpText,1,i-1));
end;