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:
parent
fc0524057e
commit
4ceeeb8128
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -34,9 +34,12 @@ typedef struct MmsEnvelope {
|
|||
Octstr *from; /* from address. */
|
||||
|
||||
Octstr *vaspid; /* VASPID (if any) */
|
||||
Octstr *vasid; /* VASID (if any) */
|
||||
Octstr *vasid; /* VASID (if any) */
|
||||
|
||||
List *to; /* List of recipients: MmsEnvelopeTo */
|
||||
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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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,12 +28,376 @@ 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, ¶ms);
|
||||
|
||||
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, ¶ms);
|
||||
|
||||
#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, ¶ms);
|
||||
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();
|
||||
|
||||
srandom(time(NULL));
|
||||
|
@ -53,7 +420,7 @@ 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);
|
||||
|
||||
|
@ -61,5 +428,595 @@ int main(int argc, char *argv[])
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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!",
|
||||
|
@ -66,6 +71,31 @@ int mms_load_mmsbox_settings(Cfg *cfg, gwthread_func_t *mmsc_handler_func)
|
|||
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
|
||||
cfg_get_bool(&send_port_ssl, grp, octstr_imm("sendmms-port-ssl"));
|
||||
|
@ -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);
|
||||
|
||||
|
@ -179,6 +218,12 @@ int mms_load_mmsbox_settings(Cfg *cfg, gwthread_func_t *mmsc_handler_func)
|
|||
} 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) {
|
||||
m->keywords = octstr_split(s, octstr_imm(";"));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
||||
|
@ -155,6 +151,9 @@ MmscSettings *mms_load_mmsc_settings(Cfg *cfg, List **proxyrelays)
|
|||
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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue