1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
3 /* gnome-vfs-mime-info.c - GNOME mime-information implementation.
5 Copyright (C) 1998 Miguel de Icaza
6 Copyright (C) 2000, 2001 Eazel, Inc.
9 The Gnome Library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
14 The Gnome Library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
19 You should have received a copy of the GNU Library General Public
20 License along with the Gnome Library; see the file COPYING.LIB. If not,
21 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.
25 Miguel De Icaza <miguel@helixcode.com>
26 Mathieu Lacage <mathieu@eazel.com>
30 #include "gnome-vfs-mime-info.h"
32 #include "gnome-vfs-mime-monitor.h"
33 #include "gnome-vfs-mime-private.h"
34 #include "gnome-vfs-mime.h"
35 #include "gnome-vfs-private-utils.h"
41 #include <sys/types.h>
45 #ifdef NEED_GNOMESUPPORT_H
46 #include "gnomesupport.h"
49 #define FAST_FILE_EOF -1
50 #define FAST_FILE_BUFFER_SIZE (1024 * 16)
60 fast_file_close (FastFile *ffh)
67 fast_file_open (FastFile *ffh, const char *filename)
69 memset (ffh, 0, sizeof (FastFile));
71 ffh->fh = fopen (filename, "r");
72 if (ffh->fh == NULL) {
76 ffh->buffer = g_malloc (FAST_FILE_BUFFER_SIZE);
77 ffh->ptr = ffh->buffer;
79 ffh->length = fread (ffh->buffer, 1, FAST_FILE_BUFFER_SIZE, ffh->fh);
81 if (ffh->length < 0) {
82 fast_file_close (ffh);
90 fast_file_getc (FastFile *ffh)
92 if (ffh->ptr < ffh->buffer + ffh->length)
95 ffh->length = fread (ffh->buffer, 1, FAST_FILE_BUFFER_SIZE, ffh->fh);
100 ffh->ptr = ffh->buffer;
101 return *(ffh->ptr++);
111 /* Describes the directories we scan for information */
115 unsigned int valid : 1;
116 unsigned int system_dir : 1;
117 unsigned int force_reload : 1;
121 #define DELETED_KEY "deleted"
122 #define DELETED_VALUE "moilegrandvizir"
124 /* These ones are used to automatically reload mime info on demand */
125 static mime_dir_source_t gnome_mime_dir, user_mime_dir;
126 static time_t last_checked;
128 /* To initialize the module automatically */
129 static gboolean gnome_vfs_mime_inited = FALSE;
131 /* you will write back or reload the file if and only if this var' value is 0 */
132 static int gnome_vfs_is_frozen = 0;
134 static GList *current_lang = NULL;
135 /* we want to replace the previous key if the current key has a higher
137 static int previous_key_lang_level = -1;
140 * A hash table containing all of the Mime records for specific
141 * mime types (full description, like image/png)
142 * It also contains a the generic types like image/
143 * extracted from .keys files
145 static GHashTable *specific_types;
146 /* user specific data */
147 static GHashTable *specific_types_user;
151 * A hash table containing all of the Mime records for all registered
153 * extracted from .mime files
155 static GHashTable *registered_types;
156 /* user specific data */
157 static GHashTable *registered_types_user;
162 static GnomeVFSResult write_back_mime_user_file (void);
163 static GnomeVFSResult write_back_keys_user_file (void);
164 static const char * gnome_vfs_mime_get_registered_mime_type_key (const char *mime_type,
168 _gnome_vfs_mime_info_mark_gnome_mime_dir_dirty (void)
170 gnome_mime_dir.force_reload = TRUE;
174 _gnome_vfs_mime_info_mark_user_mime_dir_dirty (void)
176 user_mime_dir.force_reload = TRUE;
180 does_string_contain_caps (const char *string)
185 while (*temp_c != '\0') {
186 if (g_ascii_isupper (*temp_c)) {
195 static GnomeMimeContext *
196 context_new (GHashTable *hash_table, GString *str)
198 GnomeMimeContext *context;
202 mime_type = g_strdup (str->str);
204 last_char = mime_type[strlen (mime_type) - 1];
205 if (last_char == '*') {
206 mime_type[strlen (mime_type) - 1] = '\0';
209 context = g_hash_table_lookup (hash_table, mime_type);
211 if (context != NULL) {
216 /* fprintf (stderr, "New context: '%s'\n", mime_type); */
218 context = g_new (GnomeMimeContext, 1);
219 context->mime_type = mime_type;
220 context->keys = g_hash_table_new_full (
221 g_str_hash, g_str_equal,
222 (GDestroyNotify) g_free,
223 (GDestroyNotify) g_free);
225 g_hash_table_insert (hash_table, context->mime_type, context);
230 context_destroy (GnomeMimeContext *context)
232 g_hash_table_destroy (context->keys);
233 g_free (context->mime_type);
237 /* this gives us a number of the language in the current language list,
238 the higher the number the "better" the translation */
240 language_level (const char *langage)
248 for (i = 1, li = current_lang; li != NULL; i++, li = g_list_next (li)) {
249 if (strcmp ((const char *) li->data, langage) == 0)
258 context_add_key (GnomeMimeContext *context, char *key, char *lang, char *value)
262 lang_level = language_level (lang);
263 /* wrong language completely */
267 /* if a previous key in the hash had a better lang_level don't do anything */
268 if (lang_level > 0 &&
269 previous_key_lang_level > lang_level) {
273 /* fprintf (stderr, "Add key: '%s' '%s' '%s' %d\n", key, lang, value, lang_level);*/
275 g_hash_table_replace (context->keys, g_strdup (key), g_strdup (value));
277 previous_key_lang_level = lang_level;
283 STATE_LOOKING_FOR_KEY,
289 /* #define APPEND_CHAR(gstr,c) g_string_insert_c ((gstr), -1, (c)) */
291 #define APPEND_CHAR(gstr,c) \
293 if (gstr->len + 1 < gstr->allocated_len) { \
294 gstr->str [gstr->len++] = c; \
295 gstr->str [gstr->len] = '\0'; \
297 g_string_insert_c (gstr, -1, c); \
306 #define load_mime_type_info_from(a,b) load_type_info_from ((a), (b), FORMAT_MIME)
307 #define load_mime_list_info_from(a,b) load_type_info_from ((a), (b), FORMAT_KEYS)
310 load_type_info_from (const char *filename,
311 GHashTable *hash_table,
319 GnomeMimeContext *context;
320 int key, lang, last_str_end; /* offsets */
322 if (!fast_file_open (&mime_file, filename)) {
329 line = g_string_sized_new (120);
330 key = lang = last_str_end = 0;
333 while ((c = fast_file_getc (&mime_file)) != EOF) {
339 if (c == '#' && column == 0) {
348 g_string_truncate (line, 0);
349 key = lang = last_str_end = 0;
357 if (state == STATE_ON_MIME_TYPE) {
358 /* setup for a new key */
359 previous_key_lang_level = -1;
360 context = context_new (hash_table, line);
362 } else if (state == STATE_ON_VALUE) {
363 APPEND_CHAR (line, '\0');
364 context_add_key (context,
366 lang ? line->str + lang : NULL,
367 line->str + last_str_end);
370 g_string_truncate (line, 0);
372 state = STATE_LOOKING_FOR_KEY;
378 if (c == ' ' || c == '\t') {
380 } else if (c == ':') {
384 state = STATE_ON_MIME_TYPE;
388 case STATE_ON_MIME_TYPE:
391 /* setup for a new key */
392 previous_key_lang_level = -1;
393 context = context_new (hash_table, line);
394 state = STATE_LOOKING_FOR_KEY;
397 APPEND_CHAR (line, c);
400 case STATE_LOOKING_FOR_KEY:
401 if (c == '\t' || c == ' ') {
411 state = STATE_ON_MIME_TYPE;
412 APPEND_CHAR (line, c);
415 state = STATE_ON_KEY;
420 c = fast_file_getc (&mime_file);
427 APPEND_CHAR (line, '\0');
428 last_str_end = line->len;
429 state = STATE_ON_VALUE;
433 if (format == FORMAT_KEYS && c == ':') {
436 APPEND_CHAR (line, '\0');
437 last_str_end = line->len;
439 /* Skip space after colon. There should be one
440 * there. That is how the file is defined. */
441 c = fast_file_getc (&mime_file);
452 state = STATE_ON_VALUE;
456 APPEND_CHAR (line, c);
460 APPEND_CHAR (line, c);
465 state = STATE_ON_KEY;
468 APPEND_CHAR (line, '\0');
469 last_str_end = line->len;
471 if (!line->str [0] ||
472 language_level (line->str + lang) < 0) {
474 key = lang = last_str_end = 0;
475 g_string_truncate (line, 0);
476 state = STATE_LOOKING_FOR_KEY;
479 APPEND_CHAR (line, c);
485 /* This happens if the last line of the file doesn't end with '\n' */
486 if (context != NULL) {
487 if (last_str_end && line->str [0]) {
488 APPEND_CHAR (line, '\0');
489 context_add_key (context,
491 lang ? line->str + lang : NULL,
492 line->str + last_str_end);
494 if (g_hash_table_size (context->keys) < 1) {
495 g_hash_table_remove (hash_table, context->mime_type);
496 context_destroy (context);
501 g_string_free (line, TRUE);
503 previous_key_lang_level = -1;
505 fast_file_close (&mime_file);
509 mime_info_load (mime_dir_source_t *source)
513 const int extlen = sizeof (".keys") - 1;
516 if (stat (source->dirname, &source->s) != -1)
517 source->valid = TRUE;
519 source->valid = FALSE;
521 dir = opendir (source->dirname);
523 source->valid = FALSE;
526 if (source->system_dir) {
527 filename = g_strconcat (source->dirname, "/gnome-vfs.keys", NULL);
528 load_mime_type_info_from (filename, specific_types);
532 while ((dent = readdir (dir)) != NULL) {
534 int len = strlen (dent->d_name);
538 if (strcmp (dent->d_name + len - extlen, ".keys"))
540 if (source->system_dir && !strcmp (dent->d_name, "gnome-vfs.keys"))
543 if (source->system_dir && !strcmp (dent->d_name, "gnome.keys")) {
544 /* Ignore the obsolete "official" one so it doesn't override
545 * the new official one.
550 if (!source->system_dir && !strcmp (dent->d_name, "user.keys"))
553 filename = g_strconcat (source->dirname, "/", dent->d_name, NULL);
554 load_mime_type_info_from (filename, specific_types);
557 if (!source->system_dir) {
558 filename = g_strconcat (source->dirname, "/user.keys", NULL);
559 load_mime_type_info_from (filename, specific_types_user);
566 mime_list_load (mime_dir_source_t *source)
570 const int extlen = sizeof (".mime") - 1;
573 if (stat (source->dirname, &source->s) != -1)
574 source->valid = TRUE;
576 source->valid = FALSE;
578 dir = opendir (source->dirname);
580 source->valid = FALSE;
583 if (source->system_dir) {
584 filename = g_strconcat (source->dirname, "/gnome-vfs.mime", NULL);
585 load_mime_list_info_from (filename, registered_types);
589 while ((dent = readdir (dir)) != NULL) {
591 int len = strlen (dent->d_name);
595 if (strcmp (dent->d_name + len - extlen, ".mime"))
597 if (source->system_dir && !strcmp (dent->d_name, "gnome-vfs.mime"))
600 if (source->system_dir && !strcmp (dent->d_name, "gnome.mime")) {
601 /* Ignore the obsolete "official" one so it doesn't override
602 * the new official one.
607 if (!source->system_dir && !strcmp (dent->d_name, "user.mime"))
610 filename = g_strconcat (source->dirname, "/", dent->d_name, NULL);
611 load_mime_list_info_from (filename, registered_types);
614 if (!source->system_dir) {
615 filename = g_strconcat (source->dirname, "/user.mime", NULL);
616 load_mime_list_info_from (filename, registered_types_user);
623 load_mime_type_info (void)
625 mime_info_load (&gnome_mime_dir);
626 mime_info_load (&user_mime_dir);
627 mime_list_load (&gnome_mime_dir);
628 mime_list_load (&user_mime_dir);
632 gnome_vfs_mime_init (void)
635 * The hash tables that store the mime keys.
637 specific_types = g_hash_table_new (g_str_hash, g_str_equal);
638 registered_types = g_hash_table_new (g_str_hash, g_str_equal);
640 specific_types_user = g_hash_table_new (g_str_hash, g_str_equal);
641 registered_types_user = g_hash_table_new (g_str_hash, g_str_equal);
643 current_lang = gnome_vfs_i18n_get_language_list ("LC_MESSAGES");
646 * Setup the descriptors for the information loading
648 gnome_mime_dir.dirname = g_strdup (DATADIR "/mime-info");
649 gnome_mime_dir.system_dir = TRUE;
651 user_mime_dir.dirname = g_strconcat
652 (g_get_home_dir (), "/.gnome/mime-info", NULL);
653 user_mime_dir.system_dir = FALSE;
658 load_mime_type_info ();
660 last_checked = time (NULL);
661 gnome_vfs_mime_inited = TRUE;
665 remove_keys (gpointer key, gpointer value, gpointer user_data)
667 GnomeMimeContext *context = value;
669 context_destroy (context);
675 reload_if_needed (void)
677 time_t now = time (NULL);
678 gboolean need_reload = FALSE;
681 if (gnome_vfs_is_frozen > 0)
684 if (gnome_mime_dir.force_reload || user_mime_dir.force_reload)
686 else if (now > last_checked + 5) {
687 if (stat (gnome_mime_dir.dirname, &s) != -1 &&
688 s.st_mtime != gnome_mime_dir.s.st_mtime)
690 else if (stat (user_mime_dir.dirname, &s) != -1 &&
691 s.st_mtime != user_mime_dir.s.st_mtime)
698 gnome_vfs_mime_info_reload ();
703 gnome_vfs_mime_info_clear (void)
705 if (specific_types != NULL) {
706 g_hash_table_foreach_remove (specific_types, remove_keys, NULL);
708 if (registered_types != NULL) {
709 g_hash_table_foreach_remove (registered_types, remove_keys, NULL);
711 if (specific_types_user != NULL) {
712 g_hash_table_foreach_remove (specific_types_user, remove_keys, NULL);
714 if (registered_types_user != NULL) {
715 g_hash_table_foreach_remove (registered_types_user, remove_keys, NULL);
720 * _gnome_vfs_mime_info_shutdown:
722 * Remove the MIME database from memory.
725 _gnome_vfs_mime_info_shutdown (void)
727 gnome_vfs_mime_info_clear ();
729 if (specific_types != NULL) {
730 g_hash_table_destroy (specific_types);
731 specific_types = NULL;
733 if (registered_types != NULL) {
734 g_hash_table_destroy (registered_types);
735 registered_types = NULL;
737 if (specific_types_user != NULL) {
738 g_hash_table_destroy (specific_types_user);
739 specific_types_user = NULL;
741 if (registered_types_user != NULL) {
742 g_hash_table_destroy (registered_types_user);
743 registered_types_user = NULL;
748 * gnome_vfs_mime_info_reload:
750 * Reload the MIME database from disk and notify any listeners
751 * holding active #GnomeVFSMIMEMonitor objects.
754 gnome_vfs_mime_info_reload (void)
756 if (!gnome_vfs_mime_inited) {
757 gnome_vfs_mime_init ();
761 gnome_vfs_mime_info_clear ();
764 load_mime_type_info ();
766 /* 3. clear our force flags */
767 gnome_mime_dir.force_reload = FALSE;
768 user_mime_dir.force_reload = FALSE;
770 /* 3. Tell anyone who cares */
771 _gnome_vfs_mime_monitor_emit_data_changed (gnome_vfs_mime_monitor_get ());
776 * gnome_vfs_mime_freeze:
778 * Freezes the mime data so that you can do multiple
779 * updates to the dat in one batch without needing
780 * to back the files to disk or readind them
783 gnome_vfs_mime_freeze (void)
785 gnome_vfs_is_frozen++;
791 * gnome_vfs_mime_thaw:
793 * UnFreezes the mime data so that you can do multiple
794 * updates to the dat in one batch without needing
795 * to back the files to disk or readind them
798 gnome_vfs_mime_thaw (void)
800 gnome_vfs_is_frozen--;
802 if (gnome_vfs_is_frozen == 0) {
803 write_back_mime_user_file ();
804 write_back_keys_user_file ();
809 static GnomeVFSResult
810 set_value_real (const char *mime_type, const char *key, const char *value,
811 GHashTable *user_hash_table)
813 GnomeMimeContext *context;
815 if (mime_type == NULL
818 return gnome_vfs_result_from_errno ();
821 g_return_val_if_fail (!does_string_contain_caps (mime_type),
822 gnome_vfs_result_from_errno ());
824 if (!gnome_vfs_mime_inited) {
825 gnome_vfs_mime_init ();
828 context = g_hash_table_lookup (user_hash_table, mime_type);
829 if (context == NULL) {
832 string = g_string_new (mime_type);
834 /* create the mime type context */
835 context = context_new (user_hash_table, string);
836 /* add the info to the mime type context */
837 g_hash_table_insert (context->keys, g_strdup (key), g_strdup (value));
838 g_string_free (string, TRUE);
840 g_hash_table_replace (context->keys, g_strdup (key), g_strdup (value));
846 * gnome_vfs_mime_set_value
847 * @mime_type: a mime type.
848 * @key: a key to store the value in.
849 * @value: the value to store in the key.
851 * This function is going to set the value
852 * associated to the key and it will save it
853 * to the user' file if necessary.
854 * You should not free the key/values passed to
855 * this function. They are used internally.
857 * Returns: GNOME_VFS_OK if the operation succeeded, otherwise an error code
861 gnome_vfs_mime_set_value (const char *mime_type, const char *key, const char *value)
863 GnomeVFSResult retval;
865 retval = set_value_real (mime_type, key, value, specific_types_user);
867 if (gnome_vfs_is_frozen == 0) {
868 return write_back_keys_user_file ();
876 is_mime_type_deleted (const char *mime_type)
878 const char *deleted_key;
880 deleted_key = gnome_vfs_mime_get_registered_mime_type_key (mime_type, DELETED_KEY);
881 return deleted_key != NULL && strcmp (deleted_key, DELETED_VALUE) == 0;
885 get_value_from_hash_table (GHashTable *hash_table, const char *mime_type, const char *key)
887 GnomeMimeContext *context;
891 context = g_hash_table_lookup (hash_table, mime_type);
892 if (context != NULL) {
893 value = g_hash_table_lookup (context->keys, key);
899 get_value_real (const char *mime_type,
901 GHashTable *user_hash_table,
902 GHashTable *system_hash_table)
905 char *generic_type, *p;
907 g_return_val_if_fail (key != NULL, NULL);
908 g_assert (user_hash_table != NULL);
909 g_assert (system_hash_table != NULL);
911 if (mime_type == NULL) {
915 g_return_val_if_fail (!does_string_contain_caps (mime_type),
920 if (strcmp (key, DELETED_KEY) != 0 && is_mime_type_deleted (mime_type)) {
924 value = get_value_from_hash_table (user_hash_table, mime_type, key);
929 value = get_value_from_hash_table (system_hash_table, mime_type, key);
934 generic_type = g_strdup (mime_type);
935 p = strchr (generic_type, '/');
939 value = get_value_from_hash_table (user_hash_table, generic_type, key);
941 g_free (generic_type);
945 value = get_value_from_hash_table (system_hash_table, generic_type, key);
946 g_free (generic_type);
956 * gnome_vfs_mime_get_value:
957 * @mime_type: a mime type.
958 * @key: A key to lookup for the given mime-type
960 * This function retrieves the value associated with @key in
961 * the given GnomeMimeContext. The string is private, you
962 * should not free the result.
964 * Returns: GNOME_VFS_OK if the operation succeeded, otherwise an error code
967 gnome_vfs_mime_get_value (const char *mime_type, const char *key)
969 if (!gnome_vfs_mime_inited)
970 gnome_vfs_mime_init ();
972 return get_value_real (mime_type, key, specific_types_user, specific_types);
976 * gnome_vfs_mime_type_is_known:
977 * @mime_type: a mime type.
979 * This function returns TRUE if @mime_type is in the MIME database at all.
981 * Returns: TRUE if anything is known about @mime_type, otherwise FALSE
984 gnome_vfs_mime_type_is_known (const char *mime_type)
986 if (mime_type == NULL) {
990 g_return_val_if_fail (!does_string_contain_caps (mime_type),
993 if (!gnome_vfs_mime_inited)
994 gnome_vfs_mime_init ();
998 if (is_mime_type_deleted (mime_type)) {
1002 if (g_hash_table_lookup (specific_types, mime_type)) {
1006 if (g_hash_table_lookup (specific_types_user, mime_type)) {
1010 if (g_hash_table_lookup (registered_types, mime_type)) {
1014 if (g_hash_table_lookup (registered_types_user, mime_type)) {
1023 * gnome_vfs_mime_keys_list_free:
1024 * @mime_type_list: A mime type list to free.
1026 * Frees the mime type list.
1029 gnome_vfs_mime_keys_list_free (GList *mime_type_list)
1031 /* we do not need to free the data in the list since
1032 the data was stolen from the internal hash table
1033 This function is there so that people do not need
1034 to know this particuliar implementation detail.
1037 g_list_free (mime_type_list);
1041 assemble_list (gpointer key, gpointer value, gpointer user_data)
1043 GList **listp = user_data;
1045 (*listp) = g_list_prepend ((*listp), key);
1049 * gnome_vfs_mime_get_key_list:
1050 * @mime_type: the MIME type to lookup
1052 * Gets a list of all keys associated with @mime_type.
1054 * Return value: a GList of const char * representing keys associated
1058 gnome_vfs_mime_get_key_list (const char *mime_type)
1060 char *p, *generic_type;
1061 GnomeMimeContext *context;
1062 GList *list = NULL, *l;
1064 if (mime_type == NULL) {
1067 g_return_val_if_fail (!does_string_contain_caps (mime_type),
1070 if (!gnome_vfs_mime_inited)
1071 gnome_vfs_mime_init ();
1073 reload_if_needed ();
1075 generic_type = g_strdup (mime_type);
1076 p = strchr (generic_type, '/');
1080 context = g_hash_table_lookup (specific_types_user, generic_type);
1081 if (context != NULL) {
1082 g_hash_table_foreach (
1083 context->keys, assemble_list, &list);
1086 context = g_hash_table_lookup (specific_types, generic_type);
1087 if (context != NULL) {
1088 g_hash_table_foreach (
1089 context->keys, assemble_list, &list);
1092 g_free (generic_type);
1093 for (l = list; l;) {
1095 void *this = l->data;
1098 for (m = l->next; m; m = m->next) {
1099 if (strcmp ((char*) this, (char*) m->data) != 0)
1101 list = g_list_remove (list, m->data);
1112 str_cmp_callback (gconstpointer a,
1115 str_cmp_callback (gconstpointer a,
1118 return (strcmp ((char *)a, (char *)b));
1122 * gnome_vfs_mime_set_extensions_list:
1123 * @mime_type: the mime type.
1124 * @extensions_list: a whitespace-separated list of the
1125 * extensions to set for this mime type.
1127 * Sets the extensions for a given mime type. Overrides
1128 * the previously set extensions.
1130 * Return value: GNOME_VFS_OK if the operation succeeded, otherwise an error code.
1133 gnome_vfs_mime_set_extensions_list (const char *mime_type,
1134 const char *extensions_list)
1136 if (is_mime_type_deleted (mime_type)) {
1137 gnome_vfs_mime_set_registered_type_key (mime_type, DELETED_KEY, "");
1140 return gnome_vfs_mime_set_registered_type_key (mime_type, "ext", extensions_list);
1145 * gnome_vfs_mime_get_extensions_list:
1146 * @mime_type: type to get the extensions of
1148 * Get the file extensions associated with mime type @mime_type.
1150 * Return value: a GList of char *s
1153 gnome_vfs_mime_get_extensions_list (const char *mime_type)
1156 const char *extensions_system, *extensions_user;
1160 GnomeMimeContext *context;
1162 if (mime_type == NULL) {
1165 g_return_val_if_fail (!does_string_contain_caps (mime_type),
1169 if (!gnome_vfs_mime_inited) {
1170 gnome_vfs_mime_init ();
1173 reload_if_needed ();
1175 extensions_system = NULL;
1176 extensions_user = NULL;
1178 context = g_hash_table_lookup (registered_types_user, mime_type);
1179 if (context != NULL) {
1180 extensions_user = g_hash_table_lookup (context->keys, "ext");
1183 context = g_hash_table_lookup (registered_types, mime_type);
1184 if (context != NULL) {
1185 extensions_system = g_hash_table_lookup (context->keys, "ext");
1190 if (extensions_user != NULL) {
1191 extensions = g_strdup (extensions_user);
1192 } else if (extensions_system != NULL) {
1193 extensions = g_strdup (extensions_system);
1196 /* build a GList from the string */
1198 if (extensions != NULL) {
1199 /* Parse the extensions and add to list */
1200 elements = g_strsplit (extensions, " ", 0);
1201 if (elements != NULL) {
1204 while (elements[index] != NULL) {
1205 if (strcmp (elements[index], "") != 0) {
1206 list = g_list_append (list, g_strdup (elements[index]));
1210 g_strfreev (elements);
1214 g_free (extensions);
1221 * gnome_vfs_mime_get_extensions_string:
1222 * @mime_type: the mime type
1224 * Retrieves the extensions associated with @mime_type as a single
1225 * space seperated string.
1227 * Return value: a string containing space seperated extensions for @mime_type
1230 gnome_vfs_mime_get_extensions_string (const char *mime_type)
1232 GList *extensions_list, *temp_list;
1235 if (mime_type == NULL) {
1238 g_return_val_if_fail (!does_string_contain_caps (mime_type),
1242 /* it might seem overkill to use gnome_vfs_mime_get_extensions_list
1243 here but it has the advantage that this function returns
1244 a list of unique extensions */
1246 extensions_list = gnome_vfs_mime_get_extensions_list (mime_type);
1247 if (extensions_list == NULL) {
1252 for (temp_list = extensions_list; temp_list != NULL; temp_list = temp_list->next) {
1254 temp_string = g_strconcat (temp_list->data, " ", extensions, NULL);
1255 g_free (extensions);
1256 extensions = temp_string;
1259 extensions[strlen (extensions) - 1] = '\0';
1264 * gnome_vfs_mime_get_extensions_pretty_string:
1265 * @mime_type: the mime type
1267 * Returns the supported extensions for @mime_type as a comma-seperated list.
1269 * Return value: a string containing comma seperated extensions for this mime-type
1272 gnome_vfs_mime_get_extensions_pretty_string (const char *mime_type)
1274 GList *extensions, *element;
1275 char *ext_str, *tmp_str;
1277 if (mime_type == NULL) {
1284 if (!gnome_vfs_mime_inited) {
1285 gnome_vfs_mime_init ();
1288 reload_if_needed ();
1290 extensions = gnome_vfs_mime_get_extensions_list (mime_type);
1291 if (extensions == NULL) {
1295 for (element = extensions; element != NULL; element = element->next) {
1296 if (ext_str != NULL) {
1299 if (element->next == NULL) {
1300 ext_str = g_strconcat (tmp_str, ".", (char *)element->data, NULL);
1302 ext_str = g_strconcat (tmp_str, ".", (char *)element->data, ", ", NULL);
1306 if (g_list_length (extensions) == 1) {
1307 ext_str = g_strconcat (".", (char *)element->data, NULL);
1309 ext_str = g_strconcat (".", (char *)element->data, ", ", NULL);
1313 gnome_vfs_mime_extensions_list_free (extensions);
1320 * gnome_vfs_mime_extensions_list_free:
1321 * @list: the extensions list
1323 * Call this function on the list returned by gnome_vfs_mime_extensions
1324 * to free the list and all of its elements.
1327 gnome_vfs_mime_extensions_list_free (GList *list)
1332 g_list_foreach (list, (GFunc) g_free, NULL);
1339 mime_list_sort (gconstpointer a, gconstpointer b)
1341 return (strcmp ((const char *) a, (const char *) b));
1347 * Hash table function that adds the name of the mime type
1348 * to the supplied GList.
1352 get_key_name (gpointer key, gpointer value, gpointer user_data)
1354 GnomeMimeContext *context;
1356 GList **list = user_data;
1359 if (value == NULL || key == NULL) {
1363 context = (GnomeMimeContext *) value;
1365 if (context->mime_type[0] == '#') {
1369 if (is_mime_type_deleted (context->mime_type)) {
1373 /* Get name from key and exit if key is NULL or string is empty */
1375 if (name == NULL || strlen (name) == 0) {
1380 duplicate = g_list_find_custom ((*list), context->mime_type, (GCompareFunc)strcmp);
1381 if (duplicate == NULL) {
1382 (*list) = g_list_insert_sorted ((*list), g_strdup(context->mime_type), mime_list_sort);
1388 * gnome_vfs_mime_reset
1390 * resets the user's mime database to the system defaults.
1393 gnome_vfs_mime_reset (void)
1397 filename = g_strconcat (user_mime_dir.dirname, "/user.keys", NULL);
1401 filename = g_strconcat (user_mime_dir.dirname, "/user.mime", NULL);
1408 * gnome_vfs_mime_registered_mime_type_delete:
1409 * @mime_type: string representing the existing type to delete
1411 * Delete a mime type for the user which runs this command.
1412 * You can undo this only by calling gnome_vfs_mime_reset
1416 gnome_vfs_mime_registered_mime_type_delete (const char *mime_type)
1418 gnome_vfs_mime_set_registered_type_key (mime_type,
1425 * gnome_vfs_get_registered_mime_types
1427 * Return the list containing the name of all
1428 * registrered mime types.
1429 * This function is costly in terms of speed.
1432 gnome_vfs_get_registered_mime_types (void)
1434 GList *type_list = NULL;
1436 if (!gnome_vfs_mime_inited) {
1437 gnome_vfs_mime_init ();
1440 reload_if_needed ();
1442 /* Extract mime type names */
1443 g_hash_table_foreach (registered_types_user, get_key_name, &type_list);
1444 g_hash_table_foreach (registered_types, get_key_name, &type_list);
1450 * gnome_vfs_mime_registered_mime_type_list_free:
1451 * @list: the extensions list
1453 * Call this function on the list returned by gnome_vfs_get_registered_mime_types
1454 * to free the list and all of its elements.
1457 gnome_vfs_mime_registered_mime_type_list_free (GList *list)
1463 g_list_foreach (list, (GFunc) g_free, NULL);
1468 * gnome_vfs_mime_set_registered_type_key:
1469 * @mime_type: Mime type to set key for
1470 * @key: The key to set
1471 * @data: The data to set for the key
1473 * This function sets the key data for the registered mime
1474 * type's hash table.
1476 * Returns: GNOME_VFS_OK if the operation succeeded, otherwise an error code
1479 gnome_vfs_mime_set_registered_type_key (const char *mime_type, const char *key, const char *value)
1481 GnomeVFSResult result;
1483 result = set_value_real (mime_type, key, value, registered_types_user);
1485 if (gnome_vfs_is_frozen == 0) {
1486 result = write_back_mime_user_file ();
1493 * gnome_vfs_mime_get_registered_mime_type_key
1494 * @mime_type: a mime type.
1495 * @key: A key to lookup for the given mime-type
1497 * This function retrieves the value associated with @key in
1498 * the given GnomeMimeContext. The string is private, you
1499 * should not free the result.
1502 gnome_vfs_mime_get_registered_mime_type_key (const char *mime_type, const char *key)
1504 if (!gnome_vfs_mime_inited)
1505 gnome_vfs_mime_init ();
1507 return get_value_real (mime_type, key,
1508 registered_types_user,
1514 ensure_user_directory_exist (void)
1519 if (stat (user_mime_dir.dirname, &user_mime_dir.s) != -1)
1520 user_mime_dir.valid = TRUE;
1522 user_mime_dir.valid = FALSE;
1525 dir = opendir (user_mime_dir.dirname);
1529 result = mkdir (user_mime_dir.dirname, S_IRWXU );
1531 user_mime_dir.valid = FALSE;
1534 dir = opendir (user_mime_dir.dirname);
1536 user_mime_dir.valid = FALSE;
1540 retval = (dir != NULL);
1548 write_back_mime_user_file_context_callback (char *key_data,
1552 fprintf (file, "\t%s: %s\n", key_data, value_data);
1555 write_back_mime_user_file_callback (char *mime_type,
1556 GnomeMimeContext *context,
1559 fprintf (file, "%s\n", mime_type);
1560 g_hash_table_foreach (context->keys,
1561 (GHFunc) write_back_mime_user_file_context_callback,
1563 fprintf (file, "\n");
1566 static GnomeVFSResult
1567 write_back_mime_user_file (void)
1572 if (!ensure_user_directory_exist ()) {
1573 return gnome_vfs_result_from_errno ();
1576 if (!user_mime_dir.system_dir) {
1577 filename = g_strconcat (user_mime_dir.dirname, "/user.mime", NULL);
1580 file = fopen (filename, "w");
1582 return gnome_vfs_result_from_errno ();
1585 "# This file was autogenerated by gnome-vfs-mime-info.\n"
1586 "# Do not edit by hand.\n");
1588 g_hash_table_foreach (registered_types_user,
1589 (GHFunc) write_back_mime_user_file_callback,
1597 return GNOME_VFS_OK;
1601 write_back_keys_user_file_context_callback (char *key_data,
1605 fprintf (file, "\t%s=%s\n", key_data, value_data);
1608 write_back_keys_user_file_callback (char *mime_type,
1609 GnomeMimeContext *context,
1613 fprintf (file, "%s\n", mime_type);
1614 g_hash_table_foreach (context->keys,
1615 (GHFunc) write_back_keys_user_file_context_callback,
1617 fprintf (file, "\n");
1620 static GnomeVFSResult
1621 write_back_keys_user_file (void)
1626 if (!ensure_user_directory_exist ()) {
1627 return gnome_vfs_result_from_errno ();
1630 if (!user_mime_dir.system_dir) {
1631 filename = g_strconcat (user_mime_dir.dirname, "/user.keys", NULL);
1634 file = fopen (filename, "w");
1636 return gnome_vfs_result_from_errno ();
1640 fprintf (file, "# this file was autogenerated by gnome-vfs-mime-info.\n"
1641 "# DO NOT EDIT BY HAND\n");
1643 g_hash_table_foreach (specific_types_user,
1644 (GHFunc) write_back_keys_user_file_callback,
1652 return GNOME_VFS_OK;