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