/* mime.c - mime type support
Copyright (C) 2000 Maurer IT Systemlösungen KEG
The Gnome Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The Gnome 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the Gnome Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Author: Dietmar Maurer <dietmar@maurer-it.com>
*/
#include <config.h>
#include <string.h>
#include "efs_internal.h"
#define FIRST_USER_TYPE 1000000
/* for a list od resistrated mime types see:
* ftp://ftp.isi.edu/in-notes/iana/assignments/media-types/media-types
*/
static gchar * std_mime_types[] = {
"application/octet-stream",
"application/postscript",
"application/rtf",
"application/pdf",
"application/zip",
"application/sgml",
"application/pgp-encrypted",
"application/pgp-signature",
"application/pgp-keys",
"application/xml",
"audio/basic",
"audio/midi",
"audio/mpeg",
"audio/x-aiff",
"audio/x-wav",
"image/bmp",
"image/cgm",
"image/g3fax",
"image/gif",
"image/jpeg",
"image/png",
"image/tiff",
"text/css",
"text/directory",
"text/enriched",
"text/html",
"text/plain",
"text/richtext",
"text/rtf",
"text/sgml",
"text/tab-separated-values",
"text/uri-list",
"text/xml",
"text/directory",
"text/calendar",
"video/mpeg",
"video/quicktime",
"video/x-msvideo",
"video/x-sgi-movie",
"model/iges",
"model/vmrl",
"model/mesh",
NULL
};
static GHashTable * s2i_std_hash = NULL;
static GHashTable * i2s_std_hash = NULL;
static void
efs_stdtype_init ()
{
guint32 i, j, k, l, code;
gchar prefix[512], *p;
gchar tmp_prefix[512];
if (s2i_std_hash) return;
s2i_std_hash = g_hash_table_new (g_str_hash, g_str_equal);
i2s_std_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
i = 0;
code = 0;
j = 0;
k = 0;
strcpy (prefix, "none");
while (std_mime_types[i]) {
p = strchr (std_mime_types[i],'/');
l = p - std_mime_types[i];
strncpy (tmp_prefix, std_mime_types[i], l);
tmp_prefix[l] = 0;
if (strcmp (prefix, tmp_prefix)) {
j ++;
k = 0;
strcpy (prefix, tmp_prefix);
}
code = j*1000+k;
g_hash_table_insert (s2i_std_hash, std_mime_types[i],
(gpointer) code);
g_hash_table_insert (i2s_std_hash, (gpointer) code,
std_mime_types[i]);
i++;
k++;
}
}
static void
efs_type_init (EFS *efs)
{
guint32 code, i;
gint32 l, br;
gchar buf[1024], *p;
if (!efs->typefd) return;
if (efs_file_seek (efs->typefd, 0, EFS_SEEK_SET, &i)) return;
efs->s2i_hash = g_hash_table_new (g_str_hash, g_str_equal);
efs->i2s_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
i = FIRST_USER_TYPE;
while (!efs_file_read (efs->typefd, &code, 4, &br)) {
if (br != 4) return;
code = GUINT32_FROM_LE (code);
if (code != i) return;
i++;
if (efs_file_read (efs->typefd, &l, 4, &br)) return;
if (br != 4) return;
l = GINT32_FROM_LE (l);
if (l >= sizeof(buf)) return;
if (efs_file_read (efs->typefd, buf, l, &br)) return;
if (br != l) return;
buf[l] = 0;
p = g_strdup (buf);
g_hash_table_insert (efs->s2i_hash, p, (gpointer) code);
g_hash_table_insert (efs->i2s_hash, (gpointer) code, p);
}
}
static EFSResult
integer_type_lookup (EFS *efs, gchar *strtype, gboolean nostd, guint32 *type)
{
if (!strcmp (strtype, EFS_MIME_DIR) ||
!strcmp (strtype, EFS_MIME_DATA)) {
*type = 0;
return EFS_ERR_OK;
}
if (!s2i_std_hash) efs_stdtype_init ();
*type = (guint32) g_hash_table_lookup (s2i_std_hash, strtype);
if (!(*type)) {
if (!nostd) return EFS_ERR_NOTYPE;
if (!efs->s2i_hash) efs_type_init (efs);
if (!efs->s2i_hash) return EFS_ERR_INT;
*type = (guint32) g_hash_table_lookup (efs->s2i_hash, strtype);
if (!(*type)) return EFS_ERR_NOTYPE;
}
return EFS_ERR_OK;
}
static EFSResult
string_type_lookup (EFSNode *node, guint32 type, gchar **strtype)
{
EFS *efs = node->efs;
if (type == 0) {
if (node->mode&EFS_DIR) *strtype = EFS_MIME_DIR;
else *strtype = EFS_MIME_DATA;
return EFS_ERR_OK;
}
if (!i2s_std_hash) efs_stdtype_init ();
*strtype = g_hash_table_lookup (i2s_std_hash, (gpointer)type);
if (!(*strtype)) {
if (!efs->i2s_hash) efs_type_init (efs);
if (!efs->i2s_hash) return EFS_ERR_INT;
*strtype = g_hash_table_lookup (efs->i2s_hash, (gpointer)type);
if (!(*strtype)) return EFS_ERR_NOTYPE;
}
return EFS_ERR_OK;
}
static guint32
efs_create_type (EFS *efs, gchar *strtype)
{
guint32 code, code_le, cpos;
gint32 l, l_le;
gchar *p;
if (!efs->s2i_hash | !efs->i2s_hash) return 0;
if (!efs->typefd) return 0;
code = FIRST_USER_TYPE + efs->tc++;
p = g_strdup (strtype);
g_hash_table_insert (efs->s2i_hash, p, (gpointer) code);
g_hash_table_insert (efs->i2s_hash, (gpointer) code, p);
if (efs_file_seek (efs->typefd, 0, EFS_SEEK_END, &cpos)) return 0;
code_le = GUINT32_TO_LE (code);
if (efs_file_write (efs->typefd, &code_le, 4)) return 0;
l = strlen(strtype);
l_le = GINT32_TO_LE (l);
if (efs_file_write (efs->typefd, &l_le, 4)) return 0;
if (efs_file_write (efs->typefd, strtype, l)) return 0;
return code;
}
EFSResult
efs_strtype_set (EFSNode *node, gchar *strtype)
{
guint32 type;
g_return_val_if_fail (node != NULL, EFS_ERR_INVAL);
g_return_val_if_fail (strtype != NULL, EFS_ERR_INVAL);
if (!integer_type_lookup (node->efs, strtype, FALSE, &type))
return efs_type_set (node, type);
if (!integer_type_lookup (node->efs, strtype, TRUE, &type))
return efs_type_set (node, type);
if (!(type = efs_create_type (node->efs, strtype))) return EFS_ERR_INT;
return efs_type_set (node, type);
}
EFSResult
efs_strtype_get (EFSNode *node, gchar **strtype)
{
EFSResult res;
guint32 type;
g_return_val_if_fail (node != NULL, EFS_ERR_INVAL);
g_return_val_if_fail (strtype != NULL, EFS_ERR_INVAL);
if ((res = efs_type_get (node, &type))) return res;
if ((res = string_type_lookup(node, type, strtype))) return res;
return EFS_ERR_OK;
}
EFSResult
efs_type_lookup (EFSNode *node, gchar *strtype, guint32 *type)
{
EFSResult res;
g_return_val_if_fail (node != NULL, EFS_ERR_INVAL);
g_return_val_if_fail (strtype != NULL, EFS_ERR_INVAL);
g_return_val_if_fail (type != NULL, EFS_ERR_INVAL);
if ((res = integer_type_lookup (node->efs, strtype, TRUE, type)))
return res;
return EFS_ERR_OK;
}
EFSResult
efs_strtype_lookup (EFSNode *node, guint32 type, gchar **strtype)
{
EFSResult res;
g_return_val_if_fail (node != NULL, EFS_ERR_INVAL);
g_return_val_if_fail (strtype != NULL, EFS_ERR_INVAL);
if ((res = string_type_lookup(node, type, strtype))) return res;
return EFS_ERR_OK;
}
syntax highlighted by Code2HTML, v. 0.9.1