/*
* File: mime.c
*
* Copyright (C) 2000-2007 Jorge Arellano Cid <jcid@dillo.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*/
#include "mime.h"
#include "../list.h"
typedef struct {
const char *Name; /* MIME type name */
Viewer_t Data; /* Pointer to a function */
} MimeItem_t;
/*
* Local data
*/
static int MimeMinItemsSize = 0, MimeMinItemsMax = 8;
static MimeItem_t *MimeMinItems = NULL;
static int MimeMajItemsSize = 0, MimeMajItemsMax = 8;
static MimeItem_t *MimeMajItems = NULL;
/*
* Add a specific MIME type (as "image/png") to our viewer list
* 'Key' is the content-type string that identifies the MIME type
* 'Method' is the function that handles it
*/
static int Mime_add_minor_type(const char *Key, Viewer_t Method)
{
a_List_add(MimeMinItems, MimeMinItemsSize, MimeMinItemsMax);
MimeMinItems[MimeMinItemsSize].Name = Key;
MimeMinItems[MimeMinItemsSize].Data = Method;
MimeMinItemsSize++;
return 0;
}
/*
* Add a major MIME type (as "text") to our viewer list
* 'Key' is the content-type string that identifies the MIME type
* 'Method' is the function that handles it
*/
static int Mime_add_major_type(const char *Key, Viewer_t Method)
{
a_List_add(MimeMajItems, MimeMajItemsSize, MimeMajItemsMax);
MimeMajItems[MimeMajItemsSize].Name = Key;
MimeMajItems[MimeMajItemsSize].Data = Method;
MimeMajItemsSize++;
return 0;
}
/*
* Search the list of specific MIME viewers, for a Method that matches 'Key'
* 'Key' is the content-type string that identifies the MIME type
*/
static Viewer_t Mime_minor_type_fetch(const char *Key, uint_t Size)
{
int i;
if (Size) {
for ( i = 0; i < MimeMinItemsSize; ++i )
if (dStrncasecmp(Key, MimeMinItems[i].Name, Size) == 0)
return MimeMinItems[i].Data;
}
return NULL;
}
/*
* Search the list of major MIME viewers, for a Method that matches 'Key'
* 'Key' is the content-type string that identifies the MIME type
*/
static Viewer_t Mime_major_type_fetch(const char *Key, uint_t Size)
{
int i;
if (Size) {
for ( i = 0; i < MimeMajItemsSize; ++i )
if (dStrncasecmp(Key, MimeMajItems[i].Name, Size) == 0)
return MimeMajItems[i].Data;
}
return NULL;
}
/*
* Initializes Mime module and, sets the supported Mime types.
*/
void a_Mime_init()
{
#ifdef ENABLE_GIF
Mime_add_minor_type("image/gif", a_Dicache_gif_image);
#endif
#ifdef ENABLE_JPEG
Mime_add_minor_type("image/jpeg", a_Dicache_jpeg_image);
Mime_add_minor_type("image/pjpeg", a_Dicache_jpeg_image);
Mime_add_minor_type("image/jpg", a_Dicache_jpeg_image);
#endif
#ifdef ENABLE_PNG
Mime_add_minor_type("image/png", a_Dicache_png_image);
Mime_add_minor_type("image/x-png", a_Dicache_png_image); /* deprecated */
#endif
Mime_add_minor_type("text/html", a_Html_text);
Mime_add_minor_type("application/xhtml+xml", a_Html_text);
/* Add a major type to handle all the text stuff */
Mime_add_major_type("text", a_Plain_text);
}
/*
* Call the handler for the MIME type to set Call and Data as appropriate
*
* Return Value:
* On success: a new Dw (and Call and Data properly set).
* On failure: NULL (and Call and Data untouched).
*/
void *a_Mime_set_viewer(const char *content_type, void *Ptr,
CA_Callback_t *Call, void **Data)
{
Viewer_t viewer;
uint_t MinSize, MajSize, i;
const char *str = content_type;
MajSize = 0;
for (i = 0; str[i] && str[i] != ' ' && str[i] != ';'; ++i) {
if (str[i] == '/' && !MajSize)
MajSize = i;
}
MinSize = i;
/* Try minor type */
viewer = Mime_minor_type_fetch(content_type, MinSize);
if (viewer)
return viewer(content_type, Ptr, Call, Data);
/* Try major type */
viewer = Mime_major_type_fetch(content_type, MajSize);
if (viewer)
return viewer(content_type, Ptr, Call, Data);
/* Type not handled */
return NULL;
}