[SVACE Issue Fixes]
[platform/core/pim/contacts-service.git] / server / db / ctsvc_db_plugin_addressbook.c
1 /*
2  * Contacts Service
3  *
4  * Copyright (c) 2010 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 #include <account.h>
20
21 #include "contacts.h"
22 #include "ctsvc_internal.h"
23 #include "ctsvc_db_schema.h"
24 #include "ctsvc_db_sqlite.h"
25 #include "ctsvc_db_utils.h"
26 #include "ctsvc_list.h"
27 #include "ctsvc_db_init.h"
28 #include "ctsvc_db_query.h"
29 #include "ctsvc_db_plugin_person_helper.h"
30 #include "ctsvc_server_person.h"
31 #include "ctsvc_record.h"
32 #include "ctsvc_notification.h"
33 #include "ctsvc_db_access_control.h"
34 #include "ctsvc_db_plugin_addressbook_helper.h"
35
36
37 static int __ctsvc_db_addressbook_value_set(cts_stmt stmt, contacts_record_h *record)
38 {
39         int i;
40         int ret;
41         char *temp;
42         ctsvc_addressbook_s *addressbook;
43
44         ret = contacts_record_create(_contacts_address_book._uri, record);
45         RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "contacts_record_create Fail(%d)", ret);
46         addressbook = (ctsvc_addressbook_s*)*record;
47
48         i = 0;
49         addressbook->id = ctsvc_stmt_get_int(stmt, i++);
50         temp = ctsvc_stmt_get_text(stmt, i++);
51         addressbook->name = SAFE_STRDUP(temp);
52         addressbook->account_id = ctsvc_stmt_get_int(stmt, i++);
53         addressbook->mode = ctsvc_stmt_get_int(stmt, i++);
54
55         return CONTACTS_ERROR_NONE;
56 }
57
58 static int __ctsvc_db_addressbook_get_record(int id, contacts_record_h *out_record)
59 {
60         int ret;
61         cts_stmt stmt = NULL;
62         char query[CTS_SQL_MAX_LEN] = {0};
63         contacts_record_h record;
64
65         RETV_IF(NULL == out_record, CONTACTS_ERROR_INVALID_PARAMETER);
66         *out_record = NULL;
67
68         snprintf(query, sizeof(query),
69                         "SELECT addressbook_id, addressbook_name, account_id, mode, last_sync_ver "
70                         "FROM "CTS_TABLE_ADDRESSBOOKS" WHERE addressbook_id = %d", id);
71
72         ret = ctsvc_query_prepare(query, &stmt);
73         RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
74
75         ret = ctsvc_stmt_step(stmt);
76         if (1 /*CTS_TRUE*/ != ret) {
77                 /* LCOV_EXCL_START */
78                 ERR("ctsvc_stmt_step() Fail(%d)", ret);
79                 ctsvc_stmt_finalize(stmt);
80                 if (CONTACTS_ERROR_NONE == ret)
81                         return CONTACTS_ERROR_NO_DATA;
82                 else
83                         return ret;
84                 /* LCOV_EXCL_STOP */
85         }
86
87         ret = __ctsvc_db_addressbook_value_set(stmt, &record);
88
89         ctsvc_stmt_finalize(stmt);
90         if (CONTACTS_ERROR_NONE != ret) {
91                 /* LCOV_EXCL_START */
92                 ERR("__ctsvc_db_addressbook_value_set(ALL) Fail(%d)", ret);
93                 return ret;
94                 /* LCOV_EXCL_STOP */
95         }
96
97         *out_record = record;
98
99         return CONTACTS_ERROR_NONE;
100 }
101
102
103 static int __ctsvc_db_addressbook_insert_record(contacts_record_h record, int *id)
104 {
105         int ret;
106         cts_stmt stmt = NULL;
107         char query[CTS_SQL_MAX_LEN] = {0};
108         char *smack = NULL;
109         ctsvc_addressbook_s *addressbook = (ctsvc_addressbook_s*)record;
110
111         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
112         RETV_IF(NULL == addressbook->name, CONTACTS_ERROR_INVALID_PARAMETER);
113         RETVM_IF(CTSVC_RECORD_ADDRESSBOOK != addressbook->base.r_type, CONTACTS_ERROR_INVALID_PARAMETER,
114                         "record is invalid type(%d)", addressbook->base.r_type);
115
116         ret = ctsvc_begin_trans();
117         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_begin_trans() Fail(%d)", ret);
118
119         /* Can not insert addressbook which has same account_id */
120         int addresbook_id;
121         account_h account = NULL;
122         snprintf(query, sizeof(query),
123                         "SELECT addressbook_id FROM "CTS_TABLE_ADDRESSBOOKS" WHERE account_id = %d",
124                         addressbook->account_id);
125         ret = ctsvc_query_get_first_int_result(query, &addresbook_id);
126         if (CONTACTS_ERROR_NO_DATA != ret) {
127                 /* LCOV_EXCL_START */
128                 ctsvc_end_trans(false);
129                 if (CONTACTS_ERROR_NONE == ret) {
130                         ERR("One addressbook which has account_id(%d) already exists", addressbook->account_id);
131                         return CONTACTS_ERROR_INVALID_PARAMETER;
132                 } else {
133                         ERR("ctsvc_query_get_first_int_result() Fail(%d)", ret);
134                         return ret;
135                 }
136                 /* LCOV_EXCL_STOP */
137         }
138
139         /* check account_id validation */
140         ret = account_create(&account);
141         if (ACCOUNT_ERROR_NONE != ret) {
142                 /* LCOV_EXCL_START */
143                 ERR("account_create() Fail(%d)", ret);
144                 ctsvc_end_trans(false);
145                 return CONTACTS_ERROR_SYSTEM;
146                 /* LCOV_EXCL_STOP */
147         }
148         ret = account_query_account_by_account_id(addressbook->account_id, &account);
149         if (ACCOUNT_ERROR_NONE != ret) {
150                 /* LCOV_EXCL_START */
151                 ERR("account_query_account_by_account_id Faild(%d) : account_id(%d)", ret, addressbook->account_id);
152                 ret = account_destroy(account);
153                 WARN_IF(ret != ACCOUNT_ERROR_NONE, "account_destroy Fail(%d)", ret);
154                 ctsvc_end_trans(false);
155                 return CONTACTS_ERROR_INVALID_PARAMETER;
156                 /* LCOV_EXCL_STOP */
157         }
158         ret = account_destroy(account);
159         WARN_IF(ret != ACCOUNT_ERROR_NONE, "account_destroy Fail(%d)", ret);
160
161         snprintf(query, sizeof(query),
162                         "INSERT INTO %s(addressbook_name, account_id, mode, smack_label) "
163                         "VALUES(?, %d, %d, ?)",
164                         CTS_TABLE_ADDRESSBOOKS, addressbook->account_id, addressbook->mode);
165
166         ret = ctsvc_query_prepare(query, &stmt);
167         if (NULL == stmt) {
168                 /* LCOV_EXCL_START */
169                 ERR("ctsvc_query_prepare() Fail(%d)", ret);
170                 ctsvc_end_trans(false);
171                 return ret;
172                 /* LCOV_EXCL_STOP */
173         }
174
175         ctsvc_stmt_bind_text(stmt, 1, addressbook->name);
176
177         smack = ctsvc_get_client_smack_label();
178         if (smack)
179                 ctsvc_stmt_bind_text(stmt, 2, smack);
180
181         /* DOING JOB */
182         do {
183                 ret = ctsvc_stmt_step(stmt);
184                 if (CONTACTS_ERROR_NONE != ret) {
185                         /* LCOV_EXCL_START */
186                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
187                         ctsvc_stmt_finalize(stmt);
188                         break;
189                         /* LCOV_EXCL_STOP */
190                 }
191
192                 /* int index = ctsvc_db_get_last_insert_id(); */
193                 if (id)
194                         *id = ctsvc_db_get_last_insert_id();
195                 ctsvc_stmt_finalize(stmt);
196
197                 ctsvc_set_addressbook_noti();
198                 ret = ctsvc_end_trans(true);
199                 if (ret < CONTACTS_ERROR_NONE) {
200                         /* LCOV_EXCL_START */
201                         ERR("ctsvc_end_trans() Fail(%d)", ret);
202                         free(smack);
203                         return ret;
204                         /* LCOV_EXCL_STOP */
205                 }
206                 /* addressbook->id = index; */
207
208                 /* SUCCESS */
209                 return CONTACTS_ERROR_NONE;
210
211         } while (0);
212
213         /* ROLLBACK TRANSACTION */
214         ctsvc_end_trans(false);
215         free(smack);
216         return ret;
217 }
218
219 static int __ctsvc_db_addressbook_update_record(contacts_record_h record)
220 {
221         int ret = CONTACTS_ERROR_NONE;
222         char *set = NULL;
223         GSList *bind_text = NULL;
224         GSList *cursor = NULL;
225         ctsvc_addressbook_s *addressbook = (ctsvc_addressbook_s*)record;
226
227         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
228         RETVM_IF(CTSVC_PROPERTY_FLAG_DIRTY != (addressbook->base.property_flag & CTSVC_PROPERTY_FLAG_DIRTY), CONTACTS_ERROR_NONE, "No update");
229         RETV_IF(NULL == addressbook->name, CONTACTS_ERROR_INVALID_PARAMETER);
230         RETVM_IF(CTSVC_RECORD_ADDRESSBOOK != addressbook->base.r_type, CONTACTS_ERROR_INVALID_PARAMETER,
231                         "record is invalid type(%d)", addressbook->base.r_type);
232
233         ret = ctsvc_begin_trans();
234         RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
235
236         ret = ctsvc_is_owner(addressbook->id);
237         if (CONTACTS_ERROR_NONE != ret) {
238                 /* LCOV_EXCL_START */
239                 if (CONTACTS_ERROR_PERMISSION_DENIED == ret)
240                         ERR("Does not have permission of address_book (%d)", addressbook->id);
241                 else
242                         ERR("ctsvc_is_owner Fail(%d)", ret);
243                 ctsvc_end_trans(false);
244                 return ret;
245                 /* LCOV_EXCL_STOP */
246         }
247
248         do {
249                 char query[CTS_SQL_MAX_LEN] = {0};
250                 cts_stmt stmt = NULL;
251
252                 if (CONTACTS_ERROR_NONE != (ret = ctsvc_db_create_set_query(record, &set, &bind_text))) break;
253                 if (NULL == set || '\0' == *set)
254                         break;
255
256                 snprintf(query, sizeof(query), "UPDATE %s SET %s WHERE addressbook_id = %d", CTS_TABLE_ADDRESSBOOKS, set, addressbook->id);
257                 ret = ctsvc_query_prepare(query, &stmt);
258                 if (NULL == stmt) {
259                         ERR("ctsvc_query_prepare() Fail(%d)", ret);
260                         break;
261                 }
262                 if (bind_text) {
263                         int i = 0;
264                         for (cursor = bind_text, i = 1; cursor; cursor = cursor->next, i++) {
265                                 const char *text = cursor->data;
266                                 if (text && *text)
267                                         ctsvc_stmt_bind_text(stmt, i, text);
268                         }
269                 }
270                 ret = ctsvc_stmt_step(stmt);
271                 if (CONTACTS_ERROR_NONE != ret) {
272                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
273                         ctsvc_stmt_finalize(stmt);
274                         break;
275                 }
276                 ctsvc_stmt_finalize(stmt);
277
278                 ctsvc_set_addressbook_noti();
279         } while (0);
280         CTSVC_RECORD_RESET_PROPERTY_FLAGS((ctsvc_record_s*)record);
281         free(set);
282
283         if (bind_text) {
284                 for (cursor = bind_text; cursor; cursor = cursor->next) {
285                         free(cursor->data);
286                         cursor->data = NULL;
287                 }
288                 g_slist_free(bind_text);
289         }
290
291         if (CONTACTS_ERROR_NONE != ret) {
292                 ctsvc_end_trans(false);
293                 return ret;
294         }
295
296         ret = ctsvc_end_trans(true);
297         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_end_trans() Fail(%d)", ret);
298
299         return CONTACTS_ERROR_NONE;
300 }
301
302 static int __ctsvc_db_addressbook_delete_record(int addressbook_id)
303 {
304         CTS_FN_CALL;
305
306         if (0 /*CTS_ADDRESSBOOK_INTERNAL*/ == addressbook_id)
307                 return ctsvc_addressbook_reset_internal_addressbook();
308
309         char query[CTS_SQL_MAX_LEN] = {0};
310         int ret = ctsvc_begin_trans();
311         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_begin_trans() Fail(%d)", ret);
312
313         ret = ctsvc_is_owner(addressbook_id);
314         if (CONTACTS_ERROR_NONE != ret) {
315                 if (CONTACTS_ERROR_PERMISSION_DENIED == ret)
316                         ERR("Does not have permission to delete address_book (%d)", addressbook_id);
317                 else
318                         ERR("ctsvc_is_owner Fail(%d)", ret);
319                 ctsvc_end_trans(false);
320                 return ret;
321         }
322
323         snprintf(query, sizeof(query), "DELETE FROM %s WHERE addressbook_id = %d",
324                         CTS_TABLE_ADDRESSBOOKS, addressbook_id);
325
326         /* DOING JOB */
327         do {
328                 ret = ctsvc_query_exec(query);
329                 if (CONTACTS_ERROR_NONE != ret) {
330                         /* LCOV_EXCL_START */
331                         ERR("ctsvc_query_exec() Fail(%d)", ret);
332                         break;
333                         /* LCOV_EXCL_STOP */
334                 }
335
336                 ret = ctsvc_db_change();
337                 if (0 < ret) {
338                         ctsvc_set_my_profile_noti();
339                         ctsvc_set_contact_noti();
340                         /* person noti will set in ctsvc_person_do_garbage_collection : ctsvc_set_person_noti(); */
341                         ctsvc_set_group_noti();
342                         ctsvc_set_addressbook_noti();
343                 } else {
344                         ret = CONTACTS_ERROR_NO_DATA;
345                         break;
346                 }
347
348                 ret = ctsvc_person_do_garbage_collection();
349                 if (CONTACTS_ERROR_NONE != ret) {
350                         /* LCOV_EXCL_START */
351                         ERR("ctsvc_person_garbagecollection() Fail(%d)", ret);
352                         break;
353                         /* LCOV_EXCL_STOP */
354                 }
355
356                 ret = ctsvc_end_trans(true);
357                 if (ret < CONTACTS_ERROR_NONE) {
358                         /* LCOV_EXCL_START */
359                         ERR("ctsvc_end_trans() Fail(%d)", ret);
360                         return ret;
361                         /* LCOV_EXCL_STOP */
362                 }
363
364                 return CONTACTS_ERROR_NONE;
365
366         } while (0);
367
368         ctsvc_end_trans(false);
369
370         return ret;
371 }
372
373 static int __ctsvc_db_addressbook_get_all_records(int offset, int limit,
374                 contacts_list_h *out_list)
375 {
376         int ret;
377         int len;
378         cts_stmt stmt;
379         char query[CTS_SQL_MAX_LEN] = {0};
380         contacts_list_h list;
381
382         len = snprintf(query, sizeof(query),
383                         "SELECT addressbook_id, addressbook_name, account_id, mode, last_sync_ver "
384                         "FROM "CTS_TABLE_ADDRESSBOOKS);
385
386         len += snprintf(query+len, sizeof(query)-len,
387                         " ORDER BY account_id, addressbook_id");
388
389         if (0 != limit) {
390                 len += snprintf(query+len, sizeof(query)-len, " LIMIT %d", limit);
391                 if (0 < offset)
392                         len += snprintf(query+len, sizeof(query)-len, " OFFSET %d", offset);
393         }
394
395         ret = ctsvc_query_prepare(query, &stmt);
396         RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
397
398         contacts_list_create(&list);
399         while ((ret = ctsvc_stmt_step(stmt))) {
400                 contacts_record_h record;
401                 if (1 != ret) {
402                         /* LCOV_EXCL_START */
403                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
404                         ctsvc_stmt_finalize(stmt);
405                         contacts_list_destroy(list, true);
406                         return ret;
407                         /* LCOV_EXCL_STOP */
408                 }
409                 __ctsvc_db_addressbook_value_set(stmt, &record);
410
411                 ctsvc_list_prepend(list, record);
412         }
413         ctsvc_stmt_finalize(stmt);
414         ctsvc_list_reverse(list);
415
416         *out_list = (contacts_list_h)list;
417         return CONTACTS_ERROR_NONE;
418 }
419
420 static int __ctsvc_db_addressbook_get_records_with_query(contacts_query_h query, int offset, int limit, contacts_list_h *out_list)
421 {
422         int ret;
423         int i;
424         int field_count;
425         ctsvc_query_s *s_query;
426         cts_stmt stmt;
427         contacts_list_h list;
428         ctsvc_addressbook_s *addressbook;
429
430         RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
431         s_query = (ctsvc_query_s*)query;
432
433         ret = ctsvc_db_make_get_records_query_stmt(s_query, offset, limit, &stmt);
434         RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_db_make_get_records_query_stmt fail(%d)", ret);
435
436         contacts_list_create(&list);
437         while ((ret = ctsvc_stmt_step(stmt))) {
438                 contacts_record_h record;
439                 if (1 != ret) {
440                         /* LCOV_EXCL_START */
441                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
442                         ctsvc_stmt_finalize(stmt);
443                         contacts_list_destroy(list, true);
444                         return ret;
445                         /* LCOV_EXCL_STOP */
446                 }
447
448                 contacts_record_create(_contacts_address_book._uri, &record);
449                 addressbook = (ctsvc_addressbook_s*)record;
450                 if (0 == s_query->projection_count) {
451                         field_count = s_query->property_count;
452                 } else {
453                         field_count = s_query->projection_count;
454                         ret = ctsvc_record_set_projection_flags(record, s_query->projection,
455                                         s_query->projection_count, s_query->property_count);
456
457                         if (CONTACTS_ERROR_NONE != ret)
458                                 ASSERT_NOT_REACHED("To set projection is Fail.\n");
459                 }
460
461                 for (i = 0; i < field_count; i++) {
462                         char *temp;
463                         int property_id;
464                         if (0 == s_query->projection_count)
465                                 property_id = s_query->properties[i].property_id;
466                         else
467                                 property_id = s_query->projection[i];
468
469                         switch (property_id) {
470                         case CTSVC_PROPERTY_ADDRESSBOOK_ID:
471                                 addressbook->id = ctsvc_stmt_get_int(stmt, i);
472                                 break;
473                         case CTSVC_PROPERTY_ADDRESSBOOK_NAME:
474                                 temp = ctsvc_stmt_get_text(stmt, i);
475                                 free(addressbook->name);
476                                 addressbook->name = SAFE_STRDUP(temp);
477                                 break;
478                         case CTSVC_PROPERTY_ADDRESSBOOK_MODE:
479                                 addressbook->mode = ctsvc_stmt_get_int(stmt, i);
480                                 break;
481                         case CTSVC_PROPERTY_ADDRESSBOOK_ACCOUNT_ID:
482                                 addressbook->account_id = ctsvc_stmt_get_int(stmt, i);
483                                 break;
484                         default:
485                                 break;
486                         }
487                 }
488                 ctsvc_list_prepend(list, record);
489         }
490         ctsvc_stmt_finalize(stmt);
491         ctsvc_list_reverse(list);
492
493         *out_list = (contacts_list_h)list;
494
495         return CONTACTS_ERROR_NONE;
496 }
497
498 ctsvc_db_plugin_info_s ctsvc_db_plugin_addressbook = {
499         .is_query_only = false,
500         .insert_record = __ctsvc_db_addressbook_insert_record,
501         .get_record = __ctsvc_db_addressbook_get_record,
502         .update_record = __ctsvc_db_addressbook_update_record,
503         .delete_record = __ctsvc_db_addressbook_delete_record,
504         .get_all_records = __ctsvc_db_addressbook_get_all_records,
505         .get_records_with_query = __ctsvc_db_addressbook_get_records_with_query,
506         .insert_records = NULL,
507         .update_records = NULL,
508         .delete_records = NULL,
509         .get_count = NULL,
510         .get_count_with_query = NULL,
511         .replace_record = NULL,
512         .replace_records = NULL,
513 };
514