Fix resource leak
[platform/core/appfw/librua.git] / src / rua.c
1 /*
2  * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21
22 #include <sqlite3.h>
23 #include <aul.h>
24 #include <dlog.h>
25
26 #include "rua_util.h"
27 #include "rua.h"
28 #include "db-schema.h"
29 #include "rua_dbus.h"
30 #include "rua_private.h"
31
32 API int rua_add_history_for_uid(char *pkg_name, char *app_path, char *arg, uid_t uid)
33 {
34         int r;
35         char time_str[32] = {0,};
36         bundle *b = NULL;
37
38         if (pkg_name == NULL || app_path == NULL) {
39                 LOGE("invalid param");
40                 return -1;
41         }
42
43         r = _rua_util_check_uid(uid);
44         if (r == -1)
45                 return r;
46
47         b = bundle_create();
48         if (b == NULL) {
49                 LOGE("bundle_create fail out of memory.");
50                 return -1;
51         }
52         snprintf(time_str, sizeof(time_str), "%d", (int)time(NULL));
53         bundle_add_str(b, AUL_K_RUA_PKGNAME, pkg_name);
54         bundle_add_str(b, AUL_K_RUA_APPPATH, app_path);
55         bundle_add_str(b, AUL_K_RUA_ARG, arg);
56         bundle_add_str(b, AUL_K_RUA_TIME, time_str);
57
58         r = aul_add_rua_history_for_uid(b, uid);
59         LOGI("rua_add_history_for_uid result : %d ", r);
60         bundle_free(b);
61         return r;
62 }
63
64 API int rua_delete_history_with_pkgname_for_uid(char *pkg_name, uid_t uid)
65 {
66         int r;
67         bundle *b;
68
69         r = _rua_util_check_uid(uid);
70         if (r == -1)
71                 return r;
72
73         b = bundle_create();
74         if (b == NULL) {
75                 LOGE("bundle_create fail out of memory.");
76                 return -1;
77         }
78         bundle_add_str(b, AUL_K_RUA_PKGNAME, pkg_name);
79         r = aul_delete_rua_history_for_uid(b, uid);
80         LOGI("rua_delete_history_with_pkgname result : %d ", r);
81         bundle_free(b);
82         return r;
83 }
84
85 API int rua_delete_history_with_pkgname(char *pkg_name)
86 {
87         return rua_delete_history_with_pkgname_for_uid(pkg_name, getuid());
88 }
89
90 API int rua_delete_history_with_apppath_for_uid(char *app_path, uid_t uid)
91 {
92         int r;
93         bundle *b;
94
95         r = _rua_util_check_uid(uid);
96         if (r == -1)
97                 return r;
98
99         b = bundle_create();
100         if (b == NULL) {
101                 LOGE("bundle_create fail out of memory.");
102                 return -1;
103         }
104         bundle_add_str(b, AUL_K_RUA_APPPATH, app_path);
105         r = aul_delete_rua_history_for_uid(b, uid);
106         LOGI("rua_delete_history_with_apppath result : %d ", r);
107         bundle_free(b);
108         return r;
109 }
110
111 API int rua_delete_history_with_apppath(char *app_path)
112 {
113         return rua_delete_history_with_apppath_for_uid(app_path, getuid());
114 }
115
116 API int rua_clear_history_for_uid(uid_t uid)
117 {
118         int r;
119
120         r = _rua_util_check_uid(uid);
121         if (r == -1)
122                 return r;
123
124         r = aul_delete_rua_history_for_uid(NULL, uid);
125         LOGI("rua_clear_history result : %d ", r);
126         return r;
127 }
128
129 API int rua_clear_history(void)
130 {
131         return rua_clear_history_for_uid(getuid());
132 }
133
134 API int rua_history_load_db_for_uid(char ***table, int *nrows, int *ncols, uid_t uid)
135 {
136         static const char query[] =
137                 "SELECT pkg_name, app_path, arg, launch_time, instance_id,"
138                 "  instance_name, icon, uri, image "
139                 "FROM rua_history ORDER BY launch_time DESC";
140         int r;
141         char *db_err = NULL;
142         char **db_result = NULL;
143         sqlite3 *db = NULL;
144
145         if (table == NULL || nrows == NULL || ncols == NULL) {
146                 LOGE("invalid parameter");
147                 return -1;
148         }
149
150         r = _rua_util_check_uid(uid);
151         if (r == -1)
152                 return r;
153
154         r = _rua_util_open_db(&db, SQLITE_OPEN_READONLY, uid, RUA_DB_NAME);
155         if (r != SQLITE_OK)
156                 return -1;
157
158         r = sqlite3_get_table(db, query, &db_result, nrows, ncols, &db_err);
159         if (r != SQLITE_OK) {
160                 LOGE("get table failed: %s", db_err);
161                 sqlite3_free(db_err);
162                 sqlite3_close_v2(db);
163                 return -1;
164         }
165
166         *table = db_result;
167
168         sqlite3_close_v2(db);
169
170         return r;
171 }
172
173 API int rua_history_load_db(char ***table, int *nrows, int *ncols)
174 {
175         return rua_history_load_db_for_uid(table, nrows, ncols, getuid());
176 }
177
178 API int rua_register_update_cb_for_uid(rua_history_update_cb callback, void *user_data, int *callback_id, uid_t uid)
179 {
180         int r;
181
182         if (callback == NULL)
183                 return -1;
184
185         r = _rua_util_check_uid(uid);
186         if (r == -1)
187                 return r;
188
189         r = rua_dbus_signal_subscribe(callback, user_data, callback_id);
190
191         return r;
192 }
193
194 API int rua_register_update_cb(rua_history_update_cb callback, void *user_data, int *callback_id)
195 {
196         return rua_register_update_cb_for_uid(callback, user_data, callback_id, getuid());
197 }
198
199 API int rua_unregister_update_cb_for_uid(int callback_id, uid_t uid)
200 {
201         int r;
202
203         r = _rua_util_check_uid(uid);
204         if (r == -1)
205                 return r;
206
207         r = rua_dbus_signal_unsubscribe(callback_id);
208
209         return r;
210 }
211
212 API int rua_unregister_update_cb(int callback_id)
213 {
214         return rua_unregister_update_cb_for_uid(callback_id, getuid());
215 }
216
217 API int rua_history_get_rec(struct rua_rec *rec, char **table, int nrows, int ncols,
218                         int row)
219 {
220         char **db_result = NULL;
221         char *tmp = NULL;
222
223         if (rec == NULL)
224                 return -1;
225         if (table == NULL)
226                 return -1;
227         if (row >= nrows)
228                 return -1;
229
230         db_result = table + ((row + 1) * ncols);
231
232         tmp = db_result[RUA_COL_PKGNAME];
233         if (tmp) {
234                 rec->pkg_name = tmp;
235                 LOGI("get rec pkg_name %s", rec->pkg_name);
236         }
237
238         tmp = db_result[RUA_COL_APPPATH];
239         if (tmp)
240                 rec->app_path = tmp;
241
242         tmp = db_result[RUA_COL_ARG];
243         if (tmp)
244                 rec->arg = tmp;
245
246         tmp = db_result[RUA_COL_LAUNCHTIME];
247         if (tmp)
248                 rec->launch_time = atoi(tmp);
249
250         tmp = db_result[RUA_COL_INSTANCE_ID];
251         if (tmp && tmp[0] != '\0')
252                 rec->instance_id = tmp;
253         else
254                 rec->instance_id = NULL;
255
256         tmp = db_result[RUA_COL_INSTANCE_NAME];
257         if (tmp && tmp[0] != '\0')
258                 rec->instance_name = tmp;
259         else
260                 rec->instance_name = NULL;
261
262         tmp = db_result[RUA_COL_ICON];
263         if (tmp && tmp[0] != '\0')
264                 rec->icon = tmp;
265         else
266                 rec->icon = NULL;
267
268         tmp = db_result[RUA_COL_URI];
269         if (tmp && tmp[0] != '\0')
270                 rec->uri = tmp;
271         else
272                 rec->uri = NULL;
273
274         tmp = db_result[RUA_COL_IMAGE];
275         if (tmp && tmp[0] != '\0')
276                 rec->image = tmp;
277         else
278                 rec->image = NULL;
279
280         return 0;
281 }
282
283 API int rua_history_unload_db(char ***table)
284 {
285         if (*table) {
286                 sqlite3_free_table(*table);
287                 *table = NULL;
288                 return 0;
289         }
290         return -1;
291 }
292
293 API int rua_is_latest_app_for_uid(const char *pkg_name, uid_t uid)
294 {
295         static const char query[] =
296                 "SELECT pkg_name FROM rua_history "
297                 "ORDER BY launch_time DESC LIMIT 1";
298         int r = -1;
299         sqlite3_stmt *stmt;
300         const unsigned char *ct;
301         sqlite3 *db = NULL;
302
303         if (!pkg_name)
304                 return -1;
305
306         r = _rua_util_check_uid(uid);
307         if (r == -1)
308                 return r;
309
310         r = _rua_util_open_db(&db, SQLITE_OPEN_READONLY, uid, RUA_DB_NAME);
311         if (r != SQLITE_OK)
312                 return -1;
313
314         r = sqlite3_prepare(db, query, strlen(query), &stmt, NULL);
315         if (r != SQLITE_OK) {
316                 sqlite3_close_v2(db);
317                 return -1;
318         }
319
320         r = sqlite3_step(stmt);
321         if (r != SQLITE_ROW) {
322                 if (r != SQLITE_DONE)
323                         LOGE("step failed: %s", sqlite3_errmsg(db));
324                 sqlite3_finalize(stmt);
325                 sqlite3_close_v2(db);
326                 return -1;
327         }
328
329         ct = sqlite3_column_text(stmt, 0);
330         if (ct == NULL || ct[0] == '\0')
331                 r = -1;
332         else if (strncmp(pkg_name, (const char *)ct, strlen(pkg_name)) == 0)
333                 r = 0;
334         else
335                 r = -1;
336
337         sqlite3_finalize(stmt);
338         sqlite3_close_v2(db);
339
340         return r;
341 }
342
343 API int rua_is_latest_app(const char *pkg_name)
344 {
345         return rua_is_latest_app_for_uid(pkg_name, getuid());
346 }
347
348 API int rua_init(void)
349 {
350         return 0;
351 }
352
353 API int rua_fini(void)
354 {
355         return 0;
356 }
357
358 API int rua_delete_history_with_instance_id(const char *app_id,
359                 const char *instance_id)
360 {
361         int ret;
362         bundle *b;
363
364         if (app_id == NULL) {
365                 LOGE("Invalid parameter");
366                 return -1;
367         }
368
369         b = bundle_create();
370         if (b == NULL) {
371                 LOGE("Out of memory");
372                 return -1;
373         }
374
375         bundle_add_str(b, AUL_K_RUA_PKGNAME, app_id);
376         if (instance_id)
377                 bundle_add_str(b, AUL_K_RUA_INSTANCE_ID, instance_id);
378
379         ret = aul_delete_rua_history_for_uid(b, getuid());
380         bundle_free(b);
381         if (ret < 0) {
382                 LOGE("Failed to delete rua history - result(%d)", ret);
383                 return -1;
384         }
385
386         return 0;
387 }