diff options
author | Matthias Clasen <mclasen@redhat.com> | 2004-11-08 19:36:12 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2004-11-08 19:36:12 +0000 |
commit | d0e90e40b1645ed93bf1dfca4f45693489c813e9 (patch) | |
tree | 4d04617969321524b69add824dc8d01f979d9ee1 /gtk/xdgmime | |
parent | 9b86c72c96c97c0904615c0822c0ea6a47a9be7d (diff) | |
download | gtk+-d0e90e40b1645ed93bf1dfca4f45693489c813e9.tar.gz |
Sync from upstream
2004-11-08 Matthias Clasen <mclasen@redhat.com>
* Sync from upstream
Diffstat (limited to 'gtk/xdgmime')
-rw-r--r-- | gtk/xdgmime/ChangeLog | 4 | ||||
-rw-r--r-- | gtk/xdgmime/Makefile.am | 6 | ||||
-rw-r--r-- | gtk/xdgmime/test-mime.c | 95 | ||||
-rw-r--r-- | gtk/xdgmime/xdgmime.c | 565 | ||||
-rw-r--r-- | gtk/xdgmime/xdgmime.h | 21 | ||||
-rw-r--r-- | gtk/xdgmime/xdgmimealias.c | 177 | ||||
-rw-r--r-- | gtk/xdgmime/xdgmimealias.h | 50 | ||||
-rw-r--r-- | gtk/xdgmime/xdgmimeglob.c | 2 | ||||
-rw-r--r-- | gtk/xdgmime/xdgmimeint.h | 11 | ||||
-rw-r--r-- | gtk/xdgmime/xdgmimemagic.c | 4 | ||||
-rw-r--r-- | gtk/xdgmime/xdgmimeparent.c | 211 | ||||
-rw-r--r-- | gtk/xdgmime/xdgmimeparent.h | 50 |
12 files changed, 1096 insertions, 100 deletions
diff --git a/gtk/xdgmime/ChangeLog b/gtk/xdgmime/ChangeLog index fb859e6272..d5fa32368f 100644 --- a/gtk/xdgmime/ChangeLog +++ b/gtk/xdgmime/ChangeLog @@ -1,3 +1,7 @@ +2004-11-08 Matthias Clasen <mclasen@redhat.com> + + * Sync from upstream + 2004-10-27 Matthias Clasen <mclasen@redhat.com> * === Released 2.5.4 === diff --git a/gtk/xdgmime/Makefile.am b/gtk/xdgmime/Makefile.am index 488c9e3fdc..d51af89bc7 100644 --- a/gtk/xdgmime/Makefile.am +++ b/gtk/xdgmime/Makefile.am @@ -5,12 +5,16 @@ noinst_LTLIBRARIES = libxdgmime.la libxdgmime_la_SOURCES = \ xdgmime.c \ xdgmime.h \ + xdgmimealias.c \ + xdgmimealias.h \ xdgmimeglob.c \ xdgmimeglob.h \ xdgmimeint.c \ xdgmimeint.h \ xdgmimemagic.c \ - xdgmimemagic.h + xdgmimemagic.h \ + xdgmimeparent.c \ + xdgmimeparent.h noinst_PROGRAMS = test-mime diff --git a/gtk/xdgmime/test-mime.c b/gtk/xdgmime/test-mime.c index 7a669c9b11..b0bcc875fe 100644 --- a/gtk/xdgmime/test-mime.c +++ b/gtk/xdgmime/test-mime.c @@ -1,31 +1,3 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ -/* test-mime.c: Test program for mime type identification - * - * More info can be found at http://www.freedesktop.org/standards/ - * - * Copyright (C) 2003 Red Hat, Inc. - * Copyright (C) 2003 Jonathan Blandford <jrb@alum.mit.edu> - * - * Licensed under the Academic Free License version 2.0 - * Or under the following terms: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <config.h> #include "xdgmime.h" #include "xdgmimeglob.h" #include <string.h> @@ -61,6 +33,67 @@ test_glob_type (void) test_individual_glob ("tree.[ch]", XDG_GLOB_FULL); } +static void +test_alias (const char *mime_a, + const char *mime_b, + int expected) +{ + int actual; + + actual = xdg_mime_mime_type_equal (mime_a, mime_b); + + if (actual != expected) + { + printf ("Test Failed: %s is %s to %s\n", + mime_a, actual ? "equal" : "not equal", mime_b); + } +} + +static void +test_aliasing (void) +{ + test_alias ("application/wordperfect", "application/vnd.wordperfect", 1); + test_alias ("application/x-gnome-app-info", "application/x-desktop", 1); + test_alias ("application/x-wordperfect", "application/vnd.wordperfect", 1); + test_alias ("application/x-wordperfect", "audio/x-midi", 0); + test_alias ("/", "vnd/vnd", 0); + test_alias ("application/octet-stream", "text/plain", 0); + test_alias ("text/plain", "text/*", 0); +} + +static void +test_subclass (const char *mime_a, + const char *mime_b, + int expected) +{ + int actual; + + actual = xdg_mime_mime_type_subclass (mime_a, mime_b); + + if (actual != expected) + { + printf ("Test Failed: %s is %s of %s\n", + mime_a, actual ? "subclass" : "not subclass", mime_b); + } +} + +static void +test_subclassing (void) +{ + test_subclass ("application/rtf", "text/plain", 1); + test_subclass ("message/news", "text/plain", 1); + test_subclass ("message/news", "message/*", 1); + test_subclass ("message/news", "text/*", 1); + test_subclass ("message/news", "application/octet-stream", 1); + test_subclass ("application/rtf", "application/octet-stream", 1); + test_subclass ("application/x-gnome-app-info", "text/plain", 1); + test_subclass ("image/x-djvu", "image/vnd.djvu", 1); + test_subclass ("image/vnd.djvu", "image/x-djvu", 1); + test_subclass ("image/vnd.djvu", "text/plain", 0); + test_subclass ("image/vnd.djvu", "text/*", 0); + test_subclass ("text/*", "text/plain", 0); +} + int main (int argc, char *argv[]) { @@ -69,6 +102,9 @@ main (int argc, char *argv[]) int i; test_glob_type (); + test_aliasing (); + test_subclassing (); + for (i = 1; i < argc; i++) { file_name = argv[i]; @@ -76,6 +112,9 @@ main (int argc, char *argv[]) printf ("File \"%s\" has a mime-type of %s\n", file_name, result); } +#if 0 + xdg_mime_dump (); +#endif return 0; } diff --git a/gtk/xdgmime/xdgmime.c b/gtk/xdgmime/xdgmime.c index 2101288277..df618b2798 100644 --- a/gtk/xdgmime/xdgmime.c +++ b/gtk/xdgmime/xdgmime.c @@ -3,8 +3,8 @@ * * More info can be found at http://www.freedesktop.org/standards/ * - * Copyright (C) 2003 Red Hat, Inc. - * Copyright (C) 2003 Jonathan Blandford <jrb@alum.mit.edu> + * Copyright (C) 2003,2004 Red Hat, Inc. + * Copyright (C) 2003,2004 Jonathan Blandford <jrb@alum.mit.edu> * * Licensed under the Academic Free License version 2.0 * Or under the following terms: @@ -30,107 +30,357 @@ #include "xdgmimeint.h" #include "xdgmimeglob.h" #include "xdgmimemagic.h" +#include "xdgmimealias.h" +#include "xdgmimeparent.h" #include <stdio.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> +#include <sys/time.h> #include <unistd.h> +#include <assert.h> + +typedef struct XdgDirTimeList XdgDirTimeList; +typedef struct XdgCallbackList XdgCallbackList; + +static int need_reread = TRUE; +static time_t last_stat_time = 0; -static int initted = 0; static XdgGlobHash *global_hash = NULL; static XdgMimeMagic *global_magic = NULL; +static XdgAliasList *alias_list = NULL; +static XdgParentList *parent_list = NULL; +static XdgDirTimeList *dir_time_list = NULL; +static XdgCallbackList *callback_list = NULL; const char *xdg_mime_type_unknown = "application/octet-stream"; + +enum +{ + XDG_CHECKED_UNCHECKED, + XDG_CHECKED_VALID, + XDG_CHECKED_INVALID +}; + +struct XdgDirTimeList +{ + time_t mtime; + char *directory_name; + int checked; + XdgDirTimeList *next; +}; + +struct XdgCallbackList +{ + XdgCallbackList *next; + XdgCallbackList *prev; + int callback_id; + XdgMimeCallback callback; + void *data; + XdgMimeDestroy destroy; +}; + +/* Function called by xdg_run_command_on_dirs. If it returns TRUE, further + * directories aren't looked at */ +typedef int (*XdgDirectoryFunc) (const char *directory, + void *user_data); + +static XdgDirTimeList * +xdg_dir_time_list_new (void) +{ + XdgDirTimeList *retval; + + retval = calloc (1, sizeof (XdgDirTimeList)); + retval->checked = XDG_CHECKED_UNCHECKED; + + return retval; +} + static void -_xdg_mime_init_from_directory (const char *directory) +xdg_dir_time_list_free (XdgDirTimeList *list) +{ + XdgDirTimeList *next; + + while (list) + { + next = list->next; + free (list->directory_name); + free (list); + list = next; + } +} + +static int +xdg_mime_init_from_directory (const char *directory) { char *file_name; + struct stat st; + XdgDirTimeList *list; + + assert (directory != NULL); file_name = malloc (strlen (directory) + strlen ("/mime/globs") + 1); - strcpy (file_name, directory); - strcat (file_name, "/mime/globs"); - _xdg_mime_glob_read_from_file (global_hash, file_name); - free (file_name); + strcpy (file_name, directory); strcat (file_name, "/mime/globs"); + if (stat (file_name, &st) == 0) + { + _xdg_mime_glob_read_from_file (global_hash, file_name); + + list = xdg_dir_time_list_new (); + list->directory_name = file_name; + list->mtime = st.st_mtime; + list->next = dir_time_list; + dir_time_list = list; + } + else + { + free (file_name); + } file_name = malloc (strlen (directory) + strlen ("/mime/magic") + 1); - strcpy (file_name, directory); - strcat (file_name, "/mime/magic"); - _xdg_mime_magic_read_from_file (global_magic, file_name); + strcpy (file_name, directory); strcat (file_name, "/mime/magic"); + if (stat (file_name, &st) == 0) + { + _xdg_mime_magic_read_from_file (global_magic, file_name); + + list = xdg_dir_time_list_new (); + list->directory_name = file_name; + list->mtime = st.st_mtime; + list->next = dir_time_list; + dir_time_list = list; + } + else + { + free (file_name); + } + + file_name = malloc (strlen (directory) + strlen ("/mime/aliases") + 1); + strcpy (file_name, directory); strcat (file_name, "/mime/aliases"); + _xdg_mime_alias_read_from_file (alias_list, file_name); + free (file_name); + + file_name = malloc (strlen (directory) + strlen ("/mime/subclasses") + 1); + strcpy (file_name, directory); strcat (file_name, "/mime/subclasses"); + _xdg_mime_parent_read_from_file (parent_list, file_name); free (file_name); + + return FALSE; /* Keep processing */ } +/* Runs a command on all the directories in the search path */ static void -xdg_mime_init (void) +xdg_run_command_on_dirs (XdgDirectoryFunc func, + void *user_data) { - if (initted == 0) + const char *xdg_data_home; + const char *xdg_data_dirs; + const char *ptr; + + xdg_data_home = getenv ("XDG_DATA_HOME"); + if (xdg_data_home) + { + if ((func) (xdg_data_home, user_data)) + return; + } + else { - const char *xdg_data_home; - const char *xdg_data_dirs; - const char *ptr; + const char *home; - global_hash = _xdg_glob_hash_new (); - global_magic = _xdg_mime_magic_new (); + home = getenv ("HOME"); + if (home != NULL) + { + char *guessed_xdg_home; + int stop_processing; + + guessed_xdg_home = malloc (strlen (home) + strlen ("/.local/share/") + 1); + strcpy (guessed_xdg_home, home); + strcat (guessed_xdg_home, "/.local/share/"); + stop_processing = (func) (guessed_xdg_home, user_data); + free (guessed_xdg_home); + + if (stop_processing) + return; + } + } + + xdg_data_dirs = getenv ("XDG_DATA_DIRS"); + if (xdg_data_dirs == NULL) + xdg_data_dirs = "/usr/local/share/:/usr/share/"; + + ptr = xdg_data_dirs; + + while (*ptr != '\000') + { + const char *end_ptr; + char *dir; + int len; + int stop_processing; + + end_ptr = ptr; + while (*end_ptr != ':' && *end_ptr != '\000') + end_ptr ++; - /* We look for globs and magic files based upon the XDG Base Directory - * Specification - */ - xdg_data_home = getenv ("XDG_DATA_HOME"); - if (xdg_data_home) + if (end_ptr == ptr) { - _xdg_mime_init_from_directory (xdg_data_home); + ptr++; + continue; } + + if (*end_ptr == ':') + len = end_ptr - ptr; else - { - const char *home; + len = end_ptr - ptr + 1; + dir = malloc (len + 1); + strncpy (dir, ptr, len); + dir[len] = '\0'; + stop_processing = (func) (dir, user_data); + free (dir); + + if (stop_processing) + return; + + ptr = end_ptr; + } +} - home = getenv ("HOME"); - if (home != NULL) +/* Checks file_path to make sure it has the same mtime as last time it was + * checked. If it has a different mtime, or if the file doesn't exist, it + * returns FALSE. + * + * FIXME: This doesn't protect against permission changes. + */ +static int +xdg_check_file (const char *file_path) +{ + struct stat st; + + /* If the file exists */ + if (stat (file_path, &st) == 0) + { + XdgDirTimeList *list; + + for (list = dir_time_list; list; list = list->next) + { + if (! strcmp (list->directory_name, file_path) && + st.st_mtime == list->mtime) { - char *guessed_xdg_home; + if (list->checked == XDG_CHECKED_UNCHECKED) + list->checked = XDG_CHECKED_VALID; + else if (list->checked == XDG_CHECKED_VALID) + list->checked = XDG_CHECKED_INVALID; - guessed_xdg_home = malloc (strlen (home) + strlen ("/.local/share/") + 1); - strcpy (guessed_xdg_home, home); - strcat (guessed_xdg_home, "/.local/share/"); - _xdg_mime_init_from_directory (guessed_xdg_home); - free (guessed_xdg_home); + return (list->checked != XDG_CHECKED_VALID); } } + return TRUE; + } - xdg_data_dirs = getenv ("XDG_DATA_DIRS"); - if (xdg_data_dirs == NULL) - xdg_data_dirs = "/usr/local/share/:/usr/share/"; + return FALSE; +} - ptr = xdg_data_dirs; +static int +xdg_check_dir (const char *directory, + int *invalid_dir_list) +{ + int invalid; + char *file_name; - while (*ptr != '\000') - { - const char *end_ptr; - char *dir; - int len; + assert (directory != NULL); - end_ptr = ptr; - while (*end_ptr != ':' && *end_ptr != '\000') - end_ptr ++; + /* Check the globs file */ + file_name = malloc (strlen (directory) + strlen ("/mime/globs") + 1); + strcpy (file_name, directory); strcat (file_name, "/mime/globs"); + invalid = xdg_check_file (file_name); + free (file_name); + if (invalid) + { + *invalid_dir_list = TRUE; + return TRUE; + } - if (end_ptr == ptr) - { - ptr++; - continue; - } + /* Check the magic file */ + file_name = malloc (strlen (directory) + strlen ("/mime/magic") + 1); + strcpy (file_name, directory); strcat (file_name, "/mime/magic"); + invalid = xdg_check_file (file_name); + free (file_name); + if (invalid) + { + *invalid_dir_list = TRUE; + return TRUE; + } - if (*end_ptr == ':') - len = end_ptr - ptr; - else - len = end_ptr - ptr + 1; - dir = malloc (len + 1); - strncpy (dir, ptr, len); - dir[len] = '\0'; - _xdg_mime_init_from_directory (dir); - free (dir); - - ptr = end_ptr; - } - initted = 1; + return FALSE; /* Keep processing */ +} + +/* Walks through all the mime files stat()ing them to see if they've changed. + * Returns TRUE if they have. */ +static int +xdg_check_dirs (void) +{ + XdgDirTimeList *list; + int invalid_dir_list = FALSE; + + for (list = dir_time_list; list; list = list->next) + list->checked = XDG_CHECKED_UNCHECKED; + + xdg_run_command_on_dirs ((XdgDirectoryFunc) xdg_check_dir, + &invalid_dir_list); + + if (invalid_dir_list) + return TRUE; + + for (list = dir_time_list; list; list = list->next) + { + if (list->checked != XDG_CHECKED_VALID) + return TRUE; + } + + return FALSE; +} + +/* We want to avoid stat()ing on every single mime call, so we only look for + * newer files every 5 seconds. This will return TRUE if we need to reread the + * mime data from disk. + */ +static int +xdg_check_time_and_dirs (void) +{ + struct timeval tv; + time_t current_time; + int retval = FALSE; + + gettimeofday (&tv, NULL); + current_time = tv.tv_sec; + + if (current_time >= last_stat_time + 5) + { + retval = xdg_check_dirs (); + last_stat_time = current_time; + } + + return retval; +} + +/* Called in every public function. It reloads the hash function if need be. + */ +static void +xdg_mime_init (void) +{ + if (xdg_check_time_and_dirs ()) + { + xdg_mime_shutdown (); + } + + if (need_reread) + { + global_hash = _xdg_glob_hash_new (); + global_magic = _xdg_mime_magic_new (); + alias_list = _xdg_mime_alias_list_new (); + parent_list = _xdg_mime_parent_list_new (); + + xdg_run_command_on_dirs ((XdgDirectoryFunc) xdg_mime_init_from_directory, + NULL); + + need_reread = FALSE; } } @@ -239,17 +489,36 @@ xdg_mime_is_valid_mime_type (const char *mime_type) void xdg_mime_shutdown (void) { + XdgCallbackList *list; + /* FIXME: Need to make this (and the whole library) thread safe */ - if (initted) + if (dir_time_list) + { + xdg_dir_time_list_free (dir_time_list); + dir_time_list = NULL; + } + + if (global_hash) { _xdg_glob_hash_free (global_hash); global_hash = NULL; - + } + if (global_magic) + { _xdg_mime_magic_free (global_magic); global_magic = NULL; + } - initted = 0; + if (alias_list) + { + _xdg_mime_alias_list_free (alias_list); + alias_list = NULL; } + + for (list = callback_list; list; list = list->next) + (list->callback) (list->data); + + need_reread = TRUE; } int @@ -259,3 +528,165 @@ xdg_mime_get_max_buffer_extents (void) return _xdg_mime_magic_get_buffer_extents (global_magic); } + +static const char * +unalias_mime_type (const char *mime_type) +{ + const char *lookup; + + if ((lookup = _xdg_mime_alias_list_lookup (alias_list, mime_type)) != NULL) + return lookup; + + return mime_type; +} + +int +xdg_mime_mime_type_equal (const char *mime_a, + const char *mime_b) +{ + const char *unalias_a, *unalias_b; + + xdg_mime_init (); + + unalias_a = unalias_mime_type (mime_a); + unalias_b = unalias_mime_type (mime_b); + + if (strcmp (unalias_a, unalias_b) == 0) + return 1; + + return 0; +} + +int +xdg_mime_media_type_equal (const char *mime_a, + const char *mime_b) +{ + char *sep; + + xdg_mime_init (); + + sep = strchr (mime_a, '/'); + + if (sep && strncmp (mime_a, mime_b, sep - mime_a + 1) == 0) + return 1; + + return 0; +} + +#if 0 +static int +xdg_mime_is_super_type (const char *mime) +{ + int length; + const char *type; + + length = strlen (mime); + type = &(mime[length - 2]); + + if (strcmp (type, "/*") == 0) + return 1; + + return 0; +} +#endif + +int +xdg_mime_mime_type_subclass (const char *mime, + const char *base) +{ + const char *umime, *ubase; + const char **parents; + + xdg_mime_init (); + + umime = unalias_mime_type (mime); + ubase = unalias_mime_type (base); + + if (strcmp (umime, ubase) == 0) + return 1; + +#if 0 + /* Handle supertypes */ + if (xdg_mime_is_super_type (ubase) && + xdg_mime_media_type_equal (umime, ubase)) + return 1; +#endif + + /* Handle special cases text/plain and application/octet-stream */ + if (strcmp (ubase, "text/plain") == 0 && + strncmp (umime, "text/", 5) == 0) + return 1; + + if (strcmp (ubase, "application/octet-stream") == 0) + return 1; + + parents = _xdg_mime_parent_list_lookup (parent_list, umime); + for (; parents && *parents; parents++) + { + if (xdg_mime_mime_type_subclass (*parents, ubase)) + return 1; + } + + return 0; +} + +void +xdg_mime_dump (void) +{ + printf ("*** ALIASES ***\n\n"); + _xdg_mime_alias_list_dump (alias_list); + printf ("\n*** PARENTS ***\n\n"); + _xdg_mime_parent_list_dump (parent_list); +} + + +/* Registers a function to be called every time the mime database reloads its files + */ +int +xdg_mime_register_reload_callback (XdgMimeCallback callback, + void *data, + XdgMimeDestroy destroy) +{ + XdgCallbackList *list_el; + static int callback_id = 1; + + /* Make a new list element */ + list_el = calloc (1, sizeof (XdgCallbackList)); + list_el->callback_id = callback_id; + list_el->callback = callback; + list_el->data = data; + list_el->destroy = destroy; + list_el->next = callback_list; + if (list_el->next) + list_el->next->prev = list_el; + + callback_list = list_el; + callback_id ++; + + return callback_id - 1; +} + +void +xdg_mime_remove_callback (int callback_id) +{ + XdgCallbackList *list; + + for (list = callback_list; list; list = list->next) + { + if (list->callback_id == callback_id) + { + if (list->next) + list->next = list->prev; + + if (list->prev) + list->prev->next = list->next; + else + callback_list = list->next; + + /* invoke the destroy handler */ + (list->destroy) (list->data); + free (list); + return; + } + } +} diff --git a/gtk/xdgmime/xdgmime.h b/gtk/xdgmime/xdgmime.h index 9d41134465..d58ceb2df6 100644 --- a/gtk/xdgmime/xdgmime.h +++ b/gtk/xdgmime/xdgmime.h @@ -41,15 +41,22 @@ extern "C" { #define _XDG_ENTRY3(prefix,func) prefix##_##func #endif +typedef void (*XdgMimeCallback) (void *user_data); +typedef void (*XdgMimeDestroy) (void *user_data); + #ifdef XDG_PREFIX #define xdg_mime_get_mime_type_for_data XDG_ENTRY(get_mime_type_for_data) #define xdg_mime_get_mime_type_for_file XDG_ENTRY(get_mime_type_for_file) #define xdg_mime_get_mime_type_from_file_name XDG_ENTRY(get_mime_type_from_file_name) #define xdg_mime_is_valid_mime_type XDG_ENTRY(is_valid_mime_type) +#define xdg_mime_mime_type_equal XDG_ENTRY(mime_type_equal) +#define xdg_mime_mime_type_subclass XDG_ENTRY(mime_type_subclass) #define xdg_mime_get_max_buffer_extents XDG_ENTRY(get_max_buffer_extents) -#define xdg_mime_type_unknown XDG_ENTRY(type_unknown) #define xdg_mime_shutdown XDG_ENTRY(shutdown) +#define xdg_mime_register_reload_callback XDG_ENTRY(register_reload_callback) +#define xdg_mime_remove_callback XDG_ENTRY(remove_callback) +#define xdg_mime_type_unknown XDG_ENTRY(type_unknown) #endif extern const char *xdg_mime_type_unknown; @@ -60,9 +67,19 @@ const char *xdg_mime_get_mime_type_for_data (const void *data, const char *xdg_mime_get_mime_type_for_file (const char *file_name); const char *xdg_mime_get_mime_type_from_file_name (const char *file_name); int xdg_mime_is_valid_mime_type (const char *mime_type); +int xdg_mime_mime_type_equal (const char *mime_a, + const char *mime_b); +int xdg_mime_media_type_equal (const char *mime_a, + const char *mime_b); +int xdg_mime_mime_type_subclass (const char *mime_a, + const char *mime_b); int xdg_mime_get_max_buffer_extents (void); void xdg_mime_shutdown (void); - +void xdg_mime_dump (void); +int xdg_mime_register_reload_callback (XdgMimeCallback callback, + void *data, + XdgMimeDestroy destroy); +void xdg_mime_remove_callback (int callback_id); #ifdef __cplusplus } diff --git a/gtk/xdgmime/xdgmimealias.c b/gtk/xdgmime/xdgmimealias.c new file mode 100644 index 0000000000..70ed13a424 --- /dev/null +++ b/gtk/xdgmime/xdgmimealias.c @@ -0,0 +1,177 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* xdgmimealias.c: Private file. Datastructure for storing the aliases. + * + * More info can be found at http://www.freedesktop.org/standards/ + * + * Copyright (C) 2004 Red Hat, Inc. + * Copyright (C) 2004 Matthias Clasen <mclasen@redhat.com> + * + * Licensed under the Academic Free License version 2.0 + * Or under the following terms: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <config.h> +#include "xdgmimealias.h" +#include "xdgmimeint.h" +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <fnmatch.h> + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +typedef struct XdgAlias XdgAlias; + +struct XdgAlias +{ + char *alias; + char *mime_type; +}; + +struct XdgAliasList +{ + struct XdgAlias *aliases; + int n_aliases; +}; + +XdgAliasList * +_xdg_mime_alias_list_new (void) +{ + XdgAliasList *list; + + list = malloc (sizeof (XdgAliasList)); + + list->aliases = NULL; + list->n_aliases = 0; + + return list; +} + +void +_xdg_mime_alias_list_free (XdgAliasList *list) +{ + int i; + + if (list->aliases) + { + for (i = 0; i < list->n_aliases; i++) + { + free (list->aliases[i].alias); + free (list->aliases[i].mime_type); + } + free (list->aliases); + } + free (list); +} + +static int +alias_entry_cmp (const void *v1, const void *v2) +{ + return strcmp (((XdgAlias *)v1)->alias, ((XdgAlias *)v2)->alias); +} + +const char * +_xdg_mime_alias_list_lookup (XdgAliasList *list, + const char *alias) +{ + XdgAlias *entry; + XdgAlias key; + + key.alias = (char *)alias; + key.mime_type = 0; + + entry = bsearch (&key, list->aliases, list->n_aliases, + sizeof (XdgAlias), alias_entry_cmp); + if (entry) + return entry->mime_type; + + return NULL; +} + +void +_xdg_mime_alias_read_from_file (XdgAliasList *list, + const char *file_name) +{ + FILE *file; + char line[255]; + int alloc; + + file = fopen (file_name, "r"); + + if (file == NULL) + return; + + /* FIXME: Not UTF-8 safe. Doesn't work if lines are greater than 255 chars. + * Blah */ + alloc = 16; + list->aliases = malloc (alloc * sizeof (XdgAlias)); + while (fgets (line, 255, file) != NULL) + { + char *sep; + if (line[0] == '#') + continue; + + sep = strchr (line, ' '); + if (sep == NULL) + continue; + *(sep++) = '\000'; + sep[strlen (sep) -1] = '\000'; + if (list->n_aliases == alloc) + { + alloc <<= 1; + list->aliases = realloc (list->aliases, + alloc * sizeof (XdgAlias)); + } + list->aliases[list->n_aliases].alias = strdup (line); + list->aliases[list->n_aliases].mime_type = strdup (sep); + list->n_aliases++; + } + list->aliases = realloc (list->aliases, + list->n_aliases * sizeof (XdgAlias)); + + fclose (file); + + qsort (list->aliases, list->n_aliases, + sizeof (XdgAlias), alias_entry_cmp); +} + + +void +_xdg_mime_alias_list_dump (XdgAliasList *list) +{ + int i; + + if (list->aliases) + { + for (i = 0; i < list->n_aliases; i++) + { + printf ("%s %s\n", + list->aliases[i].alias, + list->aliases[i].mime_type); + } + } +} + + diff --git a/gtk/xdgmime/xdgmimealias.h b/gtk/xdgmime/xdgmimealias.h new file mode 100644 index 0000000000..3df18d6606 --- /dev/null +++ b/gtk/xdgmime/xdgmimealias.h @@ -0,0 +1,50 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* xdgmimealias.h: Private file. Datastructure for storing the aliases. + * + * More info can be found at http://www.freedesktop.org/standards/ + * + * Copyright (C) 2004 Red Hat, Inc. + * Copyright (C) 200 Matthias Clasen <mclasen@redhat.com> + * + * Licensed under the Academic Free License version 2.0 + * Or under the following terms: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __XDG_MIME_ALIAS_H__ +#define __XDG_MIME_ALIAS_H__ + +#include "xdgmime.h" + +typedef struct XdgAliasList XdgAliasList; + +#ifdef XDG_PREFIX +#define _xdg_mime_alias_read_from_file XDG_ENTRY(alias_read_from_file) +#define _xdg_mime_alias_list_new XDG_ENTRY(alias_list_new) +#define _xdg_mime_alias_list_free XDG_ENTRY(alias_list_free) +#define _xdg_mime_alias_list_lookup XDG_ENTRY(alias_list_lookup) +#endif + +void _xdg_mime_alias_read_from_file (XdgAliasList *list, + const char *file_name); +XdgAliasList *_xdg_mime_alias_list_new (void); +void _xdg_mime_alias_list_free (XdgAliasList *list); +const char *_xdg_mime_alias_list_lookup (XdgAliasList *list, + const char *alias); +void _xdg_mime_alias_list_dump (XdgAliasList *list); + +#endif /* __XDG_MIME_ALIAS_H__ */ diff --git a/gtk/xdgmime/xdgmimeglob.c b/gtk/xdgmime/xdgmimeglob.c index 0be281ca77..1960efe2e1 100644 --- a/gtk/xdgmime/xdgmimeglob.c +++ b/gtk/xdgmime/xdgmimeglob.c @@ -348,6 +348,8 @@ _xdg_glob_hash_free_nodes (XdgGlobHashNode *node) _xdg_glob_hash_free_nodes (node->child); if (node->next) _xdg_glob_hash_free_nodes (node->next); + if (node->mime_type) + free ((void *) node->mime_type); free (node); } } diff --git a/gtk/xdgmime/xdgmimeint.h b/gtk/xdgmime/xdgmimeint.h index c0db921a10..64dd3f6418 100644 --- a/gtk/xdgmime/xdgmimeint.h +++ b/gtk/xdgmime/xdgmimeint.h @@ -30,7 +30,16 @@ #include "xdgmime.h" -/* FIXME: Should be configure check */ + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +/* FIXME: Needs to be configure check */ typedef unsigned int xdg_unichar_t; typedef unsigned char xdg_uchar8_t; typedef unsigned short xdg_uint16_t; diff --git a/gtk/xdgmime/xdgmimemagic.c b/gtk/xdgmime/xdgmimemagic.c index d8fb6ba3e6..f9b322e99e 100644 --- a/gtk/xdgmime/xdgmimemagic.c +++ b/gtk/xdgmime/xdgmimemagic.c @@ -636,8 +636,10 @@ _xdg_mime_magic_new (void) void _xdg_mime_magic_free (XdgMimeMagic *mime_magic) { - if (mime_magic) + if (mime_magic) { + _xdg_mime_magic_match_free (mime_magic->match_list); free (mime_magic); + } } int diff --git a/gtk/xdgmime/xdgmimeparent.c b/gtk/xdgmime/xdgmimeparent.c new file mode 100644 index 0000000000..17bf15dc5b --- /dev/null +++ b/gtk/xdgmime/xdgmimeparent.c @@ -0,0 +1,211 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* xdgmimealias.c: Private file. Datastructure for storing the hierarchy. + * + * More info can be found at http://www.freedesktop.org/standards/ + * + * Copyright (C) 2004 Red Hat, Inc. + * Copyright (C) 2004 Matthias Clasen <mclasen@redhat.com> + * + * Licensed under the Academic Free License version 2.0 + * Or under the following terms: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <config.h> +#include "xdgmimeparent.h" +#include "xdgmimeint.h" +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <fnmatch.h> + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +typedef struct XdgMimeParents XdgMimeParents; + +struct XdgMimeParents +{ + char *mime; + char **parents; + int n_parents; +}; + +struct XdgParentList +{ + struct XdgMimeParents *parents; + int n_mimes; +}; + +XdgParentList * +_xdg_mime_parent_list_new (void) +{ + XdgParentList *list; + + list = malloc (sizeof (XdgParentList)); + + list->parents = NULL; + list->n_mimes = 0; + + return list; +} + +void +_xdg_mime_parent_list_free (XdgParentList *list) +{ + int i; + char **p; + + if (list->parents) + { + for (i = 0; i < list->n_mimes; i++) + { + for (p = list->parents[i].parents; *p; p++) + free (*p); + + free (list->parents[i].parents); + free (list->parents[i].mime); + } + free (list->parents); + } + free (list); +} + +static int +parent_entry_cmp (const void *v1, const void *v2) +{ + return strcmp (((XdgMimeParents *)v1)->mime, ((XdgMimeParents *)v2)->mime); +} + +const char ** +_xdg_mime_parent_list_lookup (XdgParentList *list, + const char *mime) +{ + XdgMimeParents *entry; + XdgMimeParents key; + + key.mime = (char *)mime; + key.parents = NULL; + + entry = bsearch (&key, list->parents, list->n_mimes, + sizeof (XdgMimeParents), &parent_entry_cmp); + if (entry) + return (const char **)entry->parents; + + return NULL; +} + +void +_xdg_mime_parent_read_from_file (XdgParentList *list, + const char *file_name) +{ + FILE *file; + char line[255]; + int i, alloc; + XdgMimeParents *entry; + + file = fopen (file_name, "r"); + + if (file == NULL) + return; + + /* FIXME: Not UTF-8 safe. Doesn't work if lines are greater than 255 chars. + * Blah */ + alloc = 16; + list->parents = malloc (alloc * sizeof (XdgMimeParents)); + while (fgets (line, 255, file) != NULL) + { + char *sep; + if (line[0] == '#') + continue; + + sep = strchr (line, ' '); + if (sep == NULL) + continue; + *(sep++) = '\000'; + sep[strlen (sep) -1] = '\000'; + entry = NULL; + for (i = 0; i < list->n_mimes; i++) + { + if (strcmp (list->parents[i].mime, line) == 0) + { + entry = &(list->parents[i]); + break; + } + } + + if (!entry) + { + if (list->n_mimes == alloc) + { + alloc <<= 1; + list->parents = realloc (list->parents, + alloc * sizeof (XdgMimeParents)); + } + list->parents[list->n_mimes].mime = strdup (line); + entry = &(list->parents[list->n_mimes]); + list->n_mimes++; + } + + if (!entry->parents) + { + entry->n_parents = 1; + entry->parents = malloc ((entry->n_parents + 1) * sizeof (char *)); + } + else + { + entry->n_parents += 1; + entry->parents = realloc (entry->parents, + (entry->n_parents + 2) * sizeof (char *)); + } + entry->parents[entry->n_parents - 1] = strdup (sep); + entry->parents[entry->n_parents] = NULL; + } + + list->parents = realloc (list->parents, + list->n_mimes * sizeof (XdgMimeParents)); + + fclose (file); + + qsort (list->parents, list->n_mimes, + sizeof (XdgMimeParents), &parent_entry_cmp); +} + + +void +_xdg_mime_parent_list_dump (XdgParentList *list) +{ + int i; + char **p; + + if (list->parents) + { + for (i = 0; i < list->n_mimes; i++) + { + for (p = list->parents[i].parents; *p; p++) + printf ("%s %s\n", list->parents[i].mime, *p); + } + } +} + + diff --git a/gtk/xdgmime/xdgmimeparent.h b/gtk/xdgmime/xdgmimeparent.h new file mode 100644 index 0000000000..da29452cb8 --- /dev/null +++ b/gtk/xdgmime/xdgmimeparent.h @@ -0,0 +1,50 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* xdgmimeparent.h: Private file. Datastructure for storing the hierarchy. + * + * More info can be found at http://www.freedesktop.org/standards/ + * + * Copyright (C) 2004 Red Hat, Inc. + * Copyright (C) 200 Matthias Clasen <mclasen@redhat.com> + * + * Licensed under the Academic Free License version 2.0 + * Or under the following terms: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __XDG_MIME_PARENT_H__ +#define __XDG_MIME_PARENT_H__ + +#include "xdgmime.h" + +typedef struct XdgParentList XdgParentList; + +#ifdef XDG_PREFIX +#define _xdg_mime_parent_read_from_file XDG_ENTRY(parent_read_from_file) +#define _xdg_mime_parent_list_new XDG_ENTRY(parent_list_new) +#define _xdg_mime_parent_list_free XDG_ENTRY(parent_list_free) +#define _xdg_mime_parent_list_lookup XDG_ENTRY(parent_list_lookup) +#endif + +void _xdg_mime_parent_read_from_file (XdgParentList *list, + const char *file_name); +XdgParentList *_xdg_mime_parent_list_new (void); +void _xdg_mime_parent_list_free (XdgParentList *list); +const char **_xdg_mime_parent_list_lookup (XdgParentList *list, + const char *mime); +void _xdg_mime_parent_list_dump (XdgParentList *list); + +#endif /* __XDG_MIME_PARENT_H__ */ |