/* * Mbuni - Open Source MMS Gateway * * MM7/SOAP message encoder/decoder and helper functions * * Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com * * Paul Bagyenda * * This program is free software, distributed under the terms of * the GNU General Public License, with a few exceptions granted (see LICENSE) */ #include "mms_mm7soap.h" /* function to traverse SOAP env:Body extracting useful headers. */ #define dfltstr(e) ((e) ? ((char *)(e)) : "") #define content(n) ((n)->xmlChildrenNode ? dfltstr(((n)->xmlChildrenNode)->content) : dfltstr((n)->content)) struct MSoapMsg_t { List *envelope; /* of http headers. */ MIMEEntity *msg; /* XXX - be sure to copy some headers to this from envelope before convert...*/ }; /* We expect ISO formatted time, or interval. */ static Octstr *parse_time(char *s) { time_t t = time(NULL); Octstr *p = octstr_create(s); int i = 0, secs = 0; octstr_strip_blanks(p); if (s && s[0] != 'P') { struct universaltime tt; if (date_parse_iso(&tt, p) >= 0) t = date_convert_universal(&tt); goto done; } else i++; while (i < octstr_len(p)) { long n = 0; int ch; if (octstr_get_char(p, i) == 'T') { secs = 1; i++; } i = octstr_parse_long(&n, p, i, 10); if (i < 0) break; ch = octstr_get_char(p, i); i++; switch(ch) { case 'Y': /* years. approx to 365 1/4 days. */ t += (365.25*24*3600*n); break; case 'M': /* month or minutes. approx month = 30 days. */ if (secs) t += n*60; else t += 30*24*3600*n; break; case 'D': t += n*24*3600; break; case 'H': /* hours. */ t += n*3600; break; case 'S': t += n; break; default: break; } } done: octstr_destroy(p); return date_format_http(t); } static int parse_header(xmlNodePtr node, List *headers, int *sigparent) { int skip = 0; int tag; char *hname; unsigned char *s = NULL; char *nvalue; Octstr *value = NULL, *tmp; if (!node || node->type != XML_ELEMENT_NODE) return -1; /* look at each node in turn, extract meaning. * we ignore some tags: senderidentification, etc because we don't need them. * we are also not strict on syntax (when receiving): we will be on sending! */ hname = (char *)node->name; nvalue = content(node); tmp = octstr_create(hname); tag = mms_string_to_mm7tag(tmp); octstr_destroy(tmp); switch(tag) { case MM7_TAG_CancelReq: case MM7_TAG_CancelRsp: case MM7_TAG_DeliverReq: case MM7_TAG_DeliverRsp: case MM7_TAG_DeliveryReportReq: case MM7_TAG_DeliveryReportRsp: case MM7_TAG_RSErrorRsp: case MM7_TAG_ReadReplyReq: case MM7_TAG_ReadReplyRsp: case MM7_TAG_ReplaceReq: case MM7_TAG_ReplaceRsp: case MM7_TAG_SubmitReq: case MM7_TAG_SubmitRsp: case MM7_TAG_VASPErrorRsp: hname = "MessageType"; value = mms_mm7tag_to_string(tag); break; case MM7_TAG_SenderIdentification: case MM7_TAG_Recipients: skip = 1; break; case MM7_TAG_Recipient: *sigparent = MM7_TAG_To; /* make it a To field. */ break; case MM7_TAG_To: case MM7_TAG_Cc: case MM7_TAG_Bcc: case MM7_TAG_Sender: case MM7_TAG_SenderAddress: skip = 1; *sigparent = tag; /* We wait for number and stuff below. */ break; case MM7_TAG_Content: if ((s = xmlGetProp(node, (unsigned char *)"href")) != NULL) { value = octstr_create((char *)s); xmlFree(s); } /* we keep 'cid:' bit. ignore the bit about adaptation. */ break; case MM7_TAG_ShortCode: case MM7_TAG_Number: /* we will not normalise number here, that's for upper level. */ value = octstr_format("%s/TYPE=PLMN", nvalue); /* -- fall through. -- */ case MM7_TAG_RFC2822Address: if (!value) value = octstr_create(nvalue); hname = (char *)mms_mm7tag_to_cstr(*sigparent); /* real tag is parent. */ s = xmlGetProp(node, (unsigned char *)"displayOnly"); if (s && strcasecmp((char *)s, "true") == 0) /* a '-' indicates don't use this to send. */ octstr_insert(value, octstr_imm("- "), 0); else octstr_insert(value, octstr_imm("+ "), 0); if (s) xmlFree(s); break; case MM7_TAG_EarliestDeliveryTime: case MM7_TAG_ExpiryDate: case MM7_TAG_TimeStamp: case MM7_TAG_Date: value = parse_time(nvalue); break; case MM7_TAG_ReplyCharging: value = octstr_imm("Requested"); if ((s = xmlGetProp(node, (unsigned char *)"replyChargingSize")) != NULL) { http_header_add(headers, "replyChargingSize", (char *)s); xmlFree(s); } if ((s = xmlGetProp(node, (unsigned char *)"replyDeadline")) != NULL) { Octstr *t = parse_time((char *)s); http_header_add(headers, "replyDeadline", octstr_get_cstr(t)); xmlFree(s); octstr_destroy(t); } break; default: break; } if (!value) value = octstr_create(nvalue); octstr_strip_blanks(value); if (!skip && tag >= 0 && hname != NULL) { http_header_add(headers, hname, octstr_get_cstr(value)); #if 1 info(0, "parse.soap, h=%s, v=%s!", hname, octstr_get_cstr(value)); #endif } octstr_destroy(value); return 0; } static int parse_headers(xmlNodePtr start, List *h, int sigparent) { xmlNodePtr x; for (x = start; x; x = x->next) if (x->type != XML_COMMENT_NODE) { parse_header(x, h, &sigparent); parse_headers(x->xmlChildrenNode, h, sigparent); } return 0; } MSoapMsg_t *mm7_parse_soap(List *headers, Octstr *body) { MIMEEntity *mime = mime_http_to_entity(headers, body), *start = NULL; Octstr *xml = NULL, *cloc; xmlDocPtr doc; MIMEEntity *msg = NULL; List *h; int s = -1; MSoapMsg_t *smsg = NULL; if (!mime) return NULL; /* Find the start element: * - either the mime entity is multipart and has start param (or implicitly first element) ... * - or entity is not multipart, so body is xml */ if ((start = mime_multipart_start_elem(mime)) != NULL) xml = mime_entity_body(start); else xml = mime_entity_body(mime); if (!xml) goto done; #if 1 info(0, "XML sent is: %s!", octstr_get_cstr(xml)); #endif doc = xmlParseMemory(octstr_get_cstr(xml), octstr_len(xml)); if (!doc || !doc->xmlChildrenNode) goto done; h = http_create_empty_headers(); parse_headers(doc->xmlChildrenNode, h, s); xmlFreeDoc(doc); if (!h) goto done; cloc = http_header_value(h, octstr_imm("Content")); if (cloc) { /* XXXX only support content that is inline. easy to add external. */ MIMEEntity *c = NULL; int i, n; char *loc = octstr_get_cstr(cloc) + 4; /* skip 'cid:' part. */ for (i = 0, n = mime_entity_num_parts(mime); ienvelope = h; smsg->msg = msg; done: if (mime) mime_entity_destroy(mime); if (start) mime_entity_destroy(start); if (xml) octstr_destroy(xml); return smsg; } static int append_address(Octstr *p, Octstr *addr_spec) { Octstr *v = addr_spec; char *y; int j, ch = octstr_get_char(v, 0); if (ch == '-') y = " displayOnly=\"true\""; else y = ""; j = octstr_case_search(v, octstr_imm("/TYPE=PLMN"),0); if (j >= 0) { Octstr *z = octstr_copy(v, 2, j-2); /* skip the initial char that is only for info purposes. */ octstr_format_append(p, "%S\n", y, z); octstr_destroy(z); } else octstr_format_append(p, "%s\n", y, octstr_get_cstr(v) + 2); /* as above... */ return 0; } static void output_rcpt(char *hdr, List *hdrs, Octstr *p) { List *l = http_header_find_all(hdrs, hdr); char x[32]; int i, n; for (i = 0, n = gwlist_len(l), x[0]=0; i < n; i++) { Octstr *h = NULL, *v = NULL; http_header_get(l, i, &h, &v); if (octstr_str_compare(h, x) != 0) { if (x[0]) octstr_format_append(p, "\n", x); strncpy(x, octstr_get_cstr(h), sizeof x); octstr_format_append(p, "<%S>\n", h); } octstr_destroy(h); append_address(p, v); octstr_destroy(v); } if (x[0]) /* close it off. */ octstr_format_append(p, "\n", x); http_destroy_headers(l); } #define XMLNSMM7 "http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-2" #define SOAP_ENV "SOAP-ENV" /* Construct by hand. */ Octstr *headers_to_soapxml(List *hdrs) { Octstr *s = octstr_create("\n"); Octstr *p, *q, *r, *fault, *mtype; int i, n; time_t t; int mtag; octstr_append_cstr(s, "<" SOAP_ENV ":Envelope xmlns:" SOAP_ENV "=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" "<" SOAP_ENV ":Header>\n"); p = http_header_value(hdrs, octstr_imm("TransactionID")); octstr_format_append(s, "%S\n", XMLNSMM7, p ? p : octstr_imm("none")); if (p) octstr_destroy(p); octstr_append_cstr(s, "\n<" SOAP_ENV ":Body>\n"); fault = http_header_value(hdrs, octstr_imm("Fault")); if (fault) { Octstr *fc = http_header_value(hdrs, octstr_imm("faultcode")); Octstr *fs = http_header_value(hdrs, octstr_imm("faultstring")); octstr_append_cstr(s, "<" SOAP_ENV ":Fault>\n"); if (fc) { octstr_format_append(s, "%S\n", fc); octstr_destroy(fc); } if (fs) { octstr_format_append(s, "%S\n", fs); octstr_destroy(fs); } octstr_append_cstr(s, "\n"); } mtype = http_header_value(hdrs, octstr_imm("MessageType")); mtag = mms_string_to_mm7tag(mtype); octstr_format_append(s, "\n", mtype, XMLNSMM7); /* Output the details. */ p = http_header_value(hdrs, octstr_imm("MM7Version")); octstr_format_append(s, "%S\n", p); octstr_destroy(p); p = http_header_value(hdrs, octstr_imm("VASPID")); q = http_header_value(hdrs, octstr_imm("VASID")); r = http_header_value(hdrs, octstr_imm("SenderAddress")); if (p || q || r) { octstr_append_cstr(s, "\n"); if (p) octstr_format_append(s, "%S\n", p); if (q) octstr_format_append(s, "%S\n", q); if (r) { Octstr *xx = octstr_create(""); append_address(xx, r); octstr_format_append(s, "%S\n", xx); octstr_destroy(xx); } octstr_append_cstr(s, "\n"); if (p) octstr_destroy(p); if (q) octstr_destroy(q); if (r) octstr_destroy(r); } p = octstr_create(""); if (mtag == MM7_TAG_SubmitReq || mtag == MM7_TAG_DeliverReq) { /* Multiple recipients,... */ output_rcpt("To", hdrs, p); output_rcpt("Cc", hdrs, p); output_rcpt("Bcc", hdrs, p); if (octstr_len(p) > 0) octstr_format_append(s, "\n%S\n", p); } else if ((q = http_header_value(hdrs, octstr_imm("To"))) != NULL) { append_address(p, q); octstr_format_append(s, "\n%S\n", p); octstr_destroy(q); } octstr_destroy(p); /* cycle through rest of headers. */ for (i = 0, n = gwlist_len(hdrs); i < n; i++) { Octstr *h = NULL, *v = NULL; char *zz; int tag; int skip = 0; http_header_get(hdrs, i, &h, &v); tag = mms_string_to_mm7tag(h); zz = octstr_get_cstr(h); switch(tag) { case MM7_TAG_MessageType: case MM7_TAG_To: case MM7_TAG_Cc: case MM7_TAG_Bcc: case MM7_TAG_Fault: case MM7_TAG_faultstring: case MM7_TAG_faultcode: case MM7_TAG_VASID: case MM7_TAG_VASPID: case MM7_TAG_MM7Version: case MM7_TAG_replyChargingSize: case MM7_TAG_replyDeadline: case MM7_TAG_TransactionID: case MM7_TAG_StatusCode: case MM7_TAG_StatusText: case MM7_TAG_Details: case MM7_TAG_SenderAddress: skip = 1; break; case MM7_TAG_Sender: p = octstr_create(""); append_address(p, v); octstr_format_append(s, "%S\n", p); octstr_destroy(p); skip = 1; break; case MM7_TAG_Content: octstr_format_append(s, "\n", v); skip = 1; break; case MM7_TAG_ReplyCharging: p = http_header_value(hdrs, octstr_imm("replyChargingSize")); q = http_header_value(hdrs, octstr_imm("replyDeadline")); octstr_append_cstr(s, "\n"); skip = 1; break; case MM7_TAG_EarliestDeliveryTime: case MM7_TAG_ExpiryDate: case MM7_TAG_TimeStamp: case MM7_TAG_Date: t = date_parse_http(v); octstr_destroy(v); v = date_create_iso(t); /* format as ISO time... */ break; case MM7_TAG_Status: p = http_header_value(hdrs, octstr_imm("StatusCode")); q = http_header_value(hdrs, octstr_imm("StatusText")); octstr_append_cstr(s, "\n"); if (p) { octstr_format_append(s, "%S\n", p); octstr_destroy(p); } if (q) { octstr_format_append(s, "%S\n", q); octstr_destroy(q); } q = http_header_value(hdrs, octstr_imm("Details")); if (q) { octstr_format_append(s, "
%S
\n", q); octstr_destroy(q); } octstr_append_cstr(s, "
\n"); skip = 1; break; default: break; } if (!skip && h && v) octstr_format_append(s, "<%S>%S\n", h, v, h); if (h) octstr_destroy(h); if (v) octstr_destroy(v); } octstr_format_append(s, "
\n", mtype); octstr_destroy(mtype); if (fault) { octstr_append_cstr(s, "
\n"); octstr_append_cstr(s, "\n"); octstr_destroy(fault); } octstr_append_cstr(s, "\n"); octstr_append_cstr(s, "\n"); return s; } int mm7_soapmsg_to_httpmsg(MSoapMsg_t *m, List **hdrs, Octstr **body) { MIMEEntity *mime; Octstr *ctype, *s; List *headers; mime = mime_entity_create(); if (m->msg) { MIMEEntity *c = mime_entity_duplicate(m->msg); Octstr *cloc = octstr_format("cid:c%ld.%d.%c%c.msg", time(NULL), random(), 'A' + random() % 26, 'a' + random() % 26); Octstr *cloc_str = octstr_format("<%s>", octstr_get_cstr(cloc) + 4); Octstr *envloc = octstr_format("", time(NULL), random(), 'A' + random() % 26, 'a' + random() % 26); MIMEEntity *xml = mime_entity_create(); List *hh = http_header_duplicate(m->envelope); List *hx; /* Replace in envelope. */ http_header_remove_all(hh, "Content"); http_header_add(hh, "Content", octstr_get_cstr(cloc)); /* Replace content location in msg part. */ hx = _x_mime_entity_headers(c); http_header_remove_all(hx, "Content-ID"); http_header_add(hx, "Content-ID", octstr_get_cstr(cloc_str)); mime_replace_headers(c, hx); http_destroy_headers(hx); hx = http_create_empty_headers(); http_header_add(hx, "Content-Type", "\"text/xml\""); http_header_add(hx, "Content-ID", octstr_get_cstr(envloc)); mime_replace_headers(xml, hx); http_destroy_headers(hx); s = headers_to_soapxml(hh); mime_entity_set_body(xml, s); octstr_destroy(s); mime_entity_add_part(mime, xml); mime_entity_add_part(mime, c); http_destroy_headers(hh); ctype = octstr_format("multipart/related; type=\"text/xml\"; start=\"%S\"", envloc); octstr_destroy(envloc); octstr_destroy(cloc); octstr_destroy(cloc_str); mime_entity_destroy(xml); mime_entity_destroy(c); } else { ctype = octstr_imm("\"text/xml\""); s = headers_to_soapxml(m->envelope); mime_entity_set_body(mime,s); octstr_destroy(s); } headers = http_create_empty_headers(); http_header_add(headers, "Content-Type", octstr_get_cstr(ctype)); http_header_add(headers, "SOAPAction", "\"some-url\""); mime_replace_headers(mime, headers); http_destroy_headers(headers); *body = mime_entity_body(mime); *hdrs = _x_mime_entity_headers(mime); mime_entity_destroy(mime); return 0; } int mm7_msgtype(MSoapMsg_t *m) { Octstr *typ = http_header_value(m->envelope, octstr_imm("MessageType")); int ret; if (!typ) return -1; ret = mms_string_to_mm7tag(typ); octstr_destroy(typ); return ret; } static int get_rcptvalues(List *to, List *headers, char *hname) { List *l; int i, n; l = http_header_find_all(headers, hname); for (i = 0, n = (l) ? gwlist_len(l) : 0; i < n; i++) { Octstr *h, *v; int ch; http_header_get(l, i, &h, &v); ch = octstr_get_char(v, 0); if (ch == '+') gwlist_append(to, octstr_copy(v, 2, octstr_len(v))); octstr_destroy(h); octstr_destroy(v); } http_destroy_headers(l); return 0; } int mm7_get_envelope(MSoapMsg_t *m, Octstr **sender, List **to, Octstr **subject, Octstr **vasid, time_t *expiry_t, time_t *delivery_t) { Octstr *s; if (*to == NULL) *to = gwlist_create(); get_rcptvalues(*to, m->envelope, "To"); get_rcptvalues(*to, m->envelope, "Cc"); get_rcptvalues(*to, m->envelope, "Bcc"); *subject = http_header_value(m->envelope, octstr_imm("Subject")); *vasid = http_header_value(m->envelope, octstr_imm("VASID")); if ((s = http_header_value(m->envelope, octstr_imm("SenderAddress"))) == NULL) s = http_header_value(m->envelope, octstr_imm("Sender")); if (s && octstr_get_char(s, 0) == '+') octstr_delete(s, 0, 2); else if (s) { octstr_destroy(s); s = NULL; } *sender = s; if (expiry_t) { Octstr *s = http_header_value(m->envelope, octstr_imm("ExpiryDate")); *expiry_t = -1; if (s) { *expiry_t = date_parse_http(s); octstr_destroy(s); } } if (delivery_t) { Octstr *s = http_header_value(m->envelope, octstr_imm("EarliestDeliveryTime")); *delivery_t = -1; if (s) { *delivery_t = date_parse_http(s); octstr_destroy(s); } } return 0; } MmsMsg *mm7_soap_to_mmsmsg(MSoapMsg_t *m, Octstr *from) { int msgtype = mm7_msgtype(m); MmsMsg *msg = NULL; Octstr *s, *f, *p, *q, *r; List *l; time_t t; switch(msgtype) { case MM7_TAG_DeliverReq: case MM7_TAG_SubmitReq: case MM7_TAG_ReplaceReq: msg = mms_frommime(m->msg); if (!msg) break; mms_remove_headers(msg, "Content-ID"); /* not necessary, but... */ /* Put in some headers... */ if (from) mms_replace_header_value(msg, "From", octstr_get_cstr(from)); if ((s = http_header_value(m->envelope, octstr_imm("MessageClass"))) != NULL) { if (mms_string_to_message_class(s) >= 0) mms_replace_header_value(msg, "X-Mms-Message-Class", octstr_get_cstr(s)); octstr_destroy(s); } if ((s = http_header_value(m->envelope, octstr_imm("Priority"))) != NULL) { if (mms_string_to_priority(s) >= 0) mms_replace_header_value(msg, "X-Mms-Priority", octstr_get_cstr(s)); octstr_destroy(s); } if ((s = http_header_value(m->envelope, octstr_imm("DeliveryReport"))) != NULL) { long x = mms_string_to_boolean_flag(s); if (x >= 0) mms_replace_header_value(msg, "X-Mms-Delivery-Report", (char *)mms_reports_to_cstr(x)); octstr_destroy(s); } if ((s = http_header_value(m->envelope, octstr_imm("ReadReply"))) != NULL) { long x = mms_string_to_boolean_flag(s); if (x >= 0) mms_replace_header_value(msg, "X-Mms-Read-Report", (char *)mms_reports_to_cstr(x)); octstr_destroy(s); } if ((s = http_header_value(m->envelope, octstr_imm("TimeStamp"))) != NULL) { mms_replace_header_value(msg, "Date", octstr_get_cstr(s)); octstr_destroy(s); } if ((s = http_header_value(m->envelope, octstr_imm("ExpiryDate"))) != NULL) { mms_replace_header_value(msg, "X-Mms-Expiry", octstr_get_cstr(s)); octstr_destroy(s); } if ((s = http_header_value(m->envelope, octstr_imm("Subject"))) != NULL) { mms_replace_header_value(msg, "Subject", octstr_get_cstr(s)); octstr_destroy(s); } if ((s = http_header_value(m->envelope, octstr_imm("MessageID"))) != NULL) { mms_replace_header_value(msg, "Message-ID", octstr_get_cstr(s)); octstr_destroy(s); } /* Put in recipient list. XXX - really?? */ l = gwlist_create(); get_rcptvalues(l, m->envelope, "To"); mms_replace_header_values(msg, "To", l); gwlist_destroy(l, (gwlist_item_destructor_t *)octstr_destroy); l = gwlist_create(); get_rcptvalues(l, m->envelope, "Cc"); mms_replace_header_values(msg, "Cc", l); gwlist_destroy(l, (gwlist_item_destructor_t *)octstr_destroy); /* XXX - we ignore reply charging, etc. */ break; case MM7_TAG_DeliveryReportReq: /* should we bother?? Can these ever be handled here?? */ case MM7_TAG_ReadReplyReq: s = http_header_value(m->envelope, octstr_imm("MessageID")); if ((p = http_header_value(m->envelope, octstr_imm("To"))) != NULL && octstr_get_char(p, 0) == '+') octstr_delete(p, 0, 2); else if (p) { octstr_destroy(p); p = NULL; } if ((f = http_header_value(m->envelope, octstr_imm("From"))) != NULL && octstr_get_char(f, 0) == '+') octstr_delete(f, 0, 2); else if (f) { octstr_destroy(f); f = NULL; } if ((q = http_header_value(m->envelope, octstr_imm("Date"))) != NULL) t = date_parse_http(q); else t = time(NULL); r = http_header_value(m->envelope, octstr_imm("MMStatus")); if (msgtype == MM7_TAG_DeliveryReportReq && p && r && mms_string_to_status(r) >= 0) msg = mms_deliveryreport(s ? s : octstr_imm("0000"), p, t, r); else if (msgtype == MM7_TAG_ReadReplyReq && f && p && r && mms_string_to_read_status(r) >= 0) msg = mms_readreport(s ? s : octstr_imm("0000"), f, p, t, r); if (s) octstr_destroy(s); if (p) octstr_destroy(p); if (r) octstr_destroy(r); if (f) octstr_destroy(f); break; default: break; } return msg; } void mm7_soap_destroy(MSoapMsg_t *m) { http_destroy_headers(m->envelope); if (m->msg) mime_entity_destroy(m->msg); gw_free(m); } static MSoapMsg_t *mm7_soap_create(int msgtype, Octstr *otransid) { MSoapMsg_t *m = gw_malloc(sizeof *m); m->envelope = http_create_empty_headers(); m->msg = NULL; http_header_add(m->envelope, "MessageType", (char *)mms_mm7tag_to_cstr(msgtype)); http_header_add(m->envelope, "MM7Version", MM7_DEFAULT_VERSION); http_header_add(m->envelope, "TransactionID", otransid ? octstr_get_cstr(otransid) : "0000"); return m; } MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto, Octstr *transid, Octstr *srvcode, Octstr *linkedid, int isclientside, char *vaspid, char *vasid) { int mtype = mms_messagetype(msg); MSoapMsg_t *m = NULL; Octstr *s; int i, n; Octstr *xfrom; List *headers; xfrom = octstr_format("+ %S", from ? from : octstr_imm("anon@anon")); switch(mtype) { case MMS_MSGTYPE_SEND_REQ: case MMS_MSGTYPE_RETRIEVE_CONF: m = mm7_soap_create(isclientside ? MM7_TAG_SubmitReq : MM7_TAG_DeliverReq, transid); m->msg = mms_tomime(msg,1); for (i = 0, n = xto ? gwlist_len(xto) : 0; i < n; i++) { /* Add recipients. */ Octstr *xx = octstr_format("+ %S", gwlist_get(xto, i)); http_header_add(m->envelope, "To", octstr_get_cstr(xx)); octstr_destroy(xx); } if (srvcode) http_header_add(m->envelope, isclientside ? "ServiceCode" : "MMSRelayServerID", octstr_get_cstr(srvcode)); if (linkedid) http_header_add(m->envelope, "LinkedID", octstr_get_cstr(linkedid)); http_header_add(m->envelope, isclientside ? "SenderAddress" : "Sender", octstr_get_cstr(xfrom)); if (isclientside) { if (vaspid) http_header_add(m->envelope, "VASPID", vaspid); if (vasid) http_header_add(m->envelope, "VASID", vasid); if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Message-Class"))) != NULL) { http_header_add(m->envelope, "MessageClass", octstr_get_cstr(s)); octstr_destroy(s); } if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Expiry"))) != NULL) { http_header_add(m->envelope, "ExpiryDate", octstr_get_cstr(s)); octstr_destroy(s); } if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Delivery-Report"))) != NULL) { char *val = (octstr_case_compare(s, octstr_imm("Yes")) == 0) ? "true" : "false"; http_header_add(m->envelope, "DeliveryReport", val); octstr_destroy(s); } if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Read-Report"))) != NULL) { char *val = (octstr_case_compare(s, octstr_imm("Yes")) == 0) ? "true" : "false"; http_header_add(m->envelope, "ReadReply", val); octstr_destroy(s); } } if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Priority"))) != NULL) { http_header_add(m->envelope, "Priority", octstr_get_cstr(s)); octstr_destroy(s); } if ((s = mms_get_header_value(msg, octstr_imm("Subject"))) != NULL) { http_header_add(m->envelope, "Subject", octstr_get_cstr(s)); octstr_destroy(s); } if ((s = mms_get_header_value(msg, octstr_imm("Date"))) != NULL) { http_header_add(m->envelope, "TimeStamp", octstr_get_cstr(s)); octstr_destroy(s); } /* Should we bother to strip message part of headers??? */ headers = _x_mime_entity_headers(m->msg); http_header_remove_all(headers, "Subject"); http_header_remove_all(headers, "X-Mms-Message-Type"); http_header_remove_all(headers, "X-Mms-Message-Version"); http_header_remove_all(headers, "From"); http_header_remove_all(headers, "To"); http_header_remove_all(headers, "Cc"); http_header_remove_all(headers, "Bcc"); mime_replace_headers(m->msg, headers); http_destroy_headers(headers); break; case MMS_MSGTYPE_READ_ORIG_IND: case MMS_MSGTYPE_DELIVERY_IND: m = mm7_soap_create((mtype == MMS_MSGTYPE_READ_ORIG_IND) ? MM7_TAG_ReadReplyReq : MM7_TAG_DeliveryReportReq, transid); http_header_add(m->envelope, "Sender", octstr_get_cstr(xfrom)); if (xto && gwlist_len(xto) > 0) { Octstr *xx = octstr_format("+ %S", gwlist_get(xto, 0)); http_header_add(m->envelope, "To", octstr_get_cstr(xx)); octstr_destroy(xx); } s = mms_get_header_value(msg, octstr_imm("Message-ID")); if (!s) s = octstr_duplicate(transid); http_header_add(m->envelope, "MessageID", octstr_get_cstr(s)); octstr_destroy(s); if ((s = mms_get_header_value(msg, octstr_imm("Date"))) != NULL) { http_header_add(m->envelope, (mtype == MMS_MSGTYPE_READ_ORIG_IND) ? "TimeStamp" : "Date", octstr_get_cstr(s)); octstr_destroy(s); } if ((s = mms_get_header_value(msg, (mtype == MMS_MSGTYPE_READ_ORIG_IND) ? octstr_imm("X-Mms-Read-Status") : octstr_imm("X-Mms-Status") )) != NULL) { http_header_add(m->envelope, "MMStatus", octstr_get_cstr(s)); octstr_destroy(s); } break; default: break; } octstr_destroy(xfrom); return m; } MSoapMsg_t *mm7_make_resp(MSoapMsg_t *mreq, int status, Octstr *msgid) { int mtype = mreq ? mm7_msgtype(mreq) : -1; Octstr *transid; MSoapMsg_t *mresp; char scode[64]; unsigned char *statustxt = mms_soap_status_to_cstr(status); transid = mreq ? http_header_value(mreq->envelope, octstr_imm("TransactionID")) : NULL; if (!MM7_SOAP_STATUS_OK(status) || mtype < 0) mresp = mm7_soap_create(MM7_TAG_RSErrorRsp, transid); else mresp = mm7_soap_create(mtype + 1, transid); sprintf(scode, "%d", status); http_header_add(mresp->envelope, "Status", ""); /* So that we get output. */ http_header_add(mresp->envelope, "StatusCode", scode); http_header_add(mresp->envelope, "StatusText", statustxt ? (char *)statustxt : "Error"); if (msgid && mtype == MM7_TAG_SubmitReq) /* only allow MessageID in submitRsp */ http_header_add(mresp->envelope, "MessageID", octstr_get_cstr(msgid)); if (!MM7_SOAP_STATUS_OK(status)) { http_header_add(mresp->envelope, "Fault", ""); /* do we really need these? XXX */ http_header_add(mresp->envelope, "faultcode", "" SOAP_ENV ":Server"); http_header_add(mresp->envelope, "faultstring", "Server error"); } octstr_destroy(transid); return mresp; } Octstr *mm7_soap_header_value(MSoapMsg_t *m, Octstr *header) { return http_header_value(m->envelope, header); }