1
0
Fork 0

First implementation of mmsbox functionality, making Mbuni provide client-side VAS functionality,

similar to that provided by Kannel for SMS.
This commit is contained in:
bagyenda 2005-09-07 10:10:41 +00:00
parent fc0524057e
commit 4ceeeb8128
22 changed files with 2276 additions and 157 deletions

View File

@ -717,8 +717,8 @@ diff -Naur gateway-1.4.0/gw/xml_shared.h gateway/gw/xml_shared.h
/*
diff -Naur gateway-1.4.0/gwlib/cfg.def gateway/gwlib/cfg.def
--- gateway-1.4.0/gwlib/cfg.def 2004-06-28 18:18:35.000000000 +0300
+++ gateway/gwlib/cfg.def 2005-09-02 13:50:06.000000000 +0300
@@ -544,6 +544,106 @@
+++ gateway/gwlib/cfg.def 2005-09-05 11:30:55.000000000 +0300
@@ -544,6 +544,113 @@
OCTSTR(unified-prefix)
)
@ -792,6 +792,8 @@ diff -Naur gateway-1.4.0/gwlib/cfg.def gateway/gwlib/cfg.def
+ OCTSTR(username)
+ OCTSTR(password)
+ OCTSTR(faked-sender)
+ OCTSTR(delivery-report-url)
+ OCTSTR(read-report-url)
+)
+
+MULTI_GROUP(mmsc,
@ -800,6 +802,10 @@ diff -Naur gateway-1.4.0/gwlib/cfg.def gateway/gwlib/cfg.def
+ OCTSTR(incoming-username)
+ OCTSTR(incoming-password)
+ OCTSTR(incoming-port)
+ OCTSTR(allow-ip)
+ OCTSTR(deny-ip)
+ OCTSTR(allowed-prefix)
+ OCTSTR(denied-prefix)
+ OCTSTR(incoming-port-ssl)
+ OCTSTR(max-throughput)
+ OCTSTR(type)
@ -818,6 +824,7 @@ diff -Naur gateway-1.4.0/gwlib/cfg.def gateway/gwlib/cfg.def
+ OCTSTR(accept-x-mbuni-headers)
+ OCTSTR(assume-plain-text)
+ OCTSTR(accepted-mmscs)
+ OCTSTR(denied-mmscs)
+ OCTSTR(keyword)
+ OCTSTR(aliases)
+ OCTSTR(http-post-parameters)

View File

@ -847,7 +847,9 @@ static MSoapMsg_t *mm7_soap_create(int msgtype, Octstr *otransid)
}
MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto,
Octstr *transid, Octstr *serverID)
Octstr *transid, Octstr *srvcode,
int isclientside,
char *vaspid, char *vasid)
{
int mtype = mms_messagetype(msg);
MSoapMsg_t *m = NULL;
@ -859,7 +861,8 @@ MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto,
switch(mtype) {
case MMS_MSGTYPE_SEND_REQ:
case MMS_MSGTYPE_RETRIEVE_CONF:
m = mm7_soap_create(MM7_TAG_DeliverReq, transid);
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. */
@ -869,10 +872,47 @@ MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto,
octstr_destroy(xx);
}
if (serverID)
http_header_add(m->envelope, "MMSRelayServerID", octstr_get_cstr(serverID));
if (srvcode)
http_header_add(m->envelope,
isclientside ? "ServiceCode" : "MMSRelayServerID",
octstr_get_cstr(srvcode));
http_header_add(m->envelope, "LinkedID", octstr_get_cstr(transid));
http_header_add(m->envelope, "Sender", octstr_get_cstr(xfrom));
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));

View File

@ -39,7 +39,9 @@ extern void mm7_soap_destroy(MSoapMsg_t *m);
/* Convert a message to a SOAP message. */
MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto,
Octstr *transid, Octstr *serverID);
Octstr *transid, Octstr *srvcode,
int isclientside,
char *vaspid, char *vasid);
MSoapMsg_t *mm7_make_resp(MSoapMsg_t *mreq, int status, Octstr *msgid);
/* Return the header value for some header. */
Octstr *mm7_soap_header_value(MSoapMsg_t *m, Octstr *header);

View File

