]> source.dussan.org Git - rspamd.git/commitdiff
* Add initial implementation of rspamd XS module
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Tue, 19 Aug 2008 15:46:10 +0000 (19:46 +0400)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Tue, 19 Aug 2008 15:46:10 +0000 (19:46 +0400)
Makefile.in
configure
main.h
perl/Makefile.PL.in [new file with mode: 0644]
perl/rspamd.pm [new file with mode: 0644]
perl/rspamd.xs [new file with mode: 0644]
perl/typemap [new file with mode: 0644]
worker.c

index aa9112e70907b24a9ed1ac9db6fabe6b43e0b2e7..65cd1a405ed1b641ec4d491acb4cc8db0944c033 100644 (file)
@@ -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!" 
index 1a822576dde4f649ef06c4408f566b79867ad064..776c15e1cf6976e2c7ae27a1c59ecd09a265e167 100755 (executable)
--- 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 e263b952198133a3ee1182acab7c3586fa0a96f4..b2441bbe704999e7422cdcab1f37a74b5d52267c 100644 (file)
--- 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 (file)
index 0000000..9b436f1
--- /dev/null
@@ -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 (file)
index 0000000..99e0e49
--- /dev/null
@@ -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 (file)
index 0000000..ada7a59
--- /dev/null
@@ -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 (file)
index 0000000..17a1b16
--- /dev/null
@@ -0,0 +1,3 @@
+TYPEMAP
+
+rspamd   T_PTROBJ
index ab02ecea2e9d6071f75e81c8e92cae1e91907339..0b3dd30bc24e39800c2fe0338fa8f24761e846b8 100644 (file)
--- 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);