aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.in7
-rwxr-xr-xconfigure20
-rw-r--r--main.h13
-rw-r--r--perl/Makefile.PL.in9
-rw-r--r--perl/rspamd.pm30
-rw-r--r--perl/rspamd.xs100
-rw-r--r--perl/typemap3
-rw-r--r--worker.c21
8 files changed, 197 insertions, 6 deletions
diff --git a/Makefile.in b/Makefile.in
index aa9112e70..65cd1a405 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,5 +1,8 @@
-all: $(TARGETS)
+all: perl $(TARGETS)
+
+perl:
+ cd perl && make && cd ..
memctest: upstream.c memcached.c memcached-test.c
$(CC) $(OPT_FLAGS) $(CFLAGS) $(PTHREAD_CFLAGS) -c upstream.c
@@ -17,11 +20,13 @@ install: $(EXEC)
clean:
rm -f *.o $(EXEC) *.core
rm -f cfg_lex.c cfg_yacc.c cfg_yacc.h
+ cd perl && make clean && cd ..
dist-clean: clean
rm -f Makefile
rm -f config.log
rm -f md5.h md5.c strlcpy.h strlcpy.c queue.h config.h modules.c
+ cd perl && rm -f Makefile.old && rm -f Makefile.PL && cd ..
creategroup:
@echo "Create group $(RSPAMD_GROUP) before installing!"
diff --git a/configure b/configure
index 1a822576d..776c15e1c 100755
--- a/configure
+++ b/configure
@@ -40,6 +40,9 @@ MANPATH="${PREFIX}/share/man"
MAKEFILE="Makefile"
MAKEFILE_IN="Makefile.in"
+PERL_MAKEFILE="perl/Makefile.PL.in"
+PERLCFLAGS=""
+PERLLDFLAGS=""
TARGETS="${EXEC}"
@@ -339,8 +342,6 @@ check_perl()
$GCC $CFLAGS $PERLCFLAGS $PTHREAD_CFLAGS -o autotest $LDFLAGS $LIBS $PERLLDFLAGS $PTHREAD_LDFLAGS autotest.c >>config.log 2>&1
if [ $? -eq 0 ] ; then
echo "found"
- LIBS="$LIBS $PERLLDFLAGS"
- CFLAGS="$CFLAGS $PERLCFLAGS"
cleanup
echo "-> OK" >> config.log
return 0
@@ -424,9 +425,21 @@ write_result()
echo "#define MODULES_NUM $modules_num" >> $CONFIG
SOURCES="$SOURCES modules.c"
OBJECTS=`echo $SOURCES | sed -e 's/\.c/\.o/g'`
+ # Write to perl Makefile
+ sed -e "s|%%libs%%|${LDFLAGS} ${LIBS}|" < $PERL_MAKEFILE > .pl_tmp
+ sed -e "s|%%include%%|${CFLAGS}|" < .pl_tmp > .pl2_tmp
+ PERL_MAKEFILE=`echo ${PERL_MAKEFILE} | sed -e 's|.in$||'`
+ mv .pl2_tmp $PERL_MAKEFILE
+ rm -f .pl_tmp .pl2_tmp
+ CURDIR=`pwd`
+ cd `dirname ${PERL_MAKEFILE}`
+ $PERL Makefile.PL
+ cd $CURDIR
# Make CFLAGS more readable
+ CFLAGS="$CFLAGS $PERLCFLAGS"
+ LIBS="$LIBS $PERLLDFLAGS"
CFLAGS=`echo $CFLAGS | tr [:space:] \\\n | sed -e 's/$/ \\\/' | sed -e '$,$s/\\\//' | sort -r -k2 | uniq`
- LDFLAGS=`echo $LDLAGS | tr [:space:] \\\n | sed -e 's/$/ \\\/' | sed -e '$,$s/\\\//' | sort -r -k2 | uniq`
+ LDFLAGS=`echo $LDFLAGS | tr [:space:] \\\n | sed -e 's/$/ \\\/' | sed -e '$,$s/\\\//' | sort -r -k2 | uniq`
LIBS=`echo $LIBS | tr [:space:] \\\n | sed -e 's/$/ \\\/' | sed -e '$,$s/\\\//' | sort -r -k2 | uniq`
cat > $MAKEFILE << END
# This is ${EXEC} Makefile
@@ -497,7 +510,6 @@ ${LEX_OUTPUT}: cfg_file.h ${LEX_SRC} ${YACC_OUTPUT}
${YACC_OUTPUT}: cfg_file.h ${YACC_SRC}
\$(YACC) -d -o ${YACC_OUTPUT} ${YACC_SRC}
END
-
}
diff --git a/main.h b/main.h
index e263b9521..b2441bbe7 100644
--- a/main.h
+++ b/main.h
@@ -22,6 +22,9 @@
#include "fstring.h"
#include "url.h"
+#include <glib.h>
+#include <gmime/gmime.h>
+
/* Default values */
#define FIXED_CONFIG_FILE "./rspamd.conf"
/* Time in seconds to exit for old worker */
@@ -74,6 +77,12 @@ struct filter_result {
TAILQ_ENTRY (filter_result) next;
};
+struct mime_part {
+ GMimeContentType *type;
+ GByteArray *content;
+ TAILQ_ENTRY (mime_part) next;
+};
+
struct worker_task {
struct rspamd_worker *worker;
enum {
@@ -93,6 +102,10 @@ struct worker_task {
struct bufferevent *bev;
/* Number of mime parts */
int parts_count;
+ /* Headers */
+ GMimeMessage *message;
+ /* All parts of message */
+ TAILQ_HEAD (mime_partq, mime_part) parts;
/* URLs extracted from message */
TAILQ_HEAD (uriq, uri) urls;
/* List of filter results */
diff --git a/perl/Makefile.PL.in b/perl/Makefile.PL.in
new file mode 100644
index 000000000..9b436f12f
--- /dev/null
+++ b/perl/Makefile.PL.in
@@ -0,0 +1,9 @@
+use ExtUtils::MakeMaker;
+WriteMakefile(
+ NAME => 'rspamd',
+ VERSION_FROM => 'rspamd.pm', # finds $VERSION
+ LIBS => ['%%libs%%'], # e.g., '-lm'
+ DEFINE => '',
+ INC => '%%include%%',
+);
+
diff --git a/perl/rspamd.pm b/perl/rspamd.pm
new file mode 100644
index 000000000..99e0e4908
--- /dev/null
+++ b/perl/rspamd.pm
@@ -0,0 +1,30 @@
+package rspamd;
+
+use 5.006001;
+use strict;
+use warnings;
+
+require Exporter;
+
+our @ISA = qw(Exporter);
+
+our $VERSION = '0.0.1';
+
+require XSLoader;
+XSLoader::load('rspamd', $VERSION);
+1;
+__END__
+
+=head1 NAME
+
+rspamd - Perl interface to the rspamd API
+
+=head1 SYNOPSIS
+
+ use rpspamd;
+
+=head1 DESCRIPTION
+
+TODO: Not ready yet
+
+=cut
diff --git a/perl/rspamd.xs b/perl/rspamd.xs
new file mode 100644
index 000000000..ada7a5997
--- /dev/null
+++ b/perl/rspamd.xs
@@ -0,0 +1,100 @@
+/*
+ * Perl XS module for interacting with rspamd
+ *
+ * vi:ts=4
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include "../config.h"
+#include "../main.h"
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#define perl_set_session(r) \
+ r = INT2PTR(struct worker_task *, SvIV((SV *) SvRV(ST(0))))
+
+#define perl_set_targ(p, len) \
+ SvUPGRADE(TARG, SVt_PV); \
+ SvPOK_on(TARG); \
+ sv_setpvn(TARG, (char *) p, len)
+
+MODULE = rspamd PACKAGE = rspamd
+PROTOTYPES: DISABLE
+
+void
+get_header (r, header)
+ CODE:
+ dXSTARG;
+ struct worker_task *r;
+ SV *header;
+ char *s;
+ STRLEN len;
+
+ perl_set_session(r);
+
+ header = ST(1);
+ if (SvROK (header) && SvTYPE (SvRV (header)) == SVt_PV) {
+ header = SvRV (header);
+ }
+
+ s = (char *) SvPV (header, len);
+
+ if ((s = (char *)g_mime_message_get_header (r->message, s)) == NULL) {
+ XSRETURN_UNDEF;
+ }
+ else {
+ ngx_http_perl_set_targ (s, strlen (s));
+ ST(0) = TARG;
+ }
+
+void
+get_part_num (r)
+ CODE:
+ dXSTARG;
+ struct worker_task *r;
+
+ perl_set_session (r);
+ sv_upgrade(TARG, SVt_IV);
+ sv_setiv(TARG, r->parts_count);
+
+ ST(0) = TARG;
+
+
+HV *
+get_part (r, num)
+ CODE:
+ struct worker_task *r;
+ SV *num;
+ int number;
+ struct mime_part *part;
+ char *type;
+
+ perl_set_session (r);
+ num = ST(1);
+
+ number = (int) SvIV (num);
+ if (number < 0 || number > r->parts_count - 1) {
+ XSRETURN_UNDEF;
+ }
+
+ TAILQ_FOREACH (part, &r->parts, next) {
+ if (--number == 0) {
+ break;
+ }
+ }
+ RETVAL = newHV();
+ type = g_mime_content_type_to_string (part->type);
+
+ hv_store_ent (RETVAL,
+ newSVpv ("type", sizeof ("type") - 1),
+ newSVpv (type, strlen(type)), 0);
+ hv_store_ent (RETVAL,
+ newSVpv ("content", sizeof ("content") - 1),
+ newSVpv ((char *)part->content->data, part->content->len), 0);
+ sv_2mortal((SV*)RETVAL);
+ OUTPUT:
+ RETVAL
+
diff --git a/perl/typemap b/perl/typemap
new file mode 100644
index 000000000..17a1b16eb
--- /dev/null
+++ b/perl/typemap
@@ -0,0 +1,3 @@
+TYPEMAP
+
+rspamd T_PTROBJ
diff --git a/worker.c b/worker.c
index ab02ecea2..0b3dd30bc 100644
--- a/worker.c
+++ b/worker.c
@@ -73,12 +73,16 @@ free_task (struct worker_task *task)
{
struct uri *cur;
struct filter_result *res;
+ struct mime_part *part;
if (task) {
if (task->msg) {
fstrfree (task->msg->buf);
free (task->msg);
}
+ if (task->message) {
+ g_object_unref (task->message);
+ }
if (task->helo) {
free (task->helo);
}
@@ -90,15 +94,22 @@ free_task (struct worker_task *task)
}
while (!TAILQ_EMPTY (&task->urls)) {
cur = TAILQ_FIRST (&task->urls);
+ TAILQ_REMOVE (&task->urls, cur, next);
free (cur->string);
free (cur);
- TAILQ_REMOVE (&task->urls, cur, next);
}
while (!TAILQ_EMPTY (&task->results)) {
res = TAILQ_FIRST (&task->results);
free (res);
TAILQ_REMOVE (&task->results, res, next);
}
+ while (!TAILQ_EMPTY (&task->parts)) {
+ part = TAILQ_FIRST (&task->parts);
+ g_object_unref (part->type);
+ g_object_unref (part->content);
+ TAILQ_REMOVE (&task->parts, part, next);
+ free (part);
+ }
free (task);
}
}
@@ -107,6 +118,7 @@ static void
mime_foreach_callback (GMimeObject *part, gpointer user_data)
{
struct worker_task *task = (struct worker_task *)user_data;
+ struct mime_part *mime_part;
const GMimeContentType *type;
GMimeDataWrapper *wrapper;
GMimeStream *part_stream;
@@ -150,6 +162,10 @@ mime_foreach_callback (GMimeObject *part, gpointer user_data)
if (g_mime_data_wrapper_write_to_stream (wrapper, part_stream) != -1) {
part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (part_stream));
type = g_mime_part_get_content_type (GMIME_PART (part));
+ mime_part = g_malloc (sizeof (struct mime_part));
+ mime_part->type = type;
+ mime_part->content = part_content;
+ TAILQ_INSERT_TAIL (&task->parts, mime_part, next);
if (g_mime_content_type_is_type (type, "text", "html")) {
url_parse_html (task, part_content);
}
@@ -182,6 +198,8 @@ process_message (struct worker_task *task)
/* parse the message from the stream */
message = g_mime_parser_construct_message (parser);
+
+ task->message = message;
/* free the parser (and the stream) */
g_object_unref (parser);
@@ -385,6 +403,7 @@ accept_socket (int fd, short what, void *arg)
new_task->parts_count = 0;
TAILQ_INIT (&new_task->urls);
TAILQ_INIT (&new_task->results);
+ TAILQ_INIT (&new_task->parts);
/* Read event */
new_task->bev = bufferevent_new (nfd, read_socket, write_socket, err_socket, (void *)new_task);