#include #include #include #include static void display_mime_content(struct mailmime_content * content_type); static void display_mime_data(struct mailmime_data * data) { switch (data->dt_type) { case MAILMIME_DATA_TEXT: printf("data : %u bytes\n", (unsigned int) data->dt_data.dt_text.dt_length); break; case MAILMIME_DATA_FILE: printf("data (file) : %s\n", data->dt_data.dt_filename); break; } } static void display_mime_dsp_parm(struct mailmime_disposition_parm * param) { switch (param->pa_type) { case MAILMIME_DISPOSITION_PARM_FILENAME: printf("filename: %s\n", param->pa_data.pa_filename); break; } } static void display_mime_disposition(struct mailmime_disposition * disposition) { clistiter * cur; for(cur = clist_begin(disposition->dsp_parms) ; cur != NULL ; cur = clist_next(cur)) { struct mailmime_disposition_parm * param; param = clist_content(cur); display_mime_dsp_parm(param); } } static void display_mime_field(struct mailmime_field * field) { switch (field->fld_type) { case MAILMIME_FIELD_TYPE: printf("content-type: "); display_mime_content(field->fld_data.fld_content); printf("\n"); break; case MAILMIME_FIELD_DISPOSITION: display_mime_disposition(field->fld_data.fld_disposition); break; } } static void display_mime_fields(struct mailmime_fields * fields) { clistiter * cur; for(cur = clist_begin(fields->fld_list) ; cur != NULL ; cur = clist_next(cur)) { struct mailmime_field * field; field = clist_content(cur); display_mime_field(field); } } static void display_date_time(struct mailimf_date_time * d) { printf("%02i/%02i/%i %02i:%02i:%02i %+04i", d->dt_day, d->dt_month, d->dt_year, d->dt_hour, d->dt_min, d->dt_sec, d->dt_zone); } static void display_orig_date(struct mailimf_orig_date * orig_date) { display_date_time(orig_date->dt_date_time); } static void display_mailbox(struct mailimf_mailbox * mb) { if (mb->mb_display_name != NULL) printf("%s ", mb->mb_display_name); printf("<%s>", mb->mb_addr_spec); } static void display_mailbox_list(struct mailimf_mailbox_list * mb_list) { clistiter * cur; for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; cur = clist_next(cur)) { struct mailimf_mailbox * mb; mb = clist_content(cur); display_mailbox(mb); if (clist_next(cur) != NULL) { printf(", "); } } } static void display_group(struct mailimf_group * group) { clistiter * cur; printf("%s: ", group->grp_display_name); for(cur = clist_begin(group->grp_mb_list->mb_list) ; cur != NULL ; cur = clist_next(cur)) { struct mailimf_mailbox * mb; mb = clist_content(cur); display_mailbox(mb); } printf("; "); } static void display_address(struct mailimf_address * a) { switch (a->ad_type) { case MAILIMF_ADDRESS_GROUP: display_group(a->ad_data.ad_group); break; case MAILIMF_ADDRESS_MAILBOX: display_mailbox(a->ad_data.ad_mailbox); break; } } static void display_address_list(struct mailimf_address_list * addr_list) { clistiter * cur; for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; cur = clist_next(cur)) { struct mailimf_address * addr; addr = clist_content(cur); display_address(addr); if (clist_next(cur) != NULL) { printf(", "); } } } static void display_from(struct mailimf_from * from) { display_mailbox_list(from->frm_mb_list); } static void display_to(struct mailimf_to * to) { display_address_list(to->to_addr_list); } static void display_cc(struct mailimf_cc * cc) { display_address_list(cc->cc_addr_list); } static void display_subject(struct mailimf_subject * subject) { printf("%s", subject->sbj_value); } static void display_field(struct mailimf_field * field) { switch (field->fld_type) { case MAILIMF_FIELD_ORIG_DATE: printf("Date: "); display_orig_date(field->fld_data.fld_orig_date); printf("\n"); break; case MAILIMF_FIELD_FROM: printf("From: "); display_from(field->fld_data.fld_from); printf("\n"); break; case MAILIMF_FIELD_TO: printf("To: "); display_to(field->fld_data.fld_to); printf("\n"); break; case MAILIMF_FIELD_CC: printf("Cc: "); display_cc(field->fld_data.fld_cc); printf("\n"); break; case MAILIMF_FIELD_SUBJECT: printf("Subject: "); display_subject(field->fld_data.fld_subject); printf("\n"); break; case MAILIMF_FIELD_MESSAGE_ID: printf("Message-ID: %s\n", field->fld_data.fld_message_id->mid_value); break; } } static void display_fields(struct mailimf_fields * fields) { clistiter * cur; for(cur = clist_begin(fields->fld_list) ; cur != NULL ; cur = clist_next(cur)) { struct mailimf_field * f; f = clist_content(cur); display_field(f); } } static void display_mime_discrete_type(struct mailmime_discrete_type * discrete_type) { switch (discrete_type->dt_type) { case MAILMIME_DISCRETE_TYPE_TEXT: printf("text"); break; case MAILMIME_DISCRETE_TYPE_IMAGE: printf("image"); break; case MAILMIME_DISCRETE_TYPE_AUDIO: printf("audio"); break; case MAILMIME_DISCRETE_TYPE_VIDEO: printf("video"); break; case MAILMIME_DISCRETE_TYPE_APPLICATION: printf("application"); break; case MAILMIME_DISCRETE_TYPE_EXTENSION: printf("%s", discrete_type->dt_extension); break; } } static void display_mime_composite_type(struct mailmime_composite_type * ct) { switch (ct->ct_type) { case MAILMIME_COMPOSITE_TYPE_MESSAGE: printf("message"); break; case MAILMIME_COMPOSITE_TYPE_MULTIPART: printf("multipart"); break; case MAILMIME_COMPOSITE_TYPE_EXTENSION: printf("%s", ct->ct_token); break; } } static void display_mime_type(struct mailmime_type * type) { switch (type->tp_type) { case MAILMIME_TYPE_DISCRETE_TYPE: display_mime_discrete_type(type->tp_data.tp_discrete_type); break; case MAILMIME_TYPE_COMPOSITE_TYPE: display_mime_composite_type(type->tp_data.tp_composite_type); break; } } static void display_mime_content(struct mailmime_content * content_type) { printf("type: "); display_mime_type(content_type->ct_type); printf("/%s\n", content_type->ct_subtype); } static void display_mime(struct mailmime * mime) { clistiter * cur; switch (mime->mm_type) { case MAILMIME_SINGLE: printf("single part\n"); break; case MAILMIME_MULTIPLE: printf("multipart\n"); break; case MAILMIME_MESSAGE: printf("message\n"); break; } if (mime->mm_mime_fields != NULL) { if (clist_begin(mime->mm_mime_fields->fld_list) != NULL) { printf("MIME headers begin\n"); display_mime_fields(mime->mm_mime_fields); printf("MIME headers end\n"); } } display_mime_content(mime->mm_content_type); switch (mime->mm_type) { case MAILMIME_SINGLE: display_mime_data(mime->mm_data.mm_single); break; case MAILMIME_MULTIPLE: for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; cur != NULL ; cur = clist_next(cur)) { display_mime(clist_content(cur)); } break; case MAILMIME_MESSAGE: if (mime->mm_data.mm_message.mm_fields) { if (clist_begin(mime->mm_data.mm_message.mm_fields->fld_list) != NULL) { printf("headers begin\n"); display_fields(mime->mm_data.mm_message.mm_fields); printf("headers end\n"); } if (mime->mm_data.mm_message.mm_msg_mime != NULL) { display_mime(mime->mm_data.mm_message.mm_msg_mime); } break; } } } int main(int argc, char ** argv) { FILE * f; int r; struct mailmime * mime; struct stat stat_info; char * data; size_t current_index; char * filename; if (argc < 2) { fprintf(stderr, "syntax: mime-parse [filename]\n"); } filename = argv[1]; f = fopen(filename, "r"); if (f == NULL) { exit(EXIT_FAILURE); } r = stat(filename, &stat_info); if (r != 0) { fclose(f); exit(EXIT_FAILURE); } data = malloc(stat_info.st_size); fread(data, 1, stat_info.st_size, f); fclose(f); current_index = 0; r = mailmime_parse(data, stat_info.st_size, ¤t_index, &mime); if (r != MAILIMF_NO_ERROR) { free(data); exit(EXIT_FAILURE); return EXIT_FAILURE; } display_mime(mime); mailmime_free(mime); free(data); exit(EXIT_SUCCESS); }