📄 smspdu.c
字号:
/*************************************************************************** * copyright : (C) 2002 by Hendrik Sattler * * mail : post@hendrik-sattler.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/#include "common.h"#include "charsets.h"#include "helpers.h"#include "smscoding.h"#include "depincludes.h"#include "smspdu.h"#include <stdlib.h>#include <string.h>void create_smssubmit_pdu(char *pdu, char* smstext, char* smsnumber, struct smsopts mysmsopts){ sms_number_t sca; //SMSC unsigned int pdutype; //8bits, convert to hex-string, use defined values! unsigned int mr=0; //message reference, DO NOT CHANGE!!! SET BY THE PHONE!, convert to hex-string sms_number_t da; //destination unsigned int pid=0; //protocol identifier, normally 0, convert to hex-string unsigned int dcs; //data coding scheme, convert to hex-string unsigned int vp_relative=255; //validity period (0-255, set to max=63 weeks), convert to hex-string unsigned char vp_absolute[15]; //validity period (YYMMDDhhmmss(TZ)) unsigned int udl; //user data length, convert to hex-string unsigned char* ud; char buffer,temp[17]; int i; wchar_t* wide_str; memset(sca.number,0,sizeof(sca.number)); memset(da.number,0,sizeof(da.number)); memset(vp_absolute,0,sizeof(vp_absolute)); memset(temp,0,sizeof(temp)); //set SMSC length to 0 to let the phone fill it in sca.length=0; //we do not have to set the rest of sca //set PDU type to standards (if you change it, make sure you know what you are doing!!!) //those are bits! pdutype = 1 | (1<<4); if (mysmsopts.srr) { pdutype |= (1<<5); } //leave message reference as is //process destination if (!strlen(smsnumber)){ errexit("Error: no SMS number specified.\n"); } strcpy(da.number,smsnumber); //check the numver if (!is_pnumber(smsnumber,1)) { errexit("Hey, no poking around with bogus SMS numbers, please.\n"); } buffer=smsnumber[0]; if(buffer=='+'){ da.type=145; da.length=strlen(da.number)-1; if ((strlen(da.number)%2)==0) { sprintf(&da.number[strlen(da.number)],"F"); } for(i=1;i<(strlen(da.number)-1);i=i+2){ sprintf(&temp[strlen(temp)],"%c%c",da.number[i+1],da.number[i]); } }else{ da.type=129; da.length=strlen(da.number); if ((strlen(da.number)%2)==1) { sprintf(&da.number[strlen(da.number)],"F"); } for(i=0;i<(strlen(da.number)-1);i=i+2){ sprintf(&temp[strlen(temp)],"%c%c",da.number[i+1],da.number[i]); } } strcpy(da.number,temp); dcs=0; //differ between normal and flash-sms if (mysmsopts.flash) { dcs &= 0xec; //clear all affected bits dcs |= 0x10; //set class 0 message (immediate display) } //leave PID and vp_relative as is //process user data length and user data wide_str=convert_to_internal(nl_langinfo(CODESET),smstext,strlen(smstext)); if (mysmsopts.unicode) { dcs &= 0xf3; //clear all affected bits dcs |= 0x08; //set unicode charset ud=convert_to_ucs2(wide_str); udl=strlen(ud)/2; //check user data content length if (udl/2 > MAXSMSSIZEUCS) { errexit ("SMS text is too long (max. %d characters).\n", MAXSMSSIZEUCS); } } else { ud=sms_data_7bit_encode(wide_str,&udl); } mem_realloc(wide_str,0); //create PDU memset(pdu,0,sizeof(pdu)); sprintf(&pdu[strlen(pdu)],"%02X",sca.length); sprintf(&pdu[strlen(pdu)],"%02X",pdutype); sprintf(&pdu[strlen(pdu)],"%02X",mr); sprintf(&pdu[strlen(pdu)],"%02X%02X%s",da.length,da.type,da.number); sprintf(&pdu[strlen(pdu)],"%02X",pid); sprintf(&pdu[strlen(pdu)],"%02X",dcs); sprintf(&pdu[strlen(pdu)],"%02X",vp_relative); sprintf(&pdu[strlen(pdu)],"%02X%s",udl,ud); mem_realloc(ud,0);}void decode_smsdeliver_pdu(unsigned char* pdu, int status){ //this is much more complicated because we have to handle ALL sms types!!! //right now, this only includes type SMS-DELIVER, SMS_SUBMIT sms_number_t sca; //SMSC unsigned int pdutype; sms_number_t oa; unsigned int pid=0; unsigned int dcs=0; unsigned char scts[91]; unsigned int udl; unsigned char ud[281]; unsigned int udh_length=0; unsigned char udh[BUFSIZ]; unsigned char temp[281]; unsigned char result[BUFSIZ]; int i, where=0; unsigned char* t; wchar_t* wide_str; struct tm sctime; memset(temp,0,sizeof(temp)); memset(result,0,sizeof(result)); memset(sca.number,0,sizeof(sca.number)); memset(oa.number,0,sizeof(oa.number)); memset(scts,0,sizeof(scts)); memset(ud,0,sizeof(ud)); memset(udh,0,sizeof(udh)); memset(&sctime,0,sizeof(sctime)); //extracting SMSC sca.length=hexstr2int(pdu+where,2); where+=2; if (sca.length){ sca.type=hexstr2int(pdu+where,2); if ((sca.type&112)==16){sprintf(sca.number,"+");} where+=sca.length*2; for (i=4;i<where;i+=2) { sprintf(&sca.number[strlen(sca.number)],"%c%c",pdu[i+1],pdu[i]); } if (!strcmp(&sca.number[strlen(sca.number)-1],"F")) { memset(&sca.number[strlen(sca.number)-1],0,1); } } //checking all type bits pdutype=hexstr2int(pdu+where,2); where+=2; //checking if PDUtype is supported and can thus be decoded if (status==0 || status==1) { switch(pdutype&3) { case SMS_DELIVER: break; case SMS_SUBMIT_REPORT: myprintf(0,"Unsupported pdu type: %s\n","SMS-SUBMIT-REPORT"); memset(pdu,0,sizeof(pdu)); return; break; case SMS_STATUS_REPORT: myprintf(0,"Unsupported pdu type: %s\n","SMS-STATUS-REPORT"); memset(pdu,0,sizeof(pdu)); return; break; default: myprintf(0,"Unknown pdu type.\n"); memset(pdu,0,sizeof(pdu)); return; break; } } else if (status==2 || status==3) { switch(pdutype&3) { case SMS_DELIVER_REPORT: myprintf(0,"Unsupported pdu type: %s\n","SMS-DELIVER-REPORT"); memset(pdu,0,sizeof(pdu)); return; break; case SMS_SUBMIT: where+=2; //MR value break; case SMS_COMMAND: myprintf(0,"Unsupported pdu type: %s\n","SMS-COMMAND"); memset(pdu,0,sizeof(pdu)); return; break; default: myprintf(0,"Unknown pdu type.\n"); memset(pdu,0,sizeof(pdu)); return; break; } } else { myprintf(0,"\nUnknown sms status %d\n", status); memset(pdu,0,sizeof(pdu)); return; } //originator address (OA) oa.length=hexstr2int(pdu+where,2); where+=2; oa.type=hexstr2int(pdu+where,2); where+=2; if (oa.length){ if ((oa.type&112)==80){ for(i=where;i<where+oa.length;i+=2){ sprintf(&oa.number[strlen(oa.number)],"%c%c",pdu[i],pdu[i+1]); } wide_str=sms_data_7bit_decode(oa.number,(oa.length*4)/7); t=convert_from_internal(nl_langinfo(CODESET),wide_str,2); mem_realloc(wide_str,0); strcpy(oa.number,t); mem_realloc(t,0); where+=oa.length; }else{ if ((oa.type&112)==16) { sprintf(oa.number,"+"); } for (i=where;i<where+oa.length;i+=2) { sprintf(&oa.number[strlen(oa.number)],"%c%c",pdu[i+1],pdu[i]); } where+=oa.length; if (!strcmp(&oa.number[strlen(oa.number)-1],"F")) { memset(&oa.number[strlen(oa.number)-1],0,1); } if (oa.length%2) { where++; } } } //we do not need PID information pid=hexstr2int(pdu+where,2); where+=2; //DCS information is critical for decoding!!! dcs=hexstr2int(pdu+where,2); where+=2; switch (pdutype&27) { case (0<<3)+1: //VP not present break; case (1<<3)+1: //VP enhanced //not yet processed where+=14; break; case (2<<3)+1: //VP relative sprintf(scts,"%d",hexstr2int(pdu+where,2)); memset(temp,0,sizeof(temp)); where+=2; break; case (3<<3)+1: //VP absolute case 0: //Service Center Time Stamp (SCTS) sprintf(temp,"%c%c%c%c%c%c%c%c%c%c%c%c", pdu[where+1],pdu[where+0],pdu[where+3],pdu[where+2], pdu[where+5],pdu[where+4],pdu[where+7],pdu[where+6], pdu[where+9],pdu[where+8],pdu[where+11],pdu[where+10]); strptime(temp,"%y%m%d%H%M%S",&sctime); strftime(scts,sizeof(scts)-11,nl_langinfo(D_T_FMT),&sctime); //timzone handling //uncomment if you want that /*sprintf(temp,"%c%c",pdu[where+13],pdu[where+12]); if (((atoi(temp)%80)/4)<=12) { if (atoi(temp)>=80) { sprintf(&scts[strlen(scts)]," (GMT-%02d%02d)",(atoi(temp)%80)/4,(atoi(temp)%320)*15); } else { sprintf(&scts[strlen(scts)]," (GMT+%02d%02d)",(atoi(temp)%80)/4,(atoi(temp)%320)*15); } }*/ memset(temp,0,sizeof(temp)); where+=14; break; } //user data length, this is hex udl=hexstr2int(pdu+where,2); where+=2; //user data if (udl) { if ((pdutype>>6)&1) { udh_length=hexstr2int(pdu+where,2); //udh +udhl drinlassen, dekodieren und dann 1+((udh_length*8)+(udh_length*8)%7)/7 von vorne abschneiden for (i=2;i<(udh_length*2)+2;i+=2) { sprintf(&udh[strlen(udh)],"%c%c",pdu[where+i],pdu[where+i+1]); } } if ( (((dcs>>6)&3)==0 && ((dcs>>2)&3)==0) // 00xx x00x || (((dcs>>6)&3)==1 && ((dcs>>2)&3)==0) // 01xx x00x || (((dcs>>4)&15)==12) // 1100 xxxx || (((dcs>>4)&15)==13) // 1101 xxxx || (((dcs>>4)&15)==15 && ((dcs>>2)&1)==0) // 1111 xxxx ) { //all encodings of uncompressed 7bit wide_str=sms_data_7bit_decode(pdu+where,udl); if ((pdutype>>6)&1){ t=convert_from_internal(nl_langinfo(CODESET),&wide_str[1+((udh_length*8)+(udh_length*8)%7)/7],2); } else { t=convert_from_internal(nl_langinfo(CODESET),wide_str,2); } mem_realloc(wide_str,0); strcpy(ud,t); mem_realloc(t,0); } else if ( (((dcs>>6)&3)==0 && ((dcs>>2)&3)==2) //00xx x10x || (((dcs>>6)&3)==1 && ((dcs>>2)&3)==2) //01xx x10x || (((dcs>>4)&15)==14) // 1110 xxxx ) { //all encodings of uncompressed 16bit unicode if ((pdutype>>6)&1){ wide_str=convert_from_ucs2(pdu+where+2+(udh_length*2)); } else { wide_str=convert_from_ucs2(pdu+where); } t=convert_from_internal(nl_langinfo(CODESET),wide_str,2); mem_realloc(wide_str,0); strcpy(ud,t); mem_realloc(t,0); //16bit means real length is only half of octet count udl /= 2; /*} else if ( (((dcs>>6)&3)==0 && ((dcs>>2)&3)==1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -