b2403afb9a1ccd01dcb5e1f6cab5152a2d95b4fe
[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 && 3 < strlen(temp))
319                 temp[3] = '\0';
320         mcc = atoi(temp);
321         for (i=0;i<sizeof(__mcc_cc_list)/sizeof(ctsvc_mcc_cc_map);i++) {
322                 if (__mcc_cc_list[i].mcc == mcc) {
323                         cc = __mcc_cc_list[i].cc;
324                         break;
325                 }
326         }
327
328         return cc;
329 }
330
331 static void __ctsvc_network_cc_changed(TapiHandle *handle, const char *noti_id, void *data, void *user_data)
332 {
333         ctsvc_get_network_cc(true);
334 }
335
336 void* ctsvc_init_tapi_handle_for_cc()
337 {
338         if (handle_for_cc)
339                 return handle_for_cc;
340
341         handle_for_cc = tel_init(NULL);
342         if (handle_for_cc) {
343                 int ret = tel_register_noti_event(handle_for_cc,
344                                 TAPI_PROP_NETWORK_PLMN, __ctsvc_network_cc_changed, NULL);
345                 WARN_IF(ret != TAPI_API_SUCCESS, "tel_register_noti_event Fail(%d)", ret);
346         }
347         else
348                 CTS_ERR("tel_init fail");
349
350         return handle_for_cc;
351 }
352
353 void ctsvc_deinit_tapi_handle_for_cc()
354 {
355         if (handle_for_cc) {
356                 int ret = tel_deregister_noti_event(handle_for_cc,  TAPI_PROP_NETWORK_PLMN);
357                 WARN_IF(ret != TAPI_API_SUCCESS, "tel_register_noti_event Fail(%d)", ret);
358                 tel_deinit(handle_for_cc);
359         }
360         handle_for_cc = NULL;
361 }
362
363 static inline int __ctsvc_phone_number_has_country_code(const char *src, int len)
364 {
365         int ret = 0;
366
367         if (len <= 0)
368                 return 0;
369
370         switch (src[ret++]-'0') {
371         case 1:
372         case 7:
373                 break;
374         case 2:
375                 if (len <= ret) return 0;
376                 switch (src[ret++]-'0') {
377                 case 0:
378                 case 7:
379                         break;
380                 case 1:
381                 case 2:
382                 case 3:
383                 case 4:
384                 case 5:
385                 case 6:
386                 case 8:
387                 case 9:
388                         ret += 1;
389                         break;
390                 default:
391                         CTS_ERR("The parameter(src:%s) has invalid character set", src);
392                 }
393                 break;
394         case 3:
395                 if (len <= ret) return 0;
396                 switch (src[ret++]-'0') {
397                 case 0:
398                 case 1:
399                 case 2:
400                 case 3:
401                 case 4:
402                 case 6:
403                 case 9:
404                         break;
405                 case 5:
406                 case 7:
407                 case 8:
408                         ret += 1;
409                         break;
410                 default:
411                         CTS_ERR("The parameter(src:%s) has invalid character set", src);
412                 }
413                 break;
414         case 4:
415                 if (len <= ret) return 0;
416                 switch (src[ret++]-'0') {
417                 case 0:
418                 case 1:
419                 case 3:
420                 case 4:
421                 case 5:
422                 case 6:
423                 case 7:
424                 case 8:
425                 case 9:
426                         break;
427                 case 2:
428                         ret += 1;
429                         break;
430                 default:
431                         CTS_ERR("The parameter(src:%s) has invalid character set", src);
432                 }
433                 break;
434         case 5:
435                 if (len <= ret) return 0;
436                 switch (src[ret++]-'0') {
437                 case 1:
438                 case 2:
439                 case 3:
440                 case 4:
441                 case 5:
442                 case 6:
443                 case 7:
444                 case 8:
445                         break;
446                 case 0:
447                 case 9:
448                         ret += 1;
449                         break;
450                 default:
451                         CTS_ERR("The parameter(src:%s) has invalid character set", src);
452                 }
453                 break;
454         case 6:
455                 if (len <= ret) return 0;
456                 switch (src[ret++]-'0') {
457                 case 0:
458                 case 1:
459                 case 2:
460                 case 3:
461                 case 4:
462                 case 5:
463                 case 6:
464                         break;
465                 case 7:
466                 case 8:
467                 case 9:
468                         ret += 1;
469                         break;
470                 default:
471                         CTS_ERR("The parameter(src:%s) has invalid character set", src);
472                 }
473                 break;
474         case 8:
475                 if (len <= ret) return 0;
476                 switch (src[ret++]-'0') {
477                 case 1:
478                 case 2:
479                 case 4:
480                 case 6:
481                         break;
482                 case 0:
483                 case 3:
484                 case 5:
485                 case 7:
486                 case 8:
487                 case 9:
488                         ret += 1;
489                         break;
490                 default:
491                         CTS_ERR("The parameter(src:%s) has invalid character set", src);
492                 }
493                 break;
494         case 9:
495                 if (len <= ret) return 0;
496                 switch (src[ret++]-'0') {
497                 case 0:
498                 case 1:
499                 case 2:
500                 case 3:
501                 case 4:
502                 case 5:
503                 case 8:
504                         break;
505                 case 6:
506                 case 7:
507                 case 9:
508                         ret += 1;
509                         break;
510                 default:
511                         CTS_ERR("The parameter(src:%s) has invalid character set", src);
512                 }
513                 break;
514         case 0:
515         default:
516                 CTS_ERR("The parameter(src:%s) has invalid character set", src);
517                 return 0;
518         }
519
520         return ret;
521 }
522
523 /*
524  * Number Matching Rule
525  * refer to the http://www.itu.int/dms_pub/itu-t/opb/sp/T-SP-E.164C-2011-PDF-E.pdf
526  */
527 enum {
528         CTSVC_PLUS_ONLY,     /* + */
529         CTSVC_PLUS_IP_ONLY,  /* +IP (International prefix) */
530         CTSVC_PLUS_CC_ONLY,  /* +CC (Country code) */
531         CTSVC_PLUS_IP_CC,    /* +IP CC */
532         CTSVC_IP_ONLY,       /* IP */
533         CTSVC_CC_ONLY,       /* CC */
534         CTSVC_IP_CC,         /* IP CC */
535         CTSVC_NONE,
536 };
537
538 static int __ctsvc_number_has_ip_and_cc(const char*number, int len, int *index)
539 {
540         bool have_cc = false;
541         bool have_plus = false;
542         int ret = CTSVC_NONE;
543         int start_index;
544         int match_len;
545         *index = 0;
546
547         /* Check IP */
548         start_index = 0;
549         match_len = 0;
550
551         switch(number[start_index]) {
552         case '+':
553                 start_index++;
554                 have_plus = true;
555                 if (len <= start_index) {
556                         *index = start_index;
557                         return CTSVC_PLUS_ONLY;   /* '+' */
558                 }
559         default:
560                 {
561                         /*
562                          * IP can be
563                          *  0 (Turks and Caicos Islands, Samoa)
564                          *  00, 011, 0011, 010, 000
565                          *  001/007 (Cambodia), 001/008 (Indonesia, Singapore)
566                          *  001/002 (Korea), 002(Taiwan)
567                          *  810 (Belarus, Kazakhstan, Russian, Tajikistan, Turkmenistan)
568                          *  009/007/005(Colombia), 009(Nigeria)
569                          *  119 (Cuba)
570                          *  00/012/013/014 (Israel)
571                          */
572                         switch(number[start_index]) {
573                         case '0':   /* '+0' */
574                                 {
575                                         start_index++;
576                                         if (len <= start_index) {
577                                                 *index = start_index;
578                                                 return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY); /* '+0' */
579                                         }
580
581                                         switch(number[start_index]) {
582                                         case '0':   /* '+00' */
583                                                 {
584                                                         start_index++;
585                                                         if (len <= start_index) {
586                                                                 *index = start_index;
587                                                                 return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);      /* '+00' */
588                                                         }
589
590                                                         switch(number[start_index]) {
591                                                         case '0':   /* '+000' */
592                                                         case '2':   /* '+002' */
593                                                         case '5':   /* '+005' */
594                                                         case '7':   /* '+007' */
595                                                         case '8':   /* '+008' */
596                                                         case '9':   /* '+009' */
597                                                                             /* or '+00 CC' */
598                                                                 start_index++;
599                                                                 if (len <= start_index) {
600                                                                         *index = start_index;
601                                                                         return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);  /* '+00Y' */
602                                                                 }
603
604                                                                 have_cc = __ctsvc_phone_number_has_country_code(&number[start_index], len-start_index);
605                                                                 if (0 < have_cc) {
606                                                                         *index = start_index;
607                                                                         return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_IP_CC);      /* '+00Y CC' */
608                                                                 }
609                                                                 else {
610                                                                         have_cc = __ctsvc_phone_number_has_country_code(&number[start_index-1], len-start_index+1);
611                                                                         if (0 < have_cc) {
612                                                                                 *index = start_index-1;
613                                                                                 return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_IP_CC);  /* '+00 CC' */
614                                                                         }
615                                                                 }
616                                                                 *index = start_index;
617                                                                 return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);      /* '+00Y XXX' */
618                                                         case '1':   /* '+001' */
619                                                                 start_index++;
620                                                                 if (len <= start_index) {
621                                                                         *index = start_index;
622                                                                         return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);  /* '+001' */
623                                                                 }
624
625                                                                 if (number[start_index] == '1') {
626                                                                         start_index++;
627                                                                         if (len <= start_index) {
628                                                                                 *index = start_index;
629                                                                                 return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);   /* '+0011' */
630                                                                         }
631
632                                                                         have_cc = __ctsvc_phone_number_has_country_code(&number[start_index], len-start_index);
633                                                                         if (0 < have_cc) {
634                                                                                 *index = start_index;
635                                                                                 return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_IP_CC);  /*  '+0011 CC' */
636                                                                         }
637                                                                         start_index--;
638                                                                 }
639
640                                                                 have_cc = __ctsvc_phone_number_has_country_code(&number[start_index], len-start_index);
641                                                                 *index = start_index;
642                                                                 if (0 < have_cc)
643                                                                         return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_IP_CC);      /* '+001 CC' */
644                                                                 else
645                                                                         return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);  /* '+001 XXX' */
646                                                         default:   /* '+00 3', '+00 4', '+00 6' */
647                                                                 *index = start_index;
648                                                                 have_cc = __ctsvc_phone_number_has_country_code(&number[start_index], len-start_index);
649                                                                 if (0 < have_cc)
650                                                                         return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_IP_CC);      /* '+00 CC' */
651                                                                 else
652                                                                         return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);  /* '+00 XXX' */
653                                                         }   /* end of fourth switch */
654                                                 }
655                                                 break;
656                                         case '1':   /* '+01' */
657                                                 {
658                                                         start_index++;
659                                                         if (len <= start_index) {
660                                                                 *index = start_index-1;   /* '+0 1' */
661                                                                 return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_NONE);
662                                                         }
663
664                                                         switch(number[start_index]) {
665                                                         case '0':   /* '+010' */
666                                                         case '1':   /* '+011' */
667                                                         case '2':   /* '+012' */
668                                                         case '3':   /* '+013' */
669                                                         case '4':   /* '+014' */
670                                                                 {
671                                                                         start_index++;
672                                                                         if (len <= start_index) {
673                                                                                 *index = start_index;
674                                                                                 return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);   /* '+01Y' */
675                                                                         }
676
677                                                                         have_cc = __ctsvc_phone_number_has_country_code(&number[start_index], len-start_index);
678                                                                         *index = start_index;
679                                                                         if (0 < have_cc)
680                                                                                 return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_IP_CC);   /* '+01Y CC' */
681                                                                         else
682                                                                                 return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);   /* '+01Y XXX' */
683                                                                 }
684                                                                 break;
685                                                         default:
686                                                                 *index = start_index-1;   /* '+0 1' */
687                                                                 return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_NONE);
688                                                         }
689                                                 }
690                                                 break;
691                                         default:   /* '+0 CC' */
692                                                 {
693                                                         have_cc = __ctsvc_phone_number_has_country_code(&number[start_index], len-start_index);
694                                                         *index = start_index;
695                                                         if (0 < have_cc)
696                                                                 return (have_plus?CTSVC_PLUS_IP_CC:CTSVC_IP_CC);          /* '+0 CC' */
697                                                         else
698                                                                 return (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);      /* '+0 XXX' */
699                                                 }
700                                                 break;
701                                         }   /* end of third switch */
702                                 }
703                                 break;   /* end of '+0' */
704                         case '1':   /* '+1' */
705                                 start_index++;
706                                 if (start_index+2 <= len && STRING_EQUAL == strncmp(&number[start_index], "19", 2)) {   /* '+119' */
707                                         match_len = start_index + 2;
708                                         ret = (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);
709                                 }
710                                 else {
711                                         match_len = start_index-1;
712                                         ret = (have_plus?CTSVC_PLUS_ONLY:CTSVC_NONE);   /* '+ CC' */
713                                 }
714                                 break;
715                         case '8':   /* '+8' */
716                                 start_index++;
717                                 if (start_index+2 <= len && STRING_EQUAL == strncmp(&number[start_index], "10", 2)) {   /* '+810' */
718                                         match_len = start_index + 2;
719                                         ret = (have_plus?CTSVC_PLUS_IP_ONLY:CTSVC_IP_ONLY);
720                                 }
721                                 else {
722                                         match_len = start_index-1;
723                                         ret = (have_plus?CTSVC_PLUS_ONLY:CTSVC_NONE);   /* '+ CC' */
724                                 }
725                                 break;
726                         default:
727                                 match_len = start_index;
728                                 ret = (have_plus?CTSVC_PLUS_ONLY:CTSVC_NONE);   /* '+ CC' */
729                                 break;
730                         }   /* end of second switch */
731                 }
732                 break;   /* '+' default */
733         }   /* end of first switch */
734         *index = match_len;
735
736         /* Check CC */
737         if (match_len < len) {
738                 have_cc = __ctsvc_phone_number_has_country_code(&number[match_len], len-match_len);
739                 if (0 < have_cc) {
740                         switch (ret) {
741                         case CTSVC_NONE:
742                                 return CTSVC_CC_ONLY;
743                         case CTSVC_PLUS_ONLY:
744                                 return CTSVC_PLUS_CC_ONLY;
745                         case CTSVC_PLUS_IP_ONLY:
746                                 return CTSVC_PLUS_IP_CC;
747                         case CTSVC_IP_ONLY:
748                                 return CTSVC_IP_CC;
749                         }
750                 }
751         }
752         return ret;
753 }
754
755 int ctsvc_normalize_number(const char *src, char *dest, int dest_size, bool replace_alphabet)
756 {
757         int ret;
758         int d_pos;
759         int s_pos;
760         char *normalized_out = NULL;
761         char temp[dest_size];
762
763
764         if (NULL == src) {
765                 CTS_ERR("The parameter(src) is NULL");
766                 return 0;
767         }
768
769         d_pos = strlen(src);
770         if (d_pos <= 0)
771                 return d_pos;
772
773         d_pos = 0;
774         s_pos = 0;
775         if (src[s_pos] == '+')
776                 temp[d_pos++] = src[s_pos++];
777         while (src[s_pos] != 0) {
778                 if (src[s_pos] == '+' || src[s_pos] == ';')
779                         s_pos++;
780                 temp[d_pos++] = src[s_pos++];
781         }
782         temp[d_pos] = 0;
783
784         ret = phone_number_get_normalized_number(temp, &normalized_out);
785         if (PHONE_NUMBER_ERROR_NONE == ret) {
786                 d_pos = strlen(normalized_out);
787                 memcpy(dest, normalized_out, d_pos+1);
788                 free(normalized_out);
789         }
790         else {
791                 memcpy(dest, temp, d_pos+1);
792         }
793
794         dest[d_pos] = 0;
795
796         return d_pos;
797 }
798
799 /*
800  * vaild character : digit, +, *, #,, ;, alphabet(depends on replace_alphabet parameter)
801  * Remove invalid string from number
802  */
803 int ctsvc_clean_number(const char *src, char *dest, int dest_size, bool replace_alphabet)
804 {
805         int s_pos;
806         int d_pos;
807         int pos;
808         char temp[dest_size];
809
810         if (NULL == src) {
811                 CTS_ERR("The parameter(src) is NULL");
812                 return 0;
813         }
814
815         s_pos = 0;
816         pos = 0;
817         while (src[s_pos] != 0) {
818                 int char_len;
819                 if (dest_size-2 < pos) break;
820
821                 char_len = ctsvc_check_utf8(src[s_pos]);
822                 if (char_len <= 0) {
823                         break;
824                 }
825
826                 if (char_len == 3) {
827                         /* fullwidth -> halfwidth */
828                         if (src[s_pos] == 0xef) {
829                                 if (src[s_pos+1] == 0xbc) {
830                                         if (0x90 <= src[s_pos+2] && src[s_pos+2] <= 0x99)        /* ef bc 90 : '0' ~ ef bc 99 : '9' */
831                                                 temp[pos++] = src[s_pos+2] - 0x60;
832                                         else if (0xa1 <= src[s_pos+2] && src[s_pos+2] <= 0xba)   /* ef bc a1 : 'A' ~ ef bc ba : 'Z' */
833                                                 temp[pos++] = src[s_pos+2] - 0x60;
834                                         else if (0x8b == src[s_pos+2])   /* ef bc 8b : '+' */
835                                                 temp[pos++] = '+';
836                                         else if (0x8a == src[s_pos+2])   /* ef bc 8a : '*' */
837                                                 temp[pos++] = '*';
838                                         else if (0x83 == src[s_pos+2])   /* ef bc 83 : '#' */
839                                                 temp[pos++] = '#';
840                                         else if (0x8c == src[s_pos+2])   /* ef bc 8c : ',' */
841                                                 temp[pos++] = ',';
842                                         else if (0x9b == src[s_pos+2])   /* ef bc 9b : ';' */
843                                                 temp[pos++] = ';';
844                                 }
845                                 else if (src[s_pos+1] == 0xbd
846                                                 && (0x81 <= src[s_pos+2] && src[s_pos+2] <= 0x9a))   /* ef bd 81 : 'a' ~ ef bd 9a : 'z' */
847                                         temp[pos++] = src[s_pos+2] - 0x40;
848                         }
849                         else {
850                                 s_pos += char_len;
851                                 continue;
852                         }
853                 }
854                 else if (char_len == 1) {
855                         if (0x41 <= src[s_pos] && src[s_pos] <= 0x5a)        /* 'A' ~ 'Z' */
856                                 temp[pos++] = src[s_pos];
857                         else if (0x61 <= src[s_pos] && src[s_pos] <= 0x7a)   /* 'a' ~ 'z' */
858                                 temp[pos++] = src[s_pos] - 0x20;
859                         else
860                                 temp[pos++] = src[s_pos];
861                 }
862                 s_pos += char_len;
863         }
864         temp[pos] = 0x0;
865
866         pos = 0;
867         d_pos = 0;
868         while (temp[pos] != 0) {
869                 if ('0' <= temp[pos] && temp[pos] <= '9')
870                         dest[d_pos++] = temp[pos];
871                 else if (temp[pos] == '+' || temp[pos] == '#'
872                                 || temp[pos] == '*' || temp[pos] == ';' || temp[pos] == ',')
873                         dest[d_pos++] = temp[pos];
874                 pos++;
875         }
876         dest[d_pos] = 0;
877
878         return d_pos;
879 }
880
881 static int __ctsvc_minmatch_number(const char *src, char *dest, int dest_size, int min_match)
882 {
883         int i;
884         int len = 0;
885         int d_pos = 0;
886         const char *temp_number;
887         const char *cc = ctsvc_get_network_cc(false);
888
889         if ('+' == src[0]) {
890                 len = __ctsvc_phone_number_has_country_code(&src[1], strlen(src)-1);
891                 temp_number = src + len +1;
892         }
893         else if ('0' == src[0])
894                 temp_number = src+1;
895         else if (cc && cc[0] == '7' && src[0] == '8')
896                 temp_number = src+1;
897         else
898                 temp_number = src;
899
900         len = strlen(temp_number);
901
902         if (0 < len) {
903                 while (0 <= (len-d_pos-1) && temp_number[len-d_pos-1]
904                                 && d_pos < min_match) {
905                         if (dest_size-d_pos == 0) {
906                                 CTS_ERR("Destination string buffer is not enough(%s)", src);
907                                 return CONTACTS_ERROR_INTERNAL;
908                         }
909
910                         dest[d_pos] = temp_number[len-d_pos-1];
911                         d_pos++;
912                 }
913                 dest[d_pos] = 0;
914
915                 len = strlen(dest);
916                 for (i=0; i<len/2;i++) {
917                         char c;
918                         c = dest[i];
919                         dest[i] = dest[len-i-1];
920                         dest[len-i-1] = c;
921                 }
922         }
923         else {
924                 memcpy(dest, src, strlen(src));
925                 dest[strlen(src)] = 0;
926         }
927
928         return CONTACTS_ERROR_NONE;
929 }
930
931 int ctsvc_get_minmatch_number(const char *src, char *dest, int dest_size, int min_match)
932 {
933         int ret;
934
935         RETV_IF(NULL == src, CONTACTS_ERROR_INVALID_PARAMETER);
936         RETV_IF(NULL == dest, CONTACTS_ERROR_INVALID_PARAMETER);
937
938         ret = __ctsvc_minmatch_number(src, dest, dest_size, min_match);
939         if (ret != CONTACTS_ERROR_NONE) {
940                 CTS_ERR("__ctsvc_minmatch_number() Fail(%d)", ret);
941                 return ret;
942         }
943
944         return CONTACTS_ERROR_NONE;
945 }
946
947 static bool __ctsvc_is_phonenumber_halfwidth(const char* keyword)
948 {
949         int i;
950         int len = strlen(keyword);
951
952         /* TODO: we should add predicate including '+' */
953         /* TODO: finally, we try to check the number with regular expression. */
954         for (i=0; i<len; i++) {
955                 if ((keyword[i] < '0' || '9' < keyword[i]) && keyword[i] != '+') {
956                         CTS_ERR("keyword[%d]: %c is not number)", i, keyword[i]);
957                         return false;
958                 }
959         }
960         return true;
961 }
962
963 #define UTF8_FULLWIDTH_LENGTH 3
964 static bool __ctsvc_is_phonenumber_fullwidth(const char* keyword)
965 {
966         int char_len = 1;
967         int str_len;
968         int i;
969         if (keyword == NULL || *keyword == '\0')
970                 return false;
971
972         str_len = strlen(keyword);
973         for (i=0;i<str_len;i += char_len) {
974                 char_len = ctsvc_check_utf8(keyword[i]);
975                 if (char_len != UTF8_FULLWIDTH_LENGTH || str_len-i < UTF8_FULLWIDTH_LENGTH)
976                         return false;
977
978                 if (keyword[i] == 0xef) {
979                         if (keyword[i+1] == 0xbc) {
980                                 if (0x90 <= keyword[i+2] && keyword[i+2] <= 0x99)            /* ef bc 90 : '0' ~ ef bc 99 : '9' */
981                                         continue;
982                                 else if (0x8b == keyword[i+2])   /* ef bc 8b : '+' */
983                                         continue;
984                                 else
985                                         return false;
986                         }
987                         else
988                                 return false;
989                 }
990                 else
991                         return false;
992         }
993         return true;
994 }
995
996 bool ctsvc_is_phonenumber(const char* src)
997 {
998         return (__ctsvc_is_phonenumber_halfwidth(src) || __ctsvc_is_phonenumber_fullwidth(src));
999 }
1000
1001 /* numbers are cleaned number or normalized number */
1002 static bool __ctsvc_number_compare(const char *number1, const char *number2)
1003 {
1004         int len1;
1005         int len2;
1006         int matched;
1007         int minmatch_len = ctsvc_get_phonenumber_min_match_digit();
1008         const char *cc = ctsvc_get_network_cc(false);
1009
1010         if (NULL == number1 || NULL == number2 || '\0' == *number1 || '\0' == *number2)
1011                 return false;
1012
1013         len1 = strlen(number1);
1014         len2 = strlen(number2);
1015
1016         /* compare  number in reverse order */
1017         for (matched = 0; 0 < len1 && 0 < len2;) {
1018                 if (number1[len1-1] != number2[len2-1])
1019                         break;
1020                 len1--;
1021                 len2--;
1022                 matched++;
1023         }
1024
1025         /* full match */
1026         if (len1 == 0 && len2 == 0)
1027                 return true;
1028
1029         /* one is substring of the other string */
1030         if (minmatch_len <= matched&& (len1 == 0 || len2 == 0))
1031                 return true;
1032
1033         /* one is +IPCC or +CC, the other is start wth NTP (National trunk prefix) */
1034         if (minmatch_len <= matched) {
1035                 int index1 = 0;
1036                 int index2 = 0;
1037                 int cc_index = 0;
1038
1039                 /*
1040                  * International Prefix (IP) is related to current location where to call
1041                  * Country Code (CC) is related to the SIM card who to call
1042                  * If you try to call in United State using Korea SIM card,
1043                  * the number will be 011 82 X XXXXXXXX.
1044                  * So, when comparing number, just check IP validation and CC and natinal number matching.
1045                  */
1046
1047                 int n1 = __ctsvc_number_has_ip_and_cc(number1, len1, &index1);
1048                 int n2 = __ctsvc_number_has_ip_and_cc(number2, len2, &index2);
1049
1050                 /*
1051                  * + (IP) CC XXXXXXXX, 0XXXXXXXX
1052                  * + (810) 7 XXX XXX XX XX, 8XXX XXX XX XX (Russian)
1053                  */
1054                 if ((CTSVC_PLUS_IP_CC == n1 || CTSVC_PLUS_CC_ONLY == n1 ||
1055                                 CTSVC_IP_CC == n1 || CTSVC_CC_ONLY == n1)
1056                                 && (number2[0] == '0' || (cc && cc[0] == '7' && number2[0] == '8')))
1057                         return true;
1058                 else if ((CTSVC_PLUS_IP_CC == n2 || CTSVC_PLUS_CC_ONLY == n2 ||
1059                                         CTSVC_IP_CC == n2 || CTSVC_CC_ONLY == n2)
1060                                 && (number1[0] == '0' || (cc && cc[0] == '7' && number1[0] == '8')))
1061                         return true;
1062                 /*
1063                  * + IP CC XXXXXXXX, + CC XXXXXXXX  (ex. +001 82  11 1234 5678, +82 10 1234 5678)
1064                  */
1065                 else if ((CTSVC_PLUS_IP_CC == n1 || CTSVC_IP_CC == n1)
1066                                 && (CTSVC_PLUS_CC_ONLY == n2 || CTSVC_CC_ONLY == n2)) {
1067                         int p = (CTSVC_PLUS_CC_ONLY == n2)?1:0;
1068                         cc_index = __ctsvc_phone_number_has_country_code(&number2[p], len2-p);
1069                         if (0 < cc_index && STRING_EQUAL == strncmp(&number1[index1], &number2[p], cc_index))
1070                                 return true;
1071                 }
1072                 else if ((CTSVC_PLUS_IP_CC == n2 || CTSVC_IP_CC == n2)
1073                                 && (CTSVC_PLUS_CC_ONLY == n1 || CTSVC_CC_ONLY == n1)) {
1074                         int p = (CTSVC_PLUS_CC_ONLY == n1)?1:0;
1075                         cc_index = __ctsvc_phone_number_has_country_code(&number1[p], len1-p);
1076                         if (0 < cc_index && STRING_EQUAL == strncmp(&number2[index2], &number1[p], cc_index))
1077                                 return true;
1078                 }
1079                 /*
1080                  * + CC XXXXXXXX, + IP CC XXXXXXXX  (ex. +001 82  10 1234 5678, +82 10 1234 5678)
1081                  */
1082                 else if ((CTSVC_PLUS_IP_ONLY == n1 || CTSVC_IP_ONLY == n1)
1083                                 && CTSVC_PLUS_ONLY == n2) {
1084                         return true;
1085                 }
1086                 else if ((CTSVC_PLUS_IP_ONLY == n2 || CTSVC_IP_ONLY == n2)
1087                                 && CTSVC_PLUS_ONLY == n1) {
1088                         return true;
1089                 }
1090         }
1091
1092         return false;
1093 }
1094
1095 /* When querying _NUMBER_COMPARE_, this function will be called. */
1096 void ctsvc_db_phone_number_equal_callback(sqlite3_context * context,
1097                 int argc, sqlite3_value ** argv)
1098 {
1099 #ifdef _CONTACTS_IPC_SERVER
1100         char *number1;
1101         char *number2;
1102
1103         if (argc < 4) {
1104                 sqlite3_result_int(context, 0);
1105                 CTS_ERR("argc invalid");
1106                 return;
1107         }
1108
1109         number1 = (char*)sqlite3_value_text(argv[0]);
1110         number2 = (char*)sqlite3_value_text(argv[1]);
1111
1112         sqlite3_result_int(context, __ctsvc_number_compare(number1, number2));
1113         return;
1114 #endif
1115 }
1116