summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile_Efreet.am8
-rw-r--r--src/bin/efreet/.gitignore1
-rw-r--r--src/bin/efreet/efreet_mime_cache_create.c453
-rw-r--r--src/bin/efreet/efreetd_cache.c124
-rw-r--r--src/bin/efreet/efreetd_ipc.c6
-rw-r--r--src/bin/efreet/efreetd_ipc.h1
-rw-r--r--src/examples/elementary/codegen_example_generated.c132
-rw-r--r--src/examples/elementary/codegen_example_generated.h65
-rw-r--r--src/lib/efreet/efreet_cache.c6
-rw-r--r--src/lib/efreet/efreet_mime.c618
-rw-r--r--src/lib/efreet/efreet_private.h2
11 files changed, 843 insertions, 573 deletions
diff --git a/src/Makefile_Efreet.am b/src/Makefile_Efreet.am
index 32d433016d..fe969f935c 100644
--- a/src/Makefile_Efreet.am
+++ b/src/Makefile_Efreet.am
@@ -90,7 +90,8 @@ bin_efreet_efreetd_DEPENDENCIES = @USE_EFREET_INTERNAL_LIBS@
90efreetinternal_bindir=$(libdir)/efreet/$(MODULE_ARCH) 90efreetinternal_bindir=$(libdir)/efreet/$(MODULE_ARCH)
91efreetinternal_bin_PROGRAMS = \ 91efreetinternal_bin_PROGRAMS = \
92bin/efreet/efreet_desktop_cache_create \ 92bin/efreet/efreet_desktop_cache_create \
93bin/efreet/efreet_icon_cache_create 93bin/efreet/efreet_icon_cache_create \
94bin/efreet/efreet_mime_cache_create
94 95
95bin_efreet_efreet_desktop_cache_create_CPPFLAGS = -I$(top_builddir)/src/lib/efl $(EFREET_COMMON_CPPFLAGS) 96bin_efreet_efreet_desktop_cache_create_CPPFLAGS = -I$(top_builddir)/src/lib/efl $(EFREET_COMMON_CPPFLAGS)
96bin_efreet_efreet_desktop_cache_create_LDADD = $(USE_EFREET_BIN_LIBS) 97bin_efreet_efreet_desktop_cache_create_LDADD = $(USE_EFREET_BIN_LIBS)
@@ -102,6 +103,11 @@ bin_efreet_efreet_icon_cache_create_LDADD = $(USE_EFREET_BIN_LIBS)
102bin_efreet_efreet_icon_cache_create_DEPENDENCIES = @USE_EFREET_INTERNAL_LIBS@ 103bin_efreet_efreet_icon_cache_create_DEPENDENCIES = @USE_EFREET_INTERNAL_LIBS@
103bin_efreet_efreet_icon_cache_create_SOURCES = bin/efreet/efreet_icon_cache_create.c 104bin_efreet_efreet_icon_cache_create_SOURCES = bin/efreet/efreet_icon_cache_create.c
104 105
106bin_efreet_efreet_mime_cache_create_CPPFLAGS = -I$(top_builddir)/src/lib/efl $(EFREET_COMMON_CPPFLAGS)
107bin_efreet_efreet_mime_cache_create_LDADD = $(USE_EFREET_BIN_LIBS)
108bin_efreet_efreet_mime_cache_create_DEPENDENCIES = @USE_EFREET_INTERNAL_LIBS@
109bin_efreet_efreet_mime_cache_create_SOURCES = bin/efreet/efreet_mime_cache_create.c
110
105### Unit tests 111### Unit tests
106 112
107if EFL_ENABLE_TESTS 113if EFL_ENABLE_TESTS
diff --git a/src/bin/efreet/.gitignore b/src/bin/efreet/.gitignore
index 76fc57659f..f6ff3d04e7 100644
--- a/src/bin/efreet/.gitignore
+++ b/src/bin/efreet/.gitignore
@@ -1,3 +1,4 @@
1/efreet_desktop_cache_create 1/efreet_desktop_cache_create
2/efreet_icon_cache_create 2/efreet_icon_cache_create
3/efreetd 3/efreetd
4/efreet_mime_cache_create
diff --git a/src/bin/efreet/efreet_mime_cache_create.c b/src/bin/efreet/efreet_mime_cache_create.c
new file mode 100644
index 0000000000..8f8b0a1f88
--- /dev/null
+++ b/src/bin/efreet/efreet_mime_cache_create.c
@@ -0,0 +1,453 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4#include <sys/stat.h>
5#include <fcntl.h>
6#include <unistd.h>
7#include <errno.h>
8#ifdef HAVE_SYS_RESOURCE_H
9#include <sys/time.h>
10#include <sys/resource.h>
11#endif
12#ifdef _WIN32
13# include <winsock2.h>
14#endif
15#include <libgen.h>
16#include <ctype.h>
17
18#include <Eina.h>
19#include <Eet.h>
20#include <Ecore.h>
21#include <Ecore_File.h>
22
23#ifndef O_BINARY
24# define O_BINARY 0
25#endif
26
27#define EFREET_MODULE_LOG_DOM _efreet_mime_cache_log_dom
28static int _efreet_mime_cache_log_dom = -1;
29static Eina_List *extra_dirs = NULL;
30
31static Eina_Hash *mimes = NULL;
32static Eina_Hash *extn_mimes = NULL;
33static Eina_Hash *glob_mimes = NULL;
34static Eina_List *mimes_sorted = NULL;
35static Eina_List *extn_mimes_sorted = NULL;
36static Eina_List *glob_mimes_sorted = NULL;
37
38#include "Efreet.h"
39#include "efreet_private.h"
40#include "efreet_cache_private.h"
41
42static int
43cache_lock_file(void)
44{
45 char file[PATH_MAX];
46 struct flock fl;
47 int lockfd;
48
49 snprintf(file, sizeof(file), "%s/efreet/mime_data.lock", efreet_cache_home_get());
50 lockfd = open(file, O_CREAT | O_BINARY | O_RDWR, S_IRUSR | S_IWUSR);
51 if (lockfd < 0) return -1;
52 efreet_fsetowner(lockfd);
53
54 memset(&fl, 0, sizeof(struct flock));
55 fl.l_type = F_WRLCK;
56 fl.l_whence = SEEK_SET;
57 if (fcntl(lockfd, F_SETLK, &fl) < 0)
58 {
59 INF("LOCKED! You may want to delete %s if this persists", file);
60 close(lockfd);
61 return -1;
62 }
63
64 return lockfd;
65}
66
67static int
68hash_list_sort_insert_cmp(const char *key1, const char *key2)
69{
70 return strcmp(key1, key2);
71}
72
73static Eina_Bool
74hash_list_sort_each(const Eina_Hash *hash EINA_UNUSED, const void *key, void *value EINA_UNUSED, void *data)
75{
76 Eina_List **list = data;
77 *list = eina_list_sorted_insert(*list,
78 EINA_COMPARE_CB(hash_list_sort_insert_cmp),
79 key);
80 return EINA_TRUE;
81}
82
83static void
84hash_list_sort(Eina_Hash *hash, Eina_List **list)
85{
86 eina_hash_foreach(hash, hash_list_sort_each, list);
87}
88
89static void
90etc_mime_types_load(const char *file)
91{
92 int len;
93 char buf[4096], buf2[4096], buf3[4096], *p, *p2;
94 const char *mime;
95 FILE *f = fopen(file, "r");
96
97 if (!f) return;
98 while (fgets(buf, sizeof(buf), f))
99 {
100 // remove newline at end of line string if there
101 buf[sizeof(buf) - 1] = 0;
102 len = strlen(buf);
103 if ((len > 0) && (buf[len - 1] == '\n')) buf[len - 1] = 0;
104 // buf: "# comment"
105 // or
106 // buf: "mime/type"
107 // buf: "mime/type "
108 // buf: "mime/type ext1"
109 // buf: "mime/type ext1 ext2"
110 // buf: "mime/type ext1 ext2 ext3"
111 // ...
112 p = buf;
113 // find first token in line
114 while ((*p) && isspace(*p)) p++;
115 // if comment - skip line
116 if (*p == '#') continue;
117 p2 = p;
118 while ((*p2) && !isspace(*p2)) p2++;
119 // token is between p and p2 (not including p2)
120 strncpy(buf2, p, p2 - p);
121 buf2[p2 - p] = 0;
122 mime = eina_stringshare_add(buf2);
123 // buf2 is now the mime type token
124 eina_hash_del(mimes, buf2, NULL);
125 eina_hash_add(mimes, buf2, mime);
126 // now lookf for all extension tokens;
127 p = p2;
128 // find next token in line
129 while ((*p) && isspace(*p)) p++;
130 while (*p)
131 {
132 // find end of token
133 p2 = p;
134 while ((*p2) && !isspace(*p2)) p2++;
135 // buf3 is now the extension token
136 strncpy(buf3, p, p2 - p);
137 buf3[p2 - p] = 0;
138 eina_hash_del(extn_mimes, buf3, NULL);
139 eina_hash_add(extn_mimes, buf3, mime);
140 // go to next token if any
141 p = p2;
142 while ((*p) && isspace(*p)) p++;
143 }
144 }
145 fclose(f);
146}
147
148static void
149share_mime_globs_load(const char *file)
150{
151 int len;
152 char buf[4096], buf2[4096], buf3[4096], *p, *p2;
153 const char *mime;
154 FILE *f = fopen(file, "r");
155
156 if (!f) return;
157 while (fgets(buf, sizeof(buf), f))
158 {
159 // remove newline at end of line string if there
160 buf[sizeof(buf) - 1] = 0;
161 len = strlen(buf);
162 if ((len > 0) && (buf[len - 1] == '\n')) buf[len - 1] = 0;
163 // buf: "# comment"
164 // or
165 // buf: "mime/type:glob"
166 // ...
167 p = buf;
168 // find first token in line
169 while ((*p) && isspace(*p)) p++;
170 // if comment - skip line
171 if (*p == '#') continue;
172 p2 = p;
173 while ((*p2) && (*p2 != ':')) p2++;
174 // token is between p and p2 (not including p2)
175 strncpy(buf2, p, p2 - p);
176 buf2[p2 - p] = 0;
177 mime = eina_stringshare_add(buf2);
178 // buf2 is now the mime type token
179 eina_hash_del(mimes, buf2, NULL);
180 eina_hash_add(mimes, buf2, mime);
181 // now lookf for all extension tokens;
182 p = p2;
183 // find next token in line
184 while ((*p) && (*p == ':')) p++;
185 // find end of token
186 p2 = p;
187 while ((*p2) && !isspace(*p2)) p2++;
188 // buf3 is now the extension token
189 strncpy(buf3, p, p2 - p);
190 buf3[p2 - p] = 0;
191 // for a shortcut a glob of "*.xxx" is the same as just an ext of "xxx"
192 // so if this is the case then put into the extn mimes not
193 // the globl mimes for speed of lookup later on
194 if ((buf3[0] == '*') && (buf3[1] == '.') &&
195 (!strchr(buf3 + 2, '*')) && (!strchr(buf3 + 2, '?')) &&
196 (!strchr(buf3 + 2, '[')) && (!strchr(buf3 + 2, ']')) &&
197 (!strchr(buf3 + 2, '\\')))
198 {
199 eina_hash_del(extn_mimes, buf3 + 2, NULL);
200 eina_hash_add(extn_mimes, buf3 + 2, mime);
201 }
202 else
203 {
204 eina_hash_del(glob_mimes, buf3, NULL);
205 eina_hash_add(glob_mimes, buf3, mime);
206 }
207 }
208 fclose(f);
209}
210
211static void *
212find_off(const char *str, Eina_List *strlist, Eina_List *offlist)
213{
214 Eina_List *l, *ll;
215 const char *s;
216
217 ll = offlist;
218 EINA_LIST_FOREACH(strlist, l, s)
219 {
220 if (!strcmp(str, s)) return ll->data;
221 ll = ll->next;
222 }
223 return (void *)-1;
224}
225static void
226store_cache(const char *out)
227{
228 char buf[PATH_MAX];
229 FILE *f;
230 size_t mimes_str_len = 0;
231 size_t extn_mimes_str_len = 0;
232 size_t glob_mimes_str_len = 0;
233 size_t str_start;
234 Eina_List *mimes_str_offsets = NULL;
235 Eina_List *extn_mimes_str_offsets = NULL;
236 Eina_List *glob_mimes_str_offsets = NULL;
237 Eina_List *l, *ll;
238 const char *s;
239 void *ptr;
240 unsigned int val;
241
242 snprintf(buf, sizeof(buf), "%s.tmp", out);
243 f = fopen(buf, "wb");
244 if (!f) return;
245 // write file magic - first 16 bytes
246 fwrite("EfrEeT-MiMeS-001", 16, 1, f);
247 // note: all offsets are in bytes from start of file
248 //
249 // "EfrEeT-MiMeS-001" <- magic 16 byte header
250 // [int] <- size of mimes array in number of entries
251 // [int] <- str byte offset of 1st mime string (sorted)
252 // [int] <- str byte offset of 2nd mime string
253 // ...
254 // [int] <- size of extn_mimes array in number of entries
255 // [int] <- str byte offset of 1st extn string (sorted)
256 // [int] <- str byte offset of 1st mime string
257 // [int] <- str byte offset of 2nd extn string
258 // [int] <- str byte offset of 2nd mine string
259 // ...
260 // [int] <- size of globs array in number of entries
261 // [int] <- str byte offset of 1st glob string (sorted)
262 // [int] <- str byte offset of 1st mime string
263 // [int] <- str byte offset of 2nd glob string
264 // [int] <- str byte offset of 2nd mime string
265 // ...
266 // strine1\0string2\0string3\0string4\0....
267 EINA_LIST_FOREACH(mimes_sorted, l, s)
268 {
269 mimes_str_offsets = eina_list_append(mimes_str_offsets,
270 (void *)mimes_str_len);
271 mimes_str_len += strlen(s) + 1;
272 }
273 EINA_LIST_FOREACH(extn_mimes_sorted, l, s)
274 {
275 extn_mimes_str_offsets = eina_list_append(extn_mimes_str_offsets,
276 (void *)extn_mimes_str_len);
277 extn_mimes_str_len += strlen(s) + 1;
278 }
279 EINA_LIST_FOREACH(glob_mimes_sorted, l, s)
280 {
281 glob_mimes_str_offsets = eina_list_append(glob_mimes_str_offsets,
282 (void *)glob_mimes_str_len);
283 glob_mimes_str_len += strlen(s) + 1;
284 }
285
286 str_start = 16 + // magic header
287 sizeof(int) +
288 (eina_list_count(mimes_sorted) * sizeof(int)) +
289 sizeof(int) +
290 (eina_list_count(extn_mimes_sorted) * sizeof(int) * 2) +
291 sizeof(int) +
292 (eina_list_count(glob_mimes_sorted) * sizeof(int) * 2);
293
294 val = eina_list_count(mimes_sorted);
295 fwrite(&val, sizeof(val), 1, f);
296 EINA_LIST_FOREACH(mimes_str_offsets, l, ptr)
297 {
298 val = (int)((long)ptr) + str_start;
299 fwrite(&val, sizeof(val), 1, f);
300 }
301
302 val = eina_list_count(extn_mimes_sorted);
303 fwrite(&val, sizeof(val), 1, f);
304 ll = extn_mimes_sorted;
305 EINA_LIST_FOREACH(extn_mimes_str_offsets, l, ptr)
306 {
307 val = (int)((long)ptr) + str_start + mimes_str_len;
308 fwrite(&val, sizeof(val), 1, f);
309 s = eina_hash_find(extn_mimes, ll->data);
310 ptr = find_off(s, mimes_sorted, mimes_str_offsets);
311 val = (int)((long)ptr) + str_start;
312 fwrite(&val, sizeof(val), 1, f);
313 ll = ll->next;
314 }
315
316 val = eina_list_count(glob_mimes_sorted);
317 fwrite(&val, sizeof(val), 1, f);
318 ll = glob_mimes_sorted;
319 EINA_LIST_FOREACH(glob_mimes_str_offsets, l, ptr)
320 {
321 val = (int)((long)ptr) + str_start + mimes_str_len + extn_mimes_str_len;
322 fwrite(&val, sizeof(val), 1, f);
323 s = eina_hash_find(glob_mimes, ll->data);
324 ptr = find_off(s, mimes_sorted, mimes_str_offsets);
325 val = (int)((long)ptr) + str_start;
326 fwrite(&val, sizeof(val), 1, f);
327 ll = ll->next;
328 }
329 EINA_LIST_FOREACH(mimes_sorted, l, s)
330 {
331 fwrite(s, strlen(s) + 1, 1, f);
332 }
333 EINA_LIST_FOREACH(extn_mimes_sorted, l, s)
334 {
335 fwrite(s, strlen(s) + 1, 1, f);
336 }
337 EINA_LIST_FOREACH(glob_mimes_sorted, l, s)
338 {
339 fwrite(s, strlen(s) + 1, 1, f);
340 }
341 fclose(f);
342 rename(buf, out);
343}
344
345int
346main(int argc, char **argv)
347{
348 char buf[PATH_MAX];
349 const char *s;
350 int i;
351 int ret = -1, lockfd = -1;
352 Eina_List *datadirs, *l;
353
354 if (!eina_init()) goto eina_error;
355 if (!eet_init()) goto eet_error;
356 if (!ecore_init()) goto ecore_error;
357 if (!ecore_file_init()) goto ecore_file_error;
358 if (!efreet_init()) goto efreet_error;
359
360 _efreet_mime_cache_log_dom =
361 eina_log_domain_register("efreet_mime_cache", EFREET_DEFAULT_LOG_COLOR);
362 if (_efreet_mime_cache_log_dom < 0)
363 {
364 EINA_LOG_ERR("Efreet: Could not create a log domain for efreet_mime_cache.");
365 return -1;
366 }
367
368 for (i = 1; i < argc; i++)
369 {
370 if (!strcmp(argv[i], "-v"))
371 eina_log_domain_level_set("efreet_mime_cache", EINA_LOG_LEVEL_DBG);
372 else if ((!strcmp(argv[i], "-h")) ||
373 (!strcmp(argv[i], "-help")) ||
374 (!strcmp(argv[i], "--h")) ||
375 (!strcmp(argv[i], "--help")))
376 {
377 printf("Options:\n");
378 printf(" -v Verbose mode\n");
379 printf(" -d dir1 dir2 Extra dirs\n");
380 exit(0);
381 }
382 else if (!strcmp(argv[i], "-d"))
383 {
384 while ((i < (argc - 1)) && (argv[(i + 1)][0] != '-'))
385 extra_dirs = eina_list_append(extra_dirs, argv[++i]);
386 }
387 }
388 extra_dirs = eina_list_sort(extra_dirs, -1, EINA_COMPARE_CB(strcmp));
389
390 /* create homedir */
391 snprintf(buf, sizeof(buf), "%s/efreet", efreet_cache_home_get());
392 if (!ecore_file_exists(buf))
393 {
394 if (!ecore_file_mkpath(buf)) goto error;
395 efreet_setowner(buf);
396 }
397
398 /* lock process, so that we only run one copy of this program */
399 lockfd = cache_lock_file();
400 if (lockfd == -1) goto error;
401
402 mimes = eina_hash_string_superfast_new(NULL);
403 extn_mimes = eina_hash_string_superfast_new(NULL);
404 glob_mimes = eina_hash_string_superfast_new(NULL);
405
406 etc_mime_types_load("/etc/mime.types");
407 share_mime_globs_load("/usr/share/mime/globs");
408 datadirs = efreet_data_dirs_get();
409 EINA_LIST_FOREACH(datadirs, l, s)
410 {
411 snprintf(buf, sizeof(buf), "%s/mime/globs", s);
412 share_mime_globs_load(buf);
413 }
414 EINA_LIST_FOREACH(extra_dirs, l, s)
415 {
416 snprintf(buf, sizeof(buf), "%s/mime/globs", s);
417 share_mime_globs_load(buf);
418 }
419 snprintf(buf, sizeof(buf), "%s/mime/globs", efreet_data_home_get());
420 share_mime_globs_load(buf);
421 // XXX: load user files and other dirs etc.
422 // XXX: load globs
423
424 hash_list_sort(mimes, &mimes_sorted);
425 hash_list_sort(extn_mimes, &extn_mimes_sorted);
426 hash_list_sort(glob_mimes, &glob_mimes_sorted);
427
428#ifdef WORDS_BIGENDIAN
429 snprintf(buf, sizeof(buf), "%s/efreet/mime_cache_%s.be.dat",
430 efreet_cache_home_get(), efreet_hostname_get());
431#else
432 snprintf(buf, sizeof(buf), "%s/efreet/mime_cache_%s.le.dat",
433 efreet_cache_home_get(), efreet_hostname_get());
434#endif
435 store_cache(buf);
436
437 ret = 0;
438 close(lockfd);
439error:
440 efreet_shutdown();
441efreet_error:
442 ecore_file_shutdown();
443ecore_file_error:
444 ecore_shutdown();
445ecore_error:
446 eet_shutdown();
447eet_error:
448 eina_list_free(extra_dirs);
449 eina_log_domain_unregister(_efreet_mime_cache_log_dom);
450 eina_shutdown();
451eina_error:
452 return ret;
453}
diff --git a/src/bin/efreet/efreetd_cache.c b/src/bin/efreet/efreetd_cache.c
index fefc852dd0..b1ef5e8b81 100644
--- a/src/bin/efreet/efreetd_cache.c
+++ b/src/bin/efreet/efreetd_cache.c
@@ -71,6 +71,13 @@ static Eet_Data_Descriptor *subdir_dir_edd = NULL;
71static Subdir_Cache *subdir_cache = NULL; 71static Subdir_Cache *subdir_cache = NULL;
72static Eina_Bool subdir_need_save = EINA_FALSE; 72static Eina_Bool subdir_need_save = EINA_FALSE;
73 73
74static Eina_Hash *mime_monitors = NULL;
75static Ecore_Timer *mime_update_timer = NULL;
76static Ecore_Exe *mime_cache_exe = NULL;
77
78static void mime_cache_init(void);
79static void mime_cache_shutdown(void);
80
74static void 81static void
75subdir_cache_dir_free(Subdir_Cache_Dir *cd) 82subdir_cache_dir_free(Subdir_Cache_Dir *cd)
76{ 83{
@@ -756,6 +763,10 @@ cache_exe_data_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
756 if ((ev->lines) && (*ev->lines->line == 'c')) update = EINA_TRUE; 763 if ((ev->lines) && (*ev->lines->line == 'c')) update = EINA_TRUE;
757 send_signal_icon_cache_update(update); 764 send_signal_icon_cache_update(update);
758 } 765 }
766 else if (ev->exe == mime_cache_exe)
767 {
768 // XXX: ZZZ: handle stdout here from cache updater... if needed
769 }
759 return ECORE_CALLBACK_RENEW; 770 return ECORE_CALLBACK_RENEW;
760} 771}
761 772
@@ -774,6 +785,11 @@ cache_exe_del_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
774 icon_cache_exe = NULL; 785 icon_cache_exe = NULL;
775 if (icon_queue) cache_icon_update(EINA_FALSE); 786 if (icon_queue) cache_icon_update(EINA_FALSE);
776 } 787 }
788 else if (ev->exe == mime_cache_exe)
789 {
790 mime_cache_exe = NULL;
791 send_signal_mime_cache_build();
792 }
777 return ECORE_CALLBACK_RENEW; 793 return ECORE_CALLBACK_RENEW;
778} 794}
779 795
@@ -838,6 +854,111 @@ cache_desktop_exists(void)
838 return desktop_exists; 854 return desktop_exists;
839} 855}
840 856
857static void
858mime_update_launch(void)
859{
860 char file[PATH_MAX];
861
862 snprintf(file, sizeof(file),
863 "%s/efreet/" MODULE_ARCH "/efreet_mime_cache_create",
864 eina_prefix_lib_get(pfx));
865 mime_cache_exe = ecore_exe_pipe_run(file,
866 ECORE_EXE_PIPE_READ |
867 ECORE_EXE_PIPE_READ_LINE_BUFFERED,
868 NULL);
869}
870
871static Eina_Bool
872mime_update_cache_cb(void *data EINA_UNUSED)
873{
874 mime_update_timer = NULL;
875 if (mime_cache_exe)
876 {
877 ecore_exe_kill(mime_cache_exe);
878 ecore_exe_free(mime_cache_exe);
879 }
880 mime_update_launch();
881 return EINA_FALSE;
882}
883
884static void
885mime_changes_cb(void *data EINA_UNUSED, Ecore_File_Monitor *em EINA_UNUSED,
886 Ecore_File_Event event, const char *path EINA_UNUSED)
887{
888 switch (event)
889 {
890 case ECORE_FILE_EVENT_NONE:
891 /* noop */
892 break;
893
894 case ECORE_FILE_EVENT_CREATED_FILE:
895 case ECORE_FILE_EVENT_DELETED_FILE:
896 case ECORE_FILE_EVENT_MODIFIED:
897 case ECORE_FILE_EVENT_CLOSED:
898 case ECORE_FILE_EVENT_DELETED_DIRECTORY:
899 case ECORE_FILE_EVENT_CREATED_DIRECTORY:
900 case ECORE_FILE_EVENT_DELETED_SELF:
901 mime_cache_shutdown();
902 mime_cache_init();
903 if (mime_update_timer) ecore_timer_del(mime_update_timer);
904 mime_update_timer = ecore_timer_add(0.2, mime_update_cache_cb, NULL);
905 break;
906 }
907}
908
909static void
910mime_cache_init(void)
911{
912 Ecore_File_Monitor *mon;
913 Eina_List *datadirs, *l;
914 const char *s;
915 char buf[PATH_MAX];
916
917 mime_monitors = eina_hash_string_superfast_new(NULL);
918
919 mon = ecore_file_monitor_add("/etc/mime.types", mime_changes_cb, NULL);
920 if (mon) eina_hash_add(mime_monitors, "/etc/mime.types", mon);
921 mon = ecore_file_monitor_add("/usr/share/mime/globs", mime_changes_cb, NULL);
922 if (mon) eina_hash_add(mime_monitors, "/usr/share/mime/globs", mon);
923
924 datadirs = efreet_data_dirs_get();
925 EINA_LIST_FOREACH(datadirs, l, s)
926 {
927 snprintf(buf, sizeof(buf), "%s/mime/globs", s);
928 if (!eina_hash_find(mime_monitors, buf))
929 {
930 mon = ecore_file_monitor_add(buf, mime_changes_cb, NULL);
931 if (mon) eina_hash_add(mime_monitors, buf, mon);
932 }
933 }
934}
935
936static Eina_Bool
937mime_cache_monitor_del(const Eina_Hash *hash EINA_UNUSED,
938 const void *key EINA_UNUSED, void *value,
939 void *data EINA_UNUSED)
940{
941 Ecore_File_Monitor *mon = value;
942 ecore_file_monitor_del(mon);
943 return EINA_TRUE;
944}
945
946static void
947mime_cache_shutdown(void)
948{
949 if (mime_update_timer)
950 {
951 ecore_timer_del(mime_update_timer);
952 mime_update_timer = NULL;
953 }
954 if (mime_monitors)
955 {
956 eina_hash_foreach(mime_monitors, mime_cache_monitor_del, NULL);
957 eina_hash_free(mime_monitors);
958 mime_monitors = NULL;
959 }
960}
961
841Eina_Bool 962Eina_Bool
842cache_init(void) 963cache_init(void)
843{ 964{
@@ -875,6 +996,8 @@ cache_init(void)
875 efreet_cache_update = 0; 996 efreet_cache_update = 0;
876 if (!efreet_init()) goto error; 997 if (!efreet_init()) goto error;
877 subdir_cache_init(); 998 subdir_cache_init();
999 mime_cache_init();
1000 mime_update_launch();
878 read_lists(); 1001 read_lists();
879 /* TODO: Should check if system dirs has changed and handles extra_dirs */ 1002 /* TODO: Should check if system dirs has changed and handles extra_dirs */
880 desktop_system_dirs = efreet_default_dirs_get(efreet_data_home_get(), 1003 desktop_system_dirs = efreet_default_dirs_get(efreet_data_home_get(),
@@ -906,6 +1029,7 @@ cache_shutdown(void)
906 eina_prefix_free(pfx); 1029 eina_prefix_free(pfx);
907 pfx = NULL; 1030 pfx = NULL;
908 1031
1032 mime_cache_shutdown();
909 subdir_cache_shutdown(); 1033 subdir_cache_shutdown();
910 efreet_shutdown(); 1034 efreet_shutdown();
911 1035
diff --git a/src/bin/efreet/efreetd_ipc.c b/src/bin/efreet/efreetd_ipc.c
index 2c483c5a79..533a33bc75 100644
--- a/src/bin/efreet/efreetd_ipc.c
+++ b/src/bin/efreet/efreetd_ipc.c
@@ -190,6 +190,12 @@ send_signal_desktop_cache_build(void)
190 _broadcast(ipc, 1 /* desktop cache build */, 1, NULL, 0); 190 _broadcast(ipc, 1 /* desktop cache build */, 1, NULL, 0);
191} 191}
192 192
193void
194send_signal_mime_cache_build(void)
195{
196 _broadcast(ipc, 4 /* mime cache build */, 1, NULL, 0);
197}
198
193Eina_Bool 199Eina_Bool
194ipc_init(void) 200ipc_init(void)
195{ 201{
diff --git a/src/bin/efreet/efreetd_ipc.h b/src/bin/efreet/efreetd_ipc.h
index 6508f8f7b4..e2b3b5abf1 100644
--- a/src/bin/efreet/efreetd_ipc.h
+++ b/src/bin/efreet/efreetd_ipc.h
@@ -4,6 +4,7 @@
4void send_signal_icon_cache_update(Eina_Bool update); 4void send_signal_icon_cache_update(Eina_Bool update);
5void send_signal_desktop_cache_update(Eina_Bool update); 5void send_signal_desktop_cache_update(Eina_Bool update);
6void send_signal_desktop_cache_build(void); 6void send_signal_desktop_cache_build(void);
7void send_signal_mime_cache_build(void);
7 8
8Eina_Bool ipc_init(void); 9Eina_Bool ipc_init(void);
9Eina_Bool ipc_shutdown(void); 10Eina_Bool ipc_shutdown(void);
diff --git a/src/examples/elementary/codegen_example_generated.c b/src/examples/elementary/codegen_example_generated.c
deleted file mode 100644
index 8ce305ebda..0000000000
--- a/src/examples/elementary/codegen_example_generated.c
+++ /dev/null
@@ -1,132 +0,0 @@
1#include "codegen_example_generated.h"
2
3Evas_Object *
4codegen_example_layout_add(Evas_Object *o, Elm_Theme *th, const char *edje_file)
5{
6 Evas_Object *l;
7
8 if (edje_file)
9 elm_theme_extension_add(th, edje_file);
10 else
11 elm_theme_extension_add(th, "./codegen_example.edj");
12
13 l = elm_layout_add(o);
14 if (!l) return NULL;
15
16 if (!elm_layout_theme_set(l, "example", "mylayout", "default"))
17 {
18 evas_object_del(l);
19 return NULL;
20 }
21
22 return l;
23}
24
25void
26codegen_example_title_set(Evas_Object *o, const char *value)
27{
28 elm_layout_text_set(o, "example/title", value);
29}
30
31const char *
32codegen_example_title_get(const Evas_Object *o)
33{
34 return elm_layout_text_get(o, "example/title");
35}
36
37void
38codegen_example_custom_set(Evas_Object *o, Evas_Object *value)
39{
40 elm_layout_content_set(o, "example/custom", value);
41}
42
43Evas_Object *
44codegen_example_custom_unset(Evas_Object *o)
45{
46 return elm_layout_content_unset(o, "example/custom");
47}
48
49Evas_Object *
50codegen_example_custom_get(const Evas_Object *o)
51{
52 return elm_layout_content_get(o, "example/custom");
53}
54
55Eina_Bool
56codegen_example_box_append(Evas_Object *o, Evas_Object *child)
57{
58 return elm_layout_box_append(o, "example/box", child);
59}
60
61Eina_Bool
62codegen_example_box_prepend(Evas_Object *o, Evas_Object *child)
63{
64 return elm_layout_box_prepend(o, "example/box", child);
65}
66
67Eina_Bool
68codegen_example_box_insert_before(Evas_Object *o, Evas_Object *child, const Evas_Object *reference)
69{
70 return elm_layout_box_insert_before(o, "example/box", child, reference);
71}
72
73Eina_Bool
74codegen_example_box_insert_at(Evas_Object *o, Evas_Object *child, unsigned int pos)
75{
76 return elm_layout_box_insert_at(o, "example/box", child, pos);
77}
78
79Evas_Object *
80codegen_example_box_remove(Evas_Object *o, Evas_Object *child)
81{
82 return elm_layout_box_remove(o, "example/box", child);
83}
84
85Eina_Bool
86codegen_example_box_remove_all(Evas_Object *o, Eina_Bool clear)
87{
88 return elm_layout_box_remove_all(o, "example/box", clear);
89}
90
91Eina_Bool
92codegen_example_table_pack(Evas_Object *o, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
93{
94 return elm_layout_table_pack(o, "example/table", child, col, row, colspan, rowspan);
95}
96
97Evas_Object *
98codegen_example_table_unpack(Evas_Object *o, Evas_Object *child)
99{
100 return elm_layout_table_unpack(o, "example/table", child);
101}
102
103Eina_Bool
104codegen_example_table_clear(Evas_Object *o, Eina_Bool clear)
105{
106 return elm_layout_table_clear(o, "example/table", clear);
107}
108
109void
110codegen_example_swallow_grow_emit(Evas_Object *o)
111{
112 elm_layout_signal_emit(o, "button,enlarge", "");
113}
114
115void
116codegen_example_swallow_shrink_emit(Evas_Object *o)
117{
118 elm_layout_signal_emit(o, "button,reduce", "");
119}
120
121void
122codegen_example_size_changed_callback_add(Evas_Object *o, Edje_Signal_Cb func, void *data)
123{
124 elm_layout_signal_callback_add(o, "size,changed", "", func, data);
125}
126
127void
128codegen_example_size_changed_callback_del(Evas_Object *o, Edje_Signal_Cb func)
129{
130 elm_layout_signal_callback_del(o, "size,changed", "", func);
131}
132
diff --git a/src/examples/elementary/codegen_example_generated.h b/src/examples/elementary/codegen_example_generated.h
deleted file mode 100644
index b8fbc4e958..0000000000
--- a/src/examples/elementary/codegen_example_generated.h
+++ /dev/null
@@ -1,65 +0,0 @@
1#ifndef _CODEGEN_EXAMPLE_GENERATED_H
2#define _CODEGEN_EXAMPLE_GENERATED_H
3
4#include <Edje.h>
5#include <Elementary.h>
6#include <Evas.h>
7
8#include <stdlib.h>
9
10/**
11 * @brief Creates the layout object and set the theme
12 * @param o The parent
13 * @param th The theme to add to, or if NULL, the default theme
14 * @param edje_file The path to edj, if NULL it's used the path given
15 * to elementary_codegen
16 */
17Evas_Object *codegen_example_layout_add(Evas_Object *o, Elm_Theme *th, const char *edje_file);
18
19/**
20 * @brief The example title
21 */
22void codegen_example_title_set(Evas_Object *o, const char *value);
23const char *codegen_example_title_get(const Evas_Object *o);
24
25/**
26 * @brief The swallow part
27 */
28void codegen_example_custom_set(Evas_Object *o, Evas_Object *value);
29Evas_Object *codegen_example_custom_unset(Evas_Object *o);
30Evas_Object *codegen_example_custom_get(const Evas_Object *o);
31
32/**
33 * @brief The box part
34 */
35Eina_Bool codegen_example_box_append(Evas_Object *o, Evas_Object *child);
36Eina_Bool codegen_example_box_prepend(Evas_Object *o, Evas_Object *child);
37Eina_Bool codegen_example_box_insert_before(Evas_Object *o, Evas_Object *child, const Evas_Object *reference);
38Eina_Bool codegen_example_box_insert_at(Evas_Object *o, Evas_Object *child, unsigned int pos);
39Evas_Object *codegen_example_box_remove(Evas_Object *o, Evas_Object *child);
40Eina_Bool codegen_example_box_remove_all(Evas_Object *o, Eina_Bool clear);
41
42/**
43 * @brief The table part
44 */
45Eina_Bool codegen_example_table_pack(Evas_Object *o, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan);
46Evas_Object *codegen_example_table_unpack(Evas_Object *o, Evas_Object *child);
47Eina_Bool codegen_example_table_clear(Evas_Object *o, Eina_Bool clear);
48
49/**
50 * @brief Executed when the button enlarges
51 */
52void codegen_example_swallow_grow_emit(Evas_Object *o);
53
54/**
55 * @brief Executed when the button reduces
56 */
57void codegen_example_swallow_shrink_emit(Evas_Object *o);
58
59/**
60 * @brief Emit the signal size,changed
61 */
62void codegen_example_size_changed_callback_add(Evas_Object *o, Edje_Signal_Cb func, void *data);
63void codegen_example_size_changed_callback_del(Evas_Object *o, Edje_Signal_Cb func);
64
65#endif /* _CODEGEN_EXAMPLE_GENERATED_H */
diff --git a/src/lib/efreet/efreet_cache.c b/src/lib/efreet/efreet_cache.c
index f8d5e5ce43..de4ca7440e 100644
--- a/src/lib/efreet/efreet_cache.c
+++ b/src/lib/efreet/efreet_cache.c
@@ -203,6 +203,8 @@ _icon_desktop_cache_update_event_add(int event_type)
203 ecore_event_add(event_type, ev, icon_cache_update_free, l); 203 ecore_event_add(event_type, ev, icon_cache_update_free, l);
204} 204}
205 205
206EAPI void (*_efreet_mime_update_func) (void) = NULL;
207
206static Eina_Bool 208static Eina_Bool
207_cb_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) 209_cb_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
208{ 210{
@@ -223,6 +225,10 @@ _cb_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
223 { 225 {
224 _icon_desktop_cache_update_event_add(EFREET_EVENT_DESKTOP_CACHE_UPDATE); 226 _icon_desktop_cache_update_event_add(EFREET_EVENT_DESKTOP_CACHE_UPDATE);
225 } 227 }
228 else if (e->major == 4) // mime cache update
229 {
230 if (_efreet_mime_update_func) _efreet_mime_update_func();
231 }
226 return ECORE_CALLBACK_DONE; 232 return ECORE_CALLBACK_DONE;
227} 233}
228 234
diff --git a/src/lib/efreet/efreet_mime.c b/src/lib/efreet/efreet_mime.c
index 87ca8ef414..4426b6a130 100644
--- a/src/lib/efreet/efreet_mime.c
+++ b/src/lib/efreet/efreet_mime.c
@@ -32,11 +32,8 @@ static int _efreet_mime_log_dom = -1;
32#include "Efreet_Mime.h" 32#include "Efreet_Mime.h"
33#include "efreet_private.h" 33#include "efreet_private.h"
34 34
35static Eina_List *globs = NULL; /* contains Efreet_Mime_Glob structs */ 35static Eina_List *magics = NULL; // contains Efreet_Mime_Magic structs
36static Eina_List *magics = NULL; /* contains Efreet_Mime_Magic structs */ 36static Eina_Hash *mime_icons = NULL; // contains cache with mime->icons
37static Eina_Hash *wild = NULL; /* contains *.ext and mime.types globs*/
38static Eina_Hash *monitors = NULL; /* contains file monitors */
39static Eina_Hash *mime_icons = NULL; /* contains cache with mime->icons */
40static Eina_Inlist *mime_icons_lru = NULL; 37static Eina_Inlist *mime_icons_lru = NULL;
41static unsigned int _efreet_mime_init_count = 0; 38static unsigned int _efreet_mime_init_count = 0;
42 39
@@ -89,13 +86,6 @@ static enum
89 */ 86 */
90//#define EFREET_MIME_ICONS_DEBUG 87//#define EFREET_MIME_ICONS_DEBUG
91 88
92typedef struct Efreet_Mime_Glob Efreet_Mime_Glob;
93struct Efreet_Mime_Glob
94{
95 const char *glob;
96 const char *mime;
97};
98
99typedef struct Efreet_Mime_Magic Efreet_Mime_Magic; 89typedef struct Efreet_Mime_Magic Efreet_Mime_Magic;
100struct Efreet_Mime_Magic 90struct Efreet_Mime_Magic
101{ 91{
@@ -134,9 +124,6 @@ struct Efreet_Mime_Icon_Entry
134 unsigned int size; 124 unsigned int size;
135}; 125};
136 126
137static int efreet_mime_glob_remove(const char *glob);
138static void efreet_mime_mime_types_load(const char *file);
139static void efreet_mime_shared_mimeinfo_globs_load(const char *file);
140static void efreet_mime_shared_mimeinfo_magic_load(const char *file); 127static void efreet_mime_shared_mimeinfo_magic_load(const char *file);
141static void efreet_mime_shared_mimeinfo_magic_parse(char *data, int size); 128static void efreet_mime_shared_mimeinfo_magic_parse(char *data, int size);
142static const char *efreet_mime_magic_check_priority(const char *file, 129static const char *efreet_mime_magic_check_priority(const char *file,
@@ -145,19 +132,12 @@ static const char *efreet_mime_magic_check_priority(const char *file,
145static int efreet_mime_init_files(void); 132static int efreet_mime_init_files(void);
146static const char *efreet_mime_special_check(const char *file); 133static const char *efreet_mime_special_check(const char *file);
147static const char *efreet_mime_fallback_check(const char *file); 134static const char *efreet_mime_fallback_check(const char *file);
148static void efreet_mime_glob_free(void *data);
149static void efreet_mime_magic_free(void *data); 135static void efreet_mime_magic_free(void *data);
150static void efreet_mime_magic_entry_free(void *data); 136static void efreet_mime_magic_entry_free(void *data);
151static int efreet_mime_glob_match(const char *str, const char *glob); 137static int efreet_mime_glob_match(const char *str, const char *glob);
152static int efreet_mime_glob_case_match(char *str, const char *glob); 138static int efreet_mime_glob_case_match(char *str, const char *glob);
153static int efreet_mime_endian_check(void); 139static int efreet_mime_endian_check(void);
154 140
155static void efreet_mime_monitor_add(const char *file);
156static void efreet_mime_cb_update_file(void *data,
157 Ecore_File_Monitor *monitor,
158 Ecore_File_Event event,
159 const char *path);
160
161static void efreet_mime_icons_flush(double now); 141static void efreet_mime_icons_flush(double now);
162static void efreet_mime_icon_entry_head_free(Efreet_Mime_Icon_Entry_Head *entry); 142static void efreet_mime_icon_entry_head_free(Efreet_Mime_Icon_Entry_Head *entry);
163static void efreet_mime_icon_entry_add(const char *mime, 143static void efreet_mime_icon_entry_add(const char *mime,
@@ -169,6 +149,218 @@ static const char *efreet_mime_icon_entry_find(const char *mime,
169 unsigned int size); 149 unsigned int size);
170static void efreet_mime_icons_debug(void); 150static void efreet_mime_icons_debug(void);
171 151
152
153
154
155
156
157
158
159
160
161
162
163static Eina_File *mimedb = NULL;
164static unsigned char *mimedb_ptr = NULL;
165static size_t mimedb_size = 0;
166
167static void
168_efreet_mimedb_shutdown(void)
169{
170 if (mimedb)
171 {
172 if (mimedb_ptr) eina_file_map_free(mimedb, mimedb_ptr);
173 eina_file_close(mimedb);
174 mimedb = NULL;
175 mimedb_ptr = NULL;
176 mimedb_size = 0;
177 }
178}
179
180static void
181_efreet_mimedb_update(void)
182{
183 char buf[PATH_MAX];
184
185 if (mimedb)
186 {
187 if (mimedb_ptr) eina_file_map_free(mimedb, mimedb_ptr);
188 eina_file_close(mimedb);
189 mimedb = NULL;
190 mimedb_ptr = NULL;
191 mimedb_size = 0;
192 }
193#ifdef WORDS_BIGENDIAN
194 snprintf(buf, sizeof(buf), "%s/efreet/mime_cache_%s.be.dat",
195 efreet_cache_home_get(), efreet_hostname_get());
196#else
197 snprintf(buf, sizeof(buf), "%s/efreet/mime_cache_%s.le.dat",
198 efreet_cache_home_get(), efreet_hostname_get());
199#endif
200 mimedb = eina_file_open(buf, EINA_FALSE);
201 if (mimedb)
202 {
203 mimedb_ptr = eina_file_map_all(mimedb, EINA_FILE_POPULATE);
204 if (mimedb_ptr)
205 {
206 mimedb_size = eina_file_size_get(mimedb);
207 if ((mimedb_size > (16 + 4 + 4 + 4) &&
208 (!strncmp((char *)mimedb_ptr, "EfrEeT-MiMeS-001", 16))))
209 {
210 // load ok - magic fine. more sanity checks?
211 }
212 else
213 {
214 eina_file_map_free(mimedb, mimedb_ptr);
215 mimedb_ptr = NULL;
216 eina_file_close(mimedb);
217 mimedb = NULL;
218 mimedb_size = 0;
219 }
220 }
221 else
222 {
223 eina_file_close(mimedb);
224 mimedb = NULL;
225 }
226 }
227}
228
229static const char *
230_efreet_mimedb_str_get(unsigned int offset)
231{
232 if (offset < (16 + 4 + 4 + 4)) return NULL;
233 if (offset >= mimedb_size) return NULL;
234 return (const char *)(mimedb_ptr + offset);
235}
236
237static unsigned int
238_efreet_mimedb_uint_get(unsigned int index)
239// index is the unit NUMBER AFTER the header
240{
241 unsigned int *ptr;
242 ptr = ((unsigned int *)(mimedb_ptr + 16)) + index;
243 if ((size_t)(((unsigned char *)ptr) - mimedb_ptr) >= (mimedb_size - 4))
244 return 0;
245 return *ptr;
246}
247
248static unsigned int
249_efreet_mimedb_mime_count(void)
250{
251 return _efreet_mimedb_uint_get(0);
252}
253
254/**** currently unused - here for symmetry and future use
255static const char *
256_efreet_mimedb_mime_get(unsigned int num)
257{
258 unsigned int offset = _efreet_mimedb_uint_get
259 (1 + num);
260 return _efreet_mimedb_str_get(offset);
261}
262*/
263
264static unsigned int
265_efreet_mimedb_extn_count(void)
266{
267 return _efreet_mimedb_uint_get(1 + _efreet_mimedb_mime_count());
268}
269
270static const char *
271_efreet_mimedb_extn_get(unsigned int num)
272{
273 unsigned int offset = _efreet_mimedb_uint_get
274 (1 + _efreet_mimedb_mime_count() + 1 + (num * 2));
275 return _efreet_mimedb_str_get(offset);
276}
277
278static const char *
279_efreet_mimedb_extn_mime_get(unsigned int num)
280{
281 unsigned int offset = _efreet_mimedb_uint_get
282 (1 + _efreet_mimedb_mime_count() + 1 + (num * 2) + 1);
283 return _efreet_mimedb_str_get(offset);
284}
285
286static const char *
287_efreet_mimedb_extn_find(const char *extn)
288{
289 unsigned int i, begin, end;
290 const char *s;
291
292 // binary search keys to get value
293 begin = 0;
294 end = _efreet_mimedb_extn_count();
295 i = (begin + end) / 2;
296 for (;;)
297 {
298 s = _efreet_mimedb_extn_get(i);
299 if (s)
300 {
301 int v = strcmp(extn, s);
302 if (v < 0)
303 {
304 end = i;
305 i = (begin + end) / 2;
306 if ((end - begin) == 0) break;
307 }
308 else if (v > 0)
309 {
310 if ((end - begin) > 1)
311 {
312 begin = i;
313 i = (begin + end) / 2;
314 if (i == end) break;
315 }
316 else
317 {
318 if ((end - begin) == 0) break;
319 begin = end;
320 i = end;
321 }
322 }
323 else if (v == 0)
324 return _efreet_mimedb_extn_mime_get(i);
325 }
326 else
327 {
328 break;
329 }
330 }
331 return NULL;
332}
333
334static unsigned int
335_efreet_mimedb_glob_count(void)
336{
337 return _efreet_mimedb_uint_get
338 (1 + _efreet_mimedb_mime_count() +
339 1 + (_efreet_mimedb_extn_count() * 2));
340}
341
342static const char *
343_efreet_mimedb_glob_get(unsigned int num)
344{
345 unsigned int offset = _efreet_mimedb_uint_get
346 (1 + _efreet_mimedb_mime_count() +
347 1 + (_efreet_mimedb_extn_count() * 2) +
348 1 + (num * 2));
349 return _efreet_mimedb_str_get(offset);
350}
351
352static const char *
353_efreet_mimedb_glob_mime_get(unsigned int num)
354{
355 unsigned int offset = _efreet_mimedb_uint_get
356 (1 + _efreet_mimedb_mime_count() +
357 1 + (_efreet_mimedb_extn_count() * 2) +
358 1 + (num * 2) + 1);
359 return _efreet_mimedb_str_get(offset);
360}
361
362/** --------------------------------- **/
363
172EAPI int 364EAPI int
173efreet_mime_init(void) 365efreet_mime_init(void)
174{ 366{
@@ -194,14 +386,15 @@ efreet_mime_init(void)
194 } 386 }
195 387
196 efreet_mime_endianess = efreet_mime_endian_check(); 388 efreet_mime_endianess = efreet_mime_endian_check();
197
198 monitors = eina_hash_string_superfast_new(EINA_FREE_CB(ecore_file_monitor_del));
199
200 efreet_mime_type_cache_clear(); 389 efreet_mime_type_cache_clear();
201 390
391 _efreet_mimedb_update();
392
202 if (!efreet_mime_init_files()) 393 if (!efreet_mime_init_files())
203 goto unregister_log_domain; 394 goto unregister_log_domain;
204 395
396 _efreet_mime_update_func = _efreet_mimedb_update;
397
205 return _efreet_mime_init_count; 398 return _efreet_mime_init_count;
206 399
207unregister_log_domain: 400unregister_log_domain:
@@ -228,6 +421,9 @@ efreet_mime_shutdown(void)
228 if (--_efreet_mime_init_count != 0) 421 if (--_efreet_mime_init_count != 0)
229 return _efreet_mime_init_count; 422 return _efreet_mime_init_count;
230 423
424 _efreet_mimedb_shutdown();
425 _efreet_mime_update_func = NULL;
426
231 efreet_mime_icons_debug(); 427 efreet_mime_icons_debug();
232 428
233 IF_RELEASE(_mime_inode_symlink); 429 IF_RELEASE(_mime_inode_symlink);
@@ -241,10 +437,7 @@ efreet_mime_shutdown(void)
241 IF_RELEASE(_mime_application_octet_stream); 437 IF_RELEASE(_mime_application_octet_stream);
242 IF_RELEASE(_mime_text_plain); 438 IF_RELEASE(_mime_text_plain);
243 439
244 IF_FREE_LIST(globs, efreet_mime_glob_free);
245 IF_FREE_LIST(magics, efreet_mime_magic_free); 440 IF_FREE_LIST(magics, efreet_mime_magic_free);
246 IF_FREE_HASH(monitors);
247 IF_FREE_HASH(wild);
248 IF_FREE_HASH(mime_icons); 441 IF_FREE_HASH(mime_icons);
249 eina_log_domain_unregister(_efreet_mime_log_dom); 442 eina_log_domain_unregister(_efreet_mime_log_dom);
250 _efreet_mime_log_dom = -1; 443 _efreet_mime_log_dom = -1;
@@ -387,11 +580,10 @@ efreet_mime_magic_type_get(const char *file)
387EAPI const char * 580EAPI const char *
388efreet_mime_globs_type_get(const char *file) 581efreet_mime_globs_type_get(const char *file)
389{ 582{
390 Eina_List *l;
391 Efreet_Mime_Glob *g;
392 char *sl, *p; 583 char *sl, *p;
393 const char *s; 584 const char *s, *mime;
394 char *ext, *mime; 585 char *ext;
586 unsigned int i, n;
395 587
396 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); 588 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
397 589
@@ -406,25 +598,27 @@ efreet_mime_globs_type_get(const char *file)
406 while (p) 598 while (p)
407 { 599 {
408 p++; 600 p++;
409 if (p && (mime = eina_hash_find(wild, p))) return mime; 601 if (p && (mime = _efreet_mimedb_extn_find(p))) return mime;
410 p = strchr(p, '.'); 602 p = strchr(p, '.');
411 } 603 }
412 } 604 }
413 605
414 /* Fallback to the other globs if not found */ 606 // Fallback to the other globs if not found
415 EINA_LIST_FOREACH(globs, l, g) 607 n = _efreet_mimedb_glob_count();
608 for (i = 0; i < n; i++)
416 { 609 {
417 if (efreet_mime_glob_match(file, g->glob)) 610 s = _efreet_mimedb_glob_get(i);
418 return g->mime; 611 if (efreet_mime_glob_match(file, s))
612 return _efreet_mimedb_glob_mime_get(i);
419 } 613 }
420
421 ext = alloca(strlen(file) + 1); 614 ext = alloca(strlen(file) + 1);
422 for (s = file, p = ext; *s; s++, p++) *p = tolower(*s); 615 for (s = file, p = ext; *s; s++, p++) *p = tolower(*s);
423 *p = 0; 616 *p = 0;
424 EINA_LIST_FOREACH(globs, l, g) 617 for (i = 0; i < n; i++)
425 { 618 {
426 if (efreet_mime_glob_case_match(ext, g->glob)) 619 s = _efreet_mimedb_glob_get(i);
427 return g->mime; 620 if (efreet_mime_glob_case_match(ext, s))
621 return _efreet_mimedb_glob_mime_get(i);
428 } 622 }
429 return NULL; 623 return NULL;
430} 624}
@@ -457,72 +651,6 @@ efreet_mime_endian_check(void)
457 651
458/** 652/**
459 * @internal 653 * @internal
460 * @param file File to monitor
461 * @return Returns no value.
462 * @brief Creates a new file monitor if we aren't already monitoring the
463 * given file
464 */
465static void
466efreet_mime_monitor_add(const char *file)
467{
468 Ecore_File_Monitor *fm = NULL;
469
470 /* if this is already in our hash then we're already monitoring so no
471 * reason to re-monitor */
472 if (eina_hash_find(monitors, file))
473 return;
474
475 if ((fm = ecore_file_monitor_add(file, efreet_mime_cb_update_file, NULL)))
476 {
477 eina_hash_del(monitors, file, NULL);
478 eina_hash_add(monitors, file, fm);
479 }
480}
481
482/**
483 * @internal
484 * @param datadirs List of XDG data dirs
485 * @param datahome Path to XDG data home directory
486 * @return Returns no value
487 * @brief Read all glob files in XDG data/home dirs.
488 * Also reads the /etc/mime.types file.
489 */
490static void
491efreet_mime_load_globs(Eina_List *datadirs, const char *datahome)
492{
493 Eina_List *l;
494 char buf[4096];
495 const char *datadir = NULL;
496
497 IF_FREE_HASH(wild);
498 wild = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
499 while (globs)
500 {
501 efreet_mime_glob_free(eina_list_data_get(globs));
502 globs = eina_list_remove_list(globs, globs);
503 }
504
505 /*
506 * This is here for legacy reasons. It is mentioned briefly
507 * in the spec and seems to still be quite valid. It is
508 * loaded first so the globs files will override anything
509 * in here.
510 */
511 efreet_mime_mime_types_load("/etc/mime.types");
512
513 datadir = datahome;
514 snprintf(buf, sizeof(buf), "%s/mime/globs", datadir);
515 efreet_mime_shared_mimeinfo_globs_load(buf);
516
517 EINA_LIST_FOREACH(datadirs, l, datadir)
518 {
519 snprintf(buf, sizeof(buf), "%s/mime/globs", datadir);
520 efreet_mime_shared_mimeinfo_globs_load(buf);
521 }
522}
523
524/**
525 * @internal
526 * @param datadirs List of XDG data dirs 654 * @param datadirs List of XDG data dirs
527 * @param datahome Path to XDG data home directory 655 * @param datahome Path to XDG data home directory
528 * @return Returns no value 656 * @return Returns no value
@@ -554,39 +682,6 @@ efreet_mime_load_magics(Eina_List *datadirs, const char *datahome)
554 682
555/** 683/**
556 * @internal 684 * @internal
557 * @param data Data pointer passed to monitor_add
558 * @param monitor Ecore_File_Monitor associated with this event
559 * @param event The type of event
560 * @param path Path to the file that was updated
561 * @return Returns no value
562 * @brief Callback for all file monitors. Just reloads the appropriate
563 * list depending on which file changed. If it was a magic file
564 * only the magic list is updated. If it was a glob file or /etc/mime.types,
565 * the globs are updated.
566 */
567static void
568efreet_mime_cb_update_file(void *data EINA_UNUSED,
569 Ecore_File_Monitor *monitor EINA_UNUSED,
570 Ecore_File_Event event EINA_UNUSED,
571 const char *path)
572{
573 Eina_List *datadirs = NULL;
574 const char *datahome = NULL;
575
576 if (!(datahome = efreet_data_home_get()))
577 return;
578
579 if (!(datadirs = efreet_data_dirs_get()))
580 return;
581
582 if (strstr(path, "magic"))
583 efreet_mime_load_magics(datadirs, datahome);
584 else
585 efreet_mime_load_globs(datadirs, datahome);
586}
587
588/**
589 * @internal
590 * @param datadirs List of XDG data dirs 685 * @param datadirs List of XDG data dirs
591 * @param datahome Path to XDG data home directory 686 * @param datahome Path to XDG data home directory
592 * @return Returns 1 on success, 0 on failure 687 * @return Returns 1 on success, 0 on failure
@@ -595,10 +690,8 @@ efreet_mime_cb_update_file(void *data EINA_UNUSED,
595static int 690static int
596efreet_mime_init_files(void) 691efreet_mime_init_files(void)
597{ 692{
598 Eina_List *l;
599 Eina_List *datadirs = NULL; 693 Eina_List *datadirs = NULL;
600 char buf[PATH_MAX]; 694 const char *datahome;
601 const char *datahome, *datadir = NULL;
602 695
603 if (!(datahome = efreet_data_home_get())) 696 if (!(datahome = efreet_data_home_get()))
604 return 0; 697 return 0;
@@ -606,32 +699,15 @@ efreet_mime_init_files(void)
606 if (!(datadirs = efreet_data_dirs_get())) 699 if (!(datadirs = efreet_data_dirs_get()))
607 return 0; 700 return 0;
608 701
609 /*
610 * Add our file monitors
611 * We watch the directories so we can watch for new files
612 */
613 datadir = datahome;
614 snprintf(buf, sizeof(buf), "%s/mime", datadir);
615 efreet_mime_monitor_add(buf);
616
617 EINA_LIST_FOREACH(datadirs, l, datadir)
618 {
619 snprintf(buf, sizeof(buf), "%s/mime", datadir);
620 efreet_mime_monitor_add(buf);
621 }
622 efreet_mime_monitor_add("/etc/mime.types");
623
624 /* Load our mime information */
625 efreet_mime_load_globs(datadirs, datahome);
626 efreet_mime_load_magics(datadirs, datahome); 702 efreet_mime_load_magics(datadirs, datahome);
627 703
628 _mime_inode_symlink = eina_stringshare_add("inode/symlink"); 704 _mime_inode_symlink = eina_stringshare_add("inode/symlink");
629 _mime_inode_fifo = eina_stringshare_add("inode/fifo"); 705 _mime_inode_fifo = eina_stringshare_add("inode/fifo");
630 _mime_inode_chardevice = eina_stringshare_add("inode/chardevice"); 706 _mime_inode_chardevice = eina_stringshare_add("inode/chardevice");
631 _mime_inode_blockdevice = eina_stringshare_add("inode/blockdevice"); 707 _mime_inode_blockdevice = eina_stringshare_add("inode/blockdevice");
632 _mime_inode_socket = eina_stringshare_add("inode/socket"); 708 _mime_inode_socket = eina_stringshare_add("inode/socket");
633 _mime_inode_mountpoint = eina_stringshare_add("inode/mountpoint"); 709 _mime_inode_mountpoint = eina_stringshare_add("inode/mountpoint");
634 _mime_inode_directory = eina_stringshare_add("inode/directory"); 710 _mime_inode_directory = eina_stringshare_add("inode/directory");
635 _mime_application_x_executable = eina_stringshare_add("application/x-executable"); 711 _mime_application_x_executable = eina_stringshare_add("application/x-executable");
636 _mime_application_octet_stream = eina_stringshare_add("application/octet-stream"); 712 _mime_application_octet_stream = eina_stringshare_add("application/octet-stream");
637 _mime_text_plain = eina_stringshare_add("text/plain"); 713 _mime_text_plain = eina_stringshare_add("text/plain");
@@ -781,198 +857,6 @@ efreet_mime_fallback_check(const char *file)
781 857
782/** 858/**
783 * @internal 859 * @internal
784 * @param glob Glob to search for
785 * @return Returns 1 on success, 0 on failure
786 * @brief Removes a glob from the list
787 */
788static int
789efreet_mime_glob_remove(const char *glob)
790{
791 Efreet_Mime_Glob *mime = NULL;
792
793 if ((mime = eina_list_search_unsorted(globs, EINA_COMPARE_CB(strcmp), glob)))
794 {
795 globs = eina_list_remove(globs, mime);
796 IF_RELEASE(mime->glob);
797 IF_RELEASE(mime->mime);
798 FREE(mime);
799 return 1;
800 }
801
802 return 0;
803}
804
805static inline const char *
806efreet_eat_space(const char *head, const Eina_File_Line *ln, Eina_Bool not)
807{
808 if (not)
809 {
810 while (!isspace(*head) && (head < ln->end))
811 head++;
812 }
813 else
814 {
815 while (isspace(*head) && (head < ln->end))
816 head++;
817 }
818
819 return head;
820}
821
822/**
823 * @internal
824 * @param file mime.types file to load
825 * @return Returns no value
826 * @brief Loads values from a mime.types style file
827 * into the globs list.
828 * @note Format:
829 * application/msaccess mdb
830 * application/msword doc dot
831 */
832static void
833efreet_mime_mime_types_load(const char *file)
834{
835 const Eina_File_Line *ln;
836 Eina_Iterator *it;
837 Eina_File *f;
838 const char *head_line;
839 const char *word_start;
840 const char *mimetype;
841
842 EINA_SAFETY_ON_NULL_RETURN(file);
843 f = eina_file_open(file, 0);
844 if (!f) return;
845
846 it = eina_file_map_lines(f);
847 if (it)
848 {
849 Eina_Strbuf *ext;
850
851 ext = eina_strbuf_new();
852
853 EINA_ITERATOR_FOREACH(it, ln)
854 {
855 head_line = efreet_eat_space(ln->start, ln, EINA_FALSE);
856 if (head_line == ln->end) continue ;
857
858 if (*head_line == '#') continue ;
859
860 word_start = head_line;
861 head_line = efreet_eat_space(head_line, ln, EINA_TRUE);
862
863 if (head_line == ln->end) continue ;
864 mimetype = eina_stringshare_add_length(word_start, head_line - word_start);
865 do
866 {
867 head_line = efreet_eat_space(head_line, ln, EINA_FALSE);
868 if (head_line == ln->end) break ;
869
870 word_start = head_line;
871 head_line = efreet_eat_space(head_line, ln, EINA_TRUE);
872
873 eina_strbuf_append_length(ext, word_start, head_line - word_start);
874
875 eina_hash_del(wild,
876 eina_strbuf_string_get(ext),
877 NULL);
878 eina_hash_add(wild,
879 eina_strbuf_string_get(ext),
880 eina_stringshare_ref(mimetype));
881
882 eina_strbuf_reset(ext);
883 }
884 while (head_line < ln->end);
885
886 eina_stringshare_del(mimetype);
887 }
888
889 eina_strbuf_free(ext);
890 eina_iterator_free(it);
891 }
892 eina_file_close(f);
893}
894
895/**
896 * @internal
897 * @param file globs file to load
898 * @return Returns no value
899 * @brief Loads values from a mime.types style file
900 * into the globs list.
901 * @note Format:
902 * text/vnd.wap.wml:*.wml
903 * application/x-7z-compressed:*.7z
904 * application/vnd.corel-draw:*.cdr
905 * text/spreadsheet:*.sylk
906 */
907static void
908efreet_mime_shared_mimeinfo_globs_load(const char *file)
909{
910 FILE *f = NULL;
911 char buf[4096], mimetype[4096], ext[4096], *p, *pp;
912 Efreet_Mime_Glob *mime = NULL;
913
914 f = fopen(file, "rb");
915 if (!f) return;
916
917 while (fgets(buf, sizeof(buf), f))
918 {
919 p = buf;
920 while (isspace(*p) && (*p != 0) && (*p != '\n')) p++;
921
922 if (*p == '#') continue;
923 if ((*p == '\n') || (*p == 0)) continue;
924
925 pp = p;
926 while ((*p != ':') && (*p != 0) && (*p != '\n')) p++;
927
928 if ((*p == '\n') || (*p == 0)) continue;
929 strncpy(mimetype, pp, (p - pp));
930 mimetype[p - pp] = 0;
931 p++;
932 pp = ext;
933
934 while ((*p != 0) && (*p != '\n'))
935 {
936 *pp = *p;
937 pp++;
938 p++;
939 }
940
941 *pp = 0;
942
943 if (ext[0] == '*' && ext[1] == '.')
944 {
945 eina_hash_del(wild, &(ext[2]), NULL);
946 eina_hash_add(wild, &(ext[2]),
947 (void*)eina_stringshare_add(mimetype));
948 }
949 else
950 {
951 mime = NEW(Efreet_Mime_Glob, 1);
952 if (mime)
953 {
954 mime->mime = eina_stringshare_add(mimetype);
955 mime->glob = eina_stringshare_add(ext);
956 if ((!mime->mime) || (!mime->glob))
957 {
958 IF_RELEASE(mime->mime);
959 IF_RELEASE(mime->glob);
960 FREE(mime);
961 }
962 else
963 {
964 efreet_mime_glob_remove(ext);
965 globs = eina_list_append(globs, mime);
966 }
967 }
968 }
969 }
970
971 fclose(f);
972}
973
974/**
975 * @internal
976 * @param in Number to count the digits 860 * @param in Number to count the digits
977 * @return Returns number of digits 861 * @return Returns number of digits
978 * @brief Calculates and returns the number of digits 862 * @brief Calculates and returns the number of digits
@@ -1341,22 +1225,6 @@ efreet_mime_magic_check_priority(const char *file,
1341 * @internal 1225 * @internal
1342 * @param data Data pointer that is being destroyed 1226 * @param data Data pointer that is being destroyed
1343 * @return Returns no value 1227 * @return Returns no value
1344 * @brief Callback for globs destroy
1345 */
1346static void
1347efreet_mime_glob_free(void *data)
1348{
1349 Efreet_Mime_Glob *m = data;
1350
1351 IF_RELEASE(m->mime);
1352 IF_RELEASE(m->glob);
1353 IF_FREE(m);
1354}
1355
1356/**
1357 * @internal
1358 * @param data Data pointer that is being destroyed
1359 * @return Returns no value
1360 * @brief Callback for magics destroy 1228 * @brief Callback for magics destroy
1361 */ 1229 */
1362static void 1230static void
diff --git a/src/lib/efreet/efreet_private.h b/src/lib/efreet/efreet_private.h
index 139754d81a..47d6deae12 100644
--- a/src/lib/efreet/efreet_private.h
+++ b/src/lib/efreet/efreet_private.h
@@ -251,6 +251,8 @@ EAPI void efreet_fsetowner(int fd);
251 251
252EAPI extern int efreet_cache_update; 252EAPI extern int efreet_cache_update;
253 253
254EAPI extern void (*_efreet_mime_update_func) (void);
255
254#undef EAPI 256#undef EAPI
255#define EAPI 257#define EAPI
256 258