Revision 1.1 |
Revision 1.4 |
Line 4 |
Line 4 |
* This file is still quite primitive as you can see. */  
|
* This file is still quite primitive as you can see. */  
|
# include <stdlib.h>
# include <string.h>
# include "mime.h"
# include "utl.h"
|
#include <stdlib.h>
#include <string.h>
#include "cow_config.h"
#include "mime.h"
|
|
#include "utl.h"
|
|
|
Mime mime[256];
|
#define NUMMIME 512
|
|
Mime mime[NUMMIME];
Mime* mimepop[NUMMIME]; /* Pointers into mime, sorted by popularity */
|
int mime_idx; // char* mime_tab[3];
|
int mime_idx; // char* mime_tab[3];
|
char default_type[16];
|
|
|
|
void
|
void add_mime_type(FILE * fp, char *media_type)
|
add_mime_type (FILE * fp, char *media_type)
|
|
{
|
{
|
int h;
int j;
int k;
int flg = 0;
char sux[16];
for (;;)
{
j = 0;
k = 1;
flg = 0;
h = eat_ws (fp);
if ('\n' == h || '\r' == h || '\0' == h)
return;
mime[mime_idx].types[0] = '\0';
strncat (mime[mime_idx].types, media_type, strlen (media_type));
sux[0] = h;
sux[1] = '\0';
for (;;)
{
h = getc (fp);
if (' ' == h || '\t' == h)
break;
if ('\n' == h || '\r' == h)
{
flg = 1;
break;
}
sux[k++] = h;
sux[k] = '\0';
|
int h;
int j;
int k;
int flg = 0;
char sux[16];
if (mime_idx >= NUMMIME)
return;
for (;;) {
j = 0;
k = 1;
flg = 0;
h = eat_ws(fp);
if ('\n' == h || '\r' == h || '\0' == h)
return;
mime[mime_idx].types[0] = '\0';
strncat(mime[mime_idx].types, media_type, strlen(media_type));
sux[0] = h;
sux[1] = '\0';
for (;;) {
h = getc(fp);
if (' ' == h || '\t' == h)
break;
if ('\n' == h || '\r' == h) {
flg = 1;
break;
}
sux[k++] = h;
|
|
sux[k] = '\0';
}
mime[mime_idx].suffix[0] = '\0';
strncat(mime[mime_idx].suffix, sux, strlen(sux));
mime[mime_idx].hits = 0;
mimepop[mime_idx] = &mime[mime_idx];
mime_idx++;
if (flg)
return;
|
}
|
}
|
mime[mime_idx].suffix[0] = '\0';
strncat (mime[mime_idx].suffix, sux, strlen (sux));
mime_idx++;
if (flg)
return;
}
|
|
}
|
}
|
int
|
int mime_init(FILE * fp)
|
mime_init (FILE * fp)
|
|
{
|
{
|
int h;
char mt_buf[128];
|
int h;
char mt_buf[128];
|
|
|
default_type[0] = '\0';
strcat (default_type, "text/html");
|
/*
* If a global mime type was set in the config file, we'll just use that
|
|
* and we don't need to read the list.
*/
if (global_mime)
return 0;
|
|
|
mime_idx = 0;
for (;;)
{
h = eat_ws (fp);
if (EOF == h)
{
return 0;
|
mime_idx = 0;
for (;;) {
h = eat_ws(fp);
if (EOF == h) {
return 0;
}
else if ('#' == h) {
|
|
eat_line(fp);
}
else {
int j = 0;
/* media type */
mt_buf[j++] = h;
for (;;) {
h = getc(fp);
if (' ' == h || '\t' == h) {
mt_buf[j++] = '\0';
add_mime_type(fp, mt_buf);
j = 0;
break;
}
else if (h == '\0')
return 0;
else if (h == '\n' || h == '\r')
break;
else
mt_buf[j++] = h;
}
}
|
}
|
}
|
else if ('#' == h)
{
eat_line (fp);
}
else
{
int j = 0;
/* media type */
mt_buf[j++] = h;
for (;;)
{
h = getc (fp);
if (' ' == h || '\t' == h)
{
mt_buf[j++] = '\0';
add_mime_type (fp, mt_buf);
j = 0;
break;
}
else if (h == '\0')
return 0;
else if (h == '\n' || h == '\r')
break;
else
mt_buf[j++] = h;
}
}
}
|
|
}
|
}
|
char *
get_mime_type (char *filename)
{
char *suffix;
int i = 0;
|
|
|
|
suffix = strrchr (filename, '.');
|
/****
|
|
* get_mime_type()
*
* Returns the mimetype for a file based on filename extension. This
* routine will slowly sort its list of mime types over time so that
* the more popular types bubble up to the top. Since most servers only
* serve a couple types of files, the loop will essentially be eliminated.
*
* @param filename The file to determine the mime type for.
*
* @return The mime type associated with the specified file. This is
* generally based on an entry in /etc/mime.types but can also
* be overridden in the config file.
****/
char *get_mime_type(char *filename) {
char *suffix;
int i = 0;
|
|
|
if (!suffix || '\0' == *suffix)
return default_type;
|
/* If there's a global mime type defined, return that */
if (global_mime)
|
|
return global_mime;
|
|
|
suffix++; // don't want '.'
|
suffix = strrchr(filename, '.');
|
|
if (!suffix || '\0' == *suffix)
return default_mime ? default_mime : "text/plain";
|
|
|
for (; i < mime_idx; i++)
|
suffix++; // don't want '.'
|
{
if (!strcmp (mime[i].suffix, suffix))
return mime[i].types;
}
|
|
|
|
return default_type;
|
for (; i < mime_idx; i++) {
|
|
if (!strcmp(mimepop[i]->suffix, suffix)) {
/*
* This is the mime type we want.
*/
Mime* tmp;
/*
* Bubble this type up (but only by a single slot) if it's more
* popular than the one above it.
*/
if (i > 0 && (++(mimepop[i]->hits) >= mimepop[i-1]->hits)) {
/* Swap this type with the one above it */
tmp = mimepop[i-1];
mimepop[i-1] = mimepop[i];
mimepop[i] = tmp;
/* Since we've swapped positions, return i-1 instead of i */
return mimepop[i-1]->types;
} else {
return mimepop[i]->types;
}
}
}
/*
* Suffix not found in list. If a default was set in the config file,
* return that. If not, just return text/plain.
*/
return default_mime ? default_mime : "text/plain";
|
}
|
}
|