1
0
Fork 0

various fixes: mt mms filter, added sendmms cgi param

This commit is contained in:
bagyenda 2007-07-17 08:26:38 +00:00
parent eef103ae02
commit 5e84205190
16 changed files with 363 additions and 86 deletions

View File

@ -1,3 +1,7 @@
2007-07-13 P. A. Bagyenda <bagyenda@dsmagic.com>
* Introduced ability to filter MT MMS on the VAS side using a generalized module.
* send-mms interface now allows you to push content by specifying a url using content-url CGI param.
* Various minor fixes.
2007-06-21 P. A. Bagyenda <bagyenda@dsmagic.com> 2007-06-21 P. A. Bagyenda <bagyenda@dsmagic.com>
* Better configurability of MM7/SOAP namespace URI and MM7 version. * Better configurability of MM7/SOAP namespace URI and MM7 version.
2007-06-12 P. A. Bagyenda <bagyenda@dsmagic.com> 2007-06-12 P. A. Bagyenda <bagyenda@dsmagic.com>

View File

@ -37,6 +37,7 @@ dnl add mmlib to the include path
INCLUDES='-I$(top_srcdir)/mmlib -I$(top_builddir)/mmlib' INCLUDES='-I$(top_srcdir)/mmlib -I$(top_builddir)/mmlib'
AC_SUBST([INCLUDES]) AC_SUBST([INCLUDES])
dnl Checks for libraries. dnl Checks for libraries.
AC_CHECK_LIB([dl], [dlsym]) AC_CHECK_LIB([dl], [dlsym])
dnl AC_CHECK_LIB([iconv], [libiconv], [LIBS="$LIBS -liconv"]) dnl AC_CHECK_LIB([iconv], [libiconv], [LIBS="$LIBS -liconv"])

View File

@ -1301,7 +1301,7 @@ lists all the configuration directives. The column <b>Mode</b>
&nbsp; &nbsp;</td> &nbsp; &nbsp;</td>
</tr> </tr>
<tr > <tr >
<td valign=top > <td valign=top >
<tt>detokenizer-library</tt> <tt>detokenizer-library</tt>
&nbsp; &nbsp;</td> &nbsp; &nbsp;</td>
@ -1572,6 +1572,31 @@ Boolean
&nbsp; &nbsp;</td> &nbsp; &nbsp;</td>
</tr> </tr>
<tr >
<td valign=top >
<tt>mmsbox-mt-filter-library</tt>
&nbsp; &nbsp;</td>
<td valign=top >
String
&nbsp; &nbsp;</td>
<td valign=top >
<i>VAS GW</i>
&nbsp; &nbsp;
</td>
<td valign=top >
Optional library to be used for filtering/transforming all content (except
SMIL), while building the MT MMS from a SMIL file. This is useful if say you want
to implement custom filtering/transformation of content (e.g. DRM
wrappers around selected content). Note that only elements
referenced within the returned SMIL are filtered. See
<tt>mmsbox_mt_filter.h</tt> for details. Also see
<tt>mm7-mt-filter-params</tt> config variable in the <a href="#mmsc_vasp">VAS specific
config section</a>.
&nbsp; &nbsp;</td>
</tr>
</table> </table>
<br> <br>
<a name="builtin"></a><h4>Built-in billing, resolver and detokenizer <a name="builtin"></a><h4>Built-in billing, resolver and detokenizer
@ -2202,6 +2227,23 @@ string
</td> </td>
</tr> </tr>
<tr>
<td valign=top >
<tt>mm7-mt-filter-params</tt>
</td>
<td valign=top >
String
</td>
<td valign=top >
Parameter(s) to be passed to the <tt>init</tt> function of the MT
MMS filter module specified in <tt>mmsbox-mt-filter-libary</tt>
above. (See
<tt>mmsbox_mt_filter.h</tt> for details.) The <tt>init function</tt> is called once for each MMC
connection, and must return no error, otherwise no filtering will be
done on MT messages via this MMC.
</td>
</tr>
</table> </table>
@ -2394,7 +2436,9 @@ faked-sender = 100<br>
settings for the configured MMSCs. <i>Note: The VAS Gateway settings for the configured MMSCs. <i>Note: The VAS Gateway
considers that any MMSC can handle email and IP address recipient considers that any MMSC can handle email and IP address recipient
addresses and so routes messages to such destinations to the first addresses and so routes messages to such destinations to the first
configured MMSC</i> configured MMSC. Note too that MT MMS filtering will not be
done on messages sent via the send-mms interface unless a particular
destination MMC is specified using this variable</i>
</td> </td>
</tr> </tr>
@ -2449,6 +2493,15 @@ faked-sender = 100<br>
</td> </td>
</tr> </tr>
<tr>
<td valign=top >
<tt>content-url</tt>
</td>
<td valign=top >
If provided, specifies the URL of the content to be sent.
</td>
</tr>
<tr> <tr>
<td valign=top > <td valign=top >
<tt>content</tt> <tt>content</tt>
@ -2509,7 +2562,7 @@ faked-sender = 100<br>
<td valign=top > <td valign=top >
<tt>allow-adaptations</tt> <tt>allow-adaptations</tt>
</td> </td>
<td valign=top > <td valign=top>
Should be 1 (yes) or 0 (no). This flag will be passed on to the Should be 1 (yes) or 0 (no). This flag will be passed on to the
operator MMSC (MM7/SOAP only) to turn on/off content adapation. operator MMSC (MM7/SOAP only) to turn on/off content adapation.
</td> </td>
@ -2520,10 +2573,10 @@ faked-sender = 100<br>
</p> </p>
<p> <p>
<b>Note: </b> You should specify only one <b>Note: </b> Only one
of <tt>text</tt>, <tt>smil</tt> or <tt>content</tt>, as only one of of <tt>text</tt>, <tt>smil</tt>, <tt>content-url</tt> or
them makes sense at any time. specifying more than one causes others <tt>content</tt> should be speficied, as only one makes sense at any time. Specifying more than one causes others
to be ignored. to be (silently) ignored.
</p> </p>
<p> <p>

