summaryrefslogtreecommitdiff
path: root/lib/Apache/Config/Preproc/include.pm
blob: f7c851c6447f7dee4bb8f2c21136e042f4ca8ed9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package Apache::Config::Preproc::include;
use strict;
use warnings;
use Apache::Admin::Config;
use Apache::Config::Preproc;
use File::Spec;
use Cwd 'abs_path';
use Carp;

sub new {
    my $class = shift;
    my $conf = shift;
    my $self = bless { included => {}, conf => $conf }, $class;
    local %_ = @_;
    $self->{server_root} = delete $_{server_root};
    croak "unrecognized arguments" if keys(%_);
    $self->{check_included} = $^O eq 'MSWin32'
	? \&_check_included_path
	: \&_check_included_stat;
    return $self;
}

sub conf { shift->{conf} }
    
sub server_root {
    my $self = shift;
    unless ($self->{server_root}) {
    	if (my $d = $self->conf->directive('ServerRoot')) {
	    $self->{server_root} = $self->conf->dequote($d->value);
	}
    }
    return $self->{server_root};
}


sub expand {
    my ($self, $d, $repl) = @_;

    if ($d->type eq 'directive' && $d->name =~ /^include(optional)?$/i) {
	my $optional = $1;

	my $pat = $self->conf->dequote($d->value);
	unless (File::Spec->file_name_is_absolute($pat)) {
	    if (my $d = $self->server_root) {
		$pat = File::Spec->catfile($d, $pat);
	    }
	}

	my @filelist = glob $pat;
	if (@filelist) {
	    foreach my $file (@filelist) {
		if ($self->check_included($file)) {
		    croak "file $file already included";
		}
		if (my $inc = new Apache::Admin::Config($file,
							@{$self->conf->options})) {
		    # NOTE: make sure each item is cloned
		    push @$repl, map { $_->clone } $inc->select;
		} else {
		    croak $Apache::Admin::Config::ERROR;
		}
	    }
	}
	return 1;
    }
	    
    return 0;
}

sub check_included {
    my ($self, $file) = @_;
    return $self->${ \ $self->{check_included} }($file);
}

# Default included file table for unix-like OSes
sub _check_included_stat {
    my ($self, $file) = @_;
    my ($dev,$ino) = stat($file) or return 0;
    return 1 if $self->{included}{$dev}{$ino};
    $self->{included}{$dev}{$ino} = 1;
    return 0;
}

# Path-bases file table, for defective OSes (MSWin32)
sub _check_included_path {
    my ($self, $file) = @_;
    my $path = abs_path($file);
    return 1 if $self->{included}{$path};
    $self->{included}{$path} = 1;
    return 0;
}

1;

__END__

=head1 NAME    

Apache::Config::Preproc::include - expand Include statements

=head1 SYNOPSIS

    $x = new Apache::Config::Preproc '/path/to/httpd.conf',
                -expand => [ qw(include) ];

    $x = new Apache::Config::Preproc '/path/to/httpd.conf',
                -expand => [
                    { include => { -server_root => $dir } }
                ];

=head1 DESCRIPTION

Processes B<Include> and B<IncludeOptional> statements and replaces them
with the contents of the files supplied in their arguments. If the argument
is not an absolute file name, it is searched in the server root directory.
The latter is determined inspecting the B<ServerRoot> statement. If this
statement is absent, the current working directory is used. The
B<-server_root> constructor argument can be used to enforce a specific
server root directory.
    
=cut

    

Return to:

Send suggestions and report system problems to the System administrator.