4 * Copyright (c) 2010 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include "ctsvc_internal.h"
24 #include "ctsvc_db_sqlite.h"
25 #include "ctsvc_db_schema.h"
26 #include "ctsvc_db_init.h"
27 #include "ctsvc_db_query.h"
28 #include "ctsvc_db_utils.h"
29 #include "ctsvc_record.h"
30 #include "ctsvc_normalize.h"
31 #include "ctsvc_number_utils.h"
32 #include "ctsvc_list.h"
33 #include "ctsvc_server_setting.h"
34 #include "ctsvc_localize_ch.h"
35 #include "ctsvc_server_group.h"
36 #include "ctsvc_notification.h"
37 #include "ctsvc_localize.h"
38 #include "ctsvc_localize_utils.h"
39 #include "ctsvc_server_person.h"
40 #include "ctsvc_notify.h"
42 #ifdef ENABLE_LOG_FEATURE
43 #include "ctsvc_server_phonelog.h"
44 #endif /* ENABLE_LOG_FEATURE */
45 #include "ctsvc_db_access_control.h"
47 #include "ctsvc_db_plugin_contact_helper.h"
48 #include "ctsvc_db_plugin_person_helper.h"
51 static int __ctsvc_db_get_contact_base_info(int id, ctsvc_contact_s *contact)
56 char query[CTS_SQL_MAX_LEN] = {0};
58 char full_path[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
60 snprintf(query, sizeof(query),
61 "SELECT contact_id, addressbook_id, person_id, changed_time, changed_ver, link_mode, %s, "
62 "display_name_source, image_thumbnail_path, "
63 "ringtone_path, vibration, message_alert, "
64 "uid, is_favorite, has_phonenumber, has_email, "
65 "sort_name, reverse_sort_name "
66 "FROM "CTS_TABLE_CONTACTS" WHERE contact_id = %d AND deleted = 0",
67 ctsvc_get_display_column(), id);
69 ret = ctsvc_query_prepare(query, &stmt);
70 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
72 ret = ctsvc_stmt_step(stmt);
73 if (1 /*CTS_TRUE*/ != ret) {
74 ERR("ctsvc_stmt_step() Fail(%d)", ret);
75 ctsvc_stmt_finalize(stmt);
76 if (CONTACTS_ERROR_NONE == ret)
77 return CONTACTS_ERROR_NO_DATA;
83 contact->id = ctsvc_stmt_get_int(stmt, i++);
84 contact->addressbook_id = ctsvc_stmt_get_int(stmt, i++);
85 contact->person_id = ctsvc_stmt_get_int(stmt, i++);
86 contact->changed_time = ctsvc_stmt_get_int(stmt, i++);
87 contact->changed_ver = ctsvc_stmt_get_int(stmt, i++);
88 contact->link_mode = ctsvc_stmt_get_int(stmt, i++);
89 temp = ctsvc_stmt_get_text(stmt, i++);
90 contact->display_name = SAFE_STRDUP(temp);
91 contact->display_source_type = ctsvc_stmt_get_int(stmt, i++);
93 temp = ctsvc_stmt_get_text(stmt, i++);
95 snprintf(full_path, sizeof(full_path), "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, temp);
96 contact->image_thumbnail_path = strdup(full_path);
99 temp = ctsvc_stmt_get_text(stmt, i++);
100 contact->ringtone_path = SAFE_STRDUP(temp);
101 temp = ctsvc_stmt_get_text(stmt, i++);
102 contact->vibration = SAFE_STRDUP(temp);
103 temp = ctsvc_stmt_get_text(stmt, i++);
104 contact->message_alert = SAFE_STRDUP(temp);
105 temp = ctsvc_stmt_get_text(stmt, i++);
106 contact->uid = SAFE_STRDUP(temp);
107 contact->is_favorite = ctsvc_stmt_get_int(stmt, i++);
108 contact->has_phonenumber = ctsvc_stmt_get_int(stmt, i++);
109 contact->has_email = ctsvc_stmt_get_int(stmt, i++);
110 temp = ctsvc_stmt_get_text(stmt, i++);
111 contact->sort_name = SAFE_STRDUP(temp);
112 temp = ctsvc_stmt_get_text(stmt, i++);
113 contact->reverse_sort_name = SAFE_STRDUP(temp);
114 ctsvc_stmt_finalize(stmt);
116 return CONTACTS_ERROR_NONE;
119 static int __ctsvc_db_get_data(int id, ctsvc_contact_s *contact)
123 cts_stmt stmt = NULL;
124 char query[CTS_SQL_MAX_LEN] = {0};
126 snprintf(query, sizeof(query),
127 "SELECT datatype, id, data.contact_id, is_default, data1, data2, "
128 "data3, data4, data5, data6, data7, data8, data9, data10, data11, data12 "
129 "FROM "CTS_TABLE_DATA", "CTSVC_DB_VIEW_CONTACT" "
130 "ON "CTS_TABLE_DATA".contact_id = "CTSVC_DB_VIEW_CONTACT".contact_id "
131 "WHERE data.contact_id = %d AND is_my_profile = 0 "
132 "ORDER BY is_default DESC", id);
134 ret = ctsvc_query_prepare(query, &stmt);
135 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
137 ret = ctsvc_stmt_step(stmt);
138 if (1 /*CTS_TRUE */!= ret) {
139 ERR("ctsvc_stmt_step() Fail(%d)", ret);
140 ctsvc_stmt_finalize(stmt);
145 datatype = ctsvc_stmt_get_int(stmt, 0);
147 case CTSVC_DATA_NAME:
148 ctsvc_get_data_info_name(stmt, (contacts_list_h)contact->name);
150 case CTSVC_DATA_EVENT:
151 ctsvc_get_data_info_event(stmt, (contacts_list_h)contact->events);
153 case CTSVC_DATA_MESSENGER:
154 ctsvc_get_data_info_messenger(stmt, (contacts_list_h)contact->messengers);
156 case CTSVC_DATA_POSTAL:
157 ctsvc_get_data_info_address(stmt, (contacts_list_h)contact->postal_addrs);
160 ctsvc_get_data_info_url(stmt, (contacts_list_h)contact->urls);
162 case CTSVC_DATA_NICKNAME:
163 ctsvc_get_data_info_nickname(stmt, (contacts_list_h)contact->nicknames);
165 case CTSVC_DATA_NUMBER:
166 ctsvc_get_data_info_number(stmt, (contacts_list_h)contact->numbers);
168 case CTSVC_DATA_EMAIL:
169 ctsvc_get_data_info_email(stmt, (contacts_list_h)contact->emails);
171 case CTSVC_DATA_PROFILE:
172 ctsvc_get_data_info_profile(stmt, (contacts_list_h)contact->profiles);
174 case CTSVC_DATA_RELATIONSHIP:
175 ctsvc_get_data_info_relationship(stmt, (contacts_list_h)contact->relationships);
177 case CTSVC_DATA_IMAGE:
178 ctsvc_get_data_info_image(stmt, (contacts_list_h)contact->images);
180 case CTSVC_DATA_COMPANY:
181 ctsvc_get_data_info_company(stmt, (contacts_list_h)contact->company);
183 case CTSVC_DATA_NOTE:
184 ctsvc_get_data_info_note(stmt, (contacts_list_h)contact->note);
186 case CTSVC_DATA_EXTENSION:
187 ctsvc_get_data_info_extension(stmt, (contacts_list_h)contact->extensions);
190 ctsvc_get_data_info_sip(stmt, (contacts_list_h)contact->sips);
193 ERR("Intenal : Not supported data type (%d)", datatype);
197 } while (1 == ctsvc_stmt_step(stmt));
199 ctsvc_stmt_finalize(stmt);
201 return CONTACTS_ERROR_NONE;
205 static inline int __ctsvc_get_contact_grouprel(int contact_id, ctsvc_contact_s *contact)
209 ctsvc_group_relation_s *grouprel;
210 cts_stmt stmt = NULL;
211 char query[CTS_SQL_MAX_LEN] = {0};
214 snprintf(query, sizeof(query),
215 "SELECT group_id, contact_id, group_name "
216 " FROM "CTSVC_DB_VIEW_GROUP_RELATION" WHERE contact_id = %d", contact_id);
218 ret = ctsvc_query_prepare(query, &stmt);
219 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
221 while (1 /*CTS_TRUE */ == ctsvc_stmt_step(stmt)) {
222 contacts_record_create(_contacts_group_relation._uri, (contacts_record_h*)&grouprel);
225 grouprel->group_id = ctsvc_stmt_get_int(stmt, 0);
226 grouprel->id = grouprel->group_id;
227 grouprel->contact_id = ctsvc_stmt_get_int(stmt, 1);
228 temp = ctsvc_stmt_get_text(stmt, 2);
229 grouprel->group_name = SAFE_STRDUP(temp);
231 ctsvc_list_prepend((contacts_list_h)contact->grouprelations, (contacts_record_h)grouprel);
235 ctsvc_stmt_finalize(stmt);
236 ctsvc_list_reverse((contacts_list_h)contact->grouprelations);
237 return CONTACTS_ERROR_NONE;
240 static int __ctsvc_db_contact_get_record(int id, contacts_record_h *out_record)
243 contacts_record_h record;
244 ctsvc_contact_s *contact;
246 RETV_IF(NULL == out_record, CONTACTS_ERROR_INVALID_PARAMETER);
249 contacts_record_create(_contacts_contact._uri, &record);
250 contact = (ctsvc_contact_s*)record;
251 ret = __ctsvc_db_get_contact_base_info(id, contact);
252 if (CONTACTS_ERROR_NONE != ret) {
253 ERR("__ctsvc_db_get_contact_base_info(ALL) Fail(%d)", ret);
254 contacts_record_destroy(record, true);
258 ret = __ctsvc_db_get_data(id, contact);
259 if (CONTACTS_ERROR_NONE != ret && CONTACTS_ERROR_NO_DATA != ret) {
260 ERR("ctsvc_get_data_info Fail(%d)", ret);
261 contacts_record_destroy(record, true);
265 ret = __ctsvc_get_contact_grouprel(id, contact);
266 if (CONTACTS_ERROR_NONE != ret) {
267 ERR("ctsvc_get_group_relations Fail(%d)", ret);
268 contacts_record_destroy(record, true);
272 *out_record = record;
274 return CONTACTS_ERROR_NONE;
277 static int __ctsvc_db_contact_delete_record(int id)
279 return ctsvc_db_contact_delete(id);
282 static inline int __ctsvc_contact_update_data(ctsvc_contact_s *contact)
287 ret = ctsvc_contact_update_data_name((contacts_list_h)contact->name, contact->id, false);
288 if (CONTACTS_ERROR_NONE != ret) {
289 ERR("ctsvc_contact_update_data_name() Fail(%d)", ret);
294 if (contact->company) {
295 ret = ctsvc_contact_update_data_company((contacts_list_h)contact->company, contact->id, false);
296 if (CONTACTS_ERROR_NONE != ret) {
297 ERR("ctsvc_contact_update_data_company() Fail(%d)", ret);
303 ret = ctsvc_contact_update_data_note((contacts_list_h)contact->note, contact->id, false);
304 if (CONTACTS_ERROR_NONE != ret) {
305 ERR("ctsvc_contact_update_data_note() Fail(%d)", ret);
310 if (contact->events) {
311 ret = ctsvc_contact_update_data_event((contacts_list_h)contact->events, contact->id, false);
312 if (CONTACTS_ERROR_NONE != ret) {
313 ERR("ctsvc_contact_update_data_events() Fail(%d)", ret);
318 if (contact->messengers) {
319 ret = ctsvc_contact_update_data_messenger((contacts_list_h)contact->messengers, contact->id, false);
320 if (CONTACTS_ERROR_NONE != ret) {
321 ERR("ctsvc_contact_update_data_messengers() Fail(%d)", ret);
326 if (contact->postal_addrs) {
327 ret = ctsvc_contact_update_data_address((contacts_list_h)contact->postal_addrs, contact->id, false);
328 if (CONTACTS_ERROR_NONE != ret) {
329 ERR("ctsvc_contact_update_data_address() Fail(%d)", ret);
335 ret = ctsvc_contact_update_data_url((contacts_list_h)contact->urls, contact->id, false);
336 if (CONTACTS_ERROR_NONE != ret) {
337 ERR("ctsvc_contact_update_data_url() Fail(%d)", ret);
342 if (contact->nicknames) {
343 ret = ctsvc_contact_update_data_nickname((contacts_list_h)contact->nicknames, contact->id, false);
344 if (CONTACTS_ERROR_NONE != ret) {
345 ERR("ctsvc_contact_update_data_nickname() Fail(%d)", ret);
350 if (contact->numbers) {
351 bool had_phonenumber;
352 ret = ctsvc_contact_update_data_number((contacts_list_h)contact->numbers, contact->id, false, &had_phonenumber);
353 if (CONTACTS_ERROR_NONE != ret) {
354 ERR("ctsvc_contact_update_data_number() Fail(%d)", ret);
357 contact->has_phonenumber = had_phonenumber;
360 if (contact->emails) {
362 ret = ctsvc_contact_update_data_email((contacts_list_h)contact->emails, contact->id, false, &had_email);
363 if (CONTACTS_ERROR_NONE != ret) {
364 ERR("ctsvc_contact_update_data_email() Fail(%d)", ret);
367 contact->has_email = had_email;
370 if (contact->profiles) {
371 ret = ctsvc_contact_update_data_profile((contacts_list_h)contact->profiles, contact->id, false);
372 if (CONTACTS_ERROR_NONE != ret) {
373 ERR("ctsvc_contact_update_data_profile() Fail(%d)", ret);
378 if (contact->relationships) {
379 ret = ctsvc_contact_update_data_relationship((contacts_list_h)contact->relationships, contact->id, false);
380 if (CONTACTS_ERROR_NONE != ret) {
381 ERR("ctsvc_contact_update_data_relationship() Fail(%d)", ret);
386 if (contact->images) {
387 ret = ctsvc_contact_update_data_image((contacts_list_h)contact->images, contact->id, false);
388 if (CONTACTS_ERROR_NONE != ret) {
389 ERR("ctsvc_contact_update_data_image() Fail(%d)", ret);
394 if (contact->extensions) {
395 ret = ctsvc_contact_update_data_extension((contacts_list_h)contact->extensions, contact->id, false);
396 if (CONTACTS_ERROR_NONE != ret) {
397 ERR("ctsvc_contact_update_data_extension() Fail(%d)", ret);
403 ret = ctsvc_contact_update_data_sip((contacts_list_h)contact->sips, contact->id, false);
404 if (CONTACTS_ERROR_NONE != ret) {
405 ERR("ctsvc_contact_update_data_sips() Fail(%d)", ret);
409 return CONTACTS_ERROR_NONE;
412 static void __ctsvc_contact_check_default_data(ctsvc_contact_s *contact)
414 if (contact->numbers)
415 contact->has_phonenumber = ctsvc_contact_check_default_number((contacts_list_h)contact->numbers);
417 contact->has_email = ctsvc_contact_check_default_email((contacts_list_h)contact->emails);
419 ctsvc_contact_check_default_image((contacts_list_h)contact->images);
420 if (contact->postal_addrs)
421 ctsvc_contact_check_default_address((contacts_list_h)contact->postal_addrs);
424 static inline int __ctsvc_contact_update_grouprel(int contact_id, contacts_list_h group_list)
427 ctsvc_group_relation_s *grouprel;
428 ctsvc_list_s *list = (ctsvc_list_s*)group_list;
434 RETV_IF(NULL == group_list, CONTACTS_ERROR_INVALID_PARAMETER);
436 for (cursor = list->deleted_records; cursor; cursor = cursor->next) {
437 grouprel = cursor->data;
438 ret = ctsvc_group_remove_contact_in_transaction(grouprel->group_id, contact_id);
443 ret = contacts_list_get_count(group_list, &count);
445 return CONTACTS_ERROR_NONE;
447 contacts_list_first(group_list);
449 contacts_list_get_current_record_p(group_list, (contacts_record_h*)&grouprel);
450 if (NULL == grouprel)
453 RETVM_IF(grouprel->group_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER, "group_id(%d) invalid", grouprel->group_id);
454 if (grouprel->group_id) {
455 ret = ctsvc_group_add_contact_in_transaction(grouprel->group_id, contact_id);
456 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_db_group_set_relation() Fail(%d)", ret);
460 } while (CONTACTS_ERROR_NONE == contacts_list_next(group_list));
465 return CONTACTS_ERROR_NONE;
468 static bool __ctsvc_contact_check_token(char *src, char *dest, int len)
473 for (i = 0; i < len; i++) {
474 if (src[i] == '@' || src[i] == '.') {
486 /* Make search data by number, email, nicknames, address, note, messenger, relationship, company */
487 static inline int __ctsvc_contact_make_search_data(ctsvc_contact_s *contact,
488 char **search_number, char **search_data)
494 char *temp_number = NULL;
495 char *temp_data = NULL;
498 RETV_IF(NULL == contact, CONTACTS_ERROR_NO_DATA);
500 if (contact->numbers) {
501 contacts_list_h number_list = (contacts_list_h)contact->numbers;
502 ctsvc_number_s *number_record;
503 contacts_list_first(number_list);
505 contacts_list_get_current_record_p(number_list, (contacts_record_h*)&number_record);
506 if (number_record && number_record->cleaned) {
507 buf_size = SAFE_STRLEN(number) + SAFE_STRLEN(number_record->cleaned) + SAFE_STRLEN(number_record->normalized) + 3;
508 temp_number = calloc(1, buf_size);
509 if (NULL == temp_number) {
510 ERR("calloc() Fail");
512 return CONTACTS_ERROR_OUT_OF_MEMORY;
516 snprintf(temp_number, buf_size, "%s %s %s", SAFE_STR(number), number_record->cleaned, number_record->normalized);
518 snprintf(temp_number, buf_size, "%s %s", number_record->cleaned, number_record->normalized);
520 number = temp_number;
522 } while (CONTACTS_ERROR_NONE == contacts_list_next(number_list));
525 if (contact->emails) {
526 contacts_list_h email_list = (contacts_list_h)contact->emails;
527 ctsvc_email_s *email;
528 contacts_list_first(email_list);
530 contacts_list_get_current_record_p(email_list, (contacts_record_h*)&email);
531 if (email && email->email_addr) {
532 int len = strlen(email->email_addr);
534 bool had = __ctsvc_contact_check_token(email->email_addr, temp, len);
536 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(email->email_addr)
538 temp_data = calloc(1, buf_size);
539 if (NULL == temp_data) {
540 ERR("calloc() Fail");
543 return CONTACTS_ERROR_OUT_OF_MEMORY;
547 snprintf(temp_data, buf_size, "%s %s %s", data, email->email_addr,
550 snprintf(temp_data, buf_size, "%s %s", email->email_addr,
556 } while (CONTACTS_ERROR_NONE == contacts_list_next(email_list));
559 if (contact->nicknames) {
560 contacts_list_h nickname_list = (contacts_list_h)contact->nicknames;
561 ctsvc_nickname_s *nickname;
562 contacts_list_first(nickname_list);
564 contacts_list_get_current_record_p(nickname_list, (contacts_record_h*)&nickname);
565 if (nickname && nickname->nickname) {
566 int len = strlen(nickname->nickname);
568 bool had = __ctsvc_contact_check_token(nickname->nickname, temp, len);
570 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(nickname->nickname) * (had ? 2 : 1) + 4;
571 temp_data = calloc(1, buf_size);
572 if (NULL == temp_data) {
573 ERR("calloc() Fail");
576 return CONTACTS_ERROR_OUT_OF_MEMORY;
580 snprintf(temp_data, buf_size, "%s %s %s", data, nickname->nickname, (had ? temp : ""));
582 snprintf(temp_data, buf_size, "%s %s", nickname->nickname, (had ? temp : ""));
586 } while (CONTACTS_ERROR_NONE == contacts_list_next(nickname_list));
589 if (contact->postal_addrs) {
590 contacts_list_h address_list = (contacts_list_h)contact->postal_addrs;
591 ctsvc_address_s *address;
592 contacts_list_first(address_list);
594 contacts_list_get_current_record_p(address_list, (contacts_record_h*)&address);
597 int str_len = SAFE_STRLEN(address->country)
598 + SAFE_STRLEN(address->pobox)
599 + SAFE_STRLEN(address->postalcode)
600 + SAFE_STRLEN(address->region)
601 + SAFE_STRLEN(address->locality)
602 + SAFE_STRLEN(address->street)
603 + SAFE_STRLEN(address->extended);
605 buf_size = SAFE_STRLEN(data)
607 temp_data = calloc(1, buf_size);
608 if (NULL == temp_data) {
609 ERR("calloc() Fail");
612 return CONTACTS_ERROR_OUT_OF_MEMORY;
615 char temp[str_len+1];
618 len += snprintf(temp_data + len, buf_size - len, "%s ", data);
620 if (address->country) {
621 had = __ctsvc_contact_check_token(address->country, temp, SAFE_STRLEN(address->country));
622 len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->country, had ? temp : "");
624 if (address->pobox) {
625 had = __ctsvc_contact_check_token(address->pobox, temp, SAFE_STRLEN(address->pobox));
626 len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->pobox, had ? temp : "");
628 if (address->postalcode) {
629 had = __ctsvc_contact_check_token(address->postalcode, temp, SAFE_STRLEN(address->postalcode));
630 len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->postalcode, had ? temp : "");
632 if (address->region) {
633 had = __ctsvc_contact_check_token(address->region, temp, SAFE_STRLEN(address->region));
634 len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->region, had ? temp : "");
636 if (address->locality) {
637 had = __ctsvc_contact_check_token(address->locality, temp, SAFE_STRLEN(address->locality));
638 len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->locality, had ? temp : "");
640 if (address->street) {
641 had = __ctsvc_contact_check_token(address->street, temp, SAFE_STRLEN(address->street));
642 len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->street, had ? temp : "");
644 if (address->extended) {
645 had = __ctsvc_contact_check_token(address->extended, temp, SAFE_STRLEN(address->extended));
646 len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->extended, had ? temp : "");
651 } while (CONTACTS_ERROR_NONE == contacts_list_next(address_list));
655 contacts_list_h note_list = (contacts_list_h)contact->note;
657 contacts_list_first(note_list);
659 contacts_list_get_current_record_p(note_list, (contacts_record_h*)¬e);
660 if (note && note->note) {
661 int len = strlen(note->note);
663 bool had = __ctsvc_contact_check_token(note->note, temp, len);
665 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(note->note) * (had ? 2 : 1) + 4;
666 temp_data = calloc(1, buf_size);
667 if (NULL == temp_data) {
668 ERR("calloc() Fail");
671 return CONTACTS_ERROR_OUT_OF_MEMORY;
675 snprintf(temp_data, buf_size, "%s %s %s", data, note->note,
678 snprintf(temp_data, buf_size, "%s %s", note->note,
684 } while (CONTACTS_ERROR_NONE == contacts_list_next(note_list));
687 if (contact->messengers) {
688 contacts_list_h messenger_list = (contacts_list_h)contact->messengers;
689 ctsvc_messenger_s *messenger;
690 contacts_list_first(messenger_list);
692 contacts_list_get_current_record_p(messenger_list, (contacts_record_h*)&messenger);
693 if (messenger && messenger->im_id) {
694 int len = strlen(messenger->im_id);
696 bool had = __ctsvc_contact_check_token(messenger->im_id, temp, len);
698 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(messenger->im_id) * (had ? 2 : 1) + 4;
699 temp_data = calloc(1, buf_size);
700 if (NULL == temp_data) {
701 ERR("calloc() Fail");
704 return CONTACTS_ERROR_OUT_OF_MEMORY;
708 snprintf(temp_data, buf_size, "%s %s %s", data, messenger->im_id,
711 snprintf(temp_data, buf_size, "%s %s", messenger->im_id,
717 } while (CONTACTS_ERROR_NONE == contacts_list_next(messenger_list));
720 if (contact->relationships) {
721 contacts_list_h relationship_list = (contacts_list_h)contact->relationships;
722 ctsvc_relationship_s *relationship;
723 contacts_list_first(relationship_list);
725 contacts_list_get_current_record_p(relationship_list, (contacts_record_h*)&relationship);
726 if (relationship && relationship->name) {
727 int len = strlen(relationship->name);
729 bool had = __ctsvc_contact_check_token(relationship->name, temp, len);
731 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(relationship->name) * (had ? 2 : 1) + 4;
732 temp_data = calloc(1, buf_size);
733 if (NULL == temp_data) {
734 ERR("calloc() Fail");
737 return CONTACTS_ERROR_OUT_OF_MEMORY;
741 snprintf(temp_data, buf_size, "%s %s %s", data, relationship->name,
744 snprintf(temp_data, buf_size, "%s %s", relationship->name,
750 } while (CONTACTS_ERROR_NONE == contacts_list_next(relationship_list));
753 if (contact->company) {
754 contacts_list_h company_list = (contacts_list_h)contact->company;
755 ctsvc_company_s *company;
756 contacts_list_first(company_list);
758 contacts_list_get_current_record_p(company_list, (contacts_record_h*)&company);
761 int str_len = SAFE_STRLEN(company->name)
762 + SAFE_STRLEN(company->department)
763 + SAFE_STRLEN(company->job_title)
764 + SAFE_STRLEN(company->role)
765 + SAFE_STRLEN(company->assistant_name)
766 + SAFE_STRLEN(company->location)
767 + SAFE_STRLEN(company->description)
768 + SAFE_STRLEN(company->phonetic_name);
770 buf_size = SAFE_STRLEN(data) + str_len * 2 + 18;
771 temp_data = calloc(1, buf_size);
772 if (NULL == temp_data) {
773 ERR("calloc() Fail");
776 return CONTACTS_ERROR_OUT_OF_MEMORY;
779 char temp[str_len+1];
782 len += snprintf(temp_data + len, buf_size - len, "%s ", data);
784 had = __ctsvc_contact_check_token(company->name, temp, SAFE_STRLEN(company->name));
785 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->name, had ? temp : "");
787 if (company->department) {
788 had = __ctsvc_contact_check_token(company->department, temp, SAFE_STRLEN(company->department));
789 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->department, had ? temp : "");
791 if (company->job_title) {
792 had = __ctsvc_contact_check_token(company->job_title, temp, SAFE_STRLEN(company->job_title));
793 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->job_title, had ? temp : "");
796 had = __ctsvc_contact_check_token(company->role, temp, SAFE_STRLEN(company->role));
797 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->role, had ? temp : "");
799 if (company->assistant_name) {
800 had = __ctsvc_contact_check_token(company->assistant_name, temp, SAFE_STRLEN(company->assistant_name));
801 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->assistant_name, had ? temp : "");
803 if (company->location) {
804 had = __ctsvc_contact_check_token(company->location, temp, SAFE_STRLEN(company->location));
805 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->location, had ? temp : "");
807 if (company->description) {
808 had = __ctsvc_contact_check_token(company->description, temp, SAFE_STRLEN(company->description));
809 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->description, had ? temp : "");
811 if (company->phonetic_name) {
812 had = __ctsvc_contact_check_token(company->phonetic_name, temp, SAFE_STRLEN(company->phonetic_name));
813 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->phonetic_name, had ? temp : "");
819 } while (CONTACTS_ERROR_NONE == contacts_list_next(company_list));
822 *search_number = number;
826 return CONTACTS_ERROR_NONE;
829 static inline int __ctsvc_contact_refresh_lookup_data(int contact_id, ctsvc_contact_s *contact)
832 int ret, len = 0, temp_len = 0;
833 char query[CTS_SQL_MAX_LEN] = {0};
835 snprintf(query, sizeof(query), "DELETE FROM %s WHERE contact_id = %d",
836 CTS_TABLE_NAME_LOOKUP, contact_id);
837 ret = ctsvc_query_exec(query);
838 if (CONTACTS_ERROR_NONE != ret) {
839 ERR("ctsvc_query_exec() Fail(%d)", ret);
843 snprintf(query, sizeof(query), "DELETE FROM %s WHERE contact_id = %d",
844 CTS_TABLE_PHONE_LOOKUP, contact_id);
845 ret = ctsvc_query_exec(query);
846 if (CONTACTS_ERROR_NONE != ret) {
847 ERR("ctsvc_query_exec() Fail(%d)", ret);
852 return CONTACTS_ERROR_NO_DATA;
855 contacts_list_h name_list = (contacts_list_h)contact->name;
856 ctsvc_name_s *name_record;
857 cts_stmt stmt = NULL;
858 char *temp_name = NULL;
859 contacts_list_first(name_list);
861 /* name record of contact should be one */
863 contacts_list_get_current_record_p(name_list, (contacts_record_h*)&name_record);
865 && (name_record->last
866 || name_record->first
867 || name_record->addition
868 || name_record->suffix)) {
869 char *normalized_name = NULL;
872 * Make reverse display name (Last name first)
873 * Default : Prefix Last, First Middle(addition), Suffix
874 * Korean, Chinese : Prefix LastMiddleFirstSuffix
875 * Japanese : Prefix Last Middle First Suffix
876 * reverse sort name does not include prefix
877 * But, if there is only prefix, reverse sort_name is prefix
879 /* make display name */
880 temp_len = SAFE_STRLEN(name_record->first)
881 + SAFE_STRLEN(name_record->addition)
882 + SAFE_STRLEN(name_record->last)
883 + SAFE_STRLEN(name_record->suffix)
885 int reverse_lang_type = ctsvc_contact_get_name_language(name_record);
886 temp_name = calloc(1, temp_len);
887 if (NULL == temp_name) {
888 ERR("calloc() Fail");
889 return CONTACTS_ERROR_OUT_OF_MEMORY;
892 if (reverse_lang_type == CTSVC_LANG_KOREAN ||
893 reverse_lang_type == CTSVC_LANG_CHINESE ||
894 reverse_lang_type == CTSVC_LANG_JAPANESE) {
895 if (name_record->last)
896 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->last);
897 if (name_record->addition)
898 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->addition);
899 if (name_record->first)
900 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->first);
901 if (name_record->suffix)
902 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->suffix);
904 if (name_record->last)
905 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->last);
906 if (name_record->first)
907 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->first);
908 if (name_record->addition)
909 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->addition);
910 if (name_record->suffix)
911 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->suffix);
914 ctsvc_normalize_str(temp_name, &normalized_name);
915 snprintf(query, sizeof(query), "INSERT INTO %s(data_id, contact_id, name, type) "
916 "VALUES(%d, %d, ?, %d)", CTS_TABLE_NAME_LOOKUP, name_record->id,
919 ret = ctsvc_query_prepare(query, &stmt);
921 ERR("ctsvc_query_prepare() Fail(%d)", ret);
923 free(normalized_name);
928 ctsvc_stmt_bind_text(stmt, 1, normalized_name);
930 ret = ctsvc_stmt_step(stmt);
933 free(normalized_name);
935 ctsvc_stmt_finalize(stmt);
937 if (CONTACTS_ERROR_NONE != ret) {
938 ERR("ctsvc_stmt_step() Fail(%d)", ret);
943 } while (CONTACTS_ERROR_NONE == contacts_list_next(name_list));
946 if (contact->numbers) {
947 contacts_list_h number_list = (contacts_list_h)contact->numbers;
948 cts_stmt stmt = NULL;
949 ctsvc_number_s *number_record;
950 contacts_list_first(number_list);
953 contacts_list_get_current_record_p(number_list, (contacts_record_h*)&number_record);
954 if (number_record && number_record->number) {
955 if (NULL == number_record->cleaned)
958 /* actually phone_lookup minmatch is not used */
959 snprintf(query, sizeof(query), "INSERT INTO %s(data_id, contact_id, number, min_match) "
960 "VALUES(%d, %d, ?, ?)", CTS_TABLE_PHONE_LOOKUP, number_record->id,
963 ret = ctsvc_query_prepare(query, &stmt);
964 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
966 if (*number_record->cleaned)
967 ctsvc_stmt_bind_text(stmt, 1, number_record->cleaned);
968 ret = ctsvc_stmt_step(stmt);
969 if (CONTACTS_ERROR_NONE != ret) {
970 ERR("ctsvc_stmt_step() Fail(%d)", ret);
971 ctsvc_stmt_finalize(stmt);
974 if (number_record->normalized && STRING_EQUAL != strcmp(number_record->cleaned, number_record->normalized)) {
975 ctsvc_stmt_reset(stmt);
976 if (*number_record->normalized)
977 ctsvc_stmt_bind_text(stmt, 1, number_record->normalized);
978 ret = ctsvc_stmt_step(stmt);
979 if (CONTACTS_ERROR_NONE != ret) {
980 ERR("ctsvc_stmt_step() Fail(%d)", ret);
981 ctsvc_stmt_finalize(stmt);
985 ctsvc_stmt_finalize(stmt);
987 } while (CONTACTS_ERROR_NONE == contacts_list_next(number_list));
990 if (contact->nicknames) {
991 contacts_list_h nickname_list = (contacts_list_h)contact->nicknames;
992 cts_stmt stmt = NULL;
993 ctsvc_nickname_s *nickname;
994 contacts_list_first(nickname_list);
996 contacts_list_get_current_record_p(nickname_list, (contacts_record_h*)&nickname);
997 if (nickname && nickname->nickname) {
998 char *normalized_nickname = NULL;
999 ctsvc_normalize_str(nickname->nickname, &normalized_nickname);
1000 snprintf(query, sizeof(query), "INSERT INTO %s(data_id, contact_id, name, type) "
1001 "VALUES(%d, %d, ?, %d)", CTS_TABLE_NAME_LOOKUP, nickname->id,
1004 ret = ctsvc_query_prepare(query, &stmt);
1006 ERR("ctsvc_query_prepare() Fail(%d)", ret);
1007 free(normalized_nickname);
1011 if (normalized_nickname && *normalized_nickname)
1012 ctsvc_stmt_bind_text(stmt, 1, normalized_nickname);
1014 ret = ctsvc_stmt_step(stmt);
1016 free(normalized_nickname);
1018 ctsvc_stmt_finalize(stmt);
1020 if (CONTACTS_ERROR_NONE != ret) {
1021 ERR("ctsvc_stmt_step() Fail(%d)", ret);
1025 } while (CONTACTS_ERROR_NONE == contacts_list_next(nickname_list));
1028 return CONTACTS_ERROR_NONE;
1031 static inline int __ctsvc_contact_update_search_data(int contact_id, bool need_refresh_lookup_data)
1034 cts_stmt stmt = NULL;
1035 char query[CTS_SQL_MAX_LEN] = {0};
1036 char *search_name = NULL;
1037 char *search_number = NULL;
1038 char *search_data = NULL;
1039 ctsvc_contact_s *contact = NULL;
1041 ret = ctsvc_begin_trans();
1042 RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
1044 ret = ctsvc_db_contact_get(contact_id, (contacts_record_h*)&contact);
1045 if (CONTACTS_ERROR_NO_DATA == ret) {
1047 snprintf(query, sizeof(query), "DELETE FROM %s WHERE contact_id = %d",
1048 CTS_TABLE_SEARCH_INDEX, contact_id);
1049 r = ctsvc_query_exec(query);
1050 if (CONTACTS_ERROR_NONE != r) {
1051 ERR("ctsvc_query_exec() Fail(%d)", r);
1052 ctsvc_end_trans(false);
1055 ctsvc_end_trans(false);
1057 } else if (CONTACTS_ERROR_NONE != ret) {
1058 ERR("ctsvc_db_contact_get() Fail(%d)", ret);
1059 ctsvc_end_trans(false);
1063 ret = ctsvc_contact_make_search_name(contact, &search_name);
1064 if (CONTACTS_ERROR_NONE != ret) {
1065 ERR("ctsvc_contact_make_search_name() Fail(%d)", ret);
1066 contacts_record_destroy((contacts_record_h)contact, true);
1067 ctsvc_end_trans(false);
1071 ret = __ctsvc_contact_make_search_data(contact, &search_number, &search_data);
1072 if (CONTACTS_ERROR_NONE != ret) {
1073 ERR("__ctsvc_contact_make_search_data() Fail(%d)", ret);
1074 contacts_record_destroy((contacts_record_h)contact, true);
1075 ctsvc_end_trans(false);
1080 snprintf(query, sizeof(query),
1081 "UPDATE %s SET name=?, number=?, data=? "
1082 "WHERE contact_id = %d",
1083 CTS_TABLE_SEARCH_INDEX, contact_id);
1085 ret = ctsvc_query_prepare(query, &stmt);
1087 ERR("ctsvc_query_prepare() Fail(%d)", ret);
1088 contacts_record_destroy((contacts_record_h)contact, true);
1089 ctsvc_end_trans(false);
1091 free(search_number);
1097 ctsvc_stmt_bind_text(stmt, 1, search_name);
1099 ctsvc_stmt_bind_text(stmt, 2, search_number);
1101 ctsvc_stmt_bind_text(stmt, 3, search_data);
1103 ret = ctsvc_stmt_step(stmt);
1106 free(search_number);
1109 if (CONTACTS_ERROR_NONE != ret) {
1110 ERR("ctsvc_stmt_step() Fail(%d)", ret);
1111 contacts_record_destroy((contacts_record_h)contact, true);
1112 ctsvc_stmt_finalize(stmt);
1113 ctsvc_end_trans(false);
1116 ctsvc_stmt_finalize(stmt);
1118 if (need_refresh_lookup_data) {
1119 /* update phone_lookup, name_lookup */
1120 ret = __ctsvc_contact_refresh_lookup_data(contact_id, contact);
1121 if (CONTACTS_ERROR_NONE != ret) {
1122 ERR("__ctsvc_contact_refresh_lookup_data() Fail(%d)", ret);
1123 contacts_record_destroy((contacts_record_h)contact, true);
1124 ctsvc_end_trans(false);
1129 contacts_record_destroy((contacts_record_h)contact, true);
1131 ret = ctsvc_end_trans(true);
1132 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_end_trans() Fail(%d)", ret);
1134 return CONTACTS_ERROR_NONE;
1137 static bool __ctsvc_list_check_dirty(ctsvc_list_s *list)
1140 if (list->deleted_records)
1144 for (c = list->records; c; c = c->next) {
1145 ctsvc_record_s *s_record = c->data;
1147 unsigned int property_info_count = 0;
1148 const property_info_s *property_info = ctsvc_view_get_all_property_infos(s_record->view_uri, &property_info_count);
1149 for (i = 0; i < property_info_count; i++) {
1150 bool ret = ctsvc_record_check_property_flag(s_record,
1151 property_info[i].property_id, CTSVC_PROPERTY_FLAG_DIRTY);
1160 static bool __ctsvc_get_need_refresh_lookup_data(ctsvc_contact_s *contact)
1162 if (__ctsvc_list_check_dirty(contact->name))
1164 if (__ctsvc_list_check_dirty(contact->numbers))
1166 if (__ctsvc_list_check_dirty(contact->nicknames))
1171 static int __ctsvc_db_contact_update_record(contacts_record_h record)
1174 int rel_changed = 0;
1177 char query[CTS_SQL_MAX_LEN] = {0};
1178 GSList *bind_text = NULL;
1179 GSList *cursor = NULL;
1180 ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
1181 bool is_invalid = false;
1182 int current_version = 0;
1184 ret = ctsvc_begin_trans();
1185 RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
1187 snprintf(query, sizeof(query),
1188 "SELECT changed_ver FROM "CTS_TABLE_CONTACTS" "
1189 "WHERE contact_id = %d AND deleted = 0", contact->id);
1190 ret = ctsvc_query_get_first_int_result(query, ¤t_version);
1191 if (CONTACTS_ERROR_NONE != ret) {
1192 ERR("The index(%d) is Invalid. %d Record(s) is(are) found", contact->id, ret);
1193 ctsvc_end_trans(false);
1197 if (false == ctsvc_have_ab_write_permission(contact->addressbook_id, false)) {
1198 ERR("No permission in this addresbook_id(%d)", contact->addressbook_id);
1199 ctsvc_end_trans(false);
1200 return CONTACTS_ERROR_PERMISSION_DENIED;
1203 if (current_version != contact->changed_ver)
1205 __ctsvc_contact_check_default_data(contact);
1207 /* check lookup data is dirty */
1208 bool need_update_lookup = __ctsvc_get_need_refresh_lookup_data(contact);
1211 ret = __ctsvc_contact_update_data(contact);
1212 if (CONTACTS_ERROR_NONE != ret) {
1213 ERR("__ctsvc_contact_update_data() Fail(%d)", ret);
1214 ctsvc_end_trans(false);
1218 if (contact->grouprelations) {
1219 rel_changed = __ctsvc_contact_update_grouprel(contact->id, (contacts_list_h)contact->grouprelations);
1220 if (rel_changed < CONTACTS_ERROR_NONE) {
1221 ERR("cts_update_contact_grouprel() Fail(%d)", rel_changed);
1222 ctsvc_end_trans(false);
1228 if (contact->images) {
1229 int ret = CONTACTS_ERROR_NONE;
1231 ctsvc_image_s *image;
1233 contacts_list_get_count((contacts_list_h)contact->images, &count);
1235 contacts_list_first((contacts_list_h)contact->images);
1237 ret = contacts_list_get_current_record_p((contacts_list_h)contact->images, (contacts_record_h*)&image);
1238 if (CONTACTS_ERROR_NONE != ret) {
1239 ERR("contacts_list_get_current_record_p() Fail(%d)", ret);
1240 ctsvc_end_trans(false);
1241 return CONTACTS_ERROR_DB;
1244 if (image->is_default)
1246 } while (CONTACTS_ERROR_NONE == contacts_list_next((contacts_list_h)contact->images));
1248 if ((NULL == contact->image_thumbnail_path && image->path) ||
1249 (contact->image_thumbnail_path && NULL == image->path) ||
1250 (contact->image_thumbnail_path && image->path && (STRING_EQUAL != strcmp(contact->image_thumbnail_path, image->path)))) {
1251 ctsvc_record_set_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
1253 if (ctsvc_contact_check_image_location(image->path))
1254 contact->image_thumbnail_path = SAFE_STRDUP(image->path + strlen(CTSVC_CONTACT_IMG_FULL_LOCATION) + 1);
1256 contact->image_thumbnail_path = SAFE_STRDUP(image->path);
1258 } else if (contact->image_thumbnail_path) {
1259 free(contact->image_thumbnail_path);
1260 contact->image_thumbnail_path = NULL;
1261 bool is_changed = ctsvc_record_check_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
1262 if ((false == is_changed && false == is_invalid) || (is_changed && false == is_invalid)) {
1263 ctsvc_record_set_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
1265 if (((ctsvc_record_s*)record)->properties_flags) {
1266 int index = _contacts_contact.image_thumbnail_path & 0x000000FF;
1267 ((ctsvc_record_s*)record)->properties_flags[index] = 0;
1274 ctsvc_contact_s *temp_contact;
1275 contacts_record_create(_contacts_contact._uri, (contacts_record_h*)&temp_contact);
1276 ret = __ctsvc_db_get_data(contact->id, temp_contact);
1277 ctsvc_contact_make_display_name(temp_contact);
1279 FREEandSTRDUP(contact->display_name, temp_contact->display_name);
1280 FREEandSTRDUP(contact->reverse_display_name, temp_contact->reverse_display_name);
1281 FREEandSTRDUP(contact->sort_name, temp_contact->sort_name);
1282 FREEandSTRDUP(contact->reverse_sort_name, temp_contact->reverse_sort_name);
1283 FREEandSTRDUP(contact->sortkey, temp_contact->sortkey);
1284 FREEandSTRDUP(contact->reverse_sortkey, temp_contact->reverse_sortkey);
1286 contact->display_name_language = temp_contact->display_name_language;
1287 contact->reverse_display_name_language = temp_contact->reverse_display_name_language;
1288 contact->display_source_type = temp_contact->display_source_type;
1290 if (ctsvc_record_check_property_flag((ctsvc_record_s*)temp_contact, _contacts_contact.display_name, CTSVC_PROPERTY_FLAG_DIRTY))
1291 ctsvc_record_set_property_flag((ctsvc_record_s*)contact, _contacts_contact.display_name, CTSVC_PROPERTY_FLAG_DIRTY);
1293 contacts_record_destroy((contacts_record_h)temp_contact, true);
1295 ctsvc_contact_make_display_name(contact);
1299 char query[CTS_SQL_MAX_LEN] = {0};
1300 char query_set[CTS_SQL_MIN_LEN] = {0, };
1301 cts_stmt stmt = NULL;
1303 version = ctsvc_get_next_ver();
1305 ret = ctsvc_db_create_set_query(record, &set, &bind_text);
1306 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_db_create_set_query() Fail(%d)", ret);
1309 len = snprintf(query_set, sizeof(query_set), "%s, ", set);
1310 len += snprintf(query_set+len, sizeof(query_set)-len, " changed_ver=%d, changed_time=%d, has_phonenumber=%d, has_email=%d",
1311 version, (int)time(NULL), contact->has_phonenumber, contact->has_email);
1312 if (ctsvc_record_check_property_flag((ctsvc_record_s*)contact, _contacts_contact.display_name, CTSVC_PROPERTY_FLAG_DIRTY)) {
1313 len += snprintf(query_set+len, sizeof(query_set)-len,
1314 ", display_name=?, reverse_display_name=?, display_name_source=%d, "
1315 "display_name_language=%d, reverse_display_name_language=%d, "
1316 "sort_name=?, reverse_sort_name=?, sortkey=?, reverse_sortkey=?",
1317 contact->display_source_type, contact->display_name_language, contact->reverse_display_name_language);
1318 bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->display_name)));
1319 bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->reverse_display_name)));
1320 bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->sort_name)));
1321 bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->reverse_sort_name)));
1322 bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->sortkey)));
1323 bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->reverse_sortkey)));
1326 if (ctsvc_record_check_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY))
1327 len += snprintf(query_set+len, sizeof(query_set)-len, ", image_changed_ver=%d", version);
1329 snprintf(query, sizeof(query), "UPDATE %s SET %s WHERE contact_id = %d", CTS_TABLE_CONTACTS, query_set, contact->id);
1331 ret = ctsvc_query_prepare(query, &stmt);
1333 ERR("ctsvc_query_prepare() Fail(%d)", ret);
1339 for (cursor = bind_text, i = 1; cursor; cursor = cursor->next, i++) {
1340 const char *text = cursor->data;
1342 ctsvc_stmt_bind_text(stmt, i, text);
1345 ret = ctsvc_stmt_step(stmt);
1346 if (CONTACTS_ERROR_NONE != ret) {
1347 ERR("ctsvc_stmt_step() Fail(%d)", ret);
1348 ctsvc_stmt_finalize(stmt);
1351 ctsvc_stmt_finalize(stmt);
1354 if (CONTACTS_ERROR_NONE != ret) {
1355 ctsvc_end_trans(false);
1356 CTSVC_RECORD_RESET_PROPERTY_FLAGS((ctsvc_record_s*)record);
1360 for (cursor = bind_text; cursor; cursor = cursor->next) {
1362 cursor->data = NULL;
1364 g_slist_free(bind_text);
1369 ctsvc_set_contact_noti();
1370 if (0 < rel_changed)
1371 ctsvc_set_group_rel_noti();
1373 __ctsvc_contact_update_search_data(contact->id, need_update_lookup);
1374 ctsvc_db_update_person((contacts_record_h)contact);
1376 CTSVC_RECORD_RESET_PROPERTY_FLAGS((ctsvc_record_s*)record);
1380 for (cursor = bind_text; cursor; cursor = cursor->next) {
1382 cursor->data = NULL;
1384 g_slist_free(bind_text);
1387 ret = ctsvc_end_trans(true);
1388 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_end_trans() Fail(%d)", ret);
1390 return CONTACTS_ERROR_NONE;
1393 static int __ctsvc_db_contact_get_all_records(int offset, int limit, contacts_list_h *out_list)
1399 char query[CTS_SQL_MAX_LEN] = {0};
1400 contacts_list_h list;
1402 len = snprintf(query, sizeof(query),
1403 "SELECT contact_id FROM "CTS_TABLE_CONTACTS" WHERE deleted = 0");
1406 len += snprintf(query+len, sizeof(query)-len, " LIMIT %d", limit);
1408 len += snprintf(query+len, sizeof(query)-len, " OFFSET %d", offset);
1411 ret = ctsvc_query_prepare(query, &stmt);
1412 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
1414 contacts_list_create(&list);
1415 while ((ret = ctsvc_stmt_step(stmt))) {
1416 contacts_record_h record;
1418 ERR("ctsvc_stmt_step() Fail(%d)", ret);
1419 ctsvc_stmt_finalize(stmt);
1420 contacts_list_destroy(list, true);
1423 contact_id = ctsvc_stmt_get_int(stmt, 0);
1424 ret = ctsvc_db_contact_get(contact_id, &record);
1425 if (CONTACTS_ERROR_NONE != ret) {
1426 ERR("ctsvc_db_contact_get() Fail(%d)", ret);
1427 ctsvc_stmt_finalize(stmt);
1428 contacts_list_destroy(list, true);
1431 ctsvc_list_prepend(list, record);
1433 ctsvc_stmt_finalize(stmt);
1434 ctsvc_list_reverse(list);
1436 *out_list = (contacts_list_h)list;
1437 return CONTACTS_ERROR_NONE;
1440 static int __ctsvc_db_contact_get_changed_ver(int contact_id, ctsvc_contact_s *contact)
1444 char query[CTS_SQL_MAX_LEN] = {0};
1446 snprintf(query, sizeof(query),
1447 "SELECT changed_ver FROM "CTS_TABLE_CONTACTS
1448 " WHERE contact_id = %d AND deleted = 0", contact_id);
1449 ret = ctsvc_query_get_first_int_result(query, &version);
1450 if (CONTACTS_ERROR_NONE == ret)
1451 contact->changed_ver = version;
1455 static int __ctsvc_db_contact_get_records_with_query(contacts_query_h query, int offset, int limit, contacts_list_h *out_list)
1460 ctsvc_query_s *s_query;
1462 contacts_list_h list;
1463 ctsvc_contact_s *contact;
1464 char full_path[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
1465 bool had_contact_id = false;
1468 RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
1469 s_query = (ctsvc_query_s*)query;
1471 if (s_query->projection) {
1472 for (i = 0; i < s_query->projection_count; i++) {
1473 if (s_query->projection[i] == CTSVC_PROPERTY_CONTACT_ID) {
1474 had_contact_id = true;
1479 s_query->projection_count = 0;
1480 had_contact_id = true;
1483 if (false == had_contact_id) {
1484 s_query->projection = realloc(s_query->projection, s_query->projection_count+1);
1485 if (NULL == s_query->projection) {
1486 ERR("realloc() Fail");
1487 return CONTACTS_ERROR_OUT_OF_MEMORY;
1490 s_query->projection[s_query->projection_count] = CTSVC_PROPERTY_CONTACT_ID;
1491 s_query->projection_count++;
1494 ret = ctsvc_db_make_get_records_query_stmt(s_query, offset, limit, &stmt);
1495 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_db_make_get_records_query_stmt fail(%d)", ret);
1497 contacts_list_create(&list);
1498 while ((ret = ctsvc_stmt_step(stmt))) {
1499 contacts_record_h record;
1501 ERR("ctsvc_stmt_step() Fail(%d)", ret);
1502 ctsvc_stmt_finalize(stmt);
1503 contacts_list_destroy(list, true);
1507 contacts_record_create(_contacts_contact._uri, &record);
1508 contact = (ctsvc_contact_s*)record;
1509 if (0 == s_query->projection_count) {
1510 field_count = s_query->property_count;
1512 field_count = s_query->projection_count;
1513 ret = ctsvc_record_set_projection_flags(record, s_query->projection,
1514 s_query->projection_count, s_query->property_count);
1516 if (CONTACTS_ERROR_NONE != ret)
1517 ASSERT_NOT_REACHED("To set projection is failed.\n");
1520 for (i = 0; i < field_count; i++) {
1523 if (0 == s_query->projection_count)
1524 property_id = s_query->properties[i].property_id;
1526 property_id = s_query->projection[i];
1528 switch (property_id) {
1529 case CTSVC_PROPERTY_CONTACT_ID:
1530 contact_id = ctsvc_stmt_get_int(stmt, i);
1532 contact->id = contact_id;
1534 case CTSVC_PROPERTY_CONTACT_DISPLAY_NAME:
1535 temp = ctsvc_stmt_get_text(stmt, i);
1536 free(contact->display_name);
1537 contact->display_name = SAFE_STRDUP(temp);
1539 case CTSVC_PROPERTY_CONTACT_DISPLAY_SOURCE_DATA_ID:
1540 contact->display_source_type = ctsvc_stmt_get_int(stmt, i);
1542 case CTSVC_PROPERTY_CONTACT_ADDRESSBOOK_ID:
1543 contact->addressbook_id = ctsvc_stmt_get_int(stmt, i);
1545 case CTSVC_PROPERTY_CONTACT_RINGTONE:
1546 temp = ctsvc_stmt_get_text(stmt, i);
1547 free(contact->ringtone_path);
1548 contact->ringtone_path = SAFE_STRDUP(temp);
1550 case CTSVC_PROPERTY_CONTACT_IMAGE_THUMBNAIL:
1551 temp = ctsvc_stmt_get_text(stmt, i);
1552 if (temp && *temp) {
1553 snprintf(full_path, sizeof(full_path), "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, temp);
1554 free(contact->image_thumbnail_path);
1555 contact->image_thumbnail_path = strdup(full_path);
1558 case CTSVC_PROPERTY_CONTACT_IS_FAVORITE:
1559 contact->is_favorite = ctsvc_stmt_get_int(stmt, i);
1561 case CTSVC_PROPERTY_CONTACT_HAS_PHONENUMBER:
1562 contact->has_phonenumber = ctsvc_stmt_get_int(stmt, i);
1564 case CTSVC_PROPERTY_CONTACT_HAS_EMAIL:
1565 contact->has_email = ctsvc_stmt_get_int(stmt, i);
1567 case CTSVC_PROPERTY_CONTACT_PERSON_ID:
1568 contact->person_id = ctsvc_stmt_get_int(stmt, i);
1570 case CTSVC_PROPERTY_CONTACT_UID:
1571 temp = ctsvc_stmt_get_text(stmt, i);
1573 contact->uid = SAFE_STRDUP(temp);
1575 case CTSVC_PROPERTY_CONTACT_VIBRATION:
1576 temp = ctsvc_stmt_get_text(stmt, i);
1577 free(contact->vibration);
1578 contact->vibration = SAFE_STRDUP(temp);
1580 case CTSVC_PROPERTY_CONTACT_MESSAGE_ALERT:
1581 temp = ctsvc_stmt_get_text(stmt, i);
1582 free(contact->message_alert);
1583 contact->message_alert = SAFE_STRDUP(temp);
1585 case CTSVC_PROPERTY_CONTACT_CHANGED_TIME:
1586 contact->changed_time = ctsvc_stmt_get_int(stmt, i);
1588 case CTSVC_PROPERTY_CONTACT_LINK_MODE:
1589 contact->link_mode = ctsvc_stmt_get_int(stmt, i);
1595 /* get changed_ver */
1596 ret = __ctsvc_db_contact_get_changed_ver(contact_id, contact);
1597 if (CONTACTS_ERROR_NONE != ret) {
1598 ERR("__ctsvc_db_contact_get_changed_ver Fail(%d)", ret);
1599 ctsvc_stmt_finalize(stmt);
1600 contacts_list_destroy(list, true);
1604 ret = __ctsvc_db_get_data(contact_id, contact);
1605 if (CONTACTS_ERROR_NONE != ret && CONTACTS_ERROR_NO_DATA != ret) {
1606 ERR("ctsvc_get_data_info Fail(%d)", ret);
1607 ctsvc_stmt_finalize(stmt);
1608 contacts_list_destroy(list, true);
1612 ret = __ctsvc_get_contact_grouprel(contact_id, contact);
1613 if (CONTACTS_ERROR_NONE != ret) {
1614 ERR("ctsvc_get_group_relations Fail(%d)", ret);
1615 ctsvc_stmt_finalize(stmt);
1616 contacts_list_destroy(list, true);
1620 ctsvc_list_prepend(list, record);
1622 ctsvc_stmt_finalize(stmt);
1623 ctsvc_list_reverse(list);
1625 *out_list = (contacts_list_h)list;
1627 return CONTACTS_ERROR_NONE;
1631 static int __ctsvc_contact_insert_data(ctsvc_contact_s *contact)
1635 /* Insert the name */
1636 if (contact->name) {
1637 ret = ctsvc_contact_insert_data_name((contacts_list_h)contact->name, contact->id, false);
1638 if (CONTACTS_ERROR_NONE != ret) {
1639 ERR("ctsvc_contact_insert_data_name() Fail(%d)", ret);
1644 /* Insert the company */
1645 if (contact->company) {
1646 ret = ctsvc_contact_insert_data_company((contacts_list_h)contact->company, contact->id, false);
1647 if (CONTACTS_ERROR_NONE != ret) {
1648 ERR("ctsvc_insert_contact_data_company() Fail(%d)", ret);
1653 /* Insert the events */
1654 if (contact->events) {
1655 ret = ctsvc_contact_insert_data_event((contacts_list_h)contact->events, contact->id, false);
1656 if (CONTACTS_ERROR_NONE != ret) {
1657 ERR("ctsvc_insert_contact_data_event() Fail(%d)", ret);
1662 /* Insert the messengers */
1663 if (contact->messengers) {
1664 ret = ctsvc_contact_insert_data_messenger((contacts_list_h)contact->messengers, contact->id, false);
1665 if (CONTACTS_ERROR_NONE != ret) {
1666 ERR("ctsvc_insert_contact_data_messenger() Fail(%d)", ret);
1671 /* Insert the postals */
1672 if (contact->postal_addrs) {
1673 ret = ctsvc_contact_insert_data_address((contacts_list_h)contact->postal_addrs, contact->id, false);
1674 if (CONTACTS_ERROR_NONE != ret) {
1675 ERR("ctsvc_insert_contact_data_postal() Fail(%d)", ret);
1680 /* Insert the Web addrs */
1681 if (contact->urls) {
1682 ret = ctsvc_contact_insert_data_url((contacts_list_h)contact->urls, contact->id, false);
1683 if (CONTACTS_ERROR_NONE != ret) {
1684 ERR("ctsvc_insert_contact_data_web() Fail(%d)", ret);
1689 /* Insert the Nick names */
1690 if (contact->nicknames) {
1691 ret = ctsvc_contact_insert_data_nickname((contacts_list_h)contact->nicknames, contact->id, false);
1692 if (CONTACTS_ERROR_NONE != ret) {
1693 ERR("ctsvc_insert_contact_data_nickname() Fail(%d)", ret);
1698 /* Insert the numbers */
1699 if (contact->numbers) {
1700 ret = ctsvc_contact_insert_data_number((contacts_list_h)contact->numbers, contact->id, false);
1701 if (ret < CONTACTS_ERROR_NONE) {
1702 ERR("ctsvc_contact_insert_data_number() Fail(%d)", ret);
1707 /* Insert the emails */
1708 if (contact->emails) {
1709 ret = ctsvc_contact_insert_data_email((contacts_list_h)contact->emails, contact->id, false);
1710 if (ret < CONTACTS_ERROR_NONE) {
1711 ERR("ctsvc_insert_contact_data_email() Fail(%d)", ret);
1716 /* Insert the profile values */
1717 if (contact->profiles) {
1718 ret = ctsvc_contact_insert_data_profile((contacts_list_h)contact->profiles, contact->id, false);
1719 if (CONTACTS_ERROR_NONE != ret) {
1720 ERR("ctsvc_insert_contact_data_profile() Fail(%d)", ret);
1725 /* Insert the relationship values */
1726 if (contact->relationships) {
1727 ret = ctsvc_contact_insert_data_relationship((contacts_list_h)contact->relationships, contact->id, false);
1728 if (CONTACTS_ERROR_NONE != ret) {
1729 ERR("ctsvc_contact_insert_data_relationship() Fail(%d)", ret);
1734 /* Insert the image values */
1735 if (contact->images) {
1736 ret = ctsvc_contact_insert_data_image((contacts_list_h)contact->images, contact->id, false);
1737 if (CONTACTS_ERROR_NONE != ret) {
1738 ERR("ctsvc_contact_insert_data_image() Fail(%d)", ret);
1743 /* Insert the note values */
1744 if (contact->note) {
1745 ret = ctsvc_contact_insert_data_note((contacts_list_h)contact->note, contact->id, false);
1746 if (CONTACTS_ERROR_NONE != ret) {
1747 ERR("ctsvc_contact_insert_data_note() Fail(%d)", ret);
1752 /* Insert the extensions values */
1753 if (contact->extensions) {
1754 ret = ctsvc_contact_insert_data_extension((contacts_list_h)contact->extensions, contact->id, false);
1755 if (CONTACTS_ERROR_NONE != ret) {
1756 ERR("ctsvc_contact_insert_data_extension() Fail(%d)", ret);
1761 /* Insert the sips */
1762 if (contact->sips) {
1763 ret = ctsvc_contact_insert_data_sip((contacts_list_h)contact->sips, contact->id, false);
1764 if (CONTACTS_ERROR_NONE != ret) {
1765 ERR("ctsvc_insert_contact_data_sip() Fail(%d)", ret);
1770 return CONTACTS_ERROR_NONE;
1773 static inline int __ctsvc_contact_insert_search_data(int contact_id, bool need_insert_lookup_data)
1776 cts_stmt stmt = NULL;
1777 char query[CTS_SQL_MAX_LEN] = {0};
1778 char *search_name = NULL;
1779 char *search_number = NULL;
1780 char *search_data = NULL;
1781 ctsvc_contact_s *contact = NULL;
1783 ret = ctsvc_begin_trans();
1784 RETVM_IF(ret, ret, "contacts_begin_trans() Fail(%d)", ret);
1786 ret = ctsvc_db_contact_get(contact_id, (contacts_record_h*)&contact);
1787 if (CONTACTS_ERROR_NONE != ret) {
1788 ERR("ctsvc_db_contact_get() Fail(%d)", ret);
1789 ctsvc_end_trans(false);
1793 ret = ctsvc_contact_make_search_name(contact, &search_name);
1794 if (CONTACTS_ERROR_NONE != ret) {
1795 ERR("ctsvc_contact_make_search_name() Fail(%d)", ret);
1796 contacts_record_destroy((contacts_record_h)contact, true);
1797 ctsvc_end_trans(false);
1801 ret = __ctsvc_contact_make_search_data(contact, &search_number, &search_data);
1802 if (CONTACTS_ERROR_NONE != ret) {
1803 ERR("__ctsvc_contact_make_search_data() Fail(%d)", ret);
1804 contacts_record_destroy((contacts_record_h)contact, true);
1805 ctsvc_end_trans(false);
1810 snprintf(query, sizeof(query),
1811 "INSERT INTO %s(contact_id, name, number, data) "
1812 "VALUES(%d, ?, ?, ?)",
1813 CTS_TABLE_SEARCH_INDEX, contact_id);
1815 ret = ctsvc_query_prepare(query, &stmt);
1817 ERR("ctsvc_query_prepare() Fail(%d)", ret);
1818 contacts_record_destroy((contacts_record_h)contact, true);
1819 ctsvc_end_trans(false);
1821 free(search_number);
1827 ctsvc_stmt_bind_text(stmt, 1, search_name);
1829 ctsvc_stmt_bind_text(stmt, 2, search_number);
1831 ctsvc_stmt_bind_text(stmt, 3, search_data);
1833 ret = ctsvc_stmt_step(stmt);
1836 free(search_number);
1839 if (CONTACTS_ERROR_NONE != ret) {
1840 ERR("ctsvc_stmt_step() Fail(%d)", ret);
1841 contacts_record_destroy((contacts_record_h)contact, true);
1842 ctsvc_stmt_finalize(stmt);
1843 ctsvc_end_trans(false);
1846 ctsvc_stmt_finalize(stmt);
1848 /* update phone_lookup, name_lookup */
1849 if (need_insert_lookup_data) {
1850 ret = __ctsvc_contact_refresh_lookup_data(contact_id, contact);
1851 if (CONTACTS_ERROR_NONE != ret) {
1852 ERR("__ctsvc_contact_refresh_lookup_data() Fail(%d)", ret);
1853 contacts_record_destroy((contacts_record_h)contact, true);
1854 ctsvc_end_trans(false);
1859 contacts_record_destroy((contacts_record_h)contact, true);
1861 ret = ctsvc_end_trans(true);
1862 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_end_trans() Fail(%d)", ret);
1864 return CONTACTS_ERROR_NONE;
1867 static inline int __ctsvc_contact_insert_grouprel(int contact_id, contacts_list_h group_list)
1870 ctsvc_group_relation_s *grouprel;
1871 int rel_changed = 0;
1875 RETV_IF(NULL == group_list, CONTACTS_ERROR_INVALID_PARAMETER);
1876 ret = contacts_list_get_count(group_list, &count);
1878 return CONTACTS_ERROR_NONE;
1880 contacts_list_first(group_list);
1882 contacts_list_get_current_record_p(group_list, (contacts_record_h*)&grouprel);
1883 if (NULL == grouprel)
1886 RETVM_IF(grouprel->group_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER, "group_id(%d) invalid", grouprel->group_id);
1887 if (grouprel->group_id) {
1888 ret = ctsvc_group_add_contact_in_transaction(grouprel->group_id, contact_id);
1889 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_db_group_set_relation() Fail(%d)", ret);
1893 } while (CONTACTS_ERROR_NONE == contacts_list_next(group_list));
1898 return CONTACTS_ERROR_NONE;
1901 static inline int __ctsvc_find_person_to_link_with_number(const char *number,
1902 int addressbook_id, int *person_id)
1905 cts_stmt stmt = NULL;
1906 char query[CTS_SQL_MIN_LEN] = {0};
1907 int number_len = SAFE_STRLEN(number);
1908 char clean_num[number_len+1];
1910 ret = ctsvc_clean_number(number, clean_num, sizeof(clean_num), true);
1912 char normal_num[sizeof(clean_num)+20];
1913 ret = ctsvc_normalize_number(clean_num, normal_num, sizeof(normal_num), true);
1914 char minmatch[sizeof(normal_num)+1];
1916 ret = ctsvc_get_minmatch_number(normal_num, minmatch, sizeof(minmatch), ctsvc_get_phonenumber_min_match_digit());
1918 snprintf(query, sizeof(query),
1919 "SELECT C.person_id FROM "CTS_TABLE_CONTACTS" C, "CTS_TABLE_DATA" D "
1920 "ON C.contact_id=D.contact_id AND D.datatype=%d AND C.deleted = 0 "
1921 "AND C.addressbook_id <> %d AND D.is_my_profile = 0 "
1922 "WHERE D.data4 = ?",
1923 /* Below condition takes long time, so omit the condition */
1924 /* AND _NUMBER_COMPARE_(D.data5, ?, NULL, NULL) */
1925 CTSVC_DATA_NUMBER, addressbook_id);
1927 ret = ctsvc_query_prepare(query, &stmt);
1928 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare fail(%d)", ret);
1929 ctsvc_stmt_bind_text(stmt, 1, minmatch);
1930 /* ctsvc_stmt_bind_text(stmt, 2, normal_num); */
1931 ret = ctsvc_stmt_step(stmt);
1933 *person_id = ctsvc_stmt_get_int(stmt, 0);
1934 ret = CONTACTS_ERROR_NONE;
1935 } else if (CONTACTS_ERROR_NONE == ret) {
1936 ret = CONTACTS_ERROR_NO_DATA;
1938 ctsvc_stmt_finalize(stmt);
1939 DBG("result ret(%d) person_id(%d)", ret, *person_id);
1943 return CONTACTS_ERROR_INVALID_PARAMETER;
1946 static inline int __ctsvc_find_person_to_link_with_email(const char *email_addr, int addressbook_id, int *person_id)
1949 cts_stmt stmt = NULL;
1950 char query[CTS_SQL_MIN_LEN] = {0};
1952 snprintf(query, sizeof(query),
1953 "SELECT C.person_id FROM "CTS_TABLE_CONTACTS" C, "CTS_TABLE_DATA" D "
1954 "ON C.contact_id=D.contact_id AND D.datatype=%d AND C.deleted = 0 AND D.is_my_profile = 0 "
1955 "AND C.addressbook_id <> %d "
1956 "WHERE D.data3 = ?",
1957 CTSVC_DATA_EMAIL, addressbook_id);
1959 ret = ctsvc_query_prepare(query, &stmt);
1960 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare fail(%d)", ret);
1962 ctsvc_stmt_bind_text(stmt, 1, email_addr);
1963 ret = ctsvc_stmt_step(stmt);
1965 *person_id = ctsvc_stmt_get_int(stmt, 0);
1966 ret = CONTACTS_ERROR_NONE;
1967 } else if (CONTACTS_ERROR_NONE == ret) {
1968 ret = CONTACTS_ERROR_NO_DATA;
1971 ctsvc_stmt_finalize(stmt);
1972 DBG("result ret(%d) person_id(%d)", ret, *person_id);
1977 static inline int __ctsvc_find_person_to_link(contacts_record_h record, int addressbook_id, int *person_id)
1980 ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
1981 ctsvc_number_s *number_data;
1982 ctsvc_email_s *email_data;
1985 for (cursor = contact->numbers->records; cursor; cursor = cursor->next) {
1986 number_data = cursor->data;
1987 if (number_data && number_data->number && number_data->number[0]) {
1988 ret = __ctsvc_find_person_to_link_with_number(number_data->number, addressbook_id, person_id);
1990 if (ret == CONTACTS_ERROR_NONE && 0 < *person_id)
1995 for (cursor = contact->emails->records; cursor; cursor = cursor->next) {
1996 email_data = cursor->data;
1997 if (email_data && email_data->email_addr && email_data->email_addr[0]) {
1998 ret = __ctsvc_find_person_to_link_with_email(email_data->email_addr, addressbook_id, person_id);
2000 if (ret == CONTACTS_ERROR_NONE && 0 < *person_id)
2005 return CONTACTS_ERROR_NO_DATA;
2008 static int __ctsvc_db_contact_insert_record(contacts_record_h record, int *id)
2011 int ret, person_id = 0;
2012 char query[CTS_SQL_MAX_LEN] = {0};
2013 bool auto_link_enabled = true;
2014 bool auto_linked = false;
2016 ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
2017 int rel_changed = 0;
2018 cts_stmt stmt = NULL;
2020 /* These check should be done in client side */
2021 RETV_IF(NULL == contact, CONTACTS_ERROR_INVALID_PARAMETER);
2022 RETVM_IF(contact->addressbook_id < 0, CONTACTS_ERROR_INVALID_PARAMETER,
2023 "addressbook_id(%d) is mandatory field to insert contact record ", contact->addressbook_id);
2024 RETVM_IF(0 < contact->id, CONTACTS_ERROR_INVALID_PARAMETER,
2025 "id(%d), This record is already inserted", contact->id);
2027 if (contact->link_mode == CONTACTS_CONTACT_LINK_MODE_IGNORE_ONCE)
2028 auto_link_enabled = false;
2030 ret = ctsvc_begin_trans();
2031 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_begin_trans() Fail(%d)", ret);
2033 if (false == ctsvc_have_ab_write_permission(contact->addressbook_id, false)) {
2034 ERR("No permission in this addresbook_id(%d)", contact->addressbook_id);
2035 ctsvc_end_trans(false);
2036 return CONTACTS_ERROR_PERMISSION_DENIED;
2039 ret = ctsvc_db_get_next_id(CTS_TABLE_CONTACTS);
2040 if (ret < CONTACTS_ERROR_NONE) {
2041 ERR("ctsvc_db_get_next_id() Fail(%d)", ret);
2042 ctsvc_end_trans(false);
2049 ctsvc_contact_make_display_name(contact);
2050 __ctsvc_contact_check_default_data(contact);
2052 /* check lookup data is dirty */
2053 bool need_insert_lookup = __ctsvc_get_need_refresh_lookup_data(contact);
2056 ret = __ctsvc_contact_insert_data(contact);
2057 if (CONTACTS_ERROR_NONE != ret) {
2058 ERR("cts_insert_contact_data() Fail(%d)", ret);
2059 ctsvc_end_trans(false);
2064 free(contact->image_thumbnail_path);
2065 contact->image_thumbnail_path = NULL;
2066 if (contact->images) {
2068 ctsvc_image_s *image;
2070 contacts_list_get_count((contacts_list_h)contact->images, &count);
2072 contacts_list_first((contacts_list_h)contact->images);
2074 ret = contacts_list_get_current_record_p((contacts_list_h)contact->images, (contacts_record_h*)&image);
2075 if (CONTACTS_ERROR_NONE != ret) {
2076 ERR("contacts_list_get_current_record_p() Fail(%d)", ret);
2077 ctsvc_end_trans(false);
2078 return CONTACTS_ERROR_DB;
2081 if (image->path && image->is_default) {
2082 contact->image_thumbnail_path = strdup(image->path);
2085 } while (CONTACTS_ERROR_NONE == contacts_list_next((contacts_list_h)contact->images));
2089 version = ctsvc_get_next_ver();
2091 if (contact->person_id) {
2094 snprintf(query, sizeof(query),
2095 "SELECT contact_id FROM "CTSVC_DB_VIEW_CONTACT" "
2096 "WHERE person_id = %d", contact->person_id);
2097 ret = ctsvc_query_get_first_int_result(query, &id);
2098 if (CONTACTS_ERROR_NONE != ret) {
2099 ERR("Invalid person_id(%d)", contact->person_id);
2100 ctsvc_end_trans(false);
2101 return CONTACTS_ERROR_INVALID_PARAMETER;
2105 } else if (auto_link_enabled) {
2106 ret = __ctsvc_find_person_to_link((contacts_record_h)contact, contact->addressbook_id, &person_id);
2107 DBG("__ctsvc_find_person_to_link return %d, person_id(%d)", ret, person_id);
2108 if (ret == CONTACTS_ERROR_NONE && 0 < person_id) {
2109 contact->person_id = person_id;
2112 ret = ctsvc_db_insert_person((contacts_record_h)contact);
2113 DBG("ctsvc_db_insert_person return %d, person_id(%d)", ret, ret);
2114 if (ret < CONTACTS_ERROR_NONE) {
2115 ERR("ctsvc_db_insert_person() Fail(%d)", ret);
2116 ctsvc_end_trans(false);
2119 contact->person_id = ret;
2122 ret = ctsvc_db_insert_person((contacts_record_h)contact);
2123 DBG("ctsvc_db_insert_person return %d, person_id(%d)", ret, ret);
2124 if (ret < CONTACTS_ERROR_NONE) {
2125 ERR("ctsvc_db_insert_person() Fail(%d)", ret);
2126 ctsvc_end_trans(false);
2129 contact->person_id = ret;
2132 snprintf(query, sizeof(query),
2133 "INSERT INTO "CTS_TABLE_CONTACTS"(contact_id, person_id, addressbook_id, is_favorite, "
2134 "created_ver, changed_ver, changed_time, link_mode, "
2135 "image_changed_ver, has_phonenumber, has_email, "
2136 "display_name, reverse_display_name, display_name_source, "
2137 "display_name_language, reverse_display_name_language, "
2138 "sort_name, reverse_sort_name, "
2139 "sortkey, reverse_sortkey, "
2140 "uid, ringtone_path, vibration, message_alert, image_thumbnail_path) "
2141 "VALUES(%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, ?, ?, %d, %d, %d, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
2142 contact->id, contact->person_id, contact->addressbook_id, contact->is_favorite,
2143 version, version, (int)time(NULL), contact->link_mode,
2144 (contact->image_thumbnail_path) ? version : 0, contact->has_phonenumber, contact->has_email,
2145 contact->display_source_type, contact->display_name_language, contact->reverse_display_name_language);
2147 ret = ctsvc_query_prepare(query, &stmt);
2149 ERR("ctsvc_query_prepare() Fail(%d)", ret);
2150 ctsvc_end_trans(false);
2154 if (contact->display_name)
2155 ctsvc_stmt_bind_text(stmt, 1, contact->display_name);
2156 if (contact->reverse_display_name)
2157 ctsvc_stmt_bind_text(stmt, 2, contact->reverse_display_name);
2158 if (contact->sort_name)
2159 ctsvc_stmt_bind_text(stmt, 3, contact->sort_name);
2160 if (contact->reverse_sort_name)
2161 ctsvc_stmt_bind_text(stmt, 4, contact->reverse_sort_name);
2162 if (contact->sortkey)
2163 ctsvc_stmt_bind_text(stmt, 5, contact->sortkey);
2164 if (contact->reverse_sortkey)
2165 ctsvc_stmt_bind_text(stmt, 6, contact->reverse_sortkey);
2167 ctsvc_stmt_bind_text(stmt, 7, contact->uid);
2168 if (contact->ringtone_path)
2169 ctsvc_stmt_bind_text(stmt, 8, contact->ringtone_path);
2170 if (contact->vibration)
2171 ctsvc_stmt_bind_text(stmt, 9, contact->vibration);
2172 if (contact->message_alert)
2173 ctsvc_stmt_bind_text(stmt, 10, contact->message_alert);
2174 if (contact->image_thumbnail_path)
2175 ctsvc_stmt_bind_text(stmt, 11, contact->image_thumbnail_path);
2177 ret = ctsvc_stmt_step(stmt);
2178 if (CONTACTS_ERROR_NONE != ret) {
2179 ERR("ctsvc_stmt_step() Fail(%d)", ret);
2180 ctsvc_stmt_finalize(stmt);
2181 ctsvc_end_trans(false);
2184 ctsvc_stmt_finalize(stmt);
2186 /* Insert group Info */
2187 if (contact->grouprelations) {
2188 rel_changed = __ctsvc_contact_insert_grouprel(contact->id, (contacts_list_h)contact->grouprelations);
2189 if (rel_changed < CONTACTS_ERROR_NONE) {
2190 ERR("__ctsvc_contact_insert_grouprel() Fail(%d)", rel_changed);
2191 ctsvc_end_trans(false);
2196 ret = __ctsvc_contact_insert_search_data(contact->id, need_insert_lookup);
2197 if (ret != CONTACTS_ERROR_NONE) {
2198 ERR("__ctsvc_contact_insert_search_data() Fail(%d)", ret);
2199 ctsvc_end_trans(false);
2203 /* person aggregation when auto_linked */
2205 ctsvc_person_aggregate(contact->person_id);
2207 #ifdef ENABLE_LOG_FEATURE
2208 /* update phonelog */
2209 if (contact->numbers) {
2211 ret = contacts_list_get_count((contacts_list_h)contact->numbers, &count);
2212 contacts_list_first((contacts_list_h)contact->numbers);
2214 ctsvc_number_s *number_record;
2216 contacts_list_get_current_record_p((contacts_list_h)contact->numbers, (contacts_record_h*)&number_record);
2217 if (number_record->number)
2218 ctsvc_db_phone_log_update_person_id(number_record->number, -1, contact->person_id, false, NULL);
2219 } while (CONTACTS_ERROR_NONE == contacts_list_next((contacts_list_h)contact->numbers));
2222 #endif /* ENABLE_LOG_FEATURE */
2224 ctsvc_set_group_rel_noti();
2225 ctsvc_set_contact_noti();
2227 ret = ctsvc_end_trans(true);
2228 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_svc_end_trans() Fail(%d)", ret);
2230 return CONTACTS_ERROR_NONE;
2233 static int __ctsvc_db_contact_replace_record(contacts_record_h record, int contact_id)
2237 int rel_changed = 0;
2240 char query[CTS_SQL_MAX_LEN] = {0};
2241 ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
2242 cts_stmt stmt = NULL;
2245 ret = ctsvc_begin_trans();
2246 RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
2248 snprintf(query, sizeof(query),
2249 "SELECT addressbook_id, person_id FROM "CTS_TABLE_CONTACTS" "
2250 "WHERE contact_id = %d AND deleted = 0", contact_id);
2251 ret = ctsvc_query_prepare(query, &stmt);
2253 ERR("ctsvc_query_prepare fail(%d)", ret);
2254 ctsvc_end_trans(false);
2257 ret = ctsvc_stmt_step(stmt);
2259 ERR("The contact_id(%d) is Invalid(%d)", contact_id, ret);
2260 ctsvc_stmt_finalize(stmt);
2261 ctsvc_end_trans(false);
2262 if (CONTACTS_ERROR_NONE == ret)
2263 return CONTACTS_ERROR_NO_DATA;
2268 addressbook_id = ctsvc_stmt_get_int(stmt, 0);
2269 person_id = ctsvc_stmt_get_int(stmt, 1);
2270 ctsvc_stmt_finalize(stmt);
2272 if (false == ctsvc_have_ab_write_permission(addressbook_id, false)) {
2273 ERR("No permission in this addresbook_id(%d)", addressbook_id);
2274 ctsvc_end_trans(false);
2275 return CONTACTS_ERROR_PERMISSION_DENIED;
2278 contact->id = contact_id;
2279 contact->person_id = person_id;
2280 ctsvc_contact_make_display_name(contact);
2281 __ctsvc_contact_check_default_data(contact);
2283 /* remove current child data */
2284 snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_DATA" WHERE contact_id = %d",
2286 ret = ctsvc_query_exec(query);
2287 if (CONTACTS_ERROR_NONE != ret) {
2288 ERR("ctsvc_query_exec() Fail(%d)", ret);
2289 ctsvc_end_trans(false);
2293 ret = __ctsvc_contact_insert_data(contact);
2294 if (CONTACTS_ERROR_NONE != ret) {
2295 ERR("__ctsvc_contact_insert_data() Fail(%d)", ret);
2296 ctsvc_end_trans(false);
2300 /* remove current child data */
2301 snprintf(query, sizeof(query),
2302 "DELETE FROM "CTS_TABLE_GROUP_RELATIONS" WHERE contact_id = %d", contact_id);
2303 ret = ctsvc_query_exec(query);
2304 if (CONTACTS_ERROR_NONE != ret) {
2305 ERR("ctsvc_query_exec() Fail(%d)", ret);
2306 ctsvc_end_trans(false);
2310 if (contact->grouprelations) {
2311 rel_changed = __ctsvc_contact_insert_grouprel(contact_id,
2312 (contacts_list_h)contact->grouprelations);
2313 if (rel_changed < CONTACTS_ERROR_NONE) {
2314 ERR("__ctsvc_contact_insert_grouprel() Fail(%d)", rel_changed);
2315 ctsvc_end_trans(false);
2321 if (contact->images) {
2322 int ret = CONTACTS_ERROR_NONE;
2324 ctsvc_image_s *image;
2326 contacts_list_get_count((contacts_list_h)contact->images, &count);
2328 contacts_list_first((contacts_list_h)contact->images);
2330 ret = contacts_list_get_current_record_p((contacts_list_h)contact->images,
2331 (contacts_record_h*)&image);
2332 if (CONTACTS_ERROR_NONE != ret) {
2333 ERR("contacts_list_get_current_record_p() Fail(%d)", ret);
2334 ctsvc_end_trans(false);
2335 return CONTACTS_ERROR_DB;
2338 if (image->is_default)
2340 } while (CONTACTS_ERROR_NONE == contacts_list_next((contacts_list_h)contact->images));
2342 if ((NULL == contact->image_thumbnail_path && image->path) ||
2343 (contact->image_thumbnail_path && NULL == image->path) ||
2344 (contact->image_thumbnail_path && image->path && STRING_EQUAL != strcmp(contact->image_thumbnail_path, image->path))) {
2345 ctsvc_record_set_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
2347 if (ctsvc_contact_check_image_location(image->path))
2348 contact->image_thumbnail_path = SAFE_STRDUP(image->path + strlen(CTSVC_CONTACT_IMG_FULL_LOCATION) + 1);
2350 contact->image_thumbnail_path = SAFE_STRDUP(image->path);
2352 } else if (contact->image_thumbnail_path) {
2353 free(contact->image_thumbnail_path);
2354 contact->image_thumbnail_path = NULL;
2355 if (false == ctsvc_record_check_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY)) {
2356 ctsvc_record_set_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
2358 if (((ctsvc_record_s*)record)->properties_flags) {
2359 int index = _contacts_contact.image_thumbnail_path & 0x000000FF;
2360 ((ctsvc_record_s*)record)->properties_flags[index] = 0;
2365 version = ctsvc_get_next_ver();
2367 len = snprintf(query, sizeof(query),
2368 "UPDATE "CTS_TABLE_CONTACTS" SET changed_ver=%d, changed_time=%d, is_favorite=%d, "
2369 "has_phonenumber=%d, has_email=%d, display_name=?, "
2370 "reverse_display_name=?, display_name_source=%d, "
2371 "display_name_language=%d, reverse_display_name_language=%d, "
2372 "sort_name=?, reverse_sort_name=?, "
2373 "sortkey=?, reverse_sortkey=?, uid=?, ringtone_path=?, vibration=?, "
2374 "message_alert =?, image_thumbnail_path=?",
2375 version, (int)time(NULL), contact->is_favorite,
2376 contact->has_phonenumber, contact->has_email,
2377 contact->display_source_type,
2378 contact->display_name_language, contact->reverse_display_name_language);
2380 if (ctsvc_record_check_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY))
2381 len += snprintf(query+len, sizeof(query)-len, ", image_changed_ver = %d", version);
2383 len += snprintf(query+len, sizeof(query)-len, " WHERE contact_id=%d", contact->id);
2385 ret = ctsvc_query_prepare(query, &stmt);
2387 ERR("ctsvc_query_prepare() Fail(%d)", ret);
2388 ctsvc_end_trans(false);
2392 if (contact->display_name)
2393 ctsvc_stmt_bind_text(stmt, 1, contact->display_name);
2394 if (contact->reverse_display_name)
2395 ctsvc_stmt_bind_text(stmt, 2, contact->reverse_display_name);
2396 if (contact->sort_name)
2397 ctsvc_stmt_bind_text(stmt, 3, contact->sort_name);
2398 if (contact->reverse_sort_name)
2399 ctsvc_stmt_bind_text(stmt, 4, contact->reverse_sort_name);
2400 if (contact->sortkey)
2401 ctsvc_stmt_bind_text(stmt, 5, contact->sortkey);
2402 if (contact->reverse_sortkey)
2403 ctsvc_stmt_bind_text(stmt, 6, contact->reverse_sortkey);
2405 ctsvc_stmt_bind_text(stmt, 7, contact->uid);
2406 if (contact->ringtone_path)
2407 ctsvc_stmt_bind_text(stmt, 8, contact->ringtone_path);
2408 if (contact->vibration)
2409 ctsvc_stmt_bind_text(stmt, 9, contact->vibration);
2410 if (contact->message_alert)
2411 ctsvc_stmt_bind_text(stmt, 10, contact->message_alert);
2412 if (contact->image_thumbnail_path)
2413 ctsvc_stmt_bind_text(stmt, 11, contact->image_thumbnail_path);
2415 ret = ctsvc_stmt_step(stmt);
2416 if (CONTACTS_ERROR_NONE != ret) {
2417 ERR("ctsvc_stmt_step() Fail(%d)", ret);
2418 ctsvc_stmt_finalize(stmt);
2419 ctsvc_end_trans(false);
2422 ctsvc_stmt_finalize(stmt);
2424 ctsvc_set_contact_noti();
2425 if (0 < rel_changed)
2426 ctsvc_set_group_rel_noti();
2428 __ctsvc_contact_update_search_data(contact->id, true);
2429 ctsvc_db_update_person((contacts_record_h)contact);
2431 ret = ctsvc_end_trans(true);
2433 if (ret < CONTACTS_ERROR_NONE)
2436 return CONTACTS_ERROR_NONE;
2439 ctsvc_db_plugin_info_s ctsvc_db_plugin_contact = {
2440 .is_query_only = false,
2441 .insert_record = __ctsvc_db_contact_insert_record,
2442 .get_record = __ctsvc_db_contact_get_record,
2443 .update_record = __ctsvc_db_contact_update_record,
2444 .delete_record = __ctsvc_db_contact_delete_record,
2445 .get_all_records = __ctsvc_db_contact_get_all_records,
2446 .get_records_with_query = __ctsvc_db_contact_get_records_with_query,
2447 .insert_records = NULL,
2448 .update_records = NULL,
2449 .delete_records = NULL,
2451 .get_count_with_query = NULL,
2452 .replace_record = __ctsvc_db_contact_replace_record,
2453 .replace_records = NULL,