Apache-Filter
view release on metacpan or search on metacpan
lib/Apache/Filter.pm view on Meta::CPAN
#warn "Turning STDOUT (@{[ref tied *STDOUT]}) into fh_in";
delete $self->{'fh_in'};
$self->{'fh_in'} = gensym;
tie *{$self->{'fh_in'}}, ref($self), tied *STDOUT;
local $^W; # Ignore "untie attempted while %d inner references still exist" warning from next line
untie *STDOUT;
}
sub filter_input {
my $self = shift;
# Don't handle directories
if ($self->is_first_filter and -d $self->finfo) {
$self->{'is_dir'} = 1; # Let mod_dir handle it
}
if ($self->{'is_dir'}) {
$self->{fh_in} = undef;
return wantarray ? ($self->{fh_in}, DECLINED) : $self->{fh_in};
}
my $status = OK;
unless (exists $self->{fh_in}) {
# Open $self->filename
#warn "+++++++++++ @{[$self->filename]}: This is the first filter";
$self->{fh_in} = gensym;
if (not -e $self->finfo) {
$self->log_error($self->filename() . " not found");
$status = NOT_FOUND;
} elsif ( not open (*{$self->{'fh_in'}}, $self->filename()) ) {
$self->log_error("Can't open " . $self->filename() . ": $!");
$status = FORBIDDEN;
}
}
#warn "END info is @{[%$self]} ";
return wantarray ? ($self->{fh_in}, $status) : $self->{fh_in};
}
sub is_last_filter {
my $self = shift;
return $self->{count} == @{$self->get_handlers('PerlHandler')};
}
sub is_first_filter {
my $self = shift;
return $self->{count} == 1;
}
sub send_http_header {
my $self = shift;
unless ($self->is_last_filter) {
# This lets previous filters set content_type, which becomes default for final filter.
$self->content_type($_[0]) if @_;
# Prevent early filters from messing up the content-length of late filters
$self->header_out('Content-Length'=> undef);
return;
}
return $self->SUPER::send_http_header(@_);
}
sub send_fd {
my $self = shift;
if ($self->is_last_filter and eval{fileno $_[0]}) {
# Can send native filehandle directly to client
$self->SUPER::send_fd(@_);
} else {
my $fd = shift;
print while <$fd>;
}
}
sub print {
my $self = shift;
$self->send_http_header() unless $self->sent_header;
print STDOUT @_;
}
sub changed_since {
my $self = shift;
# If any previous handlers are non-deterministic, then the content is
# volatile, so tell them it's changed.
if ($self->{'count'} > 1) {
return 1 if grep {not $self->{'determ'}{$_}} (1..$self->{'count'}-1);
}
# Okay, only deterministic handlers have touched this. If the file has
# changed since the given time, return true. Otherwise, return false.
return 1 if ((stat $self->finfo)[9] > shift);
return 0;
}
sub deterministic {
my $self = shift;
if (@_) {
$self->{'determ'}{$self->{'count'}} = shift;
}
return $self->{'determ'}{$self->{'count'}};
}
# This package is a TIEHANDLE package, so it can be used like this:
# tie(*HANDLE, 'Apache::Filter');
# All it does is save strings that are written to the filehandle, and
# spits them back out again when you read from the filehandle.
sub TIEHANDLE {
my $class = shift;
my $self = (@_ ? shift : { content => '' });
return bless $self, $class;
}
sub PRINT {
shift()->{'content'} .= join "", @_;
}
sub PRINTF {
my $self = shift;
my $format = shift;
$self->{'content'} .= sprintf($format, @_);
}
sub READLINE {
# I've tried to emulate the behavior of real filehandles here
# with respect to $/, but I might have screwed something up.
( run in 0.880 second using v1.01-cache-2.11-cpan-5735350b133 )