aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/edje/src/bin/edje_decc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/edje/src/bin/edje_decc.c')
-rw-r--r--libraries/edje/src/bin/edje_decc.c472
1 files changed, 472 insertions, 0 deletions
diff --git a/libraries/edje/src/bin/edje_decc.c b/libraries/edje/src/bin/edje_decc.c
new file mode 100644
index 0000000..1b79e13
--- /dev/null
+++ b/libraries/edje/src/bin/edje_decc.c
@@ -0,0 +1,472 @@
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;
22char *progname = NULL;
23char *file_in = NULL;
24char *file_out = NULL;
25
26Edje_File *edje_file = NULL;
27SrcFile_List *srcfiles = NULL;
28Font_List *fontlist = NULL;
29
30int line = 0;
31int build_sh = 1;
32int new_dir = 1;
33
34int decomp(void);
35void output(void);
36static int compiler_cmd_is_sane();
37static int root_filename_is_sane();
38
39static void
40main_help(void)
41{
42 printf
43 ("Usage:\n"
44 "\t%s input_file.edj [-main-out file.edc] [-no-build-sh] [-current-dir]\n"
45 "\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"
49 "\n"
50 ,progname);
51}
52
53Eet_File *ef;
54Eet_Dictionary *ed;
55
56int
57main(int argc, char **argv)
58{
59 int i;
60
61 setlocale(LC_NUMERIC, "C");
62 if (!eina_init())
63 exit(-1);
64 _edje_cc_log_dom = eina_log_domain_register
65 ("edje_decc", EDJE_CC_DEFAULT_LOG_COLOR);
66 if (_edje_cc_log_dom < 0)
67 {
68 EINA_LOG_ERR("Impossible to create a log domain.");
69 eina_shutdown();
70 exit(-1);
71 }
72 eina_log_level_set(EINA_LOG_LEVEL_INFO);
73 progname = argv[0];
74 for (i = 1; i < argc; i++)
75 {
76 if (!strcmp(argv[i], "-h"))
77 {
78 main_help();
79 exit(0);
80 }
81 if (!file_in)
82 file_in = argv[i];
83 else if ((!strcmp(argv[i], "-main-out")) && (i < (argc - 1)))
84 {
85 i++;
86 file_out = argv[i];
87 }
88 else if (!strcmp(argv[i], "-no-build-sh"))
89 build_sh = 0;
90 else if (!strcmp(argv[i], "-current-dir"))
91 new_dir = 0;
92 }
93 if (!file_in)
94 {
95 ERR("%s: Error: no input file specified.", progname);
96 main_help();
97 exit(-1);
98 }
99
100 if (!edje_init())
101 exit(-1);
102 source_edd();
103
104 if (!decomp()) return -1;
105 output();
106
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");
110 eet_close(ef);
111 edje_shutdown();
112 eina_log_domain_unregister(_edje_cc_log_dom);
113 _edje_cc_log_dom = -1;
114 eina_shutdown();
115 return 0;
116}
117
118int
119decomp(void)
120{
121 ef = eet_open(file_in, EET_FILE_MODE_READ);
122 if (!ef)
123 {
124 ERR("ERROR: cannot open %s", file_in);
125 return 0;
126 }
127
128 srcfiles = source_load(ef);
129 if (!srcfiles || !srcfiles->list)
130 {
131 ERR("ERROR: %s has no decompile information", file_in);
132 eet_close(ef);
133 return 0;
134 }
135 if (!eina_list_data_get(srcfiles->list) || !root_filename_is_sane())
136 {
137 ERR("ERROR: Invalid root filename: '%s'", (char *) eina_list_data_get(srcfiles->list));
138 eet_close(ef);
139 return 0;
140 }
141 edje_file = eet_data_read(ef, _edje_edd_edje_file, "edje/file");
142 if (!edje_file)
143 {
144 ERR("ERROR: %s does not appear to be an edje file", file_in);
145 eet_close(ef);
146 return 0;
147 }
148 /* force compiler to be edje_cc */
149 edje_file->compiler = strdup("edje_cc");
150 if (!edje_file->compiler)
151 {
152 edje_file->compiler = strdup("edje_cc");
153 }
154 else if (!compiler_cmd_is_sane())
155 {
156 ERR("ERROR: invalid compiler executable: '%s'", edje_file->compiler);
157 eet_close(ef);
158 return 0;
159 }
160 fontlist = source_fontmap_load(ef);
161 return 1;
162}
163
164void
165output(void)
166{
167 Eina_List *l;
168 Eet_File *tef;
169 SrcFile *sf;
170 char *outdir, *p;
171
172 if (!new_dir)
173 outdir = strdup(".");
174 else
175 {
176 p = strrchr(file_in, '/');
177 if (p)
178 outdir = strdup(p + 1);
179 else
180 outdir = strdup(file_in);
181 p = strrchr(outdir, '.');
182 if (p) *p = 0;
183 ecore_file_mkpath(outdir);
184 }
185
186
187 tef = eet_open(file_in, EET_FILE_MODE_READ);
188
189 if (edje_file->image_dir)
190 {
191 Edje_Image_Directory_Entry *ei;
192 unsigned int i;
193
194 for (i = 0; i < edje_file->image_dir->entries_count; ++i)
195 {
196 ei = &edje_file->image_dir->entries[i];
197
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) &&
201 (ei->entry))
202 {
203 Ecore_Evas *ee;
204 Evas *evas;
205 Evas_Object *im;
206 char buf[4096];
207 char out[4096];
208 char *pp;
209
210 ecore_init();
211 ecore_evas_init();
212 ee = ecore_evas_buffer_new(1, 1);
213 if (!ee)
214 {
215 ERR("Cannot create buffer engine canvas for image save.");
216 exit(-1);
217 }
218 evas = ecore_evas_get(ee);
219 im = evas_object_image_add(evas);
220 if (!im)
221 {
222 ERR("Cannot create image object for save.");
223 exit(-1);
224 }
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);
229 pp = strdup(out);
230 p = strrchr(pp, '/');
231 *p = 0;
232 if (strstr(pp, "../"))
233 {
234 ERR("Potential security violation. attempt to write in parent dir.");
235 exit(-1);
236 }
237 ecore_file_mkpath(pp);
238 free(pp);
239 if (!evas_object_image_save(im, out, NULL, "quality=100 compress=9"))
240 {
241 ERR("Cannot write file %s. Perhaps missing JPEG or PNG saver modules for Evas.", out);
242 exit(-1);
243 }
244 evas_object_del(im);
245 ecore_evas_free(ee);
246 ecore_evas_shutdown();
247 ecore_shutdown();
248 }
249 }
250 }
251
252 EINA_LIST_FOREACH(srcfiles->list, l, sf)
253 {
254 char out[4096];
255 FILE *f;
256 char *pp;
257
258 snprintf(out, sizeof(out), "%s/%s", outdir, sf->name);
259 INF("Output Source File: %s\n", out);
260 pp = strdup(out);
261 p = strrchr(pp, '/');
262 *p = 0;
263 if (strstr(pp, "../"))
264 {
265 ERR("Potential security violation. attempt to write in parent dir.");
266 exit (-1);
267 }
268 ecore_file_mkpath(pp);
269 free(pp);
270 if (strstr(out, "../"))
271 {
272 ERR("Potential security violation. attempt to write in parent dir.");
273 exit (-1);
274 }
275 f = fopen(out, "wb");
276 if (!f)
277 {
278 ERR("Unable to write file (%s).", out);
279 exit (-1);
280 }
281
282 /* if the file is empty, sf->file will be NULL.
283 * note that that's not an error
284 */
285 if (sf->file) fputs(sf->file, f);
286 fclose(f);
287 }
288 if (edje_file->fonts)
289 {
290 Edje_Font_Directory_Entry *fn;
291 Eina_Iterator *it;
292
293 it = eina_hash_iterator_data_new(edje_file->fonts);
294 EINA_ITERATOR_FOREACH(it, fn)
295 {
296 void *font;
297 int fontsize;
298 char out[4096];
299 /* FIXME!!!! */
300 /* should be fn->entry -v */
301 snprintf(out, sizeof(out), "edje/fonts/%s", fn->file);
302 font = eet_read(tef, out, &fontsize);
303 if (font)
304 {
305 FILE *f;
306 char *pp;
307
308 /* should be fn->file -v */
309 snprintf(out, sizeof(out), "%s/%s", outdir, fn->entry);
310 INF("Output Font: %s", out);
311 pp = strdup(out);
312 p = strrchr(pp, '/');
313 *p = 0;
314 if (strstr(pp, "../"))
315 {
316 ERR("Potential security violation. attempt to write in parent dir.");
317 exit (-1);
318 }
319 ecore_file_mkpath(pp);
320 free(pp);
321 if (strstr(out, "../"))
322 {
323 ERR("Potential security violation. attempt to write in parent dir.");
324 exit (-1);
325 }
326 if (!(f = fopen(out, "wb")))
327 {
328 ERR("Could not open file: %s", out);
329 exit (-1);
330 }
331 if (fwrite(font, fontsize, 1, f) != 1)
332 ERR("Could not write font: %s", strerror(errno));
333 if (f) fclose(f);
334 free(font);
335 }
336 }
337 eina_iterator_free(it);
338 }
339 {
340 char out[4096];
341 FILE *f;
342 sf = eina_list_data_get(srcfiles->list);
343
344
345 if (build_sh)
346 {
347 snprintf(out, sizeof(out), "%s/build.sh", outdir);
348 printf("Output Build Script: %s\n", out);
349 if (strstr(out, "../"))
350 {
351 ERR("potential security violation. attempt to write in parent dir.\n");
352 exit (-1);
353 }
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);
357 fclose(f);
358
359 WRN("\n*** CAUTION ***\n"
360 "Please check the build script for anything malicious "
361 "before running it!\n\n");
362 }
363
364 if (file_out)
365 {
366 snprintf(out, sizeof(out), "%s/%s", outdir, file_out);
367 if (ecore_file_symlink(sf->name, out) != EINA_TRUE)
368 {
369 ERR("symlink %s -> %s failed\n", sf->name, out);
370 }
371 }
372
373 chmod(out, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP);
374
375 }
376
377 if (edje_file->sound_dir)
378 {
379 Edje_Sound_Sample *sample;
380 void *sound_data;
381 char out[PATH_MAX];
382 char out1[PATH_MAX];
383 char *pp;
384 int sound_data_size;
385 FILE *f;
386 int i;
387
388 for (i = 0; i < (int)edje_file->sound_dir->samples_count; i++)
389 {
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);
394 if (sound_data)
395 {
396 snprintf(out1, sizeof(out1), "%s/%s", outdir, sample->name);
397 pp = strdup(out1);
398 p = strrchr(pp, '/');
399 *p = 0;
400 if (strstr(pp, "../"))
401 {
402 ERR("Potential security violation. attempt to write in parent dir.");
403 exit(-1);
404 }
405 ecore_file_mkpath(pp);
406 free(pp);
407 if (strstr(out, "../"))
408 {
409 ERR("Potential security violation. attempt to write in parent dir.");
410 exit(-1);
411 }
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));
415 fclose(f);
416 free(sound_data);
417 }
418 }
419
420 }
421 eet_close(tef);
422}
423
424static int
425compiler_cmd_is_sane()
426{
427 const char *c = edje_file->compiler, *ptr;
428
429 if ((!c) || (!*c))
430 {
431 return 0;
432 }
433
434 for (ptr = c; ptr && *ptr; ptr++)
435 {
436 /* only allow [a-z][A-Z][0-9]_- */
437 if ((!isalnum(*ptr)) && (*ptr != '_') && (*ptr != '-'))
438 {
439 return 0;
440 }
441 }
442
443 return 1;
444}
445
446static int
447root_filename_is_sane()
448{
449 SrcFile *sf = eina_list_data_get(srcfiles->list);
450 char *f = sf->name, *ptr;
451
452 if (!f || !*f)
453 {
454 return 0;
455 }
456
457 for (ptr = f; ptr && *ptr; ptr++)
458 {
459 /* only allow [a-z][A-Z][0-9]_-./ */
460 switch (*ptr)
461 {
462 case '_': case '-': case '.': case '/':
463 break;
464 default:
465 if (!isalnum(*ptr))
466 {
467 return 0;
468 }
469 }
470 }
471 return 1;
472}