summaryrefslogtreecommitdiff
path: root/lib/Apache/Config/Preproc/ifdefine.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Apache/Config/Preproc/ifdefine.pm')
-rw-r--r--lib/Apache/Config/Preproc/ifdefine.pm137
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).
+
+

Return to:

Send suggestions and report system problems to the System administrator.