@ -35,17 +35,6 @@
#define ITEM_DEL 2
#define ITEM_MOD 3
static unsigned long hash(char *s)
{
unsigned h = 0;
while (*s) {
unsigned int ch = tolower(*s);
s++;
h += ((unsigned)(ch) << 4) + 1249;
}
return h;
}
/* Initialise the root of the mmbox. Should be called once from load settings. */
@ -82,7 +71,7 @@ int mmbox_root_init(char *mmbox_root)
static Octstr *user_mmbox_dir(char *mmbox_root, char *userid)
{
unsigned long h = hash(userid);
unsigned long h = _mshash(userid);
char d1[2], d2[3], fbuf[512];
Octstr *t, *s;

View File

@ -89,6 +89,8 @@ static int free_envelope(MmsEnvelope *e, int removefromqueue);
* M - Application specific data (string)
* V - VASID -- from VASP
* v - vasid -- from VASP
* U - url1 -- e.g. for delivery report
* u - url2 -- e.g. for read report
*/
@ -267,6 +269,15 @@ MmsEnvelope *mms_queue_readenvelope(char *qf, char *mms_queuedir, int shouldbloc
case 'v':
e->vasid = octstr_create(res);
break;
case 'U':
e->url1 = octstr_create(res);
break;
case 'u':
e->url2 = octstr_create(res);
break;
case '.':
okfile = 1;
break;
@ -412,6 +423,11 @@ static int writeenvelope(MmsEnvelope *e, int newenv)
if (e->vasid)
_putline(fd, "v", octstr_get_cstr(e->vasid));
if (e->url1)
_putline(fd, "U", octstr_get_cstr(e->url1));
if (e->url2)
_putline(fd, "u", octstr_get_cstr(e->url2));
if (e->dlr)
_putline(fd, "r", "Yes");
@ -602,6 +618,7 @@ Octstr *mms_queue_add(Octstr *from, List *to,
Octstr *fromproxy, Octstr *viaproxy,
time_t senddate, time_t expirydate, MmsMsg *m, Octstr *token,
Octstr *vaspid, Octstr *vasid,
Octstr *url1, Octstr *url2,
int dlr,
char *directory, Octstr *mmscname)
{
@ -652,6 +669,8 @@ Octstr *mms_queue_add(Octstr *from, List *to,
e->token = token;
e->vaspid = vaspid;
e->vasid = vasid;
e->url1 = url1;
e->url2 = url2;
e->dlr = dlr;
e->bill.billed = 0;
@ -702,12 +721,14 @@ Octstr *mms_queue_add(Octstr *from, List *to,
gw_free(to);
}
list_destroy(e->to, NULL);
gw_free(e);
gw_free(e); /* Free struct only, caller responsible for arguments. */
octstr_destroy(ms);
octstr_destroy(msgid);
if (xfrom)
octstr_destroy(xfrom);
return res;
}
@ -741,6 +762,18 @@ static int free_envelope(MmsEnvelope *e, int removefromqueue)
if (e->subject)
octstr_destroy(e->subject);
if (e->vaspid)
octstr_destroy(e->vaspid);
if (e->vasid)
octstr_destroy(e->vasid);
if (e->url1)
octstr_destroy(e->url1);
if (e->url2)
octstr_destroy(e->url2);
if (removefromqueue) {
char fname[2*QFNAMEMAX];

View File

@ -34,9 +34,12 @@ typedef struct MmsEnvelope {
Octstr *from; /* from address. */
Octstr *vaspid; /* VASPID (if any) */
Octstr *vasid; /* VASID (if any) */
List *to; /* List of recipients: MmsEnvelopeTo */
Octstr *vasid; /* VASID (if any) */
Octstr *url1; /* Generic URLs (2) associated with message. */
Octstr *url2;
List *to; /* List of recipients: MmsEnvelopeTo */
Octstr *subject; /* Message subject (if any). */
@ -60,6 +63,10 @@ typedef struct MmsEnvelope {
Octstr *mdata; /* Generic string data used by any interface. */
Octstr *fromproxy; /* Which proxy sent us this message.*/
Octstr *viaproxy; /* Which proxy must we send this message through. */
void *_x; /* Generic storage field used by module clients. */
/* DO NOT MODIFY ANYTHING BEYOND THIS POINT. */
struct { /* Name of the queue file, pointer to it (locked). DO NOT USE THESE! */
char name[QFNAMEMAX]; /* Name of the file. */
char dir[QFNAMEMAX]; /* Directory in which file is .*/
@ -82,6 +89,7 @@ extern Octstr *mms_queue_add(Octstr *from, List *to,
Octstr *fromproxy, Octstr *viaproxy,
time_t senddate, time_t expirydate, MmsMsg *m, Octstr *token,
Octstr *vaspid, Octstr *vasid,
Octstr *url1, Octstr *url2,
int dlr,
char *directory, Octstr *mmscname);

View File

@ -253,7 +253,6 @@ VNSTRING(MM7_5, "Content",MM7_TAG_Content)
VNSTRING(MM7_5, "Date",MM7_TAG_Date)
VNSTRING(MM7_5, "DeliverReq",MM7_TAG_DeliverReq)
VNSTRING(MM7_5, "DeliverRsp",MM7_TAG_DeliverRsp)
VNSTRING(MM7_5, "DeliveryReport",MM7_TAG_DeliveryReport)
VNSTRING(MM7_5, "DeliveryReportReq",MM7_TAG_DeliveryReportReq)
VNSTRING(MM7_5, "DeliveryReportRsp",MM7_TAG_DeliveryReportRsp)
VNSTRING(MM7_5, "DistributionIndicator",MM7_TAG_DistributionIndicator)
@ -269,7 +268,6 @@ VNSTRING(MM7_5, "Number",MM7_TAG_Number)
VNSTRING(MM7_5, "Priority",MM7_TAG_Priority)
VNSTRING(MM7_5, "RFC2822Address",MM7_TAG_RFC2822Address)
VNSTRING(MM7_5, "RSErrorRsp",MM7_TAG_RSErrorRsp)
VNSTRING(MM7_5, "ReadReply",MM7_TAG_ReadReply)
VNSTRING(MM7_5, "ReadReplyReq",MM7_TAG_ReadReplyReq)
VNSTRING(MM7_5, "ReadReplyRsp",MM7_TAG_ReadReplyRsp)
VNSTRING(MM7_5, "Recipient",MM7_TAG_Recipient)

View File

@ -830,3 +830,124 @@ MIMEEntity *mime_entity_duplicate(MIMEEntity *m)
return mx;
}
void mms_collect_envdata_from_msgheaders(List *mh, List **xto,
Octstr **subject,
Octstr **otransid, time_t *expiryt,
time_t *deliveryt, long default_msgexpiry)
{
Octstr *s;
List *l = http_header_find_all(mh, "To");
if (l) {
int i, n;
for (i = 0, n = list_len(l); i<n; i++) {
Octstr *name, *value;
http_header_get(l, i, &name, &value);
list_append(*xto, value);
octstr_destroy(name);
}
http_destroy_headers(l);
}
l = http_header_find_all(mh, "Cc");
if (l) {
int i, n;
for (i = 0, n = list_len(l); i<n; i++) {
Octstr *name, *value;
http_header_get(l, i, &name, &value);
list_append(*xto, value);
octstr_destroy(name);
}
http_destroy_headers(l);
}
l = http_header_find_all(mh, "Bcc");
if (l) {
int i, n;
for (i = 0, n = list_len(l); i<n; i++) {
Octstr *name, *value;
http_header_get(l, i, &name, &value);
list_append(*xto, value);
octstr_destroy(name);
}
http_destroy_headers(l);
}
/* Find expiry and delivery times */
if (expiryt) {
s = http_header_value(mh, octstr_imm("X-Mms-Expiry"));
if (s) {
*expiryt = date_parse_http(s);
octstr_destroy(s);
} else
*expiryt = time(NULL) + default_msgexpiry;
}
if (deliveryt) {
s = http_header_value(mh, octstr_imm("X-Mms-Delivery-Time"));
if (s) {
*deliveryt = date_parse_http(s);
octstr_destroy(s);
} else
*deliveryt = 0;
}
if (subject)
*subject = http_header_value(mh, octstr_imm("Subject"));
if (otransid)
*otransid = http_header_value(mh, octstr_imm("X-Mms-Transaction-ID"));
}
unsigned long _mshash(char *s)
{
unsigned h = 0;
while (*s) {
unsigned int ch = tolower(*s);
s++;
h += ((unsigned)(ch) << 4) + 1249;
}
return h;
}
int isphonenum(Octstr *s)
{
int i = 0, n = octstr_len(s);
char *cs;
if (s && octstr_len(s) >= 1 &&
octstr_get_cstr(s)[0] == '+')
i++;
for ( cs = octstr_get_cstr(s); i<n; i++)
if (!gw_isdigit(cs[i]))
return 0;
return 1;
}
/* Doesn't handle IP addresses. */
void _mms_fixup_address(Octstr *address)
{
int i;
if (!address) return;
i = octstr_search_char(address, '@', 0);
if (i>0)
return;
i = octstr_search(address, octstr_imm("/TYPE="), 0);
if (i > 0)
return;
if (isphonenum(address))
octstr_append(address, octstr_imm("/TYPE=PLMN"));
else
octstr_append(address, octstr_imm("@unknown"));
}

View File

@ -19,7 +19,7 @@
#include "config.h"
#include "mms_strings.h"
#include "mms_msg.h"
#include "mms_mm7soap.h"
#include "mms_mmbox.h"
@ -49,6 +49,7 @@
/* Message location flags: Used to distinguish fetch-urls */
enum mms_loc_t {MMS_LOC_MMBOX = 1, MMS_LOC_MQUEUE=2};
extern int mms_load_core_settings(CfgGroup *cgrp);
extern Octstr *mms_maketransid(char *qf, Octstr *mmscname);
@ -124,4 +125,22 @@ int _mms_gw_isprint(int c);
/* Special form of cfg_get which returns zero-length string when there is nothing. */
Octstr *_mms_cfg_getx(CfgGroup *grp, Octstr *item);
/* Get envelope data from message headers. */
void mms_collect_envdata_from_msgheaders(List *mh, List **xto,
Octstr **subject,
Octstr **otransid, time_t *expiryt,
time_t *deliveryt, long default_msgexpiry);
/* Simple hash function */
unsigned long _mshash(char *s);
/* Tell us whether address is a phone number. */
int isphonenum(Octstr *s);
/* Fixup an address: Add type, etc. */
void _mms_fixup_address(Octstr *address);
#define MAXQTRIES 100
#define BACKOFF_FACTOR 5*60 /* In seconds */
#define QUEUERUN_INTERVAL 15*60 /* 15 minutes. */
#define DEFAULT_EXPIRE 3600*24*7 /* One week */
#endif

View File

@ -51,7 +51,8 @@ CONFIG_CLEAN_FILES =
am__installdirs = "$(DESTDIR)$(bindir)"
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(bin_PROGRAMS)
am_mmsbox_OBJECTS = mmsbox.$(OBJEXT) mmsbox_cfg.$(OBJEXT)
am_mmsbox_OBJECTS = mmsbox.$(OBJEXT) mmsbox_cfg.$(OBJEXT) \
dlr.$(OBJEXT) bearerbox.$(OBJEXT)
mmsbox_OBJECTS = $(am_mmsbox_OBJECTS)
mmsbox_LDADD = $(LDADD)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
@ -81,7 +82,7 @@ AUTOMAKE = ${SHELL} /Users/bagyenda/src/mbuni/missing --run automake-1.9
AWK = gawk
CC = gcc
CCDEPMODE = depmode=gcc3
CFLAGS = -I./../mmlib -g -O2 -DDARWIN=1 -I/sw/include -I/usr/local/include/kannel -DDARWIN=1 -I/sw/include/libxml2 -I/sw/include -I/sw/include
CFLAGS = -I./../mmlib -g -Wall -O2 -DDARWIN=1 -I/sw/include -I/usr/local/include/kannel -DDARWIN=1 -I/sw/include/libxml2 -I/sw/include -I/sw/include
CPP = gcc -E
CPPFLAGS =
CXX = g++
@ -169,7 +170,7 @@ sbindir = ${exec_prefix}/sbin
sharedstatedir = ${prefix}/com
sysconfdir = ${prefix}/etc
target_alias =
mmsbox_SOURCES = mmsbox.c mmsbox_cfg.c
mmsbox_SOURCES = mmsbox.c mmsbox_cfg.c dlr.c bearerbox.c
all: all-am
.SUFFIXES:
@ -241,6 +242,8 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
include ./$(DEPDIR)/bearerbox.Po
include ./$(DEPDIR)/dlr.Po
include ./$(DEPDIR)/mmsbox.Po
include ./$(DEPDIR)/mmsbox_cfg.Po

View File

@ -1,3 +1,3 @@
bin_PROGRAMS = mmsbox
mmsbox_SOURCES = mmsbox.c mmsbox_cfg.c
mmsbox_SOURCES = mmsbox.c mmsbox_cfg.c dlr.c bearerbox.c

833
mbuni/mmsbox/bearerbox.c Normal file
View File

@ -0,0 +1,833 @@
/*
* Mbuni - Open Source MMS Gateway
*
* MMSC handler functions: Receive and send MMS messages to MMSCs
*
* 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 <sys/file.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mmsbox.h"
#include "mms_queue.h"
#include "mmsbox.h"
typedef struct MmsHTTPClientInfo {
HTTPClient *client;
Octstr *ua;
Octstr *ip;
List *headers;
Octstr *url;
Octstr *body;
List *cgivars;
MmscGrp *m;
} MmsHTTPClientInfo;
static void free_clientInfo(MmsHTTPClientInfo *h, int freeh);
static int auth_check(Octstr *user, Octstr *pass, List *headers)
{
int i, res = -1;
Octstr *v = http_header_value(headers, octstr_imm("Authorization"));
Octstr *p = NULL, *q = NULL;
if (!v ||
octstr_search(v, octstr_imm("Basic "), 0) != 0)
goto done;
p = octstr_copy(v, sizeof "Basic", octstr_len(v));
octstr_base64_to_binary(p);
i = octstr_search_char(p, ':', 0);
q = octstr_copy(p, i+1, octstr_len(p));
octstr_delete(p, i, octstr_len(p));
/* p = user, q = pass. */
if (octstr_compare(user, p) != 0 ||
octstr_compare(pass, q) != 0)
res = -1;
else
res = 0;
done:
if (v)
octstr_destroy(v);
if (p)
octstr_destroy(p);
if (q)
octstr_destroy(q);
return res;
}
static int send_report(Octstr *from, char *report_type, Octstr *status, Octstr *msgid, Octstr *mmc_id)
{
Octstr *url = mms_dlr_url_get(msgid, report_type, mmc_id);
List *rh, *rph = NULL;
Octstr *furl = NULL, *rb = NULL;
if (!url)
return 0;
rh = http_create_empty_headers();
http_header_add(rh, "X-Mbuni-Report-Type", report_type);
http_header_add(rh, "X-Mbuni-MM-Status", octstr_get_cstr(status));
http_header_add(rh, "X-Mbuni-Message-ID", octstr_get_cstr(msgid));
http_header_add(rh, "X-Mbuni-MMSC-ID", octstr_get_cstr(mmc_id));
http_header_add(rh, "X-Mbuni-From", octstr_get_cstr(from));
http_get_real(HTTP_METHOD_GET, url, rh, &furl, &rph, &rb);
if (furl)
octstr_destroy(furl);
if (rb)
octstr_destroy(rb);
octstr_destroy(url);
if (rph)
http_destroy_headers(rph);
http_destroy_headers(rh);
/* At what point do we delete it? For now, when we get a read report,
* and also when we get a delivery report that is not 'deferred'
*/
if (strcmp(report_type, "read-report") == 0 ||
octstr_case_compare(status, octstr_imm("Deferred")) != 0)
mms_dlr_url_remove(msgid, report_type, mmc_id);
return 0;
}
/* These functions are very similar to those in mmsproxy */
static void mm7soap_receive(MmsHTTPClientInfo *h)
{
MSoapMsg_t *mreq = NULL, *mresp = NULL;
int hstatus = HTTP_OK;
List *rh = NULL;
Octstr *reply_body = NULL, *value;
List *to = NULL;
Octstr *from = NULL, *subject = NULL, *vasid = NULL, *msgid = NULL;
time_t expiryt = -1, delivert = -1;
MmsMsg *m = NULL;
int status = 1000;
unsigned char *msgtype = (unsigned char *)"";
Octstr *qf = NULL;
if (h->body)
mreq = mm7_parse_soap(h->headers, h->body);
if (mreq)
msgtype = mms_mm7tag_to_cstr(mm7_msgtype(mreq));
debug("mmsbox.mm7sendinterface", 0,
" --> Enterred mm7dispatch interface, mreq=%s mtype = %s <-- ",
mreq ? "Ok" : "Null",
mreq ? (char *)msgtype : "Null");
if (!mreq) {
mresp = mm7_make_resp(NULL, MM7_SOAP_FORMAT_CORRUPT, NULL);
goto done;
}
mm7_get_envelope(mreq, &from, &to, &subject, &vasid, &expiryt, &delivert);
if (!from)
from = octstr_imm("anon@anon");
switch (mm7_msgtype(mreq)) {
case MM7_TAG_DeliverReq:
m = mm7_soap_to_mmsmsg(mreq, from);
if (m) {
Octstr *value;
int dlr;
value = mms_get_header_value(m, octstr_imm("X-Mms-Delivery-Report"));
if (value &&
octstr_case_compare(value, octstr_imm("Yes")) == 0)
dlr = 1;
else
dlr = 0;
if (delivert < 0)
delivert = time(NULL);
if (expiryt < 0)
expiryt = time(NULL) + DEFAULT_EXPIRE;
qf = mms_queue_add(from, to, subject,
h->m->id, NULL,
delivert, expiryt, m, NULL,
NULL, NULL,
NULL, NULL,
dlr,
octstr_get_cstr(incoming_qdir),
octstr_imm(MM_NAME));
msgid = mms_maketransid(octstr_get_cstr(qf), octstr_imm(MM_NAME));
mms_log("Received", from, to, -1, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL);
octstr_destroy(value);
} else
status = 4000;
mresp = mm7_make_resp(mreq, status, msgid);
break;
case MM7_TAG_DeliveryReportReq:
msgid = mm7_soap_header_value(mreq, octstr_imm("MessageID"));
value = mm7_soap_header_value(mreq, octstr_imm("MMStatus"));
send_report(from, "delivery-report", value, msgid, h->m->id);
if (value)
octstr_destroy(value);
mms_log("DeliveryReport",
from, NULL, -1, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL);
mresp = mm7_make_resp(mreq, status, NULL);
break;
case MM7_TAG_ReadReplyReq:
msgid = mm7_soap_header_value(mreq, octstr_imm("MessageID"));
value = mm7_soap_header_value(mreq, octstr_imm("MMStatus"));
send_report(from, "read-report", value, msgid, h->m->id);
if (value)
octstr_destroy(value);
mms_log("ReadReport",
from, NULL, -1, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL);
mresp = mm7_make_resp(mreq, status, NULL);
break;
default:
mresp = mm7_make_resp(mreq, MM7_SOAP_UNSUPPORTED_OPERATION, NULL);
break;
}
done:
if (mresp && mm7_soapmsg_to_httpmsg(mresp, &rh, &reply_body) == 0)
http_send_reply(h->client, hstatus, rh, reply_body);
else
http_close_client(h->client);
debug("mmsbox.mm7sendinterface", 0,
" --> leaving mm7dispatch interface, mresp=%s, body=%s <-- ",
mresp ? "ok" : "(null)",
reply_body ? "ok" : "(null)");
if (from)
octstr_destroy(from);
if (subject)
octstr_destroy(subject);
if (vasid)
octstr_destroy(vasid);
if (msgid)
octstr_destroy(msgid);
if (qf)
octstr_destroy(qf);
if (m)
mms_destroy(m);
if (rh)
http_destroy_headers(rh);
if (reply_body)
octstr_destroy(reply_body);
if (mresp)
mm7_soap_destroy(mresp);
if (mreq)
mm7_soap_destroy(mreq);
if (to)
list_destroy(to, (list_item_destructor_t *)octstr_destroy);
}
static void mm7eaif_receive(MmsHTTPClientInfo *h)
{
MmsMsg *m = NULL;
List *mh = NULL;
int hstatus = HTTP_NO_CONTENT;
List *rh = http_create_empty_headers();
Octstr *reply_body = NULL, *value, *value2;
List *to = list_create(), *hto = NULL;
Octstr *subject = NULL, *otransid = NULL, *msgid = NULL;
Octstr *hfrom = NULL;
time_t expiryt = -1, deliveryt = -1;
Octstr *qf = NULL;
int msize = h->body ? octstr_len(h->body) : 0;
int dlr;
int mtype;
debug("mmsbox.mm7eaif.sendinterface", 0,
" --> Enterred eaif send interface, blen=%d <--- ",
msize);
hfrom = http_header_value(h->headers, octstr_imm("X-NOKIA-MMSC-From"));
if (!h->body || /* A body is required, and must parse */
(m = mms_frombinary(h->body, hfrom ? hfrom : octstr_imm("anon@anon"))) == NULL) {
http_header_add(rh, "Content-Type", "text/plain");
hstatus = HTTP_BAD_REQUEST;
reply_body = octstr_format("Unexpected MMS message, no body?");
goto done;
}
/* XXXX handle delivery reports differently. */
mtype = mms_messagetype(m);
mh = mms_message_headers(m);
/* Now get sender and receiver data.
* for now we ignore adaptation flags.
*/
mms_collect_envdata_from_msgheaders(mh, &to, &subject,
&otransid, &expiryt, &deliveryt,
DEFAULT_EXPIRE);
if ((hto = http_header_find_all(h->headers, "X-NOKIA-MMSC-To")) != NULL &&
list_len(hto) > 0) { /* To address is in headers. */
int i, n;
if (to)
list_destroy(to, (list_item_destructor_t *)octstr_destroy);
to = list_create();
for (i = 0, n = list_len(hto); i < n; i++) {
Octstr *h = NULL, *v = NULL;
List *l;
int j, m;
http_header_get(hto,i, &h, &v);
l = http_header_split_value(v);
for (j = 0, m = list_len(l); j < m; j++)
list_append(to, list_get(l, j));
list_destroy(l, NULL);
if (h) octstr_destroy(h);
if (v) octstr_destroy(v);
}
}
switch(mtype) {
case MMS_MSGTYPE_SEND_REQ:
/* Get Message ID */
if ((msgid = http_header_value(h->headers, octstr_imm("X-NOKIA-MMSC-Message-Id"))) == NULL)
msgid = http_header_value(mh, octstr_imm("Message-ID"));
value = http_header_value(mh, octstr_imm("X-Mms-Delivery-Report"));
if (value &&
octstr_case_compare(value, octstr_imm("Yes")) == 0)
dlr = 1;
else
dlr = 0;
if (value)
octstr_destroy(value);
if (deliveryt < 0)
deliveryt = time(NULL);
if (expiryt < 0)
expiryt = time(NULL) + DEFAULT_EXPIRE;
if (hfrom == NULL)
hfrom = http_header_value(mh, octstr_imm("From"));
mms_remove_headers(m, "Bcc");
mms_remove_headers(m, "X-Mms-Delivery-Time");
mms_remove_headers(m, "X-Mms-Expiry");
mms_remove_headers(m, "X-Mms-Sender-Visibility");
/* Save it, put message id in header, return. */
qf = mms_queue_add(hfrom, to, subject,
h->m->id, NULL, deliveryt, expiryt, m, NULL,
NULL, NULL,
NULL, NULL,
dlr,
octstr_get_cstr(incoming_qdir),
octstr_imm(MM_NAME));
if (qf) {
/* Log to access log */
mms_log("Received", hfrom, to, msize, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL);
octstr_destroy(qf);
hstatus = HTTP_NO_CONTENT;
} else
hstatus = HTTP_INTERNAL_SERVER_ERROR;
break;
case MMS_MSGTYPE_DELIVERY_IND:
value = http_header_value(mh, octstr_imm("X-Mms-Status"));
value2 = http_header_value(mh, octstr_imm("Message-ID"));
send_report(hfrom, "delivery-report", value, value2, h->m->id);
if (value)
octstr_destroy(value);
if (value2)
octstr_destroy(value2);
break;
case MMS_MSGTYPE_READ_ORIG_IND:
value = http_header_value(mh, octstr_imm("X-Mms-Read-Status"));
value2 = http_header_value(mh, octstr_imm("Message-ID"));
send_report(hfrom, "read-report", value, value2, h->m->id);
if (value)
octstr_destroy(value);
if (value2)
octstr_destroy(value2);
break;
}
done:
http_header_add(rh, "X-NOKIA-MMSC-Version", EAIF_VERSION);
http_send_reply(h->client, hstatus, rh, octstr_imm(""));
if (hto)
http_destroy_headers(hto);
if (to)
list_destroy(to, (list_item_destructor_t *)octstr_destroy);
if (hfrom)
octstr_destroy(hfrom);
if (subject)
octstr_destroy(subject);
if (otransid)
octstr_destroy(otransid);
if (msgid)
octstr_destroy(msgid);
if (mh)
http_destroy_headers(mh);
if (m) mms_destroy(m);
}
void mmsc_receive_func(MmscGrp *m)
{
MmsHTTPClientInfo h = {NULL};
h.m = m;
while(rstop == 0 &&
(h.client = http_accept_request(m->incoming.port,
&h.ip, &h.url, &h.headers,
&h.body, &h.cgivars)) != NULL)
if (is_allowed_ip(m->incoming.deny_ip, m->incoming.allow_ip, h.ip)) {
h.ua = http_header_value(h.headers, octstr_imm("User-Agent"));
debug("mmsbox", 0,
" MM7 Incoming, ip=%s, mmsc id=%s ",
h.ip ? octstr_get_cstr(h.ip) : "",
octstr_get_cstr(m->id));
/* Dump headers, url etc. */
#if 1
http_header_dump(h.headers);
if (h.body) octstr_dump(h.body, 0);
if (h.ip) octstr_dump(h.ip, 0);
#endif
if (auth_check(m->incoming.user,
m->incoming.pass,
h.headers) != 0) { /* Ask it to authenticate... */
List *hh = http_create_empty_headers();
http_header_add(hh, "WWW-Authenticate",
"Basic realm=\"" MM_NAME "\"");
http_send_reply(h.client, HTTP_UNAUTHORIZED, hh,
octstr_imm(""));
http_destroy_headers(hh);
} else if (m->type == SOAP_MMSC)
mm7soap_receive(&h);
else
mm7eaif_receive(&h);
free_clientInfo(&h, 0);
} else {
free_clientInfo(&h, 0);
http_close_client(h.client);
}
debug("proxy", 0, "MMSBox: MM7 Shutting down...");
}
static void free_clientInfo(MmsHTTPClientInfo *h, int freeh)
{
debug("free info", 0,
" entered free_clientinfo %d, ip=%d", freeh, (int)h->ip);
if (h->ip)
octstr_destroy(h->ip);
if (h->url)
octstr_destroy(h->url);
if (h->ua) octstr_destroy(h->ua);
if (h->body) octstr_destroy(h->body);
if (h->cgivars)
http_destroy_cgiargs(h->cgivars);
if (h->headers)
http_destroy_headers(h->headers);
if (freeh)
gw_free(h);
debug("free info", 0,
" left free_clientinfo");
}
/* XXX Returns msgid in mmsc or NULL if error. Caller uses this for DLR issues.
* Caller must make sure throughput issues
* are observed!
* Don't remove from queue on fail, just leave it to expire.
*/
static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, Octstr *to, Octstr *msgId,
char *vasid,
MmsMsg *m, Octstr **error)
{
Octstr *ret = NULL;
int mtype = mms_messagetype(m);
int hstatus = HTTP_OK, tstatus;
List *xto = list_create();
MSoapMsg_t *mreq = NULL, *mresp = NULL;
List *rh = NULL, *ph = NULL;
Octstr *body = NULL, *rbody = NULL, *url = NULL;
Octstr *s;
info(0, "MMSBox: Send[soap] to MMSC[%s], msg type [%s], from %s, to %s",
mmc->id ? octstr_get_cstr(mmc->id) : "",
mms_message_type_to_cstr(mtype),
octstr_get_cstr(from), octstr_get_cstr(to));
list_append(xto, to);
if ((mreq = mm7_mmsmsg_to_soap(m, from, xto, msgId,
NULL,
1, octstr_get_cstr(mmc->id), vasid)) == NULL) {
*error = octstr_format("Failed to convert Msg[%s] 2 SOAP message!",
mms_message_type_to_cstr(mtype));
goto done1;
}
if (mm7_soapmsg_to_httpmsg(mreq, &rh, &body) < 0) {
*error = octstr_format("Failed to convert SOAP message 2 HTTP Msg!");
goto done1;
}
hstatus = mmsbox_http_fetch_content(HTTP_METHOD_POST, mmc->mmsc_url, rh, body, &ph,&rbody);
if (hstatus != HTTP_OK) {
*error = octstr_format("Failed to contact MMC[url=%s] => HTTP returned status = %d!",
octstr_get_cstr(mmc->mmsc_url), hstatus);
goto done1;
}
if ((mresp = mm7_parse_soap(ph, rbody)) == NULL) {
*error = octstr_format("Failed to parse MMSC[url=%s, id=%s] response!",
octstr_get_cstr(mmc->mmsc_url),
octstr_get_cstr(mmc->id));
goto done1;
}
/* Now look at response code and use it to tell you what you want. */
if ((s = mm7_soap_header_value(mresp, octstr_imm("StatusCode"))) != NULL) {
tstatus = atoi(octstr_get_cstr(s));
octstr_destroy(s);
} else
tstatus = MM7_SOAP_FORMAT_CORRUPT;
if (!MM7_SOAP_STATUS_OK(tstatus)) {
Octstr *detail = mm7_soap_header_value(mresp, octstr_imm("Details"));
ret = NULL;
info(0, "Send to MMSC[%s], failed, code=[%d=>%s], detail=%s",
mmc ? octstr_get_cstr(mmc->id) : "",
tstatus, mms_soap_status_to_cstr(tstatus),
detail ? octstr_get_cstr(detail) : "");
*error = octstr_format("Failed to deliver to MMC[url=%s, id=%s], status=[%d=>%s]!",
octstr_get_cstr(mmc->mmsc_url),
octstr_get_cstr(mmc->id),
tstatus,
mms_soap_status_to_cstr(tstatus));
if (detail)
octstr_destroy(detail);
} else
ret = mm7_soap_header_value(mresp, octstr_imm("MessageID"));
info(0, "Sent to MMC[%s], code=[%d=>%s]", octstr_get_cstr(mmc->id),
tstatus, mms_soap_status_to_cstr(tstatus));
done1:
if (mreq)
mm7_soap_destroy(mreq);
if (mresp)
mm7_soap_destroy(mresp);
if (rh)
http_destroy_headers(rh);
if (body)
octstr_destroy(body);
if (ph)
http_destroy_headers(ph);
if (rbody)
octstr_destroy(rbody);
if (url)
octstr_destroy(url);
list_destroy(xto, NULL);
return ret;
}
static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to,
char *vasid,
MmsMsg *m, Octstr **error)
{
Octstr *ret = NULL;
int mtype = mms_messagetype(m);
int hstatus = HTTP_OK;
List *rh = http_create_empty_headers(), *ph = NULL;
Octstr *body = NULL, *rbody = NULL, *url = NULL;
char *msgtype;
info(0, "MMSBox: Send [eaif] to MMC[%s], msg type [%s], from %s, to %s",
mmc ? octstr_get_cstr(mmc->id) : "",
mms_message_type_to_cstr(mtype),
octstr_get_cstr(from), octstr_get_cstr(to));
http_header_add(rh, "X-NOKIA-MMSC-To", octstr_get_cstr(to));
http_header_add(rh, "X-NOKIA-MMSC-From", octstr_get_cstr(from));
http_header_add(rh, "X-NOKIA-MMSC-Version", EAIF_VERSION);
if (mtype == MMS_MSGTYPE_SEND_REQ)
msgtype = "MultiMediaMessage";
else if (mtype == MMS_MSGTYPE_DELIVERY_IND)
msgtype = "DeliveryReport";
else
msgtype = "ReadReply";
http_header_add(rh, "X-NOKIA-MMSC-Message-Type", msgtype);
http_header_add(rh, "Content-Type", "application/vnd.wap.mms-message");
body = mms_tobinary(m);
hstatus = mmsbox_http_fetch_content(HTTP_METHOD_POST, mmc->mmsc_url, rh, body, &ph, &rbody);
if (http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) {
*error = octstr_format("Failed to contact MMC[url=%s] => HTTP returned status = %d !",
octstr_get_cstr(mmc->mmsc_url), hstatus);
} else
info(0, "Sent to MMC[%s], code=[%d]", octstr_get_cstr(mmc->id), hstatus);
if (hstatus < 0)
ret = NULL;
else {
hstatus = http_status_class(hstatus);
if (hstatus == HTTP_STATUS_SERVER_ERROR)
ret = NULL;
else
ret = http_header_value(ph, octstr_imm("X-Nokia-MMSC-Message-Id"));
}
if (rh)
http_destroy_headers(rh);
if (body)
octstr_destroy(body);
if (ph)
http_destroy_headers(ph);
if (rbody)
octstr_destroy(rbody);
if (url)
octstr_destroy(url);
return ret;
}
static int mms_sendtommsc(MmscGrp *mmc, Octstr *from, Octstr *to, Octstr *msgid,
char *vasid,
MmsMsg *m,
Octstr *dlr_url,
Octstr *rr_url,
Octstr **err)
{
Octstr *id = NULL;
mutex_lock(mmc->mutex); { /* Grab a lock on it. */
if (mmc->type == SOAP_MMSC)
id = mm7soap_send(mmc, from, to, msgid, vasid, m, err);
else if (mmc->type == EAIF_MMSC)
id = mm7eaif_send(mmc, from, to, vasid, m, err);
else
error(0, "MMC[%s] of unknown type, can't send!",
mmc->id ? octstr_get_cstr(mmc->id) : "");
if (id && mmc->throughput > 0)
gwthread_sleep(1.0/mmc->throughput);
} mutex_unlock(mmc->mutex); /* release lock */
if (id) {
if (dlr_url) /* remember the url's for reporting purposes. */
mms_dlr_url_put(id, "delivery-report", mmc->id, dlr_url);
if (rr_url)
mms_dlr_url_put(id, "read-report", mmc->id, rr_url);
octstr_destroy(id);
return MMS_SEND_OK;
} else
return MMS_SEND_ERROR_TRANSIENT; /* don't kill entry, wait a little. */
}
/* Get the MMC that should handler this recipient. */
static MmscGrp *get_handler_mmc(Octstr *id, Octstr *to)
{
MmscGrp *mmc = NULL;
int i, j, n;
Octstr *phonenum = NULL;
if (id)
for (i = 0, n = list_len(mmscs); i < n; i++)
if ((mmc = list_get(mmscs, i)) != NULL &&
mmc->id && octstr_compare(mmc->id, id) == 0)
return mmc;
if (octstr_search_char(to, '@', 0) > 0 ||
octstr_case_search(to, octstr_imm("/TYPE=IPv"), 0) > 0) /* For emails, or ip take first mmsc. */
return list_get(mmscs, 0);
j = octstr_case_search(to, octstr_imm("/TYPE=PLMN"), 0);
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == octstr_len(to))
phonenum = octstr_copy(to, 0, j);
else
phonenum = octstr_duplicate(to);
normalize_number(octstr_get_cstr(unified_prefix), &phonenum);
for (i = 0, n = list_len(mmscs); i < n; i++)
if ((mmc = list_get(mmscs, i)) != NULL &&
does_prefix_match(mmc->allowed_prefix, phonenum) &&
!does_prefix_match(mmc->denied_prefix, phonenum))
return mmc;
if (phonenum)
octstr_destroy(phonenum);
return NULL;
}
static int sendMsg(MmsEnvelope *e)
{
MmsMsg *msg = NULL;
int i, n;
msg = mms_queue_getdata(e);
for (i = 0, n = list_len(e->to); i<n; i++) {
int res = MMS_SEND_OK;
MmsEnvelopeTo *to = list_get(e->to, i);
Octstr *err = NULL;
time_t tnow = time(NULL);
MmscGrp *mmc = NULL;
if (!to || !to->process)
continue;
if (e->expiryt != 0 && /* Handle message expiry. */
e->expiryt < tnow) {
err = octstr_format("MMSC error: Message expired while sending to %S!", to->rcpt);
res = MMS_SEND_ERROR_FATAL;
goto done;
} else if (e->attempts >= mmsbox_maxsendattempts) {
err = octstr_format("MMSBox error: Failed to deliver to "
"%S after %ld attempts. (max attempts allowed is %ld)!",
to->rcpt, e->attempts,
mmsbox_maxsendattempts);
res = MMS_SEND_ERROR_FATAL;
goto done;
}
if ((mmc = get_handler_mmc(e->viaproxy, to->rcpt)) == NULL) {
err = octstr_format("MMSBox error: Failed to deliver to "
"%S. Don't know how to route!",
to->rcpt);
res = MMS_SEND_ERROR_TRANSIENT;
goto done;
}
res = mms_sendtommsc(mmc, e->from, to->rcpt,
e->msgId,
e->vasid ? octstr_get_cstr(e->vasid) : NULL,
msg,
e->url1, e->url2,
&err);
done:
if (res == MMS_SEND_OK)
to->process = 0;
else if (mmc)
send_report(to->rcpt, "delivery-report",
(e->expiryt != 0 && e->expiryt < tnow) ?
octstr_imm("Expired") : octstr_imm("Rejected"),
e->msgId, mmc->id);
if (res == MMS_SEND_ERROR_FATAL)
to->process = 0; /* No more attempts. */
info(0, "%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld: err=%s",
SEND_ERROR_STR(res),
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
err ? octstr_get_cstr(err) : "(null)");
e->lasttry = tnow;
if (mms_queue_update(e) == 1) {
e = NULL;
break; /* Queue entry gone. */
}
}
if (msg)
mms_destroy(msg);
if (e) { /* Update the queue if it is still valid (e.g. recipients not handled)
* XXX can this happen here??...
*/
e->lasttry = time(NULL);
e->attempts++; /* Update count of number of delivery attempts. */
e->sendt = e->lasttry + mmsbox_send_back_off * e->attempts;
if (mms_queue_update(e) != 1)
mms_queue_free_env(e);
}
return 1; /* always delete queue entry. */
}
void mmsbox_outgoing_queue_runner(int *rstop)
{
mms_queue_run(octstr_get_cstr(outgoing_qdir),
sendMsg, queue_interval, maxthreads, rstop);
}

118
mbuni/mmsbox/dlr.c Normal file
View File

@ -0,0 +1,118 @@
/*
* Mbuni - Open Source MMS Gateway
*
* MMSBox Dlr: Dlr storage for MMSBox
*
* 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 <sys/file.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mmsbox.h"
#include "mms_queue.h"
#define MAXTRIES 10
static int dlr_entry_fname(char *msgid, char *rtype, Octstr *mmc_id, Octstr **efname)
{
char d1[2], d2[3], fbuf[512], *p;
unsigned long h = _mshash(msgid);
Octstr *t, *s;
int i, fd;
/* Make toplevel dir. */
d1[0] = _TT[h%_TTSIZE];
d1[1] = '\0';
/* Then lower level. */
h /= _TTSIZE;
d2[0] = _TT[h%_TTSIZE];
h /= _TTSIZE;
d2[1] = _TT[h%_TTSIZE];
d2[2] = '\0';
/* Try and create the next level dir (first level was created by root_init) */
sprintf(fbuf, "%s/%s/%s", octstr_get_cstr(dlr_dir), d1, d2);
if (mkdir(fbuf,
S_IRWXU|S_IRWXG) < 0 &&
errno != EEXIST) {
error(0, "mmsbox: failed to create dir [%s] "
"while initialising dlr dir for %s: %s!",
fbuf, msgid, strerror(errno));
return -1;
}
t = octstr_format("%S-%s_%s", mmc_id, msgid, rtype); /* Put mmc id into name. */
octstr_replace(t, octstr_imm("/"), octstr_imm("$")); /* XXX safe in all cases?? */
s = octstr_format("%s/%S", fbuf, t);
octstr_destroy(t);
p = octstr_get_cstr(s);
i = 0;
do
if ((fd = open(p, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)) < 0) {
error(0, "Failed to open DLR URL store file [%s], error: %s!",
p, strerror(errno));
break;
} else if (mm_lockfile(fd, p, 1) != 0) {
close(fd);
fd = -1;
}
while (i++ < MAXTRIES && fd < 0);
if (efname)
*efname = s;
else
octstr_destroy(s);
return fd;
}
void mms_dlr_url_put(Octstr *msgid, char *rtype, Octstr *mmc_id, Octstr *dlr_url)
{
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_id, NULL);
if (fd >= 0) {
octstr_write_data(dlr_url, fd, 0);
close(fd);
}
}
Octstr *mms_dlr_url_get(Octstr *msgid, char *rtype, Octstr *mmc_id)
{
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_id, NULL);
FILE *f;
if (fd >= 0 && (f = fdopen(fd, "r+")) != NULL) {
Octstr *s = octstr_read_pipe(f);
fclose(f);
return s;
} else if (fd >= 0)
close(fd);
return NULL;
}
void mms_dlr_url_remove(Octstr *msgid, char *rtype, Octstr *mmc_id)
{
Octstr *fname = NULL;
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_id, &fname);
if (fname)
unlink(octstr_get_cstr(fname));
if (fd >= 0)
close(fd);
}