View File

@ -1,4 +1,4 @@
noinst_LTLIBRARIES = libmms.la noinst_LIBRARIES = libmms.a
libmms_la_SOURCES = mms_mmbox.c mms_msg.c mms_queue.c mms_strings.c mms_uaprof.c mms_util.c mms_mm7soap.c mms_cfg.c libmms_a_SOURCES = mms_mmbox.c mms_msg.c mms_queue.c mms_strings.c mms_uaprof.c mms_util.c mms_mm7soap.c mms_cfg.c
EXTRA_DIST=mms_strings.def mms_mm7soap.h mms_mmbox.h mms_msg.h mms_queue.h mms_strings.h mms_uaprof.h mms_util.h mms_cfg.h mms_cfg.def EXTRA_DIST=mms_strings.def mms_mm7soap.h mms_mmbox.h mms_msg.h mms_queue.h mms_strings.h mms_uaprof.h mms_util.h mms_cfg.h mms_cfg.def

View File

@ -84,6 +84,8 @@ SINGLE_GROUP(mbuni,
OCTSTR(sendmms-port) OCTSTR(sendmms-port)
OCTSTR(sendmms-port-ssl) OCTSTR(sendmms-port-ssl)
OCTSTR(mmsbox-mt-filter-library)
) )
MULTI_GROUP(mmsproxy, MULTI_GROUP(mmsproxy,
@ -131,6 +133,7 @@ MULTI_GROUP(mmsc,
OCTSTR(type) OCTSTR(type)
OCTSTR(mm7-version) OCTSTR(mm7-version)
OCTSTR(mm7-soap-xmlns) OCTSTR(mm7-soap-xmlns)
OCTSTR(mm7-mt-filter-params)
) )
MULTI_GROUP(mms-service, MULTI_GROUP(mms-service,

View File

@ -1288,6 +1288,14 @@ static void unconvert_mime_msg(MIMEEntity *m)
else if (octstr_case_compare(content_type, else if (octstr_case_compare(content_type,
octstr_imm("multipart/mixed")) == 0) octstr_imm("multipart/mixed")) == 0)
s = "application/vnd.wap.multipart.mixed"; s = "application/vnd.wap.multipart.mixed";
else if (octstr_case_search(content_type, octstr_imm("application/vnd.drm."), 0) == 0 &&
mime_entity_num_parts(m) > 0) { /* fixup drm that might have been screwed up. */
Octstr *x = mime_entity_body(m);
while (mime_entity_num_parts(m) > 0) /* remove them all. this message must not be parsed as mime. */
mime_entity_remove_part(m, 0);
mime_entity_set_body(m, x);
octstr_destroy(x);
}
octstr_destroy(content_type); octstr_destroy(content_type);
} }
@ -1329,7 +1337,7 @@ MIMEEntity *mms_tomime(MmsMsg *msg, int base64)
} }
convert_mime_msg(m); convert_mime_msg(m);
if (base64) if (base64)
base64_mimeparts(m); base64_mimeparts(m,0);
return m; return m;
} }

View File

@ -423,14 +423,14 @@ int _mms_gw_isprint(int c)
/* Change content coding for mime entities that need it. */ /* Change content coding for mime entities that need it. */
void base64_mimeparts(MIMEEntity *m) void base64_mimeparts(MIMEEntity *m, int all)
{ {
int i, n; int i, n;
if ((n = mime_entity_num_parts(m)) > 0) if ((n = mime_entity_num_parts(m)) > 0)
for (i = 0; i<n; i++) { for (i = 0; i<n; i++) {
MIMEEntity *x = mime_entity_get_part(m, i); MIMEEntity *x = mime_entity_get_part(m, i);
base64_mimeparts(x); base64_mimeparts(x, all);
mime_entity_replace_part(m, i, x); mime_entity_replace_part(m, i, x);
mime_entity_destroy(x); mime_entity_destroy(x);
} }
@ -439,10 +439,13 @@ void base64_mimeparts(MIMEEntity *m)
Octstr *ctype = http_header_value(headers, octstr_imm("Content-Type")); Octstr *ctype = http_header_value(headers, octstr_imm("Content-Type"));
Octstr *te = http_header_value(headers, octstr_imm("Content-Transfer-Encoding")); Octstr *te = http_header_value(headers, octstr_imm("Content-Transfer-Encoding"));
Octstr *body = mime_entity_body(m); Octstr *body = mime_entity_body(m);
if (ctype && !te && if (ctype &&
(body && octstr_check_range(body, 0, octstr_len(body), _mms_gw_isprint) == 0)) { (te == NULL || octstr_str_case_compare(te, "binary") == 0) &&
body &&
(all || octstr_check_range(body, 0, octstr_len(body), _mms_gw_isprint) == 0)) {
octstr_binary_to_base64(body); octstr_binary_to_base64(body);
http_header_remove_all(headers, "Content-Transfer-Encoding");
http_header_add(headers, "Content-Transfer-Encoding", "base64"); http_header_add(headers, "Content-Transfer-Encoding", "base64");
mime_entity_set_body(m, body); mime_entity_set_body(m, body);
mime_replace_headers(m, headers); mime_replace_headers(m, headers);
@ -681,7 +684,7 @@ int mms_sendtoemail(Octstr *from, Octstr *to,
return -ret; return -ret;
} }
base64_mimeparts(m); /* make sure parts are base64 formatted. */ base64_mimeparts(m,0); /* make sure parts are base64 formatted. */
headers = mime_entity_headers(m); headers = mime_entity_headers(m);
@ -1140,7 +1143,7 @@ done:
return ret; return ret;
} }
/* get content-ID header, fix: WAP decoder may leave " at beginning */ /* get content-ID header, fix: WAP decoder may leave \" at beginning */
Octstr *_x_get_content_id(List *headers) Octstr *_x_get_content_id(List *headers)
{ {
Octstr *cid = http_header_value(headers, octstr_imm("Content-ID")); Octstr *cid = http_header_value(headers, octstr_imm("Content-ID"));
@ -1166,6 +1169,10 @@ void strip_boundary_element(List *headers, char *s)
if ((n = get_content_type(headers, &ctype, &params)) < 0) { if ((n = get_content_type(headers, &ctype, &params)) < 0) {
octstr_destroy(ctype); octstr_destroy(ctype);
ctype = NULL; /* no ctype found, so do not replace it! */ ctype = NULL; /* no ctype found, so do not replace it! */
} else if (ctype &&
octstr_case_search(ctype, octstr_imm("application/vnd.oma.drm"), 0) == 0) {
octstr_destroy(ctype);
ctype = NULL; /* leave drm alone! */
} }
if (s) {/* we are replacing the content type as well as stripping */ if (s) {/* we are replacing the content type as well as stripping */
@ -1223,8 +1230,9 @@ static struct {
{"application/smil", "smil"}, {"application/smil", "smil"},
{"application/vnd.wap.mms-message", "mms"}, {"application/vnd.wap.mms-message", "mms"},
{"application/java-archive", "jar"}, {"application/java-archive", "jar"},
{"video/3gpp", "3gp"},
{"video/3gpp", "3gp2"}, {"video/3gpp", "3gp2"},
{"video/3gpp", "3gp"},
{NULL, NULL} {NULL, NULL}
}; };
@ -1241,6 +1249,16 @@ Octstr *filename2content_type(char *fname)
return octstr_imm("application/octet-stream"); return octstr_imm("application/octet-stream");
} }
char *content_type2file_ext(Octstr *ctype)
{
int i;
for (i = 0; exts[i].file_ext; i++)
if (octstr_str_case_compare(ctype, exts[i].ctype) == 0)
return exts[i].file_ext;
return ".dat";
}
static int fetch_url_with_auth(HTTPCaller *c, int method, Octstr *url, List *request_headers, static int fetch_url_with_auth(HTTPCaller *c, int method, Octstr *url, List *request_headers,
Octstr *body, Octstr *auth_hdr, List **reply_headers, Octstr **reply_body); Octstr *body, Octstr *auth_hdr, List **reply_headers, Octstr **reply_body);

View File

@ -15,6 +15,7 @@
#include "gwlib/gwlib.h" #include "gwlib/gwlib.h"
#include "gwlib/mime.h" #include "gwlib/mime.h"
#include "gwlib/regex.h"
#include "mbuni-config.h" #include "mbuni-config.h"
#include "mms_strings.h" #include "mms_strings.h"
@ -88,8 +89,10 @@ void unpack_mimeheaders(MIMEEntity *m);
/* Where element has base64 encoding, decode. */ /* Where element has base64 encoding, decode. */
void unbase64_mimeparts(MIMEEntity *m); void unbase64_mimeparts(MIMEEntity *m);
/* Where element contains binary data, encode it base64. */ /* Where element contains binary data, encode it base64. Set all = 1 to ignore whether body is binary
void base64_mimeparts(MIMEEntity *m); * and should be coded.
*/
void base64_mimeparts(MIMEEntity *m, int all);
/* Send this message to email recipient: Returns 0 on success 1 or 2 on profile error /* Send this message to email recipient: Returns 0 on success 1 or 2 on profile error
@ -183,6 +186,10 @@ int mms_is_token(Octstr *token);
/* try to guess content type from file name extension. */ /* try to guess content type from file name extension. */
Octstr *filename2content_type(char *fname); Octstr *filename2content_type(char *fname);
/* try to give a good extension name based on the content type. */
char *content_type2file_ext(Octstr *ctype);
#define MAXQTRIES 100 #define MAXQTRIES 100
#define BACKOFF_FACTOR 5*60 /* In seconds */ #define BACKOFF_FACTOR 5*60 /* In seconds */
#define QUEUERUN_INTERVAL 1*60 /* 1 minutes. */ #define QUEUERUN_INTERVAL 1*60 /* 1 minutes. */

View File

@ -1,7 +1,7 @@
libmms = $(top_builddir)/mmlib/libmms.la libmms = $(top_builddir)/mmlib/libmms.a
bin_PROGRAMS = mmsbox bin_PROGRAMS = mmsbox
mmsbox_SOURCES = mmsbox.c mmsbox_cfg.c dlr.c bearerbox.c mmsbox_SOURCES = mmsbox.c mmsbox_cfg.c dlr.c bearerbox.c
mmsbox_LDADD = $(libmms) mmsbox_LDADD = $(libmms)
EXTRA_DIST = mmsbox_cfg.h mmsbox.h EXTRA_DIST = mmsbox_cfg.h mmsbox.h mmsbox_msg_filter.h

View File

@ -626,7 +626,7 @@ static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, Octstr *to,
tstatus, tmp ? tmp : "", tstatus, tmp ? tmp : "",
detail ? octstr_get_cstr(detail) : ""); detail ? octstr_get_cstr(detail) : "");
*error = octstr_format("Failed to deliver to MMC[url=%s, id=%S], status=[%d=>%s]!", *error = octstr_format("Failed to deliver to MMC[url=%S, id=%S], status=[%d=>%s]!",
mmc->mmsc_url, mmc->mmsc_url,
mmc->id, mmc->id,
tstatus, tstatus,
@ -737,7 +737,8 @@ static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to,
if (ret) if (ret)
mms_log2("Sent", from, to, -1, ret, NULL, mmc->id, "MMSBox", NULL, NULL); mms_log2("Sent", from, to, -1, ret, NULL, mmc->id, "MMSBox", NULL, NULL);
info(0, "Sent to MMC[%s], code=[%d], resp=[%s] msgid [%s]", octstr_get_cstr(mmc->id), info(0, "Sent to MMC[%s], code=[%d], resp=[%s] msgid [%s]",
octstr_get_cstr(mmc->id),
hstatus, resp ? octstr_get_cstr(resp) : "(none)", ret ? octstr_get_cstr(ret) : "(none)"); hstatus, resp ? octstr_get_cstr(resp) : "(none)", ret ? octstr_get_cstr(ret) : "(none)");
if (rh) if (rh)
@ -806,44 +807,6 @@ static int mms_sendtommsc(MmscGrp *mmc, Octstr *from, Octstr *to, Octstr *transi
return ret; return ret;
} }
/* 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 = gwlist_len(mmscs); i < n; i++)
if ((mmc = gwlist_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 gwlist_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 = gwlist_len(mmscs); i < n; i++)
if ((mmc = gwlist_get(mmscs, i)) != NULL &&
(mmc->allowed_prefix == NULL ||
does_prefix_match(mmc->allowed_prefix, phonenum)) &&
(mmc->denied_prefix == NULL ||
!does_prefix_match(mmc->denied_prefix, phonenum)))
return mmc;
if (phonenum)
octstr_destroy(phonenum);
return NULL;
}
static int sendMsg(MmsEnvelope *e) static int sendMsg(MmsEnvelope *e)
{ {

View File

@ -299,6 +299,7 @@ static int make_and_queue_msg(Octstr *data, Octstr *ctype, List *reply_headers,
Octstr *svc_name, Octstr *faked_sender, Octstr *service_code, Octstr *svc_name, Octstr *faked_sender, Octstr *service_code,
int accept_x_headers, int accept_x_headers,
List *passthro_headers, List *passthro_headers,
Octstr *mmc_id,
Octstr **err); Octstr **err);
static int fetch_serviceurl(MmsEnvelope *e, static int fetch_serviceurl(MmsEnvelope *e,
MmsService *ms, MmsMsg *m, MmsService *ms, MmsMsg *m,
@ -424,7 +425,7 @@ static int fetch_serviceurl(MmsEnvelope *e,
res = make_and_queue_msg(rb, ctype, rph, base_url, res = make_and_queue_msg(rb, ctype, rph, base_url,
typ, e, ms->name, ms->faked_sender, ms->service_code, typ, e, ms->name, ms->faked_sender, ms->service_code,
ms->accept_x_headers, ms->passthro_headers, ms->accept_x_headers, ms->passthro_headers,
err); e->fromproxy, err);
if (base_url) if (base_url)
octstr_destroy(base_url); octstr_destroy(base_url);
@ -658,7 +659,9 @@ static int has_url_scheme(char *url)
static int add_msg_part(MIMEEntity *res, xmlNodePtr node, Octstr *base_url, static int add_msg_part(MIMEEntity *res, xmlNodePtr node, Octstr *base_url,
Octstr *top_url, Octstr *top_url,
int type, Octstr *svc_name, Dict *url_map) int type, Octstr *svc_name,
Octstr *mmc_id,
Dict *url_map)
{ {
Octstr *curl = NULL, *ctype = NULL, *body = NULL; Octstr *curl = NULL, *ctype = NULL, *body = NULL;
char *src = NULL; char *src = NULL;
@ -729,7 +732,8 @@ static int add_msg_part(MIMEEntity *res, xmlNodePtr node, Octstr *base_url,
} }
if (ctype && body) { /* If we got it, put it in. */ if (ctype && body) { /* If we got it, put it in. */
Octstr *attr = octstr_format("cid:%06d", ++cntr); char *fext = content_type2file_ext(ctype);
Octstr *attr = octstr_format("cid:%06d.%s", ++cntr,fext);
char *p = octstr_get_cstr(attr) + 4; char *p = octstr_get_cstr(attr) + 4;
Octstr *cid_header_val = octstr_format("<%s>", p); Octstr *cid_header_val = octstr_format("<%s>", p);
MIMEEntity *x = mime_entity_create(); MIMEEntity *x = mime_entity_create();
@ -737,10 +741,18 @@ static int add_msg_part(MIMEEntity *res, xmlNodePtr node, Octstr *base_url,
http_header_add(headers, "Content-Type", octstr_get_cstr(ctype)); http_header_add(headers, "Content-Type", octstr_get_cstr(ctype));
http_header_add(headers, "Content-ID", octstr_get_cstr(cid_header_val)); http_header_add(headers, "Content-ID", octstr_get_cstr(cid_header_val));
http_header_add(headers, "Content-Location", p);
mime_replace_headers(x, headers); mime_replace_headers(x, headers);
mime_entity_set_body(x, body); mime_entity_set_body(x, body);
if (mt_filter && mmc_id)
mt_filter->filter(&x, curl, mmc_id);
#if 1
/* show it. */
Octstr *_x = mime_entity_to_octstr(x);
octstr_dump(_x,0);
#endif
mime_entity_add_part(res, x); mime_entity_add_part(res, x);
mime_entity_destroy(x); mime_entity_destroy(x);
@ -767,15 +779,18 @@ done:
/* Traverse the tree doing the above. */ /* Traverse the tree doing the above. */
static void add_msg_parts(MIMEEntity *res, xmlNodePtr node, Octstr *base_url, static void add_msg_parts(MIMEEntity *res, xmlNodePtr node, Octstr *base_url,
Octstr *top_url, Octstr *top_url,
int type, Octstr *svc_name, Dict *url_map) int type, Octstr *svc_name,
Octstr *mmc_id,
Dict *url_map)
{ {
xmlNodePtr n; xmlNodePtr n;
/* Do all the children recursively, then come back and do parent. */ /* Do all the children recursively, then come back and do parent. */
for (n = node; n; n = n->next) for (n = node; n; n = n->next)
if (n->type != XML_COMMENT_NODE) { if (n->type != XML_COMMENT_NODE) {
add_msg_part(res, n, base_url, top_url, type, svc_name, url_map); add_msg_part(res, n, base_url, top_url, type, svc_name, mmc_id, url_map);
add_msg_parts(res, n->xmlChildrenNode, base_url, top_url, type, svc_name, url_map); add_msg_parts(res, n->xmlChildrenNode, base_url, top_url, type,
} svc_name, mmc_id, url_map);
}
} }
/* Given content, make a message. We'll also use this for send-mms-user! */ /* Given content, make a message. We'll also use this for send-mms-user! */
@ -783,6 +798,7 @@ static int make_and_queue_msg(Octstr *data, Octstr *ctype, List *reply_headers,
Octstr *base_url, int type, MmsEnvelope *e, Octstr *base_url, int type, MmsEnvelope *e,
Octstr *svc_name, Octstr *faked_sender, Octstr *service_code, Octstr *svc_name, Octstr *faked_sender, Octstr *service_code,
int accept_x_headers, List *passthro_headers, int accept_x_headers, List *passthro_headers,
Octstr *mmc_id,
Octstr **err) Octstr **err)
{ {
Octstr *from = NULL, *subject = NULL, *turl = get_toplevel_url(base_url); Octstr *from = NULL, *subject = NULL, *turl = get_toplevel_url(base_url);
@ -850,7 +866,9 @@ static int make_and_queue_msg(Octstr *data, Octstr *ctype, List *reply_headers,
goto done; goto done;
} }
add_msg_parts(me, smil->xmlChildrenNode, base_url, turl, type, svc_name, url_map); add_msg_parts(me, smil->xmlChildrenNode,
base_url, turl, type, svc_name,
mmc_id, url_map);
dict_destroy(url_map); dict_destroy(url_map);
/* SMIL has been modified, convert it to text, put it in. */ /* SMIL has been modified, convert it to text, put it in. */
@ -1097,6 +1115,8 @@ static void sendmms_func(void *unused)
if ((base_url = http_cgi_variable(cgivars, "base-url")) == NULL) if ((base_url = http_cgi_variable(cgivars, "base-url")) == NULL)
base_url = octstr_imm("http://localhost"); base_url = octstr_imm("http://localhost");
else
base_url = octstr_duplicate(base_url); /* because we need to delete it below. */
if ((data = http_cgi_variable(cgivars, "text")) != NULL) { /* text. */ if ((data = http_cgi_variable(cgivars, "text")) != NULL) { /* text. */
Octstr *charset = http_cgi_variable(cgivars, "charset"); Octstr *charset = http_cgi_variable(cgivars, "charset");
@ -1106,7 +1126,24 @@ static void sendmms_func(void *unused)
octstr_format_append(ctype, "; charset=%S", charset); octstr_format_append(ctype, "; charset=%S", charset);
} else if ((data = http_cgi_variable(cgivars, "smil")) != NULL) /* smil. */ } else if ((data = http_cgi_variable(cgivars, "smil")) != NULL) /* smil. */
ctype = octstr_imm("application/smil"); ctype = octstr_imm("application/smil");
else if ((data = http_cgi_variable(cgivars, "content")) != NULL) { /* any content. */ else if ((data = http_cgi_variable(cgivars, "content-url")) != NULL) { /* arbitrary content. */
List *rh = http_create_empty_headers(), *rph = NULL;
Octstr *reply = NULL, *params = NULL;
http_header_add(rh, "User-Agent", MM_NAME "/" VERSION);
if (mmsbox_url_fetch_content(HTTP_METHOD_GET, data, rh, octstr_imm(""), &rph, &reply) == HTTP_OK)
get_content_type(rph, &ctype, &params);
else
rb = octstr_format("failed to fetch content from url [%S]!", data);
base_url = url_path_prefix(data, URL_TYPE);
data = reply;
http_destroy_headers(rh);
http_destroy_headers(rph);
octstr_destroy(params);
} else if ((data = http_cgi_variable(cgivars, "content")) != NULL) { /* any content. */
Octstr *_xctype = NULL; /* ... because cgi var stuff is destroyed elsewhere, we must dup it !! */ Octstr *_xctype = NULL; /* ... because cgi var stuff is destroyed elsewhere, we must dup it !! */
/* If the user sent us a content element, then they should have /* If the user sent us a content element, then they should have
@ -1115,8 +1152,7 @@ static void sendmms_func(void *unused)
*/ */
if ((_xctype = http_cgi_variable(cgivars, "content_type")) == NULL) if ((_xctype = http_cgi_variable(cgivars, "content_type")) == NULL)
if (cgivar_ctypes) if (cgivar_ctypes)
_xctype = http_cgi_variable(cgivar_ctypes, "content"); _xctype = http_cgi_variable(cgivar_ctypes, "content");
if (_xctype) if (_xctype)
ctype = octstr_duplicate(_xctype); ctype = octstr_duplicate(_xctype);
} else if (body && tparse != 0) { /* if all above fails, } else if (body && tparse != 0) { /* if all above fails,
@ -1177,7 +1213,9 @@ static void sendmms_func(void *unused)
res = make_and_queue_msg(data, ctype, rh, base_url, URL_TYPE, NULL, res = make_and_queue_msg(data, ctype, rh, base_url, URL_TYPE, NULL,
vasid ? vasid : octstr_imm("sendmms-user"), vasid ? vasid : octstr_imm("sendmms-user"),
u->faked_sender, service_code, u->faked_sender, service_code,
1, NULL, &err); 1, NULL,
mmc,
&err);
if (res < 0) if (res < 0)
rb = octstr_imm("Error in message conversion"); rb = octstr_imm("Error in message conversion");
} else if (!rb) } else if (!rb)
@ -1190,10 +1228,10 @@ static void sendmms_func(void *unused)
if (rh) if (rh)
http_destroy_headers(rh); http_destroy_headers(rh);
if (ctype)
octstr_destroy(ctype); octstr_destroy(ctype);
if (rb) octstr_destroy(rb);
octstr_destroy(rb); octstr_destroy(base_url);
} else { } else {
http_send_reply(client, HTTP_UNAUTHORIZED, hh, http_send_reply(client, HTTP_UNAUTHORIZED, hh,
octstr_imm("Authentication failed")); octstr_imm("Authentication failed"));

View File

@ -23,6 +23,7 @@
#include "mmsbox_cfg.h" #include "mmsbox_cfg.h"
#include "mms_queue.h" #include "mms_queue.h"
List *sendmms_users = NULL; /* list of SendMmsUser structs */ List *sendmms_users = NULL; /* list of SendMmsUser structs */
List *mms_services = NULL; /* list of MMS Services */ List *mms_services = NULL; /* list of MMS Services */
List *mmscs = NULL; List *mmscs = NULL;
@ -34,6 +35,45 @@ Octstr *unified_prefix;
struct SendMmsPortInfo sendmms_port; struct SendMmsPortInfo sendmms_port;
struct MmsBoxMTfilter *mt_filter = NULL;
static void *load_module(mCfgGrp *grp, char *config_key,
char *symbolname)
{
Octstr *s = NULL;
void *retval = NULL;
s = mms_cfg_get(grp, octstr_imm(config_key));
if (s) {
void *x;
void *y = NULL;
#ifdef __APPLE__
char sbuf[512];
#endif
x = dlopen(octstr_get_cstr(s), RTLD_LAZY);
#ifdef __APPLE__
sprintf(sbuf, "_%s", symbolname);
#endif
if (x == NULL || ((y = dlsym(x, symbolname)) == NULL
#ifdef __APPLE__ /* fink version of dlsym has issues it seems. */
&& (y = dlsym(x, sbuf)) == NULL
#endif
))
panic(0,
"Error, unable to load dynamic libary (%s): "
"libhandle is %s, funcs is %s, err=%s",
octstr_get_cstr(s),
x ? "OK" : "Not OK", y ? "OK" : "Not OK", dlerror());
else
retval = y;
octstr_destroy(s);
}
return retval;
}
int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func) int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func)
{ {
mCfgGrp *grp = mms_cfg_get_single(cfg, octstr_imm("mbuni")); mCfgGrp *grp = mms_cfg_get_single(cfg, octstr_imm("mbuni"));
@ -116,6 +156,10 @@ int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func)
sendmms_port.allow_ip = mms_cfg_get(grp, octstr_imm("allow-ip")); sendmms_port.allow_ip = mms_cfg_get(grp, octstr_imm("allow-ip"));
sendmms_port.deny_ip = mms_cfg_get(grp, octstr_imm("deny-ip")); sendmms_port.deny_ip = mms_cfg_get(grp, octstr_imm("deny-ip"));
/* load the filter if any. */
if ((mt_filter = load_module(grp, "mmsbox-mt-filter-library", "mmsbox_mt_filter")) != NULL)
info(0, "MMSBox: Loaded MT Filter [%s]", mt_filter->name);
/* Now get sendmms users. */ /* Now get sendmms users. */
l = mms_cfg_get_multi(cfg, octstr_imm("send-mms-user")); l = mms_cfg_get_multi(cfg, octstr_imm("send-mms-user"));
@ -225,6 +269,20 @@ int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func)
} else } else
m->threadid = -1; m->threadid = -1;
/* Init for filter. */
if ((s = mms_cfg_get(x, octstr_imm("mm7-mt-filter-params"))) != NULL) {
if (mt_filter)
m->use_mt_filter = (mt_filter->init(m->mmsc_url, m->id, s) == 1);
else
panic(0, "MMSBox: mt-filter-params set for MMSC[%s] but no MT-filter lib "
"specified!",
octstr_get_cstr(m->id));
if (!m->use_mt_filter)
warning(0, "MMSBox: MT MMS filter turned off for MMSC[%s]. Init failed",
octstr_get_cstr(m->id));
octstr_destroy(s);
} else
m->use_mt_filter = 0;
m->mutex = mutex_create(); m->mutex = mutex_create();
gwlist_append(mmscs, m); gwlist_append(mmscs, m);
} }
@ -369,3 +427,42 @@ int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func)
return 0; return 0;
} }
/* Get the MMC that should handler this recipient. */
MmscGrp *get_handler_mmc(Octstr *id, Octstr *to)
{
MmscGrp *mmc = NULL;
int i, j, n;
Octstr *phonenum = NULL;
if (id)
for (i = 0, n = gwlist_len(mmscs); i < n; i++)
if ((mmc = gwlist_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 gwlist_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 = gwlist_len(mmscs); i < n; i++)
if ((mmc = gwlist_get(mmscs, i)) != NULL &&
(mmc->allowed_prefix == NULL ||
does_prefix_match(mmc->allowed_prefix, phonenum)) &&
(mmc->denied_prefix == NULL ||
!does_prefix_match(mmc->denied_prefix, phonenum)))
return mmc;
if (phonenum)
octstr_destroy(phonenum);
return NULL;
}

View File

@ -13,7 +13,7 @@
#ifndef __MMSBOX_CFG_INCLUDED__ #ifndef __MMSBOX_CFG_INCLUDED__
#define __MMSBOX_CFG_INCLUDED__ #define __MMSBOX_CFG_INCLUDED__
#include "mms_util.h" #include "mms_util.h"
#include "mmsbox_mt_filter.h"
typedef struct MmscGrp { typedef struct MmscGrp {
Octstr *id; /* MMSC id (for logging). */ Octstr *id; /* MMSC id (for logging). */
Octstr *group_id; /* GROUP MMSC id (used for qf). */ Octstr *group_id; /* GROUP MMSC id (used for qf). */
@ -30,7 +30,7 @@ typedef struct MmscGrp {
long threadid; /* handler thread. */ long threadid; /* handler thread. */
MM7Version_t ver; /* supported MM7/SOAP version. */ MM7Version_t ver; /* supported MM7/SOAP version. */
int use_mt_filter; /* whether to use MT filter on this connection. */
Mutex *mutex; Mutex *mutex;
} MmscGrp; } MmscGrp;
@ -86,6 +86,7 @@ extern struct SendMmsPortInfo {
Octstr *deny_ip; Octstr *deny_ip;
} sendmms_port; } sendmms_port;
extern struct MmsBoxMTfilter *mt_filter;
extern int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func); extern int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func);
extern MmscGrp *get_handler_mmc(Octstr *id, Octstr *to);
#endif #endif

