void test_multipart () { MIME *m; FILE *fp; struct stat st; char *buf, *fbuf; int sz; if (stat (MNAME, &st)) { error ("Can't stat %s\n", MNAME); return; } buf = (char *) malloc (st.st_size + 1); fp = fopen (MNAME, "rb"); fread (buf, 1, st.st_size, fp); fclose (fp); buf[st.st_size] = 0; debug ("parsing %s sz=%d...\n", MNAME, st.st_size); if ((m = mime_parse (buf)) == NULL) error ("Failed parsing %s\n", MNAME); fbuf = mime_format (m); info ("Passed multipart mime test\n", fbuf); debug ("formated...\n%s\n", fbuf); free (buf); free (fbuf); }
int main(int argc, char **argv) { Octstr *mime_content, *pap_content, *push_data, *rdf_content, *boundary, *push_content_file = NULL, *this_header, *pap_osname, *data_osname; List *content_headers, *source_parts; char *pap_content_file, *push_data_file, *rdf_content_file; int ret, std_out, opt, d_file, c_file; FILE *fp1, *fp2, *fp3; gwlib_init(); std_out = 0; d_file = 0; c_file = 0; data_osname = NULL; pap_osname = NULL; while ((opt = getopt(argc, argv, "hd:sc:")) != EOF) { switch(opt) { case 'h': help(); exit(1); break; case 'd': d_file = 1; data_osname = octstr_create(optarg); break; case 'c': c_file = 1; pap_osname = octstr_create(optarg); break; case 's': std_out = 1; break; case '?': default: error(0, "Invalid option %c", opt); help(); panic(0, "Stopping"); break; } } if (optind >= argc) { help(); panic(0, "missing arguments, stopping"); } if (!c_file) pap_content_file = "test/pap.txt"; else pap_content_file = octstr_get_cstr(pap_osname); if (!d_file) push_data_file = "test/data.txt"; else push_data_file = octstr_get_cstr(data_osname); rdf_content_file = "test/rdf.txt"; mime_content = octstr_read_file(argv[optind]); if (mime_content == NULL) { octstr_destroy(mime_content); error(0, "No MIME source"); panic(0, "Stopping"); } source_parts = octstr_split(mime_content, octstr_imm("content=")); if (gwlist_len(source_parts) == 1) { /* a hack to circumvent a bug */ error(0, "Badly formatted source:"); octstr_destroy(mime_content); gwlist_destroy(source_parts, octstr_destroy_item); panic(0, "Stopping"); } boundary = gwlist_extract_first(source_parts); octstr_delete(boundary, 0, octstr_len(octstr_imm("boundary="))); if (skip_tail(&boundary, ';') == 0) { error(0, "Cannot determine boundary, no delimiter; possible"); octstr_dump(boundary, 0); goto no_parse; } octstr_destroy(mime_content); mime_content = gwlist_extract_first(source_parts); if (skip_tail(&mime_content, ';') == 0){ error(0, "Cannot determine mime content, no delimiter"); octstr_dump(mime_content, 0); goto no_parse; } prepend_crlf(&mime_content); add_crs(mime_content); append_crlf(mime_content); ret = mime_parse(boundary, mime_content, &pap_content, &push_data, &content_headers, &rdf_content); if (ret == 0) { error(0, "Mime_parse returned 0, cannot continue"); goto error; } remove_crs(pap_content); if (!std_out) { fp1 = fopen(pap_content_file, "a"); if (fp1 == NULL) { error(0, "Cannot open the file for pap control message"); goto error; } octstr_print(fp1, pap_content); debug("test.mime", 0, "pap control message appended to the file"); fclose(fp1); } else { debug("test.mime", 0, "pap control message was"); octstr_dump(pap_content, 0); } remove_crs(push_data); if (!std_out) { fp2 = fopen(push_data_file, "a"); if (fp2 == NULL) { error(0, "Cannot open the push data file"); goto error; } push_content_file = octstr_create(""); octstr_append(push_content_file, octstr_imm("headers=")); while (gwlist_len(content_headers) > 0) { octstr_append(push_content_file, this_header = gwlist_extract_first(content_headers)); octstr_format_append(push_content_file, "%c", ' '); octstr_destroy(this_header); } octstr_append(push_content_file, octstr_imm(";\n")); octstr_append(push_content_file, octstr_imm("content=")); octstr_append(push_content_file, push_data); octstr_append(push_content_file, octstr_imm(";\n")); octstr_print(fp2, push_content_file); debug("test.mime", 0, "push content appended to the file"); fclose(fp2); } else { debug("test.mime", 0, "Content headers were"); http_header_dump(content_headers); debug("test.mime", 0, "And push content itself"); octstr_dump(push_data, 0); } if (rdf_content != NULL) remove_crs(rdf_content); if (!std_out && rdf_content != NULL) { fp3 = NULL; if (rdf_content != NULL) { fp3 = fopen(rdf_content_file, "a"); if (fp3 == NULL) { error(0, "Cannot open the rdf file"); goto cerror; } octstr_print(fp3, rdf_content); debug("test.mime", 0, "push caps message appended to the file"); fclose(fp3); } } else { if (rdf_content != NULL) { debug("test.mime", 0, "push caps message was"); octstr_dump(rdf_content, 0); } } octstr_destroy(boundary); octstr_destroy(mime_content); octstr_destroy(pap_content); octstr_destroy(push_data); octstr_destroy(rdf_content); octstr_destroy(pap_osname); octstr_destroy(data_osname); http_destroy_headers(content_headers); gwlist_destroy(source_parts, octstr_destroy_item); octstr_destroy(push_content_file); gwlib_shutdown(); info(0, "MIME data parsed successfully"); return 0; no_parse: octstr_destroy(mime_content); octstr_destroy(pap_osname); octstr_destroy(data_osname); gwlist_destroy(source_parts, octstr_destroy_item); octstr_destroy(boundary); gwlib_shutdown(); panic(0, "Stopping"); error: octstr_destroy(mime_content); gwlist_destroy(source_parts, octstr_destroy_item); octstr_destroy(boundary); octstr_destroy(pap_content); octstr_destroy(push_data); octstr_destroy(pap_osname); octstr_destroy(data_osname); http_destroy_headers(content_headers); octstr_destroy(rdf_content); gwlib_shutdown(); panic(0, "Stopping"); cerror: octstr_destroy(mime_content); gwlist_destroy(source_parts, octstr_destroy_item); octstr_destroy(boundary); octstr_destroy(pap_content); octstr_destroy(push_data); octstr_destroy(push_content_file); octstr_destroy(pap_osname); octstr_destroy(data_osname); http_destroy_headers(content_headers); octstr_destroy(rdf_content); gwlib_shutdown(); panic(0, "Stopping"); /* return after panic always required by gcc */ return 1; }
/* * parse a reply message and update the queue row with status */ int ebxml_parse_reply (char *reply, QUEUEROW *r) { MIME *msg, *part; XML *xml; char *ch, buf[PTIMESZ]; if (ebxml_status (reply)) return (-1); if ((msg = mime_parse (reply)) == NULL) { error ("Failed parsing reply message\n"); return (-1); } /* check the ebxml envelope for ack or error */ if ((part = mime_getMultiPart (msg, 1)) == NULL) { error ("Reply missing ebxml envelope\n"); mime_free (msg); return (-1); } if ((xml = xml_parse (mime_getBody (part))) == NULL) { error ("Failed parsing ebxml envelop\n"); mime_free (msg); return (-1); } strcpy (buf, xml_get_text (xml, SOAPACTION)); if (!strcmp (buf, "MessageError")) { debug ("Error reply received!\n"); queue_field_set (r, "PROCESSINGSTATUS", "done"); queue_field_set (r, "TRANSPORTSTATUS", "failed"); ch = xml_get_attribute (xml, SOAPERROR, "eb:errorCode"); debug ("%s eb:errorCode %s\n", SOAPERROR, ch); queue_field_set (r, "TRANSPORTERRORCODE", ch); queue_field_set (r, "APPLICATIONSTATUS", "not-set"); queue_field_set (r, "APPLICATIONERRORCODE", "none"); ch = xml_get_text (xml, SOAPERROR); debug ("SOAPERROR %s\n", ch); queue_field_set (r, "APPLICATIONRESPONSE", ch); queue_field_set (r, "MESSAGERECEIVEDTIME", ptime (NULL, buf)); xml_free (xml); mime_free (msg); return (0); } xml_free (xml); /* Ping reply */ if (strcmp (queue_field_get (r, "ACTION"), "Ping") == 0) { if (strcmp (buf, "Pong")) { error ("Expected 'Pong' action but got '%s'\n", buf); mime_free (msg); return (-1); } queue_field_set (r, "APPLICATIONSTATUS", "not-set"); queue_field_set (r, "APPLICATIONERRORCODE", "none"); queue_field_set (r, "APPLICATIONRESPONSE", "none"); queue_field_set (r, "MESSAGERECEIVEDTIME", ptime (NULL, buf)); } else /* regular reply */ { if ((part = mime_getMultiPart (msg, 2)) == NULL) { error ("Reply missing status part\n"); mime_free (msg); return (-1); } debug ("Body is...\n%s\n", mime_getBody (part)); if ((xml = xml_parse (mime_getBody (part))) == NULL) { error ("Miss formatted Reply status\n"); mime_free (msg); return (-1); } queue_field_set (r, "APPLICATIONSTATUS", xml_get_text (xml, "response.msh_response.status")); queue_field_set (r, "APPLICATIONERRORCODE", xml_get_text (xml, "response.msh_response.error")); queue_field_set (r, "APPLICATIONRESPONSE", xml_get_text (xml, "response.msh_response.appdata")); queue_field_set (r, "MESSAGERECEIVEDTIME", ptime (NULL, buf)); /* TODO... queue_field_set (r, "RESPONSEMESSAGEID", ""); queue_field_set (r, "RESPONSEARGUMENTS", ""); queue_field_set (r, "RESPONSELOCALFILE", ""); queue_field_set (r, "RESPONSEFILENAME", ""); queue_field_set (r, "RESPONSEMESSAGEORIGIN", ""); queue_field_set (r, "RESPONSEMESSAGESIGNATURE", ""); */ xml_free (xml); } queue_field_set (r, "PROCESSINGSTATUS", "done"); queue_field_set (r, "TRANSPORTSTATUS", "success"); queue_field_set (r, "TRANSPORTERRORCODE", "none"); mime_free (msg); return (0); }
/* * parse a mime package */ MIME *mime_parse (char *buf) { char *ch, *p; int l, c; MIME *m, **n; char boundary[100]; /* * first find the header end */ if ((ch = strstr (buf, "\n\r\n")) != NULL) ch += 3; else if ((ch = strstr (buf, "\n\n")) != NULL) ch += 2; else { debug ("headers not found\n"); return (NULL); } c = *ch; *ch = 0; m = mime_alloc (); m->headers = (char *) malloc (ch - buf + 1); strcpy (m->headers, buf); *ch = c; debug ("headers:\n%s", m->headers); /* * next determine the size */ if ((m->len = mime_getLength (m)) == 0) { m->len = strlen (ch); mime_setLength (m, m->len); } debug ("len=%d\n", m->len); /* * copy in the body * if not a multipart then it's all body * we alloc an extra byte for the EOS */ if ((l = mime_getBoundary (m, boundary, 100)) < 1) { m->body = (unsigned char *) malloc (m->len + 1); memmove (m->body, ch, m->len); m->body[m->len] = 0; debug ("parse completed\n"); return (m); } /* * each part goes into the next chain */ n = &m->next; p = strstr (ch - 1, boundary); if (p > ch -1) { m->len = p - ch; c = *p; *p = 0; m->body = (unsigned char *) malloc (m->len + 1); memmove (m->body, ch, m->len + 1); } else m->len = 0; ch = p; while (1) { ch += l; /* bump past boundary marker */ debug ("checking end of boundry\n"); if ((ch[0] == ch[1]) && (ch[0] == '-')) break; /* find next one */ if (*ch++ == '\r') ch++; /* bump past CR LF */ if ((p = strstr (ch, boundary)) == NULL) { debug ("end boundary not found\n"); return (mime_free (m)); } c = *p; /* parse to it */ *p = 0; debug ("next part...\n"); if ((*n = mime_parse (ch)) == NULL) { debug ("next part did not parse\n"); return (mime_free (m)); } n = &(*n)->next; *p = c; ch = p; /* set up for next part */ } debug ("parse completed\n"); return (m); }