2.0_beta
[platform/core/messaging/msg-service.git] / plugin / sms_plugin / SmsPluginParamCodec.cpp
1 /*
2 * Copyright 2012  Samsung Electronics Co., Ltd
3 *
4 * Licensed under the Flora License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *    http://www.tizenopensource.org/license
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <string.h>
19
20 #include "MsgDebug.h"
21 #include "SmsPluginUDCodec.h"
22 #include "SmsPluginTextConvert.h"
23 #include "SmsPluginParamCodec.h"
24
25
26 /*==================================================================================================
27                                      IMPLEMENTATION OF SmsPluginParamCodec - Member Functions
28 ==================================================================================================*/
29 SmsPluginParamCodec::SmsPluginParamCodec()
30 {
31
32
33 }
34
35
36 SmsPluginParamCodec::~SmsPluginParamCodec()
37 {
38
39
40 }
41
42
43 /*==================================================================================================
44                                      Encode Functions
45 ==================================================================================================*/
46 int SmsPluginParamCodec::encodeAddress(const SMS_ADDRESS_S *pAddress, char **ppParam)
47 {
48         int offset = 0, length = 0;
49         char *temp = (char *)pAddress->address;
50
51         SMS_TON_T ton;
52
53         *ppParam = new char[MAX_ADD_PARAM_LEN];
54
55         // Set Address Length
56         if (temp[0] == '+')
57         {
58                 (*ppParam)[offset++] = strlen(temp) - 1;
59                 temp++;
60
61                 ton = SMS_TON_INTERNATIONAL;
62         }
63         else
64         {
65                 (*ppParam)[offset++] = strlen(temp);
66
67                 ton = pAddress->ton;
68         }
69
70         // Set TON, NPI
71         (*ppParam)[offset++] = 0x80 + (ton << 4) + pAddress->npi;
72
73         MSG_DEBUG("Address length is %d.", (*ppParam)[0]);
74         MSG_DEBUG("pAddress->ton : %d.", ton);
75         MSG_DEBUG("pAddress->npi : %d.", pAddress->npi);
76
77         length = convertDigitToBcd(temp, strlen(temp), (unsigned char *) &((*ppParam)[offset]));
78
79         offset += length;
80
81         return offset ;
82 }
83
84
85 int SmsPluginParamCodec::encodeTime(const SMS_TIMESTAMP_S *pTimeStamp, char **ppParam)
86 {
87         int offset = 0;
88
89         if(pTimeStamp->format == SMS_TIME_ABSOLUTE)
90         {
91                 int timeZone = pTimeStamp->time.absolute.timeZone;
92                 *ppParam = new char[MAX_ABS_TIME_PARAM_LEN];
93
94                 (*ppParam)[offset++] = ((pTimeStamp->time.absolute.year % 10)  << 4) + (pTimeStamp->time.absolute.year / 10);
95                 (*ppParam)[offset++] = ((pTimeStamp->time.absolute.month % 10) << 4) + (pTimeStamp->time.absolute.month / 10);
96                 (*ppParam)[offset++] = ((pTimeStamp->time.absolute.day % 10) << 4) + (pTimeStamp->time.absolute.day / 10);
97                 (*ppParam)[offset++] = ((pTimeStamp->time.absolute.hour % 10) << 4) + (pTimeStamp->time.absolute.hour / 10);
98                 (*ppParam)[offset++] = ((pTimeStamp->time.absolute.minute % 10) << 4) + (pTimeStamp->time.absolute.minute / 10);
99                 (*ppParam)[offset++] = ((pTimeStamp->time.absolute.second % 10) << 4) + (pTimeStamp->time.absolute.second / 10);
100
101                 if(timeZone < 0)
102                 {
103                         timeZone *= -1;
104                         (*ppParam)[offset] = 0x08;
105                 }
106                 (*ppParam)[offset++] += ((pTimeStamp->time.absolute.timeZone % 10) << 4) + (pTimeStamp->time.absolute.timeZone / 10);
107
108
109                 return offset;
110         }
111         else if(pTimeStamp->format == SMS_TIME_RELATIVE)
112         {
113                 *ppParam = new char[MAX_REL_TIME_PARAM_LEN+1];
114
115                 memcpy(*ppParam, &(pTimeStamp->time.relative.time), MAX_REL_TIME_PARAM_LEN);
116
117                 return MAX_REL_TIME_PARAM_LEN;
118         }
119
120         return offset;
121 }
122
123
124 int SmsPluginParamCodec::encodeDCS(const SMS_DCS_S *pDCS, char **ppParam)
125 {
126         *ppParam = new char;
127
128         **ppParam = 0x00;
129
130         switch (pDCS->codingGroup)
131         {
132                 case SMS_GROUP_GENERAL:
133                 {
134                         if (pDCS->msgClass != SMS_MSG_CLASS_NONE)
135                         {
136                                 **ppParam = 0x10 + pDCS->msgClass;
137                         }
138
139                         if (pDCS->bCompressed)
140                         {
141                                 **ppParam |= 0x20;
142                         }
143                 }
144                 break;
145
146                 case SMS_GROUP_CODING_CLASS:
147                 {
148                         **ppParam = 0xF0 + pDCS->msgClass;
149                 }
150                 break;
151
152                 case SMS_GROUP_DELETION:
153                         //not supported
154                 break;
155
156                 case SMS_GROUP_DISCARD:
157                         //not supported
158                 break;
159
160                 case SMS_GROUP_STORE:
161                         //not supported
162                 break;
163
164                 default:
165                         return 0;
166         }
167
168         switch (pDCS->codingScheme)
169         {
170                 case SMS_CHARSET_7BIT:
171
172                 break;
173
174                 case SMS_CHARSET_8BIT:
175                         **ppParam |= 0x04;
176                 break;
177
178                 case SMS_CHARSET_UCS2:
179                         **ppParam |= 0x08;
180                 break;
181
182                 default:
183                         return 0;
184         }
185
186         return 1;
187 }
188
189
190 int SmsPluginParamCodec::encodeSMSC(const char *pAddress, unsigned char *pEncodeAddr)
191 {
192         char newAddr[MAX_SMSC_LEN+1];
193         memset(newAddr, 0x00, sizeof(newAddr));
194
195 //MSG_DEBUG("SMSC [%s]", pAddress);
196
197         if (pAddress[0] == '+')
198         {
199                 strncpy(newAddr, pAddress+1, MAX_SMSC_LEN);
200         }
201         else
202         {
203                 strncpy(newAddr, pAddress, MAX_SMSC_LEN);
204         }
205
206         // Set Address
207         int encodeLen = convertDigitToBcd(newAddr, strlen(newAddr), pEncodeAddr);
208
209         pEncodeAddr[encodeLen] = '\0';
210
211         return encodeLen;
212 }
213
214
215 int SmsPluginParamCodec::encodeSMSC(const SMS_ADDRESS_S *pAddress, unsigned char *pSMSC)
216 {
217         char newAddr[MAX_SMSC_LEN+1];
218         memset(newAddr, 0x00, sizeof(newAddr));
219
220         int dataSize = 0, addrLen = 0;
221
222         if (pAddress->address[0] == '+')
223                 memcpy(newAddr, pAddress->address+1, strlen(pAddress->address)-1);
224         else
225                 memcpy(newAddr, pAddress->address, strlen(pAddress->address));
226
227         addrLen = strlen(newAddr);
228
229         if (addrLen % 2 == 0)
230                 dataSize = 2 + (addrLen/2);
231         else
232                 dataSize = 2 + (addrLen/2) + 1;
233
234         if (dataSize > MAX_SMSC_LEN)
235         {
236                 MSG_DEBUG("addrLen is too long [%d]", addrLen);
237                 MSG_DEBUG("dataSize is too long [%d]", dataSize);
238
239                 return 0;
240         }
241
242         // Set Address Length
243         // Check IPC 4.0 -> addrLen/2
244         pSMSC[0] = addrLen;
245
246         // Set TON, NPI
247         pSMSC[1] = 0x80 + (pAddress->ton << 4) + pAddress->npi;
248
249         // Set Address
250         convertDigitToBcd(newAddr, addrLen, &(pSMSC[2]));
251
252         pSMSC[dataSize] = '\0';
253
254         return dataSize;
255 }
256
257
258 /*==================================================================================================
259                                      Decode Functions
260 ==================================================================================================*/
261 int SmsPluginParamCodec::decodeAddress(const unsigned char *pTpdu, SMS_ADDRESS_S *pAddress)
262 {
263         int offset = 0, addrLen = 0, bcdLen = 0;
264         memset(pAddress->address, 0x00, sizeof(pAddress->address));
265
266         addrLen = (int)pTpdu[offset++];
267
268         if (addrLen % 2 == 0)
269                 bcdLen = addrLen/2;
270         else
271                 bcdLen = addrLen/2 + 1;
272
273         pAddress->ton = (pTpdu[offset] & 0x70) >> 4;
274         pAddress->npi = pTpdu[offset++] & 0x0F;
275
276 MSG_DEBUG("ton [%d]", pAddress->ton);
277 MSG_DEBUG("npi [%d]", pAddress->npi);
278
279         if (pAddress->ton == SMS_TON_ALPHANUMERIC)
280         {
281                 MSG_DEBUG("Alphanumeric address");
282
283                 char* tmpAddress = new char[MAX_ADDRESS_LEN];
284                 int tmplength = 0;
285
286                 tmplength = SmsPluginUDCodec::unpack7bitChar(&(pTpdu[offset]), bcdLen, 0, tmpAddress);
287
288                 SMS_LANG_INFO_S langInfo = {0};
289
290                 langInfo.bSingleShift = false;
291                 langInfo.bLockingShift = false;
292
293                 SmsPluginTextConvert::instance()->convertGSM7bitToUTF8((unsigned char*)pAddress->address, MAX_ADDRESS_LEN, (unsigned char*)tmpAddress, tmplength, &langInfo);
294         }
295         else if (pAddress->ton == SMS_TON_INTERNATIONAL)
296         {
297                 (pAddress->address)[0] = '+';
298                 convertBcdToDigit(&(pTpdu[offset]), bcdLen, &((pAddress->address)[1]));
299         }
300         else
301         {
302                 convertBcdToDigit(&(pTpdu[offset]), bcdLen, &((pAddress->address)[0]));
303         }
304
305         offset +=       bcdLen;
306
307 //MSG_DEBUG("address [%s]", pAddress->address);
308
309         return offset;
310 }
311
312
313 int SmsPluginParamCodec::decodeTime(const unsigned char *pTpdu, SMS_TIMESTAMP_S *pTimeStamp)
314 {
315         int offset = 0;
316
317         // decode in ABSOLUTE time type.
318         pTimeStamp->format = SMS_TIME_ABSOLUTE;
319
320         pTimeStamp->time.absolute.year = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
321         offset++;
322
323         pTimeStamp->time.absolute.month = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
324         offset++;
325
326         pTimeStamp->time.absolute.day = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
327         offset++;
328
329         pTimeStamp->time.absolute.hour = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
330         offset++;
331
332         pTimeStamp->time.absolute.minute = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
333         offset++;
334
335         pTimeStamp->time.absolute.second = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
336         offset++;
337
338         pTimeStamp->time.absolute.timeZone = (pTpdu[offset] & 0x07)*10 + ((pTpdu[offset] & 0xF0) >> 4);
339
340         if (pTpdu[offset] & 0x08)
341                 pTimeStamp->time.absolute.timeZone *= (-1);
342
343         offset++;
344
345         return offset;
346 }
347
348
349 int SmsPluginParamCodec::decodeDCS(const unsigned char *pTpdu, SMS_DCS_S *pDCS)
350 {
351         int offset = 0;
352         char dcs = pTpdu[offset++];
353
354         pDCS->bMWI = false;
355         pDCS->bIndActive = false;
356         pDCS->indType = SMS_OTHER_INDICATOR;
357
358         if (((dcs & 0xC0) >> 6) == 0)
359         {
360                 pDCS->codingGroup = SMS_GROUP_GENERAL;
361                 pDCS->bCompressed = (dcs & 0x20) >> 5;
362                 pDCS->codingScheme = (dcs & 0x0C) >> 2;
363
364                 if (((dcs & 0x10) >> 4) == 0)
365                         pDCS->msgClass = SMS_MSG_CLASS_NONE;
366                 else
367                         pDCS->msgClass = dcs & 0x03;
368         }
369         else if (((dcs & 0xF0) >> 4) == 0x0F)
370         {
371                 pDCS->codingGroup = SMS_GROUP_CODING_CLASS;
372                 pDCS->bCompressed = false;
373                 pDCS->codingScheme = (dcs & 0x0C) >> 2;
374
375                 pDCS->msgClass = dcs & 0x03;
376         }
377         else if (((dcs & 0xC0) >> 6) == 1)
378         {
379                 pDCS->codingGroup = SMS_GROUP_DELETION;
380                 pDCS->bCompressed = false;
381                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
382
383                 // TODO: finish here. ??
384         }
385         else if (((dcs & 0xF0) >> 4) == 0x0C)
386         {
387                 pDCS->codingGroup = SMS_GROUP_DISCARD;
388                 pDCS->bCompressed = false;
389                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
390
391                 pDCS->bMWI = true;
392                 pDCS->bIndActive = (((dcs & 0x08) >> 3) == 1)? false:true;
393                 pDCS->indType = (SMS_INDICATOR_TYPE_T)(dcs & 0x03);
394         }
395         else if (((dcs & 0xF0) >> 4) == 0x0D)
396         {
397                 pDCS->codingGroup = SMS_GROUP_STORE;
398                 pDCS->codingScheme = SMS_CHARSET_7BIT;
399                 pDCS->bCompressed = false;
400                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
401
402                 pDCS->bMWI = true;
403                 pDCS->bIndActive = (((dcs & 0x08) >> 3) == 1)? false:true;
404                 pDCS->indType = (SMS_INDICATOR_TYPE_T)(dcs & 0x03);
405         }
406         else if (((dcs & 0xF0) >> 4) == 0x0E)
407         {
408                 pDCS->codingGroup = SMS_GROUP_STORE;
409                 pDCS->codingScheme = SMS_CHARSET_UCS2;
410                 pDCS->bCompressed = false;
411                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
412
413                 pDCS->bMWI = true;
414                 pDCS->bIndActive = (((dcs & 0x08) >> 3) == 1)? false:true;
415                 pDCS->indType = (SMS_INDICATOR_TYPE_T)(dcs & 0x03);
416         }
417         else
418         {
419                 pDCS->codingGroup = SMS_GROUP_UNKNOWN;
420
421                 pDCS->bCompressed = (dcs & 0x20) >> 5;
422                 pDCS->codingScheme = (dcs & 0x0C) >> 2;
423
424                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
425         }
426
427         return offset;
428 }
429
430
431 void SmsPluginParamCodec::decodeSMSC(unsigned char* pAddress, int AddrLen, MSG_SMS_TON_T ton, char *pDecodeAddr)
432 {
433         if (pAddress == NULL || AddrLen == 0)
434                 return;
435
436         if (ton == SMS_TON_INTERNATIONAL)
437         {
438                 pDecodeAddr[0] = '+';
439                 convertBcdToDigit(pAddress, AddrLen, &(pDecodeAddr[1]));
440         }
441         else
442         {
443                 convertBcdToDigit(pAddress, AddrLen, pDecodeAddr);
444         }
445 }
446
447
448 /*==================================================================================================
449                                      Util Functions
450 ==================================================================================================*/
451 int SmsPluginParamCodec::convertDigitToBcd(char *pDigit, int DigitLen, unsigned char *pBcd)
452 {
453         int offset = 0;
454         unsigned char temp;
455
456 //MSG_DEBUG("DigitLen [%d]", DigitLen);
457 //MSG_DEBUG("pDigit [%s]", pDigit);
458
459         for (int i = 0; i < DigitLen; i++)
460         {
461                 if (pDigit[i] == '*')
462                         temp = 0x0A;
463                 else if (pDigit[i] == '#')
464                         temp = 0x0B;
465                 else if (pDigit[i] == 'P' || pDigit[i] == 'p')
466                         temp = 0x0C;
467                 else
468                         temp = pDigit[i] - '0';
469
470                 if ((i%2) == 0)
471                         pBcd[offset] = temp & 0x0F;
472                 else
473                         pBcd[offset++] |= ((temp & 0x0F) << 4);
474         }
475
476         if ((DigitLen%2) == 1)
477         {
478                 pBcd[offset++] |= 0xF0;
479         }
480
481         return offset;
482 }
483
484
485 int SmsPluginParamCodec::convertBcdToDigit(const unsigned char *pBcd, int BcdLen, char *pDigit)
486 {
487         int offset = 0;
488         unsigned char temp;
489
490         for (int i = 0; i < BcdLen; i++)
491         {
492                 temp = pBcd[i] & 0x0F;
493
494                 if (temp == 0x0A)
495                         pDigit[offset++] = '*';
496                 else if (temp == 0x0B)
497                         pDigit[offset++] = '#';
498                 else if (temp == 0x0C)
499                         pDigit[offset++] = 'P';
500                 else
501                         pDigit[offset++] = temp + '0';
502
503                 temp = (pBcd[i] & 0xF0) >> 4;
504
505                 if (temp == 0x0F)
506                 {
507                         pDigit[offset] = '\0';
508                         return offset;
509                 }
510
511                 if (temp == 0x0A)
512                         pDigit[offset++] = '*';
513                 else if (temp == 0x0B)
514                         pDigit[offset++] = '#';
515                 else if (temp == 0x0C)
516                         pDigit[offset++] = 'P';
517                 else
518                         pDigit[offset++] = temp + '0';
519         }
520
521         pDigit[offset] = '\0';
522
523         return offset;
524 }
525