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 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. */
24 * Authors: George Lebl
25 * Based on original mime-info database code by Miguel de Icaza
29 #include "gnome-vfs-application-registry.h"
30 #include "gnome-vfs-configuration.h"
31 #include "gnome-vfs-mime-handlers.h"
32 #include "gnome-vfs-mime-private.h"
33 #include "gnome-vfs-mime.h"
34 #include "gnome-vfs-private-utils.h"
35 #include "gnome-vfs-result.h"
45 #include <sys/types.h>
49 #if !defined getc_unlocked && !defined HAVE_GETC_UNLOCKED
50 # define getc_unlocked(fp) getc (fp)
53 typedef struct _Application Application;
57 /* The following is true if this was found in the
58 * home directory or if the user changed any keys
59 * here. It means that it will be saved into a user
63 GnomeVFSMimeApplicationArgumentType expects_uris;
65 GList *supported_uri_schemes;
66 /* The user_owned version of this if this is a system
68 Application *user_application;
71 /* Describes the directories we scan for information */
74 unsigned int valid : 1;
75 unsigned int system_dir : 1;
76 } ApplicationRegistryDir;
78 /* These ones are used to automatically reload mime info on demand */
79 static FileDateTracker *registry_date_tracker;
80 static ApplicationRegistryDir gnome_registry_dir;
81 static ApplicationRegistryDir user_registry_dir;
83 /* To initialize the module automatically */
84 static gboolean gnome_vfs_application_registry_initialized = FALSE;
87 static GList *current_lang = NULL;
88 /* we want to replace the previous key if the current key has a higher
90 static char *previous_key = NULL;
91 static int previous_key_lang_level = -1;
94 * A hash table containing application registry record (Application)
95 * keyed by application ids.
97 static GHashTable *global_applications = NULL;
99 * A hash table containing GList's of application registry records (Application)
100 * keyed by the mime types
102 /* specific mime_types (e.g. image/png) */
103 static GHashTable *specific_mime_types = NULL;
104 /* generic mime_types (e.g. image/<star>) */
105 static GHashTable *generic_mime_types = NULL;
108 * Dirty flag, just to make sure we don't sync needlessly
110 static gboolean user_file_dirty = FALSE;
113 * Some local prototypes
115 static void gnome_vfs_application_registry_init (void);
116 static void application_clear_mime_types (Application *application);
119 application_ref (Application *application)
121 g_return_val_if_fail(application != NULL, NULL);
123 application->ref_count ++;
129 hash_foreach_free_key_value(gpointer key, gpointer value, gpointer user_data)
136 application_unref (Application *application)
138 g_return_if_fail(application != NULL);
140 application->ref_count --;
142 if (application->ref_count == 0) {
143 application_clear_mime_types (application);
145 if (application->keys != NULL) {
146 g_hash_table_foreach(application->keys, hash_foreach_free_key_value, NULL);
147 g_hash_table_destroy(application->keys);
148 application->keys = NULL;
151 g_free(application->app_id);
152 application->app_id = NULL;
154 if (application->user_application != NULL) {
155 application_unref (application->user_application);
156 application->user_application = NULL;
164 application_new (const char *app_id, gboolean user_owned)
166 Application *application;
168 application = g_new0 (Application, 1);
169 application->app_id = g_strdup(app_id);
170 application->ref_count = 1;
171 application->expects_uris = GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_PATHS;
172 application->user_owned = user_owned;
178 application_lookup_or_create (const char *app_id, gboolean user_owned)
180 Application *application;
182 g_return_val_if_fail(app_id != NULL, NULL);
184 gnome_vfs_application_registry_init ();
186 application = g_hash_table_lookup (global_applications, app_id);
187 if (application != NULL) {
189 /* if we find only a user app, do magic */
190 if (application->user_owned) {
191 Application *new_application;
192 new_application = application_new (app_id, FALSE/*user_owned*/);
193 new_application->user_application = application;
194 /* override the user application */
195 g_hash_table_insert (global_applications, new_application->app_id,
197 return new_application;
202 if (application->user_owned) {
204 } if (application->user_application != NULL) {
205 return application->user_application;
207 Application *new_application;
208 new_application = application_new (app_id, TRUE/*user_owned*/);
209 application->user_application = new_application;
210 return new_application;
215 application = application_new (app_id, user_owned);
217 g_hash_table_insert (global_applications, application->app_id, application);
223 application_lookup (const char *app_id)
225 g_return_val_if_fail(app_id != NULL, NULL);
227 if (global_applications == NULL)
230 return g_hash_table_lookup (global_applications, app_id);
234 peek_value (const Application *application, const char *key)
236 g_return_val_if_fail(application != NULL, NULL);
237 g_return_val_if_fail(key != NULL, NULL);
239 if (application->keys == NULL)
242 return g_hash_table_lookup (application->keys, key);
246 set_value (Application *application, const char *key, const char *value)
248 char *old_value, *old_key;
250 g_return_if_fail(application != NULL);
251 g_return_if_fail(key != NULL);
252 g_return_if_fail(value != NULL);
254 if (application->keys == NULL)
255 application->keys = g_hash_table_new (g_str_hash, g_str_equal);
257 if (g_hash_table_lookup_extended (application->keys, key,
258 (gpointer *)&old_key,
259 (gpointer *)&old_value)) {
260 g_hash_table_insert (application->keys,
261 old_key, g_strdup (value));
264 g_hash_table_insert (application->keys,
265 g_strdup (key), g_strdup (value));
270 unset_key (Application *application, const char *key)
272 char *old_value, *old_key;
274 g_return_if_fail(application != NULL);
275 g_return_if_fail(key != NULL);
277 if (application->keys == NULL)
280 if (g_hash_table_lookup_extended (application->keys, key,
281 (gpointer *)&old_key,
282 (gpointer *)&old_value)) {
283 g_hash_table_remove (application->keys, old_key);
290 value_looks_true (const char *value)
297 atoi (value) != 0)) {
305 get_bool_value (const Application *application, const char *key,
308 const char *value = peek_value (application, key);
315 return value_looks_true (value);
320 set_bool_value (Application *application, const char *key,
323 set_value (application, key, value ? "true" : "false");
327 application_compare (Application *application1,
328 Application *application2)
330 return strcmp (application1->app_id, application2->app_id);
334 add_application_to_mime_type_table (Application *application,
335 const char *mime_type)
337 GList *application_list;
341 if (gnome_vfs_mime_type_is_supertype (mime_type))
342 table = generic_mime_types;
344 table = specific_mime_types;
346 g_assert (table != NULL);
348 if (g_hash_table_lookup_extended (table, mime_type,
349 (gpointer *)&old_key,
350 (gpointer *)&application_list)) {
351 /* Sorted order is important as we can then easily
352 * uniquify the results */
353 application_list = g_list_insert_sorted
355 application_ref (application),
356 (GCompareFunc) application_compare);
357 g_hash_table_insert (table, old_key, application_list);
359 application_list = g_list_prepend (NULL,
360 application_ref (application));
361 g_hash_table_insert (table, g_strdup (mime_type), application_list);
366 add_mime_type_to_application (Application *application, const char *mime_type)
368 /* if this exists already, just return */
369 if (g_list_find_custom (application->mime_types,
370 /*glib is const incorrect*/(gpointer)mime_type,
371 (GCompareFunc) strcmp) != NULL)
374 application->mime_types =
375 g_list_prepend (application->mime_types,
376 g_strdup (mime_type));
378 add_application_to_mime_type_table (application, mime_type);
383 add_supported_uri_scheme_to_application (Application *application,
384 const char *supported_uri_scheme)
386 if (g_list_find_custom (application->supported_uri_schemes,
387 /*glib is const incorrect*/(gpointer) supported_uri_scheme,
388 (GCompareFunc) strcmp) != NULL) {
392 application->supported_uri_schemes =
393 g_list_prepend (application->supported_uri_schemes,
394 g_strdup (supported_uri_scheme));
399 supported_uri_scheme_list_copy (GList *supported_uri_schemes)
401 GList *copied_list, *node;
404 for (node = supported_uri_schemes; node != NULL;
406 copied_list = g_list_prepend (copied_list,
407 g_strdup ((char *) node->data));
414 remove_application_from_mime_type_table (Application *application,
415 const char *mime_type)
419 GList *application_list, *entry;
421 if (gnome_vfs_mime_type_is_supertype (mime_type))
422 table = generic_mime_types;
424 table = specific_mime_types;
426 g_assert (table != NULL);
428 if (g_hash_table_lookup_extended (table, mime_type,
429 (gpointer *)&old_key,
430 (gpointer *)&application_list)) {
431 entry = g_list_find (application_list, application);
433 /* if this fails we're in deep doodoo I guess */
434 g_assert (entry != NULL);
436 application_list = g_list_remove_link (application_list, entry);
438 application_unref (application);
440 if (application_list != NULL) {
441 g_hash_table_insert (table, old_key, application_list);
443 g_hash_table_remove (table, old_key);
447 g_assert_not_reached ();
451 remove_mime_type_for_application (Application *application, const char *mime_type)
455 g_return_if_fail(application != NULL);
456 g_return_if_fail(mime_type != NULL);
458 entry = g_list_find_custom
459 (application->mime_types,
460 /*glib is const incorrect*/(gpointer)mime_type,
461 (GCompareFunc) strcmp);
463 /* if this doesn't exist, just return */
468 remove_application_from_mime_type_table (application, mime_type);
470 /* Free data last, in case caller passed in mime_type string
471 * that was stored in this table.
473 application->mime_types =
474 g_list_remove_link (application->mime_types, entry);
475 g_free (entry->data);
476 g_list_free_1 (entry);
481 application_clear_mime_types (Application *application)
483 g_return_if_fail (application != NULL);
485 while (application->mime_types)
486 remove_mime_type_for_application (application, application->mime_types->data);
490 application_remove (Application *application)
492 Application *main_application;
494 g_return_if_fail (application != NULL);
496 if (global_applications == NULL) {
500 main_application = application_lookup (application->app_id);
501 if (main_application == NULL) {
505 /* We make sure the mime types are killed even if the application
506 * entry lives after unreffing it */
507 application_clear_mime_types (application);
509 if (main_application == application) {
510 if (application->user_application)
511 application_clear_mime_types (application->user_application);
513 g_hash_table_remove (global_applications, application->app_id);
515 /* This must be a user application */
516 g_assert (main_application->user_application == application);
518 main_application->user_application = NULL;
521 application_unref (application);
526 sync_key (gpointer key, gpointer value, gpointer user_data)
528 char *key_string = key;
529 char *value_string = value;
530 FILE *fp = user_data;
532 fprintf (fp, "\t%s=%s\n", key_string, value_string);
535 /* write an application to a file */
537 application_sync (Application *application, FILE *fp)
541 g_return_if_fail (application != NULL);
542 g_return_if_fail (application->app_id != NULL);
543 g_return_if_fail (fp != NULL);
545 fprintf (fp, "%s\n", application->app_id);
547 if (application->keys != NULL)
548 g_hash_table_foreach (application->keys, sync_key, fp);
550 if (application->mime_types != NULL) {
552 fprintf (fp, "\tmime_types=");
554 for (li = application->mime_types; li != NULL; li = li->next) {
555 char *mime_type = li->data;
556 fprintf (fp, "%s%s", separator, mime_type);
565 /* this gives us a number of the language in the current language list,
566 the higher the number the "better" the translation */
568 language_level (const char *lang)
576 for (i = 1, li = current_lang; li != NULL; i++, li = g_list_next (li)) {
577 if (strcmp ((const char *) li->data, lang) == 0)
586 application_add_key (Application *application, const char *key,
587 const char *lang, const char *value)
591 g_return_if_fail (application != NULL);
592 g_return_if_fail (key != NULL);
593 g_return_if_fail (value != NULL);
595 if (strcmp (key, "mime_types") == 0 ||
596 strcmp (key, "supported_uri_schemes") == 0) {
597 char *value_copy = g_strdup (value);
599 /* FIXME: There used to be a check here for
600 the value of "lang", but spamming
601 the terminal about it is not really
602 the right way to deal with that, nor
603 is "MIME Types can't have languages, bad!"
604 which is what was here before */
605 next_value = strtok (value_copy, ", \t");
606 while (next_value != NULL) {
607 if (strcmp (key, "mime_types") == 0) {
608 add_mime_type_to_application (application, next_value);
611 add_supported_uri_scheme_to_application (application, next_value);
613 next_value = strtok (NULL, ", \t");
616 /* fall through so that we can store the values as keys too */
618 else if (strcmp (key, "expects_uris") == 0) {
619 if (strcmp (value, "non-file") == 0) {
620 application->expects_uris = GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_URIS_FOR_NON_FILES;
622 else if (value_looks_true (value)) {
623 application->expects_uris = GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_URIS;
626 application->expects_uris = GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_PATHS;
630 lang_level = language_level (lang);
631 /* wrong language completely */
635 /* if we have some language defined and
636 if there was a previous_key */
637 if (lang_level > 0 &&
639 /* our language level really sucks and the previous
640 translation was of better language quality so just
642 previous_key_lang_level > lang_level) {
646 set_value (application, key, value);
648 /* set this as the previous key */
649 g_free(previous_key);
650 previous_key = g_strdup(key);
651 previous_key_lang_level = lang_level;
657 STATE_LOOKING_FOR_KEY,
658 STATE_ON_APPLICATION,
664 * strip_trailing_whitespace
668 * strips the white space from a string.
673 strip_trailing_whitespace (GString *string)
677 for (i = string->len - 1; i >= 0; i--) {
678 if (!g_ascii_isspace (string->str[i]))
682 g_string_truncate (string, i + 1);
686 * load_application_info_from
688 * filename: Target filename to application info from.
689 * user_owned: if application is user owned or not.
691 * This function will load application info from a file and parse through the
692 * application loading the registry with the information contained in the file.
698 load_application_info_from (const char *filename, gboolean user_owned)
701 gboolean in_comment, app_used;
705 Application *application;
709 fp = fopen (filename, "r");
719 line = g_string_sized_new (120);
722 while ((c = getc_unlocked (fp)) != EOF){
727 if (c == '#' && column == 0){
735 if (state == STATE_ON_APPLICATION) {
737 /* set previous key to nothing
738 for this mime type */
739 g_free(previous_key);
741 previous_key_lang_level = -1;
743 strip_trailing_whitespace (line);
744 application = application_lookup_or_create (line->str, user_owned);
746 g_string_assign (line, "");
747 state = STATE_LOOKING_FOR_KEY;
750 if (state == STATE_ON_VALUE){
752 application_add_key (application, key, lang, line->str);
753 g_string_assign (line, "");
758 state = STATE_LOOKING_FOR_KEY;
769 if (c != ' ' && c != '\t')
770 state = STATE_ON_APPLICATION;
775 case STATE_ON_APPLICATION:
780 g_string_append_c (line, c);
783 case STATE_LOOKING_FOR_KEY:
784 if (c == '\t' || c == ' ')
793 state = STATE_ON_APPLICATION;
794 g_string_append_c (line, c);
797 state = STATE_ON_KEY;
807 key = g_strdup (line->str);
808 g_string_assign (line, "");
809 state = STATE_ON_VALUE;
812 g_string_append_c (line, c);
816 g_string_append_c (line, c);
821 state = STATE_ON_KEY;
824 lang = g_strdup(line->str);
827 state = STATE_LOOKING_FOR_KEY;
829 g_string_assign (line, "");
832 g_string_append_c (line, c);
838 if (key && line->str [0])
839 application_add_key (application, key, lang, line->str);
842 application_remove (application);
845 g_string_free (line, TRUE);
849 /* free the previous_key stuff */
850 g_free(previous_key);
852 previous_key_lang_level = -1;
856 _gnome_vfs_file_date_tracker_start_tracking_file (registry_date_tracker, filename);
860 * application_info_load
868 application_info_load (ApplicationRegistryDir *source)
872 const int extlen = sizeof (".applications") - 1;
876 if (stat (source->dirname, &s) != -1)
877 source->valid = TRUE;
879 source->valid = FALSE;
881 dir = opendir (source->dirname);
883 source->valid = FALSE;
886 if (source->system_dir) {
887 filename = g_strconcat (source->dirname, "/gnome-vfs.applications", NULL);
888 load_application_info_from (filename, FALSE /*user_owned*/);
892 while ((dent = readdir (dir)) != NULL){
894 int len = strlen (dent->d_name);
898 if (strcmp (dent->d_name + len - extlen, ".applications"))
900 if (source->system_dir && strcmp (dent->d_name, "gnome-vfs.applications") == 0)
902 if ( ! source->system_dir && strcmp (dent->d_name, "user.applications") == 0)
904 filename = g_strconcat (source->dirname, "/", dent->d_name, NULL);
905 load_application_info_from (filename, FALSE /*user_owned*/);
909 if ( ! source->system_dir) {
910 filename = g_strconcat (source->dirname, "/user.applications", NULL);
911 /* Currently this is the only file that is "user owned". It actually makes
912 * sense. Editting of other files from the API would be too complex */
913 load_application_info_from (filename, TRUE /*user_owned*/);
918 _gnome_vfs_file_date_tracker_start_tracking_file (registry_date_tracker, source->dirname);
922 * load_application_info
924 * This function will load the registry for an application from disk.
928 load_application_info (void)
930 application_info_load (&gnome_registry_dir);
931 application_info_load (&user_registry_dir);
935 * gnome_vfs_application_registry_init
937 * This function initializes the gnome-vfs application registry.
941 gnome_vfs_application_registry_init (void)
943 if (gnome_vfs_application_registry_initialized)
946 registry_date_tracker = _gnome_vfs_file_date_tracker_new ();
949 * The hash tables that store the mime keys.
951 global_applications = g_hash_table_new (g_str_hash, g_str_equal);
952 generic_mime_types = g_hash_table_new (g_str_hash, g_str_equal);
953 specific_mime_types = g_hash_table_new (g_str_hash, g_str_equal);
955 current_lang = gnome_vfs_i18n_get_language_list ("LC_MESSAGES");
958 * Setup the descriptors for the information loading
961 gnome_registry_dir.dirname = g_strdup (DATADIR "/application-registry");
962 gnome_registry_dir.system_dir = TRUE;
964 user_registry_dir.dirname = g_strconcat (g_get_home_dir(), "/.gnome/application-info", NULL);
965 user_registry_dir.system_dir = FALSE;
967 /* Make sure user directory exists */
968 if (mkdir (user_registry_dir.dirname, 0700) &&
970 g_warning("Could not create per-user Gnome application-registry directory: %s",
971 user_registry_dir.dirname);
974 /* Things have been initialized flag it as ready so that we can load
975 * the applications without attempting to reinitialize
977 gnome_vfs_application_registry_initialized = TRUE;
979 load_application_info ();
985 * This function will initialize the registry in memory and then reloads the
992 gnome_vfs_application_registry_init ();
994 if (!_gnome_vfs_file_date_tracker_date_has_changed (registry_date_tracker)) {
998 gnome_vfs_application_registry_reload ();
1008 * FIXME: I need a clearer explanation on what this does.
1013 remove_apps (gpointer key, gpointer value, gpointer user_data)
1015 Application *application = value;
1017 application_clear_mime_types (application);
1019 application_unref (application);
1025 * gnome_vfs_application_registry_clear:
1027 * This will wipe the registry clean removing everything from the registry.
1028 * This is different from gnome_vfs_application_registry_shutdown which will
1029 * actually delete the registry and leave it in an uninitialized state.
1034 gnome_vfs_application_registry_clear (void)
1036 if (global_applications != NULL)
1037 g_hash_table_foreach_remove (global_applications, remove_apps, NULL);
1041 * gnome_vfs_application_registry_shutdown
1043 * Synchronize gnome-vfs application registry data to disk, and free
1049 gnome_vfs_application_registry_shutdown (void)
1051 gnome_vfs_application_registry_clear ();
1053 if (global_applications != NULL) {
1054 g_hash_table_destroy (global_applications);
1055 global_applications = NULL;
1058 if(generic_mime_types != NULL) {
1059 g_hash_table_destroy (generic_mime_types);
1060 generic_mime_types = NULL;
1063 if(specific_mime_types != NULL) {
1064 g_hash_table_destroy (specific_mime_types);
1065 specific_mime_types = NULL;
1068 _gnome_vfs_file_date_tracker_free (registry_date_tracker);
1070 g_free(gnome_registry_dir.dirname);
1071 gnome_registry_dir.dirname = NULL;
1072 g_free(user_registry_dir.dirname);
1073 user_registry_dir.dirname = NULL;
1075 g_list_free(current_lang);
1076 current_lang = NULL;
1078 gnome_vfs_application_registry_initialized = FALSE;
1083 * gnome_vfs_application_registry_reload
1085 * If this function is called for the first time it will initialize the
1086 * registry. Subsequent calls to the function will clear out the current
1087 * registry contents and load registry contents from the save file. Make
1088 * certain that you've saved your registry before calling this function. It
1089 * will destroy unsaved changes.
1094 gnome_vfs_application_registry_reload (void)
1096 if ( ! gnome_vfs_application_registry_initialized) {
1097 /* If not initialized, initialization will do a "reload" */
1098 gnome_vfs_application_registry_init ();
1100 gnome_vfs_application_registry_clear ();
1101 load_application_info ();
1110 * gnome_vfs_application_registry_exists
1111 * @app_id: an application ID
1113 * This function will return TRUE if there is an entry for @app_id in
1114 * the registry, otherwise FALSE.
1116 * Returns: TRUE if the application is in the registry, FALSE if not
1121 gnome_vfs_application_registry_exists (const char *app_id)
1123 g_return_val_if_fail (app_id != NULL, FALSE);
1127 if (application_lookup (app_id) != NULL)
1135 * Getting arbitrary keys
1145 * FIXME: I have no idea what this function does.
1149 get_keys_foreach(gpointer key, gpointer value, gpointer user_data)
1151 GList **listp = user_data;
1153 /* make sure we only insert unique keys */
1154 if ( (*listp) && strcmp ((const char *) (*listp)->data, (const char *) key) == 0)
1157 (*listp) = g_list_insert_sorted ((*listp), key,
1158 (GCompareFunc) strcmp);
1162 * gnome_vfs_application_registry_get_keys:
1163 * @app_id: the application ID for which to get keys
1165 * This function wil return a list of strings which is the list of
1166 * keys set for @app_id in the application registry.
1168 * Returns: A list of the keys set for @app_id
1173 gnome_vfs_application_registry_get_keys (const char *app_id)
1176 Application *application;
1178 g_return_val_if_fail (app_id != NULL, NULL);
1182 application = application_lookup (app_id);
1183 if (application == NULL)
1188 if (application->keys != NULL)
1189 g_hash_table_foreach (application->keys, get_keys_foreach,
1192 if (application->user_application != NULL &&
1193 application->user_application->keys)
1194 g_hash_table_foreach (application->user_application->keys,
1195 get_keys_foreach, &retval);
1204 * @application: registry application
1207 * Returns: the value associated with the key, or NULL if there is no
1210 * This function looks and returns the value of the target key in the registry
1216 real_peek_value (const Application *application, const char *key)
1220 g_return_val_if_fail (application != NULL, NULL);
1221 g_return_val_if_fail (key != NULL, NULL);
1225 if (application->user_application)
1226 retval = peek_value (application->user_application, key);
1229 retval = peek_value (application, key);
1235 * real_get_bool_value
1237 * application: Application structure
1239 * got_key: actual key stored in application if key exists.
1241 * This function will try to determine whether a key exists in the application.
1242 * It first checks the user applications and then the system applications and
1243 * then returns whether the key exists and what the value is from the value of
1250 real_get_bool_value (const Application *application, const char *key, gboolean *got_key)
1252 gboolean sub_got_key, retval;
1254 g_return_val_if_fail (application != NULL, FALSE);
1255 g_return_val_if_fail (key != NULL, FALSE);
1257 sub_got_key = FALSE;
1259 if (application->user_application)
1260 retval = get_bool_value (application->user_application, key,
1264 retval = get_bool_value (application, key, &sub_got_key);
1266 if (got_key != NULL)
1267 *got_key = sub_got_key;
1274 * gnome_vfs_application_registry_peek_value
1275 * @app_id: the application ID for which to look up a value
1276 * @key: the key to look up
1278 * This will return the value associated with @key for @app_id in the
1279 * application registry. There is no need to free the return value.
1281 * Returns: the value associated with the key, or NULL if there is no
1287 gnome_vfs_application_registry_peek_value (const char *app_id, const char *key)
1289 Application *application;
1291 g_return_val_if_fail (app_id != NULL, NULL);
1292 g_return_val_if_fail (key != NULL, NULL);
1296 application = application_lookup (app_id);
1297 if (application == NULL)
1300 return real_peek_value (application, key);
1304 * gnome_vfs_application_registry_get_bool_value
1305 * @app_id: registry id of the application
1306 * @key: key to look up
1307 * @got_key: TRUE if a setting was dound, otherwise FALSE
1309 * This will look up a key in the structure pointed to by app_id and return the
1310 * boolean value of that key. It will return false if there are no
1311 * applications associated with the app_id.
1313 * Returns: TRUE if @key is set to "true" or "yes" for @app_id, otherwise FALSE
1318 gnome_vfs_application_registry_get_bool_value (const char *app_id, const char *key,
1321 Application *application;
1323 g_return_val_if_fail (app_id != NULL, FALSE);
1324 g_return_val_if_fail (key != NULL, FALSE);
1328 application = application_lookup (app_id);
1329 if (application == NULL)
1332 return real_get_bool_value (application, key, got_key);
1340 * gnome_vfs_application_registry_remove_application
1341 * @app_id: registry id of the application
1343 * Given the registry id this function will remove all applications that has
1344 * been set by the user. You will need to call
1345 * gnome_vfs_application_registry_sync to save the changes.
1350 gnome_vfs_application_registry_remove_application (const char *app_id)
1352 Application *application;
1354 g_return_if_fail (app_id != NULL);
1358 application = application_lookup (app_id);
1359 if (application == NULL)
1362 /* Only remove the user_owned stuff */
1363 if (application->user_owned) {
1364 application_remove (application);
1365 user_file_dirty = TRUE;
1366 } else if (application->user_application != NULL) {
1367 application_remove (application->user_application);
1368 user_file_dirty = TRUE;
1373 * gnome_vfs_application_registry_set_value
1374 * @app_id: registry id of the application
1376 * @value: value to set the target key to
1378 * This function will set values pertaining to registry entry pointed to by
1379 * app_id. You will need to call gnome_vfs_application_registry_sync to
1380 * realize the changes.
1385 gnome_vfs_application_registry_set_value (const char *app_id,
1389 Application *application;
1391 g_return_if_fail (app_id != NULL);
1392 g_return_if_fail (key != NULL);
1393 g_return_if_fail (value != NULL);
1397 application = application_lookup_or_create (app_id, TRUE/*user_owned*/);
1399 set_value (application, key, value);
1401 user_file_dirty = TRUE;
1405 * gnome_vfs_application_registry_set_bool_value:
1406 * @app_id: registry id of the application
1408 * @value: value you want to set the target key to
1410 * This function will modify those registry values that are of type boolean to
1411 * a value specified by the user. You will need to call
1412 * gnome_vfs_application_registry_sync to save your changes.
1416 gnome_vfs_application_registry_set_bool_value (const char *app_id,
1420 Application *application;
1422 g_return_if_fail (app_id != NULL);
1423 g_return_if_fail (key != NULL);
1427 application = application_lookup_or_create (app_id, TRUE/*user_owned*/);
1429 set_bool_value (application, key, value);
1431 user_file_dirty = TRUE;
1435 * gnome_vfs_application_registry_unset_key:
1436 * @app_id: registry id of the application
1439 * This function given the application and the target will wipe the current
1440 * value that the key contains.
1445 gnome_vfs_application_registry_unset_key (const char *app_id,
1448 Application *application;
1450 g_return_if_fail (app_id != NULL);
1451 g_return_if_fail (key != NULL);
1455 application = application_lookup_or_create (app_id, TRUE/*user_owned*/);
1457 unset_key (application, key);
1459 user_file_dirty = TRUE;
1468 cb_application_collect (gpointer key, gpointer value, gpointer user_data)
1470 Application *application = value;
1471 GList **list = user_data;
1472 *list = g_list_prepend (*list, application->app_id);
1476 * gnome_vfs_application_registry_get_applications
1477 * @mime_type: mime type string
1479 * This will return all applications from the registry that are associated with
1480 * the given mime type string, if NULL it returns all applications.
1482 * Returns: a list of the application IDs for all applications which
1483 * support the given mime type.
1488 gnome_vfs_application_registry_get_applications (const char *mime_type)
1490 GList *app_list, *app_list2, *retval, *li;
1498 if (mime_type == NULL) {
1499 g_hash_table_foreach (global_applications, cb_application_collect, &retval);
1503 if (gnome_vfs_mime_type_is_supertype (mime_type)) {
1504 app_list = g_hash_table_lookup (generic_mime_types, mime_type);
1506 app_list = g_hash_table_lookup (specific_mime_types, mime_type);
1508 supertype = gnome_vfs_get_supertype_from_mime_type (mime_type);
1509 if (supertype != NULL) {
1510 app_list2 = g_hash_table_lookup (generic_mime_types, supertype);
1515 for (li = app_list; li != NULL; li = li->next) {
1516 Application *application = li->data;
1517 /* Note that this list is sorted so to kill duplicates
1518 * in app_list we only need to check the first entry */
1519 if (retval == NULL ||
1520 strcmp ((const char *) retval->data, application->app_id) != 0)
1521 retval = g_list_prepend (retval, application->app_id);
1524 for (li = app_list2; li != NULL; li = li->next) {
1525 Application *application = li->data;
1526 if (g_list_find_custom (retval, application->app_id,
1527 (GCompareFunc) strcmp) == NULL)
1528 retval = g_list_prepend (retval, application->app_id);
1535 * gnome_vfs_application_registry_get_mime_types
1536 * @app_id: registry id of application
1538 * This function returns a list of strings that represent the mime
1539 * types that can be handled by an application.
1541 * Returns: a list of the mime types supported
1546 gnome_vfs_application_registry_get_mime_types (const char *app_id)
1548 Application *application;
1551 g_return_val_if_fail (app_id != NULL, NULL);
1555 application = application_lookup (app_id);
1556 if (application == NULL)
1559 retval = g_list_copy (application->mime_types);
1561 /* merge in the mime types from the user_application,
1563 if (application->user_application) {
1565 for (li = application->user_application->mime_types;
1568 Application *application = li->data;
1569 if (g_list_find_custom (retval, application->app_id,
1570 (GCompareFunc) strcmp) == NULL)
1571 retval = g_list_prepend (retval,
1572 application->app_id);
1580 * gnome_vfs_application_registry_supports_uri_scheme
1581 * @app_id: registry id of application
1582 * @uri_scheme: uri schme string
1584 * Given the id of the application this function will determine if the
1585 * uri scheme will given is supported.
1587 * Returns: TRUE if @app_id supports @uri_scheme, otherwise FALSE
1592 gnome_vfs_application_registry_supports_uri_scheme (const char *app_id,
1593 const char *uri_scheme)
1595 Application *application;
1596 gboolean uses_gnomevfs;
1598 g_return_val_if_fail (app_id != NULL, FALSE);
1599 g_return_val_if_fail (uri_scheme != NULL, FALSE);
1603 application = application_lookup (app_id);
1604 if (application == NULL)
1607 uses_gnomevfs = real_get_bool_value (application, GNOME_VFS_APPLICATION_REGISTRY_USES_GNOMEVFS, NULL);
1609 if (strcmp (uri_scheme, "file") == 0 &&
1610 uses_gnomevfs == FALSE &&
1611 application->supported_uri_schemes == NULL &&
1612 application->user_application->supported_uri_schemes == NULL) {
1616 /* check both the application and the user application
1617 * mime_types lists */
1618 /* FIXME: This method does not allow a user to override and remove
1619 uri schemes that an application can handle. Is this an issue? */
1621 if ((g_list_find_custom (application->supported_uri_schemes,
1622 /*glib is const incorrect*/(gpointer)uri_scheme,
1623 (GCompareFunc) strcmp) != NULL) ||
1624 (application->user_application &&
1625 g_list_find_custom (application->user_application->supported_uri_schemes,
1626 /*glib is const incorrect*/(gpointer) uri_scheme,
1627 (GCompareFunc) strcmp) != NULL)) {
1630 /* check in the list of uris supported by gnome-vfs if necessary */
1631 else if (uses_gnomevfs) {
1632 GList *supported_uris;
1635 supported_uris = _gnome_vfs_configuration_get_methods_list();
1636 res = (g_list_find_custom(supported_uris,
1637 /*glib is const incorrect*/(gpointer) uri_scheme,
1638 (GCompareFunc) strcmp) != NULL);
1640 g_list_foreach(supported_uris, (GFunc) g_free, NULL);
1641 g_list_free(supported_uris);
1650 * gnome_vfs_application_registry_supports_mime_type
1651 * @app_id: registry id of application
1652 * @mime_type: mime type string
1654 * Use this function to see if there is an application associated with a given
1655 * mime type. The function will return true or false.
1657 * Returns: TRUE if @app_id supports @mime_type, otherwise FALSE.
1662 gnome_vfs_application_registry_supports_mime_type (const char *app_id,
1663 const char *mime_type)
1665 Application *application;
1667 g_return_val_if_fail (app_id != NULL, FALSE);
1668 g_return_val_if_fail (mime_type != NULL, FALSE);
1672 application = application_lookup (app_id);
1673 if (application == NULL)
1676 /* check both the application and the user application
1677 * mime_types lists */
1678 /* FIXME: This method does not allow a user to override and remove
1679 mime types that an application can handle. Is this an issue? */
1680 if ((g_list_find_custom (application->mime_types,
1681 /*glib is const incorrect*/(gpointer)mime_type,
1682 (GCompareFunc) strcmp) != NULL) ||
1683 (application->user_application &&
1684 g_list_find_custom (application->user_application->mime_types,
1685 /*glib is const incorrect*/(gpointer)mime_type,
1686 (GCompareFunc) strcmp) != NULL))
1694 * Mime type functions
1695 * Note that mime_type can be a specific (image/png) or generic (image/<star>) type
1700 * gnome_vfs_application_registry_clear_mime_types
1701 * @app_id: Application id
1703 * This function will remove the mime types associated with the application.
1704 * Changes are not realized until the gnome_vfs_application_registry_sync
1705 * function is called to save the changes to the file.
1710 gnome_vfs_application_registry_clear_mime_types (const char *app_id)
1712 Application *application;
1714 g_return_if_fail (app_id != NULL);
1718 application = application_lookup_or_create (app_id, TRUE/*user_owned*/);
1720 application_clear_mime_types (application);
1722 user_file_dirty = TRUE;
1726 * gnome_vfs_application_registry_add_mime_type
1727 * @app_id: registry id of application
1728 * @mime_type: mime type string
1730 * This function will associate a mime type with an application given the
1731 * application registry id and the mime type. Changes are not realized until
1732 * the gnome_vfs_application_registry_sync function is called to save the
1733 * changes to the file.
1738 gnome_vfs_application_registry_add_mime_type (const char *app_id,
1739 const char *mime_type)
1741 Application *application;
1743 g_return_if_fail (app_id != NULL);
1744 g_return_if_fail (mime_type != NULL);
1748 application = application_lookup_or_create (app_id, TRUE/*user_owned*/);
1750 add_mime_type_to_application (application, mime_type);
1752 user_file_dirty = TRUE;
1756 * gnome_vfs_application_registry_remove_mime_type
1757 * @app_id: registry id of the application
1758 * @mime_type: mime type string
1760 * This function will de-associate a mime type from an application registry.
1761 * Given the application registry id and the mime type. Changes are not
1762 * realized until the gnome_vfs_application_registry_sync function is called to
1763 * save the changes to the file.
1768 gnome_vfs_application_registry_remove_mime_type (const char *app_id,
1769 const char *mime_type)
1771 Application *application;
1773 g_return_if_fail (app_id != NULL);
1777 application = application_lookup_or_create (app_id, TRUE/*user_owned*/);
1779 remove_mime_type_for_application (application, mime_type);
1781 user_file_dirty = TRUE;
1789 application_sync_foreach (gpointer key, gpointer value, gpointer user_data)
1791 Application *application = value;
1792 FILE *fp = user_data;
1794 /* Only sync things that are user owned */
1795 if (application->user_owned)
1796 application_sync (application, fp);
1797 else if (application->user_application)
1798 application_sync (application->user_application, fp);
1802 * gnome_vfs_application_registry_sync
1804 * This function will sync the registry. Typically you would use this function
1805 * after a modification of the registry. When you modify the registry a dirty
1806 * flag is set. Calling this function will save your modifications to disk and
1809 * If successful, will return GNOME_VFS_OK
1811 * Returns: GnomeVFSResult
1816 gnome_vfs_application_registry_sync (void)
1822 if ( ! user_file_dirty)
1823 return GNOME_VFS_OK;
1827 file = g_strconcat (user_registry_dir.dirname, "/user.applications", NULL);
1828 fp = fopen (file, "w");
1831 g_warning ("Cannot open '%s' for writing", file);
1833 return gnome_vfs_result_from_errno ();
1840 fprintf (fp, "# This file is automatically generated by gnome-vfs "
1841 "application registry\n"
1842 "# Do NOT edit by hand\n# Generated: %s\n",
1845 if (global_applications != NULL)
1846 g_hash_table_foreach (global_applications, application_sync_foreach, fp);
1850 user_file_dirty = FALSE;
1852 return GNOME_VFS_OK;
1857 * gnome_vfs_application_registry_get_mime_application
1858 * @app_id: registry id of the application
1860 * Returns a structure that contains the application that handles
1861 * the mime type associated by the application referred by app_id.
1863 * Returns: GnomeVFSMimeApplication
1867 GnomeVFSMimeApplication *
1868 gnome_vfs_application_registry_get_mime_application (const char *app_id)
1870 Application *i_application;
1871 GnomeVFSMimeApplication *application;
1872 gboolean uses_gnomevfs = FALSE;
1874 g_return_val_if_fail (app_id != NULL, NULL);
1878 i_application = application_lookup (app_id);
1880 if (i_application == NULL)
1883 application = g_new0 (GnomeVFSMimeApplication, 1);
1885 application->id = g_strdup (app_id);
1888 g_strdup (real_peek_value
1890 GNOME_VFS_APPLICATION_REGISTRY_NAME));
1891 application->command =
1892 g_strdup (real_peek_value
1894 GNOME_VFS_APPLICATION_REGISTRY_COMMAND));
1896 application->can_open_multiple_files =
1899 GNOME_VFS_APPLICATION_REGISTRY_CAN_OPEN_MULTIPLE_FILES,
1901 application->expects_uris = i_application->expects_uris;
1902 application->supported_uri_schemes =
1903 supported_uri_scheme_list_copy (i_application->supported_uri_schemes);
1905 application->requires_terminal =
1908 GNOME_VFS_APPLICATION_REGISTRY_REQUIRES_TERMINAL,
1911 uses_gnomevfs = real_get_bool_value (i_application, GNOME_VFS_APPLICATION_REGISTRY_USES_GNOMEVFS, NULL);
1913 if (uses_gnomevfs) {
1914 GList *methods_list =
1915 _gnome_vfs_configuration_get_methods_list();
1917 if (application->expects_uris == GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_PATHS) {
1918 application->expects_uris = GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_URIS;
1920 for (l = methods_list; l != NULL; l = l->next) {
1921 if (g_list_find_custom (application->supported_uri_schemes,
1922 /*glib is const incorrect*/(gpointer) l->data,
1923 (GCompareFunc) strcmp) == NULL) {
1924 application->supported_uri_schemes =
1925 g_list_prepend(application->supported_uri_schemes,
1931 g_list_free(methods_list);
1938 * gnome_vfs_application_registry_save_mime_application
1939 * @application: application associated with the mime type
1941 * This will save to the registry the application that will be associated with
1942 * a defined mime type. The defined mime type is located within the
1943 * GnomeVFSMimeApplication structure. Changes are not realized until the
1944 * gnome_vfs_application_registry_sync function is called.
1949 gnome_vfs_application_registry_save_mime_application (const GnomeVFSMimeApplication *application)
1951 Application *i_application;
1953 g_return_if_fail (application != NULL);
1955 /* make us a new user application */
1956 i_application = application_lookup_or_create (application->id, TRUE);
1958 application_ref (i_application);
1960 set_value (i_application, GNOME_VFS_APPLICATION_REGISTRY_NAME,
1962 set_value (i_application, GNOME_VFS_APPLICATION_REGISTRY_COMMAND,
1963 application->command);
1964 set_bool_value (i_application, GNOME_VFS_APPLICATION_REGISTRY_CAN_OPEN_MULTIPLE_FILES,
1965 application->can_open_multiple_files);
1966 i_application->expects_uris = application->expects_uris;
1967 set_bool_value (i_application, GNOME_VFS_APPLICATION_REGISTRY_REQUIRES_TERMINAL,
1968 application->requires_terminal);
1969 /* FIXME: Need to save supported_uri_schemes information */
1970 user_file_dirty = TRUE;
1974 * gnome_vfs_application_is_user_owned_application
1975 * @application: data structure of the mime application
1977 * This function will determine if a mime application is user owned or not. By
1978 * user ownered this means that the application is not a system application
1979 * located in the prerequisite /usr area but rather in the user's area.
1985 gnome_vfs_application_is_user_owned_application (const GnomeVFSMimeApplication *application)
1987 Application *i_application;
1989 g_return_val_if_fail (application != NULL, FALSE);
1991 /* make us a new user application */
1992 i_application = g_hash_table_lookup (global_applications, application->id);
1993 if (i_application != NULL) {
1994 return i_application->user_owned;