#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "eps.h"
static mime_t *mime_new_instance(void);
static int mime_header(eps_t *, mime_t *, header_t *);
static void mime_content_type(eps_t *, header_t *, void *);
static void mime_transfer_encoding(eps_t *, header_t *, void *);
static void mime_content_disposition(eps_t *, header_t *, void *);
struct i_header_t _m_i_headers[] = {
{ "Content-Type", mime_content_type },
{ "Content-Transfer-Encoding", mime_transfer_encoding },
{ "Content-Disposition", mime_content_disposition },
{ NULL, NULL }
};
/*
Allocate, and initialize a new mime_t
structure to return.
*/
mime_t *mime_new_instance(void)
{
mime_t *m = NULL;
m = (mime_t *)malloc(sizeof(mime_t));
if (m == NULL)
return NULL;
memset((mime_t *)m, 0, sizeof(mime_t));
m->content_type = CON_TEXT;
m->encoding = ENC_TEXT;
m->disposition = DIS_NONE;
return m;
}
int mime_header(eps_t *eps, mime_t *m, header_t *h)
{
int i = 0;
for (i = 0; _m_i_headers[i].name; i++) {
if (!(strcasecmp(_m_i_headers[i].name, h->name))) {
_m_i_headers[i].func(eps, h, (void *)m);
return 1;
}
}
return 0;
}
void mime_content_type(eps_t *eps, header_t *h, void *mx)
{
int len = 0;
char *p = NULL;
mime_t *m = (mime_t *)mx;
if ((!h) || (!h->atoms) || (!h->atoms->next) || (!h->atoms->next->data))
m->content_type = CON_TEXT;
else {
if (m->h_content_type)
free(m->h_content_type);
len = strlen(h->atoms->next->data);
m->h_content_type = (char *)malloc(len + 1);
if (m->h_content_type) {
memset(m->h_content_type, 0, len + 1);
memcpy(m->h_content_type, h->atoms->next->data, len);
}
m->content_type = content_parse(h->atoms->next->data, TYP_CON);
}
if (!(m->filename)) {
p = header_fetch_atom(h, "name");
if (p)
m->filename = mstrdup(p);
}
if (m->content_type & CON_MULTI) {
p = header_fetch_atom(h, "boundary");
if (p)
boundary_add(eps, p);
}
}
void mime_transfer_encoding(eps_t *eps, header_t *h, void *mx)
{
mime_t *m = (mime_t *)mx;
if ((!h) || (!h->atoms) || (!h->atoms->next) || (!h->atoms->next->data))
m->encoding = ENC_TEXT;
else
m->encoding = content_parse(h->atoms->next->data, TYP_ENC);
}
void mime_content_disposition(eps_t *eps, header_t *h, void *mx)
{
char *p = NULL;
mime_t *m = (mime_t *)mx;
if ((!h) || (!h->atoms) || (!h->atoms->next) || (!h->atoms->next->data))
m->disposition = DIS_NONE;
else
m->disposition = content_parse(h->atoms->next->data, TYP_DIS);
if (!(m->filename)) {
p = header_fetch_atom(h, "filename");
if (p)
m->filename = mstrdup(p);
}
}
void mime_kill(mime_t *m)
{
if (m->filename)
free(m->filename);
if (m->boundary)
free(m->boundary);
if (m->orig)
free(m->orig);
if (m->h_content_type)
free(m->h_content_type);
free(m);
}
int mime_init_stream(eps_t *eps)
{
char *p = NULL;
if (eps->m)
mime_kill(eps->m);
eps->u->eof = 0;
eps->m = mime_new_instance();
p = boundary_fetch(eps, eps->b->cdepth);
if (p) {
eps->m->boundary = mstrdup(p);
eps->m->depth = eps->b->cdepth;
}
else
eps->m->depth = -1;
#ifdef MIME_DEBUG
printf("New MIME: [%s](%d)\n", p ? p : "NONE", eps->m->depth);
#endif
return 1;
}
header_t *mime_next_header(eps_t *eps)
{
unsigned char *l = NULL;
l = unfold_next_line(eps->u);
if (l == NULL) {
#ifdef MIME_DEBUG
printf("Unfold ends\n");
#endif
return NULL;
}
if (eps->h)
header_kill(eps->h);
eps->h = header_parse(l);
if (eps->h) {
if ((eps->h->name) && (eps->h->data))
mime_header(eps, eps->m, eps->h);
}
eps_source(eps, l);
return eps->h;
}
unsigned char *mime_next_line(eps_t *eps)
{
int ret = 0;
unsigned char *l = NULL;
l = buffer_next_line(eps->u->b);
if (l == NULL)
return NULL;
eps_source(eps, l);
if ((*l == '-') && (*(l + 1) == '-')) {
ret = boundary_is(eps, (l + 2));
if (ret == 1) {
if (eps->m->orig)
free(eps->m->orig);
eps->m->orig = (char *)malloc(strlen(l) + 1);
if (eps->m->orig) {
memset((char *)eps->m->orig, 0, strlen(l) + 1);
memcpy((char *)eps->m->orig, (char *)l, strlen(l));
}
return NULL;
}
else if (ret == 2) {
#ifdef MIME_DEBUG
printf("Boundary [%s] terminates; removing\n", eps->m->boundary);
#endif
eps->m->depth = -1;
boundary_remove_last(eps);
if (eps->b->cdepth == 0) {
#ifdef MIME_DEBUG
printf("Reached 0 depth: EOF\n");
#endif
eps->u->b->eof = 1;
}
if (eps->m->orig)
free(eps->m->orig);
eps->m->orig = (char *)malloc(strlen(l) + 1);
if (eps->m->orig) {
memset((char *)eps->m->orig, 0, strlen(l) + 1);
memcpy((char *)eps->m->orig, (char *)l, strlen(l));
}
return NULL;
}
}
if (eps->m->orig) {
free(eps->m->orig);
eps->m->orig = NULL;
}
return l;
}
syntax highlighted by Code2HTML, v. 0.9.1