View File

@ -14,10 +14,13 @@
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include "mms_queue.h"
#include "mms_uaprof.h"
#include "mmsbox.h"
#include "mmsbox_cfg.h"
static int rstop = 0;
int rstop = 0;
static void quit_now(int notused)
{
rstop = 1;
@ -25,11 +28,375 @@ static void quit_now(int notused)
/* Close all MMSC http ports, kill all MMSC threads, kill sendmms port... */
}
static MIMEEntity *find_textpart(MIMEEntity *m)
{
Octstr *ctype = NULL, *params = NULL;
MIMEEntity *res = NULL;
if (!m) return NULL;
get_content_type(m->headers, &ctype, &params);
if (ctype && octstr_str_compare(ctype, "text/plain") == 0) {
res = m;
goto done;
}
if (m->multiparts) {
int i, n = list_len(m->multiparts);
for (i = 0; i < n; i++)
if ((res = find_textpart(list_get(m->multiparts, i))) != NULL)
goto done;
}
done:
if (ctype)
octstr_destroy(ctype);
if (res) { /* We got it! Convert charset if needed. */
List *params_h = get_value_parameters(params);
Octstr *charset = http_header_value(params_h, octstr_imm("charset"));
if (charset == NULL ||
octstr_str_compare(charset, "unknown") == 0) {
if (charset) octstr_destroy(charset);
charset = octstr_imm(DEFAULT_CHARSET);
}
if (octstr_case_compare(charset, octstr_imm(DEFAULT_CHARSET)) != 0)
charset_convert(m->body, DEFAULT_CHARSET, octstr_get_cstr(charset)); /* XXX error ignored? */
http_destroy_headers(params_h);
octstr_destroy(charset);
}
if (params)
octstr_destroy(params);
return res;
}
/* Gets the keyword, if any, from the text part of the message.
* converts charset as needed.
*/
static Octstr *get_keyword(MIMEEntity *me)
{
MIMEEntity *t = find_textpart(me);
Octstr *txt = t ? t->body : NULL;
List *l = t ? octstr_split_words(txt) : NULL;
Octstr *keyword = l ? list_get(l, 0) : NULL;
if (keyword)
keyword = octstr_duplicate(keyword);
if (l)
list_destroy(l, (list_item_destructor_t *)octstr_destroy);
return keyword;
}
static MmsService *get_service(Octstr *keyword, Octstr *mmc_id)
{
int i, n;
for (i = 0, n = list_len(mms_services); i < n; i++) {
MmsService *ms = list_get(mms_services,i);
/* Check that mmc_id is allowed:
* denied list is not null and we are on it, or allowed list is not null and we
* are *not* on it.
*/
if (ms->denied_mmscs &&
list_search(ms->denied_mmscs, mmc_id, (list_item_matches_t *)octstr_compare) != NULL)
continue;
if (ms->allowed_mmscs &&
list_search(ms->allowed_mmscs, mmc_id, (list_item_matches_t *)octstr_compare) == NULL)
continue;
if (keyword == NULL ||
list_search(ms->keywords, keyword,
(list_item_matches_t *)octstr_case_compare) != NULL)
return ms;
}
return NULL;
}
static void add_all_matching_parts(MIMEEntity *plist, MmsServiceUrlParam *pm,
MIMEEntity *me, MmsMsg *msg, int lev)
{
int i, n;
Octstr *data = NULL, *ctype = NULL, *xctype = NULL, *params = NULL;
if (pm->type == WHOLE_BINARY && lev == 0) {
data = mms_tobinary(msg);
ctype = octstr_imm("application/vnd.wap.mms-message");
}
if (me->multiparts && list_len(me->multiparts) > 0) {
for (i = 0, n = list_len(me->multiparts); i < n; i++)
add_all_matching_parts(plist, pm,
list_get(me->multiparts, i), msg, lev+1);
goto done;
}
get_content_type(me->headers, &xctype, &params);
#define BEGINSWITH(s, prefix) (octstr_case_search(s, octstr_imm(prefix),0) == 0)
#define TYPE_MATCH(typ, prefix) ((pm->type) == (typ) && \
BEGINSWITH(xctype, prefix))
if (xctype)
if (TYPE_MATCH(IMAGE_PART,"image/") ||
TYPE_MATCH(VIDEO_PART,"video/") ||
TYPE_MATCH(TEXT_PART,"text/") ||
TYPE_MATCH(SMIL_PART,"application/smil") ||
pm->type == ANY_PART || /* Skip top-level for 'any' parts. */
(pm->type == OTHER_PART &&
(!BEGINSWITH(xctype, "text/") &&
!BEGINSWITH(xctype, "video/") &&
!BEGINSWITH(xctype, "image/") &&
!BEGINSWITH(xctype, "application/smil")))) {
ctype = http_header_value(me->headers, octstr_imm("Content-Type"));
data = me->body ? octstr_duplicate(me->body) : octstr_create("");
}
done:
if (ctype) {
MIMEEntity *p = mime_entity_create();
Octstr *cd = octstr_format("form-data; name=\"%S\"", pm->name);
http_header_add(p->headers, "Content-Type", octstr_get_cstr(ctype));
http_header_add(p->headers, "Content-Disposition", octstr_get_cstr(cd));
p->body = data;
base64_mimeparts(p);
list_append(plist->multiparts, p);
octstr_destroy(ctype);
octstr_destroy(cd);
}
if (xctype)
octstr_destroy(xctype);
if (params)
octstr_destroy(params);
}
enum _xurltype {FILE_TYPE, URL_TYPE};
static Octstr *url_path_prefix(Octstr *url, int type);
static Octstr *filename2content_type(char *fname);
static int make_and_queue_msg(Octstr *data, Octstr *ctype, List *reply_headers,
Octstr *base_url, int type, MmsEnvelope *e,
Octstr *svc_name, Octstr *faked_sender,
int accept_x_headers, Octstr **err);
static int fetch_serviceurl(MmsEnvelope *e,
MmsService *ms, MmsMsg *m,
MIMEEntity *msg,
Octstr **err)
{
List *rh, *rph = NULL;
Octstr *body = NULL, *rb = NULL;
Octstr *ctype = NULL, *params = NULL;
int i, n, method, typ = FILE_TYPE;
FILE *fp = NULL;
int res = -1;
switch (ms->type) {
case TRANS_TYPE_GET_URL:
case TRANS_TYPE_POST_URL:
rh = http_create_empty_headers();
http_header_add(rh, "User-Agent", MM_NAME "/" GW_VERSION);
/* Put in some useful headers. */
if (e->msgId)
http_header_add(rh, "X-Mbuni-Message-ID", octstr_get_cstr(e->msgId));
if (e->fromproxy)
http_header_add(rh, "X-Mbuni-MMSC-ID", octstr_get_cstr(e->fromproxy));
if (e->from)
http_header_add(rh, "X-Mbuni-From", octstr_get_cstr(e->from));
if (e->subject)
http_header_add(rh, "X-Mbuni-Subject", octstr_get_cstr(e->subject));
for (i = 0, n = list_len(e->to); i < n; i++) {
MmsEnvelopeTo *r = list_get(e->to, i);
if (r && r->rcpt)
http_header_add(rh, "X-Mbuni-To", octstr_get_cstr(r->rcpt));
}
if (ms->type == TRANS_TYPE_POST_URL) { /* Put in the parameters. */
MIMEEntity *x = mime_entity_create();
http_header_add(rh, "Content-Type", "multipart/form-data");
http_destroy_headers(x->headers);
x->headers = rh;
for (i = 0, n = list_len(ms->params); i < n; i++) {
MmsServiceUrlParam *p = list_get(ms->params, i);
add_all_matching_parts(x, p, msg, m, 0);
}
mime_entity_body_and_headers(x, &body, &rh);
mime_entity_destroy(x);
method = HTTP_METHOD_POST;
} else
method = HTTP_METHOD_GET;
typ = URL_TYPE;
if (mmsbox_http_fetch_content(method, ms->url, rh, body, &rph, &rb) == HTTP_OK)
get_content_type(rph, &ctype, &params);
else
*err = octstr_format("MMSBox: Failed to fetch content for Service %S, url %S!",
ms->name, ms->url);
http_destroy_headers(rh);
if (body)
octstr_destroy(body);
break;
case TRANS_TYPE_FILE:
case TRANS_TYPE_EXEC:
fp = (ms->type == TRANS_TYPE_EXEC) ?
popen(octstr_get_cstr(ms->url), "r") :
fopen(octstr_get_cstr(ms->url), "r");
rb = octstr_read_pipe(fp);
if (ms->type == TRANS_TYPE_EXEC) {
ctype = octstr_imm("application/smil");
pclose(fp);
} else {
fclose(fp);
ctype = filename2content_type(octstr_get_cstr(ms->url));
}
if (!rb)
*err = octstr_format("MMSBox: Failed to fetch content for Service %S, file/path = %S!",
ms->name, ms->url);
typ = FILE_TYPE;
break;
case TRANS_TYPE_TEXT:
rb = octstr_duplicate(ms->url);
ctype = octstr_imm("text/plain");
typ = URL_TYPE;
break;
default:
*err = octstr_format(0, "MMSBOX: Unknown Service type for service %S!", ms->name);
break;
}
/* If we have the content, make the message and write it to out-going. */
if (!ctype || !rb)
goto done;
else {
Octstr *base_url = url_path_prefix(ms->url, typ);
res = make_and_queue_msg(rb, ctype, rph, base_url,
typ, e, ms->name, ms->faked_sender,
ms->accept_x_headers, err);
if (base_url)
octstr_destroy(base_url);
}
done:
if (ctype)
octstr_destroy(ctype);
if (rb)
octstr_destroy(rb);
if (rph)
http_destroy_headers(rph);
if (params)
octstr_destroy(params);
return res;
}
static int mmsbox_service_dispatch(MmsEnvelope *e)
{
MmsMsg *msg = NULL;
MIMEEntity *me = NULL;
int i, n, res = 0;
time_t tnow = time(NULL);
Octstr *err = NULL, *keyword = NULL;
MmsService *ms;
gw_assert(e->msgtype == MMS_MSGTYPE_SEND_REQ);
if ((msg = mms_queue_getdata(e)) == NULL) {
err = octstr_format("Failed to read message for queue entry %s!",
e->xqfname);
res = -1;
goto done;
} else if (e->expiryt != 0 && /* Handle message expiry. */
e->expiryt < tnow) {
err = octstr_format("Queue entry [msgid=%S,mmc_id=%S] "
"expired while sending to service!", e->msgId, e->fromproxy);
res = -1;
goto done;
} else if (e->attempts >= mmsbox_maxsendattempts) {
err = octstr_format("Failed to deliver [msgid=%S,mmc_id=%S] "
"after %ld attempts. (max attempts allowed is %ld)!",
e->msgId, e->fromproxy, e->attempts,
mmsbox_maxsendattempts);
res = -1;
goto done;
}
me = mms_tomime(msg, 0);
keyword = get_keyword(me);
ms = get_service(keyword, e->fromproxy);
if (!ms) {
err = octstr_format("No Service to handle %S (keyword %S)!",
e->msgId, keyword ? octstr_imm("") : keyword);
res = -1;
goto done;
}
e->_x = ms; /* Remember it for later. */
res = fetch_serviceurl(e, ms, msg, me, &err);
done:
if (err) {
error(0, "MMSBox error: %s", octstr_get_cstr(err));
octstr_destroy(err);
}
if (res == -1 || res == 0) /* Fatal error, or success delete queue entry. */
for (i = 0, n = list_len(e->to); i < n; i++) {
MmsEnvelopeTo *r = list_get(e->to,i);
if (r)
r->process = 0;
}
else { /* Not succeeded so we need to wait a bit and try later. */
e->lasttry = time(NULL);
e->attempts++; /* Update count of number of delivery attempts. */
e->sendt = e->lasttry + mmsbox_send_back_off * e->attempts;
}
if (mms_queue_update(e) != 1)
mms_queue_free_env(e);
if (keyword)
octstr_destroy(keyword);
if (msg)
mms_destroy(msg);
if (me)
mime_entity_destroy(me);
return 1;
}
static void sendmms_func(void *unused);
int main(int argc, char *argv[])
{
Octstr *fname;
int cfidx;
Cfg *cfg;
long qthread = 0, sthread = 0;
mms_lib_init();
@ -53,13 +420,603 @@ int main(int argc, char *argv[])
info(0, " " MM_NAME " MMSBox version %s starting", MMSC_VERSION);
mms_load_mmsbox_settings(cfg,NULL);
mms_load_mmsbox_settings(cfg,(gwthread_func_t *)mmsc_receive_func);
cfg_destroy(cfg);
signal(SIGHUP, quit_now);
signal(SIGTERM, quit_now);
signal(SIGPIPE,SIG_IGN); /* Ignore pipe errors. They kill us sometimes for nothing*/
/* Start out-going queue thread. */
qthread = gwthread_create((gwthread_func_t *)mmsbox_outgoing_queue_runner, &rstop);
/* Start sendmms port */
if (sendmms_port.port > 0)
sthread = gwthread_create((gwthread_func_t *)sendmms_func, NULL);
mms_queue_run(octstr_get_cstr(incoming_qdir),
mmsbox_service_dispatch,
queue_interval, maxthreads, &rstop);
/* Wait for the sender thread, then quit. */
gwthread_join(qthread); /* Wait for it to die... */
if (sendmms_port.port > 0)
gwthread_join(sthread);
sleep(2);
return 0;
}
int mmsbox_http_fetch_content(int method, Octstr *url, List *request_headers,
Octstr *body, List **reply_headers, Octstr **reply_body)
{
HTTPCaller *c = http_caller_create();
int status = 0;
Octstr *furl = NULL;
http_start_request(c, method, url, request_headers, body, 1, NULL, NULL);
if (http_receive_result(c, &status, &furl, reply_headers, reply_body) == NULL)
status = -1;
if (furl)
octstr_destroy(furl);
http_caller_destroy(c);
return status;
}
/* Mapping file extensions to content types. */
static struct {
char *ctype, *file_ext;
} exts[] = {
{"text/plain", "txt"},
{"image/jpeg", "jpg"},
{"image/jpeg", "jpeg"},
{"image/png", "png"},
{"image/tiff", "tiff"},
{"image/gif", "gif"},
{"image/bmp", "bmp"},
{"image/vnd.wap.wbmp", "wbmp"},
{"image/x-bmp", "bmp"},
{"image/x-wmf", "bmp"},
{"image/vnd.wap.wpng", "png"},
{"image/x-up-wpng", "png"},
{"audio/mpeg", "mp3"},
{"audio/wav", "wav"},
{"audio/x-wav", "wav"},
{"audio/basic", "au"},
{"audio/amr", "amr"},
{"audio/x-amr", "amr"},
{"audio/amr-wb", "amr"},
{"audio/midi", "mid"},
{"audio/sp-midi", "mid"},
{"application/smil", "smil"},
{NULL, NULL}
};
static Octstr *filename2content_type(char *fname)
{
char *p = strrchr(fname, '.');
int i;
if (p)
for (i = 0; exts[i].file_ext; i++)
if (strcasecmp(p+1, exts[i].file_ext) == 0)
return octstr_imm(exts[i].ctype);
return octstr_imm("application/octet-stream");
}
/* Return the prefix part of a url or file. */
static Octstr *url_path_prefix(Octstr *url, int type)
{
int i, j, len = octstr_len(url);
char *p = octstr_get_cstr(url);
/* Set lower/upper limit of search. */
if (type == URL_TYPE) { /* then skip first slashes. */
char *x;
i = octstr_search(url, octstr_imm("://"),0);
if (i > 0)
i += 3;
else
i = 0;
x = rindex(p, '#'); /* look for fragment if any. */
if (x)
j = x - p - 1;
else
j = len - 1;
} else {
i = 0;
j = len - 1;
}
/* Now search backwards for the last '/'.
* if you don't find one, set to end of string.
*/
for (;j > i; j--)
if (p[j] == '/')
break;
if (j <= i)
j = len;
return octstr_copy(url, 0, j);
}
/* Get's just the host:port part, leaving out UrI */
static Octstr *get_toplevel_url(Octstr *url)
{
int i, len = octstr_len(url);
char *p = octstr_get_cstr(url);
i = octstr_search(url, octstr_imm("://"),0);
if (i > 0)
i += 3;
else
i = 0;
for ( ; i < len; i++)
if (p[i] == '/')
break;
return octstr_copy(url, 0, i);
}
/* little dirty method to see if file begins with url scheme. */
static int has_url_scheme(char *url)
{
char *p = strstr(url, "://");
if (!p)
return 0;
for (p -= 1; p >= url; p--)
if (!isalpha(*p))
return 0;
return 1;
}
static int add_msg_part(MIMEEntity *res, xmlNodePtr node, Octstr *base_url,
Octstr *top_url,
int type, MmsEnvelope *e)
{
Octstr *curl = NULL, *ctype = NULL, *body = NULL;
char *src = NULL;
int isurl, slash_prefix;
MmsService *ms = e->_x;
static int cntr; /* For generating cids */
/* For each node in the smil doc, if it has an src attribute, then:
* - if our type of base_url is FILE *and the src attribute does not look
* like a url, then file the file referenced, load it into the message and go
* - if our type is URL and the url scheme is http/https (or has no scheme)
* then fetch it and put into message.
*/
if (!node || node->type != XML_ELEMENT_NODE ||
(src = (char *)xmlGetProp(node, (unsigned char *)"src")) == NULL)
return 0; /* Nothing to do. */
if (src[0] == '\\') { /* User can escape url to prevent substitution. */
xmlSetProp(node, (xmlChar *)"src", (xmlChar *)(src + 1));
goto done;
}
isurl = has_url_scheme(src);
slash_prefix = (src[0] == '/');
if (isurl && strstr(src, "http") != 0) /* Only http and https allowed! */
goto done;
if (isurl)
ctype = octstr_create(src);
else if (slash_prefix) {
if (type == URL_TYPE)
curl = octstr_format("%S%s",
top_url, src);
else
curl = octstr_create(src);
} else
curl = octstr_format("%S/%s",base_url, src);
isurl |= (type == URL_TYPE); /* From now on, this flag tells us whether we are fetching a url.*/
if (isurl) {
List *rh = http_create_empty_headers(), *rph = NULL;
http_header_add(rh, "User-Agent", MM_NAME "/" GW_VERSION);
if (mmsbox_http_fetch_content(HTTP_METHOD_POST, curl, rh, NULL, &rph, &body) == HTTP_OK)
ctype = http_header_value(rph, octstr_imm("Content-Type"));
else
error(0, "MMSBOX: Failed to load url %s within SMIL content from service %s!",
octstr_get_cstr(curl), octstr_get_cstr(ms->name));
if (rph)
http_destroy_headers(rph);
http_destroy_headers(rh);
} else {
body = octstr_read_file(octstr_get_cstr(curl));
ctype = filename2content_type(src);
}
if (ctype && body) { /* If we got it, put it in. */
Octstr *attr = octstr_format("cid:%06d", ++cntr);
char *p = octstr_get_cstr(attr) + 4;
Octstr *cid_header_val = octstr_format("<%s>", p);
MIMEEntity *x = mime_entity_create();
http_header_add(x->headers, "Content-Type", octstr_get_cstr(ctype));
http_header_add(x->headers, "Content-ID", octstr_get_cstr(cid_header_val));
x->body = body;
list_append(res->multiparts, x);
xmlSetProp(node, (xmlChar *)"src", (xmlChar *)octstr_get_cstr(attr));
octstr_destroy(attr);
octstr_destroy(cid_header_val);
}
done:
if (curl)
octstr_destroy(curl);
if (ctype)
octstr_destroy(ctype);
xmlFree(src);
return 0;
}
/* Traverse the tree doing the above. */
static void add_msg_parts(MIMEEntity *res, xmlNodePtr node, Octstr *base_url,
Octstr *top_url,
int type, MmsEnvelope *e)
{
xmlNodePtr n;
/* Do all the children recursively, then come back and do parent. */
for (n = node; n; n = n->next)
if (n->type != XML_COMMENT_NODE) {
add_msg_part(res, n, base_url, top_url, type, e);
add_msg_parts(res, n->xmlChildrenNode, base_url, top_url, type, e);
}
}
/* Given content, make a message. We'll also use this for send-mms-user! */
static int make_and_queue_msg(Octstr *data, Octstr *ctype, List *reply_headers,
Octstr *base_url, int type, MmsEnvelope *e,
Octstr *svc_name, Octstr *faked_sender,
int accept_x_headers, Octstr **err)
{
Octstr *from = NULL, *subject = NULL, *turl = get_toplevel_url(base_url);
Octstr *dlr_url = NULL, *rr_url = NULL, *mmc = NULL;
MmsMsg *m = NULL;
MIMEEntity *me = mime_entity_create();
time_t expiryt = 0;
Octstr *x;
List *xto = list_create();;
int i, n, res = -1;
gw_assert(svc_name);
/* Get the from address. */
if (faked_sender)
from = octstr_duplicate(faked_sender);
else if (accept_x_headers && reply_headers &&
(from = http_header_value(reply_headers, octstr_imm("X-Mbuni-From"))) != NULL)
(void)0; /* all done above. */
else {
/* get first recipient, set that as sender. */
MmsEnvelopeTo *r = (e) ? list_get(e->to, 0) : NULL;
if (r)
from = octstr_duplicate(r->rcpt);
else
from = octstr_imm("anon@anon");
}
/* start with the easy one... */
if (octstr_case_compare(ctype, octstr_imm("application/vnd.wap.mms-message")) == 0) {
m = mms_frombinary(data, from);
goto done; /* all done! */
} else if (octstr_case_compare(ctype, octstr_imm("application/smil")) == 0) {
xmlDocPtr smil;
xmlChar *buf = NULL;
int bsize = 0;
/* This is the hard bit! */
http_header_add(me->headers, "Content-Type", "multipart/related; "
"type=\"application/smil\"; start=\"<presentation>\"");
/* Parse the smil as XML. */
smil = xmlParseMemory(octstr_get_cstr(data), octstr_len(data));
if (!smil || !smil->xmlChildrenNode) {
*err = octstr_format("MMSBox: Error parsing SMIL response from service[%s], "
" msgid %s!", octstr_get_cstr(svc_name),
(e && e->msgId) ? octstr_get_cstr(e->msgId) : "(none)");
goto done;
}
add_msg_parts(me, smil->xmlChildrenNode, base_url, turl, type, e);
/* SMIL has been modified, convert it to text, put it in. */
xmlDocDumpFormatMemory(smil, &buf, &bsize, 1);
xmlFreeDoc(smil);
if (buf) {
MIMEEntity *sm = mime_entity_create();
http_header_add(sm->headers, "Content-Type", "application/smil");
http_header_add(sm->headers, "Content-ID", "<presentation>");
sm->body = octstr_create_from_data((char *)buf, bsize);
list_append(me->multiparts, sm);
me->start = sm;
xmlFree(buf);
} else {
*err = octstr_format("MMSBox: Error writing converted SMIL "
"for response from service[%s], "
" msgid %s!",
octstr_get_cstr(svc_name),
(e && e->msgId) ? octstr_get_cstr(e->msgId) : "(none)");
goto done;
}
} else { /* all others, make the message as-is and hope for the best! */
http_header_add(me->headers, "Content-Type", octstr_get_cstr(ctype));
me->body = octstr_duplicate(data);
}
/* Get headers needed, if we are allowed to do so. */
if (accept_x_headers && reply_headers) {
Octstr *x = NULL;
List *l = NULL;
subject = http_header_value(reply_headers, octstr_imm("X-Mbuni-Subject"));
if ((x = http_header_value(reply_headers, octstr_imm("X-Mbuni-Expiry"))) != NULL)
expiryt = date_parse_http(x);
if ((l = http_header_find_all(reply_headers, "X-Mbuni-To")) != NULL) {
int i, n;
for (i = 0, n = list_len(l); i<n; i++) {
Octstr *h = NULL, *v = NULL;
http_header_get(l, i, &h, &v);
list_append(xto, v);
octstr_destroy(h);
}
http_destroy_headers(l);
}
dlr_url = http_header_value(reply_headers, octstr_imm("X-Mbuni-DLR-Url"));
rr_url = http_header_value(reply_headers, octstr_imm("X-Mbuni-RR-Url"));
mmc = http_header_value(reply_headers, octstr_imm("X-Mbuni-MMSC"));
}
if (list_len(xto) == 0 && e && e->from)
list_append(xto, octstr_duplicate(e->from));
if (!subject && e && e->subject)
subject = octstr_duplicate(e->subject);
if (!mmc && e)
mmc = e->fromproxy;
/* Add some nice headers. */
http_header_add(me->headers, "From", octstr_get_cstr(from));
for (i = 0, n = list_len(xto); i < n; i++) {
Octstr *v, *h;
http_header_get(xto, i, &h, &v);
http_header_add(me->headers, "To", octstr_get_cstr(v));
octstr_destroy(h);
octstr_destroy(v);
}
if (dlr_url)
http_header_add(me->headers, "X-Mms-Delivery-Report", "Yes");
if (rr_url)
http_header_add(me->headers, "X-Mms-Read-Report", "Yes");
if (subject)
http_header_add(me->headers, "Subject", octstr_get_cstr(subject));
if (expiryt > 0) {
Octstr *x = date_format_http(expiryt);
http_header_add(me->headers, "X-Mms-Expiry", octstr_get_cstr(x));
octstr_destroy(x);
}
if (me)
m = mms_frommime(me);
if (!m) {
*err = octstr_format("MMSBox: Failed to convert Mms Message from service %s!",
octstr_get_cstr(svc_name));
goto done;
}
/* Write to queue. */
x = mms_queue_add(from, xto, subject,
e ? e->fromproxy : NULL,
mmc,
time(NULL), expiryt, m, NULL,
NULL, svc_name,
dlr_url, rr_url,
(dlr_url != NULL),
octstr_get_cstr(outgoing_qdir),
octstr_imm(MM_NAME));
info(0, "MMSBox: Queued message from service [%s] to outgoing: %s",
octstr_get_cstr(svc_name), octstr_get_cstr(x));
octstr_destroy(x);
res = 0;
done:
if (dlr_url)
octstr_destroy(dlr_url);
if (rr_url)
octstr_destroy(rr_url);
if (from)
octstr_destroy(from);
if (subject)
octstr_destroy(subject);
if (me)
mime_entity_destroy(me);
if (m)
mms_destroy(m);
if (xto)
list_destroy(xto, (list_item_destructor_t *)octstr_destroy);
return res;
}
static SendMmsUser *auth_user(Octstr *user, Octstr *pass)
{
int i, n;
SendMmsUser *u = NULL;
for (i = 0, n = list_len(sendmms_users); i < n; i++)
if ((u = list_get(sendmms_users, i)) != NULL &&
octstr_compare(u->user, user) == 0 &&
octstr_compare(u->pass, pass) == 0)
return u;
return NULL;
}
static void sendmms_func(void *unused)
{
HTTPClient *client = NULL;
Octstr *ip = NULL, *url = NULL;
Octstr *body = NULL;
List *cgivars = NULL, *h = NULL;
while (!rstop &&
(client = http_accept_request(sendmms_port.port,
&ip, &url, &h, &body, &cgivars)) != NULL) {
SendMmsUser *u = NULL;
List *hh = http_create_empty_headers();
Octstr *username = http_cgi_variable(cgivars, "username");
Octstr *password = http_cgi_variable(cgivars, "password");
Octstr *err = NULL;
if ((u = auth_user(username, password)) != NULL &&
is_allowed_ip(sendmms_port.deny_ip, sendmms_port.allow_ip, ip)) {
Octstr *data, *ctype = NULL, *mmc, *to, *from, *dlr_url;
Octstr *rr_url, *subject = NULL;
List *lto = NULL, *rh = http_create_empty_headers();
Octstr *rb = NULL, *base_url = octstr_imm("http://localhost");
int i, n, res = 0;
if ((data = http_cgi_variable(cgivars, "text")) != NULL) { /* text. */
Octstr *charset = http_cgi_variable(cgivars, "charset");
ctype = octstr_format("text/plain");
if (charset) {
octstr_format_append(ctype, "; charset=%S", charset);
octstr_destroy(charset);
}
} else if ((data = http_cgi_variable(cgivars, "smil")) != NULL) /* smil. */
ctype = octstr_imm("application/smil");
else
rb = octstr_imm("Missing content");
if ((from = http_cgi_variable(cgivars, "from")) == NULL && !u->faked_sender)
rb = octstr_imm("Missing Sender address");
dlr_url = http_cgi_variable(cgivars, "dlr_url");
rr_url = http_cgi_variable(cgivars, "rr_url");
mmc = http_cgi_variable(cgivars, "mmsc");
subject = http_cgi_variable(cgivars, "subject");
if ((to = http_cgi_variable(cgivars, "to")) == NULL)
rb = octstr_imm("Missing recipient!");
else
lto = octstr_split_words(to);
/* Build the fake reply headers. */
if (ctype)
http_header_add(rh, "Content-Type", octstr_get_cstr(ctype));
if (from) {
http_header_add(rh, "X-Mbuni-From", octstr_get_cstr(from));
octstr_destroy(from);
}
if (lto) {
for (i = 0, n = list_len(lto); i < n; i++) {
Octstr *x = list_get(lto, i);
_mms_fixup_address(x);
http_header_add(rh, "X-Mbuni-To", octstr_get_cstr(x));
}
list_destroy(lto, (list_item_destructor_t *)octstr_destroy);
}
if (dlr_url) {
http_header_add(rh, "X-Mbuni-DLR-Url", octstr_get_cstr(dlr_url));
octstr_destroy(dlr_url);
}
if (rr_url) {
http_header_add(rh, "X-Mbuni-RR-Url", octstr_get_cstr(rr_url));
octstr_destroy(rr_url);
}
if (mmc) {
http_header_add(rh, "X-Mbuni-MMSC", octstr_get_cstr(mmc));
octstr_destroy(mmc);
}
if (subject) {
http_header_add(rh, "X-Mbuni-Subject", octstr_get_cstr(subject));
octstr_destroy(subject);
}
/* Requests to make_and_queue below can block, but for now we don't care. */
if (ctype && data) {
res = make_and_queue_msg(data, ctype, rh, base_url, URL_TYPE, NULL,
octstr_imm("sendmms-user"), u->faked_sender,
1, &err);
http_destroy_headers(rh);
if (res < 0)
rb = octstr_imm("Error in message conversion");
} else if (!rb)
rb = octstr_imm("Failed to send message");
http_send_reply(client, HTTP_BAD_REQUEST, hh, rb);
info(0, "MMSBox.mmssend: u=%s, %s",
u ? octstr_get_cstr(u->user) : "none",
(res == 0) ? "Sent" : "Not Sent");
octstr_destroy(base_url);
if (data)
octstr_destroy(data);
if (ctype)
octstr_destroy(ctype);
} else {
http_send_reply(client, HTTP_UNAUTHORIZED, hh,
octstr_imm("Authentication failed"));
err = octstr_format("MMSBox: SendMMS, Authentication failed, "
"username=%s, password=%s!",
username ? octstr_get_cstr(username) : "(null)",
password ? octstr_get_cstr(password) : "(null)");
}
if (err) {
error(0, "%s", octstr_get_cstr(err));
octstr_destroy(err);
}
/* Free the ip and other stuff here. */
if (username)
octstr_destroy(username);
if (password)
octstr_destroy(password);
octstr_destroy(ip);
if (body) octstr_destroy(body);
octstr_destroy(url);
http_destroy_cgiargs(cgivars);
http_destroy_headers(h);
}
}

