]>
git.proxmox.com Git - pmg-api.git/blob - src/PMG/RuleDB/Remove.pm
e7c353c744877eb8e1604d190783b4f9e21d8d66
1 package PMG
::RuleDB
::Remove
;
15 use PMG
::RuleDB
::Object
;
17 use base
qw(PMG::RuleDB::Object);
24 return 'Remove attachments';
44 my ($type, $all, $text, $ogroup, $quarantine) = @_;
46 my $class = ref($type) || $type;
48 $all = 0 if !defined ($all);
50 my $self = $class->SUPER::new
($class->otype(), $ogroup);
53 $self->{text
} = $text;
54 $self->{quarantine
} = $quarantine;
60 my ($type, $ruledb, $id, $ogroup, $value) = @_;
62 my $class = ref($type) || $type;
64 defined ($value) || die "undefined value: ERROR";
68 if ($value =~ m/^([01])\,([01])(\:(.*))?$/s) {
69 $text = PMG
::Utils
::try_decode_utf8
($4);
70 $obj = $class->new($1, $text, $ogroup, $2);
71 } elsif ($value =~ m/^([01])(\:(.*))?$/s) {
72 $text = PMG
::Utils
::try_decode_utf8
($3);
73 $obj = $class->new($1, $text, $ogroup);
75 $obj = $class->new(0, undef, $ogroup);
80 $obj->{digest
} = Digest
::SHA
::sha1_hex
($id, $value, $ogroup);
86 my ($self, $ruledb) = @_;
88 defined($self->{ogroup
}) || die "undefined ogroup: ERROR";
90 my $value = $self->{all
} ?
'1' : '0';
91 $value .= ','. ($self->{quarantine
} ?
'1' : '0');
94 $value .= encode
('UTF-8', ":$self->{text}");
97 if (defined ($self->{id
})) {
101 "UPDATE Object SET Value = ? WHERE ID = ?",
102 undef, $value, $self->{id
});
107 my $sth = $ruledb->{dbh
}->prepare(
108 "INSERT INTO Object (Objectgroup_ID, ObjectType, Value) " .
109 "VALUES (?, ?, ?);");
111 $sth->execute($self->ogroup, $self->otype, $value);
113 $self->{id
} = PMG
::Utils
::lastid
($ruledb->{dbh
}, 'object_id_seq');
119 sub delete_marked_parts
{
120 my ($self, $queue, $entity, $html, $rtype, $marks, $rulename) = @_;
124 my $ctype = $entity->head->mime_type;
125 my $pn = $entity->parts;
126 for (my $i = 0; $i < $pn; $i++) {
127 my $part = $entity->parts($i);
131 if ($id = $part->head->mime_attr('x-proxmox-tmp-aid')) {
135 my $ctype_part = $part->head->mime_type;
136 if ($self->{message_seen
}) {
139 if ($ctype =~ m
|multipart
/alternative
|i
) {
140 if ($ctype_part !~ m{text/(?:plain|html)}i) {
145 # we have not seen the message and it is the
146 # end of the first multipart/alternative, mark as message seen
147 $self->{message_seen
} = 1;
150 if ($ctype_part =~ m{text/(?:plain|html)}i) {
151 $self->{message_seen
} = 1;
152 } elsif ($ctype_part !~ m
|multipart
/|i
) {
158 foreach my $m (@$marks) {
159 $found = 1 if $m eq $id;
167 my $on = PMG
::Utils
::extract_filename
($part->head) || '';
169 my $text = PMG
::Utils
::subst_values
($html, { FILENAME
=> $on } );
171 my $fname = "REMOVED_ATTACHMENT_$id." . ($rtype eq "text/html" ?
"html" : "txt");
173 my $ent = MIME
::Entity-
>build(
176 Encoding
=> "quoted-printable",
178 Disposition
=> "attachment",
179 Data
=> encode
('UTF-8', $text));
181 push (@$nparts, $ent);
183 syslog
('info', "%s: removed attachment $id ('%s', rule: %s)",
184 $queue->{logid
}, $on, $rulename);
187 $self->delete_marked_parts($queue, $part, $html, $rtype, $marks, $rulename);
188 push (@$nparts, $part);
192 $entity->parts ($nparts);
196 my ($self, $queue, $ruledb, $mod_group, $targets,
197 $msginfo, $vars, $marks, $ldap) = @_;
199 my $rulename = encode
('UTF-8', $vars->{RULE
} // 'unknown');
201 if (!$self->{all
} && ($#$marks == -1)) {
206 my $subgroups = $mod_group->subgroups ($targets);
208 my $html = PMG
::Utils
::subst_values
($self->{text
}, $vars);
211 $html = "This attachment was removed: __FILENAME__\n";
212 $html .= "It was put into the Attachment Quarantine, please contact your Administrator\n" if $self->{quarantine
};
215 my $rtype = "text/plain";
217 if ($html =~ m/\<\w+\>/s) {
218 $rtype = "text/html";
221 foreach my $ta (@$subgroups) {
222 my ($tg, $entity) = (@$ta[0], @$ta[1]);
224 # copy original entity to attachment quarantine if configured
225 if ($self->{quarantine
}) {
226 my $original_entity = $entity->dup;
227 PMG
::Utils
::remove_marks
($original_entity);
228 if (my $qid = $queue->quarantine_mail($ruledb, 'A', $original_entity, $tg, $msginfo, $vars, $ldap)) {
229 # adapt the Message-ID header of the mail without attachment to
230 # prevent 2 different mails with the same Message-ID
231 my $message_id = $entity->head->get('Message-ID');
232 if (defined($message_id)) {
233 $message_id =~ s/^(<?)(.+)(>?)$/$1pmg-aquar-$$-$2$3/;
234 $entity->head->replace('Message-ID', $message_id);
240 "$queue->{logid}: moved mail for <%s> to attachment quarantine - %s (rule: %s)",
249 # handle singlepart mails
250 my $ctype = $entity->head->mime_type;
251 if (!$entity->is_multipart && (!$self->{all
} || $ctype !~ m
|text
/.*|i
)) {
252 $entity->make_multipart();
253 my $first_part = $entity->parts(0);
254 $first_part->head->mime_attr('x-proxmox-tmp-aid' => $entity->head->mime_attr('x-proxmox-tmp-aid'));
255 $entity->head->delete('x-proxmox-tmp-aid');
258 $self->{message_seen
} = 0;
259 $self->delete_marked_parts($queue, $entity, $html, $rtype, $marks, $rulename);
260 delete $self->{message_seen
};
262 if ($msginfo->{testmode
}) {
263 $entity->head->mime_attr('Content-type.boundary' => '------=_TEST123456') if $entity->is_multipart;
272 return "remove all attachments";
274 return "remove matching attachments";
283 description
=> "Remove all attachments",
288 description
=> "Copy original mail to attachment Quarantine.",
294 description
=> "The replacement text.",
305 text
=> $self->{text
},
307 quarantine
=> $self->{quarantine
},
312 my ($self, $param) = @_;
314 $self->{text
} = $param->{text
};
315 $self->{all
} = $param->{all
} ?
1 : 0;
316 $self->{quarantine
} = $param->{quarantine
} ?
1 : 0;
322 =head1 PMG::RuleDB::Remove