Index: update-mime-database.c =================================================================== RCS file: /cvs/mime/shared-mime-info/update-mime-database.c,v retrieving revision 1.30 diff -u -p -r1.30 update-mime-database.c --- update-mime-database.c 13 Oct 2003 09:43:38 -0000 1.30 +++ update-mime-database.c 12 Sep 2004 17:13:31 -0000 @@ -94,6 +94,12 @@ static GHashTable *globs_hash = NULL; /* 'magic' nodes */ static GPtrArray *magic_array = NULL; +/* Maps MIME type names to superclass names */ +static GHashTable *subclass_hash = NULL; + +/* Maps aliases to Types */ +static GHashTable *alias_hash = NULL; + /* Static prototypes */ static Magic *magic_new(xmlNode *node, Type *type, GError **error); @@ -295,12 +301,37 @@ static gboolean process_freedesktop_node { char *other_type; gboolean valid; + GSList *list, *nlist; + other_type = xmlGetNsProp(field, "type", NULL); valid = other_type && strchr(other_type, '/'); - xmlFree(other_type); if (valid) - return FALSE; /* Copy through */ + { + char *typename; + typename = g_strdup_printf("%s/%s", + type->media, + type->subtype); + + if (strcmp(field->name, "alias") == 0) + g_hash_table_insert(alias_hash, + g_strdup(other_type), type); + + else + { + list = g_hash_table_lookup(subclass_hash, typename); + nlist = g_slist_append (list, g_strdup(other_type)); + if (list == NULL) + g_hash_table_insert(subclass_hash, + g_strdup(typename), nlist); + } + g_free(typename); + xmlFree(other_type); + + return FALSE; /* Copy through */ + } + + xmlFree(other_type); g_set_error(error, MIME_ERROR, 0, _("Incorrect or missing 'type' attribute " "in <%s>"), field->name); @@ -1310,6 +1341,66 @@ static void write_namespaces(FILE *strea g_ptr_array_free(lines, TRUE); } +static void write_subclass(gpointer key, gpointer value, gpointer data) +{ + GSList *list = value; + FILE *stream = data; + GSList *l; + char *line; + + for (l = list; l; l = l->next) + { + line = g_strconcat (key, " ", l->data, "\n", NULL); + fwrite(line, 1, strlen(line), stream); + g_free (line); + } +} + +/* Write all the collected subclass information to 'subclasses' */ +static void write_subclasses(FILE *stream) +{ + g_hash_table_foreach(subclass_hash, write_subclass, stream); +} + +/* Extract one entry from alias_hash and put it in the GPtrArray so + * we can sort it. + */ +static void add_alias(gpointer key, gpointer value, gpointer data) +{ + GPtrArray *lines = (GPtrArray *) data; + const guchar *alias = (guchar *) key; + Type *type = (Type *) value; + + g_ptr_array_add(lines, g_strconcat(alias, " ", type->media, + "/", type->subtype, "\n", + NULL)); +} + +/* Write all the collected aliases */ +static void write_aliases(FILE *stream) +{ + GPtrArray *lines; + int i; + + lines = g_ptr_array_new(); + + g_hash_table_foreach(alias_hash, add_alias, lines); + + g_ptr_array_sort(lines, strcmp2); + + for (i = 0; i < lines->len; i++) + { + char *line = (char *) lines->pdata[i]; + + fwrite(line, 1, strlen(line), stream); + + g_free(line); + } + + g_ptr_array_free(lines, TRUE); +} + + /* Issue a warning if 'path' won't be found by applications */ static void check_in_path_xdg_data(const char *mime_path) { @@ -1371,6 +1462,14 @@ out: g_free(path); } +static void free_string_list(gpointer data) +{ + GSList *list = data; + + g_slist_foreach(list, (GFunc)g_free, NULL); + g_slist_free(list); +} + int main(int argc, char **argv) { char *mime_dir = NULL; @@ -1442,7 +1541,11 @@ int main(int argc, char **argv) namespace_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); magic_array = g_ptr_array_new(); - + subclass_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, free_string_list); + alias_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + scan_source_dir(package_dir); g_free(package_dir); @@ -1494,7 +1597,7 @@ int main(int argc, char **argv) atomic_update(magic_path); g_free(magic_path); } - + { FILE *stream; char *ns_path; @@ -1510,12 +1613,47 @@ int main(int argc, char **argv) atomic_update(ns_path); g_free(ns_path); } + + { + FILE *stream; + char *path; + + path = g_strconcat(mime_dir, "/subclasses.new", NULL); + stream = fopen(path, "wb"); + if (!stream) + g_error("Failed to open '%s' for writing\n", + path); + + write_subclasses(stream); + + atomic_update(path); + g_free(path); + } + + { + FILE *stream; + char *path; + + path = g_strconcat(mime_dir, "/aliases.new", NULL); + stream = fopen(path, "wb"); + if (!stream) + g_error("Failed to open '%s' for writing\n", + path); + + write_aliases(stream); + + atomic_update(path); + g_free(path); + } + g_ptr_array_free(magic_array, TRUE); g_hash_table_destroy(types); g_hash_table_destroy(globs_hash); g_hash_table_destroy(namespace_hash); + g_hash_table_destroy(subclass_hash); + g_hash_table_destroy(alias_hash); g_print("***\n"); Index: shared-mime-info-spec.xml =================================================================== RCS file: /cvs/mime/shared-mime-info/shared-mime-info-spec.xml,v retrieving revision 1.53 diff -u -p -r1.53 shared-mime-info-spec.xml --- shared-mime-info-spec.xml 11 May 2004 10:33:33 -0000 1.53 +++ shared-mime-info-spec.xml 12 Sep 2004 17:13:31 -0000 @@ -165,6 +165,12 @@ The files created by update-mim <MIME>/magic (contains a mapping from file contents to MIME types) +<MIME>/subclasses (contains a mapping from MIME types to types they inherit from) + + +<MIME>/aliases (contains a mapping from aliases to MIME types) + + <MIME>/XMLnamespaces (contains a mapping from XML (namespaceURI, localName) pairs to MIME types)