summaryrefslogtreecommitdiff
path: root/fml
diff options
context:
space:
mode:
authorfukachan <fukachan>2006-05-13 11:45:40 +0000
committerfukachan <fukachan>2006-05-13 11:45:40 +0000
commite910a4f5d2e95a96b3fdac9b089fe32c3ebb0a16 (patch)
treeb9f853edb485c521d6cbc23058fd15e263c68549 /fml
parent4480917b1d0080b6d32dc6bd502945e596db0ba5 (diff)
downloadfml8-e910a4f5d2e95a96b3fdac9b089fe32c3ebb0a16.tar.gz
fml8-e910a4f5d2e95a96b3fdac9b089fe32c3ebb0a16.tar.bz2
fml8-e910a4f5d2e95a96b3fdac9b089fe32c3ebb0a16.zip
enable body based loop check
Diffstat (limited to 'fml')
-rw-r--r--fml/lib/FML/Body.pm200
-rw-r--r--fml/lib/FML/Process/Kernel.pm37
-rw-r--r--fml/lib/FML/Process/Utils.pm60
3 files changed, 295 insertions, 2 deletions
diff --git a/fml/lib/FML/Body.pm b/fml/lib/FML/Body.pm
new file mode 100644
index 00000000..97b05e3a
--- /dev/null
+++ b/fml/lib/FML/Body.pm
@@ -0,0 +1,200 @@
+#-*- perl -*-
+#
+# Copyright (C) 2006 Ken'ichi Fukamachi
+# All rights reserved. This program is free software; you can
+# redistribute it and/or modify it under the same terms as Perl itself.
+#
+# $FML: @template.pm,v 1.10 2006/01/07 13:16:41 fukachan Exp $
+#
+
+package FML::Body;
+use strict;
+use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD);
+use Carp;
+
+=head1 NAME
+
+FML::Body - operations for mail body.
+
+=head1 SYNOPSIS
+
+=head1 DESCRIPTION
+
+=head1 METHODS
+
+=head2 new()
+
+constructor.
+
+=cut
+
+
+# Descriptions: constructor
+# Arguments: OBJ($self) OBJ($curproc)
+# Side Effects: none
+# Return Value: OBJ
+sub new
+{
+ my ($self, $curproc) = @_;
+ my ($type) = ref($self) || $self;
+ my $me = { _curproc => $curproc };
+ return bless $me, $type;
+}
+
+
+# Descriptions: checksum of mail body part.
+# return 1 if the same checksum is found in the database.
+# Arguments: OBJ($self) OBJ($config)
+# Side Effects: update database.
+# Return Value: NUM
+sub check_body_checksum
+{
+ my ($self, $config) = @_;
+ my $curproc = $self->{ _curproc };
+ my $body_file = $curproc->incoming_message_print_body_as_file();
+
+ # calculate checksum of $body_file.
+ use Mail::Message::Checksum;
+ my $cksum = new Mail::Message::Checksum;
+ my $md5 = $cksum->md5_file($body_file);
+
+ # compare md5 value with the checksum database.
+ my $retval = 0;
+ my $db_dir = $config->{ incoming_mail_body_checksum_cache_dir };
+ my $db = $self->db_open( { directory => $db_dir } );
+ if (defined $db) {
+ if ($db->{ $md5 }) {
+ $retval = 1;
+ }
+ else {
+ $db->{ $md5 } = time;
+ $retval = 0;
+ }
+ $self->db_close();
+ }
+ return $retval;
+}
+
+
+=head1 DATABASE
+
+=head2 db_open($db_args)
+
+open database (journalized db).
+
+=head2 db_close($db_args)
+
+dummy.
+
+=cut
+
+
+# Descriptions: open database.
+# Arguments: OBJ($self) HASH_REF($db_args)
+# Side Effects: open database.
+# Return Value: HASH_ERF
+sub db_open
+{
+ my ($self, $db_args) = @_;
+ my $dir = $db_args->{ 'directory' } || '';
+ my $mode = 'temporal';
+ my $days = 14;
+
+ if ($dir) {
+ unless (-d $dir) {
+ # XXX-TODO: dir_mode is hard-coded ?
+ my $dir_mode = $self->{ _dir_mode } || 0700;
+
+ use File::Path;
+ mkpath( [ $dir ], 0, $dir_mode );
+ }
+
+ my %db = ();
+ use Tie::JournaledDir;
+ tie %db, 'Tie::JournaledDir', { dir => $dir };
+
+ $self->{ _db } = \%db;
+ return \%db;
+ }
+
+ return undef;
+}
+
+
+sub db_close
+{
+ ;
+}
+
+
+=head1 ACCESS METHODS
+
+=head2 set_checksum_type($type)
+
+set checksum method type.
+
+=head2 get_checksum_type()
+
+get checksum method type.
+return 'md5' by default.
+
+=cut
+
+
+my $global_default_checksum_type = 'md5';
+
+
+# Descriptions: set checksum method type.
+# Arguments: OBJ($self) STR($type)
+# Side Effects: update $self
+# Return Value: none
+sub set_checksum_type
+{
+ my ($self, $type) = @_;
+ my $curproc = $self->{ _curproc };
+
+ if ($type eq 'md5') {
+ $self->{ _type } = $type;
+ }
+ else {
+ $curproc->logerror("unsupported checksum: $type");
+ }
+}
+
+
+# Descriptions: return checksum method type.
+# Arguments: OBJ($self)
+# Side Effects: none
+# Return Value: STR
+sub get_checksum_type
+{
+ my ($self) = @_;
+
+ return( $self->{ _type } || $global_default_checksum_type );
+}
+
+
+=head1 CODING STYLE
+
+See C<http://www.fml.org/software/FNF/> on fml coding style guide.
+
+=head1 AUTHOR
+
+Ken'ichi Fukamachi
+
+=head1 COPYRIGHT
+
+Copyright (C) 2006 Ken'ichi Fukamachi
+
+All rights reserved. This program is free software; you can
+redistribute it and/or modify it under the same terms as Perl itself.
+
+=head1 HISTORY
+
+FML::Body appeared in fml8 mailing list driver package.
+See C<http://www.fml.org/> for more details.
+
+=cut
+
+
+1;
diff --git a/fml/lib/FML/Process/Kernel.pm b/fml/lib/FML/Process/Kernel.pm
index 45d2f7d9..56553981 100644
--- a/fml/lib/FML/Process/Kernel.pm
+++ b/fml/lib/FML/Process/Kernel.pm
@@ -4,7 +4,7 @@
# All rights reserved. This program is free software; you can
# redistribute it and/or modify it under the same terms as Perl itself.
#
-# $FML: Kernel.pm,v 1.282 2006/05/04 05:21:29 fukachan Exp $
+# $FML: Kernel.pm,v 1.283 2006/05/12 13:50:11 fukachan Exp $
#
package FML::Process::Kernel;
@@ -668,6 +668,9 @@ sub simple_loop_check
unless ($match) {
$match = $curproc->_header_based_loop_check();
}
+ unless ($match) {
+ $match = $curproc->_body_based_loop_check();
+ }
# $match contains the first matched rule name (== reason).
if ($match) {
@@ -742,6 +745,38 @@ sub _header_based_loop_check
}
+# Descriptions: body based loop check.
+# Arguments: OBJ($curproc)
+# Side Effects: none
+# Return Value: STR
+sub _body_based_loop_check
+{
+ my ($curproc) = @_;
+ my $config = $curproc->config();
+ my $match = undef;
+ my $var_rules = 'incoming_mail_body_loop_check_rules';
+
+ if ($config->yes('use_incoming_mail_body_loop_check')) {
+ use FML::Body;
+ my $body = new FML::Body $curproc;
+
+ my $rules = $config->get_as_array_ref($var_rules);
+ RULE:
+ for my $rule (@$rules) {
+ if ($body->can($rule)) {
+ $match = $body->$rule($config) ? $rule : undef;
+ }
+ else {
+ $curproc->logwarn("body->${rule}() is undefined");
+ }
+ last RULE if $match;
+ }
+ }
+
+ return $match;
+}
+
+
# Descriptions: commit message-id cache update transaction.
# Arguments: OBJ($curproc)
# Side Effects: update cache.
diff --git a/fml/lib/FML/Process/Utils.pm b/fml/lib/FML/Process/Utils.pm
index 898a8382..f74c6f90 100644
--- a/fml/lib/FML/Process/Utils.pm
+++ b/fml/lib/FML/Process/Utils.pm
@@ -4,7 +4,7 @@
# All rights reserved. This program is free software; you can
# redistribute it and/or modify it under the same terms as Perl itself.
#
-# $FML: Utils.pm,v 1.148 2006/02/15 13:44:04 fukachan Exp $
+# $FML: Utils.pm,v 1.149 2006/04/22 08:29:23 fukachan Exp $
#
package FML::Process::Utils;
@@ -329,6 +329,64 @@ sub incoming_message_remove_queue
}
+=head2 incoming_message_print_body_as_file()
+
+dupliate the body part into a temporary file.
+return a newly created temporary file path.
+
+=cut
+
+
+# Descriptions: dupliate the body part into a temporary file.
+# Arguments: OBJ($curproc) OBJ($queue)
+# Side Effects: create a temporary file.
+# Return Value: STR
+sub incoming_message_print_body_as_file
+{
+ my ($curproc, $queue) = @_;
+ my $cache_file = $curproc->incoming_message_get_cache_file_path();
+ my $tmp_file = $curproc->tmp_file_path();
+
+ if (-f $cache_file) {
+ my $rh = new FileHandle $cache_file;
+ my $wh = new FileHandle "> $tmp_file";
+ if (defined $rh && defined $wh) {
+ my $found = 0;
+ my $buf;
+ LINE:
+ while ($buf = <$rh>) {
+ unless ($found) {
+ if ($buf =~ /^$/o) {
+ $found = 1;
+ }
+ next LINE;
+ }
+ print $wh $buf;
+ }
+ $wh->close();
+ $rh->close();
+
+ return $tmp_file;
+ }
+ else {
+ my $myname = "incoming_message_dup_body";
+ unless (defined $rh) {
+ $curproc->logerror("$myname: cannot open $cache_file");
+ }
+ unless (defined $wh) {
+ $curproc->logerror("$myname: cannot open $tmp_file");
+ }
+
+ return undef;
+ }
+ }
+ else {
+ $curproc->logerror("incoming_message_dup_body: no cache");
+ return undef;
+ }
+}
+
+
=head1 access METHODS to handle article
available only in C<libexec/distribute> process.