View File

@ -0,0 +1,48 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Empty wrapper library
*
* Copyright (C) 20078 - , Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is proprietary software, refer to licence holder for details
*/
#include <sys/file.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
#include <dlfcn.h>
#include <strings.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mmsbox_mt_filter.h"
static int myinit(Octstr *mmc_url, Octstr *mmc_id, Octstr *startup_params)
{
return 0;
}
static int myfilter(MIMEEntity **msg, Octstr *loc_url, Octstr *mmc_id)
{
return 0;
}
static void myclose(Octstr *mmc_id)
{
return;
}
struct MmsBoxMTfilter mmsbox_mt_filter = {
.name = "Empty Wrapper",
.init = myinit,
.filter = myfilter,
.destroy = myclose
};

View File

@ -0,0 +1,36 @@
/*
* Mbuni - Open Source MMS Gateway
*
* MMSBOX MT MMS filter: Optional filter for MT messages
*
* 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)
*/
#ifndef __MMSMT_FILTER_INCLUDED__
#define __MMSMT_FILTER_INCLUDED__
#include "mms_util.h"
struct MmsBoxMTfilter {
/* name of filter. */
char *name;
/* Init: called once for each mmc to determine if to use filter on MT MMS via the particular MMC. Returns 1
* on success, error otherwise
*/
int (*init)(Octstr *mmc_url, Octstr *mmc_id, Octstr *startup_params);
/* filter: Filter/transform the message. Return 0 on success. May modify the message itself of course */
int (*filter)(MIMEEntity **msg, Octstr *loc_url, Octstr *mmc_id);
/* destroy this mmc's settings in filter. */
void (*destroy)(Octstr *mmc_id);
};
/* Each module must export this symbol, a pointer to the structure.
* WARNING: Ensure your module is thread-safe
*/
extern struct MmsBoxMTfilter mmsbox_mt_filter;
#endif

View File

@ -1,8 +1,8 @@
libmms = $(top_builddir)/mmlib/libmms.la libmms = $(top_builddir)/mmlib/libmms.a
libmmsc = libmmsc.la libmmsc = libmmsc.a
noinst_LTLIBRARIES = libmmsc.la noinst_LIBRARIES = libmmsc.a
libmmsc_la_SOURCES = mmsc_cfg.c mms_detokenize.c mms_resolve.c mms_billing.c mms_detokenize_shell.c mms_resolve_shell.c mms_billing_shell.c libmmsc_a_SOURCES = mmsc_cfg.c mms_detokenize.c mms_resolve.c mms_billing.c mms_detokenize_shell.c mms_resolve_shell.c mms_billing_shell.c
bin_PROGRAMS = mmsrelay mmsproxy mmsfromemail mmssend bin_PROGRAMS = mmsrelay mmsproxy mmsfromemail mmssend
mmsrelay_SOURCES = mmsglobalsender.c mmsmobilesender.c mmsrelay.c mmsrelay_SOURCES = mmsglobalsender.c mmsmobilesender.c mmsrelay.c