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"
33 #ifdef _CONTACTS_IPC_SERVER
34 #include "ctsvc_server_change_subject.h"
35 #include "ctsvc_server_sim.h"
36 #endif /* _CONTACTS_IPC_SERVER */
38 int ctsvc_phone_log_reset_statistics()
40 char query[CTS_SQL_MIN_LEN] = {0};
41 snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_PHONELOG_STAT);
42 return ctsvc_query_exec(query);
45 int ctsvc_phone_log_delete(contacts_phone_log_delete_e op, ...)
49 char query[CTS_SQL_MAX_LEN] = {0};
54 case CONTACTS_PHONE_LOG_DELETE_BY_ADDRESS:
56 number = va_arg(args, char *);
58 RETV_IF(NULL == number, CONTACTS_ERROR_INVALID_PARAMETER);
59 snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_PHONELOGS" WHERE number = '%s'", number);
61 case CONTACTS_PHONE_LOG_DELETE_BY_MESSAGE_EXTRA_DATA1:
63 extra_data1 = va_arg(args, int);
65 snprintf(query, sizeof(query),
66 "DELETE FROM "CTS_TABLE_PHONELOGS" "
67 "WHERE data1 = %d AND %d <= log_type AND log_type <= %d",
68 extra_data1, CONTACTS_PLOG_TYPE_MMS_INCOMMING, CONTACTS_PLOG_TYPE_MMS_BLOCKED);
70 case CONTACTS_PHONE_LOG_DELETE_BY_EMAIL_EXTRA_DATA1:
72 extra_data1 = va_arg(args, int);
74 snprintf(query, sizeof(query),
75 "DELETE FROM "CTS_TABLE_PHONELOGS" "
76 "WHERE data1 = %d AND %d <= log_type AND log_type <= %d",
77 extra_data1, CONTACTS_PLOG_TYPE_EMAIL_RECEIVED, CONTACTS_PLOG_TYPE_EMAIL_SENT);
80 ERR("the operation is not proper (op : %d)", op);
81 return CONTACTS_ERROR_INVALID_PARAMETER;
83 ret = ctsvc_begin_trans();
84 RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
86 ret = ctsvc_query_exec(query);
87 if (CONTACTS_ERROR_NONE != ret) {
88 ERR("ctsvc_query_exec() Fail(%d)", ret);
89 ctsvc_end_trans(false);
92 ctsvc_set_phonelog_noti();
93 ret = ctsvc_end_trans(true);
97 void ctsvc_db_phone_log_delete_callback(sqlite3_context *context,
98 int argc, sqlite3_value **argv)
100 #ifdef _CONTACTS_IPC_SERVER
104 sqlite3_result_null(context);
108 phone_log_id = sqlite3_value_int(argv[0]);
109 ctsvc_change_subject_add_changed_phone_log_id(CONTACTS_CHANGE_DELETED, phone_log_id);
111 sqlite3_result_null(context);
116 static int __ctsvc_db_phone_log_find_person_id(char *number, char *normal_num, char *minmatch, int person_id, int *find_number_type)
119 int find_person_id = -1;
120 char query[CTS_SQL_MAX_LEN] = {0};
121 GSList *bind_text = NULL;
122 GSList *cursor = NULL;
125 *find_number_type = -1;
127 ret = snprintf(query, sizeof(query),
128 "SELECT person_id, data1 FROM "CTS_TABLE_CONTACTS", "CTS_TABLE_DATA" "
129 "ON "CTS_TABLE_CONTACTS".contact_id = "CTS_TABLE_DATA".contact_id "
130 "AND datatype = %d AND is_my_profile = 0 AND deleted = 0 "
131 "WHERE data4 = ? AND _NUMBER_COMPARE_(data5, ?, NULL, NULL)",
133 bind_text = g_slist_append(bind_text, strdup(minmatch));
134 bind_text = g_slist_append(bind_text, strdup(normal_num));
138 /* several person can have same number */
139 cts_stmt stmt = NULL;
141 int number_type = -1;
143 ret = ctsvc_query_prepare(query, &stmt);
145 ERR("ctsvc_query_prepare fail(%d)", ret);
147 for (cursor = bind_text; cursor; cursor = cursor->next)
149 g_slist_free(bind_text);
151 return CONTACTS_ERROR_DB;
155 for (cursor = bind_text, i = 1; cursor; cursor = cursor->next, i++) {
156 const char *text = cursor->data;
158 ctsvc_stmt_bind_text(stmt, i, text);
162 while ((ret = ctsvc_stmt_step(stmt))) {
163 id = ctsvc_stmt_get_int(stmt, 0);
164 number_type = ctsvc_stmt_get_int(stmt, 1);
165 if (find_person_id <= 0 && 0 < id) {
166 find_person_id = id; /* find first match person_id */
167 *find_number_type = number_type;
172 if (id == person_id) {
173 find_person_id = person_id;
174 *find_number_type = number_type;
178 ctsvc_stmt_finalize(stmt);
182 for (cursor = bind_text; cursor; cursor = cursor->next)
184 g_slist_free(bind_text);
187 return find_person_id;
190 int ctsvc_db_phone_log_update_person_id(const char *number, int old_person_id, int candidate_person_id, bool person_link)
195 char query[CTS_SQL_MAX_LEN] = {0};
196 cts_stmt get_log = NULL;
197 cts_stmt update_log = NULL;
198 GSList *bind_text = NULL;
199 GSList *cursor = NULL;
202 RETVM_IF(old_person_id <= 0 && NULL == number, CONTACTS_ERROR_INVALID_PARAMETER,
203 "old person_id (%d), number is NULL", old_person_id);
205 len = snprintf(query, sizeof(query),
206 "SELECT id, number, normal_num, minmatch FROM "CTS_TABLE_PHONELOGS" "
207 "WHERE log_type <= %d ",
208 CONTACTS_PLOG_TYPE_EMAIL_RECEIVED);
210 if (number && *number) {
211 char clean_num[strlen(number)+1];
212 len += snprintf(query+len, sizeof(query)-len, "AND ((number = ?) ");
213 bind_text = g_slist_append(bind_text, strdup(number));
215 ret = ctsvc_clean_number(number, clean_num, sizeof(clean_num), true);
217 char normal_num[sizeof(clean_num) + 20];
218 ret = ctsvc_normalize_number(clean_num, normal_num, sizeof(normal_num), true);
220 char minmatch[sizeof(normal_num)+1];
221 ret = ctsvc_get_minmatch_number(normal_num, minmatch, sizeof(minmatch), ctsvc_get_phonenumber_min_match_digit());
222 if (CONTACTS_ERROR_NONE == ret) {
223 len += snprintf(query+len, sizeof(query)-len,
224 "OR (minmatch = ? AND _NUMBER_COMPARE_(normal_num, ?, NULL, NULL))) ");
225 bind_text = g_slist_append(bind_text, strdup(minmatch));
226 bind_text = g_slist_append(bind_text, strdup(normal_num));
228 len += snprintf(query+len, sizeof(query)-len, ") ");
231 len += snprintf(query+len, sizeof(query)-len, ") ");
234 len += snprintf(query+len, sizeof(query)-len, ") ");
238 if (0 < old_person_id)
239 len += snprintf(query+len, sizeof(query)-len, "AND person_id = %d ", old_person_id);
241 len += snprintf(query+len, sizeof(query)-len, "AND person_id IS NULL ");
243 ret = ctsvc_query_prepare(query, &get_log);
244 if (get_log == NULL) {
245 ERR("ctsvc_query_prepare() Fail(%d)", ret);
247 for (cursor = bind_text; cursor; cursor = cursor->next)
249 g_slist_free(bind_text);
251 return CONTACTS_ERROR_DB;
255 for (cursor = bind_text, i = 1; cursor; cursor = cursor->next, i++) {
256 const char *text = cursor->data;
258 ctsvc_stmt_bind_text(get_log, i, text);
262 snprintf(query, sizeof(query),
263 "UPDATE "CTS_TABLE_PHONELOGS" SET person_id=?, number_type = ? WHERE id = ?");
264 ret = ctsvc_query_prepare(query, &update_log);
265 if (update_log == NULL) {
266 ERR("ctsvc_query_prepare() Fail(%d)", ret);
267 ctsvc_stmt_finalize(get_log);
270 for (cursor = bind_text; cursor; cursor = cursor->next)
272 g_slist_free(bind_text);
274 return CONTACTS_ERROR_DB;
277 while ((ret = ctsvc_stmt_step(get_log))) {
279 int new_person_id = -1;
281 int number_type = -1;
283 char *normal_address;
284 char *minmatch_address;
286 phonelog_id = ctsvc_stmt_get_int(get_log, 0);
287 address = ctsvc_stmt_get_text(get_log, 1);
288 normal_address = ctsvc_stmt_get_text(get_log, 2);
289 minmatch_address = ctsvc_stmt_get_text(get_log, 3);
291 /* CASE : number is inserted (contact insert/update) => update person_id of phone logs from NULL */
292 if (number && old_person_id <= 0 && 0 < candidate_person_id) {
293 __ctsvc_db_phone_log_find_person_id(address, normal_address, minmatch_address, candidate_person_id, &number_type);
294 new_person_id = candidate_person_id;
295 } else if (number && old_person_id <= 0) {
296 /* CASE : phonelog insert without person_id */
297 /* address == number */
298 new_person_id = __ctsvc_db_phone_log_find_person_id(address, normal_address, minmatch_address, -1, &number_type);
299 if (new_person_id <= 0) continue;
300 } else if (number && 0 < old_person_id) {
301 /* CASE : number update/delete (contact update/delete) => find new_person_id by address */
302 /* CASE : phonelog insert with person_id */
303 /* address == number */
304 /* although new_person_id and old_person_id are same, update phonelog for setting number_type */
305 new_person_id = __ctsvc_db_phone_log_find_person_id(address, normal_address, minmatch_address, old_person_id, &number_type);
306 } else if (NULL == number && 0 < old_person_id && 0 < candidate_person_id && person_link) {
307 /* CASE : person link => deleted person_id -> new person_id (base_person_id) */
308 new_person_id = candidate_person_id;
309 } else if (NULL == number && 0 < old_person_id && 0 < candidate_person_id) {
310 /* CASE : person unlink => check person_id of the address, */
311 /* if person_id is not old_person_id then change person_id to new_person_id */
312 temp_id = __ctsvc_db_phone_log_find_person_id(address, normal_address, minmatch_address, candidate_person_id, &number_type);
313 if (0 < temp_id && temp_id == old_person_id)
315 else if (0 < temp_id && temp_id != old_person_id)
316 new_person_id = temp_id;
317 } else if (NULL == number && 0 < old_person_id) {
318 /* CASE : person delete => find new_person_id by address */
319 new_person_id = __ctsvc_db_phone_log_find_person_id(address, normal_address, minmatch_address, candidate_person_id, &number_type);
321 /* Already check this case as above : RETVM_IF(old_person_id <= 0 && NULL == number, ... */
327 if (0 < new_person_id)
328 ctsvc_stmt_bind_int(update_log, 1, new_person_id);
329 if (0 <= number_type)
330 ctsvc_stmt_bind_int(update_log, 2, number_type);
331 ctsvc_stmt_bind_int(update_log, 3, phonelog_id);
332 ctsvc_stmt_step(update_log);
333 ctsvc_stmt_reset(update_log);
335 ctsvc_stmt_finalize(get_log);
336 ctsvc_stmt_finalize(update_log);
339 for (cursor = bind_text; cursor; cursor = cursor->next)
341 g_slist_free(bind_text);
344 return CONTACTS_ERROR_NONE;