/[projects]/smsdaemon/SmsPdu.cpp
ViewVC logotype

Diff of /smsdaemon/SmsPdu.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 68 by torben, Thu Jun 12 18:54:24 2008 UTC revision 75 by torben, Fri Jun 13 10:10:06 2008 UTC
# Line 16  Line 16 
16    
17  using namespace std;  using namespace std;
18    
   
19  namespace SmsPdu  namespace SmsPdu
20  {  {
21    
22    
23    
24  string SwitchChars(string input)          string SwitchChars(string input)
 {  
         for (unsigned int i=1; i<input.length(); i+=2)  
25          {          {
26                  char tmp = input[i];                  for (unsigned int i=1; i<input.length(); i+=2)
27                  input[i] = input[i-1];          {
28                  input[i-1] = tmp;                          char tmp = input[i];
29                            input[i] = input[i-1];
30                            input[i-1] = tmp;
31                    }
32                    return input;
33          }          }
         return input;  
 }  
   
 string EncodePhonenr(string input)  
 {  
         if ( (input.length() % 2) == 1)  
                 input.append("F");  
         return SwitchChars(input);  
 }  
   
 string DecodePhonenr(string input)  
 {  
         input = SwitchChars(input);  
         int last = input.length() -1;  
   
         if (input.at(last) == 'F')  
                 input.erase(last,1);  
         return input;  
 }  
   
   
34    
35            string EncodePhonenr(string input)
36            {
37                    if ( input.at(0) == '+' )
38                            input.erase(0,1);
39    
40  string HexformatVector(vector<unsigned char> vec)                  if ( (input.length() % 2) == 1)
41  {                          input.append("F");
42          ostringstream os;                  return SwitchChars(input);
43            }
44    
45          for (unsigned int i=0; i<vec.size(); ++i)          string DecodePhonenr(string input)
46          {          {
47                  os.width(2);                  input = SwitchChars(input);
48                  os.fill('0');                  int last = input.length() -1;
49                  os << hex << uppercase << static_cast<unsigned int>(vec.at(i));  
50                    if (input.at(last) == 'F')
51                            input.erase(last,1);
52                    return input;
53          }          }
54    
55    
         return os.str();  
 }  
56    
 std::string Decode8to7bit(vector<unsigned char> input)  
 {  
         string result;  
57    
58          int shift = 0;          string HexformatVector(vector<unsigned char> vec)
         for (unsigned int i=0; i<input.size(); ++i)  
59          {          {
60                  unsigned char current = input.at(i);                  ostringstream os;
                 unsigned char prev = (i>0) ? input.at(i-1) : 0;  
61    
62                  current <<= shift;                  for (unsigned int i=0; i<vec.size(); ++i)
63                    {
64                            os.width(2);
65                            os.fill('0');
66                            os << hex << uppercase << static_cast<unsigned int>(vec.at(i));
67                    }
68    
                 prev >>= (8-shift);  
69    
70                  unsigned char byte = current | prev;                  return os.str();
71                  byte &= 0x7F;          }
72    
73                  result.append(1, byte);          vector<unsigned char> HexDecodeString(string str)
74            {
75                    vector<unsigned char> vec;
76                    for (unsigned int i=0; i<str.length(); i+=2)
77                            vec.push_back( strtol( str.substr(i,2).c_str(), 0, 16 ));
78    
79                  if (shift == 6)                  return vec;
80                          result.append(1, input.at(i) >> 1);          }
81    
82                  shift = (shift+1) % 7;          std::string Decode8to7bit(vector<unsigned char> input, int shift_start)
83            {
84                    string result;
85    
86          }                  int shift = shift_start;
87                    for (unsigned int i=0; i<input.size(); ++i)
88                    {
89                            unsigned char current = input.at(i);
90                            unsigned char prev = (i>0) ? input.at(i-1) : 0;
91    
92          return result;                          current <<= shift;
 }  
93    
94                            prev >>= (8-shift);
95    
96                            unsigned char byte = current | prev;
97                            byte &= 0x7F;
98    
99                            result.append(1, byte);
100    
101  vector<unsigned char> Encode7to8bit(std::string str)                          if (shift == 6)
102  {                                  result.append(1, input.at(i) >> 1);
         vector<unsigned char> buf;  
103    
104          int shift = 0;                          shift = (shift+1) % 7;
         for (unsigned int i=0; i<str.size(); ++i)  
         {  
                 unsigned char current = str.at(i) & 0x7F;  
                 unsigned char next = ( (i+1)<str.size()) ? str.at(i+1) : 0;  
                 next &= 0x7F;  
105    
106                  current >>= shift;                  }
                 next <<= (7-shift);  
107    
108                  unsigned char byte = current | next;                  return result;
109                  buf.push_back(byte);          }
110    
                 if (shift == 6)  
                         i++;  
111    
                 shift = (shift+1) % 7;  
112    
         }  
113    
114          return buf;          vector<unsigned char> Encode7to8bit(std::string str, int shift_start)
115  }          {
116                    vector<unsigned char> buf;
117    
118  vector<PduInfo> CreateSmsPdu(string to, string message, bool allowMultipart)                  int shift = shift_start;
119  {                  for (unsigned int i=0; i<str.size(); ++i)
120          bool multipart = allowMultipart && message.length() > 160;                  {
121                            unsigned char current = str.at(i) & 0x7F;
122                            unsigned char next = ( (i+1)<str.size()) ? str.at(i+1) : 0;
123                            next &= 0x7F;
124    
125          const unsigned char UDHI = multipart ? 0x40 : 0;                          current >>= shift;
126                            next <<= (7-shift);
127    
128          srand(time(0));                          unsigned char byte = current | next;
129          unsigned char csms_ref = rand() % 128;                          buf.push_back(byte);
130    
131          int part_count;                          if (shift == 6)
132                                    i++;
133    
134          const int PDU_LEN = 153;                          shift = (shift+1) % 7;
135    
         if (multipart)  
         {  
                 if (message.length() > 800)  
                 {  
                         Common::instance()->logMessage("Trying to send multipart sms > 800 bytes !!!");  
                         message = message.substr(0,800);  
136                  }                  }
137    
138                  part_count = message.length() / PDU_LEN;                  return buf;
                 if (message.length() % PDU_LEN)  
                         part_count++;  
         }  
         else  
         {  
                 part_count = 1;  
139          }          }
140    
141          vector<PduInfo> result;          vector<PduInfo> CreateSmsPdu(string to, string message, bool allowMultipart)
         for (int partnr = 0; partnr < part_count; ++partnr)  
142          {          {
143                  vector<unsigned char> pdu;                  bool multipart = allowMultipart && message.length() > 160;
144    
145                  pdu.push_back(0x00); // use SMSC from phone                  const unsigned char UDHI = multipart ? 0x40 : 0;
                 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  
146    
147                                    srand(time(0));
148                  string phone = EncodePhonenr(to);                  unsigned char csms_ref = rand() % 128;
149                  pdu.insert( pdu.end(), phone.begin(), phone.end());  
150                    int part_count;
151    
152                  pdu.push_back(0x00); // Protocol identifier                  const int PDU_LEN = 153;
                 pdu.push_back(0x00); // Data coding scheme  
153    
                 string message_part;  
154                  if (multipart)                  if (multipart)
155                  {                  {
156                          message_part = message.substr(0, PDU_LEN);                          if (message.length() > 800)
157                          message.erase(0, PDU_LEN);                          {
158                                    Common::instance()->logMessage("Trying to send multipart sms > 800 bytes !!!");
159                          pdu.push_back( message_part.length()+ 7 );  //UserDataLength                                  message = message.substr(0,800);
160                          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);  
161    
162                            part_count = message.length() / PDU_LEN;
163                            if (message.length() % PDU_LEN)
164                                    part_count++;
165                  }                  }
166                  else                  else
167                  {                  {
168                          if (message.length() > 160)                          part_count = 1;
169                    }
170    
171                    vector<PduInfo> result;
172                    for (int partnr = 0; partnr < part_count; ++partnr)
173                    {
174                            vector<unsigned char> pdu;
175    
176                            pdu.push_back(0x00); // use SMSC from phone
177                            pdu.push_back( 0x01|UDHI ); // first octet -- no timeout
178                            pdu.push_back(0x00); // TP-MR message reference
179                            pdu.push_back(to.length() ); //length of phone nr
180                            pdu.push_back(0x81); // type of address (international nr  + ISDN/telephone range) - else try 0x81
181    
182    
183                            vector<unsigned char> phone = HexDecodeString( EncodePhonenr(to ));
184                            pdu.insert( pdu.end(), phone.begin(), phone.end());
185    
186                            pdu.push_back(0x00); // Protocol identifier
187                            pdu.push_back(0x00); // Data coding scheme
188    
189                            int shift_start = 0;
190                            string message_part;
191                            if (multipart)
192                          {                          {
193                                  message_part = message.substr(0,160); //truncate to 160                                  message_part = message.substr(0, PDU_LEN);
194                                  Common::instance()->logMessage("Truncated message");                                  message.erase(0, PDU_LEN);
195    
196                                    pdu.push_back( message_part.length()+ 7 );  //UserDataLength
197                                    pdu.push_back( 0x06 ); // UDH Len
198                                    pdu.push_back( 0x00 ); // UDH Element Identifier
199                                    pdu.push_back( 0x03 ); // UDH element length
200                                    pdu.push_back( csms_ref ); // csms_ref reference
201                                    pdu.push_back( part_count );
202                                    pdu.push_back( partnr+1 );
203                                    pdu.push_back( 0x00);
204                                    //shift_start = 6;
205                          }                          }
206                          else                          else
207                          {                          {
208                                  message_part = message;                                  if (message.length() > 160)
209                                    {
210                                            message_part = message.substr(0,160); //truncate to 160
211                                            Common::instance()->logMessage("Truncated message");
212                                    }
213                                    else
214                                    {
215                                            message_part = message;
216                                    }
217    
218                                    pdu.push_back( message_part.length() ); //UserDataLength
219                          }                          }
220    
221                          pdu.push_back( message_part.length() ); //UserDataLength                          vector<unsigned char> userData = Encode7to8bit(message_part, shift_start);
222    
223                            pdu.insert( pdu.end(), userData.begin(), userData.end());
224    
225                            PduInfo info;
226                            info.len = pdu.size()-1;
227                            info.pdu = HexformatVector(pdu);
228                            result.push_back(info);
229    
230                    }
231                    return result;
232            }
233    
234            typedef vector<unsigned char>::iterator char_it;
235    
236            string DecodeRawPhonenr(char_it start, char_it end)
237            {
238                    ostringstream os;
239    
240                    for (char_it it = start; it != end; ++it)
241                    {
242                            os.width(2);
243                            os.fill('0');
244                            os << hex << (int)(*it);
245                  }                  }
246                    return DecodePhonenr(os.str());
247            }
248    
249            string DecodeTimestamp(char_it start, char_it end)
250            {
251                    string stamp = DecodeRawPhonenr(start,end);
252    
253                    ostringstream os;
254    
255                    os << stamp.substr(0,2) << "/"; //year
256                    os << stamp.substr(2,2) << "/"; //month
257                    os << stamp.substr(4,2) << ","; //day
258                    os << stamp.substr(6,2) << ":"; //hour
259                    os << stamp.substr(8,2) << ":"; //minute
260                    os << stamp.substr(10,2) ; //second
261    
262                    int timezone = strtol(stamp.substr(12,2).c_str(), 0, 16);
263    
264    
265                    if (timezone > 127)
266                            os << "-";
267                    else
268                            os << "+";
269    
270                  vector<unsigned char> userData = Encode7to8bit(message_part);                  os.width(2);
271                    os.fill('0');
272                    os << (timezone & 0x7F);
273    
274                    return os.str();
275            }
276    
277    
278            SMS ParseSmsPdu(std::string pdu_str)
279            {
280                    SMS result;
281    
282                    vector<unsigned char> pdu = HexDecodeString(pdu_str);
283    
284                    vector<unsigned char>::iterator it = pdu.begin();
285    
286                    it += (*it++); // Skip smsc info
287    
288                    unsigned char deliver_first_octet = (*it++);
289    
290                    bool UDHI = (deliver_first_octet & 0x40) > 0;
291    
292                    unsigned char sender_len = (*it++);
293                    if ( (sender_len % 2) == 1)
294                            sender_len++;
295    
296                  pdu.insert( pdu.end(), userData.begin(), userData.end());                  ++it; //ignore Type-Of-Address
297    
298                  PduInfo info;                  result.sender = DecodeRawPhonenr( it, it+(sender_len/2) );
                 info.len = pdu.size()-1;  
                 info.pdu = HexformatVector(pdu);  
                 result.push_back(info);  
299    
300                    it += (sender_len/2);
301                    ++it; //protocol identifier
302                    ++it; //Data encoding
303    
304                    result.timestamp = DecodeTimestamp(it, it+7);
305                    it += 7;
306    
307    
308                    unsigned char data_len = (*it++);
309    
310                    int shift_start = 0;
311                    if (UDHI)
312                    {
313                            int udh_len = (*it++);
314                            it += udh_len; //just ignore the User Data Header
315                            data_len -= udh_len;
316    
317                            shift_start = udh_len+1; //make the 8to7bit decode start with the right shift level
318                    }
319    
320    
321                    vector<unsigned char> user_data;
322                    user_data.insert(user_data.end(), it, it+data_len);
323                    
324                    result.message = Decode8to7bit(user_data, shift_start);
325                    
326    
327                    return result;
328          }          }
         return result;  
 }  
329    
330  }  }
331    

Legend:
Removed from v.68  
changed lines
  Added in v.75

  ViewVC Help
Powered by ViewVC 1.1.20