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