Merge branch 'master' into tizen_2.0
[platform/core/messaging/msg-service.git] / plugin / sms_plugin / SmsPluginParamCodec.cpp
1 /*
2 * Copyright 2012-2013  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 "MsgTextConvert.h"
22 #include "SmsPluginUDCodec.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         MsgTextConvert textCvt;
265         memset(pAddress->address, 0x00, sizeof(pAddress->address));
266
267         addrLen = (int)pTpdu[offset++];
268
269         if (addrLen % 2 == 0)
270                 bcdLen = addrLen/2;
271         else
272                 bcdLen = addrLen/2 + 1;
273
274         pAddress->ton = (pTpdu[offset] & 0x70) >> 4;
275         pAddress->npi = pTpdu[offset++] & 0x0F;
276
277 MSG_DEBUG("ton [%d]", pAddress->ton);
278 MSG_DEBUG("npi [%d]", pAddress->npi);
279
280         if (pAddress->ton == SMS_TON_ALPHANUMERIC)
281         {
282                 MSG_DEBUG("Alphanumeric address");
283
284                 char* tmpAddress = new char[MAX_ADDRESS_LEN];
285                 int tmplength = 0;
286
287                 tmplength = SmsPluginUDCodec::unpack7bitChar(&(pTpdu[offset]), bcdLen, 0, tmpAddress);
288
289                 MSG_LANG_INFO_S langInfo = {0,};
290
291                 langInfo.bSingleShift = false;
292                 langInfo.bLockingShift = false;
293
294                 textCvt.convertGSM7bitToUTF8((unsigned char*)pAddress->address, MAX_ADDRESS_LEN, (unsigned char*)tmpAddress, tmplength, &langInfo);
295
296                 if (tmpAddress)
297                         delete[] tmpAddress;
298         }
299         else if (pAddress->ton == SMS_TON_INTERNATIONAL)
300         {
301                 (pAddress->address)[0] = '+';
302                 convertBcdToDigit(&(pTpdu[offset]), bcdLen, &((pAddress->address)[1]));
303         }
304         else
305         {
306                 convertBcdToDigit(&(pTpdu[offset]), bcdLen, &((pAddress->address)[0]));
307         }
308
309         offset +=       bcdLen;
310
311 //MSG_DEBUG("address [%s]", pAddress->address);
312
313         return offset;
314 }
315
316
317 int SmsPluginParamCodec::decodeTime(const unsigned char *pTpdu, SMS_TIMESTAMP_S *pTimeStamp)
318 {
319         int offset = 0;
320
321         // decode in ABSOLUTE time type.
322         pTimeStamp->format = SMS_TIME_ABSOLUTE;
323
324         pTimeStamp->time.absolute.year = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
325         offset++;
326
327         pTimeStamp->time.absolute.month = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
328         offset++;
329
330         pTimeStamp->time.absolute.day = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
331         offset++;
332
333         pTimeStamp->time.absolute.hour = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
334         offset++;
335
336         pTimeStamp->time.absolute.minute = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
337         offset++;
338
339         pTimeStamp->time.absolute.second = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
340         offset++;
341
342         pTimeStamp->time.absolute.timeZone = (pTpdu[offset] & 0x07)*10 + ((pTpdu[offset] & 0xF0) >> 4);
343
344         if (pTpdu[offset] & 0x08)
345                 pTimeStamp->time.absolute.timeZone *= (-1);
346
347         offset++;
348
349         return offset;
350 }
351
352
353 int SmsPluginParamCodec::decodeDCS(const unsigned char *pTpdu, SMS_DCS_S *pDCS)
354 {
355         int offset = 0;
356         char dcs = pTpdu[offset++];
357
358         pDCS->bMWI = false;
359         pDCS->bIndActive = false;
360         pDCS->indType = SMS_OTHER_INDICATOR;
361
362         if (((dcs & 0xC0) >> 6) == 0)
363         {
364                 pDCS->codingGroup = SMS_GROUP_GENERAL;
365                 pDCS->bCompressed = (dcs & 0x20) >> 5;
366                 pDCS->codingScheme = (dcs & 0x0C) >> 2;
367
368                 if (((dcs & 0x10) >> 4) == 0)
369                         pDCS->msgClass = SMS_MSG_CLASS_NONE;
370                 else
371                         pDCS->msgClass = dcs & 0x03;
372         }
373         else if (((dcs & 0xF0) >> 4) == 0x0F)
374         {
375                 pDCS->codingGroup = SMS_GROUP_CODING_CLASS;
376                 pDCS->bCompressed = false;
377                 pDCS->codingScheme = (dcs & 0x0C) >> 2;
378
379                 pDCS->msgClass = dcs & 0x03;
380         }
381         else if (((dcs & 0xC0) >> 6) == 1)
382         {
383                 pDCS->codingGroup = SMS_GROUP_DELETION;
384                 pDCS->bCompressed = false;
385                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
386
387                 // TODO: finish here. ??
388         }
389         else if (((dcs & 0xF0) >> 4) == 0x0C)
390         {
391                 pDCS->codingGroup = SMS_GROUP_DISCARD;
392                 pDCS->bCompressed = false;
393                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
394
395                 pDCS->bMWI = true;
396                 pDCS->bIndActive = (((dcs & 0x08) >> 3) == 1)? true:false;
397                 pDCS->indType = (SMS_INDICATOR_TYPE_T)(dcs & 0x03);
398         }
399         else if (((dcs & 0xF0) >> 4) == 0x0D)
400         {
401                 pDCS->codingGroup = SMS_GROUP_STORE;
402                 pDCS->codingScheme = SMS_CHARSET_7BIT;
403                 pDCS->bCompressed = false;
404                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
405
406                 pDCS->bMWI = true;
407                 pDCS->bIndActive = (((dcs & 0x08) >> 3) == 1)? true:false;
408                 pDCS->indType = (SMS_INDICATOR_TYPE_T)(dcs & 0x03);
409         }
410         else if (((dcs & 0xF0) >> 4) == 0x0E)
411         {
412                 pDCS->codingGroup = SMS_GROUP_STORE;
413                 pDCS->codingScheme = SMS_CHARSET_UCS2;
414                 pDCS->bCompressed = false;
415                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
416
417                 pDCS->bMWI = true;
418                 pDCS->bIndActive = (((dcs & 0x08) >> 3) == 1)? false:true;
419                 pDCS->indType = (SMS_INDICATOR_TYPE_T)(dcs & 0x03);
420         }
421         else
422         {
423                 pDCS->codingGroup = SMS_GROUP_UNKNOWN;
424
425                 pDCS->bCompressed = (dcs & 0x20) >> 5;
426                 pDCS->codingScheme = (dcs & 0x0C) >> 2;
427
428                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
429         }
430
431         return offset;
432 }
433
434
435 void SmsPluginParamCodec::decodeSMSC(unsigned char* pAddress, int AddrLen, MSG_SMS_TON_T ton, char *pDecodeAddr)
436 {
437         if (pAddress == NULL || AddrLen == 0)
438                 return;
439
440         if (ton == SMS_TON_INTERNATIONAL)
441         {
442                 pDecodeAddr[0] = '+';
443                 convertBcdToDigit(pAddress, AddrLen, &(pDecodeAddr[1]));
444         }
445         else
446         {
447                 convertBcdToDigit(pAddress, AddrLen, pDecodeAddr);
448         }
449 }
450
451
452 /*==================================================================================================
453                                      Util Functions
454 ==================================================================================================*/
455 int SmsPluginParamCodec::convertDigitToBcd(char *pDigit, int DigitLen, unsigned char *pBcd)
456 {
457         int offset = 0;
458         unsigned char temp;
459
460 //MSG_DEBUG("DigitLen [%d]", DigitLen);
461 //MSG_DEBUG("pDigit [%s]", pDigit);
462
463         for (int i = 0; i < DigitLen; i++)
464         {
465                 if (pDigit[i] == '*')
466                         temp = 0x0A;
467                 else if (pDigit[i] == '#')
468                         temp = 0x0B;
469                 else if (pDigit[i] == 'P' || pDigit[i] == 'p')
470                         temp = 0x0C;
471                 else
472                         temp = pDigit[i] - '0';
473
474                 if ((i%2) == 0)
475                         pBcd[offset] = temp & 0x0F;
476                 else
477                         pBcd[offset++] |= ((temp & 0x0F) << 4);
478         }
479
480         if ((DigitLen%2) == 1)
481         {
482                 pBcd[offset++] |= 0xF0;
483         }
484
485         return offset;
486 }
487
488
489 int SmsPluginParamCodec::convertBcdToDigit(const unsigned char *pBcd, int BcdLen, char *pDigit)
490 {
491         int offset = 0;
492         unsigned char temp;
493
494         for (int i = 0; i < BcdLen; i++)
495         {
496                 temp = pBcd[i] & 0x0F;
497
498                 if (temp == 0x0A)
499                         pDigit[offset++] = '*';
500                 else if (temp == 0x0B)
501                         pDigit[offset++] = '#';
502                 else if (temp == 0x0C)
503                         pDigit[offset++] = 'P';
504                 else
505                         pDigit[offset++] = temp + '0';
506
507                 temp = (pBcd[i] & 0xF0) >> 4;
508
509                 if (temp == 0x0F)
510                 {
511                         pDigit[offset] = '\0';
512                         return offset;
513                 }
514
515                 if (temp == 0x0A)
516                         pDigit[offset++] = '*';
517                 else if (temp == 0x0B)
518                         pDigit[offset++] = '#';
519                 else if (temp == 0x0C)
520                         pDigit[offset++] = 'P';
521                 else
522                         pDigit[offset++] = temp + '0';
523         }
524
525         pDigit[offset] = '\0';
526
527         return offset;
528 }
529