Tizen 2.1 base
[platform/core/appfw/ail.git] / src / ail_desktop.c
1 /*
2  * ail
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23
24 #define _GNU_SOURCE
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <time.h>
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <xdgmime.h>
33
34 #include <vconf.h>
35 #include <glib.h>
36
37 #include "ail_private.h"
38 #include "ail_db.h"
39 #include "ail.h"
40
41 #define OPT_DESKTOP_DIRECTORY "/opt/share/applications"
42 #define USR_DESKTOP_DIRECTORY "/usr/share/applications"
43 #define BUFSZE 4096
44
45 #define whitespace(c) (((c) == ' ') || ((c) == '\t'))
46 #define argsdelimiter   " \t"
47
48 typedef enum {
49         NOTI_ADD,
50         NOTI_UPDATE,
51         NOTI_REMOVE,
52         NOTI_MAX,
53 } noti_type;
54
55 struct entry_parser {
56         const char *field;
57         ail_error_e (*value_cb)(void *data, char *tag, char *value);
58 };
59
60 inline static char *_ltrim(char *str)
61 {
62         if (!str) return NULL;
63
64         while (*str == ' ' || *str == '\t' || *str == '\n') str ++;
65
66         return str;
67 }
68
69
70
71 inline static int _rtrim(char *str)
72 {
73         int len;
74
75         len = strlen(str);
76         while (--len >= 0 && (str[len] == ' ' || str[len] == '\n' || str[len] == '\t')) str[len] = '\0';
77
78         return len;
79 }
80
81 struct name_item {
82         char *locale;
83         char *name;
84 };
85
86 typedef struct {
87         const char*     package;
88         char*           exec;
89         char*           name;
90         char*           type;
91         char*           icon;
92         char*           categories;
93         char*           version;
94         char*           mimetype;
95         char*           x_slp_service;
96         char*           x_slp_packagetype;
97         char*           x_slp_packagecategories;
98         char*           x_slp_packageid;
99         char*           x_slp_uri;
100         char*           x_slp_svc;
101         char*           x_slp_exe_path;
102         char*           x_slp_appid;
103         char*           x_slp_pkgid;
104         char*           x_slp_domain;
105         int             x_slp_baselayoutwidth;
106         int             x_slp_installedtime;
107         int             nodisplay;
108         int             x_slp_taskmanage;
109         int             x_slp_multiple;
110         int             x_slp_removable;
111         int             x_slp_ishorizontalscale;
112         int             x_slp_inactivated;
113         char*           desktop;
114         GSList*         localname;
115 } desktop_info_s;
116
117
118
119 static ail_error_e _read_exec(void *data, char *tag, char *value)
120 {
121         desktop_info_s *info = data;
122         char *token_exe_path;
123         char *save_ptr;
124         char *temp_exec;
125
126         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
127         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
128
129         SAFE_FREE_AND_STRDUP(value, info->exec);
130         retv_if(!info->exec, AIL_ERROR_OUT_OF_MEMORY);
131
132         temp_exec = strdup(value);
133         if(!temp_exec) {
134                 free(info->exec);
135                 return AIL_ERROR_OUT_OF_MEMORY;
136         }
137
138         token_exe_path = strtok_r(temp_exec, argsdelimiter, &save_ptr);
139
140         info->x_slp_exe_path = strdup(token_exe_path);
141         if(!info->x_slp_exe_path) {
142                 free(info->exec);
143                 info->exec = NULL;
144                 free(temp_exec);
145                 return AIL_ERROR_OUT_OF_MEMORY;
146         }
147
148         free(temp_exec);
149
150         return AIL_ERROR_OK;
151 }
152
153
154
155 static ail_error_e _read_name(void *data, char *tag, char *value)
156 {
157         desktop_info_s *info = data;
158
159         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
160         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
161         retv_if(0 == strlen(value), AIL_ERROR_FAIL);
162
163         if (tag && strlen(tag) > 0) {
164                 struct name_item *item;
165                 item = (struct name_item *)calloc(1, sizeof(struct name_item));
166                 retv_if (NULL == item, AIL_ERROR_OUT_OF_MEMORY);
167
168                 SAFE_FREE_AND_STRDUP(tag, item->locale);
169                 if(NULL == item->locale) {
170                         _E("(NULL == item->locale) return\n");
171                         free(item);
172                         return AIL_ERROR_OUT_OF_MEMORY;
173                 }
174
175                 SAFE_FREE_AND_STRDUP(value, item->name);
176                 if(NULL == item->name) {
177                         _E("(NULL == item->name) return\n");
178                         free(item->locale);
179                         free(item);
180                         return AIL_ERROR_OUT_OF_MEMORY;
181                 }
182
183                 info->localname = g_slist_append(info->localname, item);
184
185                 return AIL_ERROR_OK;
186         } else {
187                 SAFE_FREE_AND_STRDUP(value, info->name);
188                 retv_if (!info->name, AIL_ERROR_OUT_OF_MEMORY);
189
190                 return AIL_ERROR_OK;
191         }
192 }
193
194
195
196 static ail_error_e _read_type(void *data, char *tag, char *value)
197 {
198         desktop_info_s *info = data;
199
200         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
201         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
202
203         SAFE_FREE_AND_STRDUP(value, info->type);
204         retv_if (!info->type, AIL_ERROR_OUT_OF_MEMORY);
205
206         return AIL_ERROR_OK;
207 }
208
209
210 static char*
211 _get_package_from_icon(char* icon)
212 {
213         char* package;
214         char* extension;
215
216         retv_if(!icon, NULL);
217
218         package = strdup(icon);
219         retv_if(!package, NULL);
220         extension = rindex(package, '.');
221         if (extension) {
222                 *extension = '\0';
223         } else {
224                 _E("cannot extract from icon [%s] to package.", icon);
225         }
226
227         return package;
228 }
229
230
231 static char*
232 _get_icon_with_path(char* icon)
233 {
234         retv_if(!icon, NULL);
235
236         if (index(icon, '/') == NULL) {
237                 char* package;
238                 char* theme = NULL;
239                 char* icon_with_path = NULL;
240                 int len;
241
242                 package = _get_package_from_icon(icon);
243                 retv_if(!package, NULL);
244
245                 theme = vconf_get_str("db/setting/theme");
246                 if (!theme) {
247                         theme = strdup("default");
248                         if(!theme) {
249                                 free(package);
250                                 return NULL;
251                         }
252                 }
253
254                 len = (0x01 << 7) + strlen(icon) + strlen(package) + strlen(theme);
255                 icon_with_path = malloc(len);
256                 if(icon_with_path == NULL) {
257                         _E("(icon_with_path == NULL) return\n");
258                         free(package);
259                         free(theme);
260                         return NULL;
261                 }
262
263                 memset(icon_with_path, 0, len);
264
265                 sqlite3_snprintf( len, icon_with_path,"/opt/share/icons/%q/small/%q", theme, icon);
266                 do {
267                         if (access(icon_with_path, R_OK) == 0) break;
268                         sqlite3_snprintf( len, icon_with_path,"/usr/share/icons/%q/small/%q", theme, icon);
269                         if (access(icon_with_path, R_OK) == 0) break;
270                         _D("cannot find icon %s", icon_with_path);
271                         sqlite3_snprintf( len, icon_with_path, "/opt/share/icons/default/small/%q", icon);
272                         if (access(icon_with_path, R_OK) == 0) break;
273                         sqlite3_snprintf( len, icon_with_path, "/usr/share/icons/default/small/%q", icon);
274                         if (access(icon_with_path, R_OK) == 0) break;
275
276                         #if 1 /* this will be remove when finish the work for moving icon path */
277                         _E("icon file must be moved to %s", icon_with_path);
278                         sqlite3_snprintf( len, icon_with_path,  "/opt/apps/%q/res/icons/%q/small/%q", package, theme, icon);
279                         if (access(icon_with_path, R_OK) == 0) break;
280                         sqlite3_snprintf( len, icon_with_path, "/usr/apps/%q/res/icons/%q/small/%q", package, theme, icon);
281                         if (access(icon_with_path, R_OK) == 0) break;
282                         _D("cannot find icon %s", icon_with_path);
283                         sqlite3_snprintf( len, icon_with_path, "/opt/apps/%q/res/icons/default/small/%q", package, icon);
284                         if (access(icon_with_path, R_OK) == 0) break;
285                         sqlite3_snprintf( len, icon_with_path, "/usr/apps/%q/res/icons/default/small/%q", package, icon);
286                         if (access(icon_with_path, R_OK) == 0) break;
287                         #endif
288                 } while (0);
289
290                 free(theme);
291                 free(package);
292
293                 _D("Icon path : %s ---> %s", icon, icon_with_path);
294
295                 return icon_with_path;
296         } else {
297                 char* confirmed_icon = NULL;
298
299                 confirmed_icon = strdup(icon);
300                 retv_if(!confirmed_icon, NULL);
301                 return confirmed_icon;
302         }
303 }
304
305
306 static ail_error_e _read_icon(void *data, char *tag, char *value)
307 {
308         desktop_info_s *info = data;
309
310         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
311         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
312
313         info->icon = _get_icon_with_path(value);
314
315         retv_if (!info->icon, AIL_ERROR_OUT_OF_MEMORY);
316
317         return AIL_ERROR_OK;
318 }
319
320
321
322 static ail_error_e _read_categories(void *data, char *tag, char *value)
323 {
324         desktop_info_s *info = data;
325
326         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
327         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
328
329         SAFE_FREE_AND_STRDUP(value, info->categories);
330         retv_if (!info->categories, AIL_ERROR_OUT_OF_MEMORY);
331
332         return AIL_ERROR_OK;
333 }
334
335
336
337 static ail_error_e _read_version(void *data, char *tag, char *value)
338 {
339         desktop_info_s *info = data;
340
341         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
342         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
343
344         SAFE_FREE_AND_STRDUP(value, info->version);
345         retv_if (!info->version, AIL_ERROR_OUT_OF_MEMORY);
346
347         return AIL_ERROR_OK;
348 }
349
350
351
352 static ail_error_e _read_mimetype(void *data, char *tag, char *value)
353 {
354         desktop_info_s *info = data;
355         int size, total_len = 0;
356         char *mimes_origin, *mimes_changed, *token_unalias, *save_ptr;
357
358         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
359         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
360         retv_if(!strlen(value), AIL_ERROR_FAIL);
361
362         mimes_origin = strdup(value);
363         retv_if(!mimes_origin, AIL_ERROR_OUT_OF_MEMORY);
364
365         size = getpagesize();
366         mimes_changed = calloc(1, size);
367         if(mimes_changed == NULL) {
368                 _E("(mimes_changed == NULL) return\n");
369                 free(mimes_origin);
370                 return AIL_ERROR_OUT_OF_MEMORY;
371         }
372
373         token_unalias = strtok_r(mimes_origin, ";", &save_ptr);
374
375         while (token_unalias) {
376                 int token_len;
377                 const char *token_alias;
378
379                 _rtrim(token_unalias);
380                 token_unalias = _ltrim(token_unalias);
381
382                 token_alias = xdg_mime_unalias_mime_type(token_unalias);
383                 if (!token_alias) continue;
384
385                 token_len = strlen(token_alias);
386                 if (total_len + token_len + (1<<1) >= size) {
387                         char *tmp;
388                         size *= 2;
389                         tmp = realloc(mimes_changed, size);
390                         if(!tmp) {
391                                 free(mimes_changed);
392                                 return AIL_ERROR_OUT_OF_MEMORY;
393                         }
394                         mimes_changed = tmp;
395                 }
396
397                 strncat(mimes_changed, token_alias, size-1);
398                 total_len += token_len;
399
400                 token_unalias = strtok_r(NULL, ";", &save_ptr);
401                 if (token_unalias) {
402                         strncat(mimes_changed, ";", size-strlen(mimes_changed)-1);
403                 }
404         }
405
406         SAFE_FREE(info->mimetype);
407         info->mimetype = mimes_changed;
408
409         return AIL_ERROR_OK;
410 }
411
412
413
414 static ail_error_e _read_nodisplay(void *data, char *tag, char *value)
415 {
416         desktop_info_s* info = data;
417
418         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
419         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
420
421         info->nodisplay = !strcasecmp(value, "true");
422
423         return AIL_ERROR_OK;
424 }
425
426
427
428 static ail_error_e _read_x_slp_service(void *data, char *tag, char *value)
429 {
430         desktop_info_s *info = data;
431
432         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
433         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
434
435         SAFE_FREE_AND_STRDUP(value, info->x_slp_service);
436         retv_if(!info->x_slp_service, AIL_ERROR_OUT_OF_MEMORY);
437
438         return AIL_ERROR_OK;
439 }
440
441
442
443 static ail_error_e _read_x_slp_packagetype(void *data, char *tag, char *value)
444 {
445         desktop_info_s *info = data;
446
447         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
448         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
449
450         SAFE_FREE_AND_STRDUP(value, info->x_slp_packagetype);
451         retv_if(!info->x_slp_packagetype, AIL_ERROR_OUT_OF_MEMORY);
452
453         return AIL_ERROR_OK;
454 }
455
456
457
458 static ail_error_e _read_x_slp_packagecategories(void *data, char *tag, char *value)
459 {
460         desktop_info_s *info = data;
461
462         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
463         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
464
465         SAFE_FREE_AND_STRDUP(value, info->x_slp_packagecategories);
466         retv_if(!info->x_slp_packagecategories, AIL_ERROR_OUT_OF_MEMORY);
467
468         return AIL_ERROR_OK;
469 }
470
471
472
473 static ail_error_e _read_x_slp_packageid(void *data, char *tag, char *value)
474 {
475         desktop_info_s *info = data;
476
477         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
478         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
479
480         SAFE_FREE_AND_STRDUP(value, info->x_slp_packageid);
481         retv_if(!info->x_slp_packageid, AIL_ERROR_OUT_OF_MEMORY);
482
483         return AIL_ERROR_OK;
484 }
485
486
487
488 static ail_error_e _read_x_slp_uri(void *data, char *tag, char *value)
489 {
490         desktop_info_s *info = data;
491
492         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
493         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
494
495         SAFE_FREE_AND_STRDUP(value, info->x_slp_uri);
496         retv_if(!info->x_slp_uri, AIL_ERROR_OUT_OF_MEMORY);
497
498         return AIL_ERROR_OK;
499 }
500
501
502
503 static ail_error_e _read_x_slp_svc(void *data, char *tag, char *value)
504 {
505         desktop_info_s *info = data;
506
507         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
508         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
509
510         SAFE_FREE_AND_STRDUP(value, info->x_slp_svc);
511         retv_if(!info->x_slp_svc, AIL_ERROR_OUT_OF_MEMORY);
512
513         return AIL_ERROR_OK;
514 }
515
516
517
518 static ail_error_e _read_x_slp_taskmanage(void *data, char *tag, char *value)
519 {
520         desktop_info_s *info = data;
521
522         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
523         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
524
525         info->x_slp_taskmanage = !strcasecmp(value, "true");
526
527         return AIL_ERROR_OK;
528 }
529
530
531
532 static ail_error_e _read_x_slp_multiple(void *data, char *tag, char *value)
533 {
534         desktop_info_s *info = data;
535
536         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
537         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
538
539         info->x_slp_multiple = !strcasecmp(value, "true");
540
541         return AIL_ERROR_OK;
542 }
543
544
545
546 static ail_error_e _read_x_slp_removable(void *data, char *tag, char *value)
547 {
548         desktop_info_s *info = data;
549
550         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
551         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
552
553         info->x_slp_removable = !strcasecmp(value, "true");
554
555         return AIL_ERROR_OK;
556 }
557
558
559 static ail_error_e _read_x_slp_appid(void *data, char *tag, char *value)
560 {
561         desktop_info_s *info = data;
562
563         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
564         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
565
566         SAFE_FREE_AND_STRDUP(value, info->x_slp_appid);
567         retv_if(!info->x_slp_appid, AIL_ERROR_OUT_OF_MEMORY);
568
569         return AIL_ERROR_OK;
570 }
571
572
573 static ail_error_e _read_x_slp_pkgid(void *data, char *tag, char *value)
574 {
575         desktop_info_s *info = data;
576
577         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
578         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
579
580         SAFE_FREE_AND_STRDUP(value, info->x_slp_pkgid);
581         retv_if(!info->x_slp_pkgid, AIL_ERROR_OUT_OF_MEMORY);
582
583         return AIL_ERROR_OK;
584 }
585
586
587 static ail_error_e _read_x_slp_domain(void *data, char *tag, char *value)
588 {
589         desktop_info_s *info = data;
590
591         retv_if(!data, AIL_ERROR_INVALID_PARAMETER);
592         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
593
594         SAFE_FREE_AND_STRDUP(value, info->x_slp_domain);
595         retv_if(!info->x_slp_appid, AIL_ERROR_OUT_OF_MEMORY);
596
597         return AIL_ERROR_OK;
598 }
599
600
601 static struct entry_parser entry_parsers[] = {
602         {
603                 .field = "exec",
604                 .value_cb = _read_exec,
605         },
606         {
607                 .field = "name",
608                 .value_cb = _read_name,
609         },
610         {
611                 .field = "type",
612                 .value_cb = _read_type,
613         },
614         {
615                 .field = "icon",
616                 .value_cb = _read_icon,
617         },
618         {
619                 .field = "categories",
620                 .value_cb = _read_categories,
621         },
622         {
623                 .field = "version",
624                 .value_cb = _read_version,
625         },
626         {
627                 .field = "mimetype",
628                 .value_cb = _read_mimetype,
629         },
630         {
631                 .field = "x-tizen-service",
632                 .value_cb = _read_x_slp_service,
633         },
634         {
635                 .field = "x-tizen-packagetype",
636                 .value_cb = _read_x_slp_packagetype,
637         },
638         {
639                 .field = "x-tizen-packagecategories",
640                 .value_cb = _read_x_slp_packagecategories,
641         },
642         {
643                 .field = "x-tizen-packageid",
644                 .value_cb = _read_x_slp_packageid,
645         },
646         {
647                 .field = "x-tizen-uri",
648                 .value_cb = _read_x_slp_uri,
649         },
650         {
651                 .field = "x-tizen-svc",
652                 .value_cb = _read_x_slp_svc,
653         },
654         {
655                 .field = "nodisplay",
656                 .value_cb = _read_nodisplay,
657         },
658         {
659                 .field = "x-tizen-taskmanage",
660                 .value_cb = _read_x_slp_taskmanage,
661         },
662         {
663                 .field = "x-tizen-multiple",
664                 .value_cb = _read_x_slp_multiple,
665         },
666         {
667                 .field = "x-tizen-removable",
668                 .value_cb = _read_x_slp_removable,
669         },
670         {
671                 .field = "x-tizen-appid",
672                 .value_cb = _read_x_slp_appid,
673         },
674         {
675                 .field = "x-tizen-pkgid",
676                 .value_cb = _read_x_slp_pkgid,
677         },
678         {
679                 .field = "x-tizen-domain",
680                 .value_cb = _read_x_slp_domain,
681         },
682         {
683                 .field = NULL,
684                 .value_cb = NULL,
685         },
686 };
687
688
689
690 /* Utility functions */
691 static int _count_all(void)
692 {
693         ail_error_e ret;
694         int count;
695
696         ret = ail_filter_count_appinfo(NULL, &count);
697         if(ret != AIL_ERROR_OK) {
698                 _E("cannot count appinfo");
699                 count = -1;
700         }
701
702         retv_if(ret != AIL_ERROR_OK, -1);
703
704         return count;
705 }
706
707
708
709 char *_pkgname_to_desktop(const char *package)
710 {
711         char *desktop;
712         int size;
713
714         retv_if(!package, NULL);
715
716         size = strlen(OPT_DESKTOP_DIRECTORY) + strlen(package) + 10;
717         desktop = malloc(size);
718         retv_if(!desktop, NULL);
719
720         snprintf(desktop, size, OPT_DESKTOP_DIRECTORY"/%s.desktop", package);
721
722         if (access(desktop, R_OK) == 0)
723                 return desktop;
724
725         snprintf(desktop, size, USR_DESKTOP_DIRECTORY"/%s.desktop", package);
726
727         return desktop;
728 }
729
730
731
732 static inline int _strlen_desktop_info(desktop_info_s* info)
733 {
734         int len = 0;
735
736         retv_if(!info, AIL_ERROR_INVALID_PARAMETER);
737
738         if (info->package) len += strlen(info->package);
739         if (info->exec) len += strlen(info->exec);
740         if (info->name) len += strlen(info->name);
741         if (info->type) len += strlen(info->type);
742         if (info->icon) len += strlen(info->icon);
743         if (info->categories) len += strlen(info->categories);
744         if (info->version) len += strlen(info->version);
745         if (info->mimetype) len += strlen(info->mimetype);
746         if (info->x_slp_service) len += strlen(info->x_slp_service);
747         if (info->x_slp_packagetype) len += strlen(info->x_slp_packagetype);
748         if (info->x_slp_packagecategories) len += strlen(info->x_slp_packagecategories);
749         if (info->x_slp_packageid) len += strlen(info->x_slp_packageid);
750         if (info->x_slp_uri) len += strlen(info->x_slp_uri);
751         if (info->x_slp_svc) len += strlen(info->x_slp_svc);
752         if (info->x_slp_exe_path) len += strlen(info->x_slp_exe_path);
753         if (info->x_slp_appid) len += strlen(info->x_slp_appid);
754         if (info->desktop) len += strlen(info->desktop);
755
756         return len;
757 }
758
759
760 int __is_ail_initdb(void)
761 {
762         if( getenv("AIL_INITDB") || getenv("INITDB") )
763                 return 1;
764         else
765                 return 0;
766 }
767
768
769
770 /* Manipulating desktop_info functions */
771 static ail_error_e _init_desktop_info(desktop_info_s *info, const char *package)
772 {
773         static int is_initdb = -1;
774
775         if(is_initdb == -1)
776                 is_initdb = __is_ail_initdb();
777
778         retv_if(!info, AIL_ERROR_INVALID_PARAMETER);
779         retv_if(!package, AIL_ERROR_INVALID_PARAMETER);
780
781         /* defaults */
782         info->package = package;
783
784         info->x_slp_taskmanage = 1;
785         info->x_slp_removable = 1;
786
787         if(is_initdb)
788                 info->x_slp_installedtime = 0;
789         else
790                 info->x_slp_installedtime = time(NULL);
791
792 #ifdef PKGTYPE
793         info->x_slp_packagetype = strdup(PKGTYPE);
794 #else
795         info->x_slp_packagetype = strdup("rpm");
796 #endif
797         retv_if(!info->x_slp_packagetype, AIL_ERROR_OUT_OF_MEMORY);
798
799         info->x_slp_packageid = strdup(package);
800         retv_if(!info->x_slp_packageid, AIL_ERROR_OUT_OF_MEMORY);
801         info->x_slp_appid = strdup(package);
802         retv_if(!info->x_slp_appid, AIL_ERROR_OUT_OF_MEMORY);
803
804         info->desktop = _pkgname_to_desktop(package);
805         retv_if(!info->desktop, AIL_ERROR_FAIL);
806
807         return AIL_ERROR_OK;
808 }
809
810
811
812 static ail_error_e _read_desktop_info(desktop_info_s* info)
813 {
814         char *line = NULL;
815         FILE *fp;
816         size_t size = 0;
817         ssize_t read;
818
819         retv_if(!info, AIL_ERROR_INVALID_PARAMETER);
820
821         fp = fopen(info->desktop, "r");
822         retv_if(!fp, AIL_ERROR_FAIL);
823
824         while ((read = getline(&line, &size, fp)) != -1) {
825                 int len, idx;
826                 char *tmp, *field, *field_name, *tag, *value;
827
828                 tmp = _ltrim(line);
829                 if(tmp == NULL) continue;
830                 if (*tmp == '#') continue;
831                 if (_rtrim(tmp) <= 0) continue;
832
833                 len = strlen(line) + 1;
834                 field = calloc(1, len);
835                 field_name = calloc(1, len);
836                 tag = calloc(1, len);
837                 value = calloc(1, len);
838
839                 if (!field || !field_name || !tag || !value) {
840                         goto NEXT;
841                 }
842
843                 sscanf(tmp, "%[^=]=%[^\n]", field, value);
844                 _rtrim(field);
845                 tmp = _ltrim(value);
846
847                 sscanf(field, "%[^[][%[^]]]", field_name, tag);
848
849                 if (!field_name || !strlen(field_name)){
850                         goto NEXT;
851                 }
852
853                 for (idx = 0; entry_parsers[idx].field; idx ++) {
854                         if (!g_ascii_strcasecmp(entry_parsers[idx].field, field_name) && entry_parsers[idx].value_cb) {
855                                 if (entry_parsers[idx].value_cb(info, tag, tmp) != AIL_ERROR_OK) {
856                                         _E("field - [%s] is wrong.", field_name);
857                                 }
858                                 break;
859                         }
860                 }
861 NEXT:
862                 SAFE_FREE(field);
863                 SAFE_FREE(field_name);
864                 SAFE_FREE(tag);
865                 SAFE_FREE(value);
866         }
867
868         _D("Read (%s).", info->package);
869         fclose(fp);
870
871         return AIL_ERROR_OK;
872 }
873
874
875
876 static ail_error_e _modify_desktop_info_bool(desktop_info_s* info,
877                                                   const char *property,
878                                                   bool value)
879 {
880         ail_prop_bool_e prop;
881         int val;
882
883         retv_if(!info, AIL_ERROR_INVALID_PARAMETER);
884         retv_if(!property, AIL_ERROR_INVALID_PARAMETER);
885
886         prop = _ail_convert_to_prop_bool(property);
887
888         if (prop < E_AIL_PROP_BOOL_MIN || prop > E_AIL_PROP_BOOL_MAX)
889                 return AIL_ERROR_INVALID_PARAMETER;
890
891         switch (prop) {
892                 case E_AIL_PROP_X_SLP_INACTIVATED_BOOL:
893                         info->x_slp_inactivated = (int)value;
894                         break;
895                 default:
896                         return AIL_ERROR_FAIL;
897         }
898
899         return AIL_ERROR_OK;
900 }
901
902
903
904 static ail_error_e _create_table(void)
905 {
906         int i;
907         ail_error_e ret;
908         const char *tbls[3] = {
909                 "CREATE TABLE app_info "
910                 "(package TEXT PRIMARY KEY, "
911                 "exec TEXT DEFAULT 'No Exec', "
912                 "name TEXT DEFAULT 'No Name', "
913                 "type TEXT DEFAULT 'Application', "
914                 "icon TEXT DEFAULT 'No Icon', "
915                 "categories TEXT, "
916                 "version TEXT, "
917                 "mimetype TEXT, "
918                 "x_slp_service TEXT, "
919                 "x_slp_packagetype TEXT, "
920                 "x_slp_packagecategories TEXT, "
921                 "x_slp_packageid TEXT, "
922                 "x_slp_uri TEXT, "
923                 "x_slp_svc TEXT, "
924                 "x_slp_exe_path TEXT, "
925                 "x_slp_appid TEXT, "
926                 "x_slp_pkgid TEXT, "
927                 "x_slp_domain TEXT, "
928                 "x_slp_baselayoutwidth INTEGER DEFAULT 0, "
929                 "x_slp_installedtime INTEGER DEFAULT 0, "
930                 "nodisplay INTEGER DEFAULT 0, "
931                 "x_slp_taskmanage INTEGER DEFAULT 1, "
932                 "x_slp_multiple INTEGER DEFAULT 0, "
933                 "x_slp_removable INTEGER DEFAULT 1, "
934                 "x_slp_ishorizontalscale INTEGER DEFAULT 0, "
935                 "x_slp_inactivated INTEGER DEFAULT 0, "
936                 "desktop TEXT UNIQUE NOT NULL);",
937                 "CREATE TABLE localname (package TEXT NOT NULL, "
938                 "locale TEXT NOT NULL, "
939                 "name TEXT NOT NULL, PRIMARY KEY (package, locale));",
940                 NULL
941         };
942
943         ret = db_open(DB_OPEN_RW);
944         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_DB_FAILED);
945
946         for (i = 0; tbls[i] != NULL; i++) {
947                 ret = db_exec(tbls[i]);
948                 retv_if(ret != AIL_ERROR_OK, AIL_ERROR_DB_FAILED);
949         }
950
951         return AIL_ERROR_OK;
952 }
953
954
955 static inline void _insert_localname(gpointer data, gpointer user_data)
956 {
957         char query[512];
958
959         struct name_item *item = (struct name_item *)data;
960         desktop_info_s *info = (desktop_info_s *)user_data;
961
962         snprintf(query, sizeof(query), "insert into localname (package, locale, name) "
963                         "values ('%s', '%s', '%s');", 
964                         info->package, item->locale, item->name);
965         if (db_exec(query) < 0)
966                 _E("Failed to insert local name of package[%s]",info->package);
967 }
968
969 static ail_error_e _insert_desktop_info(desktop_info_s *info)
970 {
971         char *query;
972         int len;
973         ail_error_e ret;
974
975         len = _strlen_desktop_info(info) + (0x01 << 10);
976         query = calloc(1, len);
977         retv_if(!query, AIL_ERROR_OUT_OF_MEMORY);
978
979         sqlite3_snprintf(len, query, "insert into app_info ("
980                 "package, "
981                 "exec, name, "
982                 "type, "
983                 "icon, "
984                 "categories, "
985                 "version, "
986                 "mimetype, "
987                 "x_slp_service, "
988                 "x_slp_packagetype, "
989                 "x_slp_packagecategories, "
990                 "x_slp_packageid, "
991                 "x_slp_uri, "
992                 "x_slp_svc, "
993                 "x_slp_exe_path, "
994                 "x_slp_appid, "
995                 "x_slp_pkgid, "
996                 "x_slp_domain, "
997                 "x_slp_baselayoutwidth, "
998                 "x_slp_installedtime, "
999                 "nodisplay, "
1000                 "x_slp_taskmanage, "
1001                 "x_slp_multiple, "
1002                 "x_slp_removable, "
1003                 "x_slp_ishorizontalscale, "
1004                 "x_slp_inactivated, "
1005                 "desktop) "
1006                 "values "
1007                 "('%q', '%q', '%q', '%q', '%q', "
1008                 "'%q', '%q', '%q', '%q', '%q', "
1009                 "'%q', '%q', '%q', '%q', '%q', "
1010                 "'%q', '%q', '%q', "
1011                 "%d, %d, %d, %d, %d, %d, "
1012                 "%d, %d, "
1013                 "'%q');",
1014                 info->package,
1015                 info->exec,
1016                 info->name,
1017                 info->type,
1018                 info->icon,
1019                 info->categories,
1020                 info->version,
1021                 info->mimetype,
1022                 info->x_slp_service,
1023                 info->x_slp_packagetype,
1024                 info->x_slp_packagecategories,
1025                 info->x_slp_packageid,
1026                 info->x_slp_uri,
1027                 info->x_slp_svc,
1028                 info->x_slp_exe_path,
1029                 info->x_slp_appid,
1030                 info->x_slp_pkgid,
1031                 info->x_slp_domain,
1032                 info->x_slp_baselayoutwidth,
1033                 info->x_slp_installedtime,
1034                 info->nodisplay,
1035                 info->x_slp_taskmanage,
1036                 info->x_slp_multiple,
1037                 info->x_slp_removable,
1038                 info->x_slp_ishorizontalscale,
1039                 info->x_slp_inactivated,
1040                 info->desktop
1041                 );
1042
1043         ret = db_open(DB_OPEN_RW);
1044         if(ret != AIL_ERROR_OK) {
1045                 _E("(tmp == NULL) return\n");
1046                 free(query);
1047                 return AIL_ERROR_DB_FAILED;
1048         }
1049
1050         ret = db_exec(query);
1051         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_DB_FAILED);
1052
1053         if (info->localname)
1054                 g_slist_foreach(info->localname, _insert_localname, info);
1055
1056         _D("Add (%s).", info->package);
1057
1058         return AIL_ERROR_OK;
1059 }
1060
1061
1062
1063 static ail_error_e _update_desktop_info(desktop_info_s *info)
1064 {
1065         char *query;
1066         int len;
1067
1068         retv_if (NULL == info, AIL_ERROR_INVALID_PARAMETER);
1069
1070         if (db_open(DB_OPEN_RW) < 0) {
1071                 return AIL_ERROR_DB_FAILED;
1072         }
1073
1074         len = _strlen_desktop_info(info) + (0x01 << 10);
1075         query = calloc(1, len);
1076         retv_if(!query, AIL_ERROR_OUT_OF_MEMORY);
1077
1078         sqlite3_snprintf ( len, query, "update app_info set "
1079                 "exec='%q', "
1080                 "name='%q', "
1081                 "type='%q', "
1082                 "icon='%q', "
1083                 "categories='%q', "
1084                 "version='%q', "
1085                 "mimetype='%q', "
1086                 "x_slp_service='%q', "
1087                 "x_slp_packagetype='%q', "
1088                 "x_slp_packagecategories='%q', "
1089                 "x_slp_packageid='%q', "
1090                 "x_slp_uri='%q', "
1091                 "x_slp_svc='%q', "
1092                 "x_slp_exe_path='%q', "
1093                 "x_slp_appid='%q', "
1094                 "x_slp_pkgid='%q', "
1095                 "x_slp_domain='%q', "
1096                 "x_slp_baselayoutwidth=%d, "
1097                 "x_slp_installedtime=%d, "
1098                 "nodisplay=%d, "
1099                 "x_slp_taskmanage=%d, "
1100                 "x_slp_multiple=%d, "
1101                 "x_slp_removable=%d, "
1102                 "x_slp_ishorizontalscale=%d, "
1103                 "x_slp_inactivated=%d, "
1104                 "desktop='%q'"
1105                 "where package='%q'",
1106                 info->exec,
1107                 info->name,
1108                 info->type,
1109                 info->icon,
1110                 info->categories,
1111                 info->version,
1112                 info->mimetype,
1113                 info->x_slp_service,
1114                 info->x_slp_packagetype,
1115                 info->x_slp_packagecategories,
1116                 info->x_slp_packageid,
1117                 info->x_slp_uri,
1118                 info->x_slp_svc,
1119                 info->x_slp_exe_path,
1120                 info->x_slp_appid,
1121                 info->x_slp_pkgid,
1122                 info->x_slp_domain,
1123                 info->x_slp_baselayoutwidth,
1124                 info->x_slp_installedtime,
1125                 info->nodisplay,
1126                 info->x_slp_taskmanage,
1127                 info->x_slp_multiple,
1128                 info->x_slp_removable,
1129                 info->x_slp_ishorizontalscale,
1130                 info->x_slp_inactivated,
1131                 info->desktop,
1132                 info->package);
1133
1134         if (db_exec(query) < 0) {
1135                 free (query);
1136                 return AIL_ERROR_DB_FAILED;
1137         }
1138
1139         snprintf(query, len, "delete from localname where package = '%s'", info->package);
1140
1141         if (db_exec(query) < 0) {
1142                 free (query);
1143                 return AIL_ERROR_DB_FAILED;
1144         }
1145
1146         if (info->localname)
1147                 g_slist_foreach(info->localname, _insert_localname, info);
1148
1149         _D("Update (%s).", info->package);
1150
1151         free(query);
1152
1153         return AIL_ERROR_OK;
1154 }
1155
1156
1157
1158 static ail_error_e _remove_package(const char* package)
1159 {
1160         char *query;
1161         int size;
1162
1163         retv_if(!package, AIL_ERROR_INVALID_PARAMETER);
1164
1165         if (db_open(DB_OPEN_RW) < 0) {
1166                 return AIL_ERROR_DB_FAILED;
1167         }
1168
1169         size = strlen(package) + (0x01 << 10);
1170         query = calloc(1, size);
1171         retv_if(!query, AIL_ERROR_OUT_OF_MEMORY);
1172
1173         snprintf(query, size, "delete from app_info where package = '%s'", package);
1174
1175         if (db_exec(query) < 0) {
1176                 free(query);
1177                 return AIL_ERROR_DB_FAILED;
1178         }
1179
1180         snprintf(query, size, "delete from localname where package = '%s'", package);
1181         _D("query=%s",query);
1182
1183         if (db_exec(query) < 0) {
1184                 free(query);
1185                 return AIL_ERROR_DB_FAILED;
1186         }
1187
1188         _D("Remove (%s).", package);
1189         free(query);
1190
1191         return AIL_ERROR_OK;
1192 }
1193
1194
1195
1196 static ail_error_e _send_db_done_noti(noti_type type, const char *package)
1197 {
1198         char *type_string, *noti_string;
1199         int size;
1200
1201         retv_if(!package, AIL_ERROR_INVALID_PARAMETER);
1202
1203         switch (type) {
1204                 case NOTI_ADD:
1205                         type_string = "create";
1206                         break;
1207                 case NOTI_UPDATE:
1208                         type_string = "update";
1209                         break;
1210                 case NOTI_REMOVE:
1211                         type_string = "delete";
1212                         break;
1213                 default:
1214                         return AIL_ERROR_FAIL;
1215         }
1216
1217         size = strlen(package) + 8;
1218         noti_string = calloc(1, size);
1219         retv_if(!noti_string, AIL_ERROR_OUT_OF_MEMORY);
1220
1221         snprintf(noti_string, size, "%s:%s", type_string, package);
1222         vconf_set_str("memory/menuscreen/desktop", noti_string);
1223         _D("Noti : %s", noti_string);
1224
1225         free(noti_string);
1226
1227         return AIL_ERROR_OK;
1228 }
1229
1230
1231 static void inline _name_item_free_func(gpointer data)
1232 {
1233         struct name_item *item = (struct name_item *)data;
1234         if (item){
1235                 SAFE_FREE(item->locale);
1236                 item->locale = NULL;
1237                 SAFE_FREE(item->name);
1238                 item->name = NULL;
1239         }
1240         SAFE_FREE(item);
1241 }
1242
1243 static void _fini_desktop_info(desktop_info_s *info)
1244 {
1245         SAFE_FREE(info->exec);
1246         SAFE_FREE(info->name);
1247         SAFE_FREE(info->type);
1248         SAFE_FREE(info->icon);
1249         SAFE_FREE(info->categories);
1250         SAFE_FREE(info->version);
1251         SAFE_FREE(info->mimetype);
1252         SAFE_FREE(info->x_slp_service);
1253         SAFE_FREE(info->x_slp_packagetype);
1254         SAFE_FREE(info->x_slp_packagecategories);
1255         SAFE_FREE(info->x_slp_packageid);
1256         SAFE_FREE(info->x_slp_uri);
1257         SAFE_FREE(info->x_slp_svc);
1258         SAFE_FREE(info->x_slp_exe_path);
1259         SAFE_FREE(info->x_slp_appid);
1260         SAFE_FREE(info->desktop);
1261         if (info->localname) {
1262                 g_slist_free_full(info->localname, _name_item_free_func);
1263                 info->localname = NULL;
1264         }
1265
1266         return;
1267 }
1268
1269
1270
1271 /* Public functions */
1272 EXPORT_API ail_error_e ail_desktop_add(const char *appid)
1273 {
1274         desktop_info_s info = {0,};
1275         ail_error_e ret;
1276         int count;
1277
1278         retv_if(!appid, AIL_ERROR_INVALID_PARAMETER);
1279
1280         count = _count_all();
1281         if (count <= 0) {
1282                 ret = _create_table();
1283                 if (ret != AIL_ERROR_OK) {
1284                         _D("Cannot create a table. Maybe there is already a table.");
1285                 }
1286         }
1287
1288         ret = _init_desktop_info(&info, appid);
1289         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_FAIL);
1290
1291         ret = _read_desktop_info(&info);
1292         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_FAIL);
1293
1294         ret = _insert_desktop_info(&info);
1295         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_FAIL);
1296
1297         ret = _send_db_done_noti(NOTI_ADD, appid);
1298         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_FAIL);
1299
1300         _fini_desktop_info(&info);
1301
1302         return AIL_ERROR_OK;
1303 }
1304
1305
1306
1307 EXPORT_API ail_error_e ail_desktop_update(const char *appid)
1308 {
1309         desktop_info_s info = {0,};
1310         ail_error_e ret;
1311
1312         retv_if(!appid, AIL_ERROR_INVALID_PARAMETER);
1313
1314         ret = _init_desktop_info(&info, appid);
1315         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_FAIL);
1316
1317         ret = _read_desktop_info(&info);
1318         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_FAIL);
1319
1320         ret = _update_desktop_info(&info);
1321         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_FAIL);
1322
1323         ret = _send_db_done_noti(NOTI_UPDATE, appid);
1324         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_FAIL);
1325
1326         _fini_desktop_info(&info);
1327
1328         return AIL_ERROR_OK;
1329 }
1330
1331
1332
1333 EXPORT_API ail_error_e ail_desktop_remove(const char *appid)
1334 {
1335         ail_error_e ret;
1336
1337         retv_if(!appid, AIL_ERROR_INVALID_PARAMETER);
1338
1339         ret = _remove_package(appid);
1340         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_FAIL);
1341
1342         ret = _send_db_done_noti(NOTI_REMOVE, appid);
1343         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_FAIL);
1344
1345         return AIL_ERROR_OK;
1346 }
1347
1348
1349 EXPORT_API ail_error_e ail_desktop_appinfo_modify_bool(const char *package,
1350                                                              const char *property,
1351                                                              bool value)
1352 {
1353         desktop_info_s info = {0,};
1354         ail_error_e ret;
1355         ail_prop_bool_e prop;
1356
1357         retv_if(!package, AIL_ERROR_INVALID_PARAMETER);
1358
1359         retv_if(strcmp(property, AIL_PROP_X_SLP_INACTIVATED_BOOL),
1360                 AIL_ERROR_INVALID_PARAMETER);
1361
1362         ret = _init_desktop_info(&info, package);
1363         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_FAIL);
1364
1365         ret = _modify_desktop_info_bool(&info, property, value);
1366         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_FAIL);
1367
1368         ret = _update_desktop_info(&info);
1369         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_FAIL);
1370
1371         ret = _send_db_done_noti(NOTI_UPDATE, package);
1372         retv_if(ret != AIL_ERROR_OK, AIL_ERROR_FAIL);
1373
1374         _fini_desktop_info(&info);
1375
1376         return AIL_ERROR_OK;
1377 }
1378
1379
1380
1381
1382 // End of File