fix svace issues
[platform/core/pim/contacts-service.git] / server / ctsvc_number_utils.c
1 /*
2  * Contacts Service
3  *
4  * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <ctype.h>
21 #include <unicode/ustring.h>
22
23 #include <TapiUtility.h>
24 #include <ITapiNetwork.h>
25 #include <sqlite3.h>
26 #include <phone_number.h>
27
28 #include "contacts.h"
29 #include "ctsvc_internal.h"
30 #include "ctsvc_server_setting.h"
31 #include "ctsvc_normalize.h"
32 #include "ctsvc_localize_utils.h"
33 #include "ctsvc_number_utils.h"
34
35 typedef struct {
36         int mcc;
37         char *cc;
38 }ctsvc_mcc_cc_map;
39
40 const static ctsvc_mcc_cc_map __mcc_cc_list[] = {
41         {0, "1"},
42         {202, "30"},
43         {204, "31"},
44         {206, "32"},
45         {208, "33"},
46         {212, "377"},
47         {213, "376"},
48         {214, "34"},
49         {216, "36"},
50         {218, "387"},
51         {219, "385"},
52         {220, "381"},
53         {222, "39"},
54         {225, "39"},
55         {226, "40"},
56         {228, "41"},
57         {230, "420"},
58         {231, "421"},
59         {232, "43"},
60         {234, "44"},
61         {235, "44"},
62         {238, "45"},
63         {240, "46"},
64         {242, "47"},
65         {244, "358"},
66         {246, "370"},
67         {247, "371"},
68         {248, "372"},
69         {250, "7"},
70         {255, "380"},
71         {257, "375"},
72         {259, "373"},
73         {260, "48"},
74         {262, "49"},
75         {266, "350"},
76         {268, "351"},
77         {270, "352"},
78         {272, "353"},
79         {274, "354"},
80         {276, "355"},
81         {278, "356"},
82         {280, "357"},
83         {282, "995"},
84         {283, "374"},
85         {284, "359"},
86         {286, "90"},
87         {288, "298"},
88         {290, "299"},
89         {292, "378"},
90         {293, "386"},
91         {294, "389"},
92         {295, "423"},
93         {297, "382"},
94         {302, "1"},
95         {308, "508"},
96         {310, "1"},
97         {311, "1"},
98         {312, "1"},
99         {313, "1"},
100         {314, "1"},
101         {315, "1"},
102         {316, "1"},
103         {330, "1"},
104         {332, "1"},
105         {334, "52"},
106         {338, "1"},
107         {340, "590"},
108         {340, "596"},
109         {342, "1"},
110         {344, "1"},
111         {346, "1"},
112         {348, "1"},
113         {350, "1"},
114         {352, "1"},
115         {354, "1"},
116         {356, "1"},
117         {358, "1"},
118         {360, "1"},
119         {362, "599"},
120         {363, "297"},
121         {364, "1"},
122         {365, "1"},
123         {366, "1"},
124         {368, "53"},
125         {370, "1"},
126         {372, "509"},
127         {374, "1"},
128         {376, "1"},
129         {400, "994"},
130         {401, "7"},
131         {402, "975"},
132         {404, "91"},
133         {405, "91"},
134         {406, "91"},
135         {410, "92"},
136         {412, "93"},
137         {413, "94"},
138         {414, "95"},
139         {415, "961"},
140         {416, "962"},
141         {417, "963"},
142         {418, "964"},
143         {419, "965"},
144         {420, "966"},
145         {421, "967"},
146         {422, "968"},
147         {424, "971"},
148         {425, "972"},
149         {426, "973"},
150         {427, "974"},
151         {428, "976"},
152         {429, "977"},
153         {430, "971"},
154         {431, "971"},
155         {432, "98"},
156         {434, "998"},
157         {436, "992"},
158         {437, "996"},
159         {438, "993"},
160         {440, "81"},
161         {441, "81"},
162         {450, "82"},
163         {452, "84"},
164         {454, "852"},
165         {455, "853"},
166         {456, "855"},
167         {457, "856"},
168         {460, "86"},
169         {461, "86"},
170         {466, "886"},
171         {467, "850"},
172         {470, "880"},
173         {472, "960"},
174         {502, "60"},
175         {505, "61"},
176         {510, "62"},
177         {514, "670"},
178         {515, "63"},
179         {520, "66"},
180         {525, "65"},
181         {528, "673"},
182         {530, "64"},
183         {536, "674"},
184         {537, "675"},
185         {539, "676"},
186         {540, "677"},
187         {541, "678"},
188         {542, "679"},
189         {543, "681"},
190         {544, "1"},
191         {545, "686"},
192         {546, "687"},
193         {547, "689"},
194         {548, "682"},
195         {549, "685"},
196         {550, "691"},
197         {551, "692"},
198         {552, "680"},
199         {602, "20"},
200         {603, "213"},
201         {604, "212"},
202         {605, "216"},
203         {606, "218"},
204         {607, "220"},
205         {608, "221"},
206         {609, "222"},
207         {610, "223"},
208         {611, "224"},
209         {612, "225"},
210         {613, "226"},
211         {614, "227"},
212         {615, "228"},
213         {616, "229"},
214         {617, "230"},
215         {618, "231"},
216         {619, "232"},
217         {620, "233"},
218         {621, "234"},
219         {622, "235"},
220         {623, "236"},
221         {624, "237"},
222         {625, "238"},
223         {626, "239"},
224         {627, "240"},
225         {628, "241"},
226         {629, "242"},
227         {630, "243"},
228         {631, "244"},
229         {632, "245"},
230         {633, "248"},
231         {634, "249"},
232         {635, "250"},
233         {636, "251"},
234         {637, "252"},
235         {638, "253"},
236         {639, "254"},
237         {640, "255"},
238         {641, "256"},
239         {642, "257"},
240         {643, "258"},
241         {645, "260"},
242         {646, "261"},
243         {647, "262"},
244         {648, "263"},
245         {649, "264"},
246         {650, "265"},
247         {651, "266"},
248         {652, "267"},
249         {653, "268"},
250         {654, "269"},
251         {655, "27"},
252         {657, "291"},
253         {702, "501"},
254         {704, "502"},
255         {706, "503"},
256         {708, "504"},
257         {710, "505"},
258         {712, "506"},
259         {714, "507"},
260         {716, "51"},
261         {722, "54"},
262         {724, "55"},
263         {730, "56"},
264         {732, "57"},
265         {734, "58"},
266         {736, "591"},
267         {738, "592"},
268         {740, "593"},
269         {742, "594"},
270         {744, "595"},
271         {746, "597"},
272         {748, "598"},
273         {750, "500"},
274 };
275
276 static char *cc = NULL;
277 static TapiHandle *handle_for_cc = NULL;
278
279 char* ctsvc_get_network_cc(bool reload)
280 {
281         int i;
282         int state;
283         int ret;
284         int mcc = 0;
285         char *temp = NULL;
286         TapiHandle *handle = NULL;
287         static bool cc_loaded = false;
288
289         if (cc_loaded && false == reload)
290                 return cc;
291
292         cc_loaded = true;
293         cc = NULL;
294         handle = (TapiHandle *)ctsvc_init_tapi_handle_for_cc();
295         RETVM_IF(NULL == handle, NULL, "tel_init() Fail");
296
297         ret = tel_get_property_int(handle, TAPI_PROP_NETWORK_SERVICE_TYPE, &state);
298         if (ret != TAPI_API_SUCCESS) {
299                 CTS_ERR("tel_get_property_int Fail(%d)", ret);
300                 tel_deinit(handle);
301                 return NULL;
302         }
303
304         if (state == TAPI_NETWORK_SERVICE_TYPE_UNKNOWN
305                         || state == TAPI_NETWORK_SERVICE_TYPE_NO_SERVICE
306                         || state == TAPI_NETWORK_SERVICE_TYPE_EMERGENCY
307                         || state == TAPI_NETWORK_SERVICE_TYPE_SEARCH) {
308                 CTS_INFO("network service is not working : state(%d)", state);
309                 return NULL;
310         }
311
312         ret = tel_get_property_string(handle, TAPI_PROP_NETWORK_PLMN,  &temp);
313         if (ret != TAPI_API_SUCCESS) {
314                 CTS_ERR("tel_get_property_string Fail(%d)", ret);
315                 return NULL;
316         }
317
318         if (temp) {
319                 if(3 < strlen(temp))
320                         temp[3] = '\0';
321                 mcc = atoi(temp);
322         }
323         for (i=0;i<sizeof(__mcc_cc_list)/sizeof(ctsvc_mcc_cc_map);i++) {
324                 if (__mcc_cc_list[i].mcc == mcc) {
325                         cc = __mcc_cc_list[i].cc;
326                         break;
327                 }
328         }
329
330         return cc;
331 }
332
333 static void __ctsvc_network_cc_changed(TapiHandle *handle, const char *noti_id, void *data, void *user_data)
334 {
335         ctsvc_get_network_cc(true);
336 }
337
338 void* ctsvc_init_tapi_handle_for_cc()
339 {
340         if (handle_for_cc)
341                 return handle_for_cc;
342
343         handle_for_cc = tel_init(NULL);
344         if (handle_for_cc) {
345                 int ret = tel_register_noti_event(handle_for_cc,
346                                 TAPI_PROP_NETWORK_PLMN, __ctsvc_network_cc_changed, NULL);
347                 WARN_IF(ret != TAPI_API_SUCCESS, "tel_register_noti_event Fail(%d)", ret);
348         }
349         else
350                 CTS_ERR("tel_init fail");
351
352         return handle_for_cc;
353 }
354
355 void ctsvc_deinit_tapi_handle_for_cc()
356 {
357         if (handle_for_cc) {
358                 int ret = tel_deregister_noti_event(handle_for_cc,  TAPI_PROP_NETWORK_PLMN);
359                 WARN_IF(ret != TAPI_API_SUCCESS, "tel_register_noti_event Fail(%d)", ret);
360                 tel_deinit(handle_for_cc);
361         }
362         handle_for_cc = NULL;
363 }
364
365 static inline int __ctsvc_phone_number_has_country_code(const char *src, int len)
366 {
367         int ret = 0;
368
369         if (len <= 0)
370                 return 0;
371
372         switch (src[ret++]-'0') {
373         case 1:
374         case 7:
375                 break;
376         case 2:
377                 if (len <= ret) return 0;
378                 switch (src[ret++]-'0') {
379                 case 0:
380                 case 7:
381                         break;
382                 case 1:
383                 case 2:
384                 case 3:
385                 case 4:
386                 case 5:
387                 case 6:
388                 case 8:
389                 case 9:
390                         ret += 1;
391                         break;
392                 default:
393                         CTS_ERR("The parameter(src:%s) has invalid character set", src);
394                 }
395                 break;
396         case 3:
397                 if (len <= ret) return 0;
398                 switch (src[ret++]-'0') {
399                 case 0:
400                 case 1:
401                 case 2:
402                 case 3:
403                 case 4:
404                 case 6:
405                 case 9:
406                         break;
407                 case 5:
408                 case 7:
409                 case 8:
410                         ret += 1;
411                         break;
412                 default:
413                         CTS_ERR("The parameter(src:%s) has invalid character set", src);
414                 }
415                 break;
416         case 4:
417                 if (len <= ret) return 0;
418                 switch (src[ret++]-'0') {
419                 case 0:
420                 case 1:
421                 case 3:
422                 case 4:
423                 case 5:
424                 case 6:
425                 case 7:
426                 case 8:
427                 case 9:
428                         break;
429                 case 2:
430                         ret += 1;
431                         break;
432                 default:
433                         CTS_ERR("The parameter(src:%s) has invalid character set", src);
434                 }
435                 break;
436         case 5:
437                 if (len <= ret) return 0;
438                 switch (src[ret++]-'0') {
439                 case 1:
440                 case 2:
441                 case 3:
442                 case 4:
443                 case 5:
444                 case 6:
445                 case 7:
446                 case 8:
447                         break;
448                 case 0:
449                 case 9:
450                         ret += 1;
451                         break;
452                 default:
453                         CTS_ERR("The parameter(src:%s) has invalid character set", src);
454                 }
455                 break;
456         case 6:
457                 if (len <= ret) return 0;
458                 switch (src[ret++]-'0') {
459                 case 0:
460                 case 1:
461                 case 2:
462                 case 3:
463                 case 4:
464                 case 5:
465                 case 6:
466                         break;
467                 case 7:
468                 case 8:
469                 case 9:
470                         ret += 1;
471                         break;
472                 default:
473                         CTS_ERR("The parameter(src:%s) has invalid character set", src);
474                 }
475                 break;
476         case 8:
477                 if (len <= ret) return 0;
478                 switch (src[ret++]-'0') {
479                 case 1:
480                 case 2:
481                 case 4:
482                 case 6:
483                         break;
484                 case 0:
485                 case 3:
486                 case 5:
487                 case 7:
488                 case 8:
489                 case 9:
490                         ret += 1;
491                         break;
492                 default:
493                         CTS_ERR("The parameter(src:%s) has invalid character set", src);
494                 }
495                 break;
496         case 9:
497                 if (len <= ret) return 0;
498                 switch (src[ret++]-'0') {
499                 case 0:
500                 case 1:
501                 case 2:
502                 case 3:
503                 case 4:
504                 case 5:
505                 case 8:
506                         break;
507                 case 6:
508                 case 7:
509                 case 9:
510                         ret += 1;
511                         break;
512                 default:
513                         CTS_ERR("The parameter(src:%s) has invalid character set", src);
514                 }
515                 break;
516         case 0:
517         default:
518                 CTS_ERR("The parameter(src:%s) has invalid character set", src);
519                 return 0;
520         }
521
522         return ret;
523 }
524
525 /*
526  * Number Matching Rule
527  * refer to the http://www.itu.int/dms_pub/itu-t/opb/sp/T-SP-E.164C-2011-PDF-E.pdf
528  */
529 enum {
530         CTSVC_PLUS_ONLY,     /* + */
531         CTSVC_PLUS_IP_ONLY,  /* +IP (International prefix) */
532         CTSVC_PLUS_CC_ONLY,  /* +CC (Country code) */
533         CTSVC_PLUS_IP_CC,    /* +IP CC */
534         CTSVC_IP_ONLY,       /* IP */
535         CTSVC_CC_ONLY,       /* CC */
536         CTSVC_IP_CC,         /* IP CC */
537         CTSVC_NONE,
538 };
539
540 static int __ctsvc_number_has_ip_and_cc(const char*number, int len, int *index)
541 {
542         bool have_cc = false;
543         bool have_plus = false;
544         int ret = CTSVC_NONE;
545         int start_index;
546         int match_len;
547         *index = 0;
548
549         /* Check IP */
550         start_index = 0;
551         match_len = 0;
552
553         switch(number[start_index]) {
554         case '+':
555                 start_index++;
556                 have_plus = true;
557                 if (len <= start_index) {
558                         *index = start_index;
559                         return CTSVC_PLUS_ONLY;   /* '+' */
560                 }
561         default:
562                 {
563                         /*
564                          * IP can be
565                          *  0 (Turks and Caicos Islands, Samoa)
566                          *  00, 011, 0011, 010, 000
567                          *  001/007 (Cambodia), 001/008 (Indonesia, Singapore)
568                          *  001/002 (Korea), 002(Taiwan)
569                          *  810 (Belarus, Kazakhstan, Russian, Tajikistan, Turkmenistan)
570                          *  009/007/005(Colombia), 009(Nigeria)
571                          *  119 (Cuba)
572                          *  00/012/013/014 (Israel)
573                          */
574                         switch(number[start_index]) {
575                         case '0':   /* '+0' */
576                                 {
577                                         start_index++;
578                                         if (len <= start_index) {
579                                                 *index = start_index;
580                                                 return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY); /* '+0' */
581                                         }
582
583                                         switch(number[start_index]) {
584                                         case '0':   /* '+00' */
585                                                 {
586                                                         start_index++;
587                                                         if (len <= start_index) {
588                                                                 *index = start_index;
589                                                                 return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);      /* '+00' */
590                                                         }
591
592                                                         switch(number[start_index]) {
593                                                         case '0':   /* '+000' */
594                                                         case '2':   /* '+002' */
595                                                         case '5':   /* '+005' */
596                                                         case '7':   /* '+007' */
597                                                         case '8':   /* '+008' */
598                                                         case '9':   /* '+009' */
599                                                                             /* or '+00 CC' */
600                                                                 start_index++;
601                                                                 if (len <= start_index) {
602                                                                         *index = start_index;
603                                                                         return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);  /* '+00Y' */
604                                                                 }
605
606                                                                 have_cc = __ctsvc_phone_number_has_country_code(&number[start_index], len-start_index);
607                                                                 if (0 < have_cc) {
608                                                                         *index = start_index;
609                                                                         return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_IP_CC);      /* '+00Y CC' */
610                                                                 }
611                                                                 else {
612                                                                         have_cc = __ctsvc_phone_number_has_country_code(&number[start_index-1], len-start_index+1);
613                                                                         if (0 < have_cc) {
614                                                                                 *index = start_index-1;
615                                                                                 return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_IP_CC);  /* '+00 CC' */
616                                                                         }
617                                                                 }
618                                                                 *index = start_index;
619                                                                 return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);      /* '+00Y XXX' */
620                                                         case '1':   /* '+001' */
621                                                                 start_index++;
622                                                                 if (len <= start_index) {
623                                                                         *index = start_index;
624                                                                         return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);  /* '+001' */
625                                                                 }
626
627                                                                 if (number[start_index] == '1') {
628                                                                         start_index++;
629                                                                         if (len <= start_index) {
630                                                                                 *index = start_index;
631                                                                                 return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);   /* '+0011' */
632                                                                         }
633
634                                                                         have_cc = __ctsvc_phone_number_has_country_code(&number[start_index], len-start_index);
635                                                                         if (0 < have_cc) {
636                                                                                 *index = start_index;
637                                                                                 return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_IP_CC);  /*  '+0011 CC' */
638                                                                         }
639                                                                         start_index--;
640                                                                 }
641
642                                                                 have_cc = __ctsvc_phone_number_has_country_code(&number[start_index], len-start_index);
643                                                                 *index = start_index;
644                                                                 if (0 < have_cc)
645                                                                         return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_IP_CC);      /* '+001 CC' */
646                                                                 else
647                                                                         return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);  /* '+001 XXX' */
648                                                         default:   /* '+00 3', '+00 4', '+00 6' */
649                                                                 *index = start_index;
650                                                                 have_cc = __ctsvc_phone_number_has_country_code(&number[start_index], len-start_index);
651                                                                 if (0 < have_cc)
652                                                                         return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_IP_CC);      /* '+00 CC' */
653                                                                 else
654                                                                         return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);  /* '+00 XXX' */
655                                                         }   /* end of fourth switch */
656                                                 }
657                                                 break;
658                                         case '1':   /* '+01' */
659                                                 {
660                                                         start_index++;
661                                                         if (len <= start_index) {
662                                                                 *index = start_index-1;   /* '+0 1' */
663                                                                 return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_NONE);
664                                                         }
665
666                                                         switch(number[start_index]) {
667                                                         case '0':   /* '+010' */
668                                                         case '1':   /* '+011' */
669                                                         case '2':   /* '+012' */
670                                                         case '3':   /* '+013' */
671                                                         case '4':   /* '+014' */
672                                                                 {
673                                                                         start_index++;
674                                                                         if (len <= start_index) {
675                                                                                 *index = start_index;
676                                                                                 return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);   /* '+01Y' */
677                                                                         }
678
679                                                                         have_cc = __ctsvc_phone_number_has_country_code(&number[start_index], len-start_index);
680                                                                         *index = start_index;
681                                                                         if (0 < have_cc)
682                                                                                 return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_IP_CC);   /* '+01Y CC' */
683                                                                         else
684                                                                                 return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);   /* '+01Y XXX' */
685                                                                 }
686                                                                 break;
687                                                         default:
688                                                                 *index = start_index-1;   /* '+0 1' */
689                                                                 return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_NONE);
690                                                         }
691                                                 }
692                                                 break;
693                                         default:   /* '+0 CC' */
694                                                 {
695                                                         have_cc = __ctsvc_phone_number_has_country_code(&number[start_index], len-start_index);
696                                                         *index = start_index;
697                                                         if (0 < have_cc)
698                                                                 return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_IP_CC);          /* '+0 CC' */
699                                                         else
700                                                                 return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);      /* '+0 XXX' */
701                                                 }
702                                                 break;
703                                         }   /* end of third switch */
704                                 }
705                                 break;   /* end of '+0' */
706                         case '1':   /* '+1' */
707                                 start_index++;
708                                 if (start_index+2 <= len && STRING_EQUAL == strncmp(&number[start_index], "19", 2)) {   /* '+119' */
709                                         match_len = start_index + 2;
710                                         ret = (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);
711                                 }
712                                 else {
713                                         match_len = start_index-1;
714                                         ret = (have_plus?CTSVC_PLUS_ONLY:CTSVC_NONE);   /* '+ CC' */
715                                 }
716                                 break;
717                         case '8':   /* '+8' */
718                                 start_index++;
719                                 if (start_index+2 <= len && STRING_EQUAL == strncmp(&number[start_index], "10", 2)) {   /* '+810' */
720                                         match_len = start_index + 2;
721                                         ret = (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);
722                                 }
723                                 else {
724                                         match_len = start_index-1;
725                                         ret = (have_plus?CTSVC_PLUS_ONLY:CTSVC_NONE);   /* '+ CC' */
726                                 }
727                                 break;
728                         default:
729                                 match_len = start_index;
730                                 ret = (have_plus?CTSVC_PLUS_ONLY:CTSVC_NONE);   /* '+ CC' */
731                                 break;
732                         }   /* end of second switch */
733                 }
734                 break;   /* '+' default */
735         }   /* end of first switch */
736         *index = match_len;
737
738         /* Check CC */
739         if (match_len < len) {
740                 have_cc = __ctsvc_phone_number_has_country_code(&number[match_len], len-match_len);
741                 if (0 < have_cc) {
742                         switch (ret) {
743                         case CTSVC_NONE:
744                                 return CTSVC_CC_ONLY;
745                         case CTSVC_PLUS_ONLY:
746                                 return CTSVC_PLUS_CC_ONLY;
747                         case CTSVC_PLUS_IP_ONLY:
748                                 return CTSVC_PLUS_IP_CC;
749                         case CTSVC_IP_ONLY:
750                                 return CTSVC_IP_CC;
751                         }
752                 }
753         }
754         return ret;
755 }
756
757 int ctsvc_normalize_number(const char *src, char *dest, int dest_size, bool replace_alphabet)
758 {
759         int ret;
760         int d_pos;
761         int s_pos;
762         char *normalized_out = NULL;
763         char temp[dest_size];
764
765
766         if (NULL == src) {
767                 CTS_ERR("The parameter(src) is NULL");
768                 return 0;
769         }
770
771         d_pos = strlen(src);
772         if (d_pos <= 0)
773                 return d_pos;
774
775         d_pos = 0;
776         s_pos = 0;
777         if (src[s_pos] == '+')
778                 temp[d_pos++] = src[s_pos++];
779         while (src[s_pos] != 0) {
780                 if (src[s_pos] == '+' || src[s_pos] == ';')
781                         s_pos++;
782                 temp[d_pos++] = src[s_pos++];
783         }
784         temp[d_pos] = 0;
785
786         ret = phone_number_get_normalized_number(temp, &normalized_out);
787         if (PHONE_NUMBER_ERROR_NONE == ret) {
788                 d_pos = strlen(normalized_out);
789                 memcpy(dest, normalized_out, d_pos+1);
790                 free(normalized_out);
791         }
792         else {
793                 memcpy(dest, temp, d_pos+1);
794         }
795
796         dest[d_pos] = 0;
797
798         return d_pos;
799 }
800
801 /*
802  * vaild character : digit, +, *, #,, ;, alphabet(depends on replace_alphabet parameter)
803  * Remove invalid string from number
804  */
805 int ctsvc_clean_number(const char *src, char *dest, int dest_size, bool replace_alphabet)
806 {
807         int s_pos;
808         int d_pos;
809         int pos;
810         char temp[dest_size];
811
812         if (NULL == src) {
813                 CTS_ERR("The parameter(src) is NULL");
814                 return 0;
815         }
816
817         s_pos = 0;
818         pos = 0;
819         while (src[s_pos] != 0) {
820                 int char_len;
821                 if (dest_size-2 < pos) break;
822
823                 char_len = ctsvc_check_utf8(src[s_pos]);
824                 if (char_len <= 0) {
825                         break;
826                 }
827
828                 if (char_len == 3) {
829                         /* fullwidth -> halfwidth */
830                         if (src[s_pos] == 0xef) {
831                                 if (src[s_pos+1] == 0xbc) {
832                                         if (0x90 <= src[s_pos+2] && src[s_pos+2] <= 0x99)        /* ef bc 90 : '0' ~ ef bc 99 : '9' */
833                                                 temp[pos++] = src[s_pos+2] - 0x60;
834                                         else if (0xa1 <= src[s_pos+2] && src[s_pos+2] <= 0xba)   /* ef bc a1 : 'A' ~ ef bc ba : 'Z' */
835                                                 temp[pos++] = src[s_pos+2] - 0x60;
836                                         else if (0x8b == src[s_pos+2])   /* ef bc 8b : '+' */
837                                                 temp[pos++] = '+';
838                                         else if (0x8a == src[s_pos+2])   /* ef bc 8a : '*' */
839                                                 temp[pos++] = '*';
840                                         else if (0x83 == src[s_pos+2])   /* ef bc 83 : '#' */
841                                                 temp[pos++] = '#';
842                                         else if (0x8c == src[s_pos+2])   /* ef bc 8c : ',' */
843                                                 temp[pos++] = ',';
844                                         else if (0x9b == src[s_pos+2])   /* ef bc 9b : ';' */
845                                                 temp[pos++] = ';';
846                                 }
847                                 else if (src[s_pos+1] == 0xbd
848                                                 && (0x81 <= src[s_pos+2] && src[s_pos+2] <= 0x9a))   /* ef bd 81 : 'a' ~ ef bd 9a : 'z' */
849                                         temp[pos++] = src[s_pos+2] - 0x40;
850                         }
851                         else {
852                                 s_pos += char_len;
853                                 continue;
854                         }
855                 }
856                 else if (char_len == 1) {
857                         if (0x41 <= src[s_pos] && src[s_pos] <= 0x5a)        /* 'A' ~ 'Z' */
858                                 temp[pos++] = src[s_pos];
859                         else if (0x61 <= src[s_pos] && src[s_pos] <= 0x7a)   /* 'a' ~ 'z' */
860                                 temp[pos++] = src[s_pos] - 0x20;
861                         else
862                                 temp[pos++] = src[s_pos];
863                 }
864                 s_pos += char_len;
865         }
866         temp[pos] = 0x0;
867
868         pos = 0;
869         d_pos = 0;
870         while (temp[pos] != 0) {
871                 if ('0' <= temp[pos] && temp[pos] <= '9')
872                         dest[d_pos++] = temp[pos];
873                 else if (temp[pos] == '+' || temp[pos] == '#'
874                                 || temp[pos] == '*' || temp[pos] == ';' || temp[pos] == ',')
875                         dest[d_pos++] = temp[pos];
876                 pos++;
877         }
878         dest[d_pos] = 0;
879
880         return d_pos;
881 }
882
883 static int __ctsvc_minmatch_number(const char *src, char *dest, int dest_size, int min_match)
884 {
885         int i;
886         int len = 0;
887         int d_pos = 0;
888         const char *temp_number;
889         const char *cc = ctsvc_get_network_cc(false);
890
891         if ('+' == src[0]) {
892                 len = __ctsvc_phone_number_has_country_code(&src[1], strlen(src)-1);
893                 temp_number = src + len +1;
894         }
895         else if ('0' == src[0])
896                 temp_number = src+1;
897         else if (cc && cc[0] == '7' && src[0] == '8')
898                 temp_number = src+1;
899         else
900                 temp_number = src;
901
902         len = strlen(temp_number);
903
904         if (0 < len) {
905                 while (0 <= (len-d_pos-1) && temp_number[len-d_pos-1]
906                                 && d_pos < min_match) {
907                         if (dest_size-d_pos == 0) {
908                                 CTS_ERR("Destination string buffer is not enough(%s)", src);
909                                 return CONTACTS_ERROR_INTERNAL;
910                         }
911
912                         dest[d_pos] = temp_number[len-d_pos-1];
913                         d_pos++;
914                 }
915                 dest[d_pos] = 0;
916
917                 len = strlen(dest);
918                 for (i=0; i<len/2;i++) {
919                         char c;
920                         c = dest[i];
921                         dest[i] = dest[len-i-1];
922                         dest[len-i-1] = c;
923                 }
924         }
925         else {
926                 memcpy(dest, src, strlen(src));
927                 dest[strlen(src)] = 0;
928         }
929
930         return CONTACTS_ERROR_NONE;
931 }
932
933 int ctsvc_get_minmatch_number(const char *src, char *dest, int dest_size, int min_match)
934 {
935         int ret;
936
937         RETV_IF(NULL == src, CONTACTS_ERROR_INVALID_PARAMETER);
938         RETV_IF(NULL == dest, CONTACTS_ERROR_INVALID_PARAMETER);
939
940         ret = __ctsvc_minmatch_number(src, dest, dest_size, min_match);
941         if (ret != CONTACTS_ERROR_NONE) {
942                 CTS_ERR("__ctsvc_minmatch_number() Fail(%d)", ret);
943                 return ret;
944         }
945
946         return CONTACTS_ERROR_NONE;
947 }
948
949 static bool __ctsvc_is_phonenumber_halfwidth(const char* keyword)
950 {
951         int i;
952         int len = strlen(keyword);
953
954         /* TODO: we should add predicate including '+' */
955         /* TODO: finally, we try to check the number with regular expression. */
956         for (i=0; i<len; i++) {
957                 if ((keyword[i] < '0' || '9' < keyword[i]) && keyword[i] != '+') {
958                         CTS_ERR("keyword[%d]: %c is not number)", i, keyword[i]);
959                         return false;
960                 }
961         }
962         return true;
963 }
964
965 #define UTF8_FULLWIDTH_LENGTH 3
966 static bool __ctsvc_is_phonenumber_fullwidth(const char* keyword)
967 {
968         int char_len = 1;
969         int str_len;
970         int i;
971         if (keyword == NULL || *keyword == '\0')
972                 return false;
973
974         str_len = strlen(keyword);
975         for (i=0;i<str_len;i += char_len) {
976                 char_len = ctsvc_check_utf8(keyword[i]);
977                 if (char_len != UTF8_FULLWIDTH_LENGTH || str_len-i < UTF8_FULLWIDTH_LENGTH)
978                         return false;
979
980                 if (keyword[i] == 0xef) {
981                         if (keyword[i+1] == 0xbc) {
982                                 if (0x90 <= keyword[i+2] && keyword[i+2] <= 0x99)            /* ef bc 90 : '0' ~ ef bc 99 : '9' */
983                                         continue;
984                                 else if (0x8b == keyword[i+2])   /* ef bc 8b : '+' */
985                                         continue;
986                                 else
987                                         return false;
988                         }
989                         else
990                                 return false;
991                 }
992                 else
993                         return false;
994         }
995         return true;
996 }
997
998 bool ctsvc_is_phonenumber(const char* src)
999 {
1000         return (__ctsvc_is_phonenumber_halfwidth(src) || __ctsvc_is_phonenumber_fullwidth(src));
1001 }
1002
1003 /* numbers are cleaned number or normalized number */
1004 static bool __ctsvc_number_compare(const char *number1, const char *number2)
1005 {
1006         int len1;
1007         int len2;
1008         int matched;
1009         int minmatch_len = ctsvc_get_phonenumber_min_match_digit();
1010         const char *cc = ctsvc_get_network_cc(false);
1011
1012         if (NULL == number1 || NULL == number2 || '\0' == *number1 || '\0' == *number2)
1013                 return false;
1014
1015         len1 = strlen(number1);
1016         len2 = strlen(number2);
1017
1018         /* compare  number in reverse order */
1019         for (matched = 0; 0 < len1 && 0 < len2;) {
1020                 if (number1[len1-1] != number2[len2-1])
1021                         break;
1022                 len1--;
1023                 len2--;
1024                 matched++;
1025         }
1026
1027         /* full match */
1028         if (len1 == 0 && len2 == 0)
1029                 return true;
1030
1031         /* one is substring of the other string */
1032         if (minmatch_len <= matched&& (len1 == 0 || len2 == 0))
1033                 return true;
1034
1035         /* one is +IPCC or +CC, the other is start wth NTP (National trunk prefix) */
1036         if (minmatch_len <= matched) {
1037                 int index1 = 0;
1038                 int index2 = 0;
1039                 int cc_index = 0;
1040
1041                 /*
1042                  * International Prefix (IP) is related to current location where to call
1043                  * Country Code (CC) is related to the SIM card who to call
1044                  * If you try to call in United State using Korea SIM card,
1045                  * the number will be 011 82 X XXXXXXXX.
1046                  * So, when comparing number, just check IP validation and CC and natinal number matching.
1047                  */
1048
1049                 int n1 = __ctsvc_number_has_ip_and_cc(number1, len1, &index1);
1050                 int n2 = __ctsvc_number_has_ip_and_cc(number2, len2, &index2);
1051
1052                 /*
1053                  * + (IP) CC XXXXXXXX, 0XXXXXXXX
1054                  * + (810) 7 XXX XXX XX XX, 8XXX XXX XX XX (Russian)
1055                  */
1056                 if ((CTSVC_PLUS_IP_CC == n1 || CTSVC_PLUS_CC_ONLY == n1 ||
1057                                 CTSVC_IP_CC == n1 || CTSVC_CC_ONLY == n1)
1058                                 && (number2[0] == '0' || (cc && cc[0] == '7' && number2[0] == '8')))
1059                         return true;
1060                 else if ((CTSVC_PLUS_IP_CC == n2 || CTSVC_PLUS_CC_ONLY == n2 ||
1061                                         CTSVC_IP_CC == n2 || CTSVC_CC_ONLY == n2)
1062                                 && (number1[0] == '0' || (cc && cc[0] == '7' && number1[0] == '8')))
1063                         return true;
1064                 /*
1065                  * + IP CC XXXXXXXX, + CC XXXXXXXX  (ex. +001 82  11 1234 5678, +82 10 1234 5678)
1066                  */
1067                 else if ((CTSVC_PLUS_IP_CC == n1 || CTSVC_IP_CC == n1)
1068                                 && (CTSVC_PLUS_CC_ONLY == n2 || CTSVC_CC_ONLY == n2)) {
1069                         int p = (CTSVC_PLUS_CC_ONLY == n2)?1:0;
1070                         cc_index = __ctsvc_phone_number_has_country_code(&number2[p], len2-p);
1071                         if (0 < cc_index && STRING_EQUAL == strncmp(&number1[index1], &number2[p], cc_index))
1072                                 return true;
1073                 }
1074                 else if ((CTSVC_PLUS_IP_CC == n2 || CTSVC_IP_CC == n2)
1075                                 && (CTSVC_PLUS_CC_ONLY == n1 || CTSVC_CC_ONLY == n1)) {
1076                         int p = (CTSVC_PLUS_CC_ONLY == n1)?1:0;
1077                         cc_index = __ctsvc_phone_number_has_country_code(&number1[p], len1-p);
1078                         if (0 < cc_index && STRING_EQUAL == strncmp(&number2[index2], &number1[p], cc_index))
1079                                 return true;
1080                 }
1081                 /*
1082                  * + CC XXXXXXXX, + IP CC XXXXXXXX  (ex. +001 82  10 1234 5678, +82 10 1234 5678)
1083                  */
1084                 else if ((CTSVC_PLUS_IP_ONLY == n1 || CTSVC_IP_ONLY == n1)
1085                                 && CTSVC_PLUS_ONLY == n2) {
1086                         return true;
1087                 }
1088                 else if ((CTSVC_PLUS_IP_ONLY == n2 || CTSVC_IP_ONLY == n2)
1089                                 && CTSVC_PLUS_ONLY == n1) {
1090                         return true;
1091                 }
1092         }
1093
1094         return false;
1095 }
1096
1097 /* When querying _NUMBER_COMPARE_, this function will be called. */
1098 void ctsvc_db_phone_number_equal_callback(sqlite3_context * context,
1099                 int argc, sqlite3_value ** argv)
1100 {
1101 #ifdef _CONTACTS_IPC_SERVER
1102         char *number1;
1103         char *number2;
1104
1105         if (argc < 4) {
1106                 sqlite3_result_int(context, 0);
1107                 CTS_ERR("argc invalid");
1108                 return;
1109         }
1110
1111         number1 = (char*)sqlite3_value_text(argv[0]);
1112         number2 = (char*)sqlite3_value_text(argv[1]);
1113
1114         sqlite3_result_int(context, __ctsvc_number_compare(number1, number2));
1115         return;
1116 #endif
1117 }
1118