summaryrefslogtreecommitdiff
path: root/src/bin/edje/edje_decc.c
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@gmail.com>2013-01-04 02:08:14 +0000
committerGustavo Sverzut Barbieri <barbieri@gmail.com>2013-01-04 02:08:14 +0000
commit9ea2ce1041549c90f94062ce5ec145056e7fbdfa (patch)
tree3bcd3fb016bc498a72ff99c8d67c8b7ef2d91718 /src/bin/edje/edje_decc.c
parente2ce20e9a4dfd12bb383a1b60032f2ef7b507850 (diff)
efl: merge edje.
this is still in progress, mostly the multisense stuff is pending. it seems that when we merge ecore_audio in edje the libremix and similar are gone, at least from Edje, and will be in ecore_audio itself (or pulseaudio). Changes: * __UNUSED__ to EINA_UNUSED * binaries (epp, embryo_cc, edje_cc) now consider EFL_RUN_IN_TREE and will assume the binaries are still not installed, running from build tree location (needs more testing, maybe doesn't work with srcdir != builddir, still doesn't solve cross compile builds) SVN revision: 82139
Diffstat (limited to 'src/bin/edje/edje_decc.c')
-rw-r--r--src/bin/edje/edje_decc.c558
1 files changed, 558 insertions, 0 deletions
diff --git a/src/bin/edje/edje_decc.c b/src/bin/edje/edje_decc.c
new file mode 100644
index 0000000000..1fe3660ab7
--- /dev/null
+++ b/src/bin/edje/edje_decc.c
@@ -0,0 +1,558 @@
1/* ugly ugly. avert your eyes. */
2
3#ifdef HAVE_CONFIG_H
4# include <config.h>
5#endif
6
7#include <string.h>
8#include <ctype.h>
9#include <unistd.h>
10#include <locale.h>
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <errno.h>
14
15
16#include <Ecore_File.h>
17#include <Ecore_Evas.h>
18
19#include "edje_decc.h"
20
21int _edje_cc_log_dom = -1;
22static const char *progname = NULL;
23char *file_in = NULL;
24char *file_out = NULL;
25int compress_mode = EET_COMPRESSION_DEFAULT;
26
27Edje_File *edje_file = NULL;
28SrcFile_List *srcfiles = NULL;
29Edje_Font_List *fontlist = NULL;
30
31int line = 0;
32int build_sh = 1;
33int new_dir = 1;
34
35int decomp(void);
36void output(void);
37static int compiler_cmd_is_sane();
38static int root_filename_is_sane();
39
40
41static void
42_edje_cc_log_cb(const Eina_Log_Domain *d,
43 Eina_Log_Level level,
44 const char *file,
45 const char *fnc,
46 int line,
47 const char *fmt,
48 EINA_UNUSED void *data,
49 va_list args)
50{
51 if ((d->name) && (d->namelen == sizeof("edje_decc") - 1) &&
52 (memcmp(d->name, "edje_decc", sizeof("edje_decc") - 1) == 0))
53 {
54 const char *prefix;
55 Eina_Bool use_color = !eina_log_color_disable_get();
56
57 if (use_color)
58 {
59#ifndef _WIN32
60 fputs(eina_log_level_color_get(level), stderr);
61#else
62 int color;
63 switch (level)
64 {
65 case EINA_LOG_LEVEL_CRITICAL:
66 color = FOREGROUND_RED | FOREGROUND_INTENSITY;
67 break;
68 case EINA_LOG_LEVEL_ERR:
69 color = FOREGROUND_RED;
70 break;
71 case EINA_LOG_LEVEL_WARN:
72 color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
73 break;
74 case EINA_LOG_LEVEL_INFO:
75 color = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
76 break;
77 case EINA_LOG_LEVEL_DBG:
78 color = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
79 break;
80 default:
81 color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
82 }
83 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
84#endif
85 }
86
87 switch (level)
88 {
89 case EINA_LOG_LEVEL_CRITICAL:
90 prefix = "Critical. ";
91 break;
92 case EINA_LOG_LEVEL_ERR:
93 prefix = "Error. ";
94 break;
95 case EINA_LOG_LEVEL_WARN:
96 prefix = "Warning. ";
97 break;
98 default:
99 prefix = "";
100 }
101 fprintf(stderr, "%s: %s", progname, prefix);
102
103 if (use_color)
104 {
105#ifndef _WIN32
106 fputs(EINA_COLOR_RESET, stderr);
107#else
108 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
109 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
110#endif
111 }
112
113
114 vfprintf(stderr, fmt, args);
115 putc('\n', stderr);
116 }
117 else
118 eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
119}
120
121static void
122main_help(void)
123{
124 printf
125 ("Usage:\n"
126 "\t%s input_file.edj [-main-out file.edc] [-no-build-sh] [-current-dir]\n"
127 "\n"
128 " -main-out\tCreate a symbolic link to the main edc \n"
129 " -no-build-sh\tDon't output build.sh \n"
130 " -current-dir\tOutput to current directory \n"
131 " -quiet\t\tProduce less output\n"
132 "\n"
133 ,progname);
134}
135
136Eet_File *ef;
137Eet_Dictionary *ed;
138
139int
140main(int argc, char **argv)
141{
142 int i;
143
144 setlocale(LC_NUMERIC, "C");
145 if (!eina_init())
146 exit(-1);
147 _edje_cc_log_dom = eina_log_domain_register
148 ("edje_decc", EDJE_CC_DEFAULT_LOG_COLOR);
149 if (_edje_cc_log_dom < 0)
150 {
151 EINA_LOG_ERR("Impossible to create a log domain.");
152 eina_shutdown();
153 exit(-1);
154 }
155 progname = ecore_file_file_get(argv[0]);
156 eina_log_print_cb_set(_edje_cc_log_cb, NULL);
157 eina_log_domain_level_set("edje_decc", EINA_LOG_LEVEL_INFO);
158
159 for (i = 1; i < argc; i++)
160 {
161 if (!strcmp(argv[i], "-h"))
162 {
163 main_help();
164 exit(0);
165 }
166 if (!file_in)
167 file_in = argv[i];
168 else if ((!strcmp(argv[i], "-main-out")) && (i < (argc - 1)))
169 {
170 i++;
171 file_out = argv[i];
172 }
173 else if (!strcmp(argv[i], "-no-build-sh"))
174 build_sh = 0;
175 else if (!strcmp(argv[i], "-current-dir"))
176 new_dir = 0;
177 else if (!strcmp(argv[i], "-quiet"))
178 eina_log_domain_level_set("edje_decc", EINA_LOG_LEVEL_WARN);
179 }
180 if (!file_in)
181 {
182 ERR("no input file specified.");
183 main_help();
184 exit(-1);
185 }
186
187 if (!edje_init())
188 exit(-1);
189 source_edd();
190
191 if (!decomp()) return -1;
192 output();
193
194 WRN("If any Image or audio data was encoded in a LOSSY way, then "
195 "re-encoding will drop quality even more. "
196 "You need access to the original data to ensure no loss of quality.");
197 eet_close(ef);
198 edje_shutdown();
199 eina_log_domain_unregister(_edje_cc_log_dom);
200 _edje_cc_log_dom = -1;
201 eina_shutdown();
202 return 0;
203}
204
205int
206decomp(void)
207{
208 ef = eet_open(file_in, EET_FILE_MODE_READ);
209 if (!ef)
210 {
211 ERR("cannot open %s", file_in);
212 return 0;
213 }
214
215 srcfiles = source_load(ef);
216 if (!srcfiles || !srcfiles->list)
217 {
218 ERR("%s has no decompile information", file_in);
219 eet_close(ef);
220 return 0;
221 }
222 if (!eina_list_data_get(srcfiles->list) || !root_filename_is_sane())
223 {
224 ERR("Invalid root filename: '%s'", (char *) eina_list_data_get(srcfiles->list));
225 eet_close(ef);
226 return 0;
227 }
228 edje_file = eet_data_read(ef, _edje_edd_edje_file, "edje/file");
229 if (!edje_file)
230 {
231 ERR("%s does not appear to be an edje file", file_in);
232 eet_close(ef);
233 return 0;
234 }
235 /* force compiler to be edje_cc */
236 edje_file->compiler = strdup("edje_cc");
237 if (!edje_file->compiler)
238 {
239 edje_file->compiler = strdup("edje_cc");
240 }
241 else if (!compiler_cmd_is_sane())
242 {
243 ERR("invalid compiler executable: '%s'", edje_file->compiler);
244 eet_close(ef);
245 return 0;
246 }
247 fontlist = source_fontmap_load(ef);
248 return 1;
249}
250
251void
252output(void)
253{
254 Eina_List *l;
255 Eet_File *tef;
256 SrcFile *sf;
257 char *outdir, *p;
258
259 if (!new_dir)
260 outdir = strdup(".");
261 else
262 {
263 p = strrchr(file_in, '/');
264 if (p)
265 outdir = strdup(p + 1);
266 else
267 outdir = strdup(file_in);
268 p = strrchr(outdir, '.');
269 if (p) *p = 0;
270 ecore_file_mkpath(outdir);
271 }
272
273
274 tef = eet_open(file_in, EET_FILE_MODE_READ);
275
276 if (edje_file->image_dir)
277 {
278 Edje_Image_Directory_Entry *ei;
279 unsigned int i;
280
281 for (i = 0; i < edje_file->image_dir->entries_count; ++i)
282 {
283 ei = &edje_file->image_dir->entries[i];
284
285 if ((ei->source_type > EDJE_IMAGE_SOURCE_TYPE_NONE) &&
286 (ei->source_type < EDJE_IMAGE_SOURCE_TYPE_LAST) &&
287 (ei->source_type != EDJE_IMAGE_SOURCE_TYPE_EXTERNAL) &&
288 (ei->entry))
289 {
290 Ecore_Evas *ee;
291 Evas *evas;
292 Evas_Object *im;
293 char buf[4096];
294 char out[4096];
295 char *pp;
296
297 ecore_init();
298 ecore_evas_init();
299 ee = ecore_evas_buffer_new(1, 1);
300 if (!ee)
301 {
302 ERR("Cannot create buffer engine canvas for image save.");
303 exit(-1);
304 }
305 evas = ecore_evas_get(ee);
306 im = evas_object_image_add(evas);
307 if (!im)
308 {
309 ERR("Cannot create image object for save.");
310 exit(-1);
311 }
312 snprintf(buf, sizeof(buf), "edje/images/%i", ei->id);
313 evas_object_image_file_set(im, file_in, buf);
314 snprintf(out, sizeof(out), "%s/%s", outdir, ei->entry);
315 INF("Output Image: %s", out);
316 pp = strdup(out);
317 p = strrchr(pp, '/');
318 *p = 0;
319 if (strstr(pp, "../"))
320 {
321 ERR("Potential security violation. attempt to write in parent dir.");
322 exit(-1);
323 }
324 ecore_file_mkpath(pp);
325 free(pp);
326 if (!evas_object_image_save(im, out, NULL, "quality=100 compress=9"))
327 {
328 ERR("Cannot write file %s. Perhaps missing JPEG or PNG saver modules for Evas.", out);
329 exit(-1);
330 }
331 evas_object_del(im);
332 ecore_evas_free(ee);
333 ecore_evas_shutdown();
334 ecore_shutdown();
335 }
336 }
337 }
338
339 EINA_LIST_FOREACH(srcfiles->list, l, sf)
340 {
341 char out[4096];
342 FILE *f;
343 char *pp;
344
345 snprintf(out, sizeof(out), "%s/%s", outdir, sf->name);
346 INF("Output Source File: %s", out);
347 pp = strdup(out);
348 p = strrchr(pp, '/');
349 *p = 0;
350 if (strstr(pp, "../"))
351 {
352 ERR("Potential security violation. attempt to write in parent dir.");
353 exit (-1);
354 }
355 ecore_file_mkpath(pp);
356 free(pp);
357 if (strstr(out, "../"))
358 {
359 ERR("Potential security violation. attempt to write in parent dir.");
360 exit (-1);
361 }
362 f = fopen(out, "wb");
363 if (!f)
364 {
365 ERR("Unable to write file (%s).", out);
366 exit (-1);
367 }
368
369 /* if the file is empty, sf->file will be NULL.
370 * note that that's not an error
371 */
372 if (sf->file) fputs(sf->file, f);
373 fclose(f);
374 }
375 if (edje_file->fonts)
376 {
377 Edje_Font_Directory_Entry *fn;
378 Eina_Iterator *it;
379
380 it = eina_hash_iterator_data_new(edje_file->fonts);
381 EINA_ITERATOR_FOREACH(it, fn)
382 {
383 void *font;
384 int fontsize;
385 char out[4096];
386 /* FIXME!!!! */
387 /* should be fn->entry -v */
388 snprintf(out, sizeof(out), "edje/fonts/%s", fn->file);
389 font = eet_read(tef, out, &fontsize);
390 if (font)
391 {
392 FILE *f;
393 char *pp;
394
395 /* should be fn->file -v */
396 snprintf(out, sizeof(out), "%s/%s", outdir, fn->entry);
397 INF("Output Font: %s", out);
398 pp = strdup(out);
399 p = strrchr(pp, '/');
400 *p = 0;
401 if (strstr(pp, "../"))
402 {
403 ERR("Potential security violation. attempt to write in parent dir.");
404 exit (-1);
405 }
406 ecore_file_mkpath(pp);
407 free(pp);
408 if (strstr(out, "../"))
409 {
410 ERR("Potential security violation. attempt to write in parent dir.");
411 exit (-1);
412 }
413 if (!(f = fopen(out, "wb")))
414 {
415 ERR("Could not open file: %s", out);
416 exit (-1);
417 }
418 if (fwrite(font, fontsize, 1, f) != 1)
419 ERR("Could not write font: %s", strerror(errno));
420 if (f) fclose(f);
421 free(font);
422 }
423 }
424 eina_iterator_free(it);
425 }
426 {
427 char out[4096];
428 FILE *f;
429 sf = eina_list_data_get(srcfiles->list);
430
431
432 if (build_sh)
433 {
434 snprintf(out, sizeof(out), "%s/build.sh", outdir);
435 INF("Output Build Script: %s", out);
436 if (strstr(out, "../"))
437 {
438 ERR("potential security violation. attempt to write in parent dir.");
439 exit (-1);
440 }
441 f = fopen(out, "wb");
442 fprintf(f, "#!/bin/sh\n");
443 fprintf(f, "%s $@ -id . -fd . %s -o %s.edj\n", edje_file->compiler, sf->name, outdir);
444 fclose(f);
445
446 WRN("*** CAUTION ***\n"
447 "Please check the build script for anything malicious "
448 "before running it!\n\n");
449 }
450
451 if (file_out)
452 {
453 snprintf(out, sizeof(out), "%s/%s", outdir, file_out);
454 if (ecore_file_symlink(sf->name, out) != EINA_TRUE)
455 {
456 ERR("symlink %s -> %s failed", sf->name, out);
457 }
458 }
459
460 chmod(out, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP);
461
462 }
463
464 if (edje_file->sound_dir)
465 {
466 Edje_Sound_Sample *sample;
467 void *sound_data;
468 char out[PATH_MAX];
469 char out1[PATH_MAX];
470 char *pp;
471 int sound_data_size;
472 FILE *f;
473 int i;
474
475 for (i = 0; i < (int)edje_file->sound_dir->samples_count; i++)
476 {
477 sample = &edje_file->sound_dir->samples[i];
478 if ((!sample) || (!sample->name)) continue;
479 snprintf(out, sizeof(out), "edje/sounds/%i", sample->id);
480 sound_data = (void *)eet_read_direct(tef, out, &sound_data_size);
481 if (sound_data)
482 {
483 snprintf(out1, sizeof(out1), "%s/%s", outdir, sample->snd_src);
484 pp = strdup(out1);
485 p = strrchr(pp, '/');
486 *p = 0;
487 if (strstr(pp, "../"))
488 {
489 ERR("Potential security violation. attempt to write in parent dir.");
490 exit(-1);
491 }
492 ecore_file_mkpath(pp);
493 free(pp);
494 if (strstr(out, "../"))
495 {
496 ERR("Potential security violation. attempt to write in parent dir.");
497 exit(-1);
498 }
499 f = fopen(out1, "wb");
500 if (fwrite(sound_data, sound_data_size, 1, f) != 1)
501 ERR("Could not write sound: %s", strerror(errno));
502 fclose(f);
503 }
504 }
505
506 }
507 eet_close(tef);
508}
509
510static int
511compiler_cmd_is_sane()
512{
513 const char *c = edje_file->compiler, *ptr;
514
515 if ((!c) || (!*c))
516 {
517 return 0;
518 }
519
520 for (ptr = c; ptr && *ptr; ptr++)
521 {
522 /* only allow [a-z][A-Z][0-9]_- */
523 if ((!isalnum(*ptr)) && (*ptr != '_') && (*ptr != '-'))
524 {
525 return 0;
526 }
527 }
528
529 return 1;
530}
531
532static int
533root_filename_is_sane()
534{
535 SrcFile *sf = eina_list_data_get(srcfiles->list);
536 char *f = sf->name, *ptr;
537
538 if (!f || !*f)
539 {
540 return 0;
541 }
542
543 for (ptr = f; ptr && *ptr; ptr++)
544 {
545 /* only allow [a-z][A-Z][0-9]_-./ */
546 switch (*ptr)
547 {
548 case '_': case '-': case '.': case '/':
549 break;
550 default:
551 if (!isalnum(*ptr))
552 {
553 return 0;
554 }
555 }
556 }
557 return 1;
558}