File: //usr/share/perl5/vendor_perl/Amavis/MIME/Body/OnOpenFh.pm
# SPDX-License-Identifier: GPL-2.0-or-later
package Amavis::MIME::Body::OnOpenFh;
# A body class that keeps data on an open file handle, read-only,
# while allowing to prepend a couple of lines when reading from it.
# $skip_bytes bytes at the beginning of a given open file are ignored.
use strict;
use re 'taint';
BEGIN {
require Exporter;
require MIME::Body;
use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
$VERSION = '2.412';
@ISA = qw(Exporter MIME::Body); # subclass of MIME::Body
}
use Amavis::Util qw(ll do_log);
sub init {
my($self, $fh,$prefix_lines,$skip_bytes) = @_;
$self->{MB_Am_fh} = $fh;
$self->{MB_Am_prefix} = defined $prefix_lines ? join('',@$prefix_lines) : '';
$self->{MB_Am_prefix_l} = length($self->{MB_Am_prefix});
$self->{MB_Am_skip_bytes} = !defined $skip_bytes ? 0 : $skip_bytes;
$self->is_encoded(1);
$self;
}
sub open {
my($self,$mode) = @_;
$self->close; # ignoring status
$mode eq 'r' or die "Only offers read-only access, mode: $mode";
my $fh = $self->{MB_Am_fh}; my $skip = $self->{MB_Am_skip_bytes};
$fh->seek($skip,0) or die "Can't rewind mail file: $!";
$self->{MB_Am_pos} = 0;
bless { parent => $self }; #** One-argument "bless" warning
}
sub close { 1 }
sub read { # SCALAR,LENGTH,OFFSET
my $self = shift; my $len = $_[1]; my $offset = $_[2];
my $parent = $self->{parent}; my $pos = $parent->{MB_Am_pos};
my $str1 = ''; my $str2 = ''; my $nbytes = 0;
if ($len > 0 && $pos < $parent->{MB_Am_prefix_l}) {
$str1 = substr($parent->{MB_Am_prefix}, $pos, $len);
$nbytes += length($str1); $len -= $nbytes;
}
my $msg;
if ($len > 0) {
my $nb = $parent->{MB_Am_fh}->read($str2,$len);
if (!defined $nb) {
$msg = "Error reading: $!";
} elsif ($nb < 1) {
# read returns 0 at eof
} else {
$nbytes += $nb; $len -= $nb;
}
}
if (defined $msg) {
undef $nbytes; # $! already set by a failed read
} else {
($offset ? substr($_[0],$offset) : $_[0]) = $str1.$str2;
$pos += $nbytes; $parent->{MB_Am_pos} = $pos;
}
$nbytes; # eof: 0; error: undef
}
1;