View File

@ -1,7 +1,7 @@
/*
* Mbuni - Open Source MMS Gateway
*
* MMSC CFG: MMC configuration and misc. functions
* MMSBox CFG: MMBox configuration and misc. functions
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
*
@ -26,14 +26,18 @@
List *sendmms_users = NULL; /* list of SendMmsUser structs */
List *mms_services = NULL; /* list of MMS Services */
List *mmscs = NULL;
Octstr *incoming_qdir, *outgoing_qdir;
Octstr *incoming_qdir, *outgoing_qdir, *dlr_dir;
long mmsbox_maxsendattempts, mmsbox_send_back_off;
long queue_interval, maxthreads;
Octstr *unified_prefix;
struct SendMmsPortInfo sendmms_port;
int mms_load_mmsbox_settings(Cfg *cfg, gwthread_func_t *mmsc_handler_func)
{
CfgGroup *grp = cfg_get_single_group(cfg, octstr_imm("mmsbox"));
CfgGroup *cgrp = cfg_get_single_group(cfg, octstr_imm("core"));
Octstr *gdir;
Octstr *gdir, *s;
int send_port_ssl = 0;
List *l;
int i, n;
@ -52,11 +56,12 @@ int mms_load_mmsbox_settings(Cfg *cfg, gwthread_func_t *mmsc_handler_func)
if (mkdir(octstr_get_cstr(gdir),
S_IRWXU|S_IRWXG) < 0 &&
errno != EEXIST)
panic(0, "Failed to create queue directory: %s - %s!",
panic(0, "Failed to create MMSBox storage directory: %s - %s!",
octstr_get_cstr(gdir), strerror(errno));
incoming_qdir = octstr_format("%S/mmsbox_incoming", gdir);
outgoing_qdir = octstr_format("%S/mmsbox_outgoing", gdir);
dlr_dir = octstr_format("%S/mmsbox_dlr", gdir);
if (mms_init_queuedir(incoming_qdir) < 0)
panic(0, "Failed to initialise incoming queue directory: %s - %s!",
@ -65,6 +70,31 @@ int mms_load_mmsbox_settings(Cfg *cfg, gwthread_func_t *mmsc_handler_func)
if (mms_init_queuedir(outgoing_qdir) < 0)
panic(0, "Failed to initialise outgoing queue directory: %s - %s!",
octstr_get_cstr(outgoing_qdir), strerror(errno));
if (mms_init_queuedir(dlr_dir) < 0)
panic(0, "Failed to initialise dlr storage directory: %s - %s!",
octstr_get_cstr(dlr_dir), strerror(errno));
if (cfg_get_integer(&mmsbox_maxsendattempts, grp,
octstr_imm("maximum-send-attempts")) < 0)
mmsbox_maxsendattempts = MAXQTRIES;
if (cfg_get_integer(&mmsbox_send_back_off, grp,
octstr_imm("send-attempt-back-off")) == -1)
mmsbox_send_back_off = BACKOFF_FACTOR;
if (cfg_get_integer(&maxthreads, grp, octstr_imm("max-send-threads")) == -1)
maxthreads = 10;
s = _mms_cfg_getx(grp, octstr_imm("queue-run-interval"));
if (!s || (queue_interval = atof(octstr_get_cstr(s))) <= 0)
queue_interval = QUEUERUN_INTERVAL;
if (s)
octstr_destroy(s);
unified_prefix = _mms_cfg_getx(grp, octstr_imm("unified-prefix"));
cfg_get_integer(&sendmms_port.port, grp, octstr_imm("sendmms-port"));
#ifdef HAVE_LIBSSL
@ -90,6 +120,8 @@ int mms_load_mmsbox_settings(Cfg *cfg, gwthread_func_t *mmsc_handler_func)
u->user = _mms_cfg_getx(x, octstr_imm("username"));
u->pass = _mms_cfg_getx(x, octstr_imm("password"));
u->faked_sender = _mms_cfg_getx(x, octstr_imm("faked-sender"));
u->dlr_url = _mms_cfg_getx(x, octstr_imm("delivery-report-url"));
u->rr_url = _mms_cfg_getx(x, octstr_imm("read-report-url"));
list_append(sendmms_users, u);
}
list_destroy(l, NULL);
@ -107,6 +139,12 @@ int mms_load_mmsbox_settings(Cfg *cfg, gwthread_func_t *mmsc_handler_func)
m->id = _mms_cfg_getx(x, octstr_imm("id"));
m->mmsc_url = _mms_cfg_getx(x, octstr_imm("mmsc-url"));
m->allowed_prefix = _mms_cfg_getx(x, octstr_imm("allowed-prefix"));
m->denied_prefix = _mms_cfg_getx(x, octstr_imm("denied-prefix"));
m->incoming.allow_ip = cfg_get(x, octstr_imm("allow-ip"));
m->incoming.deny_ip = cfg_get(x, octstr_imm("deny-ip"));
m->incoming.user = _mms_cfg_getx(x, octstr_imm("incoming-username"));
m->incoming.pass = _mms_cfg_getx(x, octstr_imm("incoming-password"));
cfg_get_integer(&m->incoming.port, x, octstr_imm("incoming-port"));
@ -135,14 +173,15 @@ int mms_load_mmsbox_settings(Cfg *cfg, gwthread_func_t *mmsc_handler_func)
m->incoming.port = 0; /* so we don't listen on it. */
}
if (mmsc_handler_func) { /* Only start threads if func passed. */
if (mmsc_handler_func && m->incoming.port > 0) { /* Only start threads if func passed and ... */
if ((m->threadid = gwthread_create(mmsc_handler_func, m)) < 0)
error(0, "MMSBox: Failed to start MMSC handler thread for MMSC[%s]: %s!",
octstr_get_cstr(m->id), strerror(errno));
} else
m->threadid = -1;
list_append(mmscs, m);
m->mutex = mutex_create();
list_append(mmscs, m);
}
list_destroy(l, NULL);
@ -178,6 +217,12 @@ int mms_load_mmsbox_settings(Cfg *cfg, gwthread_func_t *mmsc_handler_func)
octstr_destroy(s);
} else
m->allowed_mmscs = NULL; /* means allow all. */
if ((s = cfg_get(x, octstr_imm("denied-mmscs"))) != NULL) {
m->denied_mmscs = octstr_split(s, octstr_imm(";"));
octstr_destroy(s);
} else
m->denied_mmscs = NULL; /* means allow all. */
/* Get key words. Start with aliases to make life easier. */
if ((s = cfg_get(x, octstr_imm("aliases"))) != NULL) {

View File

@ -19,18 +19,23 @@ typedef struct MmscGrp {
Octstr *mmsc_url; /* URL at which MMSC can be reached. */
struct {
Octstr *user, *pass;
Octstr *allow_ip;
Octstr *deny_ip;
long port;
} incoming; /* user, pass, port (and whether SSL) that MMSC uses to connect to us. */
Octstr *allowed_prefix, *denied_prefix;
enum {UNKNOWN_MMSC, SOAP_MMSC, EAIF_MMSC} type; /* type of connection. */
long throughput; /* Max send rate. */
long threadid; /* handler thread. */
Mutex *mutex;
} MmscGrp;
typedef struct MmsServiceUrlParam {
Octstr *name;
enum {NO_PART, IMAGE_PART, VIDEO_PART,
TEXT_PART, SMIL_PART , OTHER_PART,
ANY_PART } type;
ANY_PART, WHOLE_BINARY} type;
Octstr *value; /* for generic value (type == NO_PART),
* or for value that follows spec (e.g. %Tisatest is allowed) */
} MmsServiceUrlParam;
@ -44,23 +49,28 @@ typedef struct MmsService {
List *keywords; /* List of keywords matched. */
enum {TRANS_TYPE_GET_URL, TRANS_TYPE_POST_URL, TRANS_TYPE_FILE, TRANS_TYPE_EXEC,
TRANS_TYPE_TEXT} type;
Octstr *url;
Octstr *url; /* The value. */
List *params; /* of MmsServiceUrlParam */
Octstr *faked_sender;
List *allowed_mmscs; /* List of MMSCs allowed to access this service (by ID). */
List *denied_mmscs; /* List of MMSCs allowed to access this service (by ID). */
} MmsService;
typedef struct SendMmsUser {
Octstr *user, *pass;
Octstr *faked_sender;
Octstr *dlr_url, *rr_url;
} SendMmsUser;
/* Basic settings for the mmsbox. */
extern List *sendmms_users; /* list of SendMmsUser structs */
extern List *mms_services; /* list of MMS Services */
extern List *mmscs;
extern Octstr *incoming_qdir, *outgoing_qdir;
extern List *mmscs; /* MMSC list. Perhaps turn into a Dict instead? */
extern Octstr *incoming_qdir, *outgoing_qdir, *dlr_dir;
extern Octstr *unified_prefix;
extern long mmsbox_maxsendattempts, mmsbox_send_back_off;
extern long queue_interval, maxthreads;
extern struct SendMmsPortInfo {
long port; /* Might be ssl-ed. */
Octstr *allow_ip;

View File

@ -23,10 +23,6 @@
#include "mmsc_cfg.h"
#include "mms_queue.h"
#define MAXQTRIES 100
#define BACKOFF_FACTOR 5*60 /* In seconds */
#define QUEUERUN_INTERVAL 15*60 /* 15 minutes. */
#define DEFAULT_EXPIRE 3600*24*7 /* One week */
#define MMS_PORT 8191 /* Default content fetch port. */
@ -154,6 +150,9 @@ MmscSettings *mms_load_mmsc_settings(Cfg *cfg, List **proxyrelays)
s = _mms_cfg_getx(grp, octstr_imm("queue-run-interval"));
if (!s || (m->queue_interval = atof(octstr_get_cstr(s))) <= 0)
m->queue_interval = QUEUERUN_INTERVAL;
if (s)
octstr_destroy(s);
if (cfg_get_integer(&m->send_back_off, grp, octstr_imm("send-attempt-back-off")) == -1)
m->send_back_off = BACKOFF_FACTOR;

View File

@ -24,7 +24,7 @@ static Octstr *xproxy;
enum {TPLMN, TEMAIL, TOTHER} ttype;
static int find_own(int i, int argc, char *argv[]);
static int isphonenum(Octstr *s);
static void fixup_recipient(void);
static void fixup_sender(void);
@ -144,6 +144,7 @@ int main(int argc, char *argv[])
qf = mms_queue_add(xfrom, lto, NULL, xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
NULL, NULL,
NULL, NULL,
dlr,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
@ -174,6 +175,7 @@ int main(int argc, char *argv[])
0, time(NULL) + settings->default_msgexpiry,
mresp, NULL,
NULL, NULL,
NULL, NULL,
0,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
@ -243,7 +245,8 @@ int main(int argc, char *argv[])
qf = mms_queue_add(xfrom, lto, NULL,
xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
NULL, NULL,
NULL, NULL,
NULL, NULL,
0,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
@ -280,6 +283,7 @@ int main(int argc, char *argv[])
xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
NULL, NULL,
NULL, NULL,
0,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
@ -335,19 +339,6 @@ static int find_own(int i, int argc, char *argv[])
return -1;
}
static int isphonenum(Octstr *s)
{
int i = 0, n = octstr_len(s);
char *cs;
if (s && octstr_len(s) >= 1 &&
octstr_get_cstr(s)[0] == '+')
i++;
for ( cs = octstr_get_cstr(s); i<n; i++)
if (!gw_isdigit(cs[i]))
return 0;
return 1;
}
static void fixup_recipient(void)
{

View File

@ -254,6 +254,7 @@ static int sendMsg(MmsEnvelope *e)
err, NULL, e->fromproxy,
tnow, tnow+settings->default_msgexpiry, m, NULL,
NULL, NULL,
NULL, NULL,
0,
qdir,
settings->host_alias);
@ -393,6 +394,7 @@ int mms_sendtomobile(Octstr *from, Octstr *to,
ret = mms_queue_add(from, l, subject, fromproxy, NULL, 0, expires, m,
x, NULL, NULL,
NULL, NULL,
dlr, mobile_qdir,
settings->host_alias);
octstr_destroy(x);
@ -432,6 +434,7 @@ static int mms_sendtoproxy(Octstr *from, Octstr *to,
Octstr *ret;
list_append(l, to);
ret = mms_queue_add(from, l, subject, NULL, proxy, 0, expires, msg,NULL,
NULL, NULL,
NULL, NULL,
dlr, mm4_qdir,
settings->host_alias);
@ -489,7 +492,8 @@ static int mm7soap_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
list_append(xto, to);
if ((mreq = mm7_mmsmsg_to_soap(m, from, xto, msgId, settings->host_alias)) == NULL) {
if ((mreq = mm7_mmsmsg_to_soap(m, from, xto, msgId, settings->host_alias,
0, NULL, NULL)) == NULL) {
*error = octstr_format("Failed to convert Msg[%s] 2 SOAP message!",
mms_message_type_to_cstr(mtype));
goto done1;

View File

@ -412,6 +412,7 @@ static int sendNotify(MmsEnvelope *e)
NULL, fromproxy,
tnow, tnow+settings->default_msgexpiry, m, NULL,
NULL, NULL,
NULL, NULL,
0,
octstr_get_cstr(settings->mm1_queuedir),
settings->host_alias);

View File

@ -23,18 +23,6 @@
#include "mms_mm7soap.h"
static Cfg *cfg;
static List *proxyrelays;
static MmscSettings *settings;
static int rstop = 0;
static void quit_now(int notused)
{
rstop = 1;
if (settings)
http_close_port(settings->port);
}
typedef struct MmsHTTPClientInfo {
HTTPClient *client;
Octstr *ua;
@ -49,6 +37,18 @@ typedef struct MmsHTTPClientInfo {
MmsVasp *vasp;
} MmsHTTPClientInfo;
static Cfg *cfg;
static List *proxyrelays;
static MmscSettings *settings;
static int rstop = 0;
static void quit_now(int notused)
{
rstop = 1;
if (settings)
http_close_port(settings->port);
}
static void free_clientInfo(MmsHTTPClientInfo *h, int freeh);
static void fetchmms_proxy(MmsHTTPClientInfo *h);
static void sendmms_proxy(MmsHTTPClientInfo *h);
@ -418,78 +418,6 @@ void fetchmms_proxy(MmsHTTPClientInfo *h)
}
/* Make list of recipients and also sender. */
static void collect_senddata(List *mh, List **xto,
Octstr **subject,
Octstr **otransid, time_t *expiryt, time_t *deliveryt)
{
Octstr *s;
List *l = http_header_find_all(mh, "To");
if (l) {
int i, n;
for (i = 0, n = list_len(l); i<n; i++) {
Octstr *name, *value;
http_header_get(l, i, &name, &value);
list_append(*xto, value);
octstr_destroy(name);
}
http_destroy_headers(l);
}
l = http_header_find_all(mh, "Cc");
if (l) {
int i, n;
for (i = 0, n = list_len(l); i<n; i++) {
Octstr *name, *value;
http_header_get(l, i, &name, &value);
list_append(*xto, value);
octstr_destroy(name);
}
http_destroy_headers(l);
}
l = http_header_find_all(mh, "Bcc");
if (l) {
int i, n;
for (i = 0, n = list_len(l); i<n; i++) {
Octstr *name, *value;
http_header_get(l, i, &name, &value);
list_append(*xto, value);
octstr_destroy(name);
}
http_destroy_headers(l);
}
/* Find expiry and delivery times */
if (expiryt) {
s = http_header_value(mh, octstr_imm("X-Mms-Expiry"));
if (s) {
*expiryt = date_parse_http(s);
octstr_destroy(s);
} else
*expiryt = time(NULL) + settings->default_msgexpiry;
}
if (deliveryt) {
s = http_header_value(mh, octstr_imm("X-Mms-Delivery-Time"));
if (s) {
*deliveryt = date_parse_http(s);
octstr_destroy(s);
} else
*deliveryt = 0;
}
if (subject)
*subject = http_header_value(mh, octstr_imm("Subject"));
if (otransid)
*otransid = http_header_value(mh, octstr_imm("X-Mms-Transaction-ID"));
}
static void sendmms_proxy(MmsHTTPClientInfo *h)
{
@ -556,7 +484,8 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
Octstr *sdf = NULL;
collect_senddata(mh, &to, &subject, &otransid, &expiryt, &deliveryt);
mms_collect_envdata_from_msgheaders(mh, &to, &subject, &otransid, &expiryt,
&deliveryt, settings->default_msgexpiry);
if (!h->client_addr) {
mresp = mms_sendconf("Error-sending-address-unresolved", "None", octstr_get_cstr(otransid),0,
@ -609,6 +538,7 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
qf = mms_queue_add(from, to, subject,
NULL, NULL, deliveryt, expiryt, m, NULL,
NULL, NULL,
NULL, NULL,
dlr,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
@ -689,7 +619,8 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
Octstr *sdf = NULL;
collect_senddata(mh, &to, &subject, &otransid, &expiryt, &deliveryt);
mms_collect_envdata_from_msgheaders(mh, &to, &subject, &otransid, &expiryt,
&deliveryt, settings->default_msgexpiry);
if (!h->client_addr) {
mresp = mms_sendconf("Error-sending-address-unresolved", "None", octstr_get_cstr(otransid),1,
@ -799,6 +730,7 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
qf2 = mms_queue_add(from, to, subject,
NULL, NULL, deliveryt, expiryt, mfwd, NULL,
NULL, NULL,
NULL, NULL,
dlr,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
@ -886,6 +818,7 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
time(NULL) + settings->default_msgexpiry,
mrep, NULL,
NULL, NULL,
NULL, NULL,
0,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
@ -1005,6 +938,7 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
x = mms_queue_add(settings->system_user, l, NULL, NULL, NULL, 0,
time(NULL) + settings->default_msgexpiry, mrpt, NULL,
NULL, NULL,
NULL, NULL,
0,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
@ -1050,12 +984,14 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
if (mms_convert_readrec2readorig(m) < 0)
goto mdone2;
collect_senddata(mh, &to, NULL, NULL, NULL, NULL);
mms_collect_envdata_from_msgheaders(mh, &to, NULL, NULL, NULL, NULL,
settings->default_msgexpiry);
x = mms_queue_add(from, to, NULL, NULL, NULL, time(NULL),
time(NULL) + settings->default_msgexpiry,
m, NULL,
NULL, NULL,
NULL, NULL,
0,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
@ -1664,7 +1600,9 @@ static void mm7soap_dispatch(MmsHTTPClientInfo *h)
qf = mms_queue_add(from ? from : sender, to, subject,
NULL, NULL,
delivert, expiryt, m, NULL,
h->vasp->id, vasid, dlr,
h->vasp->id, vasid,
NULL, NULL,
dlr,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
msgid = mms_maketransid(octstr_get_cstr(qf), settings->host_alias);
@ -1857,7 +1795,8 @@ static void mm7eaif_dispatch(MmsHTTPClientInfo *h)
/* Now get sender and receiver data.
* for now we ignore adaptation flags.
*/
collect_senddata(mh, &to, &subject, &otransid, &expiryt, &deliveryt);
mms_collect_envdata_from_msgheaders(mh, &to, &subject, &otransid, &expiryt,
&deliveryt, settings->default_msgexpiry);
if ((hto = http_header_find_all(h->headers, "X-NOKIA-MMSC-To")) != NULL &&
@ -1912,6 +1851,7 @@ static void mm7eaif_dispatch(MmsHTTPClientInfo *h)
qf = mms_queue_add(hfrom, to, subject,
NULL, NULL, deliveryt, expiryt, m, NULL,
NULL, NULL,
NULL, NULL,
dlr,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
@ -1955,7 +1895,7 @@ static void mm7eaif_dispatch(MmsHTTPClientInfo *h)
static void mm7proxy(void *unused)
{
MmsHTTPClientInfo h = {NULL};
MmsHTTPClientInfo h = {NULL};
while(rstop == 0 &&
(h.client = http_accept_request(settings->mm7port,
&h.ip, &h.url, &h.headers,

View File

@ -137,6 +137,7 @@ int main(int argc, char *argv[])
time(NULL) + settings->default_msgexpiry, m,
NULL,
NULL, NULL,
NULL, NULL,
0,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);