[SVACE Issue Fixes]
[platform/core/pim/contacts-service.git] / server / db / ctsvc_db_plugin_activity.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 "contacts.h"
20 #include "ctsvc_internal.h"
21 #include "ctsvc_db_schema.h"
22 #include "ctsvc_db_sqlite.h"
23 #include "ctsvc_list.h"
24 #include "ctsvc_db_plugin_activity_photo_helper.h"
25 #include "ctsvc_db_plugin_contact_helper.h"
26 #include "ctsvc_db_init.h"
27 #include "ctsvc_db_utils.h"
28 #include "ctsvc_record.h"
29 #include "ctsvc_db_query.h"
30 #include "ctsvc_notification.h"
31 #include "ctsvc_db_access_control.h"
32
33
34 static int __ctsvc_db_activity_insert_record(contacts_record_h record, int *id)
35 {
36         int ret;
37         int activity_id;
38         int addressbook_id;
39         cts_stmt stmt = NULL;
40         int count = 0;
41         char query[CTS_SQL_MAX_LEN] = {0};
42         ctsvc_activity_s *activity = (ctsvc_activity_s*)record;
43
44         RETV_IF(NULL == activity, CONTACTS_ERROR_INVALID_PARAMETER);
45         RETVM_IF(activity->id, CONTACTS_ERROR_INVALID_PARAMETER,
46                         "The activity has ID(%d)", activity->id);
47
48         RETVM_IF(activity->contact_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER,
49                         "The contact_id(%d) does not exist", activity->contact_id);
50
51         ret = ctsvc_begin_trans();
52         RETVM_IF(ret, ret, "contacts_svc_begin_trans() Fail(%d)", ret);
53
54         snprintf(query, sizeof(query),
55                         "SELECT addressbook_id from %s WHERE contact_id = %d",
56                         CTSVC_DB_VIEW_CONTACT, activity->contact_id);
57
58         ret = ctsvc_query_get_first_int_result(query, &addressbook_id);
59         if (CONTACTS_ERROR_NONE != ret) {
60                 ctsvc_end_trans(false);
61                 if (CONTACTS_ERROR_NO_DATA == ret) {
62                         /* LCOV_EXCL_START */
63                         ERR("No data : contact id (%d)", activity->contact_id);
64                         return CONTACTS_ERROR_INVALID_PARAMETER;
65                         /* LCOV_EXCL_STOP */
66                 } else {
67                         /* LCOV_EXCL_START */
68                         ERR("ctsvc_query_get_first_int_result() Fail(%d)", ret);
69                         return ret;
70                         /* LCOV_EXCL_STOP */
71                 }
72         }
73
74         ret = ctsvc_is_owner(addressbook_id);
75         if (CONTACTS_ERROR_NONE != ret) {
76                 if (CONTACTS_ERROR_PERMISSION_DENIED == ret)
77                         /* LCOV_EXCL_START */
78                         ERR("Does not have permission of address_book (%d)", addressbook_id);
79                 else
80                         ERR("ctsvc_is_owner() Fail(%d)", ret);
81                 ctsvc_end_trans(false);
82                 return ret;
83                 /* LCOV_EXCL_STOP */
84         }
85
86         snprintf(query, sizeof(query), "INSERT INTO "CTS_TABLE_ACTIVITIES"("
87                         "contact_id, source_name, status, timestamp, "
88                         "service_operation, uri) "
89                         "VALUES(%d, ?, ?, %d, ?, ?)",
90                         activity->contact_id, activity->timestamp);
91
92         ret = ctsvc_query_prepare(query, &stmt);
93         if (NULL == stmt) {
94                 /* LCOV_EXCL_START */
95                 ERR("ctsvc_query_prepare() Fail(%d)", ret);
96                 ctsvc_end_trans(false);
97                 return ret;
98                 /* LCOV_EXCL_STOP */
99         }
100
101         if (activity->source_name)
102                 ctsvc_stmt_bind_text(stmt, 1, activity->source_name);
103         if (activity->status)
104                 ctsvc_stmt_bind_text(stmt, 2, activity->status);
105         if (activity->service_operation)
106                 ctsvc_stmt_bind_text(stmt, 3, activity->service_operation);
107         if (activity->uri)
108                 ctsvc_stmt_bind_text(stmt, 4, activity->uri);
109
110         ret = ctsvc_stmt_step(stmt);
111         if (CONTACTS_ERROR_NONE != ret) {
112                 /* LCOV_EXCL_START */
113                 ERR("ctsvc_stmt_step() Fail(%d)", ret);
114                 ctsvc_stmt_finalize(stmt);
115                 ctsvc_end_trans(false);
116                 return ret;
117                 /* LCOV_EXCL_STOP */
118         }
119
120         activity_id = ctsvc_db_get_last_insert_id();
121
122         ctsvc_stmt_finalize(stmt);
123
124         if (activity->photos) {
125                 ret = contacts_list_get_count((contacts_list_h)activity->photos, &count);
126                 if (CONTACTS_ERROR_NONE == ret && 0 < count) {
127                         ctsvc_activity_photo_s *photo = NULL;
128                         contacts_record_h record = NULL;
129
130                         contacts_list_first((contacts_list_h)activity->photos);
131                         do {
132                                 contacts_list_get_current_record_p((contacts_list_h)activity->photos, &record);
133                                 photo = (ctsvc_activity_photo_s*)record;
134                                 ret = ctsvc_db_activity_photo_insert((contacts_record_h)photo, activity_id, NULL);
135                                 if (CONTACTS_ERROR_DB == ret) {
136                                         /* LCOV_EXCL_START */
137                                         ERR("return (%d)", ret);
138                                         break;
139                                         /* LCOV_EXCL_STOP */
140                                 }
141                         } while (CONTACTS_ERROR_NONE == contacts_list_next((contacts_list_h)activity->photos));
142                 }
143         }
144
145         ctsvc_set_activity_noti();
146         ctsvc_set_person_noti();
147
148         if (id)
149                 *id = activity_id;
150
151         ret = ctsvc_end_trans(true);
152         if (ret < CONTACTS_ERROR_NONE)
153                 return ret;
154         else
155                 return CONTACTS_ERROR_NONE;
156 }
157
158 static int __ctsvc_db_activity_value_set(cts_stmt stmt, contacts_record_h *record)
159 {
160         int i = 0;
161         char *temp;
162         ctsvc_activity_s *activity;
163
164         contacts_record_create(_contacts_activity._uri, record);
165         activity = (ctsvc_activity_s*)*record;
166
167         activity->id = ctsvc_stmt_get_int(stmt, i++);
168         activity->contact_id = ctsvc_stmt_get_int(stmt, i++);
169         temp = ctsvc_stmt_get_text(stmt, i++);
170         activity->source_name = SAFE_STRDUP(temp);
171         temp = ctsvc_stmt_get_text(stmt, i++);
172         activity->status = SAFE_STRDUP(temp);
173         activity->timestamp = ctsvc_stmt_get_int(stmt, i++);
174         temp = ctsvc_stmt_get_text(stmt, i++);
175         activity->service_operation = SAFE_STRDUP(temp);
176         temp = ctsvc_stmt_get_text(stmt, i++);
177         activity->uri = SAFE_STRDUP(temp);
178
179         return CONTACTS_ERROR_NONE;
180 }
181
182
183 static int __ctsvc_db_activity_get_record(int id, contacts_record_h *out_record)
184 {
185         char query[CTS_SQL_MAX_LEN] = {0};
186         int ret;
187         cts_stmt stmt = NULL;
188         contacts_record_h record;
189
190         snprintf(query, sizeof(query), "SELECT id, contact_id, source_name, status, "
191                         "timestamp, service_operation, uri "
192                         "FROM "CTSVC_DB_VIEW_ACTIVITY" WHERE id = %d", id);
193
194         ret = ctsvc_query_prepare(query, &stmt);
195         RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
196
197         ret = ctsvc_stmt_step(stmt);
198         if (1 /*CTS_TRUE*/ != ret) {
199                 /* LCOV_EXCL_START */
200                 ERR("ctsvc_stmt_step() Fail(%d)", ret);
201                 ctsvc_stmt_finalize(stmt);
202                 if (CONTACTS_ERROR_NONE == ret)
203                         return CONTACTS_ERROR_NO_DATA;
204                 else
205                         return ret;
206                 /* LCOV_EXCL_STOP */
207         }
208
209         __ctsvc_db_activity_value_set(stmt, &record);
210         ctsvc_stmt_finalize(stmt);
211
212         ctsvc_db_activity_photo_get_records(id, record);
213
214         *out_record = (contacts_record_h)record;
215
216         return CONTACTS_ERROR_NONE;
217 }
218
219 static int __ctsvc_db_activity_update_record(contacts_record_h record)
220 {
221         /* LCOV_EXCL_START */
222         ERR("Invalid operation : activity can not update, only insert/delete");
223         return CONTACTS_ERROR_INVALID_PARAMETER;
224         /* LCOV_EXCL_STOP */
225 }
226
227 static int __ctsvc_db_activity_delete_record(int id)
228 {
229         int ret;
230         int addressbook_id;
231         char query[CTS_SQL_MAX_LEN] = {0};
232
233         ret = ctsvc_begin_trans();
234         RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
235
236         snprintf(query, sizeof(query),
237                         "SELECT addressbook_id FROM "CTSVC_DB_VIEW_CONTACT" "
238                         "WHERE contact_id = (SELECT contact_id FROM "CTSVC_DB_VIEW_ACTIVITY" WHERE id = %d)", id);
239         ret = ctsvc_query_get_first_int_result(query, &addressbook_id);
240         if (CONTACTS_ERROR_NONE != ret) {
241                 /* LCOV_EXCL_START */
242                 ERR("No data : id (%d)", id);
243                 ctsvc_end_trans(false);
244                 return ret;
245                 /* LCOV_EXCL_STOP */
246         }
247
248         ret = ctsvc_is_owner(addressbook_id);
249         if (CONTACTS_ERROR_NONE != ret) {
250                 if (CONTACTS_ERROR_PERMISSION_DENIED == ret)
251                         /* LCOV_EXCL_START */
252                         ERR("Does not have permission of address_book (%d)", addressbook_id);
253                 else
254                         ERR("ctsvc_is_owner Fail(%d)", ret);
255                 ctsvc_end_trans(false);
256                 return ret;
257                 /* LCOV_EXCL_STOP */
258         }
259
260         snprintf(query, sizeof(query),
261                         "DELETE FROM "CTS_TABLE_ACTIVITIES" WHERE id = %d", id);
262         ret = ctsvc_query_exec(query);
263         if (CONTACTS_ERROR_NONE != ret) {
264                 /* LCOV_EXCL_START */
265                 ERR("ctsvc_query_exec() Fail(%d)", ret);
266                 ctsvc_end_trans(false);
267                 return ret;
268                 /* LCOV_EXCL_STOP */
269         }
270
271         ctsvc_set_activity_noti();
272         ctsvc_set_person_noti();
273
274         ret = ctsvc_end_trans(true);
275         if (ret < CONTACTS_ERROR_NONE)
276                 return ret;
277         else
278                 return CONTACTS_ERROR_NONE;
279 }
280
281 static int __ctsvc_db_activity_get_all_records(int offset, int limit,
282                 contacts_list_h *out_list)
283 {
284         int ret;
285         int len;
286         int activity_id;
287         cts_stmt stmt;
288         char query[CTS_SQL_MAX_LEN] = {0};
289         contacts_list_h list;
290
291         len = snprintf(query, sizeof(query),
292                         "SELECT id FROM "CTSVC_DB_VIEW_ACTIVITY);
293
294         if (0 != limit) {
295                 len += snprintf(query+len, sizeof(query)-len, " LIMIT %d", limit);
296                 if (0 < offset)
297                         len += snprintf(query+len, sizeof(query)-len, " OFFSET %d", offset);
298         }
299
300         ret = ctsvc_query_prepare(query, &stmt);
301         RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
302
303         contacts_list_create(&list);
304         while ((ret = ctsvc_stmt_step(stmt))) {
305                 contacts_record_h record;
306                 if (1 != ret) {
307                         /* LCOV_EXCL_START */
308                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
309                         ctsvc_stmt_finalize(stmt);
310                         contacts_list_destroy(list, true);
311                         return ret;
312                         /* LCOV_EXCL_STOP */
313                 }
314                 activity_id = ctsvc_stmt_get_int(stmt, 0);
315                 ret = ctsvc_db_get_record(_contacts_activity._uri, activity_id, &record);
316                 if (CONTACTS_ERROR_NONE != ret) {
317                         /* LCOV_EXCL_START */
318                         ERR("contacts_db_get_record() Fail(%d)", ret);
319                         ctsvc_stmt_finalize(stmt);
320                         contacts_list_destroy(list, true);
321                         return ret;
322                         /* LCOV_EXCL_STOP */
323                 }
324                 ctsvc_list_prepend(list, record);
325         }
326         ctsvc_stmt_finalize(stmt);
327         ctsvc_list_reverse(list);
328
329         *out_list = (contacts_list_h)list;
330         return CONTACTS_ERROR_NONE;
331 }
332
333 static int __ctsvc_db_activity_get_records_with_query(contacts_query_h query, int offset, int limit, contacts_list_h *out_list)
334 {
335         int ret;
336         int i;
337         int field_count;
338         int activity_id = 0;
339         ctsvc_query_s *s_query;
340         cts_stmt stmt;
341         contacts_list_h list;
342         ctsvc_activity_s *activity;
343         bool had_activity_id = false;
344
345         RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
346         s_query = (ctsvc_query_s*)query;
347
348         if (s_query->projection) {
349                 for (i = 0; i < s_query->projection_count; i++) {
350                         if (s_query->projection[i] == CTSVC_PROPERTY_ACTIVITY_ID) {
351                                 had_activity_id = true;
352                                 break;
353                         }
354                 }
355         } else {
356                 s_query->projection_count = 0;
357                 had_activity_id = true;
358         }
359
360         if (false == had_activity_id) {
361                 s_query->projection = realloc(s_query->projection, s_query->projection_count+1);
362                 if (NULL == s_query->projection) {
363                         /* LCOV_EXCL_START */
364                         ERR("realloc() Fail");
365                         return CONTACTS_ERROR_OUT_OF_MEMORY;
366                         /* LCOV_EXCL_STOP */
367                 }
368                 s_query->projection[s_query->projection_count] = CTSVC_PROPERTY_ACTIVITY_ID;
369                 s_query->projection_count++;
370         }
371
372         ret = ctsvc_db_make_get_records_query_stmt(s_query, offset, limit, &stmt);
373         RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_db_make_get_records_query_stmt fail(%d)", ret);
374
375         contacts_list_create(&list);
376         while ((ret = ctsvc_stmt_step(stmt))) {
377                 contacts_record_h record;
378                 if (1 /*CTS_TRUE */ != ret) {
379                         /* LCOV_EXCL_START */
380                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
381                         ctsvc_stmt_finalize(stmt);
382                         contacts_list_destroy(list, true);
383                         return ret;
384                         /* LCOV_EXCL_STOP */
385                 }
386
387                 contacts_record_create(_contacts_activity._uri, &record);
388                 activity = (ctsvc_activity_s*)record;
389                 if (0 == s_query->projection_count) {
390                         field_count = s_query->property_count;
391                 } else {
392                         field_count = s_query->projection_count;
393                         ret = ctsvc_record_set_projection_flags(record, s_query->projection,
394                                         s_query->projection_count, s_query->property_count);
395
396                         if (CONTACTS_ERROR_NONE != ret)
397                                 ASSERT_NOT_REACHED("To set projection is Fail\n");
398                 }
399
400                 for (i = 0; i < field_count; i++) {
401                         char *temp;
402                         int property_id;
403                         if (0 == s_query->projection_count)
404                                 property_id = s_query->properties[i].property_id;
405                         else
406                                 property_id = s_query->projection[i];
407
408
409                         switch (property_id) {
410                         case CTSVC_PROPERTY_ACTIVITY_ID:
411                                 activity_id = ctsvc_stmt_get_int(stmt, i);
412                                 if (had_activity_id)
413                                         activity->id = activity_id;
414                                 break;
415                         case CTSVC_PROPERTY_ACTIVITY_CONTACT_ID:
416                                 activity->contact_id = ctsvc_stmt_get_int(stmt, i);
417                                 break;
418                         case CTSVC_PROPERTY_ACTIVITY_SOURCE_NAME:
419                                 temp = ctsvc_stmt_get_text(stmt, i);
420                                 free(activity->source_name);
421                                 activity->source_name = SAFE_STRDUP(temp);
422                                 break;
423                         case CTSVC_PROPERTY_ACTIVITY_STATUS:
424                                 temp = ctsvc_stmt_get_text(stmt, i);
425                                 free(activity->status);
426                                 activity->status = SAFE_STRDUP(temp);
427                                 break;
428                         case CTSVC_PROPERTY_ACTIVITY_TIMESTAMP:
429                                 activity->timestamp = ctsvc_stmt_get_int(stmt, i);
430                                 break;
431                         case CTSVC_PROPERTY_ACTIVITY_SERVICE_OPERATION:
432                                 temp = ctsvc_stmt_get_text(stmt, i);
433                                 free(activity->service_operation);
434                                 activity->service_operation = SAFE_STRDUP(temp);
435                                 break;
436                         case CTSVC_PROPERTY_ACTIVITY_URI:
437                                 temp = ctsvc_stmt_get_text(stmt, i);
438                                 free(activity->uri);
439                                 activity->uri = SAFE_STRDUP(temp);
440                                 break;
441                         default:
442                                 break;
443                         }
444                 }
445                 ctsvc_db_activity_photo_get_records(activity_id, record);
446
447                 ctsvc_list_prepend(list, record);
448         }
449         ctsvc_stmt_finalize(stmt);
450         ctsvc_list_reverse(list);
451
452         *out_list = list;
453         return CONTACTS_ERROR_NONE;
454 }
455
456 ctsvc_db_plugin_info_s ctsvc_db_plugin_activity = {
457         .is_query_only = false,
458         .insert_record = __ctsvc_db_activity_insert_record,
459         .get_record = __ctsvc_db_activity_get_record,
460         .update_record = __ctsvc_db_activity_update_record,
461         .delete_record = __ctsvc_db_activity_delete_record,
462         .get_all_records = __ctsvc_db_activity_get_all_records,
463         .get_records_with_query = __ctsvc_db_activity_get_records_with_query,
464         .insert_records = NULL,
465         .update_records = NULL,
466         .delete_records = NULL,
467         .get_count = NULL,
468         .get_count_with_query = NULL,
469         .replace_record = NULL,
470         .replace_records = NULL,
471 };
472