#include #include #include #include #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; }