package SyslogScan::SendmailLineTrans;
$VERSION = 0.23;
sub Version { $VERSION };
@ISA = qw ( SyslogScan::SendmailLine );
use SyslogScan::SendmailLineFrom;
use SyslogScan::SendmailLineTo;
use SyslogScan::SendmailLineClone;
use strict;
# pUnbalancedParen: pointer to static function to check if there are
# different ('s than )'s in a given string.
my $pUnbalancedParen = sub {
my($stringToCheck) = @_;
my($left, $right) = (0,0);
my @eachChar;
# short-circuit for efficiency
return '' unless $stringToCheck =~ /[\(\)]/;
@eachChar = split(/ */, $stringToCheck);
grep($_ eq '(' && $left++,@eachChar);
grep($_ eq ')' && $right++,@eachChar);
return 't' if $left != $right;
'';
};
# TODO: change attrHash to toHash or fromHash
# parseFromOrTo: parse a message like:
# to=bar@foo.org,baz@foo.org, delay=03:50:20, mailer=smtp,
# relay=relay.uthbar.com [128.206.5.3],
# stat=Sent (May, have (embedded, commas)), or even, from=line
# or
# stat=Deferred: 451 collect: unexpected close, from=<foo@bar.com>: Host down
sub parseContent
{
my($self) = @_;
my($attr) = $$self{"attrListString"};
undef $$self{"attrListString"};
my($clonedFrom);
# check if this is a clone line
if ($attr =~ /^clone ([^,]+), (.+)/)
{
$clonedFrom = $1;
$attr = $2;
}
# clear out trailing stat line:
my $stat;
if ($attr =~ s/, (stat=.+, [^\)]+)$//)
{
$stat = $1;
print STDERR "interpreting $1 as a single stat attribute\n"
unless $::gbQuiet;
}
my(@attrList) = split(', ',$attr);
push(@attrList,$stat) if defined $stat;
# Suppose $attr was "foo=bar, uth=(bar, baz)"
# @attrList will be
# ("foo=bar", "uth=(bar", "baz)")
# which is not what we want.
# @completeAttrList will be
# ("foo=bar", "uth=(bar, baz)")
# which is how we want to parse sendmail log lines.
my ($attribute, @completeAttrList);
while ($attribute = shift @attrList)
{
while (&$pUnbalancedParen($attribute))
{
die "unbalanced parens in $attribute" unless @attrList;
$attribute .= (", " . shift @attrList);
}
unshift @completeAttrList, $attribute;
}
my (%attrHash);
eval {%attrHash = _listToHash $self @completeAttrList};
if ($@)
{
die $@ unless $@ =~ /equals not found/;
undef $@;
return; # generic SendmailTrans line
}
$$self{"attrHash"} = \%attrHash;
if (defined $clonedFrom)
{
$$self{clonedFrom} = $clonedFrom;
bless ($self, "SyslogScan::SendmailLineClone");
return $self -> SyslogScan::SendmailLineClone::parseContent;
}
if (defined $attrHash{"from"})
{
bless($self, "SyslogScan::SendmailLineFrom");
return $self -> SyslogScan::SendmailLineFrom::parseContent;
}
if (defined $attrHash{"to"})
{
bless($self, "SyslogScan::SendmailLineTo");
return $self -> SyslogScan::SendmailLineTo::parseContent;
}
return; #generic unsupported line with message ID
}
# _listToHash: transforms list of equations like
# ("foo=bar", "uth=fod=baz")
# into perl hash table like
# ("foo" => "bar", "uth" => "fod=baz")
sub _listToHash
{
my ($self, @list) = @_;
my (%hash);
foreach (@list)
{
s/\'/\"/g; # TODO: remove this eroot-compatibility hack
die "equals not found in $_" unless /([^=]+)=(.+)/;
$hash{$1} = $2;
}
%hash;
}
syntax highlighted by Code2HTML, v. 0.9.1