1
0
Fork 0
mbuni/mbuni/mmlib/mms_mm7soap.c

1040 lines
29 KiB
C

/*
* 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 <bagyenda@dsmagic.com>
*
* 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);
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 entity is multipart and start element is (implicitly) first element
* - or entity is not multipart, so body is xml
*/
if (mime->start)
xml = mime->start->body;
else if (mime->multiparts && list_len(mime->multiparts) > 0) {
MIMEEntity *x = list_get(mime->multiparts,0);
xml = x->body;
} else
xml = mime->body;
/* Don't free 'xml'! It is part of mime object. */
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 = list_len(mime->multiparts); i<n; i++) {
MIMEEntity *x = list_get(mime->multiparts, i);
Octstr *y = x ? http_header_value(x->headers, octstr_imm("Content-ID")) : NULL;
char *cid = (y && octstr_get_char(y, 0) == '<') ? octstr_get_cstr(y) + 1 : (y ? octstr_get_cstr(y) : "");
int cid_len = (y && octstr_get_char(y, 0) == '<') ? octstr_len(y) - 2 : (y ? octstr_len(y) : 0);
if (y && strncmp(loc, cid, cid_len) == 0)
c = x;
if (y)
octstr_destroy(y);
if (c)
break;
}
if (c)
msg = mime_entity_duplicate(c);
octstr_destroy(cloc);
}
smsg = gw_malloc(sizeof *smsg);
smsg->envelope = h;
smsg->msg = msg;
done:
if (mime)
mime_entity_destroy(mime);
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, "<Number%s>%S</Number>\n", y, z);
octstr_destroy(z);
} else
octstr_format_append(p, "<RFC2822Address%s>%s</RFC2822Address>\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 = list_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, "</%s>\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, "</%s>\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"
/* Construct by hand. */
Octstr *headers_to_soapxml(List *hdrs)
{
Octstr *s = octstr_create("<?xml version=\"1.0\" ?>\n");
Octstr *p, *q, *r, *fault, *mtype;
int i, n;
time_t t;
int mtag;
octstr_append_cstr(s,
"<env:Envelope xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
"<env:Header>\n");
p = http_header_value(hdrs, octstr_imm("TransactionID"));
octstr_format_append(s, "<mm7:TransactionID xmlns:mm7=\"%s\" env:mustUnderstand=\"1\">%S</mm7:TransactionID>\n",
XMLNSMM7, p ? p : octstr_imm("none"));
if (p)
octstr_destroy(p);
octstr_append_cstr(s, "</env:Header>\n<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, "<env:Fault>\n");
if (fc) {
octstr_format_append(s, "<faultcode>%S</faultcode>\n", fc);
octstr_destroy(fc);
}
if (fs) {
octstr_format_append(s, "<faultstring>%S</faultstring>\n", fs);
octstr_destroy(fs);
}
octstr_append_cstr(s, "<detail>\n");
}
mtype = http_header_value(hdrs, octstr_imm("MessageType"));
mtag = mms_string_to_mm7tag(mtype);
octstr_format_append(s, "<%S xmlns=\"%s\">\n", mtype, XMLNSMM7);
/* Output the details. */
p = http_header_value(hdrs, octstr_imm("MM7Version"));
octstr_format_append(s, "<MM7Version>%S</MM7Version>\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, "<SenderIdentification>\n");
if (p)
octstr_format_append(s, "<VASPID>%S</VASPID>\n", p);
if (q)
octstr_format_append(s, "<VASID>%S</VASID>\n", q);
if (r) {
Octstr *xx = octstr_create("");
append_address(xx, r);
octstr_format_append(s, "<SenderAddress>%S</SenderAddress>\n", xx);
octstr_destroy(xx);
}
octstr_append_cstr(s, "</SenderIdentification>\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, "<Recipients>\n%S</Recipients>\n", p);
} else if ((q = http_header_value(hdrs, octstr_imm("To"))) != NULL) {
append_address(p, q);
octstr_format_append(s, "<Recipient>\n%S</Recipient>\n", p);
octstr_destroy(q);
}
octstr_destroy(p);
/* cycle through rest of headers. */
for (i = 0, n = list_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, "<Sender>%S</Sender>\n", p);
octstr_destroy(p);
skip = 1;
break;
case MM7_TAG_Content:
octstr_format_append(s, "<Content href=\"%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, "<ReplyCharging");
if (p) {
octstr_format_append(s, " replyChargingSize=\"%S\"", p);
octstr_destroy(p);
}
if (q) {
octstr_format_append(s, " replyDeadline=\"%S\"", q);
octstr_destroy(q);
}
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, "<Status>\n");
if (p) {
octstr_format_append(s, "<StatusCode>%S</StatusCode>\n", p);
octstr_destroy(p);
}
if (q) {
octstr_format_append(s, "<StatusText>%S</StatusText>\n", q);
octstr_destroy(q);
}
q = http_header_value(hdrs, octstr_imm("Details"));
if (q) {
octstr_format_append(s, "<Details>%S</Details>\n", q);
octstr_destroy(q);
}
octstr_append_cstr(s, "</Status>\n");
skip = 1;
break;
default:
break;
}
if (!skip && h && v)
octstr_format_append(s, "<%S>%S</%S>\n", h, v, h);
if (h) octstr_destroy(h);
if (v) octstr_destroy(v);
}
octstr_format_append(s, "</%S>\n", mtype);
octstr_destroy(mtype);
if (fault) {
octstr_append_cstr(s, "</detail>\n");
octstr_append_cstr(s, "</env:Fault>\n");
octstr_destroy(fault);
}
octstr_append_cstr(s, "</env:Body>\n");
octstr_append_cstr(s, "</env:Envelope>\n");
return s;
}
int mm7_soapmsg_to_httpmsg(MSoapMsg_t *m, List **hdrs, Octstr **body)
{
MIMEEntity *mime;
Octstr *ctype;
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("<s%ld.%d.%c%c.msg>",
time(NULL), random(),
'A' + random() % 26,
'a' + random() % 26);
MIMEEntity *xml = mime_entity_create();
List *hh = http_header_duplicate(m->envelope);
/* Replace in envelope. */
http_header_remove_all(hh, "Content");
http_header_add(hh, "Content", octstr_get_cstr(cloc));
/* Replace content location in msg part. */
http_header_remove_all(c->headers, "Content-ID");
http_header_add(c->headers, "Content-ID", octstr_get_cstr(cloc_str));
http_header_add(xml->headers, "Content-Type", "text/xml");
http_header_add(xml->headers, "Content-ID", octstr_get_cstr(envloc));
xml->body = headers_to_soapxml(hh);
list_append(mime->multiparts, xml);
list_append(mime->multiparts, c);
http_destroy_headers(hh);
ctype = octstr_format("multipart/related"
"; start=\"%S\""
#if 0
"; type=text/xml"
#endif
,
envloc);
octstr_destroy(envloc);
octstr_destroy(cloc);
octstr_destroy(cloc_str);
} else {
ctype = octstr_imm("text/xml");
mime->body = headers_to_soapxml(m->envelope);
}
http_header_add(mime->headers, "Content-Type", octstr_get_cstr(ctype));
http_header_add(mime->headers, "SOAPAction", "\"\"");
mime_entity_body_and_headers(mime, body, hdrs);
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) ? list_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 == '+')
list_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 = list_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;
/* 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) {
if (mms_string_to_reports(s) >= 0)
mms_replace_header_value(msg, "X-Mms-Delivery-Report", octstr_get_cstr(s));
octstr_destroy(s);
}
if ((s = http_header_value(m->envelope, octstr_imm("ReadReply"))) != NULL) {
if (mms_string_to_reports(s) >= 0)
mms_replace_header_value(msg, "X-Mms-Read-Report", octstr_get_cstr(s));
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);
}
/* Put in recipient list. XXX - really?? */
l = list_create();
get_rcptvalues(l, m->envelope, "To");
mms_replace_header_values(msg, "To", l);
list_destroy(l, (list_item_destructor_t *)octstr_destroy);
l = list_create();
get_rcptvalues(l, m->envelope, "Cc");
mms_replace_header_values(msg, "Cc", l);
list_destroy(l, (list_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;
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 ? list_len(xto) : 0; i < n; i++) { /* Add recipients. */
Octstr *xx = octstr_format("+ %S", list_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", vaspid);
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??? */
http_header_remove_all(m->msg->headers, "Subject");
http_header_remove_all(m->msg->headers, "X-Mms-Message-Type");
http_header_remove_all(m->msg->headers, "X-Mms-Message-Version");
http_header_remove_all(m->msg->headers, "From");
http_header_remove_all(m->msg->headers, "To");
http_header_remove_all(m->msg->headers, "Cc");
http_header_remove_all(m->msg->headers, "Bcc");
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 && list_len(xto) > 0) {
Octstr *xx = octstr_format("+ %S", list_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)
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", "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);
}