diff options
author | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2009-02-26 18:09:28 +0300 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2009-02-26 18:09:28 +0300 |
commit | cfb5348f75790ef694edd5a9c131890eeceec204 (patch) | |
tree | 55c6bc5ff03a346ced6008dcae0a70ba6b36fb32 /perl | |
parent | 5d77f4552b6e39ab1072d2c91b219dac2498ac88 (diff) | |
download | rspamd-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.in | 16 | ||||
-rw-r--r-- | perl/Rspamd.pm (renamed from perl/rspamd.pm) | 4 | ||||
-rw-r--r-- | perl/Rspamd.pod | 562 | ||||
-rw-r--r-- | perl/Rspamd.xs | 324 | ||||
-rw-r--r-- | perl/Rspamd/Config.xs | 141 | ||||
-rw-r--r-- | perl/Rspamd/ContentType.xs | 87 | ||||
-rw-r--r-- | perl/Rspamd/Hash.xs | 258 | ||||
-rw-r--r-- | perl/Rspamd/InternetAddress.xs | 124 | ||||
-rw-r--r-- | perl/Rspamd/Message.xs | 264 | ||||
-rw-r--r-- | perl/Rspamd/Object.xs | 152 | ||||
-rw-r--r-- | perl/Rspamd/Part.xs | 160 | ||||
-rw-r--r-- | perl/Rspamd/Task.xs | 83 | ||||
-rw-r--r-- | perl/rspamd.xs | 501 | ||||
-rw-r--r-- | perl/typemap | 27 |
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, ¶m); - /* 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, ¶m, 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, ¶m); - /* 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 |