/* using http://sourceforge.net/projects/libserial/ */ #include "SmsPdu.h" #include #include #include #include #include "common.h" #include "util.h" using namespace std; namespace SmsPdu { string SwitchChars(string input) { for (unsigned int i=1; i vec) { ostringstream os; for (unsigned int i=0; i(vec.at(i)); } return os.str(); } vector HexDecodeString(string str) { vector vec; for (unsigned int i=0; i input, int shift_start) { string result; int shift = shift_start; for (unsigned int i=0; i0) ? input.at(i-1) : 0; current <<= shift; prev >>= (8-shift); unsigned char byte = current | prev; byte &= 0x7F; result.append(1, byte); if (shift == 6) result.append(1, input.at(i) >> 1); shift = (shift+1) % 7; } return result; } vector Encode7to8bit(std::string str, int shift_start) { vector buf; int shift = shift_start; for (unsigned int i=0; i>= shift; next <<= (7-shift); unsigned char byte = current | next; buf.push_back(byte); if (shift == 6) i++; shift = (shift+1) % 7; } return buf; } vector CreateSmsPdu(string to, string message, bool allowMultipart) { bool multipart = allowMultipart && message.length() > 160; const unsigned char UDHI = multipart ? 0x40 : 0; srand(time(0)); unsigned char csms_ref = rand() % 128; int part_count; const int PDU_LEN = 153; if (multipart) { if (message.length() > 800) { Common::instance()->logMessage("Trying to send multipart sms > 800 bytes !!!"); message = message.substr(0,800); } part_count = message.length() / PDU_LEN; if (message.length() % PDU_LEN) part_count++; } else { part_count = 1; } vector result; for (int partnr = 0; partnr < part_count; ++partnr) { vector pdu; pdu.push_back(0x00); // use SMSC from phone pdu.push_back( 0x01|UDHI ); // first octet -- no timeout pdu.push_back(0x00); // TP-MR message reference pdu.push_back(to.length() ); //length of phone nr pdu.push_back(0x81); // type of address (international nr + ISDN/telephone range) - else try 0x81 vector phone = HexDecodeString( EncodePhonenr(to )); pdu.insert( pdu.end(), phone.begin(), phone.end()); pdu.push_back(0x00); // Protocol identifier pdu.push_back(0x00); // Data coding scheme int shift_start = 0; string message_part; if (multipart) { message_part = message.substr(0, PDU_LEN); message.erase(0, PDU_LEN); pdu.push_back( message_part.length()+ 7 ); //UserDataLength pdu.push_back( 0x06 ); // UDH Len pdu.push_back( 0x00 ); // UDH Element Identifier pdu.push_back( 0x03 ); // UDH element length pdu.push_back( csms_ref ); // csms_ref reference pdu.push_back( part_count ); pdu.push_back( partnr+1 ); pdu.push_back( 0x00); //shift_start = 6; } else { if (message.length() > 160) { message_part = message.substr(0,160); //truncate to 160 Common::instance()->logMessage("Truncated message"); } else { message_part = message; } pdu.push_back( message_part.length() ); //UserDataLength } vector userData = Encode7to8bit(message_part, shift_start); pdu.insert( pdu.end(), userData.begin(), userData.end()); PduInfo info; info.len = pdu.size()-1; info.pdu = HexformatVector(pdu); result.push_back(info); } return result; } typedef vector::iterator char_it; string DecodeRawPhonenr(char_it start, char_it end) { ostringstream os; for (char_it it = start; it != end; ++it) { os.width(2); os.fill('0'); os << hex << (int)(*it); } return DecodePhonenr(os.str()); } string DecodeTimestamp(char_it start, char_it end) { string stamp = DecodeRawPhonenr(start,end); ostringstream os; os << stamp.substr(0,2) << "/"; //year os << stamp.substr(2,2) << "/"; //month os << stamp.substr(4,2) << ","; //day os << stamp.substr(6,2) << ":"; //hour os << stamp.substr(8,2) << ":"; //minute os << stamp.substr(10,2) ; //second int timezone = strtol(stamp.substr(12,2).c_str(), 0, 16); if (timezone > 127) os << "-"; else os << "+"; os.width(2); os.fill('0'); os << (timezone & 0x7F); return os.str(); } SMS ParseSmsPdu(std::string pdu_str) { SMS result; vector pdu = HexDecodeString(pdu_str); vector::iterator it = pdu.begin(); it += (*it++); // Skip smsc info unsigned char deliver_first_octet = (*it++); bool UDHI = (deliver_first_octet & 0x40) > 0; unsigned char sender_len = (*it++); if ( (sender_len % 2) == 1) sender_len++; ++it; //ignore Type-Of-Address result.sender = DecodeRawPhonenr( it, it+(sender_len/2) ); it += (sender_len/2); ++it; //protocol identifier ++it; //Data encoding result.timestamp = DecodeTimestamp(it, it+7); it += 7; unsigned char data_len = (*it++); int shift_start = 0; if (UDHI) { int udh_len = (*it++); it += udh_len; //just ignore the User Data Header data_len -= udh_len; shift_start = udh_len+1; //make the 8to7bit decode start with the right shift level } vector user_data; user_data.insert(user_data.end(), it, it+data_len); result.message = Decode8to7bit(user_data, shift_start).substr(0,data_len); result.message = Util::str_trim(result.message); return result; } }