4 * Copyright (c) 2010 - 2012 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"
50 static int __ctsvc_db_contact_insert_record(contacts_record_h record, int *id);
51 static int __ctsvc_db_contact_get_record(int id, contacts_record_h* out_record);
52 static int __ctsvc_db_contact_update_record(contacts_record_h record);
53 static int __ctsvc_db_contact_delete_record(int id);
54 static int __ctsvc_db_contact_replace_record(contacts_record_h record, int id);
56 static int __ctsvc_db_contact_get_all_records(int offset, int limit, contacts_list_h* out_list);
57 static int __ctsvc_db_contact_get_records_with_query(contacts_query_h query, int offset, int limit, contacts_list_h* out_list);
59 ctsvc_db_plugin_info_s ctsvc_db_plugin_contact = {
60 .is_query_only = false,
61 .insert_record = __ctsvc_db_contact_insert_record,
62 .get_record = __ctsvc_db_contact_get_record,
63 .update_record = __ctsvc_db_contact_update_record,
64 .delete_record = __ctsvc_db_contact_delete_record,
65 .get_all_records = __ctsvc_db_contact_get_all_records,
66 .get_records_with_query = __ctsvc_db_contact_get_records_with_query,
67 .insert_records = NULL,
68 .update_records = NULL,
69 .delete_records = NULL,
71 .get_count_with_query = NULL,
72 .replace_record = __ctsvc_db_contact_replace_record,
73 .replace_records = NULL,
76 static int __ctsvc_db_get_contact_base_info(int id, ctsvc_contact_s *contact)
81 char query[CTS_SQL_MAX_LEN] = {0};
83 char full_path[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
85 snprintf(query, sizeof(query),
86 "SELECT contact_id, addressbook_id, person_id, changed_time, changed_ver, link_mode, %s, "
87 "display_name_source, image_thumbnail_path, "
88 "ringtone_path, vibration, message_alert, "
89 "uid, is_favorite, has_phonenumber, has_email, "
90 "sort_name, reverse_sort_name "
91 "FROM "CTS_TABLE_CONTACTS" WHERE contact_id = %d AND deleted = 0",
92 ctsvc_get_display_column(), id);
94 ret = ctsvc_query_prepare(query, &stmt);
95 RETVM_IF(NULL == stmt, ret, "DB error : ctsvc_query_prepare() Fail(%d)", ret);
97 ret = ctsvc_stmt_step(stmt);
98 if (1 /*CTS_TRUE*/ != ret) {
99 CTS_ERR("ctsvc_stmt_step() Fail(%d)", ret);
100 ctsvc_stmt_finalize(stmt);
101 if (CONTACTS_ERROR_NONE == ret)
102 return CONTACTS_ERROR_NO_DATA;
108 contact->id = ctsvc_stmt_get_int(stmt, i++);
109 contact->addressbook_id = ctsvc_stmt_get_int(stmt, i++);
110 contact->person_id = ctsvc_stmt_get_int(stmt, i++);
111 contact->changed_time = ctsvc_stmt_get_int(stmt, i++);
112 contact->changed_ver = ctsvc_stmt_get_int(stmt, i++);
113 contact->link_mode = ctsvc_stmt_get_int(stmt, i++);
114 temp = ctsvc_stmt_get_text(stmt, i++);
115 contact->display_name = SAFE_STRDUP(temp);
116 contact->display_source_type = ctsvc_stmt_get_int(stmt, i++);
118 temp = ctsvc_stmt_get_text(stmt, i++);
120 snprintf(full_path, sizeof(full_path), "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, temp);
121 contact->image_thumbnail_path = strdup(full_path);
124 temp = ctsvc_stmt_get_text(stmt, i++);
125 contact->ringtone_path = SAFE_STRDUP(temp);
126 temp = ctsvc_stmt_get_text(stmt, i++);
127 contact->vibration = SAFE_STRDUP(temp);
128 temp = ctsvc_stmt_get_text(stmt, i++);
129 contact->message_alert = SAFE_STRDUP(temp);
130 temp = ctsvc_stmt_get_text(stmt, i++);
131 contact->uid = SAFE_STRDUP(temp);
132 contact->is_favorite = ctsvc_stmt_get_int(stmt, i++);
133 contact->has_phonenumber = ctsvc_stmt_get_int(stmt, i++);
134 contact->has_email = ctsvc_stmt_get_int(stmt, i++);
135 temp = ctsvc_stmt_get_text(stmt, i++);
136 contact->sort_name = SAFE_STRDUP(temp);
137 temp = ctsvc_stmt_get_text(stmt, i++);
138 contact->reverse_sort_name = SAFE_STRDUP(temp);
139 ctsvc_stmt_finalize(stmt);
141 return CONTACTS_ERROR_NONE;
144 static int __ctsvc_db_get_data(int id, ctsvc_contact_s *contact)
148 cts_stmt stmt = NULL;
149 char query[CTS_SQL_MAX_LEN] = {0};
151 snprintf(query, sizeof(query),
152 "SELECT datatype, id, data.contact_id, is_default, data1, data2, "
153 "data3, data4, data5, data6, data7, data8, data9, data10, data11, data12 "
154 "FROM "CTS_TABLE_DATA", "CTSVC_DB_VIEW_CONTACT" "
155 "ON "CTS_TABLE_DATA".contact_id = "CTSVC_DB_VIEW_CONTACT".contact_id "
156 "WHERE data.contact_id = %d AND is_my_profile = 0 "
157 "ORDER BY is_default DESC", id);
159 ret = ctsvc_query_prepare(query, &stmt);
160 RETVM_IF(NULL == stmt, ret, "DB error : ctsvc_query_prepare() Fail(%d)", ret);
162 ret = ctsvc_stmt_step(stmt);
163 if (1 /*CTS_TRUE */!= ret) {
164 CTS_ERR("ctsvc_stmt_step() Fail(%d)", ret);
165 ctsvc_stmt_finalize(stmt);
170 datatype = ctsvc_stmt_get_int(stmt, 0);
172 case CTSVC_DATA_NAME:
173 ctsvc_get_data_info_name(stmt, (contacts_list_h)contact->name);
175 case CTSVC_DATA_EVENT:
176 ctsvc_get_data_info_event(stmt, (contacts_list_h)contact->events);
178 case CTSVC_DATA_MESSENGER:
179 ctsvc_get_data_info_messenger(stmt, (contacts_list_h)contact->messengers);
181 case CTSVC_DATA_POSTAL:
182 ctsvc_get_data_info_address(stmt, (contacts_list_h)contact->postal_addrs);
185 ctsvc_get_data_info_url(stmt, (contacts_list_h)contact->urls);
187 case CTSVC_DATA_NICKNAME:
188 ctsvc_get_data_info_nickname(stmt, (contacts_list_h)contact->nicknames);
190 case CTSVC_DATA_NUMBER:
191 ctsvc_get_data_info_number(stmt, (contacts_list_h)contact->numbers);
193 case CTSVC_DATA_EMAIL:
194 ctsvc_get_data_info_email(stmt, (contacts_list_h)contact->emails);
196 case CTSVC_DATA_PROFILE:
197 ctsvc_get_data_info_profile(stmt, (contacts_list_h)contact->profiles);
199 case CTSVC_DATA_RELATIONSHIP:
200 ctsvc_get_data_info_relationship(stmt, (contacts_list_h)contact->relationships);
202 case CTSVC_DATA_IMAGE:
203 ctsvc_get_data_info_image(stmt, (contacts_list_h)contact->images);
205 case CTSVC_DATA_COMPANY:
206 ctsvc_get_data_info_company(stmt, (contacts_list_h)contact->company);
208 case CTSVC_DATA_NOTE:
209 ctsvc_get_data_info_note(stmt, (contacts_list_h)contact->note);
211 case CTSVC_DATA_EXTENSION:
212 ctsvc_get_data_info_extension(stmt, (contacts_list_h)contact->extensions);
215 CTS_ERR("Intenal : Not supported data type (%d)", datatype);
219 } while (1 == ctsvc_stmt_step(stmt));
221 ctsvc_stmt_finalize(stmt);
223 return CONTACTS_ERROR_NONE;
227 static inline int __ctsvc_get_contact_grouprel(int contact_id, ctsvc_contact_s *contact)
231 ctsvc_group_relation_s *grouprel;
232 cts_stmt stmt = NULL;
233 char query[CTS_SQL_MAX_LEN] = {0};
236 snprintf(query, sizeof(query),
237 "SELECT group_id, contact_id, group_name "
238 " FROM "CTSVC_DB_VIEW_GROUP_RELATION" WHERE contact_id = %d", contact_id);
240 ret = ctsvc_query_prepare(query, &stmt);
241 RETVM_IF(NULL == stmt, ret, "DB error : ctsvc_query_prepare() Fail(%d)", ret);
243 while (1 /*CTS_TRUE */ == ctsvc_stmt_step(stmt)) {
244 contacts_record_create(_contacts_group_relation._uri, (contacts_record_h*)&grouprel);
247 grouprel->group_id = ctsvc_stmt_get_int(stmt, 0);
248 grouprel->id = grouprel->group_id;
249 grouprel->contact_id = ctsvc_stmt_get_int(stmt, 1);
250 temp = ctsvc_stmt_get_text(stmt, 2);
251 grouprel->group_name = SAFE_STRDUP(temp);
253 ctsvc_list_prepend((contacts_list_h)contact->grouprelations, (contacts_record_h)grouprel);
257 ctsvc_stmt_finalize(stmt);
258 ctsvc_list_reverse((contacts_list_h)contact->grouprelations);
259 return CONTACTS_ERROR_NONE;
262 static int __ctsvc_db_contact_get_record(int id, contacts_record_h* out_record)
265 contacts_record_h record;
266 ctsvc_contact_s *contact;
268 RETV_IF(NULL == out_record, CONTACTS_ERROR_INVALID_PARAMETER);
271 contacts_record_create(_contacts_contact._uri, &record);
272 contact = (ctsvc_contact_s *)record;
273 ret = __ctsvc_db_get_contact_base_info(id, contact);
274 if (CONTACTS_ERROR_NONE != ret) {
275 CTS_ERR("__ctsvc_db_get_contact_base_info(ALL) Fail(%d)", ret);
276 contacts_record_destroy(record, true);
280 ret = __ctsvc_db_get_data(id, contact);
281 if (CONTACTS_ERROR_NONE != ret && CONTACTS_ERROR_NO_DATA != ret) {
282 CTS_ERR("ctsvc_get_data_info Fail(%d)", ret);
283 contacts_record_destroy(record, true);
287 ret = __ctsvc_get_contact_grouprel(id, contact);
288 if (CONTACTS_ERROR_NONE != ret) {
289 CTS_ERR("ctsvc_get_group_relations Fail(%d)", ret);
290 contacts_record_destroy(record, true);
294 *out_record = record;
296 return CONTACTS_ERROR_NONE;
299 static int __ctsvc_db_contact_delete_record(int id)
301 return ctsvc_db_contact_delete(id);
304 static inline int __ctsvc_contact_update_data(ctsvc_contact_s *contact)
309 ret = ctsvc_contact_update_data_name((contacts_list_h)contact->name, contact->id, false);
310 if (CONTACTS_ERROR_NONE != ret) {
311 CTS_ERR("ctsvc_contact_update_data_name() Fail(%d)", ret);
316 if (contact->company) {
317 ret = ctsvc_contact_update_data_company((contacts_list_h)contact->company, contact->id, false);
318 if (CONTACTS_ERROR_NONE != ret) {
319 CTS_ERR("ctsvc_contact_update_data_company() Fail(%d)", ret);
325 ret = ctsvc_contact_update_data_note((contacts_list_h)contact->note, contact->id, false);
326 if (CONTACTS_ERROR_NONE != ret) {
327 CTS_ERR("ctsvc_contact_update_data_note() Fail(%d)", ret);
332 if (contact->events) {
333 ret = ctsvc_contact_update_data_event((contacts_list_h)contact->events, contact->id, false);
334 if (CONTACTS_ERROR_NONE != ret) {
335 CTS_ERR("ctsvc_contact_update_data_events() Fail(%d)", ret);
340 if (contact->messengers) {
341 ret = ctsvc_contact_update_data_messenger((contacts_list_h)contact->messengers, contact->id, false);
342 if (CONTACTS_ERROR_NONE != ret) {
343 CTS_ERR("ctsvc_contact_update_data_messengers() Fail(%d)", ret);
348 if (contact->postal_addrs) {
349 ret = ctsvc_contact_update_data_address((contacts_list_h)contact->postal_addrs, contact->id, false);
350 if (CONTACTS_ERROR_NONE != ret) {
351 CTS_ERR("ctsvc_contact_update_data_address() Fail(%d)", ret);
357 ret = ctsvc_contact_update_data_url((contacts_list_h)contact->urls, contact->id, false);
358 if (CONTACTS_ERROR_NONE != ret) {
359 CTS_ERR("ctsvc_contact_update_data_url() Fail(%d)", ret);
364 if (contact->nicknames) {
365 ret = ctsvc_contact_update_data_nickname((contacts_list_h)contact->nicknames, contact->id, false);
366 if (CONTACTS_ERROR_NONE != ret) {
367 CTS_ERR("ctsvc_contact_update_data_nickname() Fail(%d)", ret);
372 if (contact->numbers) {
373 bool had_phonenumber;
374 ret = ctsvc_contact_update_data_number((contacts_list_h)contact->numbers, contact->id, false, &had_phonenumber);
375 if (CONTACTS_ERROR_NONE != ret) {
376 CTS_ERR("ctsvc_contact_update_data_number() Fail(%d)", ret);
379 contact->has_phonenumber = had_phonenumber;
382 if (contact->emails) {
384 ret = ctsvc_contact_update_data_email((contacts_list_h)contact->emails, contact->id, false, &had_email);
385 if (CONTACTS_ERROR_NONE != ret) {
386 CTS_ERR("ctsvc_contact_update_data_email() Fail(%d)", ret);
389 contact->has_email = had_email;
392 if (contact->profiles) {
393 ret = ctsvc_contact_update_data_profile((contacts_list_h)contact->profiles, contact->id, false);
394 if (CONTACTS_ERROR_NONE != ret) {
395 CTS_ERR("ctsvc_contact_update_data_profile() Fail(%d)", ret);
400 if (contact->relationships) {
401 ret = ctsvc_contact_update_data_relationship((contacts_list_h)contact->relationships, contact->id, false);
402 if (CONTACTS_ERROR_NONE != ret) {
403 CTS_ERR("ctsvc_contact_update_data_relationship() Fail(%d)", ret);
408 if (contact->images) {
409 ret = ctsvc_contact_update_data_image((contacts_list_h)contact->images, contact->id, false);
410 if (CONTACTS_ERROR_NONE != ret) {
411 CTS_ERR("ctsvc_contact_update_data_image() Fail(%d)", ret);
416 if (contact->extensions) {
417 ret = ctsvc_contact_update_data_extension((contacts_list_h)contact->extensions, contact->id, false);
418 if (CONTACTS_ERROR_NONE != ret) {
419 CTS_ERR("ctsvc_contact_update_data_extension() Fail(%d)", ret);
424 return CONTACTS_ERROR_NONE;
427 static void __ctsvc_contact_check_default_data(ctsvc_contact_s *contact)
429 if (contact->numbers)
430 contact->has_phonenumber = ctsvc_contact_check_default_number((contacts_list_h)contact->numbers);
432 contact->has_email = ctsvc_contact_check_default_email((contacts_list_h)contact->emails);
434 ctsvc_contact_check_default_image((contacts_list_h)contact->images);
435 if (contact->postal_addrs)
436 ctsvc_contact_check_default_address((contacts_list_h)contact->postal_addrs);
439 static inline int __ctsvc_contact_update_grouprel(int contact_id, contacts_list_h group_list)
442 ctsvc_group_relation_s *grouprel;
443 ctsvc_list_s *list = (ctsvc_list_s*)group_list;
449 RETV_IF(NULL == group_list, CONTACTS_ERROR_INVALID_PARAMETER);
451 for (cursor = list->deleted_records;cursor;cursor=cursor->next) {
452 grouprel = (ctsvc_group_relation_s *)cursor->data;
453 ret = ctsvc_group_remove_contact_in_transaction(grouprel->group_id, contact_id);
458 ret = contacts_list_get_count(group_list, &count);
460 return CONTACTS_ERROR_NONE;
462 contacts_list_first(group_list);
464 contacts_list_get_current_record_p(group_list, (contacts_record_h*)&grouprel);
465 if (NULL == grouprel)
468 RETVM_IF(grouprel->group_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER, "group_id(%d) invalid", grouprel->group_id);
469 if (grouprel->group_id) {
470 ret = ctsvc_group_add_contact_in_transaction(grouprel->group_id, contact_id);
471 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_db_group_set_relation() Fail(%d)", ret);
475 } while (CONTACTS_ERROR_NONE == contacts_list_next(group_list));
480 return CONTACTS_ERROR_NONE;
483 static bool __ctsvc_contact_check_token(char *src, char *dest, int len)
488 for (i=0;i<len;i++) {
489 if (src[i] == '@' || src[i] == '.') {
501 /* Make search data by number, email, nicknames, address, note, messenger, relationship, company */
502 static inline int __ctsvc_contact_make_search_data(ctsvc_contact_s *contact,
503 char **search_number, char **search_data)
509 char *temp_number=NULL;
510 char *temp_data=NULL;
513 RETV_IF(NULL == contact, CONTACTS_ERROR_NO_DATA);
515 if (contact->numbers) {
516 contacts_list_h number_list = (contacts_list_h)contact->numbers;
517 ctsvc_number_s *number_record;
518 contacts_list_first(number_list);
520 contacts_list_get_current_record_p(number_list, (contacts_record_h*)&number_record);
521 if (number_record && number_record->cleaned) {
522 buf_size = SAFE_STRLEN(number) + SAFE_STRLEN(number_record->cleaned) + SAFE_STRLEN(number_record->normalized) + 3;
523 temp_number = calloc(1, buf_size);
524 if (NULL == temp_number) {
525 CTS_ERR("calloc() Fail");
527 return CONTACTS_ERROR_OUT_OF_MEMORY;
531 snprintf(temp_number, buf_size, "%s %s %s", SAFE_STR(number), number_record->cleaned, number_record->normalized);
533 snprintf(temp_number, buf_size, "%s %s", number_record->cleaned, number_record->normalized);
535 number = temp_number;
537 } while (CONTACTS_ERROR_NONE == contacts_list_next(number_list));
540 if (contact->emails) {
541 contacts_list_h email_list = (contacts_list_h)contact->emails;
542 ctsvc_email_s *email;
543 contacts_list_first(email_list);
545 contacts_list_get_current_record_p(email_list, (contacts_record_h*)&email);
546 if (email && email->email_addr) {
547 int len = strlen(email->email_addr);
549 bool had = __ctsvc_contact_check_token(email->email_addr, temp, len);
551 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(email->email_addr) * (had?2:1) + 4;
552 temp_data = calloc(1, buf_size);
553 if (NULL == temp_data) {
554 CTS_ERR("calloc() Fail");
557 return CONTACTS_ERROR_OUT_OF_MEMORY;
561 snprintf(temp_data, buf_size, "%s %s %s",data, email->email_addr, (had?temp:""));
563 snprintf(temp_data, buf_size, "%s %s",email->email_addr, (had?temp:""));
567 } while (CONTACTS_ERROR_NONE == contacts_list_next(email_list));
570 if (contact->nicknames) {
571 contacts_list_h nickname_list = (contacts_list_h)contact->nicknames;
572 ctsvc_nickname_s *nickname;
573 contacts_list_first(nickname_list);
575 contacts_list_get_current_record_p(nickname_list, (contacts_record_h*)&nickname);
576 if (nickname && nickname->nickname) {
577 int len = strlen(nickname->nickname);
579 bool had = __ctsvc_contact_check_token(nickname->nickname, temp, len);
581 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(nickname->nickname) * (had?2:1) + 4;
582 temp_data = calloc(1, buf_size);
583 if (NULL == temp_data) {
584 CTS_ERR("calloc() Fail");
587 return CONTACTS_ERROR_OUT_OF_MEMORY;
591 snprintf(temp_data, buf_size, "%s %s %s", data, nickname->nickname, (had?temp:""));
593 snprintf(temp_data, buf_size, "%s %s", nickname->nickname, (had?temp:""));
597 } while (CONTACTS_ERROR_NONE == contacts_list_next(nickname_list));
600 if (contact->postal_addrs) {
601 contacts_list_h address_list = (contacts_list_h)contact->postal_addrs;
602 ctsvc_address_s *address;
603 contacts_list_first(address_list);
605 contacts_list_get_current_record_p(address_list, (contacts_record_h*)&address);
608 int str_len = SAFE_STRLEN(address->country)
609 + SAFE_STRLEN(address->pobox)
610 + SAFE_STRLEN(address->postalcode)
611 + SAFE_STRLEN(address->region)
612 + SAFE_STRLEN(address->locality)
613 + SAFE_STRLEN(address->street)
614 + SAFE_STRLEN(address->extended);
616 buf_size = SAFE_STRLEN(data)
618 temp_data = calloc(1, buf_size);
619 if (NULL == temp_data) {
620 CTS_ERR("calloc() Fail");
623 return CONTACTS_ERROR_OUT_OF_MEMORY;
626 char temp[str_len+1];
629 len += snprintf(temp_data + len, buf_size - len, "%s ", data);
631 if (address->country) {
632 had = __ctsvc_contact_check_token(address->country, temp, SAFE_STRLEN(address->country));
633 len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->country, had?temp:"");
635 if (address->pobox) {
636 had = __ctsvc_contact_check_token(address->pobox, temp, SAFE_STRLEN(address->pobox));
637 len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->pobox, had?temp:"");
639 if (address->postalcode) {
640 had = __ctsvc_contact_check_token(address->postalcode, temp, SAFE_STRLEN(address->postalcode));
641 len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->postalcode, had?temp:"");
643 if (address->region) {
644 had = __ctsvc_contact_check_token(address->region, temp, SAFE_STRLEN(address->region));
645 len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->region, had?temp:"");
647 if (address->locality) {
648 had = __ctsvc_contact_check_token(address->locality, temp, SAFE_STRLEN(address->locality));
649 len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->locality, had?temp:"");
651 if (address->street) {
652 had = __ctsvc_contact_check_token(address->street, temp, SAFE_STRLEN(address->street));
653 len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->street, had?temp:"");
655 if (address->extended) {
656 had = __ctsvc_contact_check_token(address->extended, temp, SAFE_STRLEN(address->extended));
657 len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->extended, had?temp:"");
662 } while (CONTACTS_ERROR_NONE == contacts_list_next(address_list));
666 contacts_list_h note_list = (contacts_list_h)contact->note;
668 contacts_list_first(note_list);
670 contacts_list_get_current_record_p(note_list, (contacts_record_h*)¬e);
671 if (note && note->note) {
672 int len = strlen(note->note);
674 bool had = __ctsvc_contact_check_token(note->note, temp, len);
676 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(note->note) * (had?2:1) + 4;
677 temp_data = calloc(1, buf_size);
678 if (NULL == temp_data) {
679 CTS_ERR("calloc() Fail");
682 return CONTACTS_ERROR_OUT_OF_MEMORY;
686 snprintf(temp_data, buf_size, "%s %s %s",data, note->note, (had?temp:""));
688 snprintf(temp_data, buf_size, "%s %s",note->note, (had?temp:""));
692 } while (CONTACTS_ERROR_NONE == contacts_list_next(note_list));
695 if (contact->messengers) {
696 contacts_list_h messenger_list = (contacts_list_h)contact->messengers;
697 ctsvc_messenger_s *messenger;
698 contacts_list_first(messenger_list);
700 contacts_list_get_current_record_p(messenger_list, (contacts_record_h*)&messenger);
701 if (messenger && messenger->im_id) {
702 int len = strlen(messenger->im_id);
704 bool had = __ctsvc_contact_check_token(messenger->im_id, temp, len);
706 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(messenger->im_id) * (had?2:1) + 4;
707 temp_data = calloc(1, buf_size);
708 if (NULL == temp_data) {
709 CTS_ERR("calloc() Fail");
712 return CONTACTS_ERROR_OUT_OF_MEMORY;
716 snprintf(temp_data, buf_size, "%s %s %s",data, messenger->im_id, (had?temp:""));
718 snprintf(temp_data, buf_size, "%s %s",messenger->im_id, (had?temp:""));
722 } while (CONTACTS_ERROR_NONE == contacts_list_next(messenger_list));
725 if (contact->relationships) {
726 contacts_list_h relationship_list = (contacts_list_h)contact->relationships;
727 ctsvc_relationship_s *relationship;
728 contacts_list_first(relationship_list);
730 contacts_list_get_current_record_p(relationship_list, (contacts_record_h*)&relationship);
731 if (relationship && relationship->name) {
732 int len = strlen(relationship->name);
734 bool had = __ctsvc_contact_check_token(relationship->name, temp, len);
736 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(relationship->name) * (had?2:1) + 4;
737 temp_data = calloc(1, buf_size);
738 if (NULL == temp_data) {
739 CTS_ERR("calloc() Fail");
742 return CONTACTS_ERROR_OUT_OF_MEMORY;
746 snprintf(temp_data, buf_size, "%s %s %s",data, relationship->name, (had?temp:""));
748 snprintf(temp_data, buf_size, "%s %s",relationship->name, (had?temp:""));
752 } while (CONTACTS_ERROR_NONE == contacts_list_next(relationship_list));
755 if (contact->company) {
756 contacts_list_h company_list = (contacts_list_h)contact->company;
757 ctsvc_company_s *company;
758 contacts_list_first(company_list);
760 contacts_list_get_current_record_p(company_list, (contacts_record_h*)&company);
763 int str_len = SAFE_STRLEN(company->name)
764 + SAFE_STRLEN(company->department)
765 + SAFE_STRLEN(company->job_title)
766 + SAFE_STRLEN(company->role)
767 + SAFE_STRLEN(company->assistant_name)
768 + SAFE_STRLEN(company->location)
769 + SAFE_STRLEN(company->description)
770 + SAFE_STRLEN(company->phonetic_name);
772 buf_size = SAFE_STRLEN(data) + str_len * 2 + 18;
773 temp_data = calloc(1, buf_size);
774 if (NULL == temp_data) {
775 CTS_ERR("calloc() Fail");
778 return CONTACTS_ERROR_OUT_OF_MEMORY;
781 char temp[str_len+1];
784 len += snprintf(temp_data + len, buf_size - len, "%s ", data);
786 had = __ctsvc_contact_check_token(company->name, temp, SAFE_STRLEN(company->name));
787 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->name, had?temp:"");
789 if (company->department) {
790 had = __ctsvc_contact_check_token(company->department, temp, SAFE_STRLEN(company->department));
791 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->department, had?temp:"");
793 if (company->job_title) {
794 had = __ctsvc_contact_check_token(company->job_title, temp, SAFE_STRLEN(company->job_title));
795 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->job_title, had?temp:"");
798 had = __ctsvc_contact_check_token(company->role, temp, SAFE_STRLEN(company->role));
799 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->role, had?temp:"");
801 if (company->assistant_name) {
802 had = __ctsvc_contact_check_token(company->assistant_name, temp, SAFE_STRLEN(company->assistant_name));
803 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->assistant_name, had?temp:"");
805 if (company->location) {
806 had = __ctsvc_contact_check_token(company->location, temp, SAFE_STRLEN(company->location));
807 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->location, had?temp:"");
809 if (company->description) {
810 had = __ctsvc_contact_check_token(company->description, temp, SAFE_STRLEN(company->description));
811 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->description, had?temp:"");
813 if (company->phonetic_name) {
814 had = __ctsvc_contact_check_token(company->phonetic_name, temp, SAFE_STRLEN(company->phonetic_name));
815 len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->phonetic_name, had?temp:"");
821 } while (CONTACTS_ERROR_NONE == contacts_list_next(company_list));
824 *search_number = number;
828 return CONTACTS_ERROR_NONE;
831 static inline int __ctsvc_contact_refresh_lookup_data(int contact_id, ctsvc_contact_s *contact)
834 int ret, len = 0, temp_len =0;
835 char query[CTS_SQL_MAX_LEN] = {0};
837 snprintf(query, sizeof(query), "DELETE FROM %s WHERE contact_id = %d",
838 CTS_TABLE_NAME_LOOKUP, contact_id);
839 ret = ctsvc_query_exec(query);
840 if (CONTACTS_ERROR_NONE != ret) {
841 CTS_ERR("ctsvc_query_exec() Fail(%d)", ret);
845 snprintf(query, sizeof(query), "DELETE FROM %s WHERE contact_id = %d",
846 CTS_TABLE_PHONE_LOOKUP, contact_id);
847 ret = ctsvc_query_exec(query);
848 if (CONTACTS_ERROR_NONE != ret) {
849 CTS_ERR("ctsvc_query_exec() Fail(%d)", ret);
854 return CONTACTS_ERROR_NO_DATA;
857 contacts_list_h name_list = (contacts_list_h)contact->name;
858 ctsvc_name_s *name_record;
859 cts_stmt stmt = NULL;
860 char *temp_name = NULL;
861 contacts_list_first(name_list);
863 /* name record of contact should be one */
865 contacts_list_get_current_record_p(name_list, (contacts_record_h*)&name_record);
867 && (name_record->last || name_record->first || name_record->addition || name_record->suffix)) {
868 char *normalized_name = NULL;
871 * Make reverse display name (Last name first)
872 * Default : Prefix Last, First Middle(addition), Suffix
873 * Korean, Chinese : Prefix LastMiddleFirstSuffix
874 * Japanese : Prefix Last Middle First Suffix
875 * reverse sort name does not include prefix
876 * But, if there is only prefix, reverse sort_name is prefix
878 /* make display name */
879 temp_len = SAFE_STRLEN(name_record->first) + SAFE_STRLEN(name_record->addition)
880 + SAFE_STRLEN(name_record->last)+ SAFE_STRLEN(name_record->suffix) + 1;
881 int reverse_lang_type = ctsvc_contact_get_name_language(name_record);
882 temp_name = calloc(1, temp_len);
883 if (NULL == temp_name) {
884 CTS_ERR("calloc() Fail");
885 return CONTACTS_ERROR_OUT_OF_MEMORY;
888 if (reverse_lang_type == CTSVC_LANG_KOREAN ||
889 reverse_lang_type == CTSVC_LANG_CHINESE ||
890 reverse_lang_type == CTSVC_LANG_JAPANESE) {
891 if (name_record->last)
892 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->last);
893 if (name_record->addition)
894 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->addition);
895 if (name_record->first)
896 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->first);
897 if (name_record->suffix)
898 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->suffix);
901 if (name_record->last)
902 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->last);
903 if (name_record->first)
904 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->first);
905 if (name_record->addition)
906 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->addition);
907 if (name_record->suffix)
908 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->suffix);
911 ctsvc_normalize_str(temp_name, &normalized_name);
912 snprintf(query, sizeof(query), "INSERT INTO %s(data_id, contact_id, name, type) "
913 "VALUES(%d, %d, ?, %d)", CTS_TABLE_NAME_LOOKUP, name_record->id,
916 ret = ctsvc_query_prepare(query, &stmt);
918 CTS_ERR("ctsvc_query_prepare() Fail(%d)", ret);
920 free(normalized_name);
925 ctsvc_stmt_bind_text(stmt, 1, normalized_name);
927 ret = ctsvc_stmt_step(stmt);
930 free(normalized_name);
932 ctsvc_stmt_finalize(stmt);
934 if (CONTACTS_ERROR_NONE != ret) {
935 CTS_ERR("ctsvc_stmt_step() Fail(%d)", ret);
940 } while (CONTACTS_ERROR_NONE == contacts_list_next(name_list));
943 if (contact->numbers) {
944 contacts_list_h number_list = (contacts_list_h)contact->numbers;
945 cts_stmt stmt = NULL;
946 ctsvc_number_s *number_record;
947 contacts_list_first(number_list);
950 contacts_list_get_current_record_p(number_list, (contacts_record_h*)&number_record);
951 if (number_record && number_record->number) {
952 if (NULL == number_record->cleaned)
955 /* actually phone_lookup minmatch is not used */
956 snprintf(query, sizeof(query), "INSERT INTO %s(data_id, contact_id, number, min_match) "
957 "VALUES(%d, %d, ?, ?)", CTS_TABLE_PHONE_LOOKUP, number_record->id,
960 ret = ctsvc_query_prepare(query, &stmt);
961 RETVM_IF(NULL == stmt, ret, "DB error : ctsvc_query_prepare() Fail(%d)", ret);
963 if (*number_record->cleaned)
964 ctsvc_stmt_bind_text(stmt, 1, number_record->cleaned);
965 ret = ctsvc_stmt_step(stmt);
966 if (CONTACTS_ERROR_NONE != ret) {
967 CTS_ERR("ctsvc_stmt_step() Fail(%d)", ret);
968 ctsvc_stmt_finalize(stmt);
971 if (number_record->normalized && STRING_EQUAL != strcmp(number_record->cleaned, number_record->normalized)) {
972 ctsvc_stmt_reset(stmt);
973 if (*number_record->normalized)
974 ctsvc_stmt_bind_text(stmt, 1, number_record->normalized);
975 ret = ctsvc_stmt_step(stmt);
976 if (CONTACTS_ERROR_NONE != ret) {
977 CTS_ERR("ctsvc_stmt_step() Fail(%d)", ret);
978 ctsvc_stmt_finalize(stmt);
982 ctsvc_stmt_finalize(stmt);
984 } while (CONTACTS_ERROR_NONE == contacts_list_next(number_list));
987 if (contact->nicknames) {
988 contacts_list_h nickname_list = (contacts_list_h)contact->nicknames;
989 cts_stmt stmt = NULL;
990 ctsvc_nickname_s *nickname;
991 contacts_list_first(nickname_list);
993 contacts_list_get_current_record_p(nickname_list, (contacts_record_h*)&nickname);
994 if (nickname && nickname->nickname) {
995 char *normalized_nickname = NULL;
996 ctsvc_normalize_str(nickname->nickname, &normalized_nickname);
997 snprintf(query, sizeof(query), "INSERT INTO %s(data_id, contact_id, name, type) "
998 "VALUES(%d, %d, ?, %d)", CTS_TABLE_NAME_LOOKUP, nickname->id,
1001 ret = ctsvc_query_prepare(query, &stmt);
1003 CTS_ERR("ctsvc_query_prepare() Fail(%d)", ret);
1004 free(normalized_nickname);
1008 if (normalized_nickname && *normalized_nickname)
1009 ctsvc_stmt_bind_text(stmt, 1, normalized_nickname);
1011 ret = ctsvc_stmt_step(stmt);
1013 free(normalized_nickname);
1015 ctsvc_stmt_finalize(stmt);
1017 if (CONTACTS_ERROR_NONE != ret) {
1018 CTS_ERR("ctsvc_stmt_step() Fail(%d)", ret);
1022 } while (CONTACTS_ERROR_NONE == contacts_list_next(nickname_list));
1025 return CONTACTS_ERROR_NONE;
1028 static inline int __ctsvc_contact_update_search_data(int contact_id, bool need_refresh_lookup_data)
1031 cts_stmt stmt = NULL;
1032 char query[CTS_SQL_MAX_LEN] = {0};
1033 char *search_name = NULL;
1034 char *search_number = NULL;
1035 char *search_data = NULL;
1036 ctsvc_contact_s *contact = NULL;
1038 ret = ctsvc_begin_trans();
1039 RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
1041 ret = ctsvc_db_contact_get(contact_id, (contacts_record_h*)&contact);
1042 if (CONTACTS_ERROR_NO_DATA == ret) {
1044 snprintf(query, sizeof(query), "DELETE FROM %s WHERE contact_id = %d",
1045 CTS_TABLE_SEARCH_INDEX, contact_id);
1046 r = ctsvc_query_exec(query);
1047 if (CONTACTS_ERROR_NONE != r) {
1048 CTS_ERR("ctsvc_query_exec() Fail(%d)", r);
1049 ctsvc_end_trans(false);
1052 ctsvc_end_trans(false);
1055 else if (CONTACTS_ERROR_NONE != ret) {
1056 CTS_ERR("ctsvc_db_contact_get() Fail(%d)", ret);
1057 ctsvc_end_trans(false);
1061 ret = ctsvc_contact_make_search_name(contact, &search_name);
1062 if (CONTACTS_ERROR_NONE != ret) {
1063 CTS_ERR("ctsvc_contact_make_search_name() Fail(%d)", ret);
1064 contacts_record_destroy((contacts_record_h)contact, true);
1065 ctsvc_end_trans(false);
1069 ret = __ctsvc_contact_make_search_data(contact, &search_number, &search_data);
1070 if (CONTACTS_ERROR_NONE != ret) {
1071 CTS_ERR("__ctsvc_contact_make_search_data() Fail(%d)", ret);
1072 contacts_record_destroy((contacts_record_h)contact, true);
1073 ctsvc_end_trans(false);
1078 snprintf(query, sizeof(query),
1079 "UPDATE %s SET name=?, number=?, data=? "
1080 "WHERE contact_id = %d",
1081 CTS_TABLE_SEARCH_INDEX, contact_id);
1083 ret = ctsvc_query_prepare(query, &stmt);
1085 CTS_ERR("ctsvc_query_prepare() Fail(%d)", ret);
1086 contacts_record_destroy((contacts_record_h)contact, true);
1087 ctsvc_end_trans(false);
1089 free(search_number);
1095 ctsvc_stmt_bind_text(stmt, 1, search_name);
1097 ctsvc_stmt_bind_text(stmt, 2, search_number);
1099 ctsvc_stmt_bind_text(stmt, 3, search_data);
1101 ret = ctsvc_stmt_step(stmt);
1104 free(search_number);
1107 if (CONTACTS_ERROR_NONE != ret) {
1108 CTS_ERR("ctsvc_stmt_step() Fail(%d)", ret);
1109 contacts_record_destroy((contacts_record_h)contact, true);
1110 ctsvc_stmt_finalize(stmt);
1111 ctsvc_end_trans(false);
1114 ctsvc_stmt_finalize(stmt);
1116 if (need_refresh_lookup_data) {
1117 /* update phone_lookup, name_lookup */
1118 ret = __ctsvc_contact_refresh_lookup_data(contact_id, contact);
1119 if (CONTACTS_ERROR_NONE != ret) {
1120 CTS_ERR("__ctsvc_contact_refresh_lookup_data() Fail(%d)", ret);
1121 contacts_record_destroy((contacts_record_h)contact, true);
1122 ctsvc_end_trans(false);
1127 contacts_record_destroy((contacts_record_h)contact, true);
1129 ret = ctsvc_end_trans(true);
1130 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_end_trans() Fail(%d)", ret);
1132 return CONTACTS_ERROR_NONE;
1135 static bool __ctsvc_list_check_dirty(ctsvc_list_s *list)
1138 if (list->deleted_records) {
1142 for (c=list->records;c;c=c->next) {
1143 ctsvc_record_s *s_record = c->data;
1145 unsigned int property_info_count = 0;
1146 const property_info_s *property_info = ctsvc_view_get_all_property_infos(s_record->view_uri, &property_info_count);
1147 for (i=0;i<property_info_count;i++) {
1148 if (ctsvc_record_check_property_flag(s_record, property_info[i].property_id, CTSVC_PROPERTY_FLAG_DIRTY)) {
1157 static bool __ctsvc_get_need_refresh_lookup_data(ctsvc_contact_s *contact)
1159 if (__ctsvc_list_check_dirty(contact->name))
1161 if (__ctsvc_list_check_dirty(contact->numbers))
1163 if (__ctsvc_list_check_dirty(contact->nicknames))
1168 static int __ctsvc_db_contact_update_record(contacts_record_h record)
1171 int rel_changed = 0;
1174 char query[CTS_SQL_MAX_LEN] = {0};
1175 GSList *bind_text = NULL;
1176 GSList *cursor = NULL;
1177 ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
1178 bool is_invalid = false;
1179 int current_version = 0;
1181 ret = ctsvc_begin_trans();
1182 RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
1184 snprintf(query, sizeof(query),
1185 "SELECT changed_ver FROM "CTS_TABLE_CONTACTS" "
1186 "WHERE contact_id = %d AND deleted = 0", contact->id);
1187 ret = ctsvc_query_get_first_int_result(query, ¤t_version);
1188 if (CONTACTS_ERROR_NONE != ret) {
1189 CTS_ERR("The index(%d) is Invalid. %d Record(s) is(are) found", contact->id, ret);
1190 ctsvc_end_trans(false);
1194 if (false == ctsvc_have_ab_write_permission(contact->addressbook_id)) {
1195 CTS_ERR("Does not have permission to update this contact");
1196 ctsvc_end_trans(false);
1197 return CONTACTS_ERROR_PERMISSION_DENIED;
1200 if (current_version != contact->changed_ver)
1202 __ctsvc_contact_check_default_data(contact);
1204 /* check lookup data is dirty */
1205 bool need_update_lookup = __ctsvc_get_need_refresh_lookup_data(contact);
1208 ret = __ctsvc_contact_update_data(contact);
1209 if (CONTACTS_ERROR_NONE != ret) {
1210 CTS_ERR("__ctsvc_contact_update_data() Fail(%d)", ret);
1211 ctsvc_end_trans(false);
1215 if (contact->grouprelations) {
1216 rel_changed = __ctsvc_contact_update_grouprel(contact->id, (contacts_list_h)contact->grouprelations);
1217 if (rel_changed < CONTACTS_ERROR_NONE) {
1218 CTS_ERR("cts_update_contact_grouprel() Fail(%d)", rel_changed);
1219 ctsvc_end_trans(false);
1225 if (contact->images) {
1226 int ret = CONTACTS_ERROR_NONE;
1228 ctsvc_image_s *image;
1230 contacts_list_get_count((contacts_list_h)contact->images, &count);
1232 contacts_list_first((contacts_list_h)contact->images);
1234 ret = contacts_list_get_current_record_p((contacts_list_h)contact->images, (contacts_record_h*)&image);
1235 if (CONTACTS_ERROR_NONE != ret) {
1236 CTS_ERR("contacts_list_get_current_record_p() Fail(%d)", ret);
1237 ctsvc_end_trans(false);
1238 return CONTACTS_ERROR_DB;
1241 if (image->is_default)
1243 } while (CONTACTS_ERROR_NONE == contacts_list_next((contacts_list_h)contact->images));
1245 if ((NULL == contact->image_thumbnail_path && image->path) ||
1246 (contact->image_thumbnail_path && NULL == image->path) ||
1247 (contact->image_thumbnail_path && image->path && (STRING_EQUAL != strcmp(contact->image_thumbnail_path, image->path)))) {
1248 ctsvc_record_set_property_flag((ctsvc_record_s *)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
1250 if (ctsvc_contact_check_image_location(image->path))
1251 contact->image_thumbnail_path = SAFE_STRDUP(image->path + strlen(CTSVC_CONTACT_IMG_FULL_LOCATION) + 1);
1253 contact->image_thumbnail_path = SAFE_STRDUP(image->path);
1256 else if (contact->image_thumbnail_path) {
1257 free(contact->image_thumbnail_path);
1258 contact->image_thumbnail_path = NULL;
1259 bool is_changed = ctsvc_record_check_property_flag((ctsvc_record_s *)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
1260 if ((false == is_changed && false == is_invalid) || (is_changed && false == is_invalid)) {
1261 ctsvc_record_set_property_flag((ctsvc_record_s *)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
1264 if (((ctsvc_record_s *)record)->properties_flags) {
1265 int index = _contacts_contact.image_thumbnail_path & 0x000000FF;
1266 ((ctsvc_record_s *)record)->properties_flags[index] = 0;
1273 ctsvc_contact_s* temp_contact;
1274 contacts_record_create(_contacts_contact._uri, (contacts_record_h*)&temp_contact);
1275 ret = __ctsvc_db_get_data(contact->id, temp_contact);
1276 ctsvc_contact_make_display_name(temp_contact);
1278 FREEandSTRDUP(contact->display_name, temp_contact->display_name);
1279 FREEandSTRDUP(contact->reverse_display_name, temp_contact->reverse_display_name);
1280 FREEandSTRDUP(contact->sort_name, temp_contact->sort_name);
1281 FREEandSTRDUP(contact->reverse_sort_name, temp_contact->reverse_sort_name);
1282 FREEandSTRDUP(contact->sortkey, temp_contact->sortkey);
1283 FREEandSTRDUP(contact->reverse_sortkey, temp_contact->reverse_sortkey);
1285 contact->display_name_language = temp_contact->display_name_language;
1286 contact->reverse_display_name_language = temp_contact->reverse_display_name_language;
1287 contact->display_source_type = temp_contact->display_source_type;
1289 if (ctsvc_record_check_property_flag((ctsvc_record_s *)temp_contact, _contacts_contact.display_name, CTSVC_PROPERTY_FLAG_DIRTY))
1290 ctsvc_record_set_property_flag((ctsvc_record_s *)contact, _contacts_contact.display_name, CTSVC_PROPERTY_FLAG_DIRTY);
1292 contacts_record_destroy((contacts_record_h)temp_contact, true);
1295 ctsvc_contact_make_display_name(contact);
1298 char query[CTS_SQL_MAX_LEN] = {0};
1299 char query_set[CTS_SQL_MIN_LEN] = {0, };
1300 cts_stmt stmt = NULL;
1302 version = ctsvc_get_next_ver();
1304 ret = ctsvc_db_create_set_query(record, &set, &bind_text);
1305 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_db_create_set_query() Fail(%d)", ret);
1308 len = snprintf(query_set, sizeof(query_set), "%s, ", set);
1309 len += snprintf(query_set+len, sizeof(query_set)-len, " changed_ver=%d, changed_time=%d, has_phonenumber=%d, has_email=%d",
1310 version, (int)time(NULL), contact->has_phonenumber, contact->has_email);
1311 if (ctsvc_record_check_property_flag((ctsvc_record_s *)contact, _contacts_contact.display_name, CTSVC_PROPERTY_FLAG_DIRTY)) {
1312 len += snprintf(query_set+len, sizeof(query_set)-len,
1313 ", display_name=?, reverse_display_name=?, display_name_source=%d, "
1314 "display_name_language=%d, reverse_display_name_language=%d, "
1315 "sort_name=?, reverse_sort_name=?, sortkey=?, reverse_sortkey=?",
1316 contact->display_source_type, contact->display_name_language, contact->reverse_display_name_language);
1317 bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->display_name)));
1318 bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->reverse_display_name)));
1319 bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->sort_name)));
1320 bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->reverse_sort_name)));
1321 bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->sortkey)));
1322 bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->reverse_sortkey)));
1325 if (ctsvc_record_check_property_flag((ctsvc_record_s *)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY))
1326 len += snprintf(query_set+len, sizeof(query_set)-len, ", image_changed_ver=%d", version);
1328 snprintf(query, sizeof(query), "UPDATE %s SET %s WHERE contact_id = %d", CTS_TABLE_CONTACTS, query_set, contact->id);
1330 ret = ctsvc_query_prepare(query, &stmt);
1332 CTS_ERR("DB error : ctsvc_query_prepare() Fail(%d)", ret);
1338 for (cursor=bind_text,i=1;cursor;cursor=cursor->next,i++) {
1339 const char *text = cursor->data;
1341 ctsvc_stmt_bind_text(stmt, i, text);
1344 ret = ctsvc_stmt_step(stmt);
1345 if (CONTACTS_ERROR_NONE != ret) {
1346 CTS_ERR("ctsvc_stmt_step() Fail(%d)", ret);
1347 ctsvc_stmt_finalize(stmt);
1350 ctsvc_stmt_finalize(stmt);
1353 if (CONTACTS_ERROR_NONE != ret) {
1354 ctsvc_end_trans(false);
1355 CTSVC_RECORD_RESET_PROPERTY_FLAGS((ctsvc_record_s *)record);
1358 for (cursor=bind_text;cursor;cursor=cursor->next)
1359 CONTACTS_FREE(cursor->data);
1360 g_slist_free(bind_text);
1365 ctsvc_set_contact_noti();
1366 if (0 < rel_changed)
1367 ctsvc_set_group_rel_noti();
1369 __ctsvc_contact_update_search_data(contact->id, need_update_lookup);
1370 ctsvc_db_update_person((contacts_record_h)contact);
1372 CTSVC_RECORD_RESET_PROPERTY_FLAGS((ctsvc_record_s *)record);
1375 for (cursor=bind_text;cursor;cursor=cursor->next)
1376 CONTACTS_FREE(cursor->data);
1377 g_slist_free(bind_text);
1380 ret = ctsvc_end_trans(true);
1381 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "DB error : ctsvc_end_trans() Fail(%d)", ret);
1383 return CONTACTS_ERROR_NONE;
1386 static int __ctsvc_db_contact_get_all_records(int offset, int limit, contacts_list_h* out_list)
1392 char query[CTS_SQL_MAX_LEN] = {0};
1393 contacts_list_h list;
1395 len = snprintf(query, sizeof(query),
1396 "SELECT contact_id FROM "CTS_TABLE_CONTACTS" WHERE deleted = 0");
1399 len += snprintf(query+len, sizeof(query)-len, " LIMIT %d", limit);
1401 len += snprintf(query+len, sizeof(query)-len, " OFFSET %d", offset);
1404 ret = ctsvc_query_prepare(query, &stmt);
1405 RETVM_IF(NULL == stmt, ret, "DB error : ctsvc_query_prepare() Fail(%d)", ret);
1407 contacts_list_create(&list);
1408 while ((ret = ctsvc_stmt_step(stmt))) {
1409 contacts_record_h record;
1411 CTS_ERR("DB error : ctsvc_stmt_step() Fail(%d)", ret);
1412 ctsvc_stmt_finalize(stmt);
1413 contacts_list_destroy(list, true);
1416 contact_id = ctsvc_stmt_get_int(stmt, 0);
1417 ret = ctsvc_db_contact_get(contact_id, &record);
1418 if (CONTACTS_ERROR_NONE != ret) {
1419 CTS_ERR("DB error : ctsvc_db_contact_get() Fail(%d)", ret);
1420 ctsvc_stmt_finalize(stmt);
1421 contacts_list_destroy(list, true);
1424 ctsvc_list_prepend(list, record);
1426 ctsvc_stmt_finalize(stmt);
1427 ctsvc_list_reverse(list);
1429 *out_list = (contacts_list_h)list;
1430 return CONTACTS_ERROR_NONE;
1433 static int __ctsvc_db_contact_get_changed_ver(int contact_id, ctsvc_contact_s *contact)
1437 char query[CTS_SQL_MAX_LEN] = {0};
1439 snprintf(query, sizeof(query),
1440 "SELECT changed_ver FROM "CTS_TABLE_CONTACTS
1441 " WHERE contact_id = %d AND deleted = 0", contact_id);
1442 ret = ctsvc_query_get_first_int_result(query, &version);
1443 if (CONTACTS_ERROR_NONE == ret)
1444 contact->changed_ver = version;
1448 static int __ctsvc_db_contact_get_records_with_query(contacts_query_h query, int offset, int limit, contacts_list_h* out_list)
1453 ctsvc_query_s *s_query;
1455 contacts_list_h list;
1456 ctsvc_contact_s *contact;
1457 char full_path[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
1458 bool had_contact_id = false;
1461 RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
1462 s_query = (ctsvc_query_s *)query;
1464 if (s_query->projection) {
1465 for (i=0;i<s_query->projection_count;i++) {
1466 if (s_query->projection[i] == CTSVC_PROPERTY_CONTACT_ID) {
1467 had_contact_id = true;
1473 s_query->projection_count = 0;
1474 had_contact_id = true;
1477 if (false == had_contact_id) {
1478 s_query->projection = realloc(s_query->projection, s_query->projection_count+1);
1479 if (NULL == s_query->projection) {
1480 CTS_ERR("realloc() Fail");
1481 return CONTACTS_ERROR_OUT_OF_MEMORY;
1484 s_query->projection[s_query->projection_count] = CTSVC_PROPERTY_CONTACT_ID;
1485 s_query->projection_count++;
1488 ret = ctsvc_db_make_get_records_query_stmt(s_query, offset, limit, &stmt);
1489 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_db_make_get_records_query_stmt fail(%d)", ret);
1491 contacts_list_create(&list);
1492 while ((ret = ctsvc_stmt_step(stmt))) {
1493 contacts_record_h record;
1495 CTS_ERR("DB error : ctsvc_stmt_step() Fail(%d)", ret);
1496 ctsvc_stmt_finalize(stmt);
1497 contacts_list_destroy(list, true);
1501 contacts_record_create(_contacts_contact._uri, &record);
1502 contact = (ctsvc_contact_s*)record;
1503 if (0 == s_query->projection_count)
1504 field_count = s_query->property_count;
1506 field_count = s_query->projection_count;
1507 ret = ctsvc_record_set_projection_flags(record, s_query->projection,
1508 s_query->projection_count, s_query->property_count);
1510 if (CONTACTS_ERROR_NONE != ret)
1511 ASSERT_NOT_REACHED("To set projection is failed.\n");
1514 for (i=0;i<field_count;i++) {
1517 if (0 == s_query->projection_count)
1518 property_id = s_query->properties[i].property_id;
1520 property_id = s_query->projection[i];
1522 switch(property_id) {
1523 case CTSVC_PROPERTY_CONTACT_ID:
1524 contact_id = ctsvc_stmt_get_int(stmt, i);
1526 contact->id = contact_id;
1528 case CTSVC_PROPERTY_CONTACT_DISPLAY_NAME:
1529 temp = ctsvc_stmt_get_text(stmt, i);
1530 free(contact->display_name);
1531 contact->display_name = SAFE_STRDUP(temp);
1533 case CTSVC_PROPERTY_CONTACT_DISPLAY_SOURCE_DATA_ID:
1534 contact->display_source_type = ctsvc_stmt_get_int(stmt, i);
1536 case CTSVC_PROPERTY_CONTACT_ADDRESSBOOK_ID:
1537 contact->addressbook_id = ctsvc_stmt_get_int(stmt, i);
1539 case CTSVC_PROPERTY_CONTACT_RINGTONE:
1540 temp = ctsvc_stmt_get_text(stmt, i);
1541 free(contact->ringtone_path);
1542 contact->ringtone_path = SAFE_STRDUP(temp);
1544 case CTSVC_PROPERTY_CONTACT_IMAGE_THUMBNAIL:
1545 temp = ctsvc_stmt_get_text(stmt, i);
1546 if (temp && *temp) {
1547 snprintf(full_path, sizeof(full_path), "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, temp);
1548 free(contact->image_thumbnail_path);
1549 contact->image_thumbnail_path = strdup(full_path);
1552 case CTSVC_PROPERTY_CONTACT_IS_FAVORITE:
1553 contact->is_favorite = ctsvc_stmt_get_int(stmt, i);
1555 case CTSVC_PROPERTY_CONTACT_HAS_PHONENUMBER:
1556 contact->has_phonenumber = ctsvc_stmt_get_int(stmt, i);
1558 case CTSVC_PROPERTY_CONTACT_HAS_EMAIL:
1559 contact->has_email = ctsvc_stmt_get_int(stmt, i);
1561 case CTSVC_PROPERTY_CONTACT_PERSON_ID:
1562 contact->person_id = ctsvc_stmt_get_int(stmt, i);
1564 case CTSVC_PROPERTY_CONTACT_UID:
1565 temp = ctsvc_stmt_get_text(stmt, i);
1567 contact->uid = SAFE_STRDUP(temp);
1569 case CTSVC_PROPERTY_CONTACT_VIBRATION:
1570 temp = ctsvc_stmt_get_text(stmt, i);
1571 free(contact->vibration);
1572 contact->vibration = SAFE_STRDUP(temp);
1574 case CTSVC_PROPERTY_CONTACT_MESSAGE_ALERT:
1575 temp = ctsvc_stmt_get_text(stmt, i);
1576 free(contact->message_alert);
1577 contact->message_alert = SAFE_STRDUP(temp);
1579 case CTSVC_PROPERTY_CONTACT_CHANGED_TIME:
1580 contact->changed_time = ctsvc_stmt_get_int(stmt, i);
1582 case CTSVC_PROPERTY_CONTACT_LINK_MODE:
1583 contact->link_mode = ctsvc_stmt_get_int(stmt, i);
1589 /* get changed_ver */
1590 ret = __ctsvc_db_contact_get_changed_ver(contact_id, contact);
1591 if (CONTACTS_ERROR_NONE != ret) {
1592 CTS_ERR("__ctsvc_db_contact_get_changed_ver Fail(%d)", ret);
1593 ctsvc_stmt_finalize(stmt);
1594 contacts_list_destroy(list, true);
1598 ret = __ctsvc_db_get_data(contact_id, contact);
1599 if (CONTACTS_ERROR_NONE != ret && CONTACTS_ERROR_NO_DATA != ret) {
1600 CTS_ERR("ctsvc_get_data_info Fail(%d)", ret);
1601 ctsvc_stmt_finalize(stmt);
1602 contacts_list_destroy(list, true);
1606 ret = __ctsvc_get_contact_grouprel(contact_id, contact);
1607 if (CONTACTS_ERROR_NONE != ret) {
1608 CTS_ERR("ctsvc_get_group_relations Fail(%d)", ret);
1609 ctsvc_stmt_finalize(stmt);
1610 contacts_list_destroy(list, true);
1614 ctsvc_list_prepend(list, record);
1616 ctsvc_stmt_finalize(stmt);
1617 ctsvc_list_reverse(list);
1619 *out_list = (contacts_list_h)list;
1621 return CONTACTS_ERROR_NONE;
1625 static int __ctsvc_contact_insert_data(ctsvc_contact_s *contact)
1629 /* Insert the name */
1630 if (contact->name) {
1631 ret = ctsvc_contact_insert_data_name((contacts_list_h)contact->name, contact->id, false);
1632 if (CONTACTS_ERROR_NONE != ret) {
1633 CTS_ERR("ctsvc_contact_insert_data_name() Fail(%d)", ret);
1638 /* Insert the company */
1639 if (contact->company) {
1640 ret = ctsvc_contact_insert_data_company((contacts_list_h)contact->company, contact->id, false);
1641 if (CONTACTS_ERROR_NONE != ret) {
1642 CTS_ERR("ctsvc_insert_contact_data_company() Fail(%d)", ret);
1647 /* Insert the events */
1648 if (contact->events) {
1649 ret = ctsvc_contact_insert_data_event((contacts_list_h)contact->events, contact->id, false);
1650 if (CONTACTS_ERROR_NONE != ret) {
1651 CTS_ERR("ctsvc_insert_contact_data_event() Fail(%d)", ret);
1656 /* Insert the messengers */
1657 if (contact->messengers) {
1658 ret = ctsvc_contact_insert_data_messenger((contacts_list_h)contact->messengers, contact->id, false);
1659 if (CONTACTS_ERROR_NONE != ret) {
1660 CTS_ERR("ctsvc_insert_contact_data_messenger() Fail(%d)", ret);
1665 /* Insert the postals */
1666 if (contact->postal_addrs) {
1667 ret = ctsvc_contact_insert_data_address((contacts_list_h)contact->postal_addrs, contact->id, false);
1668 if (CONTACTS_ERROR_NONE != ret) {
1669 CTS_ERR("ctsvc_insert_contact_data_postal() Fail(%d)", ret);
1674 /* Insert the Web addrs */
1675 if (contact->urls) {
1676 ret = ctsvc_contact_insert_data_url((contacts_list_h)contact->urls, contact->id, false);
1677 if (CONTACTS_ERROR_NONE != ret) {
1678 CTS_ERR("ctsvc_insert_contact_data_web() Fail(%d)", ret);
1683 /* Insert the Nick names */
1684 if (contact->nicknames) {
1685 ret = ctsvc_contact_insert_data_nickname((contacts_list_h)contact->nicknames, contact->id, false);
1686 if (CONTACTS_ERROR_NONE != ret) {
1687 CTS_ERR("ctsvc_insert_contact_data_nickname() Fail(%d)", ret);
1692 /* Insert the numbers */
1693 if (contact->numbers) {
1694 ret = ctsvc_contact_insert_data_number((contacts_list_h)contact->numbers, contact->id, false);
1695 if (ret < CONTACTS_ERROR_NONE) {
1696 CTS_ERR("ctsvc_contact_insert_data_number() Fail(%d)", ret);
1701 /* Insert the emails */
1702 if (contact->emails) {
1703 ret = ctsvc_contact_insert_data_email((contacts_list_h)contact->emails, contact->id, false);
1704 if (ret < CONTACTS_ERROR_NONE) {
1705 CTS_ERR("ctsvc_insert_contact_data_email() Fail(%d)", ret);
1710 /* Insert the profile values */
1711 if (contact->profiles) {
1712 ret = ctsvc_contact_insert_data_profile((contacts_list_h)contact->profiles, contact->id, false);
1713 if (CONTACTS_ERROR_NONE != ret) {
1714 CTS_ERR("ctsvc_insert_contact_data_profile() Fail(%d)", ret);
1719 /* Insert the relationship values */
1720 if (contact->relationships) {
1721 ret = ctsvc_contact_insert_data_relationship((contacts_list_h)contact->relationships, contact->id, false);
1722 if (CONTACTS_ERROR_NONE != ret) {
1723 CTS_ERR("ctsvc_contact_insert_data_relationship() Fail(%d)", ret);
1728 /* Insert the image values */
1729 if (contact->images) {
1730 ret = ctsvc_contact_insert_data_image((contacts_list_h)contact->images, contact->id, false);
1731 if (CONTACTS_ERROR_NONE != ret) {
1732 CTS_ERR("ctsvc_contact_insert_data_image() Fail(%d)", ret);
1737 /* Insert the note values */
1738 if (contact->note) {
1739 ret = ctsvc_contact_insert_data_note((contacts_list_h)contact->note, contact->id, false);
1740 if (CONTACTS_ERROR_NONE != ret) {
1741 CTS_ERR("ctsvc_contact_insert_data_note() Fail(%d)", ret);
1746 /* Insert the extensions values */
1747 if (contact->extensions) {
1748 ret = ctsvc_contact_insert_data_extension((contacts_list_h)contact->extensions, contact->id, false);
1749 if (CONTACTS_ERROR_NONE != ret) {
1750 CTS_ERR("ctsvc_contact_insert_data_extension() Fail(%d)", ret);
1755 return CONTACTS_ERROR_NONE;
1758 static inline int __ctsvc_contact_insert_search_data(int contact_id, bool need_insert_lookup_data)
1761 cts_stmt stmt = NULL;
1762 char query[CTS_SQL_MAX_LEN] = {0};
1763 char *search_name = NULL;
1764 char *search_number = NULL;
1765 char *search_data = NULL;
1766 ctsvc_contact_s *contact = NULL;
1768 ret = ctsvc_begin_trans();
1769 RETVM_IF(ret, ret, "contacts_begin_trans() Fail(%d)", ret);
1771 ret = ctsvc_db_contact_get(contact_id, (contacts_record_h*)&contact);
1772 if (CONTACTS_ERROR_NONE != ret) {
1773 CTS_ERR("ctsvc_db_contact_get() Fail(%d)", ret);
1774 ctsvc_end_trans(false);
1778 ret = ctsvc_contact_make_search_name(contact, &search_name);
1779 if (CONTACTS_ERROR_NONE != ret) {
1780 CTS_ERR("ctsvc_contact_make_search_name() Fail(%d)", ret);
1781 contacts_record_destroy((contacts_record_h)contact, true);
1782 ctsvc_end_trans(false);
1786 ret = __ctsvc_contact_make_search_data(contact, &search_number, &search_data);
1787 if (CONTACTS_ERROR_NONE != ret) {
1788 CTS_ERR("__ctsvc_contact_make_search_data() Fail(%d)", ret);
1789 contacts_record_destroy((contacts_record_h)contact, true);
1790 ctsvc_end_trans(false);
1795 snprintf(query, sizeof(query),
1796 "INSERT INTO %s(contact_id, name, number, data) "
1797 "VALUES(%d, ?, ?, ?)",
1798 CTS_TABLE_SEARCH_INDEX, contact_id);
1800 ret = ctsvc_query_prepare(query, &stmt);
1802 CTS_ERR("ctsvc_query_prepare() Fail(%d)", ret);
1803 contacts_record_destroy((contacts_record_h)contact, true);
1804 ctsvc_end_trans(false);
1806 free(search_number);
1812 ctsvc_stmt_bind_text(stmt, 1, search_name);
1814 ctsvc_stmt_bind_text(stmt, 2, search_number);
1816 ctsvc_stmt_bind_text(stmt, 3, search_data);
1818 ret = ctsvc_stmt_step(stmt);
1821 free(search_number);
1824 if (CONTACTS_ERROR_NONE != ret) {
1825 CTS_ERR("ctsvc_stmt_step() Fail(%d)", ret);
1826 contacts_record_destroy((contacts_record_h)contact, true);
1827 ctsvc_stmt_finalize(stmt);
1828 ctsvc_end_trans(false);
1831 ctsvc_stmt_finalize(stmt);
1833 /* update phone_lookup, name_lookup */
1834 if (need_insert_lookup_data) {
1835 ret = __ctsvc_contact_refresh_lookup_data(contact_id, contact);
1836 if (CONTACTS_ERROR_NONE != ret) {
1837 CTS_ERR("__ctsvc_contact_refresh_lookup_data() Fail(%d)", ret);
1838 contacts_record_destroy((contacts_record_h)contact, true);
1839 ctsvc_end_trans(false);
1844 contacts_record_destroy((contacts_record_h)contact, true);
1846 ret = ctsvc_end_trans(true);
1847 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_end_trans() Fail(%d)", ret);
1849 return CONTACTS_ERROR_NONE;
1852 static inline int __ctsvc_contact_insert_grouprel(int contact_id, contacts_list_h group_list)
1855 ctsvc_group_relation_s *grouprel;
1856 int rel_changed = 0;
1860 RETV_IF(NULL == group_list, CONTACTS_ERROR_INVALID_PARAMETER);
1861 ret = contacts_list_get_count(group_list, &count);
1863 return CONTACTS_ERROR_NONE;
1865 contacts_list_first(group_list);
1867 contacts_list_get_current_record_p(group_list, (contacts_record_h*)&grouprel);
1868 if (NULL == grouprel)
1871 RETVM_IF(grouprel->group_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER, "group_id(%d) invalid", grouprel->group_id);
1872 if (grouprel->group_id) {
1873 ret = ctsvc_group_add_contact_in_transaction(grouprel->group_id, contact_id);
1874 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_db_group_set_relation() Fail(%d)", ret);
1878 } while (CONTACTS_ERROR_NONE == contacts_list_next(group_list));
1883 return CONTACTS_ERROR_NONE;
1886 inline static int __ctsvc_find_person_to_link_with_number(const char *number, int addressbook_id, int *person_id)
1889 cts_stmt stmt = NULL;
1890 char query[CTS_SQL_MIN_LEN] = {0};
1891 int number_len = SAFE_STRLEN(number);
1892 char clean_num[number_len+1];
1894 ret = ctsvc_clean_number(number, clean_num, sizeof(clean_num), true);
1896 char normal_num[sizeof(clean_num)+20];
1897 ret = ctsvc_normalize_number(clean_num, normal_num, sizeof(normal_num), true);
1898 char minmatch[sizeof(normal_num)+1];
1900 ret = ctsvc_get_minmatch_number(normal_num, minmatch, sizeof(minmatch), ctsvc_get_phonenumber_min_match_digit());
1902 snprintf(query, sizeof(query),
1903 "SELECT C.person_id FROM "CTS_TABLE_CONTACTS" C, "CTS_TABLE_DATA" D "
1904 "ON C.contact_id=D.contact_id AND D.datatype=%d AND C.deleted = 0 "
1905 "AND C.addressbook_id <> %d AND D.is_my_profile = 0 "
1906 "WHERE D.data4 = ?",
1907 /* Below condition takes long time, so omit the condition */
1908 /* AND _NUMBER_COMPARE_(D.data5, ?, NULL, NULL) */
1909 CTSVC_DATA_NUMBER, addressbook_id);
1911 ret = ctsvc_query_prepare(query, &stmt);
1912 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare fail(%d)", ret);
1913 ctsvc_stmt_bind_text(stmt, 1, minmatch);
1914 /* ctsvc_stmt_bind_text(stmt, 2, normal_num); */
1915 ret = ctsvc_stmt_step(stmt);
1917 *person_id = ctsvc_stmt_get_int(stmt, 0);
1918 ret = CONTACTS_ERROR_NONE;
1920 else if (CONTACTS_ERROR_NONE == ret) {
1921 ret = CONTACTS_ERROR_NO_DATA;
1923 ctsvc_stmt_finalize(stmt);
1924 CTS_DBG("result ret(%d) person_id(%d)", ret, *person_id);
1928 return CONTACTS_ERROR_INVALID_PARAMETER;
1931 inline static int __ctsvc_find_person_to_link_with_email(const char *email_addr, int addressbook_id, int *person_id)
1934 cts_stmt stmt = NULL;
1935 char query[CTS_SQL_MIN_LEN] = {0};
1937 snprintf(query, sizeof(query),
1938 "SELECT C.person_id FROM "CTS_TABLE_CONTACTS" C, "CTS_TABLE_DATA" D "
1939 "ON C.contact_id=D.contact_id AND D.datatype=%d AND C.deleted = 0 AND D.is_my_profile = 0 "
1940 "AND C.addressbook_id <> %d "
1941 "WHERE D.data3 = ?",
1942 CTSVC_DATA_EMAIL, addressbook_id);
1944 ret = ctsvc_query_prepare(query, &stmt);
1945 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare fail(%d)", ret);
1947 ctsvc_stmt_bind_text(stmt, 1, email_addr);
1948 ret = ctsvc_stmt_step(stmt);
1950 *person_id = ctsvc_stmt_get_int(stmt, 0);
1951 ret = CONTACTS_ERROR_NONE;
1953 else if (CONTACTS_ERROR_NONE == ret) {
1954 ret = CONTACTS_ERROR_NO_DATA;
1957 ctsvc_stmt_finalize(stmt);
1958 CTS_DBG("result ret(%d) person_id(%d)", ret, *person_id);
1963 inline static int __ctsvc_find_person_to_link(contacts_record_h record, int addressbook_id, int *person_id)
1966 ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
1967 ctsvc_number_s *number_data;
1968 ctsvc_email_s *email_data;
1971 for (cursor = contact->numbers->records;cursor;cursor=cursor->next) {
1972 number_data = (ctsvc_number_s *)cursor->data;
1973 if (number_data && number_data->number && number_data->number[0]) {
1974 ret = __ctsvc_find_person_to_link_with_number(number_data->number, addressbook_id, person_id);
1976 if (ret == CONTACTS_ERROR_NONE && 0 < *person_id)
1981 for (cursor = contact->emails->records;cursor;cursor=cursor->next) {
1982 email_data = (ctsvc_email_s *)cursor->data;
1983 if (email_data && email_data->email_addr && email_data->email_addr[0]) {
1984 ret = __ctsvc_find_person_to_link_with_email(email_data->email_addr, addressbook_id, person_id);
1986 if (ret == CONTACTS_ERROR_NONE && 0 < *person_id)
1991 return CONTACTS_ERROR_NO_DATA;
1994 static int __ctsvc_db_contact_insert_record(contacts_record_h record, int *id)
1997 int ret, person_id = 0;
1998 char query[CTS_SQL_MAX_LEN] = {0};
1999 bool auto_link_enabled = true;
2000 bool auto_linked = false;
2002 ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
2003 int rel_changed = 0;
2004 cts_stmt stmt = NULL;
2006 /* These check should be done in client side */
2007 RETVM_IF(NULL == contact, CONTACTS_ERROR_INVALID_PARAMETER,
2008 "Invalid parameter : contact is NULL");
2009 RETVM_IF(contact->addressbook_id < 0, CONTACTS_ERROR_INVALID_PARAMETER,
2010 "Invalid parameter : addressbook_id(%d) is mandatory field to insert contact record ", contact->addressbook_id);
2011 RETVM_IF(0 < contact->id, CONTACTS_ERROR_INVALID_PARAMETER,
2012 "Invalid parameter : id(%d), This record is already inserted", contact->id);
2014 if (contact->link_mode == CONTACTS_CONTACT_LINK_MODE_IGNORE_ONCE)
2015 auto_link_enabled = false;
2017 ret = ctsvc_begin_trans();
2018 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_begin_trans() Fail(%d)", ret);
2020 if (false == ctsvc_have_ab_write_permission(contact->addressbook_id)) {
2021 CTS_ERR("ctsvc_have_ab_write_permission fail : does not have permission(addressbook_id : %d)",
2022 contact->addressbook_id);
2023 ctsvc_end_trans(false);
2024 return CONTACTS_ERROR_PERMISSION_DENIED;
2027 ret = ctsvc_db_get_next_id(CTS_TABLE_CONTACTS);
2028 if (ret < CONTACTS_ERROR_NONE) {
2029 CTS_ERR("ctsvc_db_get_next_id() Fail(%d)", ret);
2030 ctsvc_end_trans(false);
2037 ctsvc_contact_make_display_name(contact);
2038 __ctsvc_contact_check_default_data(contact);
2040 /* check lookup data is dirty */
2041 bool need_insert_lookup = __ctsvc_get_need_refresh_lookup_data(contact);
2044 ret = __ctsvc_contact_insert_data(contact);
2045 if (CONTACTS_ERROR_NONE != ret) {
2046 CTS_ERR("cts_insert_contact_data() Fail(%d)", ret);
2047 ctsvc_end_trans(false);
2052 free(contact->image_thumbnail_path);
2053 contact->image_thumbnail_path = NULL;
2054 if (contact->images) {
2055 ctsvc_image_s *image;
2057 contacts_list_first((contacts_list_h)contact->images);
2059 ret = contacts_list_get_current_record_p((contacts_list_h)contact->images, (contacts_record_h*)&image);
2060 if (CONTACTS_ERROR_NONE != ret) {
2061 CTS_ERR("contacts_list_get_current_record_p() Fail(%d)", ret);
2062 ctsvc_end_trans(false);
2063 return CONTACTS_ERROR_DB;
2066 if (image->path && image->is_default) {
2067 contact->image_thumbnail_path = strdup(image->path);
2070 } while (CONTACTS_ERROR_NONE == contacts_list_next((contacts_list_h)contact->images));
2073 version = ctsvc_get_next_ver();
2075 if (contact->person_id) {
2078 snprintf(query,sizeof(query),
2079 "SELECT contact_id FROM "CTSVC_DB_VIEW_CONTACT" "
2080 "WHERE person_id = %d", contact->person_id);
2081 ret = ctsvc_query_get_first_int_result(query, &id);
2082 if (CONTACTS_ERROR_NONE != ret) {
2083 CTS_ERR("Invalid person_id(%d)", contact->person_id);
2084 ctsvc_end_trans(false);
2085 return CONTACTS_ERROR_INVALID_PARAMETER;
2090 else if (auto_link_enabled) {
2091 ret = __ctsvc_find_person_to_link((contacts_record_h)contact, contact->addressbook_id, &person_id);
2092 CTS_DBG("__ctsvc_find_person_to_link return %d, person_id(%d)", ret, person_id);
2093 if (ret == CONTACTS_ERROR_NONE && 0 < person_id) {
2094 contact->person_id = person_id;
2098 ret = ctsvc_db_insert_person((contacts_record_h)contact);
2099 CTS_DBG("ctsvc_db_insert_person return %d, person_id(%d)", ret, ret);
2100 if (ret < CONTACTS_ERROR_NONE) {
2101 CTS_ERR("ctsvc_db_insert_person() Fail(%d)", ret);
2102 ctsvc_end_trans(false);
2105 contact->person_id = ret;
2109 ret = ctsvc_db_insert_person((contacts_record_h)contact);
2110 CTS_DBG("ctsvc_db_insert_person return %d, person_id(%d)", ret, ret);
2111 if (ret < CONTACTS_ERROR_NONE) {
2112 CTS_ERR("ctsvc_db_insert_person() Fail(%d)", ret);
2113 ctsvc_end_trans(false);
2116 contact->person_id = ret;
2119 snprintf(query, sizeof(query),
2120 "INSERT INTO "CTS_TABLE_CONTACTS"(contact_id, person_id, addressbook_id, is_favorite, "
2121 "created_ver, changed_ver, changed_time, link_mode, "
2122 "image_changed_ver, has_phonenumber, has_email, "
2123 "display_name, reverse_display_name, display_name_source, "
2124 "display_name_language, reverse_display_name_language, "
2125 "sort_name, reverse_sort_name, "
2126 "sortkey, reverse_sortkey, "
2127 "uid, ringtone_path, vibration, message_alert, image_thumbnail_path) "
2128 "VALUES(%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, ?, ?, %d, %d, %d, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
2129 contact->id, contact->person_id, contact->addressbook_id, contact->is_favorite,
2130 version, version, (int)time(NULL), contact->link_mode,
2131 (contact->image_thumbnail_path)?version:0, contact->has_phonenumber, contact->has_email,
2132 contact->display_source_type, contact->display_name_language, contact->reverse_display_name_language);
2134 ret = ctsvc_query_prepare(query, &stmt);
2136 CTS_ERR("ctsvc_query_prepare() Fail(%d)", ret);
2137 ctsvc_end_trans(false);
2141 if (contact->display_name)
2142 ctsvc_stmt_bind_text(stmt, 1, contact->display_name);
2143 if (contact->reverse_display_name)
2144 ctsvc_stmt_bind_text(stmt, 2, contact->reverse_display_name);
2145 if (contact->sort_name)
2146 ctsvc_stmt_bind_text(stmt, 3, contact->sort_name);
2147 if (contact->reverse_sort_name)
2148 ctsvc_stmt_bind_text(stmt, 4, contact->reverse_sort_name);
2149 if (contact->sortkey)
2150 ctsvc_stmt_bind_text(stmt, 5, contact->sortkey);
2151 if (contact->reverse_sortkey)
2152 ctsvc_stmt_bind_text(stmt, 6, contact->reverse_sortkey);
2154 ctsvc_stmt_bind_text(stmt, 7, contact->uid);
2155 if (contact->ringtone_path)
2156 ctsvc_stmt_bind_text(stmt, 8, contact->ringtone_path);
2157 if (contact->vibration)
2158 ctsvc_stmt_bind_text(stmt, 9, contact->vibration);
2159 if (contact->message_alert)
2160 ctsvc_stmt_bind_text(stmt, 10, contact->message_alert);
2161 if (contact->image_thumbnail_path)
2162 ctsvc_stmt_bind_text(stmt, 11, contact->image_thumbnail_path);
2164 ret = ctsvc_stmt_step(stmt);
2165 if (CONTACTS_ERROR_NONE != ret) {
2166 CTS_ERR("ctsvc_stmt_step() Fail(%d)", ret);
2167 ctsvc_stmt_finalize(stmt);
2168 ctsvc_end_trans(false);
2171 ctsvc_stmt_finalize(stmt);
2173 /* Insert group Info */
2174 if (contact->grouprelations) {
2175 rel_changed = __ctsvc_contact_insert_grouprel(contact->id, (contacts_list_h)contact->grouprelations);
2176 if (rel_changed < CONTACTS_ERROR_NONE) {
2177 CTS_ERR("__ctsvc_contact_insert_grouprel() Fail(%d)", rel_changed);
2178 ctsvc_end_trans(false);
2183 ret = __ctsvc_contact_insert_search_data(contact->id, need_insert_lookup);
2184 if (ret != CONTACTS_ERROR_NONE) {
2185 CTS_ERR("__ctsvc_contact_insert_search_data() Fail(%d)", ret);
2186 ctsvc_end_trans(false);
2190 /* person aggregation when auto_linked */
2192 ctsvc_person_aggregate(contact->person_id);
2194 #ifdef ENABLE_LOG_FEATURE
2195 /* update phonelog */
2196 if (contact->numbers) {
2198 ret = contacts_list_get_count((contacts_list_h)contact->numbers, &count);
2199 contacts_list_first((contacts_list_h)contact->numbers);
2201 ctsvc_number_s *number_record;
2203 contacts_list_get_current_record_p((contacts_list_h)contact->numbers, (contacts_record_h*)&number_record);
2204 if (number_record->number)
2205 ctsvc_db_phone_log_update_person_id(number_record->number, -1, contact->person_id, false);
2206 } while(CONTACTS_ERROR_NONE == contacts_list_next((contacts_list_h)contact->numbers));
2209 #endif /* ENABLE_LOG_FEATURE */
2211 ctsvc_set_group_rel_noti();
2212 ctsvc_set_contact_noti();
2214 ret = ctsvc_end_trans(true);
2215 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_svc_end_trans() Fail(%d)", ret);
2217 return CONTACTS_ERROR_NONE;
2220 static int __ctsvc_db_contact_replace_record(contacts_record_h record, int contact_id)
2224 int rel_changed = 0;
2227 char query[CTS_SQL_MAX_LEN] = {0};
2228 ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
2229 cts_stmt stmt = NULL;
2232 ret = ctsvc_begin_trans();
2233 RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
2235 snprintf(query, sizeof(query),
2236 "SELECT addressbook_id, person_id FROM "CTS_TABLE_CONTACTS" "
2237 "WHERE contact_id = %d AND deleted = 0", contact_id);
2238 ret = ctsvc_query_prepare(query, &stmt);
2240 CTS_ERR("DB errror : ctsvc_query_prepare fail(%d)", ret);
2241 ctsvc_end_trans(false);
2244 ret = ctsvc_stmt_step(stmt);
2246 CTS_ERR("The contact_id(%d) is Invalid(%d)", contact_id, ret);
2247 ctsvc_stmt_finalize(stmt);
2248 ctsvc_end_trans(false);
2249 if (CONTACTS_ERROR_NONE == ret)
2250 return CONTACTS_ERROR_NO_DATA;
2255 addressbook_id = ctsvc_stmt_get_int(stmt, 0);
2256 person_id = ctsvc_stmt_get_int(stmt, 1);
2257 ctsvc_stmt_finalize(stmt);
2259 if (false == ctsvc_have_ab_write_permission(addressbook_id)) {
2260 CTS_ERR("Does not have permission to replace this contact (addressbook_id : %d, contact_id : %d", addressbook_id, contact_id);
2261 ctsvc_end_trans(false);
2262 return CONTACTS_ERROR_PERMISSION_DENIED;
2265 contact->id = contact_id;
2266 contact->person_id = person_id;
2267 ctsvc_contact_make_display_name(contact);
2268 __ctsvc_contact_check_default_data(contact);
2270 /* remove current child data */
2271 snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_DATA" WHERE contact_id = %d", contact_id);
2272 ret = ctsvc_query_exec(query);
2273 if (CONTACTS_ERROR_NONE != ret) {
2274 CTS_ERR("ctsvc_query_exec() Fail(%d)", ret);
2275 ctsvc_end_trans(false);
2279 ret = __ctsvc_contact_insert_data(contact);
2280 if (CONTACTS_ERROR_NONE != ret) {
2281 CTS_ERR("__ctsvc_contact_insert_data() Fail(%d)", ret);
2282 ctsvc_end_trans(false);
2286 /* remove current child data */
2287 snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_GROUP_RELATIONS" WHERE contact_id = %d", contact_id);
2288 ret = ctsvc_query_exec(query);
2289 if (CONTACTS_ERROR_NONE != ret) {
2290 CTS_ERR("ctsvc_query_exec() Fail(%d)", ret);
2291 ctsvc_end_trans(false);
2295 if (contact->grouprelations) {
2296 rel_changed = __ctsvc_contact_insert_grouprel(contact_id, (contacts_list_h)contact->grouprelations);
2297 if (rel_changed < CONTACTS_ERROR_NONE) {
2298 CTS_ERR("__ctsvc_contact_insert_grouprel() Fail(%d)", rel_changed);
2299 ctsvc_end_trans(false);
2305 if (contact->images) {
2306 int ret = CONTACTS_ERROR_NONE;
2308 ctsvc_image_s *image;
2310 contacts_list_get_count((contacts_list_h)contact->images, &count);
2312 contacts_list_first((contacts_list_h)contact->images);
2314 ret = contacts_list_get_current_record_p((contacts_list_h)contact->images, (contacts_record_h*)&image);
2315 if (CONTACTS_ERROR_NONE != ret) {
2316 CTS_ERR("contacts_list_get_current_record_p() Fail(%d)", ret);
2317 ctsvc_end_trans(false);
2318 return CONTACTS_ERROR_DB;
2321 if (image->is_default)
2323 } while (CONTACTS_ERROR_NONE == contacts_list_next((contacts_list_h)contact->images));
2325 if ((NULL == contact->image_thumbnail_path && image->path) ||
2326 (contact->image_thumbnail_path && NULL == image->path) ||
2327 (contact->image_thumbnail_path && image->path && STRING_EQUAL != strcmp(contact->image_thumbnail_path, image->path))) {
2328 ctsvc_record_set_property_flag((ctsvc_record_s *)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
2330 if (ctsvc_contact_check_image_location(image->path))
2331 contact->image_thumbnail_path = SAFE_STRDUP(image->path + strlen(CTSVC_CONTACT_IMG_FULL_LOCATION) + 1);
2333 contact->image_thumbnail_path = SAFE_STRDUP(image->path);
2336 else if (contact->image_thumbnail_path) {
2337 free(contact->image_thumbnail_path);
2338 contact->image_thumbnail_path = NULL;
2339 if (false == ctsvc_record_check_property_flag((ctsvc_record_s *)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY)) {
2340 ctsvc_record_set_property_flag((ctsvc_record_s *)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
2343 if (((ctsvc_record_s *)record)->properties_flags) {
2344 int index = _contacts_contact.image_thumbnail_path & 0x000000FF;
2345 ((ctsvc_record_s *)record)->properties_flags[index] = 0;
2350 version = ctsvc_get_next_ver();
2352 len = snprintf(query, sizeof(query),
2353 "UPDATE "CTS_TABLE_CONTACTS" SET changed_ver=%d, changed_time=%d, is_favorite=%d, "
2354 "has_phonenumber=%d, has_email=%d, display_name=?, "
2355 "reverse_display_name=?, display_name_source=%d, "
2356 "display_name_language=%d, reverse_display_name_language=%d, "
2357 "sort_name=?, reverse_sort_name=?, "
2358 "sortkey=?, reverse_sortkey=?, uid=?, ringtone_path=?, vibration=?, "
2359 "message_alert =?, image_thumbnail_path=?",
2360 version, (int)time(NULL), contact->is_favorite,
2361 contact->has_phonenumber, contact->has_email,
2362 contact->display_source_type,
2363 contact->display_name_language, contact->reverse_display_name_language);
2365 if (ctsvc_record_check_property_flag((ctsvc_record_s *)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY))
2366 len += snprintf(query+len, sizeof(query)-len, ", image_changed_ver = %d", version);
2368 len += snprintf(query+len, sizeof(query)-len, " WHERE contact_id=%d", contact->id);
2370 ret = ctsvc_query_prepare(query, &stmt);
2372 CTS_ERR("ctsvc_query_prepare() Fail(%d)", ret);
2373 ctsvc_end_trans(false);
2377 if (contact->display_name)
2378 ctsvc_stmt_bind_text(stmt, 1, contact->display_name);
2379 if (contact->reverse_display_name)
2380 ctsvc_stmt_bind_text(stmt, 2, contact->reverse_display_name);
2381 if (contact->sort_name)
2382 ctsvc_stmt_bind_text(stmt, 3, contact->sort_name);
2383 if (contact->reverse_sort_name)
2384 ctsvc_stmt_bind_text(stmt, 4, contact->reverse_sort_name);
2385 if (contact->sortkey)
2386 ctsvc_stmt_bind_text(stmt, 5, contact->sortkey);
2387 if (contact->reverse_sortkey)
2388 ctsvc_stmt_bind_text(stmt, 6, contact->reverse_sortkey);
2390 ctsvc_stmt_bind_text(stmt, 7, contact->uid);
2391 if (contact->ringtone_path)
2392 ctsvc_stmt_bind_text(stmt, 8, contact->ringtone_path);
2393 if (contact->vibration)
2394 ctsvc_stmt_bind_text(stmt, 9, contact->vibration);
2395 if (contact->message_alert)
2396 ctsvc_stmt_bind_text(stmt, 10, contact->message_alert);
2397 if (contact->image_thumbnail_path)
2398 ctsvc_stmt_bind_text(stmt, 11, contact->image_thumbnail_path);
2400 ret = ctsvc_stmt_step(stmt);
2401 if (CONTACTS_ERROR_NONE != ret) {
2402 CTS_ERR("ctsvc_stmt_step() Fail(%d)", ret);
2403 ctsvc_stmt_finalize(stmt);
2404 ctsvc_end_trans(false);
2407 ctsvc_stmt_finalize(stmt);
2409 ctsvc_set_contact_noti();
2410 if (0 < rel_changed)
2411 ctsvc_set_group_rel_noti();
2413 __ctsvc_contact_update_search_data(contact->id, true);
2414 ctsvc_db_update_person((contacts_record_h)contact);
2416 ret = ctsvc_end_trans(true);
2418 if (ret < CONTACTS_ERROR_NONE)
2421 return CONTACTS_ERROR_NONE;