Sync from upstream

2004-11-08  Matthias Clasen  <mclasen@redhat.com>

	* Sync from upstream
This commit is contained in:
Matthias Clasen 2004-11-08 19:36:12 +00:00 committed by Matthias Clasen
parent 9b86c72c96
commit d0e90e40b1
12 changed files with 1112 additions and 116 deletions

View File

@ -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 ===

View File

@ -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

View File

@ -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;
}

View File

@ -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";
static void
_xdg_mime_init_from_directory (const char *directory)
enum
{
char *file_name;
XDG_CHECKED_UNCHECKED,
XDG_CHECKED_VALID,
XDG_CHECKED_INVALID
};
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);
struct XdgDirTimeList
{
time_t mtime;
char *directory_name;
int checked;
XdgDirTimeList *next;
};
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);
free (file_name);
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_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");
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");
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_run_command_on_dirs (XdgDirectoryFunc func,
void *user_data)
{
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 *home;
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 ++;
if (end_ptr == ptr)
{
ptr++;
continue;
}
if (*end_ptr == ':')
len = end_ptr - ptr;
else
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;
}
}
/* 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)
{
if (list->checked == XDG_CHECKED_UNCHECKED)
list->checked = XDG_CHECKED_VALID;
else if (list->checked == XDG_CHECKED_VALID)
list->checked = XDG_CHECKED_INVALID;
return (list->checked != XDG_CHECKED_VALID);
}
}
return TRUE;
}
return FALSE;
}
static int
xdg_check_dir (const char *directory,
int *invalid_dir_list)
{
int invalid;
char *file_name;
assert (directory != NULL);
/* 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;
}
/* 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;
}
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 (initted == 0)
if (xdg_check_time_and_dirs ())
{
const char *xdg_data_home;
const char *xdg_data_dirs;
const char *ptr;
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 ();
/* 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)
{
_xdg_mime_init_from_directory (xdg_data_home);
}
else
{
const char *home;
xdg_run_command_on_dirs ((XdgDirectoryFunc) xdg_mime_init_from_directory,
NULL);
home = getenv ("HOME");
if (home != NULL)
{
char *guessed_xdg_home;
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);
}
}
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;
end_ptr = ptr;
while (*end_ptr != ':' && *end_ptr != '\000')
end_ptr ++;
if (end_ptr == ptr)
{
ptr++;
continue;
}
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;
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;
}
}
}

View File

@ -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
}

177
gtk/xdgmime/xdgmimealias.c Normal file
View File

@ -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);
}
}
}

View File

@ -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__ */

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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

211
gtk/xdgmime/xdgmimeparent.c Normal file
View File

@ -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);
}
}
}

View File

@ -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__ */