diff options
Diffstat (limited to 'lib/Apache/Config/Preproc/ifdefine.pm')
-rw-r--r-- | lib/Apache/Config/Preproc/ifdefine.pm | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/lib/Apache/Config/Preproc/ifdefine.pm b/lib/Apache/Config/Preproc/ifdefine.pm new file mode 100644 index 0000000..834d602 --- /dev/null +++ b/lib/Apache/Config/Preproc/ifdefine.pm @@ -0,0 +1,137 @@ +package Apache::Config::Preproc::ifdefine; +use strict; +use warnings; +use Carp; + +sub new { + my $class = shift; + my $conf = shift; + my $self = bless {}, $class; + @{$self->{D}}{@_} = (1) x @_; + return $self; +} + +sub find_define { + my ($self,$elt,$id) = @_; + + while (my $p = $elt->parent) { + if (grep { + (split /\s+/, $_->value)[0] eq $id + } $p->directive('define')) { + return 1; + } + } + return; +} + +sub _changed_in_section { + my ($self, $section, $id, $before) = @_; + foreach my $d (reverse $section->select) { + if ($before) { + if ($d == $before) { + $before = undef; + } + next; + } + + if ($d->type eq 'directive') { + if ($d->name =~ m/^(un)?define$/i && $d->value eq $id) { + if ($1) { + $self->undefine($id); + } else { + $self->define($id); + } + return 1; + } + } elsif ($d->type eq 'section' && lc($d->name) eq 'virtualhost') { + # Need to descend into VirtualHost, because accorind to the + # Apache docs + # see (https://httpd.apache.org/docs/2.4/mod/core.html#define): + # + # While [the Define] directive is supported in virtual host + # context, the changes it makes are visible to any later + # configuration directives, beyond any enclosing virtual host. + # + # The same is said about the UnDefine directive. + + return 1 if $self->_changed_in_section($d, $id); + } + } + return 0; +} + +sub is_defined { + my ($self,$id,$d) = @_; + + unless ($self->{D}{$id}) { + my $before = $d; + while ($d = $d->parent) { + last if $self->_changed_in_section($d, $id, $before); + $before = undef; + } + } + return $self->{D}{$id}; +} + +sub define { + my ($self,$id) = @_; + $self->{D}{$id} = 1; +} + +sub undefine { + my ($self,$id) = @_; + delete $self->{D}{$id}; +} + +sub expand { + my ($self, $d, $repl) = @_; + if ($d->type eq 'section') { + if (lc($d->name) eq 'ifdefine') { + my $id = $d->value; + my $negate = $id =~ s/^!//; + my $res = $self->is_defined($id, $d); + $res = !$res if $negate; + if ($res) { + push @$repl, $d->select; + } + return 1; + } + } + if ($d->type eq 'directive') { + my $name = lc($d->name); + if ($name eq 'define') { + $self->define($d->value); + return 1; + } elsif ($name eq 'undefine') { + $self->undefine($d->value); + return 1; + } + } + return 0; +} + +1; +__END__ + +=head1 NAME + +Apache::Config::Preproc::ifmodule - expand IfDefine sections + +=head1 SYNOPSIS + + $x = new Apache::Config::Preproc '/path/to/httpd.conf', + -expand => [ qw(ifdefine) ]; + + $x = new Apache::Config::Preproc '/path/to/httpd.conf', + -expand => [ + { ifdefine => [qw(SYM1 SYM2)] } + ]; + +=head1 DESCRIPTION + +Eliminates the B<Define> and B<UnDefine> statements and expands the +B<E<lt>IfDefineE<gt>> statements in the Apache configuration parse +tree. Optional arguments to the constructor are treated as the names +of symbols to define (similar to the B<httpd> B<-D> options). + + |