]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
* Completely rewrite and reorganize perl API
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Thu, 26 Feb 2009 15:09:28 +0000 (18:09 +0300)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Thu, 26 Feb 2009 15:09:28 +0000 (18:09 +0300)
* 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

15 files changed:
CMakeLists.txt
perl/Makefile.PL.in
perl/Rspamd.pm [moved from perl/rspamd.pm with 92% similarity]
perl/Rspamd.pod [new file with mode: 0644]
perl/Rspamd.xs [new file with mode: 0644]
perl/Rspamd/Config.xs [new file with mode: 0644]
perl/Rspamd/ContentType.xs [new file with mode: 0644]
perl/Rspamd/Hash.xs [new file with mode: 0644]
perl/Rspamd/InternetAddress.xs [new file with mode: 0644]
perl/Rspamd/Message.xs [new file with mode: 0644]
perl/Rspamd/Object.xs [new file with mode: 0644]
perl/Rspamd/Part.xs [new file with mode: 0644]
perl/Rspamd/Task.xs [new file with mode: 0644]
perl/rspamd.xs [deleted file]
perl/typemap

index 7a1031b937fa94147c085a3ed66c2c77e41e3282..853169bff93bbb4d0984224b50d79ebeb09405b2 100644 (file)
@@ -308,3 +308,7 @@ SET_TARGET_PROPERTIES(utils/url-extracter PROPERTIES COMPILE_FLAGS ${PERL_CFLAGS
 TARGET_LINK_LIBRARIES(utils/url-extracter ${GLIB2_LIBRARIES})
 TARGET_LINK_LIBRARIES(utils/url-extracter event)
 TARGET_LINK_LIBRARIES(utils/url-extracter ${GMIME2_LIBRARIES})
+
+INSTALL(TARGETS rspamd utils/url-extracter RUNTIME DESTINATION bin)
+INSTALL(PROGRAMS rspamc.pl DESTINATION bin RENAME rspamc)
+INSTALL(CODE "EXECUTE_PROCESS(COMMAND make install WORKING_DIRECTORY perl)")
index 502e842279178837e1f2ce2ff9d9a193edb90c6d..0d70d427032681057e604dacfe00d8ae49913b3a 100644 (file)
@@ -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
+},
+       },
 );
 
similarity index 92%
rename from perl/rspamd.pm
rename to perl/Rspamd.pm
index 6048f1a3f016b43e6d6ccca4435b8778a7f191a7..2966cb3ca4ae9d2d4f9e8669aca090f4ca7e5c8b 100644 (file)
@@ -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 (file)
index 0000000..d405748
--- /dev/null
@@ -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 (file)
index 0000000..c6c33c0
--- /dev/null
@@ -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 (file)
index 0000000..49b26db
--- /dev/null
@@ -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 (file)
index 0000000..dae8a35
--- /dev/null
@@ -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 (file)
index 0000000..b61cebc
--- /dev/null
@@ -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 (file)
index 0000000..834117b
--- /dev/null
@@ -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 (file)
index 0000000..6e3a16d
--- /dev/null
@@ -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 (file)
index 0000000..89bc09b
--- /dev/null
@@ -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 (file)
index 0000000..b95a5fc
--- /dev/null
@@ -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 (file)
index 0000000..dec5216
--- /dev/null
@@ -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 (file)
index c7e1ae7..0000000
+++ /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;
-
index cdf52b17c72fac6b516d75f56428fbf0d1bee535..fa2dabb436cad740f07182507998537133955cb9 100644 (file)
@@ -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