Sync with tizen 2.4
[platform/core/messaging/msg-service.git] / plugin / sms_plugin / SmsPluginParamCodec.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved
3  *
4  * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
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 = MsgTextConvert::instance();
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]), (addrLen*4 )/7, 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                 convertBcdToDigit(&(pTpdu[offset]), bcdLen, &((pAddress->address)[1]));
302                 if (pAddress->address[1] != '\0')
303                         pAddress->address[0] = '+';
304         }
305         else
306         {
307                 convertBcdToDigit(&(pTpdu[offset]), bcdLen, &((pAddress->address)[0]));
308         }
309
310         offset +=       bcdLen;
311
312 //MSG_DEBUG("address [%s]", pAddress->address);
313
314         return offset;
315 }
316
317
318 int SmsPluginParamCodec::decodeTime(const unsigned char *pTpdu, SMS_TIMESTAMP_S *pTimeStamp)
319 {
320         int offset = 0;
321
322         // decode in ABSOLUTE time type.
323         pTimeStamp->format = SMS_TIME_ABSOLUTE;
324
325         pTimeStamp->time.absolute.year = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
326         offset++;
327
328         pTimeStamp->time.absolute.month = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
329         offset++;
330
331         pTimeStamp->time.absolute.day = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
332         offset++;
333
334         pTimeStamp->time.absolute.hour = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
335         offset++;
336
337         pTimeStamp->time.absolute.minute = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
338         offset++;
339
340         pTimeStamp->time.absolute.second = (pTpdu[offset] & 0x0F)*10 + ((pTpdu[offset] & 0xF0) >> 4);
341         offset++;
342
343         pTimeStamp->time.absolute.timeZone = (pTpdu[offset] & 0x07)*10 + ((pTpdu[offset] & 0xF0) >> 4);
344
345         if (pTpdu[offset] & 0x08)
346                 pTimeStamp->time.absolute.timeZone *= (-1);
347
348         offset++;
349
350         return offset;
351 }
352
353
354 int SmsPluginParamCodec::decodeDCS(const unsigned char *pTpdu, SMS_DCS_S *pDCS)
355 {
356         int offset = 0;
357         char dcs = pTpdu[offset++];
358
359         pDCS->bMWI = false;
360         pDCS->bIndActive = false;
361         pDCS->indType = SMS_OTHER_INDICATOR;
362
363         if (((dcs & 0xC0) >> 6) == 0)
364         {
365                 pDCS->codingGroup = SMS_GROUP_GENERAL;
366                 pDCS->bCompressed = (dcs & 0x20) >> 5;
367                 pDCS->codingScheme = (dcs & 0x0C) >> 2;
368
369                 if (((dcs & 0x10) >> 4) == 0)
370                         pDCS->msgClass = SMS_MSG_CLASS_NONE;
371                 else
372                         pDCS->msgClass = dcs & 0x03;
373         }
374         else if (((dcs & 0xF0) >> 4) == 0x0F)
375         {
376                 pDCS->codingGroup = SMS_GROUP_CODING_CLASS;
377                 pDCS->bCompressed = false;
378                 pDCS->codingScheme = (dcs & 0x0C) >> 2;
379
380                 pDCS->msgClass = dcs & 0x03;
381         }
382         else if (((dcs & 0xC0) >> 6) == 1)
383         {
384                 pDCS->codingGroup = SMS_GROUP_DELETION;
385                 pDCS->bCompressed = false;
386                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
387
388                 // TODO: finish here. ??
389         }
390         else if (((dcs & 0xF0) >> 4) == 0x0C)
391         {
392                 pDCS->codingGroup = SMS_GROUP_DISCARD;
393                 pDCS->bCompressed = false;
394                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
395
396                 pDCS->bMWI = true;
397                 pDCS->bIndActive = (((dcs & 0x08) >> 3) == 1)? true:false;
398                 pDCS->indType = (SMS_INDICATOR_TYPE_T)(dcs & 0x03);
399         }
400         else if (((dcs & 0xF0) >> 4) == 0x0D)
401         {
402                 pDCS->codingGroup = SMS_GROUP_STORE;
403                 pDCS->codingScheme = SMS_CHARSET_7BIT;
404                 pDCS->bCompressed = false;
405                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
406
407                 pDCS->bMWI = true;
408                 pDCS->bIndActive = (((dcs & 0x08) >> 3) == 1)? true:false;
409                 pDCS->indType = (SMS_INDICATOR_TYPE_T)(dcs & 0x03);
410         }
411         else if (((dcs & 0xF0) >> 4) == 0x0E)
412         {
413                 pDCS->codingGroup = SMS_GROUP_STORE;
414                 pDCS->codingScheme = SMS_CHARSET_UCS2;
415                 pDCS->bCompressed = false;
416                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
417
418                 pDCS->bMWI = true;
419                 pDCS->bIndActive = (((dcs & 0x08) >> 3) == 1)? true:false;
420                 pDCS->indType = (SMS_INDICATOR_TYPE_T)(dcs & 0x03);
421         }
422         else
423         {
424                 pDCS->codingGroup = SMS_GROUP_UNKNOWN;
425
426                 pDCS->bCompressed = (dcs & 0x20) >> 5;
427                 pDCS->codingScheme = (dcs & 0x0C) >> 2;
428
429                 pDCS->msgClass = SMS_MSG_CLASS_NONE;
430         }
431
432         return offset;
433 }
434
435
436 void SmsPluginParamCodec::decodeSMSC(unsigned char* pAddress, int AddrLen, MSG_SMS_TON_T ton, char *pDecodeAddr)
437 {
438         if (pAddress == NULL || AddrLen == 0)
439                 return;
440
441         if (ton == SMS_TON_INTERNATIONAL)
442         {
443                 pDecodeAddr[0] = '+';
444                 convertBcdToDigit(pAddress, AddrLen, &(pDecodeAddr[1]));
445         }
446         else
447         {
448                 convertBcdToDigit(pAddress, AddrLen, pDecodeAddr);
449         }
450 }
451
452
453 /*==================================================================================================
454                                      Util Functions
455 ==================================================================================================*/
456 int SmsPluginParamCodec::convertDigitToBcd(char *pDigit, int DigitLen, unsigned char *pBcd)
457 {
458         int offset = 0;
459         unsigned char temp;
460
461 //MSG_DEBUG("DigitLen [%d]", DigitLen);
462 //MSG_DEBUG("pDigit [%s]", pDigit);
463
464         for (int i = 0; i < DigitLen; i++)
465         {
466                 if (pDigit[i] == '*')
467                         temp = 0x0A;
468                 else if (pDigit[i] == '#')
469                         temp = 0x0B;
470                 else if (pDigit[i] == 'P' || pDigit[i] == 'p')
471                         temp = 0x0C;
472                 else
473                         temp = pDigit[i] - '0';
474
475                 if ((i%2) == 0)
476                         pBcd[offset] = temp & 0x0F;
477                 else
478                         pBcd[offset++] |= ((temp & 0x0F) << 4);
479         }
480
481         if ((DigitLen%2) == 1)
482         {
483                 pBcd[offset++] |= 0xF0;
484         }
485
486         return offset;
487 }
488
489
490 int SmsPluginParamCodec::convertBcdToDigit(const unsigned char *pBcd, int BcdLen, char *pDigit)
491 {
492         int offset = 0;
493         unsigned char temp;
494
495         for (int i = 0; i < BcdLen; i++)
496         {
497                 temp = pBcd[i] & 0x0F;
498
499                 if (temp == 0x0A)
500                         pDigit[offset++] = '*';
501                 else if (temp == 0x0B)
502                         pDigit[offset++] = '#';
503                 else if (temp == 0x0C)
504                         pDigit[offset++] = 'P';
505                 else
506                         pDigit[offset++] = temp + '0';
507
508                 temp = (pBcd[i] & 0xF0) >> 4;
509
510                 if (temp == 0x0F)
511                 {
512                         pDigit[offset] = '\0';
513                         return offset;
514                 }
515
516                 if (temp == 0x0A)
517                         pDigit[offset++] = '*';
518                 else if (temp == 0x0B)
519                         pDigit[offset++] = '#';
520                 else if (temp == 0x0C)
521                         pDigit[offset++] = 'P';
522                 else
523                         pDigit[offset++] = temp + '0';
524         }
525
526         pDigit[offset] = '\0';
527
528         return offset;
529 }
530
531 bool SmsPluginParamCodec::checkCphsVmiMsg(const unsigned char *pTpdu, int *setType, int *indType)
532 {
533         bool ret = false;
534
535         int offset = 0;
536         int addrLen = 0;
537
538         addrLen = (int)pTpdu[offset++];
539
540         if (addrLen == 0x04 && pTpdu[offset++] == 0xD0) {
541                 if (pTpdu[offset] == 0x11 || pTpdu[offset] == 0x10) {
542                         MSG_DEBUG("####### VMI msg ######");
543                         *setType = (int)(pTpdu[offset] & 0x01); // 0 : clear, 1 : set
544
545                         *indType = (int)(pTpdu[offset+1] & 0x01); // 0 : indicator 1, 1 : indicator 2
546
547                         ret = true;
548                 }
549         }
550
551         return ret;
552 }