From 68ff71a0cbf9c11a9be8878146bf485be9bd8f87 Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Mon, 15 Oct 2007 13:39:07 +0000 Subject: Split part of the sugar library to sugar-base --- (limited to 'lib/xdgmimemagic.c') diff --git a/lib/xdgmimemagic.c b/lib/xdgmimemagic.c deleted file mode 100644 index 6088edb..0000000 --- a/lib/xdgmimemagic.c +++ /dev/null @@ -1,807 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ -/* xdgmimemagic.: Private file. Datastructure for storing magic files. - * - * More info can be found at http://www.freedesktop.org/standards/ - * - * Copyright (C) 2003 Red Hat, Inc. - * Copyright (C) 2003 Jonathan Blandford - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "xdgmimemagic.h" -#include "xdgmimeint.h" -#include -#include -#include -#include -#include -#include - -#ifndef FALSE -#define FALSE (0) -#endif - -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -#if !defined getc_unlocked && !defined HAVE_GETC_UNLOCKED -# define getc_unlocked(fp) getc (fp) -#endif - -typedef struct XdgMimeMagicMatch XdgMimeMagicMatch; -typedef struct XdgMimeMagicMatchlet XdgMimeMagicMatchlet; - -typedef enum -{ - XDG_MIME_MAGIC_SECTION, - XDG_MIME_MAGIC_MAGIC, - XDG_MIME_MAGIC_ERROR, - XDG_MIME_MAGIC_EOF -} XdgMimeMagicState; - -struct XdgMimeMagicMatch -{ - const char *mime_type; - int priority; - XdgMimeMagicMatchlet *matchlet; - XdgMimeMagicMatch *next; -}; - - -struct XdgMimeMagicMatchlet -{ - int indent; - int offset; - unsigned int value_length; - unsigned char *value; - unsigned char *mask; - unsigned int range_length; - unsigned int word_size; - XdgMimeMagicMatchlet *next; -}; - - -struct XdgMimeMagic -{ - XdgMimeMagicMatch *match_list; - int max_extent; -}; - -static XdgMimeMagicMatch * -_xdg_mime_magic_match_new (void) -{ - return calloc (1, sizeof (XdgMimeMagicMatch)); -} - - -static XdgMimeMagicMatchlet * -_xdg_mime_magic_matchlet_new (void) -{ - XdgMimeMagicMatchlet *matchlet; - - matchlet = malloc (sizeof (XdgMimeMagicMatchlet)); - - matchlet->indent = 0; - matchlet->offset = 0; - matchlet->value_length = 0; - matchlet->value = NULL; - matchlet->mask = NULL; - matchlet->range_length = 1; - matchlet->word_size = 1; - matchlet->next = NULL; - - return matchlet; -} - - -static void -_xdg_mime_magic_matchlet_free (XdgMimeMagicMatchlet *mime_magic_matchlet) -{ - if (mime_magic_matchlet) - { - if (mime_magic_matchlet->next) - _xdg_mime_magic_matchlet_free (mime_magic_matchlet->next); - if (mime_magic_matchlet->value) - free (mime_magic_matchlet->value); - if (mime_magic_matchlet->mask) - free (mime_magic_matchlet->mask); - free (mime_magic_matchlet); - } -} - - -/* Frees mime_magic_match and the remainder of its list - */ -static void -_xdg_mime_magic_match_free (XdgMimeMagicMatch *mime_magic_match) -{ - XdgMimeMagicMatch *ptr, *next; - - ptr = mime_magic_match; - while (ptr) - { - next = ptr->next; - - if (ptr->mime_type) - free ((void *) ptr->mime_type); - if (ptr->matchlet) - _xdg_mime_magic_matchlet_free (ptr->matchlet); - free (ptr); - - ptr = next; - } -} - -/* Reads in a hunk of data until a newline character or a '\000' is hit. The - * returned string is null terminated, and doesn't include the newline. - */ -static unsigned char * -_xdg_mime_magic_read_to_newline (FILE *magic_file, - int *end_of_file) -{ - unsigned char *retval; - int c; - int len, pos; - - len = 128; - pos = 0; - retval = malloc (len); - *end_of_file = FALSE; - - while (TRUE) - { - c = getc_unlocked (magic_file); - if (c == EOF) - { - *end_of_file = TRUE; - break; - } - if (c == '\n' || c == '\000') - break; - retval[pos++] = (unsigned char) c; - if (pos % 128 == 127) - { - len = len + 128; - retval = realloc (retval, len); - } - } - - retval[pos] = '\000'; - return retval; -} - -/* Returns the number read from the file, or -1 if no number could be read. - */ -static int -_xdg_mime_magic_read_a_number (FILE *magic_file, - int *end_of_file) -{ - /* LONG_MAX is about 20 characters on my system */ -#define MAX_NUMBER_SIZE 30 - char number_string[MAX_NUMBER_SIZE + 1]; - int pos = 0; - int c; - long retval = -1; - - while (TRUE) - { - c = getc_unlocked (magic_file); - - if (c == EOF) - { - *end_of_file = TRUE; - break; - } - if (! isdigit (c)) - { - ungetc (c, magic_file); - break; - } - number_string[pos] = (char) c; - pos++; - if (pos == MAX_NUMBER_SIZE) - break; - } - if (pos > 0) - { - number_string[pos] = '\000'; - errno = 0; - retval = strtol (number_string, NULL, 10); - - if ((retval < INT_MIN) || (retval > INT_MAX) || (errno != 0)) - return -1; - } - - return retval; -} - -/* Headers are of the format: - * [:] - */ -static XdgMimeMagicState -_xdg_mime_magic_parse_header (FILE *magic_file, XdgMimeMagicMatch *match) -{ - int c; - char *buffer; - char *end_ptr; - int end_of_file = 0; - - assert (magic_file != NULL); - assert (match != NULL); - - c = getc_unlocked (magic_file); - if (c == EOF) - return XDG_MIME_MAGIC_EOF; - if (c != '[') - return XDG_MIME_MAGIC_ERROR; - - match->priority = _xdg_mime_magic_read_a_number (magic_file, &end_of_file); - if (end_of_file) - return XDG_MIME_MAGIC_EOF; - if (match->priority == -1) - return XDG_MIME_MAGIC_ERROR; - - c = getc_unlocked (magic_file); - if (c == EOF) - return XDG_MIME_MAGIC_EOF; - if (c != ':') - return XDG_MIME_MAGIC_ERROR; - - buffer = (char *)_xdg_mime_magic_read_to_newline (magic_file, &end_of_file); - if (end_of_file) - return XDG_MIME_MAGIC_EOF; - - end_ptr = buffer; - while (*end_ptr != ']' && *end_ptr != '\000' && *end_ptr != '\n') - end_ptr++; - if (*end_ptr != ']') - { - free (buffer); - return XDG_MIME_MAGIC_ERROR; - } - *end_ptr = '\000'; - - match->mime_type = strdup (buffer); - free (buffer); - - return XDG_MIME_MAGIC_MAGIC; -} - -static XdgMimeMagicState -_xdg_mime_magic_parse_error (FILE *magic_file) -{ - int c; - - while (1) - { - c = getc_unlocked (magic_file); - if (c == EOF) - return XDG_MIME_MAGIC_EOF; - if (c == '\n') - return XDG_MIME_MAGIC_SECTION; - } -} - -/* Headers are of the format: - * [ indent ] ">" start-offset "=" value - * [ "&" mask ] [ "~" word-size ] [ "+" range-length ] "\n" - */ -static XdgMimeMagicState -_xdg_mime_magic_parse_magic_line (FILE *magic_file, - XdgMimeMagicMatch *match) -{ - XdgMimeMagicMatchlet *matchlet; - int c; - int end_of_file; - int indent = 0; - int bytes_read; - - assert (magic_file != NULL); - - /* Sniff the buffer to make sure it's a valid line */ - c = getc_unlocked (magic_file); - if (c == EOF) - return XDG_MIME_MAGIC_EOF; - else if (c == '[') - { - ungetc (c, magic_file); - return XDG_MIME_MAGIC_SECTION; - } - else if (c == '\n') - return XDG_MIME_MAGIC_MAGIC; - - /* At this point, it must be a digit or a '>' */ - end_of_file = FALSE; - if (isdigit (c)) - { - ungetc (c, magic_file); - indent = _xdg_mime_magic_read_a_number (magic_file, &end_of_file); - if (end_of_file) - return XDG_MIME_MAGIC_EOF; - if (indent == -1) - return XDG_MIME_MAGIC_ERROR; - c = getc_unlocked (magic_file); - if (c == EOF) - return XDG_MIME_MAGIC_EOF; - } - - if (c != '>') - return XDG_MIME_MAGIC_ERROR; - - matchlet = _xdg_mime_magic_matchlet_new (); - matchlet->indent = indent; - matchlet->offset = _xdg_mime_magic_read_a_number (magic_file, &end_of_file); - if (end_of_file) - { - _xdg_mime_magic_matchlet_free (matchlet); - return XDG_MIME_MAGIC_EOF; - } - if (matchlet->offset == -1) - { - _xdg_mime_magic_matchlet_free (matchlet); - return XDG_MIME_MAGIC_ERROR; - } - c = getc_unlocked (magic_file); - if (c == EOF) - { - _xdg_mime_magic_matchlet_free (matchlet); - return XDG_MIME_MAGIC_EOF; - } - else if (c != '=') - { - _xdg_mime_magic_matchlet_free (matchlet); - return XDG_MIME_MAGIC_ERROR; - } - - /* Next two bytes determine how long the value is */ - matchlet->value_length = 0; - c = getc_unlocked (magic_file); - if (c == EOF) - { - _xdg_mime_magic_matchlet_free (matchlet); - return XDG_MIME_MAGIC_EOF; - } - matchlet->value_length = c & 0xFF; - matchlet->value_length = matchlet->value_length << 8; - - c = getc_unlocked (magic_file); - if (c == EOF) - { - _xdg_mime_magic_matchlet_free (matchlet); - return XDG_MIME_MAGIC_EOF; - } - matchlet->value_length = matchlet->value_length + (c & 0xFF); - - matchlet->value = malloc (matchlet->value_length); - - /* OOM */ - if (matchlet->value == NULL) - { - _xdg_mime_magic_matchlet_free (matchlet); - return XDG_MIME_MAGIC_ERROR; - } - bytes_read = fread (matchlet->value, 1, matchlet->value_length, magic_file); - if (bytes_read != matchlet->value_length) - { - _xdg_mime_magic_matchlet_free (matchlet); - if (feof (magic_file)) - return XDG_MIME_MAGIC_EOF; - else - return XDG_MIME_MAGIC_ERROR; - } - - c = getc_unlocked (magic_file); - if (c == '&') - { - matchlet->mask = malloc (matchlet->value_length); - /* OOM */ - if (matchlet->mask == NULL) - { - _xdg_mime_magic_matchlet_free (matchlet); - return XDG_MIME_MAGIC_ERROR; - } - bytes_read = fread (matchlet->mask, 1, matchlet->value_length, magic_file); - if (bytes_read != matchlet->value_length) - { - _xdg_mime_magic_matchlet_free (matchlet); - if (feof (magic_file)) - return XDG_MIME_MAGIC_EOF; - else - return XDG_MIME_MAGIC_ERROR; - } - c = getc_unlocked (magic_file); - } - - if (c == '~') - { - matchlet->word_size = _xdg_mime_magic_read_a_number (magic_file, &end_of_file); - if (end_of_file) - { - _xdg_mime_magic_matchlet_free (matchlet); - return XDG_MIME_MAGIC_EOF; - } - if (matchlet->word_size != 0 && - matchlet->word_size != 1 && - matchlet->word_size != 2 && - matchlet->word_size != 4) - { - _xdg_mime_magic_matchlet_free (matchlet); - return XDG_MIME_MAGIC_ERROR; - } - c = getc_unlocked (magic_file); - } - - if (c == '+') - { - matchlet->range_length = _xdg_mime_magic_read_a_number (magic_file, &end_of_file); - if (end_of_file) - { - _xdg_mime_magic_matchlet_free (matchlet); - return XDG_MIME_MAGIC_EOF; - } - if (matchlet->range_length == -1) - { - _xdg_mime_magic_matchlet_free (matchlet); - return XDG_MIME_MAGIC_ERROR; - } - c = getc_unlocked (magic_file); - } - - - if (c == '\n') - { - /* We clean up the matchlet, byte swapping if needed */ - if (matchlet->word_size > 1) - { - int i; - if (matchlet->value_length % matchlet->word_size != 0) - { - _xdg_mime_magic_matchlet_free (matchlet); - return XDG_MIME_MAGIC_ERROR; - } - /* FIXME: need to get this defined in a style file */ -#if LITTLE_ENDIAN - for (i = 0; i < matchlet->value_length; i = i + matchlet->word_size) - { - if (matchlet->word_size == 2) - *((xdg_uint16_t *) matchlet->value + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->value + i))); - else if (matchlet->word_size == 4) - *((xdg_uint32_t *) matchlet->value + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->value + i))); - if (matchlet->mask) - { - if (matchlet->word_size == 2) - *((xdg_uint16_t *) matchlet->mask + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->mask + i))); - else if (matchlet->word_size == 4) - *((xdg_uint32_t *) matchlet->mask + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->mask + i))); - - } - } -#endif - } - - matchlet->next = match->matchlet; - match->matchlet = matchlet; - - - return XDG_MIME_MAGIC_MAGIC; - } - - _xdg_mime_magic_matchlet_free (matchlet); - if (c == EOF) - return XDG_MIME_MAGIC_EOF; - - return XDG_MIME_MAGIC_ERROR; -} - -static int -_xdg_mime_magic_matchlet_compare_to_data (XdgMimeMagicMatchlet *matchlet, - const void *data, - size_t len) -{ - int i, j; - for (i = matchlet->offset; i < matchlet->offset + matchlet->range_length; i++) - { - int valid_matchlet = TRUE; - - if (i + matchlet->value_length > len) - return FALSE; - - if (matchlet->mask) - { - for (j = 0; j < matchlet->value_length; j++) - { - if ((matchlet->value[j] & matchlet->mask[j]) != - ((((unsigned char *) data)[j + i]) & matchlet->mask[j])) - { - valid_matchlet = FALSE; - break; - } - } - } - else - { - for (j = 0; j < matchlet->value_length; j++) - { - if (matchlet->value[j] != ((unsigned char *) data)[j + i]) - { - valid_matchlet = FALSE; - break; - } - } - } - if (valid_matchlet) - return TRUE; - } - return FALSE; -} - -static int -_xdg_mime_magic_matchlet_compare_level (XdgMimeMagicMatchlet *matchlet, - const void *data, - size_t len, - int indent) -{ - while ((matchlet != NULL) && (matchlet->indent == indent)) - { - if (_xdg_mime_magic_matchlet_compare_to_data (matchlet, data, len)) - { - if ((matchlet->next == NULL) || - (matchlet->next->indent <= indent)) - return TRUE; - - if (_xdg_mime_magic_matchlet_compare_level (matchlet->next, - data, - len, - indent + 1)) - return TRUE; - } - - do - { - matchlet = matchlet->next; - } - while (matchlet && matchlet->indent > indent); - } - - return FALSE; -} - -static int -_xdg_mime_magic_match_compare_to_data (XdgMimeMagicMatch *match, - const void *data, - size_t len) -{ - return _xdg_mime_magic_matchlet_compare_level (match->matchlet, data, len, 0); -} - -static void -_xdg_mime_magic_insert_match (XdgMimeMagic *mime_magic, - XdgMimeMagicMatch *match) -{ - XdgMimeMagicMatch *list; - - if (mime_magic->match_list == NULL) - { - mime_magic->match_list = match; - return; - } - - if (match->priority > mime_magic->match_list->priority) - { - match->next = mime_magic->match_list; - mime_magic->match_list = match; - return; - } - - list = mime_magic->match_list; - while (list->next != NULL) - { - if (list->next->priority < match->priority) - { - match->next = list->next; - list->next = match; - return; - } - list = list->next; - } - list->next = match; - match->next = NULL; -} - -XdgMimeMagic * -_xdg_mime_magic_new (void) -{ - return calloc (1, sizeof (XdgMimeMagic)); -} - -void -_xdg_mime_magic_free (XdgMimeMagic *mime_magic) -{ - if (mime_magic) { - _xdg_mime_magic_match_free (mime_magic->match_list); - free (mime_magic); - } -} - -int -_xdg_mime_magic_get_buffer_extents (XdgMimeMagic *mime_magic) -{ - return mime_magic->max_extent; -} - -const char * -_xdg_mime_magic_lookup_data (XdgMimeMagic *mime_magic, - const void *data, - size_t len, - const char *mime_types[], - int n_mime_types) -{ - XdgMimeMagicMatch *match; - const char *mime_type; - int n; - - mime_type = NULL; - for (match = mime_magic->match_list; match; match = match->next) - { - if (_xdg_mime_magic_match_compare_to_data (match, data, len)) - { - if ((mime_type == NULL) || (_xdg_mime_mime_type_subclass (match->mime_type, mime_type))) { - mime_type = match->mime_type; - } - } - else - { - for (n = 0; n < n_mime_types; n++) - { - if (mime_types[n] && - _xdg_mime_mime_type_equal (mime_types[n], match->mime_type)) - mime_types[n] = NULL; - } - } - } - - if (mime_type == NULL) - { - for (n = 0; n < n_mime_types; n++) - { - if (mime_types[n]) - mime_type = mime_types[n]; - } - } - - return mime_type; -} - -static void -_xdg_mime_update_mime_magic_extents (XdgMimeMagic *mime_magic) -{ - XdgMimeMagicMatch *match; - int max_extent = 0; - - for (match = mime_magic->match_list; match; match = match->next) - { - XdgMimeMagicMatchlet *matchlet; - - for (matchlet = match->matchlet; matchlet; matchlet = matchlet->next) - { - int extent; - - extent = matchlet->value_length + matchlet->offset + matchlet->range_length; - if (max_extent < extent) - max_extent = extent; - } - } - - mime_magic->max_extent = max_extent; -} - -static XdgMimeMagicMatchlet * -_xdg_mime_magic_matchlet_mirror (XdgMimeMagicMatchlet *matchlets) -{ - XdgMimeMagicMatchlet *new_list; - XdgMimeMagicMatchlet *tmp; - - if ((matchlets == NULL) || (matchlets->next == NULL)) - return matchlets; - - new_list = NULL; - tmp = matchlets; - while (tmp != NULL) - { - XdgMimeMagicMatchlet *matchlet; - - matchlet = tmp; - tmp = tmp->next; - matchlet->next = new_list; - new_list = matchlet; - } - - return new_list; - -} - -static void -_xdg_mime_magic_read_magic_file (XdgMimeMagic *mime_magic, - FILE *magic_file) -{ - XdgMimeMagicState state; - XdgMimeMagicMatch *match = NULL; /* Quiet compiler */ - - state = XDG_MIME_MAGIC_SECTION; - - while (state != XDG_MIME_MAGIC_EOF) - { - switch (state) - { - case XDG_MIME_MAGIC_SECTION: - match = _xdg_mime_magic_match_new (); - state = _xdg_mime_magic_parse_header (magic_file, match); - if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR) - _xdg_mime_magic_match_free (match); - break; - case XDG_MIME_MAGIC_MAGIC: - state = _xdg_mime_magic_parse_magic_line (magic_file, match); - if (state == XDG_MIME_MAGIC_SECTION || - (state == XDG_MIME_MAGIC_EOF && match->mime_type)) - { - match->matchlet = _xdg_mime_magic_matchlet_mirror (match->matchlet); - _xdg_mime_magic_insert_match (mime_magic, match); - } - else if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR) - _xdg_mime_magic_match_free (match); - break; - case XDG_MIME_MAGIC_ERROR: - state = _xdg_mime_magic_parse_error (magic_file); - break; - case XDG_MIME_MAGIC_EOF: - default: - /* Make the compiler happy */ - assert (0); - } - } - _xdg_mime_update_mime_magic_extents (mime_magic); -} - -void -_xdg_mime_magic_read_from_file (XdgMimeMagic *mime_magic, - const char *file_name) -{ - FILE *magic_file; - char header[12]; - - magic_file = fopen (file_name, "r"); - - if (magic_file == NULL) - return; - - if (fread (header, 1, 12, magic_file) == 12) - { - if (memcmp ("MIME-Magic\0\n", header, 12) == 0) - _xdg_mime_magic_read_magic_file (mime_magic, magic_file); - } - - fclose (magic_file); -} -- cgit v0.9.1