static int msg_cb (void *dummy_arg, rfc822parse_event_t event, rfc822parse_t msg) { show_event (event); if (event == RFC822PARSE_T2BODY) { rfc822parse_field_t ctx; void *ectx; const char *line; for (ectx=NULL; (line = rfc822parse_enum_header_lines (msg, &ectx)); ) { printf ("*** HDR: %s\n", line); } rfc822parse_enum_header_lines (NULL, &ectx); /* Close enumerator. */ ctx = rfc822parse_parse_field (msg, "Content-Type", -1); if (ctx) { const char *s1, *s2; s1 = rfc822parse_query_media_type (ctx, &s2); if (s1) printf ("*** media: `%s/%s'\n", s1, s2); else printf ("*** media: [not found]\n"); show_param (ctx, "boundary"); show_param (ctx, "protocol"); rfc822parse_release_field (ctx); } else printf ("*** media: text/plain [assumed]\n"); ctx = rfc822parse_parse_field (msg, "Content-Disposition", -1); if (ctx) { const char *s1; TOKEN t; s1 = rfc822parse_query_parameter (ctx, NULL, 1); if (s1) printf ("*** disp: type=`%s'\n", s1); s1 = rfc822parse_query_parameter (ctx, "filename", 0); if (s1) printf ("*** disp: fname=`%s'\n", s1); rfc822parse_release_field (ctx); } } return 0; }
/**************** * We have read in all header lines and are about to receive the body * part. The delimiter line has already been processed. * * FIXME: we's better return an error in case of memory failures. */ static int transition_to_body (rfc822parse_t msg) { rfc822parse_field_t ctx; int rc; rc = do_callback (msg, RFC822PARSE_T2BODY); if (!rc) { /* Store the boundary if we have multipart type. */ ctx = rfc822parse_parse_field (msg, "Content-Type", -1); if (ctx) { const char *s; s = rfc822parse_query_media_type (ctx, NULL); if (s && !strcmp (s,"multipart")) { s = rfc822parse_query_parameter (ctx, "boundary", 0); if (s) { assert (!msg->current_part->boundary); msg->current_part->boundary = malloc (strlen (s) + 1); if (msg->current_part->boundary) { part_t part; strcpy (msg->current_part->boundary, s); msg->boundary = msg->current_part->boundary; part = new_part (); if (!part) { int save_errno = errno; rfc822parse_release_field (ctx); errno = save_errno; return -1; } rc = do_callback (msg, RFC822PARSE_LEVEL_DOWN); assert (!msg->current_part->down); msg->current_part->down = part; msg->current_part = part; msg->in_preamble = 1; } } } rfc822parse_release_field (ctx); } } return rc; }
/* Internal debug function to print the structure of the message. */ static void dump_structure (rfc822parse_t msg, part_t part, int indent) { if (!part) { printf ("*** Structure of this message:\n"); part = msg->parts; } for (; part; part = part->right) { rfc822parse_field_t ctx; part_t save_part; /* ugly hack - we should have a function to get part inforation. */ const char *s; save_part = msg->current_part; msg->current_part = part; ctx = rfc822parse_parse_field (msg, "Content-Type", -1); msg->current_part = save_part; if (ctx) { const char *s1, *s2; s1 = rfc822parse_query_media_type (ctx, &s2); if (s1) printf ("*** %*s %s/%s", indent*2, "", s1, s2); else printf ("*** %*s [not found]", indent*2, ""); s = rfc822parse_query_parameter (ctx, "boundary", 0); if (s) printf (" (boundary=\"%s\")", s); rfc822parse_release_field (ctx); } else printf ("*** %*s text/plain [assumed]", indent*2, ""); putchar('\n'); if (part->down) dump_structure (msg, part->down, indent + 1); } }
/* This function is called by the parser to communicate events. This callback communicates with the main program using a structure passed in OPAQUE. Should retrun 0 or set errno and return -1. */ static int message_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg) { struct parse_info_s *info = opaque; if (debug) show_event (event); if (event == RFC822PARSE_T2BODY) { rfc822parse_field_t ctx; size_t off; char *p; info->mime_type = MT_NONE; info->transfer_encoding = TE_NONE; info->test_base64 = 0; info->got_probe = 0; info->no_mime = 0; ctx = rfc822parse_parse_field (msg, "Content-Type", -1); if (ctx) { const char *s1, *s2; s1 = rfc822parse_query_media_type (ctx, &s2); if (!s1) ; else if (!strcmp (s1, "application") && !strcmp (s2, "octet-stream")) info->mime_type = MT_OCTET_STREAM; else if (!strcmp (s1, "text") && !strcmp (s2, "html")) info->mime_type = MT_TEXT_HTML; else if (!strcmp (s1, "audio")) info->mime_type = MT_AUDIO; else if (!strcmp (s1, "image")) info->mime_type = MT_IMAGE; if (verbose) { printf ("# Content-Type: %s/%s", s1?s1:"", s2?s2:""); s1 = rfc822parse_query_parameter (ctx, "charset", 0); if (s1) printf ("; charset=%s", s1); putchar ('\n'); } rfc822parse_release_field (ctx); } else { p = rfc822parse_get_field (msg, "MIME-Version", -1, NULL); if (p) free (p); else info->no_mime = 1; } if (verbose) { const char *s1; p = rfc822parse_get_field (msg, "Content-Disposition", -1, NULL); if (p) { printf ("# %s\n", p); free (p); } ctx = rfc822parse_parse_field (msg, "Content-Disposition", -1); if (ctx) { s1 = rfc822parse_query_parameter (ctx, "filename", 0); if (s1) printf ("# Content-Disposition has filename=`%s'\n", s1); rfc822parse_release_field (ctx); } } p = rfc822parse_get_field (msg, "Content-Transfer-Encoding", -1, &off); if (p) { lowercase_string (p+off); if (!strcmp (p+off, "base64")) info->transfer_encoding = TE_BASE64; free (p); } if (!info->top_seen) { info->top_seen = 1; p = rfc822parse_get_field (msg, "To", -1, NULL); if (p) { if ( strstr (p, "Werner Koch") ) { if (verbose) fputs ("# Found known name in To\n", stdout); info->wk_seen = 1; } free (p); } if (!info->wk_seen) { p = rfc822parse_get_field (msg, "Cc", -1, NULL); if (p) { if ( strstr (p, "Werner Koch") ) { if (verbose) fputs ("# Found known name in Cc\n", stdout); info->wk_seen = 1; } free (p); } } } if ((info->mime_type == MT_OCTET_STREAM || info->mime_type == MT_AUDIO || info->mime_type == MT_IMAGE) && info->transfer_encoding == TE_BASE64) info->test_base64 = 1; else if (info->mime_type == MT_TEXT_HTML) { if (!quiet) fputs ("HTML\n", stdout); if (opt_match_html && !info->wk_seen) exit (0); } } else if (event == RFC822PARSE_PREAMBLE) ; else if (event == RFC822PARSE_BOUNDARY || event == RFC822PARSE_LAST_BOUNDARY) { if (info->test_base64) info->got_probe = 1; info->test_base64 = 0; } else if (event == RFC822PARSE_BEGIN_HEADER) { } return 0; }