# Configuration and some common code use vars qw($pts_dir $spool_dir $conf_sub_template $db_filename $db_tags_filename $conf_unsub_template $conf_unsuball_template $sendmail $sendmaildefault $sendmailnobody $sources $pts_email @available_tags @default_tags %db_content $db %db_tags_content $db_tags %db_bounces_content $db_bounces %bin2src %src $open_count); # Configuration variables $pts_dir = "/org/packages.qa.debian.org"; $spool_dir = "$pts_dir/spool"; $conf_sub_template = "$pts_dir/etc/conf_tpl.txt"; $conf_unsub_template = "$pts_dir/etc/conf_unsub_tpl.txt"; $conf_unsuball_template = "$pts_dir/etc/conf_unsuball_tpl.txt"; $db_filename = "$pts_dir/db/subscription.db"; $db_tags_filename = "$pts_dir/db/tags.db"; $db_bounces_filename = "$pts_dir/db/bounces.db"; $sendmail = '/usr/sbin/sendmail'; $sendmaildefault = '/usr/sbin/sendmail -f bounces@packages.qa.debian.org'; $sendmailnobody = '/usr/sbin/sendmail -f bounces-likely-spam@packages.qa.debian.org'; $sources = "/org/packages.qa.debian.org/www/incoming/sources"; $pts_email = 'pts@qa.debian.org'; @available_tags = qw(default bts bts-control cvs summary ddtp upload-source upload-binary katie-other derivatives); @default_tags = qw(default bts bts-control summary upload-source katie-other); # Global variables %db_content = (); $db = undef; %db_tags_content = (); $db_tags = undef; %db_bounces_content = (); $db_bounces = undef; %bin2src = (); %src = (); $open_count = 0; # Common code sub open_db_write { $DB_BTREE->{'flags'} = R_DUP; if ($open_count <= 0) { $db = tie %db_content, "DB_File", $db_filename, O_RDWR|O_CREAT, 0660, $DB_BTREE or die "Can't open database $db_filename : $!\n"; $db_tags = tie %db_tags_content, "DB_File", $db_tags_filename, O_RDWR|O_CREAT, 0660, $DB_HASH or die "Can't open database $db_tags_filename : $!\n"; } $open_count++; } sub open_db_read { $DB_BTREE->{'flags'} = R_DUP; if ($open_count <= 0) { if (-f $db_filename and -f $db_tags_filename) { $db = tie %db_content, "DB_File", $db_filename, O_RDONLY, 0660, $DB_BTREE or die "Can't open database $db_filename : $!\n"; $db_tags = tie %db_tags_content, "DB_File", $db_tags_filename, O_RDONLY, 0660, $DB_HASH or die "Can't open database $db_tags_filename : $!\n"; } else { open_db_write(); } } $open_count++; } sub close_db { $open_count--; if ($open_count <= 0) { undef $db; untie %db_content; undef $db_tags; untie %db_tags_content; } } sub open_db_bounces { $db_bounces = tie %db_bounces_content, "DB_File", $db_bounces_filename, O_RDWR|O_CREAT, 0660, $DB_HASH or die "Can't open database $db_bounces_filename : $!\n"; } sub close_db_bounces { undef $db_bounces; untie %db_bounces_content; } sub update_bounces_db { my ($date, $email, $sent) = @_; # $sent: 1=>new mail sent, 0=> bounces received my @stats = split(" ", $db_bounces_content{$email}); my $found = 0; for(my $i = 0; $i < scalar(@stats); $i += 3) { if ($stats[$i] eq $date) { if ($found) { $stats[$i+1]++; } else { $stats[$i+2]++; } $found = 1; } } if ($sent && (!$found)) { push @stats, $date, 1, 0; } if (scalar(@stats) > 12) { shift @stats; shift @stats; shift @stats; } $db_bounces_content{$email} = join(" ", @stats); } sub has_too_many_bounces { my ($email) = @_; my @stats = split(" ", $db_bounces_content{$email}); my $count = 0; for(my $i = 0; $i < scalar(@stats); $i += 3) { if ($stats[$i+2] >= $stats[$i+1]) { $count++; } } return ($count >= 3) ? 1: 0; } sub subscribe { my ($address, $package) = @_; open_db_write(); my @emails = $db->get_dup($package); my $found = 0; foreach (@emails) { $found = 1 if ($_ eq $address); } $db_content{$package} = $address if (! $found); close_db(); return ! $found; } sub unsubscribe { my ($address, $package) = @_; my $ok = 1; open_db_write(); if ($db->find_dup($package, $address) == 0) { $db->del_dup($package, $address); } else { $ok = 0; } close_db(); return $ok; } sub which { my ($address) = @_; my @l; my %seen; open_db_read(); foreach my $p (keys %db_content) { next if (exists $seen{$p}); $seen{$p} = 1; my %list = $db->get_dup($p, 1); if ((exists $list{lc($address)}) && $list{lc($address)}) { push @l, $p; } } close_db(); return @l; } sub list { my ($package) = @_; open_db_read(); my @l = $db->get_dup($package); close_db(); return @l; } sub load_sources { return if (scalar(keys %bin2src)); open(SOURCES, "< $sources") || warn "Can't open $sources: $!\n"; while(defined($_=)) { my ($bin, $comp, $src) = (split(/\s+/)); $bin2src{lc($bin)} = lc($src); $src{lc($src)} = 1; } close(SOURCES); } sub map_package { my ($pkg) = @_; my ($package, @msg); load_sources(); if (exists $src{$pkg}) { $package = $pkg; } elsif (exists $bin2src{$pkg}) { $package = $bin2src{$pkg}; push @msg, "$pkg is not a source package. However $package is \n"; push @msg, "the source package for the $pkg binary package.\n"; push @msg, "\n"; } else { $package = $pkg; push @msg, "$pkg is neither a source package nor a binary package. \n"; push @msg, "It may be a 'pseudo package' or a mistake...\n"; push @msg, "\n"; } return ($package, @msg); } sub available_tags { return @available_tags; } sub is_valid_tag { my ($tag) = @_; $tag = lc($tag); foreach (available_tags()) { return 1 if ($tag eq $_); } return 0; } sub clean_tags { my %h; foreach (@_) { $h{lc($_)} = 1 } return grep { defined($h{$_}) && $h{$_} } available_tags(); } sub get_default_tags { my ($email) = @_; $email = lc($email); open_db_read(); my @res; if (exists $db_tags_content{$email}) { @res = split(/,/, $db_tags_content{$email}); } else { @res = @default_tags; } close_db(); return @res; } sub set_default_tags { my ($email, @tags) = @_; open_db_write(); $db_tags_content{lc($email)} = join(",", clean_tags(@tags)); close_db(); } sub get_tags { my ($email, $package) = @_; $email = lc($email); $package = lc($package); open_db_read(); my @res; if (exists $db_tags_content{"$email#$package"}) { @res = split(/,/, $db_tags_content{"$email#$package"}); } elsif (exists $db_tags_content{$email}) { @res = split(/,/, $db_tags_content{$email}); } else { @res = @default_tags; } close_db(); return @res; } sub set_tags { my ($email, $package, @tags) = @_; open_db_write(); $db_tags_content{lc("$email#$package")} = join(",", clean_tags(@tags)); close_db(); } 1;