1 /* ugly ugly. avert your eyes. */
11 #include <sys/types.h>
16 #include <Ecore_File.h>
17 #include <Ecore_Evas.h>
19 #include "edje_decc.h"
21 int _edje_cc_log_dom = -1;
22 char *progname = NULL;
24 char *file_out = NULL;
26 Edje_File *edje_file = NULL;
27 SrcFile_List *srcfiles = NULL;
28 Font_List *fontlist = NULL;
36 static int compiler_cmd_is_sane();
37 static int root_filename_is_sane();
44 "\t%s input_file.edj [-main-out file.edc] [-no-build-sh] [-current-dir]\n"
46 " -main-out\tCreate a symbolic link to the main edc \n"
47 " -no-build-sh\tDon't output build.sh \n"
48 " -current-dir\tOutput to current directory \n"
57 main(int argc, char **argv)
61 setlocale(LC_NUMERIC, "C");
64 _edje_cc_log_dom = eina_log_domain_register
65 ("edje_decc", EDJE_CC_DEFAULT_LOG_COLOR);
66 if (_edje_cc_log_dom < 0)
68 EINA_LOG_ERR("Impossible to create a log domain.");
72 eina_log_level_set(EINA_LOG_LEVEL_INFO);
74 for (i = 1; i < argc; i++)
76 if (!strcmp(argv[i], "-h"))
83 else if ((!strcmp(argv[i], "-main-out")) && (i < (argc - 1)))
88 else if (!strcmp(argv[i], "-no-build-sh"))
90 else if (!strcmp(argv[i], "-current-dir"))
95 ERR("%s: Error: no input file specified.", progname);
104 if (!decomp()) return -1;
107 printf("WARNING! If any Image or audio data was encoded in a LOSSY way, then\n"
108 "re-encoding will drop quality even more. You need access to the original\n"
109 "data to ensure no loss of quality.\n");
112 eina_log_domain_unregister(_edje_cc_log_dom);
113 _edje_cc_log_dom = -1;
121 ef = eet_open(file_in, EET_FILE_MODE_READ);
124 ERR("ERROR: cannot open %s", file_in);
128 srcfiles = source_load(ef);
129 if (!srcfiles || !srcfiles->list)
131 ERR("ERROR: %s has no decompile information", file_in);
135 if (!eina_list_data_get(srcfiles->list) || !root_filename_is_sane())
137 ERR("ERROR: Invalid root filename: '%s'", (char *) eina_list_data_get(srcfiles->list));
141 edje_file = eet_data_read(ef, _edje_edd_edje_file, "edje/file");
144 ERR("ERROR: %s does not appear to be an edje file", file_in);
148 /* force compiler to be edje_cc */
149 edje_file->compiler = strdup("edje_cc");
150 if (!edje_file->compiler)
152 edje_file->compiler = strdup("edje_cc");
154 else if (!compiler_cmd_is_sane())
156 ERR("ERROR: invalid compiler executable: '%s'", edje_file->compiler);
160 fontlist = source_fontmap_load(ef);
173 outdir = strdup(".");
176 p = strrchr(file_in, '/');
178 outdir = strdup(p + 1);
180 outdir = strdup(file_in);
181 p = strrchr(outdir, '.');
183 ecore_file_mkpath(outdir);
187 tef = eet_open(file_in, EET_FILE_MODE_READ);
189 if (edje_file->image_dir)
191 Edje_Image_Directory_Entry *ei;
194 for (i = 0; i < edje_file->image_dir->entries_count; ++i)
196 ei = &edje_file->image_dir->entries[i];
198 if ((ei->source_type > EDJE_IMAGE_SOURCE_TYPE_NONE) &&
199 (ei->source_type < EDJE_IMAGE_SOURCE_TYPE_LAST) &&
200 (ei->source_type != EDJE_IMAGE_SOURCE_TYPE_EXTERNAL) &&
212 ee = ecore_evas_buffer_new(1, 1);
215 ERR("Cannot create buffer engine canvas for image save.");
218 evas = ecore_evas_get(ee);
219 im = evas_object_image_add(evas);
222 ERR("Cannot create image object for save.");
225 snprintf(buf, sizeof(buf), "edje/images/%i", ei->id);
226 evas_object_image_file_set(im, file_in, buf);
227 snprintf(out, sizeof(out), "%s/%s", outdir, ei->entry);
228 printf("Output Image: %s\n", out);
230 p = strrchr(pp, '/');
232 if (strstr(pp, "../"))
234 ERR("Potential security violation. attempt to write in parent dir.");
237 ecore_file_mkpath(pp);
239 if (!evas_object_image_save(im, out, NULL, "quality=100 compress=9"))
241 ERR("Cannot write file %s. Perhaps missing JPEG or PNG saver modules for Evas.", out);
246 ecore_evas_shutdown();
252 EINA_LIST_FOREACH(srcfiles->list, l, sf)
258 snprintf(out, sizeof(out), "%s/%s", outdir, sf->name);
259 INF("Output Source File: %s\n", out);
261 p = strrchr(pp, '/');
263 if (strstr(pp, "../"))
265 ERR("Potential security violation. attempt to write in parent dir.");
268 ecore_file_mkpath(pp);
270 if (strstr(out, "../"))
272 ERR("Potential security violation. attempt to write in parent dir.");
275 f = fopen(out, "wb");
278 ERR("Unable to write file (%s).", out);
282 /* if the file is empty, sf->file will be NULL.
283 * note that that's not an error
285 if (sf->file) fputs(sf->file, f);
288 if (edje_file->fonts)
290 Edje_Font_Directory_Entry *fn;
293 it = eina_hash_iterator_data_new(edje_file->fonts);
294 EINA_ITERATOR_FOREACH(it, fn)
300 /* should be fn->entry -v */
301 snprintf(out, sizeof(out), "edje/fonts/%s", fn->file);
302 font = eet_read(tef, out, &fontsize);
308 /* should be fn->file -v */
309 snprintf(out, sizeof(out), "%s/%s", outdir, fn->entry);
310 INF("Output Font: %s", out);
312 p = strrchr(pp, '/');
314 if (strstr(pp, "../"))
316 ERR("Potential security violation. attempt to write in parent dir.");
319 ecore_file_mkpath(pp);
321 if (strstr(out, "../"))
323 ERR("Potential security violation. attempt to write in parent dir.");
326 if (!(f = fopen(out, "wb")))
328 ERR("Could not open file: %s", out);
331 if (fwrite(font, fontsize, 1, f) != 1)
332 ERR("Could not write font: %s", strerror(errno));
337 eina_iterator_free(it);
342 sf = eina_list_data_get(srcfiles->list);
347 snprintf(out, sizeof(out), "%s/build.sh", outdir);
348 printf("Output Build Script: %s\n", out);
349 if (strstr(out, "../"))
351 ERR("potential security violation. attempt to write in parent dir.\n");
354 f = fopen(out, "wb");
355 fprintf(f, "#!/bin/sh\n");
356 fprintf(f, "%s $@ -id . -fd . %s -o %s.edj\n", edje_file->compiler, sf->name, outdir);
359 WRN("\n*** CAUTION ***\n"
360 "Please check the build script for anything malicious "
361 "before running it!\n\n");
366 snprintf(out, sizeof(out), "%s/%s", outdir, file_out);
367 if (ecore_file_symlink(sf->name, out) != EINA_TRUE)
369 ERR("symlink %s -> %s failed\n", sf->name, out);
373 chmod(out, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP);
377 if (edje_file->sound_dir)
379 Edje_Sound_Sample *sample;
388 for (i = 0; i < (int)edje_file->sound_dir->samples_count; i++)
390 sample = &edje_file->sound_dir->samples[i];
391 if ((!sample) || (!sample->name)) continue;
392 snprintf(out, sizeof(out), "edje/sounds/%i", sample->id);
393 sound_data = (void *)eet_read_direct(tef, out, &sound_data_size);
396 snprintf(out1, sizeof(out1), "%s/%s", outdir, sample->name);
398 p = strrchr(pp, '/');
400 if (strstr(pp, "../"))
402 ERR("Potential security violation. attempt to write in parent dir.");
405 ecore_file_mkpath(pp);
407 if (strstr(out, "../"))
409 ERR("Potential security violation. attempt to write in parent dir.");
412 f = fopen(out1, "wb");
413 if (fwrite(sound_data, sound_data_size, 1, f) != 1)
414 ERR("Could not write sound: %s", strerror(errno));
425 compiler_cmd_is_sane()
427 const char *c = edje_file->compiler, *ptr;
434 for (ptr = c; ptr && *ptr; ptr++)
436 /* only allow [a-z][A-Z][0-9]_- */
437 if ((!isalnum(*ptr)) && (*ptr != '_') && (*ptr != '-'))
447 root_filename_is_sane()
449 SrcFile *sf = eina_list_data_get(srcfiles->list);
450 char *f = sf->name, *ptr;
457 for (ptr = f; ptr && *ptr; ptr++)
459 /* only allow [a-z][A-Z][0-9]_-./ */
462 case '_': case '-': case '.': case '/':