fix #2709: ruledb: match-field: optionally restrict to top mime-part

The current Match Field (header) what-objects always traverse each
mime-part of a mail.
This can be inconvenient, and causes unexpected matches when you
forward a message as attachment(message/rfc822).

following the patches for adding a Disclaimer on top of a mail from an
implementation point of view, this simply adds an optional
top-level-only attribute for the MatchField object, which is disabled
by default for backwards-compatibility.

Tested-by: Dominik Csapak <d.csapak@proxmox.com>
Reviewed-by: Dominik Csapak <d.csapak@proxmox.com>
Tested-by: Friedrich Weber <f.weber@proxmox.com>
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
This commit is contained in:
Stoiko Ivanov 2025-02-21 17:48:18 +01:00 committed by Thomas Lamprecht
parent af418f434b
commit b961581e83
2 changed files with 45 additions and 4 deletions

View File

@ -35,7 +35,7 @@ sub new {
$fvalue = $nt;
}
my $self = $class->SUPER::new('content-type', $fvalue, $ogroup);
my $self = $class->SUPER::new('content-type', $fvalue, $ogroup, undef);
$self->{only_content} = $only_content;
return $self;

View File

@ -27,7 +27,7 @@ sub otype_text {
}
sub new {
my ($type, $field, $field_value, $ogroup) = @_;
my ($type, $field, $field_value, $ogroup, $top_part_only) = @_;
my $class = ref($type) || $type;
@ -35,6 +35,7 @@ sub new {
$self->{field} = $field;
$self->{field_value} = $field_value;
$self->{top_part_only} = $top_part_only;
return $self;
}
@ -54,12 +55,28 @@ sub load_attr {
my $decoded_field_value = PMG::Utils::try_decode_utf8($field_value);
# use known constructor, bless afterwards (because sub class can have constructor
# with other parameter signature).
my $obj = PMG::RuleDB::MatchField->new($field, $decoded_field_value, $ogroup);
my $obj = PMG::RuleDB::MatchField->new($field, $decoded_field_value, $ogroup, undef);
bless $obj, $class;
my $sth = $ruledb->{dbh}->prepare(
"SELECT * FROM Attribut WHERE Object_ID = ?");
$sth->execute($id);
$obj->{top_part_only} = 0;
while (my $ref = $sth->fetchrow_hashref()) {
if ($ref->{name} eq 'top_part_only') {
$obj->{top_part_only} = $ref->{value};
}
}
$sth->finish();
$obj->{id} = $id;
$obj->{digest} = Digest::SHA::sha1_hex($id, $field, $field_value, $ogroup);
$obj->{digest} = Digest::SHA::sha1_hex(
$id, $field, $field_value, $ogroup, $obj->{top_part_only});
return $obj;
}
@ -79,6 +96,9 @@ sub save {
if (defined ($self->{id})) {
# update
$ruledb->{dbh}->do(
"DELETE FROM Attribut WHERE Object_ID = ?",
undef, $self->{id});
$ruledb->{dbh}->do(
"UPDATE Object SET Value = ? WHERE ID = ?",
@ -96,6 +116,12 @@ sub save {
$self->{id} = PMG::Utils::lastid($ruledb->{dbh}, 'object_id_seq');
}
if (defined($self->{top_part_only})) {
$ruledb->{dbh}->do(
"INSERT INTO Attribut (Value, Name, Object_ID) VALUES (?, 'top_part_only', ?)",
undef, $self->{top_part_only}, $self->{id});
}
return $self->{id};
}
@ -124,6 +150,8 @@ sub parse_entity {
}
}
return $res if $self->{top_part_only};
foreach my $part ($entity->parts) {
if (my $match = $self->parse_entity($part)) {
push @$res, @$match;
@ -160,6 +188,12 @@ sub properties {
type => 'string',
maxLength => 1024,
},
'top-part-only' => {
description => "only match the headers in the first MIME-Part",
type => 'boolean',
optional => 1,
default => 0,
},
};
}
@ -169,6 +203,7 @@ sub get {
return {
field => $self->{field},
value => $self->{field_value},
'top-part-only' => $self->{top_part_only},
};
}
@ -177,6 +212,12 @@ sub update {
$self->{field_value} = $param->{value};
$self->{field} = $param->{field};
if (defined($param->{'top-part-only'}) && $param->{'top-part-only'} == 1) {
$self->{top_part_only} = 1;
} else {
delete $self->{top_part_only};
}
}
1;