tizen 2.3 release
[apps/livebox/data-provider-master.git] / src / parser.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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> /* strtod */
19 #include <errno.h>
20 #include <ctype.h> /* isspace */
21
22 #include <Eina.h>
23 #include <dlog.h>
24
25 #include <dynamicbox_service.h>
26 #include <dynamicbox_errno.h>
27 #include <dynamicbox_conf.h>
28
29 #include "util.h"
30 #include "debug.h"
31 #include "conf.h"
32 #include "parser.h"
33
34 static Eina_List *s_list;
35 int errno;
36
37 #if __x86__64__
38 #define RETURN_TYPE long long
39 #else
40 #define RETURN_TYPE int
41 #endif
42
43 struct parser {
44         char *filename;
45         double period;
46         int timeout;
47         int network;
48         char *auto_launch;
49         unsigned int size;
50         unsigned int gbar_width;
51         unsigned int gbar_height;
52         char *group;
53         int secured;
54
55         char *gbar_path;
56         char *gbar_group;
57
58         char *dbox_path;
59         char *dbox_group;
60         int pinup;
61         int text_gbar;
62         int text_lb;
63         int buffer_gbar;
64         int buffer_lb;
65
66         char *abi;
67
68         char *script;
69 };
70
71 HAPI double parser_period(struct parser *handle)
72 {
73         return handle->period;
74 }
75
76 HAPI int parser_network(struct parser *handle)
77 {
78         return handle->network;
79 }
80
81 HAPI int parser_timeout(struct parser *handle)
82 {
83         return handle->timeout;
84 }
85
86 HAPI const char *parser_auto_launch(struct parser *handle)
87 {
88         return handle->auto_launch;
89 }
90
91 HAPI const char *parser_script(struct parser *handle)
92 {
93         return handle->script;
94 }
95
96 HAPI const char *parser_abi(struct parser *handle)
97 {
98         return handle->abi;
99 }
100
101 HAPI unsigned int parser_size(struct parser *handle)
102 {
103         return handle->size;
104 }
105
106 HAPI const char *parser_dbox_path(struct parser *handle)
107 {
108         return handle->dbox_path;
109 }
110
111 HAPI const char *parser_dbox_group(struct parser *handle)
112 {
113         return handle->dbox_group;
114 }
115
116 HAPI const char *parser_gbar_path(struct parser *handle)
117 {
118         return handle->gbar_path;
119 }
120
121 HAPI const char *parser_gbar_group(struct parser *handle)
122 {
123         return handle->gbar_group;
124 }
125
126 HAPI const char *parser_group_str(struct parser *handle)
127 {
128         return handle->group;
129 }
130
131 HAPI int parser_secured(struct parser *handle)
132 {
133         return handle->secured;
134 }
135
136 HAPI void parser_get_gbar_size(struct parser *handle, unsigned int *width, unsigned int *height)
137 {
138         *width = handle->gbar_width;
139         *height = handle->gbar_height;
140 }
141
142 HAPI int parser_pinup(struct parser *handle)
143 {
144         return handle->pinup;
145 }
146
147 HAPI int parser_text_dbox(struct parser *handle)
148 {
149         return handle->text_lb;
150 }
151
152 HAPI int parser_text_gbar(struct parser *handle)
153 {
154         return handle->text_gbar;
155 }
156
157 HAPI int parser_buffer_dbox(struct parser *handle)
158 {
159         return handle->buffer_lb;
160 }
161
162 HAPI int parser_buffer_gbar(struct parser *handle)
163 {
164         return handle->buffer_gbar;
165 }
166
167 HAPI RETURN_TYPE parser_find(const char *pkgname)
168 {
169         Eina_List *l;
170         struct parser *item;
171         char *filename;
172         int len;
173         int ret;
174
175         len = strlen(pkgname) * 2 + strlen(DYNAMICBOX_CONF_CONF_PATH);
176
177         filename = malloc(len);
178         if (!filename) {
179                 return (RETURN_TYPE)0;
180         }
181
182         ret = snprintf(filename, len, DYNAMICBOX_CONF_CONF_PATH, pkgname, pkgname);
183         if (ret < 0) {
184                 DbgFree(filename);
185                 return (RETURN_TYPE)0;
186         }
187
188         DbgPrint("Conf file %s for package %s\n", filename, pkgname);
189
190         EINA_LIST_FOREACH(s_list, l, item) {
191                 if (!strcmp(item->filename, filename)) {
192                         DbgFree(filename);
193                         return (RETURN_TYPE)item;
194                 }
195         }
196
197         DbgFree(filename);
198         return (RETURN_TYPE)0;
199 }
200
201 static inline int parse_size(const char *buffer, unsigned int *size)
202 {
203         register int i;
204         int w;
205         int h;
206
207         enum {
208                 START,
209                 WIDTH,
210                 DELIM,
211                 HEIGHT,
212                 ERROR,
213                 STOP,
214                 END
215         } state;
216
217         *size = 0;
218         state = START;
219         i = 0;
220         w = 0;
221         h = 0;
222
223         while (state != ERROR && state != END) {
224                 switch (state) {
225                 case START:
226                         switch (buffer[i]) {
227                         case '1'...'9':
228                                 state = WIDTH;
229                                 break;
230                         case ' ':
231                         case '\t':
232                         case ';':
233                                 i++;
234                                 break;
235                         case '\0':
236                                 state = END;
237                                 break;
238                         default:
239                                 state = ERROR;
240                                 break;
241                         }
242                         break;
243                 case WIDTH:
244                         switch (buffer[i]) {
245                         case '0'...'9':
246                                 w = (w * 10) + (buffer[i] - '0');
247                                 i++;
248                                 break;
249                         case 'x':
250                                 state = DELIM;
251                                 i++;
252                                 break;
253                         default:
254                                 state = ERROR;
255                                 break;
256                         }
257
258                         break;
259                 case DELIM:
260                         switch (buffer[i]) {
261                         case '1'...'9':
262                                 state = HEIGHT;
263                                 break;
264                         case ' ':
265                         case '\t':
266                                 i++;
267                                 break;
268                         default:
269                                 state = ERROR;
270                                 break;
271                         }
272                         break;
273                 case HEIGHT:
274                         switch (buffer[i]) {
275                         case '0'...'9':
276                                 h = (h * 10) + (buffer[i] - '0');
277                                 i++;
278                                 break;
279                         case ';':
280                         case '\0':
281                                 state = STOP;
282                                 break;
283                         default:
284                                 state = ERROR;
285                                 break;
286                         }
287                         break;
288                 case STOP:
289                         if (w == 1 && h == 1) {
290                                 *size |= DBOX_SIZE_TYPE_1x1;
291                         } else if (w == 2 && h == 1) {
292                                 *size |= DBOX_SIZE_TYPE_2x1;
293                         } else if (w == 2 && h == 2) {
294                                 *size |= DBOX_SIZE_TYPE_2x2;
295                         } else if (w == 4 && h == 1) {
296                                 *size |= DBOX_SIZE_TYPE_4x1;
297                         } else if (w == 4 && h == 2) {
298                                 *size |= DBOX_SIZE_TYPE_4x2;
299                         } else if (w == 4 && h == 3) {
300                                 *size |= DBOX_SIZE_TYPE_4x3;
301                         } else if (w == 4 && h == 4) {
302                                 *size |= DBOX_SIZE_TYPE_4x4;
303                         } else if (w == 21 && h == 21) {
304                                 *size |= DBOX_SIZE_TYPE_EASY_1x1;
305                         } else if (w == 23 && h == 21) {
306                                 *size |= DBOX_SIZE_TYPE_EASY_3x1;
307                         } else if (w == 23 && h == 23) {
308                                 *size |= DBOX_SIZE_TYPE_EASY_3x3;
309                         } else {
310                                 ErrPrint("Invalid size type: %dx%d\n", w, h);
311                         }
312
313                         if (buffer[i] == ';') {
314                                 state = START;
315                         } else if (buffer[i] == '\0') {
316                                 state = END;
317                         }
318
319                         w = 0;
320                         h = 0;
321                         break;
322                 default:
323                         return -1;
324                 }
325         }
326
327         return *size ? 0 : -1;
328 }
329
330 /*!
331  * \note
332  * This will change the value of "buffer"
333  */
334 static inline const char *rtrim(char *buffer)
335 {
336         int len;
337
338         len = strlen(buffer);
339         while (len > 0 && isspace(buffer[len - 1])) {
340                 len--;
341         }
342
343         if (len <= 0) {
344                 return NULL;
345         }
346
347         buffer[len] = '\0';
348
349         return buffer;
350 }
351
352 /*!
353  * \note
354  * This will change the value of "buffer"
355  */
356 static inline char *dup_rtrim(char *buffer)
357 {
358         char *ret;
359
360         if (!rtrim(buffer)) {
361                 return NULL;
362         }
363
364         ret = strdup(buffer);
365         if (!ret) {
366                 ErrPrint("Heap: %s\n", strerror(errno));
367                 return NULL;
368         }
369
370         return ret;
371 }
372
373 static void period_handler(struct parser *item, char *buffer)
374 {
375         char *tmp = NULL;
376
377         if (!rtrim(buffer)) {
378                 return;
379         }
380
381         item->period = strtod(buffer, &tmp);
382 }
383
384 static void timeout_handler(struct parser *item, char *buffer)
385 {
386         if (!rtrim(buffer)) {
387                 return;
388         }
389
390         item->timeout = atoi(buffer);
391 }
392
393 static void network_handler(struct parser *item, char *buffer)
394 {
395         if (!rtrim(buffer)) {
396                 return;
397         }
398
399         item->network = !!atoi(buffer);
400 }
401
402 static void auto_launch_handler(struct parser *item, char *buffer)
403 {
404         if (!rtrim(buffer)) {
405                 return;
406         }
407
408         item->auto_launch = strdup(buffer);
409         if (!item->auto_launch) {
410                 ErrPrint("Heap: %s\n", strerror(errno));
411                 return;
412         }
413 }
414
415 static void size_handler(struct parser *item, char *buffer)
416 {
417         if (parse_size(buffer, &item->size) == -1) {
418                 ErrPrint("Failed to get size\n");
419                 item->size = 0x00000001;
420         }
421 }
422
423 static void gbar_size_handler(struct parser *item, char *buffer)
424 {
425         if (sscanf(buffer, "%ux%u", &item->gbar_width, &item->gbar_height) != 2) {
426                 ErrPrint("parse pd size\n");
427         }
428 }
429
430 static void text_dbox_handler(struct parser *item, char *buffer)
431 {
432         if (!rtrim(buffer)) {
433                 return;
434         }
435
436         item->text_lb = !!atoi(buffer);
437 }
438
439 static void abi_handler(struct parser *item, char *buffer)
440 {
441         item->abi = dup_rtrim(buffer);
442 }
443
444 static void script_handler(struct parser *item, char *buffer)
445 {
446         item->script = dup_rtrim(buffer);
447 }
448
449 static void buffer_gbar_handler(struct parser *item, char *buffer)
450 {
451         if (!rtrim(buffer)) {
452                 return;
453         }
454
455         item->buffer_gbar = !!atoi(buffer);
456 }
457
458 static void buffer_dbox_handler(struct parser *item, char *buffer)
459 {
460         if (!rtrim(buffer)) {
461                 return;
462         }
463
464         item->buffer_lb = !!atoi(buffer);
465 }
466
467 static void text_gbar_handler(struct parser *item, char *buffer)
468 {
469         if (!rtrim(buffer)) {
470                 return;
471         }
472
473         item->text_gbar = !!atoi(buffer);
474 }
475
476 static void pinup_handler(struct parser *item, char *buffer)
477 {
478         if (!rtrim(buffer)) {
479                 return;
480         }
481
482         item->pinup = !!atoi(buffer);
483 }
484
485 static void dbox_path_handler(struct parser *item, char *buffer)
486 {
487         if (item->dbox_path) {
488                 DbgFree(item->dbox_path);
489         }
490
491         item->dbox_path = dup_rtrim(buffer);
492         if (!item->dbox_path) {
493                 ErrPrint("Error: %s\n", strerror(errno));
494         }
495 }
496
497 static void group_handler(struct parser *item, char *buffer)
498 {
499         if (item->group) {
500                 DbgFree(item->group);
501         }
502
503         item->group = dup_rtrim(buffer);
504         if (!item->group) {
505                 ErrPrint("Error: %s\n", strerror(errno));
506         }
507 }
508
509 static void secured_handler(struct parser *item, char *buffer)
510 {
511         if (!rtrim(buffer)) {
512                 return;
513         }
514
515         item->secured = !!atoi(buffer);
516 }
517
518 static void dbox_group_handler(struct parser *item, char *buffer)
519 {
520         if (item->dbox_group) {
521                 DbgFree(item->dbox_group);
522         }
523
524         item->dbox_group = dup_rtrim(buffer);
525         if (!item->dbox_group) {
526                 ErrPrint("Error: %s\n", strerror(errno));
527         }
528 }
529
530 static void gbar_path_handler(struct parser *item, char *buffer)
531 {
532         if (item->gbar_path) {
533                 DbgFree(item->gbar_path);
534         }
535
536         item->gbar_path = dup_rtrim(buffer);
537         if (!item->gbar_path) {
538                 ErrPrint("Error: %s\n", strerror(errno));
539         }
540 }
541
542 static void gbar_group_handler(struct parser *item, char *buffer)
543 {
544         if (item->gbar_group) {
545                 DbgFree(item->gbar_group);
546         }
547
548         item->gbar_group = dup_rtrim(buffer);
549         if (!item->gbar_group) {
550                 ErrPrint("Error: %s\n", strerror(errno));
551         }
552 }
553
554 HAPI struct parser *parser_load(const char *pkgname)
555 {
556         struct parser *item;
557         FILE *fp;
558         int c;
559         enum state {
560                 START,
561                 SPACE,
562                 TOKEN,
563                 VALUE,
564                 ERROR,
565                 COMMENT,
566                 END
567         } state;
568         int ch_idx;
569         int token_idx;
570         int buffer_idx;
571         int quote;
572         int len;
573         int linelen;
574         char buffer[256];
575         static const struct token_parser {
576                 const char *name;
577                 void (*handler)(struct parser *, char *buffer);
578         } token_handler[] = {
579                 {
580                         .name = "period",
581                         .handler = period_handler,
582                 },
583                 {
584                         .name = "timeout",
585                         .handler = timeout_handler,
586                 },
587                 {
588                         .name = "network",
589                         .handler = network_handler,
590                 },
591                 {
592                         .name = "auto_launch",
593                         .handler = auto_launch_handler,
594                 },
595                 {
596                         .name = "size",
597                         .handler = size_handler,
598                 },
599                 {
600                         .name = "group",
601                         .handler = group_handler,
602                 },
603                 {
604                         .name = "secured",
605                         .handler = secured_handler,
606                 },
607                 {
608                         .name = "dynamicbox_path",
609                         .handler = dbox_path_handler,
610                 },
611                 {
612                         .name = "dynamicbox_group",
613                         .handler = dbox_group_handler,
614                 },
615                 {
616                         .name = "gbar_path",
617                         .handler = gbar_path_handler,
618                 },
619                 {
620                         .name = "gbar_group",
621                         .handler = gbar_group_handler,
622                 },
623                 {
624                         .name = "gbar_size",
625                         .handler = gbar_size_handler,
626                 },
627                 {
628                         .name = "pinup",
629                         .handler = pinup_handler,
630                 },
631                 {
632                         .name = "text_dynamicbox",
633                         .handler = text_dbox_handler,
634                 },
635                 {
636                         .name = "text_gbar",
637                         .handler = text_gbar_handler,
638                 },
639                 {
640                         .name = "buffer_dynamicbox",
641                         .handler = buffer_dbox_handler,
642                 },
643                 {
644                         .name = "buffer_gbar",
645                         .handler = buffer_gbar_handler,
646                 },
647                 {
648                         .name = "script",
649                         .handler = script_handler,
650                 },
651                 {
652                         .name = "abi",
653                         .handler = abi_handler,
654                 },
655                 {
656                         .name = NULL,
657                         .handler = NULL,
658                 },
659         };
660         int ret;
661
662         item = calloc(1, sizeof(*item));
663         if (!item) {
664                 return 0;
665         }
666
667         /* live-, .conf */
668         len = strlen(DYNAMICBOX_CONF_CONF_PATH) + strlen(pkgname) * 2;
669         item->filename = malloc(len);
670         if (!item->filename) {
671                 ErrPrint("Error: %s\n", strerror(errno));
672                 DbgFree(item);
673                 return 0;
674         }
675
676         ret = snprintf(item->filename, len, DYNAMICBOX_CONF_CONF_PATH, pkgname, pkgname);
677         if (ret < 0) {
678                 ErrPrint("Error: %s\n", strerror(errno));
679                 DbgFree(item->filename);
680                 DbgFree(item);
681                 return 0;
682         }
683
684         item->dbox_path = NULL;
685         item->dbox_group = NULL;
686         item->gbar_width = 0;
687         item->gbar_height = 0;
688         item->auto_launch = NULL;
689         item->size = 0x00000001;
690         item->group = NULL;
691         item->secured = 0;
692         item->pinup = 0;
693
694         fp = fopen(item->filename, "rt");
695         if (!fp) {
696                 DbgFree(item->filename);
697                 DbgFree(item);
698                 return 0;
699         }
700
701         state = START;
702         ch_idx = 0;
703         token_idx = -1;
704         buffer_idx = 0;
705         quote = 0;
706         linelen = 0;
707         do {
708                 c = getc(fp);
709                 if ((c == EOF) && (state == VALUE)) {
710                         state = END;
711                 }
712
713                 switch (state) {
714                 case COMMENT:
715                         if (c == CR || c == LF || c == EOF) {
716                                 buffer[buffer_idx] = '\0';
717
718                                 state = START;
719                                 token_idx = -1;
720                                 ch_idx = 0;
721                                 buffer_idx = 0;
722                                 linelen = -1; /* Will be ZERO by follwing increment code */
723                                 quote = 0;
724                         } else {
725                                 buffer[buffer_idx++] = c;
726                                 if (buffer_idx == (sizeof(buffer) - 1)) {
727                                         buffer[buffer_idx] = '\0';
728                                         buffer_idx = 0;
729                                 }
730                         }
731                         break;
732                 case START:
733                         if (linelen == 0 && c == '#') {
734                                 state = COMMENT;
735                         } else if (isspace(c)) {
736                                 /* Ignore empty space */
737                         } else {
738                                 state = TOKEN;
739                                 ungetc(c, fp);
740                         }
741                         break;
742                 case SPACE:
743                         if (c == '=') {
744                                 state = VALUE;
745                         } else if (!isspace(c)) {
746                                 state = ERROR;
747                         }
748                         break;
749                 case VALUE:
750                         if (c == '"') {
751                                 if (quote == 1) {
752                                         buffer[buffer_idx] = '\0';
753                                         state = END;
754                                 } else if (buffer_idx != 0) {
755                                         buffer[buffer_idx++] = c;
756                                         if (buffer_idx >= sizeof(buffer)) {
757                                                 state = ERROR;
758                                         }
759                                 } else {
760                                         quote = 1;
761                                 }
762                         } else if (isspace(c)) {
763                                 if (buffer_idx == 0) {
764                                         /* Ignore */
765                                 } else if (quote == 1) {
766                                         buffer[buffer_idx++] = c;
767                                         if (buffer_idx >= sizeof(buffer)) {
768                                                 state = ERROR;
769                                         }
770                                 } else {
771                                         buffer[buffer_idx] = '\0';
772                                         ungetc(c, fp);
773                                         state = END;
774                                 }
775                         } else {
776                                 buffer[buffer_idx++] = c;
777                                 if (buffer_idx >= sizeof(buffer)) {
778                                         state = ERROR;
779                                 }
780                         }
781                         break;
782                 case TOKEN:
783                         if (c == '=') {
784                                 if (token_idx < 0) {
785                                         state = ERROR;
786                                 } else {
787                                         state = VALUE;
788                                 }
789                         } else if (isspace(c)) {
790                                 if (token_idx < 0) {
791                                         break;
792                                 }
793
794                                 if (token_handler[token_idx].name[ch_idx] != '\0') {
795                                         state = ERROR;
796                                 } else {
797                                         state = SPACE;
798                                 }
799                         } else  {
800                                 if (token_idx < 0) {
801                                         /* Now start to find a token! */
802                                         token_idx = 0;
803                                 }
804
805                                 if (token_handler[token_idx].name[ch_idx] == c) {
806                                         ch_idx++;
807                                 } else {
808                                         ungetc(c, fp);
809                                         while (ch_idx-- > 0) {
810                                                 ungetc(token_handler[token_idx].name[ch_idx], fp);
811                                         }
812
813                                         token_idx++;
814
815                                         if (token_handler[token_idx].name == NULL) {
816                                                 state = ERROR;
817                                         } else {
818                                                 ch_idx = 0;
819                                         }
820                                 }
821                         }
822                         break;
823                 case ERROR:
824                         if (c == CR || c == LF || c == EOF) {
825                                 state = START;
826                                 token_idx = -1;
827                                 buffer_idx = 0;
828                                 ch_idx = 0;
829                                 linelen = -1;
830                                 quote = 0;
831                         }
832                         break;
833                 case END:
834                         if (c == LF || c == CR || c == EOF) {
835                                 state = START;
836
837                                 /*!
838                                  * \NOTE
839                                  * Make the string terminator
840                                  */
841                                 buffer[buffer_idx] = '\0';
842
843                                 if (token_idx >= 0 && token_handler[token_idx].handler) {
844                                         token_handler[token_idx].handler(item, buffer);
845                                 }
846
847                                 token_idx = -1;
848                                 ch_idx = 0;
849                                 buffer_idx = 0;
850                                 linelen = -1;
851                                 quote = 0;
852                                 /* Finish */
853                         } else if (isspace(c)) {
854                                 /* ignore */
855                         } else {
856                                 state = ERROR;
857                         }
858                         break;
859                 default:
860                         /* ?? */
861                         break;
862                 }
863
864                 linelen++;
865         } while (c != EOF);
866
867         if (fclose(fp) != 0) {
868                 ErrPrint("fclose: %s\n", strerror(errno));
869         }
870
871         s_list = eina_list_append(s_list, item);
872         return item;
873 }
874
875 HAPI int parser_unload(struct parser *item)
876 {
877         s_list = eina_list_remove(s_list, item);
878
879         DbgFree(item->auto_launch);
880         DbgFree(item->abi);
881         DbgFree(item->script);
882         DbgFree(item->group);
883         DbgFree(item->gbar_group);
884         DbgFree(item->gbar_path);
885         DbgFree(item->dbox_group);
886         DbgFree(item->dbox_path);
887         DbgFree(item->filename);
888         DbgFree(item);
889         return DBOX_STATUS_ERROR_NONE;
890 }
891
892 /* End of a file */