📄 libsms_getsms.c
字号:
/*SMS Server ToolsCopyright (C) 2000-2002 Stefan FringsThis program is free software unless you got it under another license directlyfrom the author. You can redistribute it and/or modify it under the terms ofthe GNU General Public License as published by the Free Software Foundation.Either version 2 of the License, or (at your option) any later version.http://www.isis.de/members/~s.fringsmailto:s.frings@mail.isis.de */#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <termios.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <syslog.h>#include "../../ut.h"#include "libsms_charset.h"#include "libsms_modem.h"#include "libsms_sms.h"#include "sms_funcs.h"#define set_date(_date,_Pointer) {\ (_date)[0] = (_Pointer)[3];\ (_date)[1] = (_Pointer)[2];\ (_date)[2] = '-';\ (_date)[3] = (_Pointer)[5];\ (_date)[4] = (_Pointer)[4];\ (_date)[5] = '-';\ (_date)[6] = (_Pointer)[1];\ (_date)[7] = (_Pointer)[0];}#define set_time( _time , _Pointer) {\ (_time)[0] = (_Pointer)[1];\ (_time)[1] = (_Pointer)[0];\ (_time)[2] = ':';\ (_time)[3] = (_Pointer)[3];\ (_time)[4] = (_Pointer)[2];\ (_time)[5] = ':';\ (_time)[6] = (_Pointer)[5];\ (_time)[7] = (_Pointer)[4];}/* converts an octet to a 8-Bit value */int octet2bin(char* octet){ int result=0; if (octet[0]>57) result=octet[0]-55; else result=octet[0]-48; result=result<<4; if (octet[1]>57) result+=octet[1]-55; else result+=octet[1]-48; return result;}/* converts a PDU-String to Ascii; the first octet is the length return the length of ascii */int pdu2ascii(char* pdu, char* ascii){ int bitposition=0; int byteposition; int byteoffset; int charcounter; int bitcounter; int count; int octetcounter; char c; char binary[500]; /* First convert all octets to bytes */ count=octet2bin(pdu); for (octetcounter=0; octetcounter<count; octetcounter++) binary[octetcounter]=octet2bin(pdu+(octetcounter<<1)+2); /* Then convert from 8-Bit to 7-Bit encapsulated in 8 bit */ for (charcounter=0; charcounter<count; charcounter++) { c=0; for (bitcounter=0; bitcounter<7; bitcounter++) { byteposition=bitposition/8; byteoffset=bitposition%8; if (binary[byteposition]&(1<<byteoffset)) c=c|128; bitposition++; c=(c>>1)&127; /* The shift fills with 1, but I want 0 */ } if (/*cs_convert*/1) ascii[charcounter]=sms2ascii(c); else if (c==0) ascii[charcounter]=183; else ascii[charcounter]=c; } ascii[count]=0; return count;}int pdu2binary(char* pdu, char* binary){ int count; int octetcounter; count=octet2bin(pdu); for (octetcounter=0; octetcounter<count; octetcounter++) binary[octetcounter]=octet2bin(pdu+(octetcounter<<1)+2); binary[count]=0; return count;}/* reads a SMS from the SIM-memory 1-10 *//* returns number of SIM memory if successful *//* on digicom the return value can be != sim */int fetchsms(struct modem *mdm, int sim, char* pdu){ char command[16]; char answer[512]; char* position; char* beginning; char* end; int foo,err; int clen; // Digicom reports date+time only with AT+CMGL if (mdm->mode==MODE_DIGICOM) { put_command(mdm,"AT+CMGL=\"ALL\"\r",14,answer, sizeof(answer),200,0); /* search for beginning of the answer */ position=strstr(answer,"+CMGL: "); if (position) { end=position+7; while (*end<'9' && *end>'0') end++; if (end==position+7) { foo = str2s(position+7,end-position-7,&err); if (!err) { DBG("DEBUG:fetchsms:Found a message at memory %i\n",foo); sim=foo; } position = 0; } position = 0; } } else { DBG("DEBUG:fetchsms:Trying to get stored message %i\n",sim); clen=sprintf(command,"AT+CMGR=%i\r",sim); put_command(mdm,command,clen,answer,sizeof(answer),50,0); /* search for beginning of the answer */ position=strstr(answer,"+CMGR:"); } /* keine SMS empfangen, weil Modem nicht mit +CMGR oder +CMGL geantwortet hat */ if (position==0) return 0; beginning=position+7; /* keine SMS, weil Modem mit +CMGR: 0,,0 geantwortet hat */ if (strstr(answer,",,0\r")) return 0; /* After that we have the PDU or ASCII string */ for( end=beginning ; *end && *end!='\r' ; end++ ); if ( !*end || end-beginning<4) return 0; for( end=end+1 ; *end && *end!='\r' ; end++ ); if ( !*end || end-beginning<4) return 0; /* Now we have the end of the PDU or ASCII string */ *end=0; strcpy(pdu,beginning); return sim;}/* deletes the selected sms from the sim card */void deletesms(struct modem *mdm, int sim) { char command[32]; char answer[128]; int clen; DBG("DEBUG:deletesms: Deleting message %i !\n",sim); clen = sprintf(command,"AT+CMGD=%i\r",sim); put_command(mdm, command, clen, answer, sizeof(answer), 50, 0);}// checks the size of the SIM memoryint check_memory(struct modem *mdm, int flag){ char answer[500]; char* posi; int laenge; int err,foo; int j, out; for(out=0,j=0;!out && j<10; j++) { if (put_command(mdm,"AT+CPMS?\r",9,answer,sizeof(answer),50,0) && (posi=strstr(answer,"+CPMS:"))!=0 ) { // Modem supports CPMS command. Read memory size if ( (posi=strchr(posi,','))!=0 ) { posi++; if ( (laenge=strcspn(posi,",\r"))!=0 ) { if (flag==USED_MEM ) { foo = str2s(posi,laenge,&err); if (err) { LOG(L_ERR,"ERROR:sms_check_memory: unable to " "convert into integer used_memory from CPMS" " response\n"); } else { return foo; } } posi+=laenge+1; if ( (laenge=strcspn(posi,",\r"))!=0 ) { foo = str2s(posi,laenge,&err); if (err) { LOG(L_ERR,"ERROR:sms_check_memory: unable to" "convert into integer max_memory from CPMS" " response\n"); } else { return foo; } } } } /* if(strstr) */ } /* if(put_command) */ /* if we are here -> some error happend */ if (checkmodem(mdm)!=0) { LOG(L_WARN,"WARNING:sms_check_memory: something happend with the" " modem -> was reinit -> let's retry\n"); } else { LOG(L_ERR,"ERROR:sms_check_memory: modem seems to be ok, but we" "had an error? I give up!\n"); out = 1; } } /* for */ if (out==0) LOG(L_ERR,"ERROR:sms_check_memory: modem does not respond after 10" "reties! I give up :-(\n"); return -1;}/* splits an ASCII string into the parts *//* returns length of ascii */int splitascii(struct modem *mdm, char *source, struct incame_sms *sms){ char* start; char* end; /* the text is after the \r */ for( start=source ; *start && *start!='\r' ; start++ ); if (!*start) return 1; start++; strcpy(sms->ascii,start); /* get the senders MSISDN */ start=strstr(source,"\",\""); if (start==0) { sms->userdatalength=strlen(sms->ascii); return 1; } start+=3; end=strstr(start,"\","); if (end==0) { sms->userdatalength=strlen(sms->ascii); return 1; } *end=0; strcpy(sms->sender,start); /* Siemens M20 inserts the senders name between MSISDN and date */ start=end+3; // Workaround for Thomas Stoeckel // if (start[0]=='\"') start++; if (start[2]!='/') { // if next is not a date is must be the name end=strstr(start,"\","); if (end==0) { sms->userdatalength=strlen(sms->ascii); return 1; } *end=0; strcpy(sms->name,start); } /* Get the date */ start=end+3; sprintf(sms->date,"%c%c-%c%c-%c%c",start[3],start[4],start[0],start[1], start[6],start[7]); /* Get the time */ start+=9; sprintf(sms->time,"%c%c:%c%c:%c%c",start[0],start[1],start[3],start[4], start[7],start[7]); sms->userdatalength=strlen(sms->ascii); return 1;}/* Subroutine for splitpdu() for messages type 0 (SMS-Deliver) Returns the length of the ascii string In binary mode ascii contains the binary SMS */int split_type_0( char* Pointer,struct incame_sms *sms){ int Length; int padding; int is_binary; Length=octet2bin(Pointer); padding=Length%2; Pointer+=4; memcpy(sms->sender,Pointer,Length+padding); swapchars(sms->sender,Length+padding); /* remove Padding characters after swapping */ sms->sender[Length]=0; Pointer=Pointer+Length+padding+3; is_binary = ((Pointer[0] & 4)==4); Pointer++; set_date(sms->date,Pointer); Pointer=Pointer+6; set_time(sms->time,Pointer); Pointer=Pointer+8; if (is_binary) sms->userdatalength = pdu2binary(Pointer,sms->ascii); else sms->userdatalength = pdu2ascii(Pointer,sms->ascii); return 1;}/* Subroutine for splitpdu() for messages type 2 (Staus Report) Returns the length of the ascii string. In binary mode ascii contains the binary SMS */int split_type_2( char* position, struct incame_sms *sms){ int length; int padding; char *p; /* get from report the sms id */ sms->sms_id = octet2bin(position); position+=2; /* get recipient address */ length=octet2bin(position); padding=length%2; position+=4; memcpy(sms->sender,position,length+padding); sms->sender[length]=0; swapchars(sms->sender,length); // get SMSC timestamp position+=length+padding; set_date(sms->date,position); set_time(sms->time,position+6); // get Discharge timestamp position+=14; p = sms->ascii + 2; set_date(p,position); *(p+DATE_LEN) = ' '; set_time(p+DATE_LEN+1,position+6); // get Status position+=14; sms->ascii[0] = (unsigned char)octet2bin(position); sms->ascii[1] = ' '; sms->ascii[2+DATE_LEN+1+TIME_LEN] = 0; sms->userdatalength=2+DATE_LEN+1+TIME_LEN; return 1;}/* Splits a PDU string into the parts *//* Returns the length of the ascii string. In binary mode ascii contains the binary SMS */int splitpdu(struct modem *mdm, char* pdu, struct incame_sms *sms){ int Length; int Type; char* Pointer; char* start; char* end; /* Get the senders Name if given. Depends on the modem. */ start=strstr(pdu,"\",\""); if (start!=0) { start+=3; end=strstr(start,"\","); if (end!=0) { memcpy(sms->name,start,end-start); sms->name[end-start]=0; } } else end=pdu; /* the pdu is after the first \r */ for( start=end+1 ; *start && *start!='\r' ; start++ ); if (!*start) return 0; pdu=++start; /* removes unwanted ctrl chars at the beginning */ while ( *pdu && (*pdu<=' ')) pdu++; Pointer=pdu; if (mdm->mode!=MODE_OLD) { /* get senders smsc */ Length=octet2bin(pdu)*2-2; if (Length>0) { Pointer=pdu+4; memcpy(sms->smsc,Pointer,Length); swapchars(sms->smsc,Length); /* remove Padding characters after swapping */ if (sms->smsc[Length-1]=='F') sms->smsc[Length-1]=0; else sms->smsc[Length] = 0; } Pointer=pdu+Length+4; } /* is UDH bit set? udh=(octet2bin(Pointer)&4) */ Type=octet2bin(Pointer) & 3; Pointer+=2; if (Type==0) { sms->is_statusreport = 0; /*SMS Deliver*/ return split_type_0( Pointer, sms); } else if (Type==2) { sms->is_statusreport = 1; /*Status Report*/ return split_type_2( Pointer, sms); } /*Unsupported type*/ return -1;}inline int decode_pdu( struct modem *mdm, char *pdu, struct incame_sms *sms){ int ret; memset( sms, 0, sizeof(struct incame_sms) ); /* Ok, now we split the PDU string into parts and show it */ if (mdm->mode==MODE_ASCII || mdm->mode==MODE_DIGICOM) ret = splitascii(mdm, pdu, sms); else ret = splitpdu(mdm, pdu, sms); if (ret==-1) { LOG(L_ERR,"ERROR:decode_pdu: unable split pdu/ascii!\n"); return -1; } return 1;}int getsms( struct incame_sms *sms, struct modem *mdm, int sim){ char pdu[500]; int found; int ret; found = fetchsms(mdm,sim,pdu); if ( !found ) { LOG(L_ERR,"ERROR:getsms: unable to fetch sms %d!\n",sim); return -1; } /* decode the pdu */ ret = decode_pdu(mdm,pdu,sms); /* delete the sms*/ deletesms(mdm,found); return ret;}int cds2sms(struct incame_sms *sms, struct modem *mdm, char *s, int s_len){ char *data; char *ptr; char tmp; int n; /* pdu starts after 2 "\r\n" */ ptr = s; for ( n=0 ; n<2 && (ptr=strstr(ptr,"\r\n")) ; n++,ptr+=2 ); if (n<2) { LOG(L_ERR,"ERROR:cds2sms: cannot find pdu begining in CDS!\n"); goto error; } data = ptr; /* pdu end with "\r\n" */ if (!(ptr=strstr(data,"\r\n"))) { LOG(L_ERR,"ERROR:cds2sms: cannot find pdu end in CDS!\n"); goto error; } tmp = ptr[0]; ptr[0] = 0; /* decode the pdu */ n = decode_pdu(mdm,data-3,sms); ptr[0] = tmp; if (n==-1) goto error; return 1;error: return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -