diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/evas/src/modules/loaders/generic/evas_image_load_generic.c | 434 |
1 files changed, 0 insertions, 434 deletions
diff --git a/libraries/evas/src/modules/loaders/generic/evas_image_load_generic.c b/libraries/evas/src/modules/loaders/generic/evas_image_load_generic.c deleted file mode 100644 index 2bbfd3e..0000000 --- a/libraries/evas/src/modules/loaders/generic/evas_image_load_generic.c +++ /dev/null | |||
@@ -1,434 +0,0 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif | ||
4 | |||
5 | #ifdef HAVE_EVIL | ||
6 | # include <Evil.h> | ||
7 | #endif | ||
8 | |||
9 | #include "evas_common.h" | ||
10 | #include "evas_private.h" | ||
11 | |||
12 | #include <stdio.h> | ||
13 | #include <sys/types.h> | ||
14 | #include <sys/mman.h> | ||
15 | #include <sys/stat.h> | ||
16 | #include <fcntl.h> | ||
17 | #include <ctype.h> | ||
18 | |||
19 | static Eina_Bool evas_image_load_file_head_generic(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4); | ||
20 | static Eina_Bool evas_image_load_file_data_generic(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4); | ||
21 | |||
22 | Evas_Image_Load_Func evas_image_load_generic_func = | ||
23 | { | ||
24 | EINA_TRUE, | ||
25 | evas_image_load_file_head_generic, | ||
26 | evas_image_load_file_data_generic, | ||
27 | NULL, | ||
28 | EINA_FALSE | ||
29 | }; | ||
30 | |||
31 | static Eina_Bool | ||
32 | illegal_char(const char *str) | ||
33 | { | ||
34 | const char *p; | ||
35 | |||
36 | for (p = str; *p; p++) | ||
37 | { | ||
38 | if (*p < '-') return EINA_TRUE; | ||
39 | if (*p == '/') return EINA_TRUE; | ||
40 | if (*p == ';') return EINA_TRUE; | ||
41 | if (*p == ':') return EINA_TRUE; | ||
42 | if (*p == '<') return EINA_TRUE; | ||
43 | if (*p == '>') return EINA_TRUE; | ||
44 | if (*p == '?') return EINA_TRUE; | ||
45 | if (*p == '[') return EINA_TRUE; | ||
46 | if (*p == '\\') return EINA_TRUE; | ||
47 | if (*p == ']') return EINA_TRUE; | ||
48 | if (*p == '`') return EINA_TRUE; | ||
49 | if (*p == '{') return EINA_TRUE; | ||
50 | if (*p == '|') return EINA_TRUE; | ||
51 | if (*p == '}') return EINA_TRUE; | ||
52 | if (*p == '~') return EINA_TRUE; | ||
53 | if (*p == 0x7f) return EINA_TRUE; | ||
54 | } | ||
55 | return EINA_FALSE; | ||
56 | } | ||
57 | |||
58 | static void | ||
59 | escape_copy(const char *src, char *dst) | ||
60 | { | ||
61 | const char *s; | ||
62 | char *d; | ||
63 | |||
64 | for (s = src, d = dst; *s; s++, d++) | ||
65 | { | ||
66 | // FIXME: escape tab, newline linefeed and friends | ||
67 | if ((*s == ' ') || | ||
68 | (*s == '!') || | ||
69 | (*s == '"') || | ||
70 | (*s == '#') || | ||
71 | (*s == '$') || | ||
72 | (*s == '%') || | ||
73 | (*s == '&') || | ||
74 | (*s == '\'') || | ||
75 | (*s == '(') || | ||
76 | (*s == ')') || | ||
77 | (*s == '*') || | ||
78 | (*s == '[') || | ||
79 | (*s == '\\') || | ||
80 | (*s == ']') || | ||
81 | (*s == '`') || | ||
82 | (*s == '{') || | ||
83 | (*s == '|') || | ||
84 | (*s == '}') || | ||
85 | (*s == '~')) | ||
86 | { | ||
87 | *d = '\\'; | ||
88 | d++; | ||
89 | } | ||
90 | *d = *s; | ||
91 | } | ||
92 | *d = 0; | ||
93 | } | ||
94 | |||
95 | static void | ||
96 | dotcat(char *dest, const char *src) | ||
97 | { | ||
98 | int len = strlen(dest); | ||
99 | const char *s; | ||
100 | char *d; | ||
101 | |||
102 | for (d = dest + len, s = src; *s; d++, s++) *d = tolower(*s); | ||
103 | *d = 0; | ||
104 | } | ||
105 | |||
106 | static Eina_Bool | ||
107 | _load(Image_Entry *ie, const char *file, const char *key, int *error, Eina_Bool get_data) | ||
108 | { | ||
109 | Eina_Bool res = EINA_FALSE; | ||
110 | int w = 0, h = 0, alpha = 0; | ||
111 | const char *dot1 = NULL, *dot2 = NULL, *end, *p; | ||
112 | char *cmd = NULL, decoders[3][128], buf[4096]; | ||
113 | char *loader = "/evas/utils/evas_image_loader"; | ||
114 | char *img_loader = NULL; | ||
115 | const char *libdir; | ||
116 | // eg $libdir/evas/generic_loaders | ||
117 | int cmd_len, len, decoders_num = 0, try_count = 0; | ||
118 | int read_data = 0; | ||
119 | char *tmpfname = NULL, *shmfname = NULL; | ||
120 | DATA32 *body; | ||
121 | FILE *f = NULL; | ||
122 | |||
123 | libdir = _evas_module_libdir_get(); | ||
124 | cmd_len = strlen(libdir); | ||
125 | cmd_len += strlen(loader); | ||
126 | img_loader = alloca(cmd_len + 1); | ||
127 | strcpy(img_loader, libdir); | ||
128 | strcat(img_loader, loader); | ||
129 | |||
130 | // params excluding file, key and loadopts | ||
131 | cmd_len += 1024; | ||
132 | cmd_len += strlen(file) * 2; | ||
133 | if (key) cmd_len += strlen(key) * 2; | ||
134 | cmd = alloca(cmd_len + 1); | ||
135 | |||
136 | len = strlen(file); | ||
137 | if (len < 1) | ||
138 | { | ||
139 | *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; | ||
140 | return EINA_FALSE; | ||
141 | } | ||
142 | end = file + len; | ||
143 | for (p = end - 1; p >= file; p--) | ||
144 | { | ||
145 | if ((!dot1) && (*p == '.')) dot1 = p; | ||
146 | else if ((!dot2) && (*p == '.')) dot2 = p; | ||
147 | else if ((dot1) && (dot2)) break; | ||
148 | } | ||
149 | if (dot2) | ||
150 | { | ||
151 | // double extn not too long | ||
152 | if (((end - dot2) <= 10) && (!illegal_char(dot2))) | ||
153 | { | ||
154 | strcpy(&(decoders[decoders_num][0]), img_loader); | ||
155 | dotcat(&(decoders[decoders_num][0]), dot2); | ||
156 | decoders_num++; | ||
157 | } | ||
158 | // single extn not too long | ||
159 | if (((end - dot1) <= 5) && (!illegal_char(dot1))) | ||
160 | { | ||
161 | strcpy(&(decoders[decoders_num][0]), img_loader); | ||
162 | dotcat(&(decoders[decoders_num][0]), dot1); | ||
163 | decoders_num++; | ||
164 | } | ||
165 | strcpy(decoders[decoders_num], img_loader); | ||
166 | decoders_num++; | ||
167 | } | ||
168 | else if (dot1) | ||
169 | { | ||
170 | // single extn not too long | ||
171 | if (((end - dot1) <= 5) && (!illegal_char(dot1))) | ||
172 | { | ||
173 | strcpy(&(decoders[decoders_num][0]), img_loader); | ||
174 | dotcat(&(decoders[decoders_num][0]), dot1); | ||
175 | decoders_num++; | ||
176 | } | ||
177 | strcpy(decoders[decoders_num], img_loader); | ||
178 | decoders_num++; | ||
179 | } | ||
180 | else | ||
181 | { | ||
182 | strcpy(decoders[decoders_num], img_loader); | ||
183 | decoders_num++; | ||
184 | } | ||
185 | |||
186 | for (try_count = 0; try_count < decoders_num; try_count++) | ||
187 | { | ||
188 | // FIXME: strcats could be more efficient, not that it matters much | ||
189 | // here as we are about to build a cmd to exec via a shell that | ||
190 | // will interpret shell stuff and path hunt that will then exec the | ||
191 | // program itself that will dynamically link that will again | ||
192 | // parse the arguments and finally do something... | ||
193 | if (access(decoders[try_count], X_OK)) continue; | ||
194 | |||
195 | strcpy(cmd, decoders[try_count]); | ||
196 | strcat(cmd, " "); | ||
197 | // filename first arg | ||
198 | len = strlen(cmd); | ||
199 | escape_copy(file, cmd + len); | ||
200 | if (!get_data) | ||
201 | { | ||
202 | strcat(cmd, " -head "); | ||
203 | } | ||
204 | if (key) | ||
205 | { | ||
206 | strcat(cmd, " -key "); | ||
207 | len = strlen(cmd); | ||
208 | escape_copy(key, cmd + len); | ||
209 | } | ||
210 | if (ie->load_opts.scale_down_by > 1) | ||
211 | { | ||
212 | strcat(cmd, " -opt-scale-down-by "); | ||
213 | snprintf(buf, sizeof(buf), "%i", ie->load_opts.scale_down_by); | ||
214 | strcat(cmd, buf); | ||
215 | } | ||
216 | if (ie->load_opts.dpi > 0.0) | ||
217 | { | ||
218 | strcat(cmd, " -opt-dpi "); | ||
219 | snprintf(buf, sizeof(buf), "%i", (int)(ie->load_opts.dpi * 1000.0)); | ||
220 | strcat(cmd, buf); | ||
221 | } | ||
222 | if ((ie->load_opts.w > 0) && | ||
223 | (ie->load_opts.h > 0)) | ||
224 | { | ||
225 | strcat(cmd, " -opt-size "); | ||
226 | snprintf(buf, sizeof(buf), "%i %i", ie->load_opts.w, ie->load_opts.h); | ||
227 | strcat(cmd, buf); | ||
228 | } | ||
229 | f = popen(cmd, "r"); | ||
230 | if (f) break; | ||
231 | } | ||
232 | if (!f) | ||
233 | { | ||
234 | *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; | ||
235 | return EINA_FALSE; | ||
236 | } | ||
237 | while (fgets(buf, sizeof(buf), f)) | ||
238 | { | ||
239 | len = strlen(buf); | ||
240 | if (len > 0) | ||
241 | { | ||
242 | if (buf[len - 1] == '\n') buf[len - 1] = 0; | ||
243 | if (!strncmp(buf, "size ", 5)) | ||
244 | { | ||
245 | int tw = 0, th = 0; | ||
246 | |||
247 | len = sscanf(buf, "%*s %i %i", &tw, &th); | ||
248 | if (len == 2) | ||
249 | { | ||
250 | if ((tw > 0) && (th > 0)) | ||
251 | { | ||
252 | w = tw; | ||
253 | h = th; | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | else if (!strncmp(buf, "alpha ", 6)) | ||
258 | { | ||
259 | int ta; | ||
260 | |||
261 | len = sscanf(buf, "%*s %i", &ta); | ||
262 | if (len == 1) | ||
263 | { | ||
264 | alpha = ta; | ||
265 | } | ||
266 | } | ||
267 | else if (!strncmp(buf, "tmpfile ", 8)) | ||
268 | { | ||
269 | tmpfname = buf + 8; | ||
270 | goto getdata; | ||
271 | } | ||
272 | #ifdef HAVE_SHM_OPEN | ||
273 | else if (!strncmp(buf, "shmfile ", 8)) | ||
274 | { | ||
275 | shmfname = buf + 8; | ||
276 | goto getdata; | ||
277 | } | ||
278 | #endif | ||
279 | else if (!strncmp(buf, "data", 4)) | ||
280 | { | ||
281 | read_data = 1; | ||
282 | goto getdata; | ||
283 | } | ||
284 | else if (!strncmp(buf, "done", 4)) | ||
285 | { | ||
286 | read_data = 2; | ||
287 | goto getdata; | ||
288 | } | ||
289 | } | ||
290 | } | ||
291 | getdata: | ||
292 | if ((!read_data) && (!tmpfname) && (!shmfname)) | ||
293 | { | ||
294 | *error = EVAS_LOAD_ERROR_CORRUPT_FILE; | ||
295 | goto on_error; | ||
296 | } | ||
297 | if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) || | ||
298 | IMG_TOO_BIG(w, h)) | ||
299 | { | ||
300 | *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; | ||
301 | goto on_error; | ||
302 | } | ||
303 | body = evas_cache_image_pixels(ie); | ||
304 | if (body) | ||
305 | { | ||
306 | if ((w != (int)ie->w) || (h != (int)ie->h)) | ||
307 | { | ||
308 | *error = EVAS_LOAD_ERROR_CORRUPT_FILE; | ||
309 | goto on_error; | ||
310 | } | ||
311 | } | ||
312 | if (alpha) ie->flags.alpha = 1; | ||
313 | ie->w = w; | ||
314 | ie->h = h; | ||
315 | |||
316 | if (get_data) | ||
317 | { | ||
318 | if (!body) evas_cache_image_surface_alloc(ie, ie->w, ie->h); | ||
319 | body = evas_cache_image_pixels(ie); | ||
320 | if (!body) | ||
321 | { | ||
322 | *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; | ||
323 | goto on_error; | ||
324 | } | ||
325 | |||
326 | if ((tmpfname) || (shmfname)) | ||
327 | { | ||
328 | int fd = -1; | ||
329 | |||
330 | // open | ||
331 | if (tmpfname) | ||
332 | fd = open(tmpfname, O_RDONLY, S_IRUSR); | ||
333 | #ifdef HAVE_SHM_OPEN | ||
334 | else if (shmfname) | ||
335 | fd = shm_open(shmfname, O_RDONLY, S_IRUSR); | ||
336 | #endif | ||
337 | if (fd >= 0) | ||
338 | { | ||
339 | void *addr; | ||
340 | |||
341 | eina_mmap_safety_enabled_set(EINA_TRUE); | ||
342 | |||
343 | // mmap | ||
344 | addr = mmap(NULL, w * h * sizeof(DATA32), | ||
345 | PROT_READ, MAP_SHARED, fd, 0); | ||
346 | if (addr != MAP_FAILED) | ||
347 | { | ||
348 | memcpy(body, addr, w * h * sizeof(DATA32)); | ||
349 | munmap(addr, w * h * sizeof(DATA32)); | ||
350 | } | ||
351 | // close | ||
352 | if (tmpfname) | ||
353 | { | ||
354 | close(fd); | ||
355 | unlink(tmpfname); | ||
356 | } | ||
357 | #ifdef HAVE_SHM_OPEN | ||
358 | else if (shmfname) | ||
359 | { | ||
360 | close(fd); | ||
361 | shm_unlink(shmfname); | ||
362 | } | ||
363 | #endif | ||
364 | } | ||
365 | else | ||
366 | { | ||
367 | *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; | ||
368 | goto on_error; | ||
369 | } | ||
370 | } | ||
371 | else if (read_data) | ||
372 | { | ||
373 | if (fread(body, w * h * sizeof(DATA32), 1, f) != 1) | ||
374 | { | ||
375 | *error = EVAS_LOAD_ERROR_CORRUPT_FILE; | ||
376 | goto on_error; | ||
377 | } | ||
378 | } | ||
379 | } | ||
380 | |||
381 | res = EINA_TRUE; | ||
382 | *error = EVAS_LOAD_ERROR_NONE; | ||
383 | |||
384 | on_error: | ||
385 | if (f) pclose(f); | ||
386 | return res; | ||
387 | } | ||
388 | |||
389 | static Eina_Bool | ||
390 | evas_image_load_file_head_generic(Image_Entry *ie, const char *file, const char *key, int *error) | ||
391 | { | ||
392 | return _load(ie, file, key, error, EINA_FALSE); | ||
393 | } | ||
394 | |||
395 | static Eina_Bool | ||
396 | evas_image_load_file_data_generic(Image_Entry *ie, const char *file, const char *key, int *error) | ||
397 | { | ||
398 | DATA32 *body; | ||
399 | |||
400 | body = evas_cache_image_pixels(ie); | ||
401 | if (!body) return _load(ie, file, key, error, EINA_TRUE); | ||
402 | *error = EVAS_LOAD_ERROR_NONE; | ||
403 | return EINA_TRUE; | ||
404 | } | ||
405 | |||
406 | static int | ||
407 | module_open(Evas_Module *em) | ||
408 | { | ||
409 | if (!em) return 0; | ||
410 | em->functions = (void *)(&evas_image_load_generic_func); | ||
411 | return 1; | ||
412 | } | ||
413 | |||
414 | static void | ||
415 | module_close(Evas_Module *em __UNUSED__) | ||
416 | { | ||
417 | } | ||
418 | |||
419 | static Evas_Module_Api evas_modapi = | ||
420 | { | ||
421 | EVAS_MODULE_API_VERSION, | ||
422 | "generic", | ||
423 | "none", | ||
424 | { | ||
425 | module_open, | ||
426 | module_close | ||
427 | } | ||
428 | }; | ||
429 | |||
430 | EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, generic); | ||
431 | |||
432 | #ifndef EVAS_STATIC_BUILD_GENERIC | ||
433 | EVAS_EINA_MODULE_DEFINE(image_loader, generic); | ||
434 | #endif | ||