1352 lines
41 KiB
C
1352 lines
41 KiB
C
/*
|
|
* Mbuni - Open Source MMS Gateway
|
|
*
|
|
* MM7/SOAP message encoder/decoder and helper functions
|
|
*
|
|
* Copyright (C) 2003 - 2008, 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 time_t 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 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:
|
|
if (has_node_children(node)) { /* account for buggy senders! XXX */
|
|
skip = 1;
|
|
*sigparent = tag; /* wait for number. */
|
|
} else {
|
|
char *sx;
|
|
char *s = (void *)xmlGetProp(node, (unsigned char *)"displayOnly");
|
|
if (s && strcasecmp((char *)s, "true") == 0) /* a '-' indicates don't use this to send. */
|
|
sx = "-";
|
|
else
|
|
sx = "+";
|
|
value = octstr_format("%s %s", sx, nvalue);
|
|
if (s) xmlFree(s);
|
|
}
|
|
break;
|
|
case MM7_TAG_Content:
|
|
if ((s = xmlGetProp(node, (unsigned char *)"href")) != NULL) {
|
|
value = octstr_create((char *)s);
|
|
xmlFree(s);
|
|
}
|
|
|
|
if ((s = xmlGetProp(node, (unsigned char *)"allowAdaptations")) != NULL) {
|
|
http_header_add(headers, "allowAdaptations", (char *)s);
|
|
xmlFree(s);
|
|
}
|
|
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 = date_format_http(parse_time(nvalue));
|
|
break;
|
|
|
|
case MM7_TAG_ReplyCharging:
|
|
value = octstr_create("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 = date_format_http(parse_time((char *)s));
|
|
http_header_add(headers, "replyDeadline", octstr_get_cstr(t));
|
|
xmlFree(s);
|
|
octstr_destroy(t);
|
|
}
|
|
break;
|
|
case MM7_TAG_UACapabilities:
|
|
if ((s = xmlGetProp(node, (unsigned char *)"UAProf")) != NULL) {
|
|
value = octstr_create((void *)s);
|
|
xmlFree(s);
|
|
} else
|
|
value = octstr_create("none");
|
|
|
|
if ((s = xmlGetProp(node, (unsigned char *)"TimeStamp")) != NULL) {
|
|
time_t lt = parse_time((char *)s);
|
|
octstr_format_append(value, ",%ld", lt);
|
|
xmlFree(s);
|
|
}
|
|
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
|
|
mms_info(0, "parse.soap", NULL, "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;
|
|
octstr_strip_blanks(xml);
|
|
#if 1
|
|
debug("mms2soap", 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);
|
|
|
|
if (octstr_case_search(cloc, octstr_imm("cid:"), 0) == 0) /* skip 'cid:' part. */
|
|
loc += 4; /* XXX This should always be there, but some MMC don't put it there. */
|
|
|
|
for (i = 0, n = mime_entity_num_parts(mime); i<n; i++) {
|
|
MIMEEntity *x = mime_entity_get_part(mime, i);
|
|
List *headers = mime_entity_headers(x);
|
|
Octstr *y = headers ? http_header_value(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 ||
|
|
octstr_compare(y, cloc) == 0)) /* XXX seems wrong, but some MMC out there behave badly, so we support it */
|
|
c = mime_entity_duplicate(x);
|
|
|
|
octstr_destroy(y);
|
|
http_destroy_headers(headers);
|
|
mime_entity_destroy(x);
|
|
if (c)
|
|
break;
|
|
}
|
|
if (c)
|
|
msg = c; /* this is already a copy. */
|
|
octstr_destroy(cloc);
|
|
} else {
|
|
/* XXX Sigh! Broken MMC don't set this parameter. Lets try to be kind to them! */
|
|
int i, n = mime_entity_num_parts(mime);
|
|
int found = 0;
|
|
for (i = 0; !found && i < n; i++) {
|
|
MIMEEntity *x = mime_entity_get_part(mime,i);
|
|
List *hx = NULL;
|
|
Octstr *xctype = NULL, *xparams = NULL;
|
|
if (!x)
|
|
goto loop;
|
|
hx = mime_entity_headers(x);
|
|
get_content_type(hx, &xctype, &xparams);
|
|
|
|
if (xctype && octstr_str_case_compare(xctype, "text/xml") != 0) {
|
|
/* Found something that might be the body, since its not XML.
|
|
* Perhaps we compare bodies? For broken ones anyway, so no bother!
|
|
*/
|
|
found = 1;
|
|
msg = x;
|
|
}
|
|
loop:
|
|
if (x && !found) mime_entity_destroy(x);
|
|
if (hx) http_destroy_headers(hx);
|
|
octstr_destroy(xctype);
|
|
octstr_destroy(xparams);
|
|
}
|
|
}
|
|
|
|
smsg = gw_malloc(sizeof *smsg);
|
|
smsg->envelope = h;
|
|
smsg->msg = msg;
|
|
|
|
done:
|
|
if (mime)
|
|
mime_entity_destroy(mime);
|
|
if (start)
|
|
mime_entity_destroy(start);
|
|
|
|
octstr_destroy(xml);
|
|
return smsg;
|
|
}
|
|
|
|
static int append_address(Octstr *p, Octstr *addr_spec, char *prefix, int add_type)
|
|
{
|
|
Octstr *v = addr_spec, *z;
|
|
char *y, *typ = "";
|
|
|
|
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 || isphonenum_ex(v, 2)) &&
|
|
octstr_search_char(v, '@', 0) < 0) { /* NO '@' */
|
|
z = j>=0 ? octstr_copy(v, 2, j-2) : octstr_copy(v, 2, octstr_len(v)); /* skip the initial char that is only for info purposes. */
|
|
typ = octstr_len(z) <= 6 ? "ShortCode" : "Number";
|
|
} else {
|
|
z = octstr_copy(v, 2, octstr_len(v));
|
|
typ = "RFC2822Address";
|
|
}
|
|
|
|
octstr_strip_blanks(z);
|
|
if (add_type)
|
|
octstr_format_append(p, "<%s%s%s>%S</%s%s>\n",
|
|
prefix, typ, y, z, prefix, typ); /* as above... */
|
|
else
|
|
octstr_append(p, z);
|
|
|
|
octstr_destroy(z);
|
|
return 0;
|
|
}
|
|
|
|
static void output_rcpt(char *hdr, List *hdrs, Octstr *p, char *prefix)
|
|
{
|
|
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, "</%s%s>\n", prefix, x);
|
|
strncpy(x, octstr_get_cstr(h), sizeof x);
|
|
octstr_format_append(p, "<%s%S>\n", prefix, h);
|
|
}
|
|
octstr_destroy(h);
|
|
append_address(p, v, prefix,1); /* put the address in */
|
|
octstr_destroy(v);
|
|
}
|
|
if (x[0]) /* close it off. */
|
|
octstr_format_append(p, "</%s%s>\n", prefix, x);
|
|
|
|
http_destroy_headers(l);
|
|
}
|
|
|
|
/* compare two mm7 version xmlns strings. Crude, but should generally work. */
|
|
static int ver_compare(MM7Version_t *v1, MM7Version_t *v2)
|
|
{
|
|
return (v1->major-v2->major)*1000 + (v1->minor1-v2->minor1)*100 + (v1->minor2-v2->minor2);
|
|
}
|
|
|
|
|
|
#define XMLNSMM7 "http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-0"
|
|
#define SOAP_ENV "SOAP-ENV"
|
|
|
|
/* Construct by hand. */
|
|
static Octstr *headers_to_soapxml(List *hdrs, MM7Version_t *ver)
|
|
{
|
|
Octstr *s = octstr_create("<?xml version='1.0' encoding='UTF-8'?>\n");
|
|
Octstr *xmlns = octstr_create((ver->xmlns[0]) ? ver->xmlns : XMLNSMM7);
|
|
Octstr *p, *q, *r, *fault, *mtype;
|
|
int i, n, mtag;
|
|
time_t t;
|
|
char *prefix = ver->use_mm7_namespace ? "mm7:" : "";
|
|
char *xml_nsp = ver->use_mm7_namespace ? ":mm7" : "";
|
|
MM7Version_t min_ver = {5,1,0}; /* minimum version we deal with. */
|
|
|
|
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, "<%sTransactionID xmlns%s=\"%s\" " SOAP_ENV
|
|
":mustUnderstand=\"1\">%S</%sTransactionID>\n",
|
|
prefix, xml_nsp,
|
|
octstr_get_cstr(xmlns), p ? p : octstr_imm("none"),
|
|
prefix);
|
|
if (p)
|
|
octstr_destroy(p);
|
|
|
|
octstr_append_cstr(s, "</" SOAP_ENV ":Header>\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, "<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%S xmlns%s=\"%s\">\n", prefix, mtype, xml_nsp, octstr_get_cstr(xmlns));
|
|
|
|
/* Output the details. */
|
|
if ((p = http_header_value(hdrs, octstr_imm("MM7Version"))) != NULL) {
|
|
octstr_format_append(s, "<%sMM7Version>%S</%sMM7Version>\n", prefix, p, prefix);
|
|
octstr_destroy(p);
|
|
} else
|
|
octstr_format_append(s, "<%sMM7Version>%d.%d.%d</%sMM7Version>\n",
|
|
prefix, ver->major, ver->minor1, ver->minor2, prefix);
|
|
|
|
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_format_append(s, "<%sSenderIdentification>\n", prefix);
|
|
if (p)
|
|
octstr_format_append(s, "<%sVASPID>%S</%sVASPID>\n", prefix, p, prefix);
|
|
|
|
if (q)
|
|
octstr_format_append(s, "<%sVASID>%S</%sVASID>\n", prefix, q, prefix);
|
|
|
|
if (r) {
|
|
Octstr *xx = octstr_create("");
|
|
append_address(xx, r, prefix,
|
|
ver_compare(ver,&min_ver) > 0);
|
|
if (octstr_len(xx) > 0)
|
|
octstr_format_append(s, "<%sSenderAddress>%S</%sSenderAddress>\n", prefix, xx, prefix);
|
|
octstr_destroy(xx);
|
|
}
|
|
|
|
octstr_format_append(s, "</%sSenderIdentification>\n", prefix);
|
|
octstr_destroy(p);
|
|
octstr_destroy(q);
|
|
octstr_destroy(r);
|
|
}
|
|
|
|
p = octstr_create("");
|
|
if (mtag == MM7_TAG_SubmitReq ||
|
|
mtag == MM7_TAG_DeliverReq) { /* Multiple recipients,... */
|
|
output_rcpt("To", hdrs, p, prefix);
|
|
output_rcpt("Cc", hdrs, p, prefix);
|
|
output_rcpt("Bcc", hdrs, p, prefix);
|
|
|
|
if (octstr_len(p) > 0)
|
|
octstr_format_append(s, "<%sRecipients>\n%S</%sRecipients>\n", prefix, p, prefix);
|
|
} else if ((q = http_header_value(hdrs, octstr_imm("To"))) != NULL) {
|
|
append_address(p, q, prefix, 1);
|
|
octstr_format_append(s, "<%sRecipient>\n%S</%sRecipient>\n", prefix, p, prefix);
|
|
octstr_destroy(q);
|
|
}
|
|
octstr_destroy(p);
|
|
octstr_destroy(xmlns);
|
|
|
|
/* cycle through rest of headers. */
|
|
|
|
for (i = 0, n = gwlist_len(hdrs); i < n; i++) {
|
|
Octstr *h = NULL, *v = NULL;
|
|
char *zz, *s1, *s2;
|
|
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:
|
|
case MM7_TAG_allowAdaptations:
|
|
skip = 1;
|
|
break;
|
|
case MM7_TAG_Sender:
|
|
p = octstr_create("");
|
|
append_address(p, v, prefix, ver_compare(ver,&min_ver) > 0);
|
|
|
|
if (octstr_len(p) > 0)
|
|
octstr_format_append(s, "<%sSender>%S</%sSender>\n", prefix, p, prefix);
|
|
octstr_destroy(p);
|
|
skip = 1;
|
|
break;
|
|
case MM7_TAG_Content:
|
|
if ((p = http_header_value(hdrs, octstr_imm("allowAdaptations"))) != NULL)
|
|
p = octstr_format(" allowAdaptations=\"%S\"", p);
|
|
else
|
|
p = octstr_imm("");
|
|
octstr_format_append(s, "<%sContent href=\"%S\"%S/>\n", prefix, v,p);
|
|
octstr_destroy(p);
|
|
skip = 1;
|
|
break;
|
|
case MM7_TAG_ReplyCharging:
|
|
p = http_header_value(hdrs, octstr_imm("replyChargingSize"));
|
|
q = http_header_value(hdrs, octstr_imm("replyDeadline"));
|
|
|
|
octstr_format_append(s, "<%sReplyCharging", prefix);
|
|
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_format_append(s, "<%sStatus>\n", prefix);
|
|
if (p) {
|
|
octstr_format_append(s, "<%sStatusCode>%S</%sStatusCode>\n", prefix, p, prefix);
|
|
octstr_destroy(p);
|
|
}
|
|
if (q) {
|
|
octstr_format_append(s, "<%sStatusText>%S</%sStatusText>\n", prefix, q, prefix);
|
|
octstr_destroy(q);
|
|
}
|
|
q = http_header_value(hdrs, octstr_imm("Details"));
|
|
if (q) {
|
|
octstr_format_append(s, "<%sDetails>%S</%sDetails>\n", prefix, q, prefix);
|
|
octstr_destroy(q);
|
|
}
|
|
|
|
octstr_format_append(s, "</%sStatus>\n", prefix);
|
|
skip = 1;
|
|
break;
|
|
case MM7_TAG_UACapabilities:
|
|
s1 = octstr_get_cstr(v);
|
|
if ((s2 = strrchr(s1, ',')) != NULL) {
|
|
t = strtoul(s2 + 1, NULL, 10);
|
|
octstr_delete(v, s2-s1, octstr_len(v));
|
|
} else
|
|
t = time(NULL);
|
|
p = date_create_iso(t);
|
|
octstr_format_append(s, "<%s%S TimeStamp=\"%S\" UAProf=\"%S\"/>\n",
|
|
prefix, h, p, v);
|
|
octstr_destroy(p);
|
|
skip = 1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!skip && h && v)
|
|
octstr_format_append(s, "<%s%S>%S</%s%S>\n", prefix, h, v, prefix, h);
|
|
|
|
octstr_destroy(h);
|
|
octstr_destroy(v);
|
|
}
|
|
octstr_format_append(s, "</%s%S>\n", prefix, mtype);
|
|
octstr_destroy(mtype);
|
|
if (fault) {
|
|
octstr_append_cstr(s, "</detail>\n");
|
|
octstr_append_cstr(s, "</" SOAP_ENV ":Fault>\n");
|
|
octstr_destroy(fault);
|
|
}
|
|
|
|
octstr_append_cstr(s, "</" SOAP_ENV ":Body>\n");
|
|
octstr_append_cstr(s, "</" SOAP_ENV ":Envelope>\n");
|
|
|
|
return s;
|
|
}
|
|
|
|
int mm7_soapmsg_to_httpmsg(MSoapMsg_t *m, MM7Version_t *ver, List **hdrs, Octstr **body)
|
|
{
|
|
MIMEEntity *mime;
|
|
Octstr *ctype = NULL, *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("<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);
|
|
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 = 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,ver);
|
|
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, ver);
|
|
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", "\"\"");
|
|
mime_replace_headers(mime, headers);
|
|
http_destroy_headers(headers);
|
|
|
|
*body = mime_entity_body(mime);
|
|
*hdrs = mime_entity_headers(mime);
|
|
#if 0
|
|
debug("mms2soap", 0, "SOAP headers dump follows: ");
|
|
http_header_dump(*hdrs);
|
|
debug("mms2soap", 0, "SOAP MSG is: %s", octstr_get_cstr(*body));
|
|
#endif
|
|
mime_entity_destroy(mime);
|
|
octstr_destroy(ctype);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mm7_msgtype(MSoapMsg_t *m)
|
|
{
|
|
Octstr *typ = m != NULL ? http_header_value(m->envelope, octstr_imm("MessageType")) : NULL;
|
|
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 **uaprof,
|
|
time_t *uaprof_tstamp)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
if (uaprof) {
|
|
Octstr *s = http_header_value(m->envelope, octstr_imm("UACapabilities"));
|
|
if (uaprof_tstamp)
|
|
*uaprof_tstamp = -1;
|
|
if (s) {
|
|
char *s1 = octstr_get_cstr(s);
|
|
char *s2 = strrchr(s1, ',');
|
|
|
|
if (s2) {
|
|
*uaprof_tstamp = strtoul(s2+1, NULL, 10);
|
|
octstr_delete(s, s2-s1, octstr_len(s));
|
|
}
|
|
*uaprof = s;
|
|
}
|
|
|
|
if (uaprof_tstamp && *uaprof_tstamp <= 0) { /* Use Date field */
|
|
Octstr *s = http_header_value(m->envelope, octstr_imm("Date"));
|
|
if (s && uaprof_tstamp)
|
|
*uaprof_tstamp = 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) {
|
|
Octstr *status = r && (mms_string_to_status(r) >= 0) ? r : octstr_imm("Indeterminate");
|
|
msg = mms_deliveryreport(s ? s : octstr_imm("0000"), from, p, t, status);
|
|
} 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);
|
|
|
|
octstr_destroy(s);
|
|
octstr_destroy(p);
|
|
octstr_destroy(r);
|
|
octstr_destroy(f);
|
|
octstr_destroy(q);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return msg;
|
|
}
|
|
|
|
void mm7_soap_destroy(MSoapMsg_t *m)
|
|
{
|
|
if (m == NULL) return;
|
|
|
|
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;
|
|
}
|
|
|
|
int mm7_msgtype_to_soaptype(int mtype, int isclientside)
|
|
{
|
|
int t;
|
|
switch (mtype) {
|
|
case MMS_MSGTYPE_SEND_REQ:
|
|
case MMS_MSGTYPE_RETRIEVE_CONF:
|
|
t = isclientside ? MM7_TAG_SubmitReq : MM7_TAG_DeliverReq;
|
|
break;
|
|
case MMS_MSGTYPE_READ_ORIG_IND:
|
|
t = MM7_TAG_ReadReplyReq;
|
|
break;
|
|
case MMS_MSGTYPE_DELIVERY_IND:
|
|
t = MM7_TAG_DeliveryReportReq;
|
|
break;
|
|
case MMS_MSGTYPE_SEND_CONF:
|
|
t = isclientside ? MM7_TAG_SubmitRsp : MM7_TAG_DeliverRsp;
|
|
break;
|
|
case -1:
|
|
t = isclientside ? MM7_TAG_RSErrorRsp : MM7_TAG_VASPErrorRsp;
|
|
break;
|
|
default:
|
|
t = 0;
|
|
break;
|
|
}
|
|
return t;
|
|
}
|
|
|
|
MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto,
|
|
Octstr *transid, Octstr *srvcode,
|
|
Octstr *linkedid, int isclientside,
|
|
char *vaspid, char *vasid,
|
|
Octstr *uaprof,
|
|
time_t uaprof_tstamp,
|
|
List *hdrs)
|
|
{
|
|
int i, n, mtype = mms_messagetype(msg), mm7type = mm7_msgtype_to_soaptype(mtype, isclientside);
|
|
MSoapMsg_t *m = NULL;
|
|
Octstr *xfrom = (from != NULL) ? octstr_format("+ %S", from) : NULL, *s;
|
|
Octstr *xuaprof_val = (uaprof) ? octstr_format("%S,%ld", uaprof, uaprof_tstamp) : NULL;
|
|
int tchanged = 0;
|
|
|
|
switch(mtype) {
|
|
case MMS_MSGTYPE_SEND_REQ:
|
|
case MMS_MSGTYPE_RETRIEVE_CONF:
|
|
|
|
s = hdrs ? http_header_value(hdrs, octstr_imm("X-Mbuni-MM7-Type")) : NULL;
|
|
if (s) { /* Might be Cancel or Replace instead of Send */
|
|
mm7type = mms_string_to_mm7tag(s);
|
|
gw_assert(mm7type >= 0);
|
|
octstr_destroy(s);
|
|
tchanged = 1;
|
|
}
|
|
m = mm7_soap_create(mm7type, transid);
|
|
if (mm7type != MM7_TAG_CancelReq) /* No body for cancel */
|
|
m->msg = mms_tomime(msg,1);
|
|
|
|
strip_non_essential_headers(m->msg);
|
|
|
|
if (mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq) /* No recipients for replace and cancel*/
|
|
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);
|
|
}
|
|
else if ((s = http_header_value(hdrs, /* For replace and cancel, add message id */
|
|
octstr_imm("X-Mbuni-Message-ID"))) != NULL) {
|
|
http_header_add(m->envelope, "MessageID", octstr_get_cstr(s));
|
|
octstr_destroy(s);
|
|
}
|
|
if (srvcode && mm7type != MM7_TAG_CancelReq)
|
|
http_header_add(m->envelope,
|
|
isclientside ? "ServiceCode" : "MMSRelayServerID",
|
|
octstr_get_cstr(srvcode));
|
|
|
|
if (linkedid && mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq)
|
|
http_header_add(m->envelope, "LinkedID", octstr_get_cstr(linkedid));
|
|
if (xfrom)
|
|
http_header_add(m->envelope,
|
|
isclientside ? "SenderAddress" : "Sender",
|
|
octstr_get_cstr(xfrom));
|
|
|
|
|
|
if (isclientside) {
|
|
Octstr *distrib_indicator = hdrs ? http_header_value(hdrs, octstr_imm("X-Mbuni-DistributionIndicator")) : NULL;
|
|
Octstr *cparty = hdrs ? http_header_value(hdrs, octstr_imm("X-Mbuni-Charged-Party")) : NULL;
|
|
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) {
|
|
if (mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq)
|
|
http_header_add(m->envelope, "MessageClass", octstr_get_cstr(s));
|
|
octstr_destroy(s);
|
|
}
|
|
|
|
/* Track adaptations stuff -- Vincent */
|
|
if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Allow-Adaptations"))) != NULL) {
|
|
char *val = (octstr_case_compare(s, octstr_imm("true")) == 0) ?
|
|
"true" : "false";
|
|
if (mm7type != MM7_TAG_CancelReq)
|
|
http_header_add(m->envelope, "allowAdaptations", val);
|
|
octstr_destroy(s);
|
|
}
|
|
|
|
if (distrib_indicator && mm7type != MM7_TAG_CancelReq)
|
|
http_header_add(m->envelope, "DistributionIndicator",
|
|
octstr_str_case_compare(distrib_indicator, "true") == 0 ? "true" : "false");
|
|
if (cparty && mm7type != MM7_TAG_CancelReq)
|
|
http_header_add(m->envelope, "ChargedParty",
|
|
octstr_get_cstr(cparty));
|
|
|
|
octstr_destroy(distrib_indicator);
|
|
octstr_destroy(cparty);
|
|
} else { /* not clientside. */
|
|
if (xuaprof_val && mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq) /* only on DeliverReq. */
|
|
http_header_add(m->envelope, "UACapabilities", octstr_get_cstr(xuaprof_val));
|
|
}
|
|
|
|
if ((s = mms_get_header_value(msg, octstr_imm("Date"))) != NULL) {
|
|
if (mm7type != MM7_TAG_CancelReq)
|
|
http_header_add(m->envelope, "TimeStamp", octstr_get_cstr(s));
|
|
octstr_destroy(s);
|
|
}
|
|
|
|
if (isclientside) { /* We need this twice because of stupid parsers out there that
|
|
* care about the order of XML fields.
|
|
*/
|
|
if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Expiry"))) != NULL) {
|
|
if (mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq)
|
|
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";
|
|
if (mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq)
|
|
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";
|
|
if (mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq)
|
|
http_header_add(m->envelope, "ReadReply", val);
|
|
octstr_destroy(s);
|
|
}
|
|
|
|
}
|
|
|
|
if ((s = mms_get_header_value(msg, octstr_imm("X-Mms-Priority"))) != NULL) {
|
|
if (mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq)
|
|
http_header_add(m->envelope, "Priority", octstr_get_cstr(s));
|
|
octstr_destroy(s);
|
|
}
|
|
|
|
if ((s = mms_get_header_value(msg, octstr_imm("Subject"))) != NULL) {
|
|
if (mm7type != MM7_TAG_CancelReq && mm7type != MM7_TAG_ReplaceReq)
|
|
http_header_add(m->envelope, "Subject", octstr_get_cstr(s));
|
|
octstr_destroy(s);
|
|
}
|
|
|
|
#if 0 /* handled above. */
|
|
/* Should we bother to strip message part of headers??? */
|
|
headers = 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, "X-Mms-Allow-Adaptations");
|
|
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);
|
|
#endif
|
|
break;
|
|
case MMS_MSGTYPE_READ_ORIG_IND:
|
|
case MMS_MSGTYPE_DELIVERY_IND:
|
|
m = mm7_soap_create(mm7type, transid);
|
|
|
|
if (xfrom)
|
|
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);
|
|
}
|
|
|
|
if (mtype == MMS_MSGTYPE_DELIVERY_IND &&
|
|
xuaprof_val) /* and for DeliveryReport. */
|
|
http_header_add(m->envelope, "UACapabilities", octstr_get_cstr(xuaprof_val));
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (m) { /* Add custom headers, hope caller knows what they are doing */
|
|
List *l = hdrs ? http_header_find_all(hdrs, "X-Mbuni-MM7-Headers") : NULL;
|
|
int i, n;
|
|
|
|
|
|
for (i = 0, n = gwlist_len(l); i<n; i++) {
|
|
Octstr *name = NULL, *value = NULL;
|
|
int j;
|
|
|
|
http_header_get(l, i, &name, &value);
|
|
|
|
if (value && (j = octstr_search_char(value, ':', 0)) > 0) {
|
|
Octstr *h = octstr_copy(value, 0, j);
|
|
Octstr *v = octstr_copy(value, j+1, octstr_len(value));
|
|
|
|
octstr_strip_blanks(h);
|
|
octstr_strip_blanks(v);
|
|
|
|
http_header_add(m->envelope, octstr_get_cstr(h), octstr_get_cstr(v));
|
|
|
|
octstr_destroy(h);
|
|
octstr_destroy(v);
|
|
}
|
|
octstr_destroy(name);
|
|
octstr_destroy(value);
|
|
}
|
|
http_destroy_headers(l);
|
|
}
|
|
octstr_destroy(xfrom);
|
|
octstr_destroy(xuaprof_val);
|
|
|
|
return m;
|
|
}
|
|
|
|
MSoapMsg_t *mm7_make_resp(MSoapMsg_t *mreq, int status, Octstr *msgid, int isclientside)
|
|
{
|
|
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(isclientside ? MM7_TAG_VASPErrorRsp : 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);
|
|
}
|
|
|
|
List *mm7_soap_headers(MSoapMsg_t *m)
|
|
{
|
|
List *l;
|
|
int i;
|
|
|
|
if (m == NULL)
|
|
return NULL;
|
|
|
|
l = http_create_empty_headers();
|
|
for (i = 0; i < gwlist_len(m->envelope); i++) {
|
|
Octstr *n = NULL, *v = NULL;
|
|
|
|
http_header_get(m->envelope, i, &n, &v);
|
|
|
|
if (!n || !v)
|
|
goto loop;
|
|
if (octstr_str_case_compare(n, "From") == 0 ||
|
|
octstr_str_case_compare(n, "To") == 0 ||
|
|
octstr_str_case_compare(n, "Sender") == 0 ||
|
|
octstr_str_case_compare(n, "Cc") == 0 ||
|
|
octstr_str_case_compare(n, "Bcc") == 0 ||
|
|
octstr_str_case_compare(n, "SenderAddress") == 0) {
|
|
if (octstr_get_char(v, 0) == '+')
|
|
octstr_delete(v, 0, 2);
|
|
}
|
|
http_header_add(l, octstr_get_cstr(n), octstr_get_cstr(v));
|
|
loop:
|
|
octstr_destroy(n);
|
|
octstr_destroy(v);
|
|
}
|
|
return l;
|
|
}
|