summaryrefslogtreecommitdiffstats
path: root/perl
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rambler-co.ru>2009-02-26 18:09:28 +0300
committerVsevolod Stakhov <vsevolod@rambler-co.ru>2009-02-26 18:09:28 +0300
commitcfb5348f75790ef694edd5a9c131890eeceec204 (patch)
tree55c6bc5ff03a346ced6008dcae0a70ba6b36fb32 /perl
parent5d77f4552b6e39ab1072d2c91b219dac2498ac88 (diff)
downloadrspamd-cfb5348f75790ef694edd5a9c131890eeceec204.tar.gz
rspamd-cfb5348f75790ef694edd5a9c131890eeceec204.zip
* Completely rewrite and reorganize perl API
* Add documentation for Mail::Rspamd * Add install targets to cmake --HG-- rename : perl/rspamd.pm => perl/Rspamd.pm rename : perl/rspamd.xs => perl/Rspamd.xs
Diffstat (limited to 'perl')
-rw-r--r--perl/Makefile.PL.in16
-rw-r--r--perl/Rspamd.pm (renamed from perl/rspamd.pm)4
-rw-r--r--perl/Rspamd.pod562
-rw-r--r--perl/Rspamd.xs324
-rw-r--r--perl/Rspamd/Config.xs141
-rw-r--r--perl/Rspamd/ContentType.xs87
-rw-r--r--perl/Rspamd/Hash.xs258
-rw-r--r--perl/Rspamd/InternetAddress.xs124
-rw-r--r--perl/Rspamd/Message.xs264
-rw-r--r--perl/Rspamd/Object.xs152
-rw-r--r--perl/Rspamd/Part.xs160
-rw-r--r--perl/Rspamd/Task.xs83
-rw-r--r--perl/rspamd.xs501
-rw-r--r--perl/typemap27
14 files changed, 2196 insertions, 507 deletions
diff --git a/perl/Makefile.PL.in b/perl/Makefile.PL.in
index 502e84227..0d70d4270 100644
--- a/perl/Makefile.PL.in
+++ b/perl/Makefile.PL.in
@@ -1,9 +1,21 @@
use ExtUtils::MakeMaker;
WriteMakefile(
- NAME => 'rspamd',
- VERSION_FROM => 'rspamd.pm', # finds $VERSION
+ NAME => 'Mail::Rspamd',
+ AUTHOR => 'Vsevolod Stakhov <vsevolod@rambler-co.ru>',
+ XS => { 'Rspamd.xs' => 'Rspamd.c' },
+ VERSION_FROM => 'Rspamd.pm', # finds $VERSION
LIBS => ['${GLIB_LDFLAGS} ${GMIME_LDFLAGS} -levent'], # e.g., '-lm'
DEFINE => '',
INC => '${GLIB_CFLAGS} ${GMIME_CFLAGS}',
+ PM => { 'Rspamd.pod' => '$(INST_LIBDIR)/Rspamd.pod',
+ 'Rspamd.pm' => '$(INST_LIBDIR)/Rspamd.pm'},
+ depend => {
+ 'Rspamd.so' => 'Rspamd.o',
+ 'Rspamd.o' => 'Rspamd.c',
+ 'Rspamd.c' => qw{
+Rspamd/ContentType.xs Rspamd/Part.xs Rspamd/Hash.xs
+Rspamd/InternetAddress.xs Rspamd/Message.xs Rspamd/Object.xs
+},
+ },
);
diff --git a/perl/rspamd.pm b/perl/Rspamd.pm
index 6048f1a3f..2966cb3ca 100644
--- a/perl/rspamd.pm
+++ b/perl/Rspamd.pm
@@ -1,4 +1,4 @@
-package rspamd;
+package Mail::Rspamd;
use 5.006001;
use strict;
@@ -20,7 +20,7 @@ our @EXPORT = qw(
our $VERSION = '0.0.1';
require XSLoader;
-XSLoader::load('rspamd', $VERSION);
+XSLoader::load('Rspamd', $VERSION);
sub module_init {
my ($cfg) = @_;
diff --git a/perl/Rspamd.pod b/perl/Rspamd.pod
new file mode 100644
index 000000000..d40574820
--- /dev/null
+++ b/perl/Rspamd.pod
@@ -0,0 +1,562 @@
+=head1 NAME
+
+Mail::Rspamd - Interface for accessing rspamd internals
+
+=head1 SYNOPSIS
+
+ use Mail::Rspamd;
+
+ sub mime_filter {
+ my ($task) = @_;
+ my $msg = $task->get_message();
+ $msg->set_subject ( 'Re: ' . $msg->get_subject () );
+ if ($msg->get_mime_part->get_content_type->to_string =~ /text/) {
+ # Do something
+ }
+ my %header;
+ tie %header, 'Mail::Rspamd::Hash::Header', $msg;
+
+ $header{'From'} = 'John Doe <john@domain>';
+ $header{'X-Info'} = 'Normal one arbitrary header';
+ $header{'X-Info'} = ['This is','Multiline X-Info header'];
+
+ my $old_header = $header{'X-Info'};
+ $header{'X-Info'} = [ 'First header', @{$old_header}, 'Last header'];
+ }
+
+
+=head1 DESCRIPTION
+
+Mail::Rspamd is a perl module for accessing internal structures of rspamd, such as
+task, message, config, logger e.t.c. Module is based on ideas from MIME::Fast.
+
+=head1 INHERITANCE
+
+This is a reformatted snipped from the official GMime documentation:
+
+ Not a real objects:
+
+ Mail::Rspamd::ContentType
+ Mail::Rspamd::Disposition
+ Mail::Rspamd::Header
+ Mail::Rspamd::Param
+ Mail::Rspamd::Hash::Header (only in perl module)
+
+ Glib objects:
+
+ Mail::Rspamd::Object
+ Mail::Rspamd::Message
+ Mail::Rspamd::Part
+ InternetAddress
+
+=head1 PUBLIC CLASSES
+
+=head2 Mail::Rspamd::Message
+
+=over 4
+
+=item I<new>()
+
+=item I<new>(pretty_headers)
+
+Class method. Create a new Mail::Rspamd::Message object.
+Such object have no headers or any mime parts.
+If you need to parse any message data use construct_message()
+method from the Mail::Rspamd::Parser submodule.
+Optional parameter I<pretty_headers> (default 0) if set to 1,
+initializes friendly order of the header items.
+The object is destroyed during the perl garbage collection.
+E.g.:
+
+ my $msg = new Mail::Rspamd::Message;
+
+=item I<set_sender>(address)
+
+=item I<get_sender>()
+
+Set and get the sender's name and address on the Mail::Rspamd::Message object.
+E.g.
+
+ $msg->set_sender("\"Joe Sixpack\" <joe\@sixpack.org>");
+ $sender = $msg->get_sender;
+
+=item I<set_reply_to>(address)
+
+=item I<get_reply_to>(address)
+
+Set and get the sender's Reply-To address of the MIME message.
+
+=item I<add_recipient>(type, name, email)
+
+Add a recipient of a chosen type to the MIME Message.
+Available recipient types include: GMIME_RECIPIENT_TYPE_TO,
+GMIME_RECIPIENT_TYPE_CC and GMIME_RECIPIENT_TYPE_BCC.
+
+=item I<add_recipients_from_string>(type, string)
+
+Add recipients of a chosen type to the MIME Message.
+E.g.:
+
+ $msg->add_recipients_from_string(GMIME_RECIPIENT_TYPE_TO,
+ "\"Mickey Mouse\" <mickey\@example>," .
+ "\"John Doe\" <john\@home>");
+
+=item I<get_recipients>(type)
+
+Returns a list of recipients of a chosen type from the MIME Message.
+The I<type> parameter is the same as in the add_recipient() method.
+
+=item I<set_subject>(subject)
+
+=item I<get_subject>()
+
+Set and get the subject of the MIME message.
+
+=item I<set_date>(date, gmt_offset)
+
+=item I<set_date_from_string>(str)
+
+Set the sent-date on the MIME message. You can give a date string
+or the numbers (time in seconds and offset in hours and minutes).
+E.g.
+
+ $msg->set_date(991697409, '+0100');
+ $msg->set_date("Wed, 7 Mar 2001 03:00:01 +0100 (CET)");
+
+=item I<get_date>()
+
+Get the sent-date of the MIME message. In scalar
+context returns date as a string value,
+otherwise two element array - time in seconds and gmt_offset.
+
+=item I<set_message_id>(message_id)
+
+=item I<get_message_id>()
+
+Set and get the Message-Id of the message.
+
+=item I<set_header>(field, value)
+
+Set a message header to the MIME Message. This can be
+such headers as X-Mailer, X-Priority, or In-Reply-To
+as well as From etc. If you want to delete
+any header - use remove_header() method.
+
+=item I<add_header>(field, value)
+
+Add a header to the message header.
+
+=item I<remove_header>(field)
+
+Removes the given field from the message header.
+
+=item I<get_header>(field)
+
+Get the header from the MIME message. This is the only (besides the
+tied header hash) way you can retrieve any arbitrary header
+(as X-Mailer etc.). Other headers can be accessed also with e.g.
+get_sender (From header), get_content_type (Mail::Rspamd::Part method), etc.
+
+=item I<set_mime_part>(mime_part)
+
+=item I<get_mime_part>()
+
+Set and get the root-level MIME part of the message.
+Parameter mime_part should be valid Mail::Rspamd::Object object.
+
+B<NOTE>: get_mime_part() does not exists in C gmime library.
+
+=item I<get_body>(want_plain = 1, is_html = 0)
+
+Returns the body of the message. Parameters are optional.
+If want_plain is 1 (default) plain text is returned.
+If HTML is in the return string, is_html is set to 1.
+Binary parts are omitted.
+
+=item I<get_headers>()
+
+Returns an allocated string containing the raw message headers.
+
+=item I<foreach_part>(function, data)
+
+Calls callback on each of the mime parts in the mime message.
+Parameters: function is the reference to the callback function,
+and data is a scalar (or any reference) that would be passed
+to each callback function call.
+E.g.:
+
+ $msg->foreach_part(\&parse,$data);
+
+=back
+
+=head2 Mail::Rspamd::Header
+
+=over 4
+
+=item *
+
+Mail::Rspamd::Header is a private structure. This structure contains
+all the headers except special ones (Content-* MIME-Version).
+Look for L<Header tied hash> for easy maintaining for header.
+Use also the Mail::Rspamd::Message::get_header() and set_header() methods.
+
+=back
+
+=head2 Mail::Rspamd::Part
+
+=over 4
+
+=item I<new> ()
+
+=item I<new> (type = "text", subtype = "plain")
+
+Class method. Create a new Mail::Rspamd::Part object (MIME part).
+It supports a few special headers (Content-* and MIME-Version),
+and has contents of specified type.
+If you do not issue any parameter to the new function,
+"text/plain" would be the default type for the new Mail::Rspamd::Part object.
+
+
+=item I<set_content_header> ($header)
+
+=item I<get_content_header> ()
+
+Sets or gets an arbitrary MIME content header.
+
+=item I<set_content_description> (description)
+
+=item I<get_content_description> ()
+
+Set and get content description (Content-Description) on the MIME part.
+
+=item I<set_content_md5> (content_md5)
+
+=item I<verify_content_md5> ()
+
+=item I<get_content_md5> ()
+
+Set, get and verify content MD5 hash (Content-MD5) on the MIME part contents.
+
+=item I<set_content_location> (location)
+
+=item I<get_content_location> ()
+
+Set and get content location (Content-Location) on the MIME part.
+
+=item I<set_encoding> (encoding)
+
+=item I<encoding_from_string> (encoding_string)
+
+=item I<get_encoding> ()
+
+=item I<encoding_to_string> ()
+
+Set and get encoding on the MIME part. Encoding could be one of these
+constants (or strings):
+
+ GMIME_PART_ENCODING_DEFAULT # string '8 bit'
+ GMIME_PART_ENCODING_7BIT # string '7 bit'
+ GMIME_PART_ENCODING_8BIT # '8 bit'
+ GMIME_PART_ENCODING_BASE64 # 'base64'
+ GMIME_PART_ENCODING_QUOTEDPRINTABLE # 'quoted-printable'
+
+E.g.
+ Mail::Rspamd::Part::encoding_to_string("GMIME_PART_ENCODING_BASE64");
+
+=item I<set_content_disposition> (disposition)
+
+=item I<set_content_disposition_object> (Mail::Rspamd::Disposition)
+
+=item I<get_content_disposition> ()
+
+=item I<get_content_disposition> ()
+
+Set and get content disposition (Content-Disposition) on the MIME part.
+As the parameter one can issue usualy 'inline' or 'attachment'.
+Function get_content_disposition() returns only the main part of this
+header (no parameters).
+
+=item I<add_content_disposition_parameter> (name, value)
+
+=item I<get_content_disposition_parameter> (name)
+
+Add and get content disposition parameter.
+
+=item I<set_filename> (filename)
+
+Add the 'filename' content disposition parameter to the Content-Disposition
+header, and 'name' parameter to the Content-Type header.
+
+=item I<get_filename> ()
+
+Get filename suggested by the MIME part headers (either from the
+Content-Disposition or Content-Type header).
+
+=item I<set_content> (content_object)
+
+Set content of the MIME part based on the supplied argument (text
+Mail::Rspamd::Stream object, Mail::Rspamd::DataWrapper object
+or FILEHANDLE).
+
+=item I<get_content> ()
+
+Get text content of the MIME part (readonly).
+
+=item I<get_content_object> ()
+
+Get Mail::Rspamd::DataWrapper object of the MIME part.
+
+=item I<set_pre_encoded_content> (content, encoding)
+
+Set pre-encoded content on the MIME part. The 'encoding'
+parameter can have values described in encoding_to_string() function above.
+These function are used by the parser. You can write your own.
+
+=back
+
+=head2 Mail::Rspamd::Object
+
+This is the base class for Mail::Rspamd objects (messages,
+parts, multiparts, filters, streams etc.).
+
+=over 4
+
+=item I<set_content_type> ($type)
+
+=item I<get_content_type> ()
+
+Set and get content type on the Mail::Rspamd::Object. The 'type' parameter
+should be a Mail::Rspamd::ContentType object.
+E.g.
+
+ $type = $part->get_content_type;
+ print "Type of $part is " . $type->to_string;
+
+=item I<set_content_type_parameter> ($name, $value)
+
+=item I<get_content_type_parameter> ($name)
+
+Sets or gets the value of the content-type param $name set on the MIME part object.
+
+=item I<set_content_id> (content_id)
+
+=item I<get_content_id> ()
+
+Set and get content id (Content-Id) on the MIME part object.
+
+=item I<set_header>(field, value)
+
+Set a message header to the MIME object.
+
+=item I<add_header>(field, value)
+
+Add a header field to the MIME object header.
+
+=item I<remove_header>(field)
+
+Removes the given field from the header.
+
+=item I<get_header>(field)
+
+Gets the value of the requested header.
+
+=item I<get_content_length> ()
+
+Get content length of the MIME object.
+
+B<NOTE>: This methoid does not exists in the C gmime.
+
+B<NOTE>: Encoded content length is only prediction, not the exact number of bytes
+you would get after final encoding. Predicted encoded length is
+greater or equal to size of the encoded parts, though. The length
+of the part/message headers is not counted.
+
+=item I<is_multipart> ()
+
+Returns 1 if the MIME object is of type multipart, 0 otherwise.
+
+B<NOTE>: This methoid does not exists in the C gmime.
+
+=item I<effective_type> ()
+
+Returns content type of the given object as a lowercase text string.
+
+B<NOTE>: This methoid does not exists in the C gmime.
+
+=item I<to_string>()
+
+Returns the contents of the MIME object as a string.
+
+=back
+
+=head2 Mail::Rspamd::ContentType
+
+=over 4
+
+=item I<new> (type, subtype)
+
+=item I<new> (str)
+
+Create new Mail::Rspamd::ContentType object with type of 'type/subtype'
+or type read from the string 'str'.
+
+=item I<type> ()
+
+Get the 'type' part (string) of the Mail::Rspamd::ContentType object.
+B<NOTE>: this method is not in gmime C library.
+
+=item I<subtype> ()
+
+Get the 'subtype' part (string) of the Mail::Rspamd::ContentType object.
+B<NOTE>: this method is not in gmime C library.
+
+=item I<to_string> ()
+
+Get the string representation for the Mail::Rspamd::ContentType object.
+
+=item I<is_type> (type, subtype)
+
+Returns 1 if content type match the given type and subtype, 0 otherwise.
+You can use '*' in place of type or subtype as a wildcard.
+This function is case insensitive.
+E.g.
+
+ $is_multipart = $content_type->is_type('multipart','*');
+ $is_text = $content_type->is_type('text','*');
+
+=item I<add_parameter> (attribute, value)
+
+=item I<get_parameter> ()
+
+Add and get parameter to/of the content type header.
+E.g.
+
+ $content_type->add_parameter('name', 'test.gif');
+
+=back
+
+=head2 Mail::Rspamd::Task
+
+This is the base class for Mail::Rspamd objects (messages,
+parts, multiparts, filters, streams etc.).
+
+=over 4
+
+=item I<get_message> ()
+
+=item I<set_message> (message)
+
+Get and set Mail::Rspamd::Message object from task.
+
+=item I<ip> ()
+
+Get ip address of client.
+
+=item I<from> ()
+
+Get MAIL FROM address.
+
+=item I<save_point> ()
+
+Set save point to task for delayed filter's processing.
+
+=item I<recall_filter> ()
+
+Restore filter's processing
+
+=item I<insert_result> (metric, symbol, flag)
+
+Insert to task result to metric <metric>, that have symbol <symbol> and value <flag>.
+
+=item I<get_conf> ()
+
+Return Mail::Rspamd::Config object.
+
+=item I<get_urls> ()
+
+Return message's urls as array of strings.
+
+=back
+
+=head2 Mail::Rspamd::Config
+
+Object that allows access to rspamd config (read and write).
+
+=over 4
+
+=item I<get_scalar> (scalar)
+
+=item I<set_scalar> (scalar, value)
+
+Gets and sets specified parameter in config.
+
+=item I<get_metric> (metric)
+
+Returns hash of parameters of specified metric:
+{
+'name' => name of metric
+'func_name' => consolidation function
+'required_score' => score for metric
+}
+
+=item I<get_statfile> (statfile)
+
+Returns parameters of specified statfile:
+{
+'alias' => alias of statfile
+'pattern' => fs pattern
+'metric' => metric of statfile
+'weight' => weigth of statfile
+'size' => size of statfile
+}
+
+=item I<get_module_param> (modulename, paramname)
+
+Return parameter's value for specified module.
+
+=back
+
+=head1 CONSTANT VARIABLES
+
+ GMIME_LENGTH_ENCODED
+ GMIME_LENGTH_CUMULATIVE
+
+ GMIME_PART_ENCODING_DEFAULT
+ GMIME_PART_ENCODING_7BIT
+ GMIME_PART_ENCODING_8BIT
+ GMIME_PART_ENCODING_BASE64
+ GMIME_PART_ENCODING_QUOTEDPRINTABLE
+ GMIME_PART_NUM_ENCODINGS
+
+ GMIME_RECIPIENT_TYPE_TO
+ GMIME_RECIPIENT_TYPE_CC
+ GMIME_RECIPIENT_TYPE_BCC
+
+ INTERNET_ADDRESS_NONE
+ INTERNET_ADDRESS_NAME
+ INTERNET_ADDRESS_GROUP
+
+=head1 REQUIREMENTS
+
+This module Mail::Rspamd requires perl 5.8.x and gmime 2.0.9 or higher.
+
+
+=head1 BUGS
+
+Quoted-printable binary parts could be wrongly decoded (when
+the new line is "\n" instead of "\r\n", and there is no equal sign
+at the end of line. RFC says that binary parts should be encoded with
+BASE64 not Q-P (it is also best compression for such parts).
+Then there is no harm.
+
+=head1 AUTHOR
+
+Piotr Klaban, post@klaban.torun.pl (original author of MIME::Fast)
+Vsevolod Stakhov, vsevolod@highsecure.ru
+
+=head1 SEE ALSO
+
+perl(1).
+
+The homepage of gmime C library at http://spruce.sourceforge.net/gmime/
+The homepage of MIME::Fast perl module is available at http://search.cpan.org/dist/MIME-Fast/
diff --git a/perl/Rspamd.xs b/perl/Rspamd.xs
new file mode 100644
index 000000000..c6c33c007
--- /dev/null
+++ b/perl/Rspamd.xs
@@ -0,0 +1,324 @@
+/*
+ * Perl XS module for interacting with rspamd
+ *
+ * vi:ts=4
+ */
+
+#include "../src/config.h"
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+
+#include "../src/main.h"
+#include "../src/message.h"
+#include "../src/cfg_file.h"
+#include "../src/perl.h"
+#include "../src/mem_pool.h"
+
+#define XSINTERFACE_FUNC_RSPAMD_MESSAGE_SET(cv,f) \
+ CvXSUBANY(cv).any_dptr = (void (*) (pTHX_ void*))(CAT2( g_mime_message_,f ))
+#define XSINTERFACE_FUNC_RSPAMD_PART_SET(cv,f) \
+ CvXSUBANY(cv).any_dptr = (void (*) (pTHX_ void*))(CAT2( g_mime_part_,f ))
+#define XSINTERFACE_FUNC_RSPAMD_IA_SET(cv,f) \
+ CvXSUBANY(cv).any_dptr = (void (*) (pTHX_ void*))(CAT2( internet_address_,f ))
+
+struct raw_header {
+ struct raw_header *next;
+ char *name;
+ char *value;
+};
+
+typedef struct _GMimeHeader {
+ GHashTable *hash;
+ GHashTable *writers;
+ struct raw_header *headers;
+} local_GMimeHeader;
+
+/* enums */
+typedef GMimePartEncodingType Mail__Rspamd__PartEncodingType;
+typedef InternetAddressType Mail__Rspamd__InternetAddressType;
+
+/* C types */
+typedef GMimeObject * Mail__Rspamd__Object;
+typedef GMimeParam * Mail__Rspamd__Param;
+typedef GMimePart * Mail__Rspamd__Part;
+typedef GMimeParser * Mail__Rspamd__Parser;
+typedef GMimeMultipart * Mail__Rspamd__MultiPart;
+typedef GMimeMessage * Mail__Rspamd__Message;
+typedef GMimeMessagePart * Mail__Rspamd__MessagePart;
+typedef GMimeMessagePartial * Mail__Rspamd__MessagePartial;
+typedef InternetAddress * Mail__Rspamd__InternetAddress;
+typedef GMimeDisposition * Mail__Rspamd__Disposition;
+typedef GMimeContentType * Mail__Rspamd__ContentType;
+typedef GMimeCharset * Mail__Rspamd__Charset;
+
+/*
+ * Declarations for message header hash array
+ */
+
+static gboolean
+recipients_destroy (gpointer key, gpointer value, gpointer user_data)
+{
+ InternetAddressList *recipients = value;
+ internet_address_list_destroy (recipients);
+
+ return TRUE;
+}
+
+typedef struct {
+ int keyindex; /* key index for firstkey */
+ char *fetchvalue; /* value for each() method fetched with FETCH */
+ Mail__Rspamd__Message objptr; /* any object pointer */
+} hash_header;
+
+typedef hash_header *Mail__Rspamd__Hash__Header;
+
+
+/*
+ * Double linked list of perl allocated pointers (for DESTROY xsubs)
+ */
+static GList *plist = NULL;
+
+/*
+ * Calling callback function for each mime part
+ */
+struct _user_data_sv {
+ SV * svfunc;
+ SV * svuser_data;
+ SV * svfunc_complete;
+ SV * svfunc_sizeout;
+};
+
+static void
+call_sub_foreach(GMimeObject *mime_object, gpointer data)
+{
+ SV * svpart;
+ SV * rvpart;
+
+ dSP ;
+ struct _user_data_sv *svdata;
+
+ svdata = (struct _user_data_sv *) data;
+ svpart = sv_newmortal ();
+
+ if (GMIME_IS_PART(mime_object)) {
+ rvpart = sv_setref_pv(svpart, "Mail::Rspamd::Part", (Mail__Rspamd__Part)mime_object);
+ } else {
+ rvpart = sv_setref_pv(svpart, "Mail::Rspamd::Object", mime_object);
+ }
+
+ PUSHMARK (sp);
+ XPUSHs (rvpart);
+ XPUSHs (sv_mortalcopy (svdata->svuser_data));
+ PUTBACK ;
+ if (svdata->svfunc) {
+ perl_call_sv (svdata->svfunc, G_DISCARD);
+ }
+}
+/* known header field types */
+enum {
+ HEADER_FROM = 0,
+ HEADER_REPLY_TO,
+ HEADER_TO,
+ HEADER_CC,
+ HEADER_BCC,
+ HEADER_SUBJECT,
+ HEADER_DATE,
+ HEADER_MESSAGE_ID,
+ HEADER_UNKNOWN
+};
+
+static GList *
+local_message_get_header(GMimeMessage *message, const char *field)
+{
+ struct raw_header *h;
+ GList * gret = NULL;
+
+ if (field == NULL) {
+ return NULL;
+ }
+ h = GMIME_OBJECT(message)->headers->headers;
+ while (h) {
+ if (h->value && !g_strncasecmp(field, h->name, strlen(field))) {
+ gret = g_list_prepend(gret, g_strdup(h->value));
+ }
+ h = h->next;
+ }
+ return gret;
+}
+
+/**
+* g_mime_message_set_date_from_string: Set the message sent-date
+* @message: MIME Message
+* @string: A string of date
+*
+* Set the sent-date on a MIME Message.
+**/
+static void
+local_mime_message_set_date_from_string (GMimeMessage *message, const gchar *string)
+{
+ time_t date;
+ int offset = 0;
+
+ date = g_mime_utils_header_decode_date (string, &offset);
+ g_mime_message_set_date (message, date, offset);
+}
+
+
+
+/* different declarations for different types of set and get functions */
+typedef const char *(*GetFunc) (GMimeMessage *message);
+typedef InternetAddressList *(*GetRcptFunc) (GMimeMessage *message, const char *type );
+typedef GList *(*GetListFunc) (GMimeMessage *message, const char *type );
+typedef void (*SetFunc) (GMimeMessage *message, const char *value);
+typedef void (*SetListFunc) (GMimeMessage *message, const char *field, const char *value);
+
+/** different types of functions
+*
+* FUNC_CHARPTR
+* - function with no arguments
+* - get returns char*
+*
+* FUNC_IA (from Internet Address)
+* - function with additional "field" argument from the fieldfunc table,
+* - get returns Glist*
+*
+* FUNC_LIST
+* - function with additional "field" argument (given arbitrary header field name)
+* - get returns Glist*
+**/
+enum {
+ FUNC_CHARPTR = 0,
+ FUNC_CHARFREEPTR,
+ FUNC_IA,
+ FUNC_LIST
+};
+
+/**
+* fieldfunc struct: structure of MIME fields and corresponding get and set
+* functions.
+**/
+static struct {
+ char * name;
+ GetFunc func;
+ GetRcptFunc rcptfunc;
+ GetListFunc getlistfunc;
+ SetFunc setfunc;
+ SetListFunc setlfunc;
+ gint functype;
+} fieldfunc[] = {
+ { "From", g_mime_message_get_sender, NULL, NULL, g_mime_message_set_sender, NULL, FUNC_CHARPTR },
+ { "Reply-To", g_mime_message_get_reply_to, NULL, NULL, g_mime_message_set_reply_to, NULL, FUNC_CHARPTR },
+ { "To", NULL, g_mime_message_get_recipients, NULL, NULL, g_mime_message_add_recipients_from_string, FUNC_IA },
+ { "Cc", NULL, g_mime_message_get_recipients, NULL, NULL, g_mime_message_add_recipients_from_string, FUNC_IA },
+ { "Bcc", NULL, g_mime_message_get_recipients, NULL, NULL, g_mime_message_add_recipients_from_string, FUNC_IA },
+ { "Subject", g_mime_message_get_subject, NULL, NULL, g_mime_message_set_subject, NULL, FUNC_CHARPTR },
+ { "Date", g_mime_message_get_date_string, NULL, NULL, local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR },
+ { "Message-Id", g_mime_message_get_message_id, NULL, NULL, g_mime_message_set_message_id, NULL, FUNC_CHARPTR },
+ { NULL, NULL, NULL, local_message_get_header, NULL, g_mime_message_add_header, FUNC_LIST }
+};
+
+/**
+* message_set_header: set header of any type excluding special (Content- and MIME-Version:)
+**/
+static void
+message_set_header (GMimeMessage *message, const char *field, const char *value)
+{
+ gint i;
+
+
+ if (!g_strcasecmp (field, "MIME-Version:") || !g_strncasecmp (field, "Content-", 8)) {
+ return;
+ }
+ for (i=0; i<=HEADER_UNKNOWN; ++i) {
+ if (!fieldfunc[i].name || !g_strncasecmp(field, fieldfunc[i].name, strlen(fieldfunc[i].name))) {
+ switch (fieldfunc[i].functype) {
+ case FUNC_CHARPTR:
+ (*(fieldfunc[i].setfunc))(message, value);
+ break;
+ case FUNC_IA:
+ (*(fieldfunc[i].setlfunc))(message, fieldfunc[i].name, value);
+ break;
+ case FUNC_LIST:
+ (*(fieldfunc[i].setlfunc))(message, field, value);
+ break;
+ }
+ break;
+ }
+ }
+}
+
+
+/**
+* message_get_header: returns the list of 'any header' values
+* (except of unsupported yet Content- and MIME-Version special headers)
+*
+* You should free the GList list by yourself.
+**/
+static
+GList *
+message_get_header(GMimeMessage *message, const char *field) {
+ gint i;
+ char * ret = NULL;
+ GList * gret = NULL;
+ InternetAddressList *ia_list = NULL, *ia;
+
+ for (i = 0; i <= HEADER_UNKNOWN; ++i) {
+ if (!fieldfunc[i].name || !g_strncasecmp(field, fieldfunc[i].name, strlen(fieldfunc[i].name))) {
+ switch (fieldfunc[i].functype) {
+ case FUNC_CHARFREEPTR:
+ ret = (char *)(*(fieldfunc[i].func))(message);
+ break;
+ case FUNC_CHARPTR:
+ ret = (char *)(*(fieldfunc[i].func))(message);
+ break;
+ case FUNC_IA:
+ ia_list = (*(fieldfunc[i].rcptfunc))(message, field);
+ gret = g_list_alloc();
+ ia = ia_list;
+ while (ia && ia->address) {
+ char *ia_string;
+
+ ia_string = internet_address_to_string ((InternetAddress *)ia->address, FALSE);
+ gret = g_list_append (gret, ia_string);
+ ia = ia->next;
+ }
+ break;
+ case FUNC_LIST:
+ gret = (*(fieldfunc[i].getlistfunc))(message, field);
+ break;
+ }
+ break;
+ }
+ }
+ if (gret == NULL && ret != NULL) {
+ gret = g_list_prepend (gret, g_strdup (ret));
+ }
+ if (fieldfunc[i].functype == FUNC_CHARFREEPTR && ret) {
+ g_free (ret);
+ }
+ return gret;
+}
+
+MODULE = Mail::Rspamd PACKAGE = Mail::Rspamd::Log PREFIX = rspamd_log_
+PROTOTYPES: DISABLE
+
+void
+rspamd_log_log (level, str)
+ int level
+ const char *str
+ CODE:
+ g_log (G_LOG_DOMAIN, level, "%s", str);
+
+
+MODULE = Mail::Rspamd PACKAGE = Mail::Rspamd
+
+INCLUDE: Rspamd/Object.xs
+INCLUDE: Rspamd/ContentType.xs
+INCLUDE: Rspamd/Part.xs
+INCLUDE: Rspamd/Message.xs
+
+INCLUDE: Rspamd/InternetAddress.xs
+INCLUDE: Rspamd/Hash.xs
+
+
diff --git a/perl/Rspamd/Config.xs b/perl/Rspamd/Config.xs
new file mode 100644
index 000000000..49b26db2f
--- /dev/null
+++ b/perl/Rspamd/Config.xs
@@ -0,0 +1,141 @@
+MODULE = Mail::Rspamd PACKAGE = Mail::Rspamd::Config PREFIX = rspamd_config_
+PROTOTYPES: DISABLE
+
+SV *
+rspamd_config_get_scalar (cfg, param)
+ Mail::Rspamd::Config cfg
+ const char *param
+ CODE:
+ struct config_scalar *sc;
+ int val;
+
+ sc = g_hash_table_lookup (cfg->cfg_params, param);
+ if (sc == NULL) {
+ XSRETURN_UNDEF;
+ }
+ else {
+ switch (sc->type) {
+ case SCALAR_TYPE_SIZE:
+ RETVAL = newSViv ((int)(*(size_t *)sc->pointer));
+ break;
+ case SCALAR_TYPE_INT:
+ case SCALAR_TYPE_UINT:
+ RETVAL = newSViv (*(int *)sc->pointer);
+ break;
+ case SCALAR_TYPE_STR:
+ RETVAL = newSVpv ((char *)sc->pointer, 0);
+ break;
+ }
+ }
+
+
+void
+rspamd_config_set_scalar (cfg, param, value)
+ Mail::Rspamd::Config cfg
+ const char *param
+ SV* value
+ CODE:
+ char *param, *charval;
+ int intval;
+
+ sc = g_hash_table_lookup (cfg->cfg_params, param);
+ if (sc == NULL) {
+ XSRETURN_UNDEF;
+ }
+ else {
+ switch (sc->type) {
+ case SCALAR_TYPE_SIZE:
+ intval = (int)SvIV (value);
+ *((size_t *)sc->pointer) = intval;
+ break;
+ case SCALAR_TYPE_INT:
+ case SCALAR_TYPE_UINT:
+ intval = (int)SvIV (value);
+ *((int *)sc->pointer) = intval;
+ break;
+ case SCALAR_TYPE_STR:
+ charval = (char *)SvPVX (value);
+ *((char **)sc->pointer) = charval;
+ break;
+ }
+ }
+
+HV *
+rspamd_config_get_metric (r, name)
+ Mail::Rspamd::Config cfg
+ const char *name
+ CODE:
+ struct metric *val;
+
+ val = g_hash_table_lookup (r->metrics, name);
+ if (val == NULL) {
+ XSRETURN_UNDEF;
+ }
+ else {
+ RETVAL = newHV();
+
+ (void)hv_store_ent (RETVAL,
+ newSVpv ("name", sizeof ("name") - 1),
+ newSVpv (val->name, strlen (val->name)), 0);
+ (void)hv_store_ent (RETVAL,
+ newSVpv ("func_name", sizeof ("func_name") - 1),
+ newSVpv (val->func_name, strlen (val->func_name)), 0);
+ (void)hv_store_ent (RETVAL,
+ newSVpv ("required_score", sizeof ("required_score") - 1),
+ newSVnv (val->required_score), 0);
+ sv_2mortal((SV*)RETVAL);
+ }
+ OUTPUT:
+ RETVAL
+
+HV *
+rspamd_config_get_statfile (r, name)
+ Mail::Rspamd::Config cfg
+ const char *name
+ CODE:
+ struct statfile *val;
+ char *name;
+
+ val = g_hash_table_lookup (r->statfiles, name);
+ if (val == NULL) {
+ XSRETURN_UNDEF;
+ }
+ else {
+ RETVAL = newHV();
+
+ (void)hv_store_ent (RETVAL,
+ newSVpv ("alias", sizeof ("alias") - 1),
+ newSVpv (val->alias, strlen (val->alias)), 0);
+ (void)hv_store_ent (RETVAL,
+ newSVpv ("pattern", sizeof ("pattern") - 1),
+ newSVpv (val->pattern, strlen (val->pattern)), 0);
+ (void)hv_store_ent (RETVAL,
+ newSVpv ("metric", sizeof ("metric") - 1),
+ newSVpv (val->metric, strlen (val->metric)), 0);
+ (void)hv_store_ent (RETVAL,
+ newSVpv ("weight", sizeof ("weight") - 1),
+ newSVnv (val->weight), 0);
+ (void)hv_store_ent (RETVAL,
+ newSVpv ("size", sizeof ("size") - 1),
+ newSViv (val->size), 0);
+ sv_2mortal((SV*)RETVAL);
+ }
+ OUTPUT:
+ RETVAL
+
+SV*
+rspamd_config_get_module_param (r, modulename, paramname)
+ Mail::Rspamd::Config cfg
+ const char *modulename
+ const char *paramname
+ CODE:
+ char *value;
+
+ value = get_module_opt (r, modulename, paramname);
+ if (value == NULL) {
+ XSRETURN_UNDEF;
+ }
+ RETVAL = newSVpv (value, 0);
+ OUTPUT:
+ RETVAL
+
diff --git a/perl/Rspamd/ContentType.xs b/perl/Rspamd/ContentType.xs
new file mode 100644
index 000000000..dae8a35ad
--- /dev/null
+++ b/perl/Rspamd/ContentType.xs
@@ -0,0 +1,87 @@
+MODULE = Mail::Rspamd PACKAGE = Mail::Rspamd::ContentType PREFIX = rspamd_content_type_
+
+Mail::Rspamd::ContentType
+rspamd_content_type_new (Class = "Mail::Rspamd::ContentType", name = 0, subname = 0)
+ CASE: items == 2
+ char * Class;
+ const char * name;
+ CODE:
+ RETVAL = g_mime_content_type_new_from_string (name);
+ plist = g_list_prepend (plist, RETVAL);
+ OUTPUT:
+ RETVAL
+ CASE: items == 3
+ char * Class;
+ const char * name;
+ const char * subname;
+ CODE:
+ RETVAL = g_mime_content_type_new (name, subname);
+ plist = g_list_prepend (plist, RETVAL);
+ OUTPUT:
+ RETVAL
+
+void
+DESTROY (mime_type)
+ Mail::Rspamd::ContentType mime_type
+ CODE:
+ if (g_list_find(plist,mime_type)) {
+ g_mime_content_type_destroy(mime_type);
+ plist = g_list_remove(plist, mime_type);
+ }
+
+SV *
+rspamd_content_type_to_string (mime_type)
+ Mail::Rspamd::ContentType mime_type
+ PREINIT:
+ char * type;
+ CODE:
+ type = g_mime_content_type_to_string (mime_type);
+ if (!type)
+ XSRETURN_UNDEF;
+ RETVAL = newSVpv(type, 0);
+ g_free (type);
+ OUTPUT:
+ RETVAL
+
+gboolean
+rspamd_content_type_is_type (mime_type, type, subtype)
+ Mail::Rspamd::ContentType mime_type
+ const char * type
+ const char * subtype
+ CODE:
+ RETVAL = g_mime_content_type_is_type (mime_type, type, subtype);
+ OUTPUT:
+ RETVAL
+
+void
+rspamd_content_type_set_parameter (mime_type, attribute, value)
+ Mail::Rspamd::ContentType mime_type
+ const char * attribute
+ const char * value
+ CODE:
+ g_mime_content_type_set_parameter (mime_type, attribute, value);
+
+const char *
+rspamd_content_type_get_parameter (mime_type, attribute)
+ Mail::Rspamd::ContentType mime_type
+ const char * attribute
+ CODE:
+ RETVAL = g_mime_content_type_get_parameter (mime_type, attribute);
+ OUTPUT:
+ RETVAL
+
+char *
+rspamd_content_type_type (ctype)
+ Mail::Rspamd::ContentType ctype
+ CODE:
+ RETVAL = ctype->type;
+ OUTPUT:
+ RETVAL
+
+char *
+rspamd_content_type_subtype (ctype)
+ Mail::Rspamd::ContentType ctype
+ CODE:
+ RETVAL = ctype->subtype;
+ OUTPUT:
+ RETVAL
diff --git a/perl/Rspamd/Hash.xs b/perl/Rspamd/Hash.xs
new file mode 100644
index 000000000..b61cebc39
--- /dev/null
+++ b/perl/Rspamd/Hash.xs
@@ -0,0 +1,258 @@
+MODULE = Mail::Rspamd PACKAGE = Mail::Rspamd::Hash::Header PREFIX=hash_
+
+Mail::Rspamd::Hash::Header
+hash_TIEHASH (Class, objptr)
+ char * Class
+ Mail::Rspamd::Message objptr
+ PREINIT:
+ hash_header * hash;
+ CODE:
+ hash = g_malloc (sizeof (hash_header));
+ hash->keyindex = 0;
+ hash->objptr = objptr;
+ hash->fetchvalue = NULL;
+ RETVAL = hash;
+ OUTPUT:
+ RETVAL
+
+void
+hash_DESTROY (obj)
+ Mail::Rspamd::Hash::Header obj
+ CODE:
+ obj->objptr = NULL;
+ g_free (obj);
+
+void
+hash_FETCH (obj, key)
+ Mail::Rspamd::Hash::Header obj
+ const char * key
+ PREINIT:
+ Mail__Rspamd__Message msg;
+ GList *gret = NULL, *item;
+ AV * retav;
+ I32 gimme = GIMME_V;
+ PPCODE:
+ msg = obj->objptr;
+
+ /* THE HACK - FETCH method would get value indirectly from NEXTKEY */
+ if (obj->keyindex != -1 && obj->fetchvalue != NULL) {
+ XPUSHs (sv_2mortal (newSVpv (obj->fetchvalue, 0)));
+ obj->fetchvalue == NULL;
+ XSRETURN(1);
+ }
+
+ obj->fetchvalue = NULL;
+
+ gret = message_get_header (msg, key);
+
+ if (!gret || gret->data == NULL) {
+ if (gret) {
+ g_list_free(gret);
+ }
+
+ XSRETURN(0);
+ } else {
+ if (gret->next == NULL) { // one value
+ XPUSHs (sv_2mortal (newSVpv ((char *)(gret->data), 0)));
+ } else {
+ if (gimme == G_ARRAY) {
+ item = gret;
+ while (item && item->data) {
+ XPUSHs (sv_2mortal (newSVpv ((char *)(item->data), 0)));
+ item = item->next;
+ }
+ } else if (gimme == G_SCALAR) {
+ retav = newAV();
+ item = gret;
+ while (item && item->data) {
+ av_push (retav, newSVpv ((char *)g_strdup ((item->data)), 0));
+ item = item->next;
+ }
+ XPUSHs (newRV_noinc ((SV *)retav));
+ }
+ }
+ }
+ if (gret) {
+ item = gret;
+ while (item) {
+ if (item->data) {
+ g_free((char *)(item->data));
+ }
+ item = item->next;
+ }
+ g_list_free(gret);
+ }
+
+void
+hash_STORE (obj, key, svmixed)
+ Mail::Rspamd::Hash::Header obj
+ const char * key
+ SV * svmixed
+ PREINIT:
+ Mail__Rspamd__Message msg;
+ char * value;
+ SV * svvalue;
+ svtype svvaltype;
+ STRLEN vallen;
+ CODE:
+ /* only one value can be stored - no arrays allowed by perl */
+ msg = obj->objptr;
+
+ svvalue = svmixed;
+ if (SvROK (svmixed)) {
+ svvalue = SvRV(svmixed);
+ }
+ svvaltype = SvTYPE (svvalue);
+
+ if (SvGMAGICAL(svvalue)) {
+ mg_get(svvalue);
+ }
+
+ /* delete header for the first array item */
+ g_mime_object_remove_header (GMIME_OBJECT(msg), key);
+
+ if (svvaltype == SVt_PVAV) {
+ AV * avvalue;
+ I32 i, avlen;
+ SV * svtmp;
+
+ /* set header */
+ avvalue = (AV *)svvalue;
+ avlen = av_len(avvalue);
+ for (i=avlen; i>=0; --i) {
+ svtmp = (SV *)(*(av_fetch (avvalue, i, 0)));
+
+ if (SvGMAGICAL(svtmp)) {
+ mg_get(svtmp);
+ }
+
+ if (svtmp && SvPOKp(svtmp)) {
+ value = (char *)SvPV(svtmp, vallen);
+ message_set_header (msg, key, value);
+ }
+ }
+ } else if (SvPOK(svvalue) || SvIOK(svvalue) || SvNOK(svvalue)) {
+ value = (char *)SvPV (svvalue, vallen);
+ message_set_header (msg, key, value);
+ } else { /* assume scalar value */
+ /* undefined value -> remove header */
+ if (!(SvOK(svvalue))) {
+ g_mime_object_remove_header (GMIME_OBJECT(msg), key);
+ }
+ }
+
+gboolean
+hash_EXISTS (obj, key)
+ Mail::Rspamd::Hash::Header obj
+ const char * key
+ PREINIT:
+ Mail__Rspamd__Message msg;
+ GList *gret, *item;
+ CODE:
+ msg = obj->objptr;
+ gret = message_get_header (msg, key);
+ RETVAL = (gret != NULL && gret->data != NULL);
+ if (gret) {
+ item = gret;
+ while (item) {
+ if (item->data) {
+ g_free((char *)(item->data));
+ }
+ item = item->next;
+ }
+ g_list_free(gret);
+ }
+ OUTPUT:
+ RETVAL
+
+void
+hash_DELETE(obj, key)
+ Mail::Rspamd::Hash::Header obj
+ const char * key
+ CODE:
+ g_mime_object_remove_header (GMIME_OBJECT(obj->objptr), key);
+
+void
+hash_NEXTKEY(obj, lastkey = NULL)
+ Mail::Rspamd::Hash::Header obj
+ const char * lastkey
+ ALIAS:
+ Mail::Rspamd::Hash::Header::FIRSTKEY = 1
+ PREINIT:
+ char * key = NULL;
+ char * value = NULL;
+ Mail__Rspamd__Message msg;
+ I32 gimme = GIMME_V;
+ gint i, j, found;
+ local_GMimeHeader * header;
+ struct raw_header *h;
+ INIT:
+ if (ix == 1) {
+ obj->keyindex = -1;
+ }
+ PPCODE:
+ msg = obj->objptr;
+ ++obj->keyindex;
+ i = obj->keyindex;
+ header = GMIME_OBJECT(msg)->headers;
+
+ h = header->headers;
+ j = 0;
+ found = 0;
+ while (h) {
+ if (j >= i) {
+ key = h->name;
+ value = h->value;
+ found = 1;
+ break;
+ }
+ j++;
+ h = h->next;
+ }
+
+ if (!found && key == NULL) {
+ obj->keyindex = -1;
+ }
+
+ /* THE HACK - FETCH method would get value indirectly */
+ obj->fetchvalue = NULL;
+
+ if (key) {
+ XPUSHs (sv_2mortal (newSVpv (key, 0)));
+ if (gimme != G_SCALAR && value) {
+ XPUSHs (sv_2mortal (newSVpv (value, 0)));
+ }
+ /* THE HACK - FETCH method would get value indirectly */
+ obj->fetchvalue = value;
+ }
+
+void
+hash_CLEAR(obj)
+ Mail::Rspamd::Hash::Header obj
+ PREINIT:
+ Mail__Rspamd__Message message;
+ local_GMimeHeader *header;
+ CODE:
+ message = obj->objptr;
+
+ g_free (message->from);
+ message->from = NULL;
+
+ g_free (message->reply_to);
+ message->reply_to = NULL;
+
+ /* destroy all recipients */
+ g_hash_table_foreach_remove (message->recipients, recipients_destroy, NULL);
+
+ g_free (message->subject);
+ message->subject = NULL;
+
+ g_free (message->message_id);
+ message->message_id = NULL;
+
+ /* free all the headers */
+ header = GMIME_OBJECT(message)->headers;
+ g_mime_header_destroy (header);
+ GMIME_OBJECT(message)->headers = g_mime_header_new ();
+
+
diff --git a/perl/Rspamd/InternetAddress.xs b/perl/Rspamd/InternetAddress.xs
new file mode 100644
index 000000000..834117bbe
--- /dev/null
+++ b/perl/Rspamd/InternetAddress.xs
@@ -0,0 +1,124 @@
+MODULE = Mail::Rspamd PACKAGE = Mail::Rspamd::InternetAddress PREFIX = rspamd_internet_address_
+
+Mail::Rspamd::InternetAddress
+rspamd_internet_address_new (Class, name, address)
+ CASE: items <= 1
+ char * Class
+ CODE:
+ RETVAL = internet_address_new ();
+ plist = g_list_prepend (plist, RETVAL);
+ OUTPUT:
+ RETVAL
+ CASE: items == 2
+ char * Class
+ char * name
+ CODE:
+ RETVAL = internet_address_new_group (name);
+ plist = g_list_prepend (plist, RETVAL);
+ OUTPUT:
+ RETVAL
+ CASE: items == 3
+ char * Class
+ char * name
+ char * address
+ CODE:
+ RETVAL = internet_address_new_name (name, address);
+ plist = g_list_prepend (plist, RETVAL);
+ OUTPUT:
+ RETVAL
+
+void
+DESTROY(ia)
+ Mail::Rspamd::InternetAddress ia
+ CODE:
+ if (g_list_find (plist,ia)) {
+ internet_address_unref (ia);
+ plist = g_list_remove (plist, ia);
+ }
+
+AV *
+rspamd_internet_address_parse_string (str)
+ const char * str
+ PREINIT:
+ InternetAddressList * addrlist;
+ AV * retav;
+ CODE:
+ addrlist = internet_address_parse_string (str);
+ retav = newAV ();
+ while (addrlist) {
+ SV * address = newSViv (0);
+ sv_setref_pv (address, "Mail::Rspamd::InternetAddress", (Mail__Rspamd__InternetAddress)(addrlist->address));
+ av_push (retav, address);
+ addrlist = addrlist->next;
+ }
+ RETVAL = retav;
+ OUTPUT:
+ RETVAL
+
+void
+interface_ia_set (ia, value)
+ Mail::Rspamd::InternetAddress ia
+ char * value
+ INTERFACE_MACRO:
+ XSINTERFACE_FUNC
+ XSINTERFACE_FUNC_RSPAMD_IA_SET
+ INTERFACE:
+ set_name
+ set_addr
+
+SV *
+rspamd_internet_address_to_string (ia, encode = TRUE)
+ Mail::Rspamd::InternetAddress ia
+ gboolean encode
+ PREINIT:
+ char * textdata;
+ CODE:
+ textdata = internet_address_to_string (ia, encode);
+ if (textdata == NULL) {
+ XSRETURN_UNDEF;
+ }
+ RETVAL = newSVpv (textdata, 0);
+ OUTPUT:
+ RETVAL
+
+void
+rspamd_internet_address_set_group (ia, ...)
+ Mail::Rspamd::InternetAddress ia
+ PREINIT:
+ Mail__Rspamd__InternetAddress addr;
+ InternetAddressList * addrlist = NULL;
+ int i;
+ CODE:
+ if (items < 2) {
+ XSRETURN_UNDEF;
+ }
+ for (i = items - 1; i > 0; --i) {
+ /* retrieve each address from the perl array */
+ if (sv_derived_from (ST (items - i), "Mail::Rspamd::InternetAddress")) {
+ IV tmp = SvIV ((SV*)SvRV (ST (items - i)));
+ addr = INT2PTR (Mail__Rspamd__InternetAddress, tmp);
+ }
+ if (addr) {
+ internet_address_list_append (addrlist, addr);
+ }
+ }
+ if (addrlist) {
+ internet_address_set_group (ia, addrlist);
+ }
+
+void
+rspamd_internet_address_add_member (ia, member)
+ Mail::Rspamd::InternetAddress ia
+ Mail::Rspamd::InternetAddress member
+ CODE:
+ internet_address_add_memeber (ia, member);
+
+Mail::Rspamd::InternetAddressType
+rspamd_internet_address_type (ia)
+ Mail::Rspamd::InternetAddress ia
+ CODE:
+ RETVAL = ia->type;
+ OUTPUT:
+ RETVAL
+
+
diff --git a/perl/Rspamd/Message.xs b/perl/Rspamd/Message.xs
new file mode 100644
index 000000000..6e3a16d8b
--- /dev/null
+++ b/perl/Rspamd/Message.xs
@@ -0,0 +1,264 @@
+MODULE = Mail::Rspamd PACKAGE = Mail::Rspamd::Message PREFIX = rspamd_message_
+
+Mail::Rspamd::Message
+rspamd_message_new(Class, pretty_headers = FALSE)
+ char * Class
+ gboolean pretty_headers
+ CODE:
+ RETVAL = g_mime_message_new (pretty_headers);
+ plist = g_list_prepend(plist, RETVAL);
+ OUTPUT:
+ RETVAL
+
+void
+DESTROY(message)
+ Mail::Rspamd::Message message
+ CODE:
+ if (g_list_find(plist,message)) {
+ g_mime_object_unref (GMIME_OBJECT (message));
+ plist = g_list_remove(plist, message);
+ }
+
+void
+rspamd_message_add_recipient(message, type, name, address)
+ Mail::Rspamd::Message message
+ char * type
+ const char * name
+ const char * address
+ CODE:
+ g_mime_message_add_recipient (message, type, name, address);
+
+void
+rspamd_message_add_recipients_from_string(message, type, recipients)
+ Mail::Rspamd::Message message
+ char * type
+ const char * recipients
+ CODE:
+ g_mime_message_add_recipients_from_string (message, type, recipients);
+
+AV *
+rspamd_message_get_recipients(message, type)
+ Mail::Rspamd::Message message
+ const char * type
+ PREINIT:
+ const InternetAddressList * rcpt;
+ AV * retav;
+ CODE:
+ retav = newAV();
+ rcpt = g_mime_message_get_recipients (message, type);
+ while (rcpt) {
+ SV * address = newSViv(0);
+ sv_setref_pv(address, "Mail::Rspamd::InternetAddress", (Mail__Rspamd__InternetAddress)(rcpt->address));
+ av_push(retav, address);
+ rcpt = rcpt->next;
+ }
+ RETVAL = retav;
+ OUTPUT:
+ RETVAL
+
+
+void
+interface_m_set (message, value)
+ Mail::Rspamd::Message message
+ char * value
+ INTERFACE_MACRO:
+ XSINTERFACE_FUNC
+ XSINTERFACE_FUNC_RSPAMD_MESSAGE_SET
+ INTERFACE:
+ set_subject
+ set_message_id
+ set_reply_to
+ set_sender
+
+const char *
+interface_m_get (message)
+ Mail::Rspamd::Message message
+ INTERFACE_MACRO:
+ XSINTERFACE_FUNC
+ XSINTERFACE_FUNC_RSPAMD_MESSAGE_SET
+ INTERFACE:
+ get_subject
+ get_message_id
+ get_reply_to
+ get_sender
+
+ # date
+void
+rspamd_message_set_date (message, date, gmt_offset)
+ Mail::Rspamd::Message message
+ time_t date
+ int gmt_offset
+ CODE:
+ g_mime_message_set_date (message, date, gmt_offset);
+
+void
+rspamd_message_set_date_from_string (message, str)
+ Mail::Rspamd::Message message
+ const char * str
+ PREINIT:
+ time_t date;
+ int offset = 0;
+ CODE:
+ date = g_mime_utils_header_decode_date (str, &offset);
+ g_mime_message_set_date (message, date, offset);
+
+
+void
+rspamd_message_get_date (message)
+ Mail::Rspamd::Message message
+ PREINIT:
+ time_t date;
+ int gmt_offset;
+ I32 gimme = GIMME_V;
+ char * str;
+ PPCODE:
+ if (gimme == G_SCALAR) {
+ str = g_mime_message_get_date_string (message);
+ if (str) {
+ XPUSHs (sv_2mortal (newSVpv (str,0)));
+ g_free (str);
+ }
+ } else if (gimme == G_ARRAY) {
+ g_mime_message_get_date (message, &date, &gmt_offset);
+ XPUSHs (sv_2mortal (newSVnv (date)));
+ XPUSHs (sv_2mortal (newSViv (gmt_offset)));
+ }
+
+void
+rspamd_message_set_header (message, field, value)
+ Mail::Rspamd::Message message
+ const char * field
+ const char * value
+ CODE:
+ g_mime_message_set_header (message, field, value);
+
+void
+rspamd_message_remove_header (message, field)
+ Mail::Rspamd::Message message
+ const char * field
+ CODE:
+ g_mime_object_remove_header (GMIME_OBJECT (message), field);
+
+void
+rspamd_message_add_header (message, field, value)
+ Mail::Rspamd::Message message
+ const char * field
+ const char * value
+ CODE:
+ g_mime_message_set_header (message, field, value);
+
+const char *
+rspamd_message_get_header (message, field)
+ Mail::Rspamd::Message message
+ const char * field
+ CODE:
+ RETVAL = g_mime_message_get_header (message, field);
+ OUTPUT:
+ RETVAL
+
+void
+rspamd_message_set_mime_part (message, mime_part)
+ Mail::Rspamd::Message message
+ Mail::Rspamd::Object mime_part
+ CODE:
+ g_mime_message_set_mime_part (message, GMIME_OBJECT (mime_part));
+ plist = g_list_remove (plist, mime_part);
+
+SV *
+rspamd_message_get_body (message, want_plain = 1, is_html = 0)
+ CASE: items == 1
+ Mail::Rspamd::Message message
+ PREINIT:
+ gboolean want_plain = 1;
+ gboolean is_html;
+ char * textdata;
+ CODE:
+ textdata = g_mime_message_get_body (message, want_plain, &is_html);
+ if (textdata == NULL)
+ XSRETURN_UNDEF;
+ RETVAL = newSVpv (textdata, 0);
+ g_free (textdata);
+ OUTPUT:
+ RETVAL
+ CASE: items == 2
+ Mail::Rspamd::Message message
+ gboolean want_plain
+ PREINIT:
+ gboolean is_html;
+ char * textdata;
+ CODE:
+ textdata = g_mime_message_get_body (message, want_plain, &is_html);
+ if (textdata == NULL)
+ XSRETURN_UNDEF;
+ RETVAL = newSVpv (textdata, 0);
+ g_free (textdata);
+ OUTPUT:
+ RETVAL
+ CASE: items == 3
+ Mail::Rspamd::Message message
+ gboolean want_plain
+ gboolean &is_html
+ PREINIT:
+ char * textdata;
+ CODE:
+ textdata = g_mime_message_get_body (message, want_plain, &is_html);
+ if (textdata == NULL) {
+ RETVAL = &PL_sv_undef;
+ }
+ RETVAL = newSVpv (textdata, 0);
+ g_free (textdata);
+ OUTPUT:
+ is_html
+ RETVAL
+
+SV *
+rspamd_message_get_headers(message)
+ Mail::Rspamd::Message message
+ PREINIT:
+ char * textdata;
+ CODE:
+ textdata = g_mime_message_get_headers (message);
+ if (textdata == NULL) {
+ RETVAL = &PL_sv_undef;
+ }
+ RETVAL = newSVpv (textdata, 0);
+ g_free (textdata);
+ OUTPUT:
+ RETVAL
+
+void
+rspamd_message_foreach_part (message, callback, svdata)
+ Mail::Rspamd::Message message
+ SV * callback
+ SV * svdata
+ PREINIT:
+ struct _user_data_sv *data;
+
+ CODE:
+ data = g_new0 (struct _user_data_sv, 1);
+ data->svuser_data = newSVsv (svdata);
+ data->svfunc = newSVsv (callback);
+ g_mime_message_foreach_part (message, call_sub_foreach, data);
+ g_free (data);
+
+SV *
+get_mime_part(message)
+ Mail::Rspamd::Message message
+ PREINIT:
+ GMimeObject * mime_object;
+ CODE:
+ if (message->mime_part != NULL) {
+ RETVAL = newSViv(4);
+ mime_object = GMIME_OBJECT (message->mime_part);
+ if (GMIME_IS_PART(mime_object)) {
+ sv_setref_pv(RETVAL, "Mail::Rspamd::Part", (Mail__Rspamd__Part)mime_object);
+ } else {
+ plist = g_list_prepend(plist, RETVAL);
+ }
+ g_mime_object_ref( mime_object );
+ } else {
+ RETVAL = &PL_sv_undef;
+ }
+ OUTPUT:
+ RETVAL
+
diff --git a/perl/Rspamd/Object.xs b/perl/Rspamd/Object.xs
new file mode 100644
index 000000000..89bc09bf8
--- /dev/null
+++ b/perl/Rspamd/Object.xs
@@ -0,0 +1,152 @@
+MODULE = Mail::Rspamd PACKAGE = Mail::Rspamd::Object PREFIX = rspamd_object_
+
+void
+rspamd_object_set_content_type (mime_object, content_type)
+ Mail::Rspamd::Object mime_object
+ Mail::Rspamd::ContentType content_type
+ CODE:
+ g_mime_object_set_content_type (mime_object, content_type);
+ plist = g_list_remove (plist, content_type);
+
+Mail::Rspamd::ContentType
+rspamd_object_get_content_type (mime_object)
+ Mail::Rspamd::Object mime_object
+ PREINIT:
+ char * textdata;
+ const GMimeContentType *ct;
+ CODE:
+ ct = g_mime_object_get_content_type (mime_object);
+ textdata = g_mime_content_type_to_string (ct);
+ RETVAL = g_mime_content_type_new_from_string (textdata);
+ plist = g_list_prepend (plist, RETVAL);
+ g_free (textdata);
+ OUTPUT:
+ RETVAL
+
+void
+rspamd_object_set_content_type_parameter (mime_object, name, value)
+ Mail::Rspamd::Object mime_object
+ const char * name
+ const char * value
+ CODE:
+ gmime_object_set_content_type_parameter (mime_object, name, value);
+
+const char *
+rspamd_object_get_content_type_parameter (mime_object, name)
+ Mail::Rspamd::Object mime_object
+ const char * name
+ CODE:
+ RETVAL = g_mime_object_get_content_type_parameter (mime_object, name);
+ OUTPUT:
+ RETVAL
+
+void
+rspamd_object_set_content_id (mime_object, content_id)
+ Mail::Rspamd::Object mime_object
+ const char * content_id
+ CODE:
+ g_mime_object_set_content_id (mime_object, content_id);
+
+const char *
+rspamd_object_get_content_id(mime_object)
+ Mail::Rspamd::Object mime_object
+ CODE:
+ RETVAL = g_mime_object_get_content_id (mime_object);
+ OUTPUT:
+ RETVAL
+
+
+void
+rspamd_object_add_header (mime_object, field, value)
+ Mail::Rspamd::Object mime_object
+ const char * field
+ const char * value
+ CODE:
+ g_mime_object_add_header (mime_object, field, value);
+
+void
+rspamd_object_set_header (mime_object, field, value)
+ Mail::Rspamd::Object mime_object
+ const char * field
+ const char * value
+ CODE:
+ g_mime_object_set_header (mime_object, field, value);
+
+const char *
+rspamd_object_get_header (mime_object, field)
+ Mail::Rspamd::Object mime_object
+ const char * field
+ CODE:
+ RETVAL = g_mime_object_get_header (mime_object, field);
+ OUTPUT:
+ RETVAL
+
+void
+rspamd_object_remove_header (mime_object, field)
+ Mail::Rspamd::Object mime_object
+ const char * field
+ CODE:
+ g_mime_object_remove_header (mime_object, field);
+
+SV *
+rspamd_object_get_headers(mime_object)
+ Mail::Rspamd::Object mime_object
+ PREINIT:
+ char * textdata;
+ CODE:
+ textdata = g_mime_object_get_headers(mime_object);
+ if (textdata == NULL) {
+ XSRETURN_UNDEF;
+ }
+ RETVAL = newSVpv (textdata, 0);
+ g_free (textdata);
+ OUTPUT:
+ RETVAL
+
+SV *
+rspamd_object_to_string(mime_object)
+ Mail::Rspamd::Object mime_object
+ PREINIT:
+ char * textdata;
+ CODE:
+ textdata = g_mime_object_to_string (mime_object);
+ if (textdata) {
+ RETVAL = newSVpv (textdata, 0);
+ g_free (textdata);
+ } else {
+ XSRETURN_UNDEF;
+ }
+ OUTPUT:
+ RETVAL
+
+guint
+rspamd_object_get_content_length(mime_object)
+ Mail::Rspamd::Object mime_object
+ PREINIT:
+ guint lsize = 0;
+ GMimePart * mime_part;
+ CODE:
+ if (mime_object) {
+ if (GMIME_IS_PART(mime_object)) { // also MESSAGE_PARTIAL
+ mime_part = GMIME_PART(mime_object);
+ lsize = (mime_part->content && mime_part->content->stream) ?
+ g_mime_stream_length (mime_part->content->stream) : 0;
+ if (lsize) {
+ GMimePartEncodingType enc;
+
+ enc = g_mime_part_get_encoding (mime_part);
+ switch (enc) {
+ case GMIME_PART_ENCODING_BASE64:
+ lsize = BASE64_ENCODE_LEN (lsize);
+ break;
+ case GMIME_PART_ENCODING_QUOTEDPRINTABLE:
+ lsize = QP_ENCODE_LEN (lsize);
+ break;
+ }
+ }
+ }
+ }
+ RETVAL = lsize;
+ OUTPUT:
+ RETVAL
+
diff --git a/perl/Rspamd/Part.xs b/perl/Rspamd/Part.xs
new file mode 100644
index 000000000..b95a5fc99
--- /dev/null
+++ b/perl/Rspamd/Part.xs
@@ -0,0 +1,160 @@
+MODULE = Mail::Rspamd PACKAGE = Mail::Rspamd::Part PREFIX = rspamd_part
+
+Mail::Rspamd::Part
+g_mime_part_new (Class = "Mail::Rspamd::Part", type = "text", subtype = "plain")
+ char * Class;
+ const char * type;
+ const char * subtype;
+ CODE:
+ RETVAL = g_mime_part_new_with_type (type, subtype);
+ plist = g_list_prepend (plist, RETVAL);
+ OUTPUT:
+ RETVAL
+
+void
+DESTROY (mime_part)
+ Mail::Rspamd::Part mime_part
+ CODE:
+ if (g_list_find (plist,mime_part)) {
+ g_object_unref (G_OBJECT (mime_part));
+ plist = g_list_remove (plist, mime_part);
+ }
+
+void
+interface_p_set(mime_part, value)
+ Mail::Rspamd::Part mime_part
+ char * value
+ INTERFACE_MACRO:
+ XSINTERFACE_FUNC
+ XSINTERFACE_FUNC_RSPAMD_PART_SET
+ INTERFACE:
+ set_content_description
+ set_content_md5
+ set_content_location
+ set_content_disposition
+ set_filename
+
+
+const char *
+interface_p_get(mime_part)
+ Mail::Rspamd::Part mime_part
+ INTERFACE_MACRO:
+ XSINTERFACE_FUNC
+ XSINTERFACE_FUNC_RSPAMD_PART_SET
+ INTERFACE:
+ get_content_description
+ get_content_md5
+ get_content_location
+ get_content_disposition
+ get_filename
+
+void
+rspamd_part_set_content_header (mime_part, field, value)
+ Mail::Rspamd::Part mime_part
+ const char * field
+ const char * value
+ CODE:
+ g_mime_part_set_content_header (mime_part, field, value);
+
+const char *
+rspamd_part_get_content_header (mime_part, field)
+ Mail::Rspamd::Part mime_part
+ const char * field
+ CODE:
+ RETVAL = g_mime_part_get_content_header (mime_part, field);
+ OUTPUT:
+ RETVAL
+
+void
+rspamd_part_set_content_type (mime_part, content_type)
+ Mail::Rspamd::Part mime_part
+ Mail::Rspamd::ContentType content_type
+ CODE:
+ g_mime_part_set_content_type (mime_part, content_type);
+ plist = g_list_remove (plist, content_type);
+
+
+void
+rspamd_part_set_encoding (mime_part, encoding)
+ Mail::Rspamd::Part mime_part
+ Mail::Rspamd::PartEncodingType encoding
+ CODE:
+ g_mime_part_set_encoding (mime_part, encoding);
+
+Mail::Rspamd::PartEncodingType
+rspamd_part_get_encoding (mime_part)
+ Mail::Rspamd::Part mime_part
+ CODE:
+ RETVAL = g_mime_part_get_encoding (mime_part);
+ OUTPUT:
+ RETVAL
+
+const char *
+rspamd_part_encoding_to_string (encoding)
+ Mail::Rspamd::PartEncodingType encoding
+ CODE:
+ RETVAL = g_mime_part_encoding_to_string (encoding);
+ OUTPUT:
+ RETVAL
+
+Mail::Rspamd::PartEncodingType
+rspamd_part_encoding_from_string (encoding)
+ const char * encoding
+ CODE:
+ RETVAL = g_mime_part_encoding_from_string(encoding);
+ OUTPUT:
+ RETVAL
+
+void
+rspamd_part_add_content_disposition_parameter (mime_part, name, value)
+ Mail::Rspamd::Part mime_part
+ const char * name
+ const char * value
+ CODE:
+ g_mime_part_add_content_disposition_parameter (mime_part, name, value);
+
+const char *
+rspamd_part_get_content_disposition_parameter (mime_part, name)
+ Mail::Rspamd::Part mime_part
+ const char * name
+ CODE:
+ RETVAL = g_mime_part_get_content_disposition_parameter (mime_part, name);
+ OUTPUT:
+ RETVAL
+
+
+void
+rspamd_part_set_pre_encoded_content(mime_part, content, encoding)
+ Mail::Rspamd::Part mime_part
+ SV * content
+ Mail::Rspamd::PartEncodingType encoding
+ PREINIT:
+ char * data;
+ STRLEN len;
+ CODE:
+ data = SvPV (content, len);
+ g_mime_part_set_pre_encoded_content (mime_part, data, len, encoding);
+
+
+SV *
+rspamd_part_get_content(mime_part)
+ Mail::Rspamd::Part mime_part
+ PREINIT:
+ guint len;
+ const char * content_char;
+ SV * content;
+ CODE:
+ ST(0) = &PL_sv_undef;
+ if (!(mime_part->content) || !(mime_part->content->stream) ||
+ (content_char = g_mime_part_get_content(mime_part, &len)) == NULL) {
+ return;
+ }
+ content = sv_newmortal ();
+ SvUPGRADE (content, SVt_PV);
+ SvREADONLY_on (content);
+ SvPVX(content) = (char *) (content_char);
+ SvCUR_set (content, len);
+ SvLEN_set (content, 0);
+ SvPOK_only (content);
+ ST(0) = content;
+
diff --git a/perl/Rspamd/Task.xs b/perl/Rspamd/Task.xs
new file mode 100644
index 000000000..dec521660
--- /dev/null
+++ b/perl/Rspamd/Task.xs
@@ -0,0 +1,83 @@
+
+MODULE = Mail::Rspamd PACKAGE = Mail::Rspamd::Task PREFIX = rspamd_task_
+PROTOTYPES: DISABLE
+
+Mail::Rspamd::Message
+rspamd_task_get_message (task)
+ Mail::Rspamd::Task task
+ CODE:
+ RETVAL = task->message;
+ OUTPUT:
+ RETVAL
+
+void
+rspamd_task_set_message (message)
+ Mail::Rspamd::Message message
+ CODE:
+ g_object_unref (G_OBJECT(task->message));
+ task->message = message;
+
+SV*
+rspamd_task_ip (task)
+ Mail::Rspamd::Task task
+ CODE:
+ RETVAL = newSVpv (inet_ntoa (task->from_addr), 0);
+ OUTPUT:
+ RETVAL
+
+SV*
+rspamd_task_from (task)
+ Mail::Rspamd::Task task
+ CODE:
+ if (task->from == NULL) {
+ XSRETURN_UNDEF;
+ }
+ RETVAL = newSVpv (task->from, 0);
+ OUTPUT:
+ RETVAL
+
+void
+rspamd_task_save_point (task)
+ Mail::Rspamd::Task task
+ CODE:
+ task->save.saved = 1;
+
+void
+rspamd_task_recall_filter (task)
+ Mail::Rspamd::Task task
+ CODE:
+ process_filters (task);
+
+void
+rspamd_task_insert_result (task, metric, symbol, flag)
+ Mail::Rspamd::Task task
+ const char *metric
+ const char *symbol
+ double flag
+ CODE:
+ insert_result (task, metric, symbol, flag);
+
+Mail::Rspamd::Conf
+rspamd_task_get_conf (task)
+ Mail::Rspamd::Task task
+ CODE:
+ RETVAL = task->cfg;
+ OUTPUT:
+ RETVAL
+
+AV*
+rspamd_task_get_urls (task)
+ Mail::Rspamd::Task task
+ PREINIT:
+ AV* retav;
+ struct uri *url;
+ CODE:
+ retav = newAV ();
+ TAILQ_FOREACH (url, &task.urls, next) {
+ av_push (retav, newSVpv ((char *)g_strdup (struri (url)), 0));
+ }
+
+ RETVAL = retav;
+ OUTPUT:
+ RETVAL
+
diff --git a/perl/rspamd.xs b/perl/rspamd.xs
deleted file mode 100644
index c7e1ae776..000000000
--- a/perl/rspamd.xs
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
- * Perl XS module for interacting with rspamd
- *
- * vi:ts=4
- */
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <EXTERN.h>
-#include <perl.h>
-#include <XSUB.h>
-#include <glib.h>
-
-#include "../src/config.h"
-#include "../src/main.h"
-#include "../src/message.h"
-#include "../src/cfg_file.h"
-#include "../src/perl.h"
-#include "../src/mem_pool.h"
-
-#define perl_set_session(r) \
- r = INT2PTR(struct worker_task *, SvIV((SV *) SvRV(ST(0))))
-
-#define perl_set_config(r) \
- r = INT2PTR(struct config_file *, 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_task PREFIX = rspamd_task_
-PROTOTYPES: DISABLE
-
-void
-rspamd_task_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 {
- perl_set_targ (s, strlen (s));
- ST(0) = TARG;
- }
-
-void
-rspamd_task_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 *
-rspamd_task_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;
- }
-
- part = g_list_nth_data (r->parts, number);
- RETVAL = newHV();
- type = g_mime_content_type_to_string (part->type);
-
- (void)hv_store_ent (RETVAL,
- newSVpv ("type", sizeof ("type") - 1),
- newSVpv (type, strlen(type)), 0);
- (void)hv_store_ent (RETVAL,
- newSVpv ("content", sizeof ("content") - 1),
- newSVpv ((char *)part->content->data, part->content->len), 0);
- sv_2mortal((SV*)RETVAL);
- OUTPUT:
- RETVAL
-
-void
-rspamd_task_ip (r)
- CODE:
- dXSTARG;
- struct worker_task *r;
- char *ip_str;
-
- perl_set_session (r);
- sv_upgrade(TARG, SVt_PV);
- ip_str = inet_ntoa (r->from_addr);
- sv_setpv(TARG, ip_str);
- ST(0) = TARG;
-
-void
-rspamd_task_from (r)
- CODE:
- dXSTARG;
- struct worker_task *r;
-
- perl_set_session (r);
- if (r->from == NULL) {
- XSRETURN_UNDEF;
- }
- sv_upgrade(TARG, SVt_PV);
- sv_setpv(TARG, r->from);
- ST(0) = TARG;
-
-void
-rspamd_task_save_point (r)
- CODE:
- struct worker_task *r;
-
- perl_set_session (r);
- r->save.saved = 1;
-
-void
-rspamd_task_recall_filter (r)
- CODE:
- struct worker_task *r;
-
- perl_set_session (r);
- process_filters (r);
-
-void
-rspamd_task_insert_result (r, metric, symbol, flag)
- CODE:
- struct worker_task *r;
- char *metric, *symbol;
- int flag;
-
- perl_set_session (r);
- metric = (char *) SvPV_nolen (ST(1));
- symbol = (char *) SvPV_nolen (ST(2));
- flag = (int) SvIV (ST(3));
-
- insert_result (r, metric, symbol, flag);
-
-
-
-void
-rspamd_task_read_memcached_key (r, key, datalen, callback)
- CODE:
- struct worker_task *r;
- char *key;
- unsigned int datalen;
- SV *callback;
- struct _param {
- SV *callback;
- struct worker_task *task;
- } *callback_data;
- memcached_ctx_t *ctx;
- memcached_param_t param;
-
- perl_set_session (r);
- key = (char *) SvPV_nolen (ST(1));
- datalen = (unsigned int) SvIV (ST(2));
- callback = SvRV(ST(3));
-
- /* Copy old ctx to new one */
- ctx = memory_pool_alloc (r->task_pool, sizeof (memcached_ctx_t));
- if (ctx == NULL) {
- XSRETURN_UNDEF;
- }
- memcpy (ctx, r->memc_ctx, sizeof (memcached_ctx_t));
- /* Set perl callback */
- ctx->callback = perl_call_memcached_callback;
- callback_data = memory_pool_alloc (r->task_pool, sizeof (struct _param));
- if (callback_data == NULL) {
- XSRETURN_UNDEF;
- }
- callback_data->callback = callback;
- callback_data->task = r;
- ctx->callback_data = (void *)callback_data;
-
- g_strlcpy (param.key, key, sizeof (param.key));
- param.buf = memory_pool_alloc (r->task_pool, datalen);
- if (param.buf != NULL) {
- param.bufsize = datalen;
- }
- param.bufpos = 0;
- param.expire = 0;
-
- memc_get (ctx, &param);
- /* Set save point */
- r->save.saved = 1;
- XSRETURN_EMPTY;
-
-void
-rspamd_task_write_memcached_key (r, key, data, expire, callback)
- CODE:
- struct worker_task *r;
- char *key, *data;
- SV *callback;
- STRLEN datalen;
- int expire;
- struct _param {
- SV *callback;
- struct worker_task *task;
- } *callback_data;
- memcached_ctx_t *ctx;
- memcached_param_t param;
-
- perl_set_session (r);
- key = (char *) SvPV_nolen (ST(1));
- data = (char *) SvPV (ST(2), datalen);
- expire = (int) SvIV (ST(3));
- callback = SvRV(ST(4));
-
- /* Copy old ctx to new one */
- ctx = memory_pool_alloc (r->task_pool, sizeof (memcached_ctx_t));
- if (ctx == NULL) {
- XSRETURN_UNDEF;
- }
- memcpy (ctx, r->memc_ctx, sizeof (memcached_ctx_t));
- /* Set perl callback */
- ctx->callback = perl_call_memcached_callback;
- callback_data = memory_pool_alloc (r->task_pool, sizeof (struct _param));
- if (callback_data == NULL) {
- XSRETURN_UNDEF;
- }
- callback_data->callback = callback;
- callback_data->task = r;
- ctx->callback_data = (void *)callback_data;
-
- g_strlcpy (param.key, key, sizeof (param.key));
- param.buf = data;
- param.bufsize = datalen;
- param.bufpos = 0;
- param.expire = expire;
-
- memc_set (ctx, &param, expire);
- /* Set save point */
- r->save.saved = 1;
- XSRETURN_EMPTY;
-
-void
-rspamd_task_delete_memcached_key (r, key, callback)
- CODE:
- struct worker_task *r;
- char *key;
- SV *callback;
- struct _param {
- SV *callback;
- struct worker_task *task;
- } *callback_data;
- memcached_ctx_t *ctx;
- memcached_param_t param;
-
- perl_set_session (r);
- key = (char *) SvPV_nolen (ST(1));
- callback = SvRV (ST(2));
-
- /* Copy old ctx to new one */
- ctx = memory_pool_alloc (r->task_pool, sizeof (memcached_ctx_t));
- if (ctx == NULL) {
- XSRETURN_UNDEF;
- }
- memcpy (ctx, r->memc_ctx, sizeof (memcached_ctx_t));
- /* Set perl callback */
- ctx->callback = perl_call_memcached_callback;
- callback_data = memory_pool_alloc (r->task_pool, sizeof (struct _param));
- if (callback_data == NULL) {
- XSRETURN_UNDEF;
- }
- callback_data->callback = callback;
- callback_data->task = r;
- ctx->callback_data = (void *)callback_data;
-
- g_strlcpy (param.key, key, sizeof (param.key));
- param.buf = NULL;
- param.bufsize = 0;
- param.bufpos = 0;
- param.expire = 0;
-
- memc_delete (ctx, &param);
- /* Set save point */
- r->save.saved = 1;
- XSRETURN_EMPTY;
-
-void
-rspamd_task_get_conf (r)
-CODE:
- struct worker_task *r;
- dXSTARG;
-
- perl_set_session (r);
-
- sv_setref_pv (TARG, "rspamd_config", r->cfg);
- ST(0) = TARG;
-
-
-MODULE = rspamd PACKAGE = rspamd_config PREFIX = rspamd_config_
-PROTOTYPES: DISABLE
-
-void
-rspamd_config_get_scalar (r, param)
-CODE:
- struct config_file *r;
- struct config_scalar *sc;
- char *param;
- int val;
- dXSTARG;
-
- perl_set_config (r);
- param = (char *) SvPV_nolen (ST(1));
-
- sc = g_hash_table_lookup (r->cfg_params, param);
- if (sc == NULL) {
- XSRETURN_UNDEF;
- }
- else {
- switch (sc->type) {
- case SCALAR_TYPE_SIZE:
- val = (int)(*(size_t *)sc->pointer);
- sv_upgrade (TARG, SVt_IV);
- sv_setiv (TARG, val);
- break;
- case SCALAR_TYPE_INT:
- case SCALAR_TYPE_UINT:
- val = *(int *)sc->pointer;
- sv_upgrade (TARG, SVt_IV);
- sv_setiv (TARG, val);
- break;
- case SCALAR_TYPE_STR:
- sv_upgrade (TARG, SVt_PV);
- SvPOK_on(TARG);
- sv_setpv (TARG, (char *)sc->pointer);
- break;
- }
- }
- ST(0) = TARG;
-
-void
-rspamd_config_set_scalar (r, param, value)
-CODE:
- struct config_file *r;
- struct config_scalar *sc;
- char *param, *charval;
- int intval;
- dXSTARG;
-
- perl_set_config (r);
- param = (char *) SvPV_nolen (ST(1));
-
- sc = g_hash_table_lookup (r->cfg_params, param);
- if (sc == NULL) {
- XSRETURN_UNDEF;
- }
- else {
- switch (sc->type) {
- case SCALAR_TYPE_SIZE:
- intval = (int)SvIV (ST(2));
- *((size_t *)sc->pointer) = intval;
- sv_upgrade (TARG, SVt_IV);
- sv_setiv (TARG, intval);
- break;
- case SCALAR_TYPE_INT:
- case SCALAR_TYPE_UINT:
- intval = (int)SvIV (ST(2));
- *((int *)sc->pointer) = intval;
- sv_upgrade (TARG, SVt_IV);
- sv_setiv (TARG, intval);
- break;
- case SCALAR_TYPE_STR:
- charval = (char *)SvPVX (ST(2));
- *((char **)sc->pointer) = charval;
- sv_upgrade (TARG, SVt_PV);
- sv_setpv (TARG, charval);
- break;
- }
- }
- ST(0) = TARG;
-
-HV *
-rspamd_config_set_metric (r, name)
-CODE:
- struct config_file *r;
- struct metric *val;
- char *name;
-
- perl_set_config (r);
- name = (char *) SvPV_nolen (ST(1));
-
- val = g_hash_table_lookup (r->metrics, name);
- if (val == NULL) {
- XSRETURN_UNDEF;
- }
- else {
- RETVAL = newHV();
-
- (void)hv_store_ent (RETVAL,
- newSVpv ("name", sizeof ("name") - 1),
- newSVpv (val->name, strlen (val->name)), 0);
- (void)hv_store_ent (RETVAL,
- newSVpv ("func_name", sizeof ("func_name") - 1),
- newSVpv (val->func_name, strlen (val->func_name)), 0);
- (void)hv_store_ent (RETVAL,
- newSVpv ("required_score", sizeof ("required_score") - 1),
- newSVnv (val->required_score), 0);
- sv_2mortal((SV*)RETVAL);
- }
-OUTPUT:
- RETVAL
-
-HV *
-rspamd_config_set_statfile (r, name)
-CODE:
- struct config_file *r;
- struct statfile *val;
- char *name;
-
- perl_set_config (r);
- name = (char *) SvPV_nolen (ST(1));
-
- val = g_hash_table_lookup (r->statfiles, name);
- if (val == NULL) {
- XSRETURN_UNDEF;
- }
- else {
- RETVAL = newHV();
-
- (void)hv_store_ent (RETVAL,
- newSVpv ("alias", sizeof ("alias") - 1),
- newSVpv (val->alias, strlen (val->alias)), 0);
- (void)hv_store_ent (RETVAL,
- newSVpv ("pattern", sizeof ("pattern") - 1),
- newSVpv (val->pattern, strlen (val->pattern)), 0);
- (void)hv_store_ent (RETVAL,
- newSVpv ("metric", sizeof ("metric") - 1),
- newSVpv (val->metric, strlen (val->metric)), 0);
- (void)hv_store_ent (RETVAL,
- newSVpv ("weight", sizeof ("weight") - 1),
- newSVnv (val->weight), 0);
- (void)hv_store_ent (RETVAL,
- newSVpv ("size", sizeof ("size") - 1),
- newSViv (val->size), 0);
- sv_2mortal((SV*)RETVAL);
- }
-OUTPUT:
- RETVAL
-
-void
-rspamd_config_get_module_param (r, modulename, paramname)
- CODE:
- struct config_file *r;
- char *module, *param, *value;
-
- dXSTARG;
- perl_set_config (r);
- module = (char *) SvPV_nolen (ST(1));
- param = (char *) SvPV_nolen (ST(2));
-
- value = get_module_opt (r, module, param);
- if (value == NULL) {
- XSRETURN_UNDEF;
- }
-
- sv_upgrade(TARG, SVt_PV);
- sv_setpv(TARG, value);
-
- ST(0) = TARG;
-
-MODULE = rspamd PACKAGE = rspamd_log PREFIX = rspamd_log_
-PROTOTYPES: DISABLE
-
-void
-rspamd_log_log (level, str)
- CODE:
- int level;
- char *str;
-
- level = (int)SvIV (ST(0));
- str = (char *)SvPV_nolen (ST(1));
-
- g_log (G_LOG_DOMAIN, level, "%s", str);
- XSRETURN_EMPTY;
-
diff --git a/perl/typemap b/perl/typemap
index cdf52b17c..fa2dabb43 100644
--- a/perl/typemap
+++ b/perl/typemap
@@ -1,4 +1,27 @@
TYPEMAP
-rspamd_task T_PTROBJ
-rspamd_config T_PTROBJ
+gint T_IV
+guint T_UV
+guint32 T_UV
+off_t T_IV
+gboolean T_BOOL
+gpointer T_PTR
+
+unsigned char * T_PV
+const unsigned char * T_PV
+const char * T_PV
+
+# enums
+Mail::Rspamd::PartEncodingType T_IV
+Mail::Rspamd::InternetAddressType T_IV
+
+# types
+Mail::Rspamd::Object T_PTROBJ
+Mail::Rspamd::Param T_PTROBJ
+Mail::Rspamd::Message T_PTROBJ
+Mail::Rspamd::Part T_PTROBJ
+Mail::Rspamd::ContentType T_PTROBJ
+Mail::Rspamd::InternetAddress T_PTROBJ
+Mail::Rspamd::Hash::Header T_PTROBJ
+
+const Mail::Rspamd::Part::EncodingType T_IV