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.
21 #include "contacts_phone_log_internal.h"
23 #include "ctsvc_internal.h"
24 #include "ctsvc_db_schema.h"
25 #include "ctsvc_db_sqlite.h"
26 #include "ctsvc_db_utils.h"
27 #include "ctsvc_notification.h"
28 #include "ctsvc_db_access_control.h"
29 #include "ctsvc_number_utils.h"
30 #include "ctsvc_localize_utils.h"
31 #include "ctsvc_server_setting.h"
32 #include "ctsvc_server_utils.h"
34 #ifdef _CONTACTS_IPC_SERVER
35 #include "ctsvc_server_change_subject.h"
36 #include "ctsvc_server_sim.h"
37 #endif /* _CONTACTS_IPC_SERVER */
39 int ctsvc_phone_log_reset_statistics()
41 char query[CTS_SQL_MIN_LEN] = {0};
42 snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_PHONELOG_STAT);
43 return ctsvc_query_exec(query);
46 int ctsvc_phone_log_reset_statistics_by_sim(int sim_slot_no)
48 char query[CTS_SQL_MIN_LEN] = {0};
51 RETVM_IF(false == ctsvc_server_have_telephony_feature(), CONTACTS_ERROR_NOT_SUPPORTED, "Telephony feature disabled");
53 sim_info_id = ctsvc_server_sim_get_info_id_by_sim_slot_no(sim_slot_no);
54 if (sim_info_id <= 0) {
55 ERR("ctsvc_server_sim_get_info_id_by_sim_slot_no() Fail(%d)", sim_info_id);
56 return CONTACTS_ERROR_NO_DATA;
59 snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_PHONELOG_STAT
60 " WHERE sim_id = %d", sim_info_id);
61 return ctsvc_query_exec(query);
64 int ctsvc_phone_log_delete(contacts_phone_log_delete_e op, ...)
68 char query[CTS_SQL_MAX_LEN] = {0};
73 case CONTACTS_PHONE_LOG_DELETE_BY_ADDRESS:
75 number = va_arg(args, char *);
77 RETV_IF(NULL == number, CONTACTS_ERROR_INVALID_PARAMETER);
78 snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_PHONELOGS" WHERE number = '%s'", number);
80 case CONTACTS_PHONE_LOG_DELETE_BY_MESSAGE_EXTRA_DATA1:
82 extra_data1 = va_arg(args, int);
84 snprintf(query, sizeof(query),
85 "DELETE FROM "CTS_TABLE_PHONELOGS" "
86 "WHERE data1 = %d AND %d <= log_type AND log_type <= %d",
87 extra_data1, CONTACTS_PLOG_TYPE_MMS_INCOMING, CONTACTS_PLOG_TYPE_MMS_BLOCKED);
89 case CONTACTS_PHONE_LOG_DELETE_BY_EMAIL_EXTRA_DATA1:
91 extra_data1 = va_arg(args, int);
93 snprintf(query, sizeof(query),
94 "DELETE FROM "CTS_TABLE_PHONELOGS" "
95 "WHERE data1 = %d AND %d <= log_type AND log_type <= %d",
96 extra_data1, CONTACTS_PLOG_TYPE_EMAIL_RECEIVED, CONTACTS_PLOG_TYPE_EMAIL_SENT);
99 ERR("the operation is not proper (op : %d)", op);
100 return CONTACTS_ERROR_INVALID_PARAMETER;
102 ret = ctsvc_begin_trans();
103 RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
105 ret = ctsvc_query_exec(query);
106 if (CONTACTS_ERROR_NONE != ret) {
107 ERR("ctsvc_query_exec() Fail(%d)", ret);
108 ctsvc_end_trans(false);
111 ctsvc_set_phonelog_noti();
112 ret = ctsvc_end_trans(true);
116 void ctsvc_db_phone_log_delete_callback(sqlite3_context *context,
117 int argc, sqlite3_value **argv)
119 #ifdef _CONTACTS_IPC_SERVER
123 sqlite3_result_null(context);
127 phone_log_id = sqlite3_value_int(argv[0]);
128 ctsvc_change_subject_add_changed_phone_log_id(CONTACTS_CHANGE_DELETED, phone_log_id);
130 sqlite3_result_null(context);
135 static int __ctsvc_db_phone_log_find_person_id(char *number, char *normal_num,
136 char *minmatch, int person_id, int *find_number_type)
139 int find_person_id = -1;
140 char query[CTS_SQL_MAX_LEN] = {0};
141 GSList *bind_text = NULL;
142 GSList *cursor = NULL;
145 *find_number_type = -1;
147 ret = snprintf(query, sizeof(query),
148 "SELECT person_id, data1 FROM "CTS_TABLE_CONTACTS", "CTS_TABLE_DATA" "
149 "ON "CTS_TABLE_CONTACTS".contact_id = "CTS_TABLE_DATA".contact_id "
150 "AND datatype = %d AND is_my_profile = 0 AND deleted = 0 "
151 "WHERE data4 = ? AND _NUMBER_COMPARE_(data5, ?, NULL, NULL)",
152 CONTACTS_DATA_TYPE_NUMBER);
153 bind_text = g_slist_append(bind_text, strdup(minmatch));
154 bind_text = g_slist_append(bind_text, strdup(normal_num));
158 /* several person can have same number */
159 cts_stmt stmt = NULL;
161 int number_type = -1;
163 ret = ctsvc_query_prepare(query, &stmt);
165 ERR("ctsvc_query_prepare fail(%d)", ret);
167 for (cursor = bind_text; cursor; cursor = cursor->next)
169 g_slist_free(bind_text);
171 return CONTACTS_ERROR_DB;
175 for (cursor = bind_text, i = 1; cursor; cursor = cursor->next, i++) {
176 const char *text = cursor->data;
178 ctsvc_stmt_bind_text(stmt, i, text);
182 while ((ret = ctsvc_stmt_step(stmt))) {
183 id = ctsvc_stmt_get_int(stmt, 0);
184 number_type = ctsvc_stmt_get_int(stmt, 1);
185 if (find_person_id <= 0 && 0 < id) {
186 find_person_id = id; /* find first match person_id */
187 *find_number_type = number_type;
192 if (id == person_id) {
193 find_person_id = person_id;
194 *find_number_type = number_type;
198 ctsvc_stmt_finalize(stmt);
202 for (cursor = bind_text; cursor; cursor = cursor->next)
204 g_slist_free(bind_text);
207 return find_person_id;
210 int ctsvc_db_phone_log_update_person_id(const char *number, int old_person_id,
211 int candidate_person_id, bool person_link, int *found_person_id)
216 char query[CTS_SQL_MAX_LEN] = {0};
217 cts_stmt get_log = NULL;
218 cts_stmt update_log = NULL;
219 GSList *bind_text = NULL;
220 GSList *cursor = NULL;
222 bool need_noti = false;
224 RETVM_IF(old_person_id <= 0 && NULL == number, CONTACTS_ERROR_INVALID_PARAMETER,
225 "old person_id (%d), number is NULL", old_person_id);
227 len = snprintf(query, sizeof(query),
228 "SELECT id, number, normal_num, minmatch FROM "CTS_TABLE_PHONELOGS" "
229 "WHERE log_type <= %d ",
230 CONTACTS_PLOG_TYPE_EMAIL_RECEIVED);
232 if (number && *number) {
233 char clean_num[strlen(number)+1];
234 len += snprintf(query+len, sizeof(query)-len, "AND ((number = ?) ");
235 bind_text = g_slist_append(bind_text, strdup(number));
237 ret = ctsvc_clean_number(number, clean_num, sizeof(clean_num), true);
239 char normal_num[sizeof(clean_num) + 20];
240 ret = ctsvc_normalize_number(clean_num, normal_num, sizeof(normal_num), true);
242 char minmatch[sizeof(normal_num)+1];
243 ret = ctsvc_get_minmatch_number(normal_num, minmatch, sizeof(minmatch),
244 ctsvc_get_phonenumber_min_match_digit());
245 if (CONTACTS_ERROR_NONE == ret) {
246 len += snprintf(query+len, sizeof(query)-len,
247 "OR (minmatch = ? AND _NUMBER_COMPARE_(normal_num, ?, NULL, NULL))) ");
248 bind_text = g_slist_append(bind_text, strdup(minmatch));
249 bind_text = g_slist_append(bind_text, strdup(normal_num));
251 len += snprintf(query+len, sizeof(query)-len, ") ");
254 len += snprintf(query+len, sizeof(query)-len, ") ");
257 len += snprintf(query+len, sizeof(query)-len, ") ");
261 if (0 < old_person_id)
262 len += snprintf(query+len, sizeof(query)-len, "AND person_id = %d ", old_person_id);
264 len += snprintf(query+len, sizeof(query)-len, "AND person_id IS NULL ");
266 ret = ctsvc_query_prepare(query, &get_log);
267 if (get_log == NULL) {
268 ERR("ctsvc_query_prepare() Fail(%d)", ret);
270 for (cursor = bind_text; cursor; cursor = cursor->next)
272 g_slist_free(bind_text);
274 return CONTACTS_ERROR_DB;
278 for (cursor = bind_text, i = 1; cursor; cursor = cursor->next, i++) {
279 const char *text = cursor->data;
281 ctsvc_stmt_bind_text(get_log, i, text);
285 snprintf(query, sizeof(query),
286 "UPDATE "CTS_TABLE_PHONELOGS" SET person_id=?, number_type = ? WHERE id = ?");
287 ret = ctsvc_query_prepare(query, &update_log);
288 if (update_log == NULL) {
289 ERR("ctsvc_query_prepare() Fail(%d)", ret);
290 ctsvc_stmt_finalize(get_log);
293 for (cursor = bind_text; cursor; cursor = cursor->next)
295 g_slist_free(bind_text);
297 return CONTACTS_ERROR_DB;
300 while ((ret = ctsvc_stmt_step(get_log))) {
302 int new_person_id = -1;
304 int number_type = -1;
306 char *normal_address;
307 char *minmatch_address;
309 phonelog_id = ctsvc_stmt_get_int(get_log, 0);
310 address = ctsvc_stmt_get_text(get_log, 1);
311 normal_address = ctsvc_stmt_get_text(get_log, 2);
312 minmatch_address = ctsvc_stmt_get_text(get_log, 3);
314 /* CASE : number is inserted (contact insert/update) => update person_id of phone logs from NULL */
315 if (number && old_person_id <= 0 && 0 < candidate_person_id) {
316 __ctsvc_db_phone_log_find_person_id(address, normal_address,
317 minmatch_address, candidate_person_id, &number_type);
318 new_person_id = candidate_person_id;
319 } else if (number && old_person_id <= 0) {
320 /* CASE : phonelog insert without person_id */
321 /* address == number */
322 new_person_id = __ctsvc_db_phone_log_find_person_id(address, normal_address,
323 minmatch_address, -1, &number_type);
324 if (new_person_id <= 0)
328 *found_person_id = new_person_id;
329 } else if (number && 0 < old_person_id) {
330 /* CASE : number update/delete (contact update/delete) => find new_person_id by address */
331 /* CASE : phonelog insert with person_id */
332 /* address == number */
333 /* although new_person_id and old_person_id are same, update phonelog for setting number_type */
334 new_person_id = __ctsvc_db_phone_log_find_person_id(address, normal_address,
335 minmatch_address, old_person_id, &number_type);
336 } else if (NULL == number && 0 < old_person_id && 0 < candidate_person_id && person_link) {
337 /* CASE : person link => deleted person_id -> new person_id (base_person_id) */
338 new_person_id = candidate_person_id;
339 } else if (NULL == number && 0 < old_person_id && 0 < candidate_person_id) {
340 /* CASE : person unlink => check person_id of the address, */
341 /* if person_id is not old_person_id then change person_id to new_person_id */
342 temp_id = __ctsvc_db_phone_log_find_person_id(address, normal_address,
343 minmatch_address, candidate_person_id, &number_type);
344 if (0 < temp_id && temp_id == old_person_id)
346 else if (0 < temp_id && temp_id != old_person_id)
347 new_person_id = temp_id;
348 } else if (NULL == number && 0 < old_person_id) {
349 /* CASE : person delete => find new_person_id by address */
350 new_person_id = __ctsvc_db_phone_log_find_person_id(address, normal_address, minmatch_address, candidate_person_id, &number_type);
352 /* Already check this case as above : RETVM_IF(old_person_id <= 0 && NULL == number, ... */
361 if (0 < new_person_id)
362 ctsvc_stmt_bind_int(update_log, 1, new_person_id);
363 if (0 <= number_type)
364 ctsvc_stmt_bind_int(update_log, 2, number_type);
365 ctsvc_stmt_bind_int(update_log, 3, phonelog_id);
366 ctsvc_stmt_step(update_log);
367 ctsvc_stmt_reset(update_log);
369 ctsvc_stmt_finalize(get_log);
370 ctsvc_stmt_finalize(update_log);
373 ctsvc_set_phonelog_noti();
376 for (cursor = bind_text; cursor; cursor = cursor->next)
378 g_slist_free(bind_text);
381 return CONTACTS_ERROR_NONE;