This is a multi-part message in MIME format.
--
[ Picked text/plain from multipart/alternative ]
Hi,
Here is a patch that add XMLRPC functionnality to Exim 4.10. The only requirement is the xmlrpc-c (
http://xmlrpc-c.sourceforge.net) library and an XMLRPC server & script. (I will post in a few day my XMLRPC modules w/ mySQL caching, etc...)
It work exactly like the ${perl{arg1}{arg2}} syntax then you can use the ${xmlrpc{function}{arg1}{arg2}..{arg8}} tag anywhere on exim.conf.
Documentation, tutorial, examples, etc.. are currently missing but I will have more time on the following day (or week <g>)
--
Joel Vandal
Infoteck Internet
Trois-Rivières, QC / CAN
====CUT====
diff -Nur exim-4.10/OS/Makefile-Base exim-4.10xmlrpc/OS/Makefile-Base
--- exim-4.10/OS/Makefile-Base 2002-07-22 04:59:45.000000000 -0400
+++ exim-4.10xmlrpc/OS/Makefile-Base 2002-11-12 10:49:21.000000000 -0500
@@ -244,7 +244,7 @@
rda.o readconf.o receive.o retry.o rewrite.o \
route.o search.o smtp_in.o smtp_out.o spool_in.o spool_out.o \
store.o string.o tls.o tod.o transport.o tree.o verify.o \
- local_scan.o $(EXIM_PERL)
+ local_scan.o $(EXIM_PERL) $(EXIM_XMLRPC)
exim: pcre/libpcre.a lookups/lookups.a auths/auths.a \
routers/routers.a transports/transports.a \
@@ -259,7 +259,8 @@
routers/routers.a transports/transports.a lookups/lookups.a \
auths/auths.a \
$(LIBRESOLV) $(LIBS) $(LIBS_EXIM) $(IPV6_LIBS) $(EXTRALIBS) \
- $(EXTRALIBS_EXIM) $(DBMLIB) $(LOOKUP_LIBS) $(PERL_LIBS) $(TLS_LIBS)
+ $(EXTRALIBS_EXIM) $(DBMLIB) $(LOOKUP_LIBS) $(PERL_LIBS) \
+ $(XMLRPC_LIBS) $(TLS_LIBS)
@if [ x"$(STRIP_COMMAND)" != x"" ]; then \
echo $(STRIP_COMMAND) exim; \
$(STRIP_COMMAND) exim; \
@@ -397,6 +398,11 @@
perl.o: $(HDRS) perl.c
$(PERL_CC) $(PERL_CCOPTS) $(INCLUDE) -c perl.c
+# Compile instructions for xmlrpc.o for when EXIM_XMLRPC is set
+
+xmlrpc.o: $(HDRS) xmlrpc.c
+ $(CC) $(CFLAGS) $(INCLUDE) -c xmlrpc.c
+
# Compile instructions for the database utility modules
exim_dumpdb.o: $(HDRS) exim_dbutil.c
diff -Nur exim-4.10/scripts/MakeLinks exim-4.10xmlrpc/scripts/MakeLinks
--- exim-4.10/scripts/MakeLinks 2002-07-22 04:59:47.000000000 -0400
+++ exim-4.10xmlrpc/scripts/MakeLinks 2002-11-12 10:48:51.000000000 -0500
@@ -213,5 +213,6 @@
ln -s ../src/tree.c tree.c
ln -s ../src/verify.c verify.c
ln -s ../src/version.c version.c
+ln -s ../src/xmlrpc.c xmlrpc.c
# End of MakeLinks
diff -Nur exim-4.10/src/EDITME exim-4.10xmlrpc/src/EDITME
--- exim-4.10/src/EDITME 2002-07-22 04:59:47.000000000 -0400
+++ exim-4.10xmlrpc/src/EDITME 2002-11-13 23:02:24.000000000 -0500
@@ -426,6 +426,20 @@
#------------------------------------------------------------------------------
+# Compiling in support for embedded XML-RPC client : If you want to be
+# able to use XMLRPC call, set EXIM_XMLRPC to xmlrpc.o.
+
+# EXIM_XMLRPC=xmlrpc.o
+
+
+#------------------------------------------------------------------------------
+# If you have specified EXIM_XMLRPC=xmlrpc.o you must uncomment the
+# following line to link xmlrpc-c library
+
+# XMLRPC_LIBS=`xmlrpc-c-config libwww-client --libs`
+
+
+#------------------------------------------------------------------------------
# Exim has support for PAM (Pluggable Authentication Modules), a facility
# which is available in the latest releases of Solaris and in some GNU/Linux
# distributions (see
http://ftp.kernel.org/pub/linux/libs/pam/). The Exim
@@ -730,4 +744,5 @@
# SUPPORT_MOVE_FROZEN_MESSAGES=yes
+
# End of EDITME for Exim 4.
diff -Nur exim-4.10/src/config.h.defaults exim-4.10xmlrpc/src/config.h.defaults
--- exim-4.10/src/config.h.defaults 2002-07-22 04:59:48.000000000 -0400
+++ exim-4.10xmlrpc/src/config.h.defaults 2002-11-07 11:38:20.000000000 -0500
@@ -33,6 +33,7 @@
#define EXIMDB_MODE 0640
#define EXIM_PERL
+#define EXIM_XMLRPC
/* Both uid and gid are triggered by this */
#define EXIM_UID
diff -Nur exim-4.10/src/expand.c exim-4.10xmlrpc/src/expand.c
--- exim-4.10/src/expand.c 2002-07-22 04:59:48.000000000 -0400
+++ exim-4.10xmlrpc/src/expand.c 2002-11-12 20:12:38.000000000 -0500
@@ -48,6 +48,9 @@
#ifdef EXIM_PERL
US"perl",
#endif
+ #ifdef EXIM_XMLRPC
+ US"xmlrpc",
+ #endif
US"readfile",
US"run",
US"sg",
@@ -60,6 +63,9 @@
#ifdef EXIM_PERL
EITEM_PERL,
#endif
+ #ifdef EXIM_XMLRPC
+ EITEM_XMLRPC,
+ #endif
EITEM_READFILE,
EITEM_RUN,
EITEM_SG,
@@ -1596,6 +1602,7 @@
${if cond {s1} {s2}} conditional; the yielded string is expanded
{s2} can be replaced by "fail" or be omitted
${perl{sub}{a1}... call Perl (if configured)
+ ${xmlrpc{sub}{a1}... call Perl (if configured)
${sg {source}{s1}{s2}} global substitution
${tr {source}{s1}{s2}} translate characters
@@ -2172,25 +2179,108 @@
if (new_yield == NULL)
{
- if (expand_string_message == NULL)
- {
- expand_string_message =
- string_sprintf("Perl subroutine \"%s\" returned undef to force "
- "failure", sub_arg[0]);
- expand_string_forcedfail = TRUE;
- }
- goto EXPAND_FAILED;
- }
-
- /* Yield succeeded. Ensure forcedfail is unset, just in case it got
- set during a callback from Perl. */
-
- expand_string_forcedfail = FALSE;
- yield = new_yield;
- continue;
+ if (expand_string_message == NULL)
+ {
+ expand_string_message =
+ string_sprintf("Perl subroutine \"%s\" returned undef to force "
+ "failure", sub_arg[0]);
+ expand_string_forcedfail = TRUE;
+ }
+ goto EXPAND_FAILED;
+ }
+
+ /* Yield succeeded. Ensure forcedfail is unset, just in case it got
+ set during a callback from Perl. */
+
+ expand_string_forcedfail = FALSE;
+ yield = new_yield;
+ continue;
}
- #endif /* EXIM_PERL */
-
+#endif /* EXIM_PERL */
+
+ /* If XMLRPC support is configured, handle calling xmlrpc subroutines,
+ unless locked out at this time. Syntax is ${xmlrpc{sub}} or
+ ${xmlrpc{sub}{arg}} or ${xmlrpc{sub}{arg1}{arg2}} or up to a maximum of
+ EXIM_XMLRPC_MAX_ARGS arguments (defined below). */
+
+#ifdef EXIM_XMLRPC
+#define EXIM_XMLRPC_MAX_ARGS 8
+
+ case EITEM_XMLRPC:
+ {
+ uschar *sub_arg[EXIM_XMLRPC_MAX_ARGS + 2];
+ uschar *new_yield;
+ uschar *initerror;
+ DEBUG(D_any) debug_printf("Entering XMLRPC\n");
+
+ if ((expand_forbid & RDO_XMLRPC) != 0)
+ {
+ expand_string_message = US"XMLRPC calls are not permitted";
+ goto EXPAND_FAILED;
+ }
+
+ switch(read_subs(sub_arg, EXIM_XMLRPC_MAX_ARGS + 1, 1, &s, skipping))
+ {
+ case 1: goto EXPAND_FAILED_CURLY;
+ case 2: expand_string_message =
+ string_sprintf("Too many arguments passed to XMLRPC "
+ "subroutine \"%s\" (max is %d)", sub_arg[0],
+ EXIM_XMLRPC_MAX_ARGS);
+ case 3: goto EXPAND_FAILED;
+ }
+
+ /* If skipping, we don't actually do anything */
+
+ if (skipping) continue;
+
+ /* Start the interpreter if necessary */
+
+ if (xmlrpc_servers == NULL)
+ {
+ expand_string_message = US"A setting of xmlrpc_servers is needed when "
+ "using the XMLRPC module";
+ goto EXPAND_FAILED;
+ }
+ DEBUG(D_any) debug_printf("Starting XMLRPC\n");
+ initerror = init_xmlrpc(xmlrpc_servers);
+ if (initerror != NULL)
+ {
+ expand_string_message =
+ string_sprintf("error in xmlrpc code: %s\n", initerror);
+ goto EXPAND_FAILED;
+ }
+
+ /* Call the function */
+
+ sub_arg[EXIM_XMLRPC_MAX_ARGS + 1] = NULL;
+ new_yield = call_xmlrpc_cat(yield, &size, &ptr, &expand_string_message,
+ sub_arg[0], sub_arg + 1);
+
+ /* NULL yield indicates failure; if the message pointer has been set to
+ NULL, the yield was undef, indicating a forced failure. Otherwise the
+ message will indicate some kind of Perl error. */
+
+ if (new_yield == NULL)
+ {
+ if (expand_string_message == NULL)
+ {
+ expand_string_message =
+ string_sprintf("XMLRPC subroutine \"%s\" returned undef to force "
+ "failure", sub_arg[0]);
+ expand_string_forcedfail = TRUE;
+ }
+ goto EXPAND_FAILED;
+ }
+
+ /* Yield succeeded. Ensure forcedfail is unset, just in case it got
+ set during a callback from Perl. */
+
+ expand_string_forcedfail = FALSE;
+ yield = new_yield;
+ continue;
+ }
+#endif /* EXIM_XMLRPC */
+
/* Handle "readfile" to insert an entire file */
case EITEM_READFILE:
diff -Nur exim-4.10/src/functions.h exim-4.10xmlrpc/src/functions.h
--- exim-4.10/src/functions.h 2002-07-22 04:59:48.000000000 -0400
+++ exim-4.10xmlrpc/src/functions.h 2002-11-07 15:25:45.000000000 -0500
@@ -19,6 +19,13 @@
extern uschar *init_perl(uschar *);
#endif
+#ifdef EXIM_XMLRPC
+extern uschar *call_xmlrpc_cat(uschar *, int *, int *, uschar **, uschar *,
+ uschar **);
+extern void cleanup_xmlrpc(void);
+extern uschar *init_xmlrpc(uschar *);
+#endif
+
#ifdef SUPPORT_TLS
extern BOOL tls_client_start(int, host_item *, address_item *, uschar *,
diff -Nur exim-4.10/src/globals.c exim-4.10xmlrpc/src/globals.c
--- exim-4.10/src/globals.c 2002-07-22 04:59:48.000000000 -0400
+++ exim-4.10xmlrpc/src/globals.c 2002-11-12 15:04:31.000000000 -0500
@@ -58,6 +58,10 @@
BOOL opt_perl_started = FALSE;
#endif
+#ifdef EXIM_XMLRPC
+uschar *xmlrpc_servers = NULL;
+#endif
+
#ifdef LOOKUP_LDAP
uschar *ldap_default_servers = NULL;
#endif
@@ -317,7 +321,8 @@
{ US"tls", D_tls },
{ US"transport", D_transport },
{ US"uid", D_uid },
- { US"verify", D_verify }
+ { US"verify", D_verify },
+ { US"xmlrpc", D_xmlrpc }
};
int debug_options_count = sizeof(debug_options)/sizeof(bit_table);
pid_t debug_pid = 0;
diff -Nur exim-4.10/src/globals.h exim-4.10xmlrpc/src/globals.h
--- exim-4.10/src/globals.h 2002-07-22 04:59:49.000000000 -0400
+++ exim-4.10xmlrpc/src/globals.h 2002-11-07 13:37:47.000000000 -0500
@@ -23,6 +23,10 @@
extern BOOL opt_perl_started; /* Set once interpreter started */
#endif
+#ifdef EXIM_XMLRPC
+extern uschar *xmlrpc_servers; /* List of servers and connect info */
+#endif
+
#ifdef LOOKUP_LDAP
extern uschar *ldap_default_servers; /* List of default servers */
#endif
diff -Nur exim-4.10/src/macros.h exim-4.10xmlrpc/src/macros.h
--- exim-4.10/src/macros.h 2002-07-22 04:59:49.000000000 -0400
+++ exim-4.10xmlrpc/src/macros.h 2002-11-12 14:10:23.000000000 -0500
@@ -304,6 +304,7 @@
#define D_transport 0x01000000
#define D_uid 0x02000000
#define D_verify 0x04000000
+#define D_xmlrpc 0x08000000
#define D_all 0xffffffff
#define D_any 0xfffffffe /* Excludes D_v */
@@ -442,6 +443,8 @@
#define RDO_RUN 0x00002000 /* Forbid "run" in expansion in filter */
#define RDO_REALLOG 0x00004000 /* Really do log (not testing/verifying) */
#define RDO_REWRITE 0x00008000 /* Rewrite generated addresses */
+#define RDO_XMLRPC 0x00010000 /* Forbid "xmlrpc" in expansion in filter */
+
/* As well as the RDO bits themselves, we need the bit numbers in order to
access (most of) the individual bits as separate options. This could be
@@ -449,7 +452,7 @@
enum { RDON_BLACKHOLE, RDON_DEFER, RDON_EACCES, RDON_ENOTDIR, RDON_EXISTS,
RDON_FAIL, RDON_FILTER, RDON_FREEZE, RDON_INCLUDE, RDON_LOG, RDON_LOOKUP,
- RDON_PERL, RDON_READFILE, RDON_RUN, RDON_REALLOG, RDON_REWRITE };
+ RDON_PERL, RDON_READFILE, RDON_RUN, RDON_REALLOG, RDON_REWRITE, RDON_XMLRPC };
/* Results of filter or forward file processing. Some are only from a filter;
some are only from a forward file. */
diff -Nur exim-4.10/src/rda.c exim-4.10xmlrpc/src/rda.c
--- exim-4.10/src/rda.c 2002-07-22 04:59:50.000000000 -0400
+++ exim-4.10xmlrpc/src/rda.c 2002-11-12 20:14:23.000000000 -0500
@@ -349,8 +349,8 @@
DEBUG(D_route) debug_printf("data is a filter program\n");
expand_forbid =
- (expand_forbid & ~(RDO_EXISTS|RDO_LOOKUP|RDO_PERL|RDO_READFILE|RDO_RUN)) |
- (options & (RDO_EXISTS|RDO_LOOKUP|RDO_PERL|RDO_READFILE|RDO_RUN));
+ (expand_forbid & ~(RDO_EXISTS|RDO_LOOKUP|RDO_PERL|RDO_READFILE|RDO_RUN|RDO_XMLRPC)) |
+ (options & (RDO_EXISTS|RDO_LOOKUP|RDO_PERL|RDO_READFILE|RDO_RUN|RDO_XMLRPC));
frc = filter_interpret(data, options, generated, error);
expand_forbid = old_expand_forbid;
return frc;
diff -Nur exim-4.10/src/readconf.c exim-4.10xmlrpc/src/readconf.c
--- exim-4.10/src/readconf.c 2002-07-22 04:59:50.000000000 -0400
+++ exim-4.10xmlrpc/src/readconf.c 2002-11-07 13:36:26.000000000 -0500
@@ -210,7 +210,10 @@
{ "untrusted_set_sender", opt_stringptr, &untrusted_set_sender },
{ "uucp_from_pattern", opt_stringptr, &uucp_from_pattern },
{ "uucp_from_sender", opt_stringptr, &uucp_from_sender },
- { "warn_message_file", opt_stringptr, &warn_message_file }
+ { "warn_message_file", opt_stringptr, &warn_message_file },
+#ifdef EXIM_XMLRPC
+ { "xmlrpc_servers", opt_stringptr, &xmlrpc_servers },
+#endif
};
static int optionlist_config_size =
diff -Nur exim-4.10/src/xmlrpc.c exim-4.10xmlrpc/src/xmlrpc.c
--- exim-4.10/src/xmlrpc.c 1969-12-31 19:00:00.000000000 -0500
+++ exim-4.10xmlrpc/src/xmlrpc.c 2002-11-13 23:38:33.000000000 -0500
@@ -0,0 +1,150 @@
+/*************************************************
+ * Exim - an Internet mail transport agent *
+ *************************************************/
+
+/* Copyright (c) 2002 Infoteck Internet <webmaster@???> */
+/* Copyright (c) 2002 Joel Vandal <jvandal@???> */
+
+/* This xmlrpc add-on can be distributed under the same terms as Exim itself. */
+/* See the file NOTICE for conditions of use and distribution. */
+
+#include "exim.h"
+
+/* Include XMLRPC headers */
+
+#include <xmlrpc.h>
+#include <xmlrpc_client.h>
+
+#define XMLRPC_CLIENT_NAME "EXIM-XMLRPC"
+#define XMLRPC_CLIENT_VERSION "4.10"
+
+#define EXIM_TRUE TRUE
+#undef TRUE
+
+#define EXIM_FALSE FALSE
+#undef FALSE
+
+void xmlrpc_clean(xmlrpc_env *env);
+
+uschar * init_xmlrpc(uschar *xmlrpcservers)
+{
+ return 0;
+}
+
+uschar * call_xmlrpc_cat(uschar *yield, int *sizep, int *ptrp,
+ uschar **errstrp, uschar *name, uschar **arg)
+{
+ uschar *str;
+ uschar *res;
+ int len;
+
+ xmlrpc_env *env;
+ xmlrpc_value *result;
+ xmlrpc_value *list;
+ xmlrpc_value *item;
+
+ /* Start up our XML-RPC client library. */
+ xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, XMLRPC_CLIENT_NAME, XMLRPC_CLIENT_VERSION);
+
+ env=(xmlrpc_env *)malloc(sizeof(xmlrpc_env));
+ xmlrpc_env_init(env);
+
+ list = xmlrpc_build_value (env, "()");
+ if (check_xmlrpc_fault(env))
+ {
+ xmlrpc_clean(env);
+ return 0;
+ }
+
+ while (*arg != 0)
+ {
+ item=xmlrpc_build_value(env, "s",*arg++);
+ if(check_xmlrpc_fault(env))
+ {
+ xmlrpc_clean(env);
+ return 0;
+ }
+
+ xmlrpc_array_append_item(env, list, item);
+ xmlrpc_DECREF(item);
+ if(check_xmlrpc_fault(env))
+ {
+ xmlrpc_clean(env);
+ return 0;
+ }
+
+ }
+
+ /* Send the XMLRPC request (an array of string) to the server */
+ if((result = xmlrpc_client_call(env,xmlrpc_servers,name, "(V)", list))==0)
+ {
+ DEBUG(D_xmlrpc) debug_printf("Error occured while calling XMLRPC server\n");
+ xmlrpc_clean(env);
+ return 0;
+ }
+
+ if(check_xmlrpc_fault(env))
+ {
+ xmlrpc_clean(env);
+ return 0;
+ }
+
+ DEBUG(D_xmlrpc) debug_printf("called XMLRPC server\n");
+
+ if(result)
+ {
+ DEBUG(D_xmlrpc) debug_printf("XMLRPC returned result is OK\n");
+
+ /* The XMLRPC result is an array of string */
+ xmlrpc_parse_value(env, result, "(s#)", &res, &len) ;
+
+ if(check_xmlrpc_fault(env))
+ {
+ xmlrpc_clean(env);
+ return 0;
+ }
+
+ DEBUG(D_xmlrpc) debug_printf("XMLRPC check result passed... value: %s len: %d\n", res, len);
+
+ }
+ else
+ {
+ xmlrpc_clean(env);
+ return 0;
+ }
+
+ DEBUG(D_xmlrpc) debug_printf("Finished sending the query via XMLRPC\n");
+
+ yield = string_cat(yield, sizep, ptrp, res, (int)strlen(res));
+
+ /* Dispose of our result value. */
+ xmlrpc_DECREF(result);
+
+ /* Shutdown our XML-RPC client library. */
+ xmlrpc_clean(env);
+
+ return yield;
+
+}
+
+void xmlrpc_clean(xmlrpc_env *env)
+{
+ xmlrpc_env_clean(env);
+ /* Shutdown our XML-RPC client library. */
+ xmlrpc_client_cleanup();
+ free(env);
+}
+
+int check_xmlrpc_fault (xmlrpc_env *env)
+{
+ /* Check our error-handling environment for an XML-RPC fault. */
+ if (env->fault_occurred)
+ {
+ DEBUG(D_xmlrpc) debug_printf("XMLRPC Fault: %s (%d)", env->fault_string, env->fault_code);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* End of xmlrpc.c */
--