51c479abebc738b1ad9a53cd7d75e6e7cc2ae4ec
[framework/appfw/data-control.git] / src / data-control-sql.c
1 #include <dlog.h>
2 #include <errno.h>
3 #include <search.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <glib.h>
9 #include <pthread.h>
10
11 #include <appsvc/appsvc.h>
12 #include <aul/aul.h>
13 #include <bundle.h>
14 #include <pkgmgr-info.h>
15 #include <security-server.h>
16
17 #include "data-control-sql.h"
18 #include "data-control-internal.h"
19
20 #define REQUEST_PATH_MAX                512
21 #define MAX_REQUEST_ARGUMENT_SIZE       1048576 // 1MB
22 #define MAX_ROW_COUNT           1024
23
24 struct datacontrol_s {
25         char *provider_id;
26         char *data_id;
27 };
28
29 typedef struct
30 {
31     char *provider_id;
32     char *app_id;
33     char *data_id;
34     char *access_info;
35     void *user_data;
36     datacontrol_sql_response_cb *sql_response_cb;
37 } sql_response_cb_s;
38
39
40 static void *datacontrol_sql_tree_root = NULL;
41
42 static void
43 datacontrol_sql_call_cb(const char *provider_id, int request_id, datacontrol_request_type type
44         , const char *data_id, bool provider_result, const char *error, long long insert_rowid, resultset_cursor* cursor, void* data)
45 {
46         SECURE_LOGI("datacontrol_sql_call_cb, dataID: %s", data_id);
47
48         datacontrol_sql_response_cb *callback = NULL;
49
50         sql_response_cb_s *sql_dc = NULL;
51         sql_dc = (sql_response_cb_s *)data;
52         callback = sql_dc->sql_response_cb;
53         if (!callback)
54         {
55                 LOGE("no listener set");
56                 return;
57         }
58
59         datacontrol_h provider;
60         datacontrol_sql_create(&provider);
61
62         datacontrol_sql_set_provider_id(provider, provider_id);
63         datacontrol_sql_set_data_id(provider, data_id);
64
65         switch (type)
66         {
67                 case DATACONTROL_TYPE_SQL_SELECT:
68                 {
69                         LOGI("SELECT");
70                         if (callback != NULL && callback->select != NULL)
71                         {
72                                 callback->select(request_id, provider, cursor, provider_result, error, sql_dc->user_data);
73                         }
74                         else
75                         {
76                                 LOGI("No registered callback function");
77                         }
78
79                         break;
80                 }
81                 case DATACONTROL_TYPE_SQL_INSERT:
82                 {
83                         SECURE_LOGI("INSERT row_id: %lld", insert_rowid);
84                         if (callback != NULL && callback->insert != NULL)
85                         {
86                                 callback->insert(request_id, provider, insert_rowid, provider_result, error, sql_dc->user_data);
87                         }
88                         else
89                         {
90                                 LOGI("No registered callback function");
91                         }
92
93                         break;
94                 }
95                 case DATACONTROL_TYPE_SQL_UPDATE:
96                 {
97                         LOGI("UPDATE");
98                         if (callback != NULL && callback->update != NULL)
99                         {
100                                 callback->update(request_id, provider, provider_result, error, sql_dc->user_data);
101                         }
102                         else
103                         {
104                                 LOGI("No registered callback function");
105                         }
106
107                         break;
108                 }
109                 case DATACONTROL_TYPE_SQL_DELETE:
110                 {
111                         LOGI("DELETE");
112                         if (callback != NULL && callback->delete != NULL)
113                         {
114                                 callback->delete(request_id, provider, provider_result, error, sql_dc->user_data);
115                         }
116                         else
117                         {
118                                 LOGI("No registered callback function");
119                         }
120                         break;
121                 }
122                 default:
123                         break;
124         }
125
126         datacontrol_sql_destroy(provider);
127 }
128
129 static void
130 datacontrol_sql_instance_free(void *datacontrol_sql_instance)
131 {
132         sql_response_cb_s *dc = (sql_response_cb_s *)datacontrol_sql_instance;
133         if (dc)
134         {
135                 free(dc->provider_id);
136                 free(dc->data_id);
137                 free(dc->app_id);
138                 free(dc->access_info);
139                 free(datacontrol_sql_instance);
140         }
141
142         return;
143 }
144
145 static int
146 datacontrol_sql_instance_compare(const void *l_datacontrol_sql_instance, const void *r_datacontrol_sql_instance)
147 {
148         sql_response_cb_s *dc_left = (sql_response_cb_s *)l_datacontrol_sql_instance;
149         sql_response_cb_s *dc_right = (sql_response_cb_s *)r_datacontrol_sql_instance;
150         return strcmp(dc_left->provider_id, dc_right->provider_id);
151 }
152
153
154 static int
155 datacontrol_sql_handle_cb(bundle* b, int request_code, appsvc_result_val res, void* data)
156 {
157         SECURE_LOGI("datacontrol_sql_handle_cb, request_code: %d, result: %d", request_code, res);
158
159         int ret = 0;
160         const char** result_list = NULL;
161         resultset_cursor *cursor = NULL;
162         const char* provider_id = NULL;
163         const char* data_id = NULL;
164         const char* error_message = NULL;
165         long long insert_rowid = -1;
166         datacontrol_request_type request_type = 0;
167         int request_id = -1;
168         int result_list_len = 0;
169         int provider_result = 0;
170         const char* resultset_path = NULL;
171         const char* p = NULL;
172
173         if (b)
174         {
175                 p = appsvc_get_data(b, OSP_K_REQUEST_ID);
176                 if (!p)
177                 {
178                         LOGE("Invalid Bundle: request_id is null");
179                         return DATACONTROL_ERROR_INVALID_PARAMETER;
180                 }
181                 else
182                 {
183                         request_id = atoi(p);
184                 }
185
186                 SECURE_LOGI("Request ID: %d", request_id);
187
188                 // result list
189                 result_list = appsvc_get_data_array(b, OSP_K_ARG, &result_list_len);
190                 if (!result_list)
191                 {
192                         LOGE("Invalid Bundle: arguement list is null");
193                         return DATACONTROL_ERROR_INVALID_PARAMETER;
194                 }
195
196                 p = result_list[0]; // result list[0] = provider_result
197                 if (!p)
198                 {
199                         LOGE("Invalid Bundle: provider_result is null");
200                         return DATACONTROL_ERROR_INVALID_PARAMETER;
201                 }
202
203                 LOGI("Provider result: %s", p);
204
205                 provider_result = atoi(p);
206
207                 error_message = result_list[1]; // result list[1] = error
208                 if (!error_message)
209                 {
210                         LOGE("Invalid Bundle: error_message is null");
211                         return DATACONTROL_ERROR_INVALID_PARAMETER;
212                 }
213
214                 LOGI("Error message: %s", error_message);
215
216                 p = appsvc_get_data(b, OSP_K_DATACONTROL_REQUEST_TYPE);
217                 if (!p)
218                 {
219                         LOGE("Invalid Bundle: data-control request type is null");
220                         return DATACONTROL_ERROR_INVALID_PARAMETER;
221                 }
222
223                 request_type = (datacontrol_request_type)atoi(p);
224
225                 provider_id = appsvc_get_data(b, OSP_K_DATACONTROL_PROVIDER);
226                 if (!provider_id)
227                 {
228                         LOGE("Invalid Bundle: provider_id is null");
229                         return DATACONTROL_ERROR_INVALID_PARAMETER;
230                 }
231
232                 data_id = appsvc_get_data(b, OSP_K_DATACONTROL_DATA);
233                 if (!data_id)
234                 {
235                         LOGE("Invalid Bundle: data_id is null");
236                         return DATACONTROL_ERROR_INVALID_PARAMETER;
237                 }
238
239                 SECURE_LOGI("Provider ID: %s, Data ID: %s, Operation type: %d", provider_id, data_id, request_type);
240
241                 switch (request_type)
242                 {
243                         case DATACONTROL_TYPE_SQL_SELECT:
244                         {
245                                 LOGI("SELECT RESPONSE");
246                                 if (provider_result)
247                                 {
248                                         resultset_path = result_list[2]; // result list[2]
249                                         if (!resultset_path)
250                                         {
251                                                 LOGE("sql query result path is null");
252                                                 return DATACONTROL_ERROR_INVALID_PARAMETER;
253                                         }
254
255                                         SECURE_LOGI("resultset_path: %s", resultset_path);
256
257                                         if (strcmp(resultset_path, "NoResultSet") != 0) // Result set exists
258                                         {
259                                                 cursor = datacontrol_sql_get_cursor(resultset_path);
260                                                 if (!cursor)
261                                                 {
262                                                         LOGE("failed to get cursor on sql query resultset");
263                                                         return DATACONTROL_ERROR_INVALID_PARAMETER;
264                                                 }
265                                         }
266                                 }
267                                 break;
268                         }
269                         case DATACONTROL_TYPE_SQL_INSERT:
270                         {
271                                 LOGI("INSERT RESPONSE");
272                                 if (provider_result)
273                                 {
274                                         p = result_list[2]; // result list[2]
275                                         if (!p)
276                                         {
277                                                 LOGE("Invalid Bundle: insert row_id is null");
278                                                 return DATACONTROL_ERROR_INVALID_PARAMETER;
279                                         }
280
281                                         insert_rowid = atoll(p);
282                                 }
283                                 break;
284                         }
285                         case DATACONTROL_TYPE_SQL_UPDATE:
286                         case DATACONTROL_TYPE_SQL_DELETE:
287                         {
288                                 LOGI("UPDATE or DELETE RESPONSE");
289                                 break;
290                         }
291
292                         default:
293                                 break;
294                 }
295
296         }
297         else
298         {
299                 LOGE("the bundle returned from datacontrol-provider-service is null");
300                 return DATACONTROL_ERROR_INVALID_PARAMETER;
301         }
302
303         if (request_type >=  DATACONTROL_TYPE_SQL_SELECT && request_type <=  DATACONTROL_TYPE_SQL_DELETE)
304         {
305                 datacontrol_sql_call_cb(provider_id, request_id, request_type, data_id, provider_result, error_message, insert_rowid, cursor, data);
306                 if ((request_type == DATACONTROL_TYPE_SQL_SELECT) && (cursor))
307                 {
308                         datacontrol_sql_remove_cursor(cursor);
309                 }
310
311                 ret = DATACONTROL_ERROR_NONE;
312         }
313         else
314         {
315                 ret = DATACONTROL_ERROR_INVALID_PARAMETER;
316         }
317
318         return ret;
319 }
320
321 static void
322 app_svc_res_cb_sql(bundle* b, int request_code, appsvc_result_val res, void* data)
323 {
324         LOGI("app_svc_res_cb_sql, request_code: %d, result: %d", request_code, res);
325
326         if (data)
327         {
328                 datacontrol_sql_handle_cb(b, request_code, res, data);
329         }
330         else
331         {
332                 LOGE("error: listener information is null");
333         }
334 }
335
336
337 static int
338 datacontrol_sql_request_provider(datacontrol_h provider, datacontrol_request_type type, bundle *arg_list, int request_id)
339 {
340         SECURE_LOGI("SQL Data control request, type: %d, request id: %d", type, request_id);
341
342         char *app_id = NULL;
343         void *data = NULL;
344
345         if ((int)type <= (int)DATACONTROL_TYPE_SQL_DELETE)
346         {
347                 if ((int)type < (int)DATACONTROL_TYPE_SQL_SELECT)
348                 {
349                         LOGE("invalid request type: %d", (int)type);
350                         return DATACONTROL_ERROR_INVALID_PARAMETER;
351                 }
352
353                 if (!datacontrol_sql_tree_root)
354                 {
355                         LOGE("the listener tree is empty");
356                         return DATACONTROL_ERROR_INVALID_PARAMETER;
357                 }
358
359                 sql_response_cb_s *sql_dc_temp = (sql_response_cb_s *)calloc(sizeof(sql_response_cb_s),1);
360                 if (!sql_dc_temp)
361                 {
362                         LOGE("failed to create sql datacontrol");
363                         return DATACONTROL_ERROR_OUT_OF_MEMORY;
364                 }
365
366                 sql_dc_temp->provider_id = strdup(provider->provider_id);
367                 if (!sql_dc_temp->provider_id)
368                 {
369                         LOGE("failed to assign provider id to sql data control: %d", errno);
370                         free(sql_dc_temp);
371                         return DATACONTROL_ERROR_OUT_OF_MEMORY;
372                 }
373
374                 sql_dc_temp->data_id = strdup(provider->data_id);
375                 if (!sql_dc_temp->data_id)
376                 {
377                         LOGE("failed to assign data id to sql data control: %d", errno);
378                         free(sql_dc_temp->provider_id);
379                         free(sql_dc_temp);
380                         return DATACONTROL_ERROR_OUT_OF_MEMORY;
381                 }
382
383                 sql_dc_temp->app_id = NULL;
384                 sql_dc_temp->access_info = NULL;
385                 sql_dc_temp->user_data = NULL;
386                 sql_dc_temp->sql_response_cb = NULL;
387
388                 void *sql_dc_returned = NULL;
389                 sql_dc_returned = tfind(sql_dc_temp, &datacontrol_sql_tree_root, datacontrol_sql_instance_compare);
390
391                 datacontrol_sql_instance_free(sql_dc_temp);
392
393                 if (!sql_dc_returned)
394                 {
395                         LOGE("sql datacontrol returned after tfind is null");
396                         return DATACONTROL_ERROR_IO_ERROR;
397                 }
398
399                 sql_response_cb_s *sql_dc = *(sql_response_cb_s **)sql_dc_returned;
400                 app_id = sql_dc->app_id;
401                 data = sql_dc;
402
403                 SECURE_LOGI("SQL datacontrol appid: %s", sql_dc->app_id);
404         }
405
406         char caller_app_id[255];
407         pid_t pid = getpid();
408         if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0)
409         {
410                 SECURE_LOGE("Failed to get appid by pid(%d).", pid);
411                 return DATACONTROL_ERROR_INVALID_PARAMETER;
412         }
413
414         appsvc_set_operation(arg_list, APPSVC_OPERATION_DEFAULT);
415         appsvc_set_appid(arg_list, app_id);
416         bundle_add_str(arg_list, OSP_K_CALLER_TYPE, OSP_V_CALLER_TYPE_OSP);
417         bundle_add_str(arg_list, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_DATACONTROL);
418         bundle_add_str(arg_list, OSP_K_DATACONTROL_PROTOCOL_VERSION, OSP_V_VERSION_2_1_0_3);
419         bundle_add_str(arg_list, AUL_K_CALLER_APPID, caller_app_id);
420         bundle_add_str(arg_list, AUL_K_NO_CANCEL, "1");
421
422
423         char datacontrol_request_operation[MAX_LEN_DATACONTROL_REQ_TYPE] = {0, };
424         snprintf(datacontrol_request_operation, MAX_LEN_DATACONTROL_REQ_TYPE, "%d", (int)(type));
425         bundle_add_str(arg_list, OSP_K_DATACONTROL_REQUEST_TYPE, datacontrol_request_operation);
426
427         char req_id[32] = {0, };
428         snprintf(req_id, 32, "%d", request_id);
429         bundle_add_str(arg_list, OSP_K_REQUEST_ID, req_id);
430
431         // For DataControl CAPI
432         bundle_add_str(arg_list, AUL_K_DATA_CONTROL_TYPE, "CORE");
433
434         SECURE_LOGI("SQL data control request - provider id: %s, data id: %s, provider appid: %s, request ID: %s", provider->provider_id, provider->data_id, app_id, req_id);
435
436         pid = -1;
437         int count = 0;
438         const int TRY_COUNT = 4;
439         const int TRY_SLEEP_TIME = 65000;
440         do
441         {
442                 pid = appsvc_run_service(arg_list, request_id, app_svc_res_cb_sql, data);
443                 if (pid >= 0)
444                 {
445                         SECURE_LOGI("Launch the provider app successfully: %d", pid);
446                         return DATACONTROL_ERROR_NONE;
447                 }
448                 else if (pid == APPSVC_RET_EINVAL)
449                 {
450                         SECURE_LOGE("not able to launch service: %d", pid);
451                         return DATACONTROL_ERROR_INVALID_PARAMETER;
452                 }
453
454                 count++;
455
456                 usleep(TRY_SLEEP_TIME);
457         }
458         while (count < TRY_COUNT);
459
460         SECURE_LOGE("unable to launch service: %d", pid);
461         return DATACONTROL_ERROR_IO_ERROR;
462 }
463
464 int
465 datacontrol_sql_create(datacontrol_h *provider)
466 {
467         struct datacontrol_s *request;
468
469         if (provider == NULL)
470         {
471                 return DATACONTROL_ERROR_INVALID_PARAMETER;
472         }
473
474         request = malloc(sizeof(struct datacontrol_s));
475         if (request == NULL)
476         {
477                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
478         }
479
480         request->provider_id = NULL;
481         request->data_id = NULL;
482
483         *provider = request;
484
485         return 0;
486 }
487
488 int
489 datacontrol_sql_destroy(datacontrol_h provider)
490 {
491         if (provider == NULL)
492         {
493                 return DATACONTROL_ERROR_INVALID_PARAMETER;
494         }
495
496         if (provider->provider_id != NULL)
497         {
498                 free(provider->provider_id);
499         }
500
501         if (provider->data_id != NULL)
502         {
503                 free(provider->data_id);
504         }
505
506         free(provider);
507         return 0;
508 }
509
510 int
511 datacontrol_sql_set_provider_id(datacontrol_h provider, const char *provider_id)
512 {
513         if (provider == NULL || provider_id == NULL)
514         {
515                 return DATACONTROL_ERROR_INVALID_PARAMETER;
516         }
517
518         if (provider->provider_id != NULL)
519         {
520                 free(provider->provider_id);
521         }
522
523         provider->provider_id = strdup(provider_id);
524         if (provider->provider_id == NULL)
525         {
526                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
527         }
528
529         return 0;
530 }
531
532 int
533 datacontrol_sql_get_provider_id(datacontrol_h provider, char **provider_id)
534 {
535         if (provider == NULL || provider_id == NULL)
536         {
537                 return DATACONTROL_ERROR_INVALID_PARAMETER;
538         }
539
540         if (provider->provider_id != NULL)
541         {
542                 *provider_id = strdup(provider->provider_id);
543                 if (*provider_id == NULL)
544                 {
545                         return DATACONTROL_ERROR_OUT_OF_MEMORY;
546                 }
547         }
548         else
549         {
550                 *provider_id = NULL;
551         }
552
553         return 0;
554 }
555
556 int
557 datacontrol_sql_set_data_id(datacontrol_h provider, const char *data_id)
558 {
559         if (provider == NULL || data_id == NULL)
560         {
561                 return DATACONTROL_ERROR_INVALID_PARAMETER;
562         }
563
564         if (provider->data_id != NULL)
565         {
566                 free(provider->data_id);
567         }
568
569         provider->data_id = strdup(data_id);
570         if (provider->data_id == NULL)
571         {
572                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
573         }
574
575         return 0;
576 }
577
578 int
579 datacontrol_sql_get_data_id(datacontrol_h provider, char **data_id)
580 {
581         if (provider == NULL || data_id == NULL)
582         {
583                 return DATACONTROL_ERROR_INVALID_PARAMETER;
584         }
585
586         if (provider->data_id != NULL)
587         {
588                 *data_id = strdup(provider->data_id);
589                 if (*data_id == NULL)
590                 {
591                         return DATACONTROL_ERROR_OUT_OF_MEMORY;
592                 }
593         }
594         else
595         {
596                 *data_id = NULL;
597         }
598         return 0;
599 }
600
601 int
602 datacontrol_sql_register_response_cb(datacontrol_h provider, datacontrol_sql_response_cb* callback, void *user_data)
603 {
604         int ret = 0;
605         char* app_id = NULL;
606         char* access = NULL;
607
608         ret = pkgmgrinfo_appinfo_get_datacontrol_info(provider->provider_id, "Sql", &app_id, &access);
609         if (ret != PMINFO_R_OK)
610         {
611                 LOGE("unable to get sql data control information: %d", ret);
612                 return DATACONTROL_ERROR_IO_ERROR;
613         }
614
615         SECURE_LOGI("data control provider appid = %s", app_id);
616
617         sql_response_cb_s *sql_dc_temp = (sql_response_cb_s *)calloc(sizeof(sql_response_cb_s),1);
618         if (!sql_dc_temp)
619         {
620                 LOGE("unable to create a temporary sql data control");
621                 ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
622                 goto EXCEPTION;
623         }
624
625         sql_dc_temp->provider_id = strdup(provider->provider_id);
626         if (!sql_dc_temp->provider_id)
627         {
628                 LOGE("unable to assign provider_id to sql data control: %d", errno);
629                 ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
630                 goto EXCEPTION;
631         }
632
633         sql_dc_temp->data_id = strdup(provider->data_id);
634         if (!sql_dc_temp->data_id)
635         {
636                 LOGE("unable to assign data_id to sql data control: %d", errno);
637                 ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
638                 goto EXCEPTION;
639         }
640
641         sql_dc_temp->app_id = app_id;
642         sql_dc_temp->access_info = access;
643         sql_dc_temp->user_data = user_data;
644         sql_dc_temp->sql_response_cb = callback;
645
646         void *sql_dc_returned = NULL;
647         sql_dc_returned = tsearch(sql_dc_temp, &datacontrol_sql_tree_root, datacontrol_sql_instance_compare);
648
649         sql_response_cb_s *sql_dc = *(sql_response_cb_s **)sql_dc_returned;
650         if (sql_dc != sql_dc_temp)
651         {
652                 sql_dc->sql_response_cb = callback;
653                 sql_dc->user_data = user_data;
654                 LOGI("the data control is already set");
655                 datacontrol_sql_instance_free(sql_dc_temp);
656         }
657
658         return DATACONTROL_ERROR_NONE;
659
660 EXCEPTION:
661         if (access)
662                 free(access);
663         if (app_id)
664                 free(app_id);
665         if (sql_dc_temp)
666         {
667                 if (sql_dc_temp->provider_id)
668                         free(sql_dc_temp->provider_id);
669                 if (sql_dc_temp->data_id)
670                         free(sql_dc_temp->data_id);
671                 free(sql_dc_temp);
672         }
673
674         return ret;
675 }
676
677 int
678 datacontrol_sql_unregister_response_cb(datacontrol_h provider)
679 {
680         int ret = DATACONTROL_ERROR_NONE;
681
682         sql_response_cb_s *sql_dc_temp = (sql_response_cb_s *)calloc(sizeof(sql_response_cb_s),1);
683
684         if (!sql_dc_temp)
685         {
686                 LOGE("unable to create a temporary sql data control");
687                 ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
688                 goto EXCEPTION;
689         }
690
691         sql_dc_temp->provider_id = strdup(provider->provider_id);
692         if (!sql_dc_temp->provider_id)
693         {
694                 LOGE("unable to assign provider_id to sql data control: %d", errno);
695                 ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
696                 goto EXCEPTION;
697         }
698
699
700         void *sql_dc_returned = NULL;
701
702         sql_dc_returned = tdelete(sql_dc_temp, &datacontrol_sql_tree_root, datacontrol_sql_instance_compare);
703         if (sql_dc_returned == NULL)
704         {
705                 LOGE("invalid parameter");
706                 ret = DATACONTROL_ERROR_INVALID_PARAMETER;
707                 goto EXCEPTION;
708         }
709
710
711 EXCEPTION:
712         if (sql_dc_temp)
713         {
714                 if (sql_dc_temp->provider_id)
715                         free(sql_dc_temp->provider_id);
716                 free(sql_dc_temp);
717          }
718
719         return ret;
720
721 }
722
723 static void
724 bundle_foreach_check_arg_size_cb(const char *key, const int type, const bundle_keyval_t *kv, void *arg_size)
725 {
726         char *value = NULL;
727         size_t value_len = 0;
728         bundle_keyval_get_basic_val((bundle_keyval_t*)kv, (void**)&value, &value_len);
729
730         arg_size += (strlen(key) + value_len) * sizeof(wchar_t);
731         return;
732 }
733
734 static void
735 bundle_foreach_cb(const char *key, const int type, const bundle_keyval_t *kv, void *user_data)
736 {
737         if (!key || !kv || !user_data)
738         {
739                 return;
740         }
741
742         int fd = *(int *)user_data;
743
744         int key_len = strlen(key);
745         char *value = NULL;
746         size_t value_len = 0;
747         bundle_keyval_get_basic_val((bundle_keyval_t*)kv, (void**)&value, &value_len);
748
749         // Write a key
750         if (write(fd, &key_len, sizeof(int)) == -1)
751         {
752                 LOGE("Writing a key_len to a file descriptor is failed. errno = %d", errno);
753         }
754         if (write(fd, key, key_len)  == -1)
755         {
756                 LOGE("Writing a key to a file descriptor is failed. errno = %d", errno);
757         }
758         // Write a value
759         if (write(fd, &value_len, sizeof(int)) == -1)
760         {
761                 LOGE("Writing a value_len to a file descriptor is failed. errno = %d", errno);
762         }
763         if (write(fd, value, value_len) == -1)
764         {
765                 LOGE("Writing a value to a file descriptor is failed. errno = %d", errno);
766         }
767
768         return;
769 }
770
771 char *
772 __get_provider_pkgid(char* provider_id)
773 {
774         char* access = NULL;
775         char *provider_appid = NULL;
776         char *provider_pkgid = NULL;
777         pkgmgrinfo_appinfo_h app_info_handle = NULL;
778
779         int ret = pkgmgrinfo_appinfo_get_datacontrol_info(provider_id, "Sql", &provider_appid, &access);
780         if (ret != PMINFO_R_OK)
781         {
782                 LOGE("unable to get sql data control information: %d", ret);
783                 return NULL;
784         }
785
786         pkgmgrinfo_appinfo_get_appinfo(provider_appid, &app_info_handle);
787         pkgmgrinfo_appinfo_get_pkgname(app_info_handle, &provider_pkgid);
788         SECURE_LOGI("provider pkg id : %s", provider_pkgid);
789
790         if (access)
791         {
792                 free(access);
793         }
794         if (provider_appid)
795         {
796                 free(provider_appid);
797         }
798         return provider_pkgid ? strdup(provider_pkgid) : NULL;
799 }
800
801 int
802 datacontrol_sql_insert(datacontrol_h provider, const bundle* insert_data, int *request_id)
803 {
804         int ret = 0;
805         char* access = NULL;
806         char *provider_appid = NULL;
807
808         if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || insert_data == NULL)
809         {
810                 LOGE("Invalid parameter");
811                 return DATACONTROL_ERROR_INVALID_PARAMETER;
812         }
813
814         SECURE_LOGI("SQL data control, insert to provider_id: %s, data_id: %s", provider->provider_id, provider->data_id);
815
816         ret = pkgmgrinfo_appinfo_get_datacontrol_info(provider->provider_id, "Sql", &provider_appid, &access);
817         if (ret != PMINFO_R_OK)
818         {
819                 LOGE("unable to get sql data control information: %d", ret);
820                 return DATACONTROL_ERROR_IO_ERROR;
821         }
822         if (provider_appid)
823                 free(provider_appid);
824
825         if (NULL != access && !strcmp(access, READ_ONLY)) {
826                 LOGE("Provider has given [%s] permission only", access);
827                 free(access);
828                 return DATACONTROL_ERROR_PERMISSION_DENIED;
829         }
830         if (access)
831                 free(access);
832
833         char caller_app_id[256] = {0, };
834         pid_t pid = getpid();
835
836         if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0)
837         {
838                 SECURE_LOGE("Failed to get appid by pid(%d).", pid);
839                 return DATACONTROL_ERROR_INVALID_PARAMETER;
840         }
841
842         // Check size of arguments
843         long long arg_size = 0;
844         bundle_foreach((bundle*)insert_data, bundle_foreach_check_arg_size_cb, &arg_size);
845         arg_size += strlen(provider->data_id) * sizeof(wchar_t);
846         if (arg_size > MAX_REQUEST_ARGUMENT_SIZE)
847         {
848                 LOGE("The size of the request argument exceeds the limit, 1M.");
849                 return DATACONTROL_ERROR_MAX_EXCEEDED;
850         }
851
852         int reqId = _datacontrol_create_request_id();
853         SECURE_LOGI("request id: %d", reqId);
854         char insert_map_file[REQUEST_PATH_MAX] = {0, };
855         ret = snprintf(insert_map_file, REQUEST_PATH_MAX, "%s%s%d", DATACONTROL_REQUEST_FILE_PREFIX, caller_app_id, reqId);
856         if (ret < 0)
857         {
858                 LOGE("unable to write formatted output to insert_map_file: %d", errno);
859                 return DATACONTROL_ERROR_IO_ERROR;
860         }
861
862         SECURE_LOGI("insert_map_file : %s", insert_map_file);
863
864         int fd = 0;
865         char *provider_pkgid = __get_provider_pkgid(provider->provider_id);
866
867         ret = security_server_shared_file_open(insert_map_file, provider_pkgid, &fd);
868         if (ret == SECURITY_SERVER_API_ERROR_FILE_EXIST) {
869                 SECURE_LOGE("The file(%s) already exist, delete and retry to open", insert_map_file);
870                 int ret_temp = security_server_shared_file_delete(insert_map_file);
871                 if (ret_temp != SECURITY_SERVER_API_SUCCESS) {
872                         SECURE_LOGE("Delete the file(%s) is failed : %d", insert_map_file, ret_temp);
873                 } else {
874                         ret = security_server_shared_file_open(insert_map_file, provider_pkgid, &fd);
875                 }
876         }
877
878         if (ret != SECURITY_SERVER_API_SUCCESS)
879         {
880                 SECURE_LOGE("unable to open insert_map_file: %d", ret);
881                 free(provider_pkgid);
882                 return DATACONTROL_ERROR_IO_ERROR;
883         }
884
885         free(provider_pkgid);
886
887         int count = bundle_get_count((bundle*)insert_data);
888         LOGI("Insert column counts: %d", count);
889
890         bundle_foreach((bundle*)insert_data, bundle_foreach_cb, &fd);
891
892         fsync(fd);
893         close(fd);
894
895         bundle *b = bundle_create();
896         if (!b)
897         {
898                 LOGE("unable to create bundle: %d", errno);
899                 return DATACONTROL_ERROR_IO_ERROR;
900         }
901
902         bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
903         bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
904
905         char insert_column_count[MAX_LEN_DATACONTROL_COLUMN_COUNT] = {0, };
906         ret = snprintf(insert_column_count, MAX_LEN_DATACONTROL_COLUMN_COUNT, "%d", count);
907         if (ret < 0)
908         {
909                 LOGE("unable to convert insert column count to string: %d", errno);
910                 bundle_free(b);
911                 return DATACONTROL_ERROR_IO_ERROR;
912         }
913
914         const char* arg_list[3];
915         arg_list[0] = provider->data_id;
916         arg_list[1] = insert_column_count;
917         arg_list[2] = insert_map_file;
918
919         bundle_add_str_array(b, OSP_K_ARG, arg_list, 3);
920
921         // Set the request id
922         *request_id = reqId;
923
924         ret = datacontrol_sql_request_provider(provider, DATACONTROL_TYPE_SQL_INSERT, b, reqId);
925         if (ret != DATACONTROL_ERROR_NONE)
926         {
927                 ret = security_server_shared_file_delete(insert_map_file);
928                 if (ret != SECURITY_SERVER_API_SUCCESS)
929                 {
930                         SECURE_LOGE("unable to remove the insert_map_file: %d", ret);
931                 }
932         }
933         bundle_free(b);
934         return ret;
935 }
936
937 int
938 datacontrol_sql_delete(datacontrol_h provider, const char *where, int *request_id)
939 {
940         int ret = 0;
941         char* access = NULL;
942         char *provider_appid = NULL;
943
944         if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL)
945         {
946                 LOGE("Invalid parameter");
947                 return DATACONTROL_ERROR_INVALID_PARAMETER;
948         }
949
950         ret = pkgmgrinfo_appinfo_get_datacontrol_info(provider->provider_id, "Sql", &provider_appid, &access);
951         if (ret != PMINFO_R_OK)
952         {
953                 LOGE("unable to get sql data control information: %d", ret);
954                 return DATACONTROL_ERROR_IO_ERROR;
955         }
956         if (provider_appid)
957                 free(provider_appid);
958
959         if (NULL != access && !strcmp(access, READ_ONLY)) {
960                 LOGE("Provider has given [%s] permission only", access);
961                 free(access);
962                 return DATACONTROL_ERROR_PERMISSION_DENIED;
963         }
964         if (access)
965                 free(access);
966
967         bundle *b = bundle_create();
968         if (!b)
969         {
970                 LOGE("unable to create bundle: %d", errno);
971                 return DATACONTROL_ERROR_IO_ERROR;
972         }
973
974         bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
975         bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
976
977         const char* arg_list[2];
978         arg_list[0] = provider->data_id;
979
980         if (where)
981         {
982                 arg_list[1] = where;
983         }
984         else
985         {
986                 arg_list[1] = DATACONTROL_EMPTY;
987         }
988
989         bundle_add_str_array(b, OSP_K_ARG, arg_list, 2);
990
991         // Set the request id
992         int reqId = _datacontrol_create_request_id();
993         *request_id = reqId;
994
995         ret = datacontrol_sql_request_provider(provider, DATACONTROL_TYPE_SQL_DELETE, b, reqId);
996         bundle_free(b);
997         return ret;
998 }
999
1000 int
1001 datacontrol_sql_select(datacontrol_h provider, char **column_list, int column_count, const char *where, const char *order, int *request_id)
1002 {
1003         return datacontrol_sql_select_with_page(provider, column_list, column_count, where, order, 1, 20, request_id);
1004 }
1005
1006 int
1007 datacontrol_sql_select_with_page(datacontrol_h provider, char **column_list, int column_count, const char *where, const char *order, int page_number, int count_per_page, int *request_id)
1008 {
1009         int ret = 0;
1010         char* access = NULL;
1011         char *provider_appid = NULL;
1012
1013         if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL)
1014         {
1015                 LOGE("Invalid parameter");
1016                 return DATACONTROL_ERROR_INVALID_PARAMETER;
1017         }
1018
1019         if (count_per_page > MAX_ROW_COUNT)
1020         {
1021                 LOGE("Exceeds max row count per page.");
1022                 return DATACONTROL_ERROR_INVALID_PARAMETER;
1023         }
1024
1025         LOGI("SQL data control, select to provider_id: %s, data_id: %s, col_count: %d, where: %s, order: %s, page_number: %d, per_page: %d", provider->provider_id, provider->data_id, column_count, where, order, page_number, count_per_page);
1026
1027         ret = pkgmgrinfo_appinfo_get_datacontrol_info(provider->provider_id, "Sql", &provider_appid, &access);
1028         if (ret != PMINFO_R_OK)
1029         {
1030                 LOGE("unable to get sql data control information: %d", ret);
1031                 return DATACONTROL_ERROR_IO_ERROR;
1032         }
1033         if (provider_appid)
1034                 free(provider_appid);
1035
1036         if (NULL != access && !strcmp(access, WRITE_ONLY)) {
1037                 LOGE("Provider has given [%s] permission only", access);
1038                 free(access);
1039                 return DATACONTROL_ERROR_PERMISSION_DENIED;
1040         }
1041         if (access)
1042                 free(access);
1043
1044         if (column_list == NULL)
1045         {
1046                 LOGE("Invalid parameter");
1047                 return DATACONTROL_ERROR_INVALID_PARAMETER;
1048         }
1049
1050         int total_arg_count = -1;
1051
1052         bundle *b = bundle_create();
1053         if (!b)
1054         {
1055                 LOGE("unable to create bundle: %d", errno);
1056                 return DATACONTROL_ERROR_IO_ERROR;
1057         }
1058
1059         bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
1060         bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
1061
1062         char page[32] = {0, };
1063         ret = snprintf(page, 32, "%d", page_number);
1064         if (ret < 0)
1065         {
1066                 LOGE("unable to convert page no to string: %d", errno);
1067                 bundle_free(b);
1068                 return DATACONTROL_ERROR_IO_ERROR;
1069         }
1070
1071         char count_per_page_no[32] = {0, };
1072         ret = snprintf(count_per_page_no, 32, "%d", count_per_page);
1073         if (ret < 0)
1074         {
1075                 LOGE("unable to convert count per page no to string: %d", errno);
1076                 bundle_free(b);
1077                 return DATACONTROL_ERROR_IO_ERROR;
1078         }
1079
1080         total_arg_count = column_count + DATACONTROL_SELECT_EXTRA_COUNT;
1081         const char** arg_list = (const char**)malloc(total_arg_count * (sizeof(char *)));
1082         if (arg_list == NULL) {
1083                 LOGE("out of memory");
1084                 bundle_free(b);
1085                 return DATACONTROL_ERROR_OUT_OF_MEMORY;
1086         }
1087
1088         LOGI("total arg count %d", total_arg_count);
1089
1090         arg_list[0] = provider->data_id; // arg[0]: data ID
1091         int i = 1;
1092         if (column_list)
1093         {
1094                 char select_column_count[MAX_LEN_DATACONTROL_COLUMN_COUNT] = {0, };
1095                 ret = snprintf(select_column_count, MAX_LEN_DATACONTROL_COLUMN_COUNT, "%d", column_count);
1096                 if(ret < 0)
1097                 {
1098                         LOGE("unable to convert select col count to string: %d", errno);
1099                         free(arg_list);
1100                         bundle_free(b);
1101                         return DATACONTROL_ERROR_IO_ERROR;
1102                 }
1103
1104
1105                 arg_list[i] = select_column_count; // arg[1]: selected column count
1106
1107                 ++i;
1108                 int select_col = 0;
1109                 while (select_col < column_count)
1110                 {
1111                         arg_list[i++] = column_list[select_col++];
1112                 }
1113         }
1114
1115         if (where)      // arg: where clause
1116         {
1117                 arg_list[i++] = where;
1118         }
1119         else
1120         {
1121                 arg_list[i++] = DATACONTROL_EMPTY;
1122         }
1123
1124         if (order)      // arg: order clause
1125         {
1126                 arg_list[i++] = order;
1127         }
1128         else
1129         {
1130                 arg_list[i++] = DATACONTROL_EMPTY;
1131         }
1132
1133
1134         arg_list[i++] = page;  // arg: page number
1135
1136         arg_list[i] = count_per_page_no;  // arg: count per page
1137
1138         bundle_add_str_array(b, OSP_K_ARG, arg_list, total_arg_count);
1139         free(arg_list);
1140
1141         int reqId = _datacontrol_create_request_id();
1142         *request_id = reqId;
1143
1144         ret = datacontrol_sql_request_provider(provider, DATACONTROL_TYPE_SQL_SELECT, b, reqId);
1145         bundle_free(b);
1146         return ret;
1147 }
1148
1149
1150 int
1151 datacontrol_sql_update(datacontrol_h provider, const bundle* update_data, const char *where, int *request_id)
1152 {
1153         int ret = 0;
1154         char* access = NULL;
1155         char *provider_appid = NULL;
1156
1157         if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || update_data == NULL || where == NULL)
1158         {
1159                 LOGE("Invalid parameter");
1160                 return DATACONTROL_ERROR_INVALID_PARAMETER;
1161         }
1162
1163         ret = pkgmgrinfo_appinfo_get_datacontrol_info(provider->provider_id, "Sql", &provider_appid, &access);
1164         if (ret != PMINFO_R_OK)
1165         {
1166                 LOGE("unable to get sql data control information: %d", ret);
1167                 return DATACONTROL_ERROR_IO_ERROR;
1168         }
1169         if (provider_appid)
1170                 free(provider_appid);
1171
1172         if (NULL != access && !strcmp(access, READ_ONLY)) {
1173                 LOGE("Provider has given [%s] permission only", access);
1174                 free(access);
1175                 return DATACONTROL_ERROR_PERMISSION_DENIED;
1176         }
1177         if (access)
1178                 free(access);
1179
1180         char caller_app_id[256] = {0, };
1181         pid_t pid = getpid();
1182
1183         if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0)
1184         {
1185                 SECURE_LOGE("Failed to get appid by pid(%d).", pid);
1186                 return DATACONTROL_ERROR_INVALID_PARAMETER;
1187         }
1188
1189         // Check size of arguments
1190         long long arg_size = 0;
1191         bundle_foreach((bundle*)update_data, bundle_foreach_check_arg_size_cb, &arg_size);
1192         arg_size += strlen(provider->data_id) * sizeof(wchar_t);
1193         if (arg_size > MAX_REQUEST_ARGUMENT_SIZE)
1194         {
1195                 LOGE("The size of the request argument exceeds the limit, 1M.");
1196                 return DATACONTROL_ERROR_MAX_EXCEEDED;
1197         }
1198
1199         int reqId = _datacontrol_create_request_id();
1200
1201         char update_map_file[REQUEST_PATH_MAX] = {0, };
1202         ret = snprintf(update_map_file, REQUEST_PATH_MAX, "%s%s%d", DATACONTROL_REQUEST_FILE_PREFIX, caller_app_id, reqId);
1203         if (ret < 0)
1204         {
1205                 LOGE("unable to write formatted output to update_map_file: %d", errno);
1206                 return DATACONTROL_ERROR_IO_ERROR;
1207         }
1208
1209         SECURE_LOGI("update_map_file : %s", update_map_file);
1210
1211         int fd = 0;
1212         char *provider_pkgid = __get_provider_pkgid(provider->provider_id);
1213
1214         ret = security_server_shared_file_open(update_map_file, provider_pkgid, &fd);
1215         if (ret == SECURITY_SERVER_API_ERROR_FILE_EXIST) {
1216                 SECURE_LOGE("The file(%s) already exist, delete and retry to open", update_map_file);
1217                 int ret_temp = security_server_shared_file_delete(update_map_file);
1218                 if (ret_temp != SECURITY_SERVER_API_SUCCESS) {
1219                         SECURE_LOGE("Delete the file(%s) is failed : %d", update_map_file, ret_temp);
1220                 } else {
1221                         ret = security_server_shared_file_open(update_map_file, provider_pkgid, &fd);
1222                 }
1223         }
1224
1225         if (ret != SECURITY_SERVER_API_SUCCESS)
1226         {
1227                 SECURE_LOGE("unable to open update_map file: %d", ret);
1228                 free(provider_pkgid);
1229                 return DATACONTROL_ERROR_IO_ERROR;
1230         }
1231
1232         free(provider_pkgid);
1233
1234         int count = bundle_get_count((bundle*)update_data);
1235         bundle_foreach((bundle*)update_data, bundle_foreach_cb, &fd);
1236
1237         fsync(fd);
1238         close(fd);
1239
1240         bundle *b = bundle_create();
1241         if (!b)
1242         {
1243                 LOGE("unable to create bundle: %d", errno);
1244                 return DATACONTROL_ERROR_IO_ERROR;
1245         }
1246
1247         bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
1248         bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
1249
1250         char update_column_count[MAX_LEN_DATACONTROL_COLUMN_COUNT] = {0, };
1251         ret = snprintf(update_column_count, MAX_LEN_DATACONTROL_COLUMN_COUNT, "%d", count);
1252         if (ret < 0)
1253         {
1254                 LOGE("unable to convert update col count to string: %d", errno);
1255                 bundle_free(b);
1256                 return DATACONTROL_ERROR_IO_ERROR;
1257         }
1258
1259         const char* arg_list[4];
1260         arg_list[0] = provider->data_id; // list(0): data ID
1261         arg_list[1] = update_column_count;
1262         arg_list[2] = update_map_file;
1263         arg_list[3] = where;
1264
1265         bundle_add_str_array(b, OSP_K_ARG, arg_list, 4);
1266
1267         *request_id = reqId;
1268
1269         ret = datacontrol_sql_request_provider(provider, DATACONTROL_TYPE_SQL_UPDATE, b, reqId);
1270         if (ret != DATACONTROL_ERROR_NONE)
1271         {
1272                 ret = security_server_shared_file_delete(update_map_file);
1273                 if (ret != SECURITY_SERVER_API_SUCCESS)
1274                 {
1275                         SECURE_LOGE("unable to remove the update_map file: %d", ret);
1276                 }
1277         }
1278         bundle_free(b);
1279         return ret;
1280 }