1# Apache::ConfigParser::Directive: A single Apache directive or start context.
2#
3# Copyright (C) 2001-2005 Blair Zajac.  All rights reserved.
4
5package Apache::ConfigParser::Directive;
6
7require 5.004_05;
8
9use strict;
10use Exporter;
11use Carp;
12use File::Spec     0.82;
13use Tree::DAG_Node 1.04;
14
15use vars qw(@EXPORT_OK @ISA $VERSION);
16@ISA     = qw(Tree::DAG_Node Exporter);
17$VERSION = '1.02';
18
19# Determine if the filenames are case sensitive.
20use constant CASE_SENSITIVE_PATH => (! File::Spec->case_tolerant);
21
22# This is a utility subroutine to determine if the specified path is
23# the /dev/null equivalent on this operating system.
24use constant DEV_NULL    =>    File::Spec->devnull;
25use constant DEV_NULL_LC => lc(File::Spec->devnull);
26sub is_dev_null {
27  if (CASE_SENSITIVE_PATH) {
28    return $_[0] eq DEV_NULL;
29  } else {
30    return lc($_[0]) eq DEV_NULL_LC;
31  }
32}
33push(@EXPORT_OK, qw(DEV_NULL DEV_NULL_LC is_dev_null));
34
35# This constant is used throughout the module.
36my $INCORRECT_NUMBER_OF_ARGS = "passed incorrect number of arguments.\n";
37
38# These are declared now but defined and documented below.
39use vars         qw(%directive_value_takes_abs_path
40                    %directive_value_takes_rel_path
41                    %directive_value_path_element_pos);
42push(@EXPORT_OK, qw(%directive_value_takes_abs_path
43                    %directive_value_takes_rel_path
44                    %directive_value_path_element_pos));
45
46=head1 NAME
47
48  Apache::ConfigParser::Directive - An Apache directive or start context
49
50=head1 SYNOPSIS
51
52  use Apache::ConfigParser::Directive;
53
54  # Create a new empty directive.
55  my $d = Apache::ConfigParser::Directive->new;
56
57  # Make it a ServerRoot directive.
58  # ServerRoot /etc/httpd
59  $d->name('ServerRoot');
60  $d->value('/etc/httpd');
61
62  # A more complicated directive.  Value automatically splits the
63  # argument into separate elements.  It treats elements in "'s as a
64  # single element.
65  # LogFormat "%h %l %u %t \"%r\" %>s %b" common
66  $d->name('LogFormat');
67  $d->value('"%h %l %u %t \"%r\" %>s %b" common');
68
69  # Get a string form of the name.
70  # Prints 'logformat'.
71  print $d->name, "\n";
72
73  # Get a string form of the value.
74  # Prints '"%h %l %u %t \"%r\" %>s %b" common'.
75  print $d->value, "\n";
76
77  # Get the values separated into individual elements.  Whitespace
78  # separated elements that are enclosed in "'s are treated as a
79  # single element.  Protected quotes, \", are honored to not begin or
80  # end a value element.  In this form protected "'s, \", are no
81  # longer protected.
82  my @value = $d->get_value_array;
83  scalar @value == 2;		# There are two elements in this array.
84  $value[0] eq '%h %l %u %t \"%r\" %>s %b';
85  $value[1] eq 'common';
86
87  # The array form can also be set.  Change style of LogFormat from a
88  # common to a referer style log.
89  $d->set_value_array('%{Referer}i -> %U', 'referer');
90
91  # This is equivalent.
92  $d->value('"%{Referer}i -> %U" referer');
93
94  # There are also an equivalent pair of values that are called
95  # 'original' that can be accessed via orig_value,
96  # get_orig_value_array and set_orig_value_array.
97  $d->orig_value('"%{User-agent}i" agent');
98  $d->set_orig_value_array('%{User-agent}i', 'agent');
99  @value = $d->get_orig_value_array;
100  scalar @value == 2;		# There are two elements in this array.
101  $value[0] eq '%{User-agent}i';
102  $value[1] eq 'agent';
103
104  # You can set undef values for the strings.
105  $d->value(undef);
106
107=head1 DESCRIPTION
108
109The C<Apache::ConfigParser::Directive> module is a subclass of
110C<Tree::DAG_Node>, which provides methods to represents nodes in a
111tree.  Each node is a single Apache configuration directive or root
112node for a context, such as <Directory> or <VirtualHost>.  All of the
113methods in that module are available here.  This module adds some
114additional methods that make it easier to represent Apache directives
115and contexts.
116
117This module holds a directive or context:
118
119  name
120  value in string form
121  value in array form
122  a separate value termed 'original' in string form
123  a separate value termed 'original' in array form
124  the filename where the directive was set
125  the line number in the filename where the directive was set
126
127The 'original' value is separate from the non-'original' value and the
128methods to operate on the two sets of values have distinct names.  The
129'original' value can be used to store the original value of a
130directive while the non-'directive' value can be a modified form, such
131as changing the CustomLog filename to make it absolute.  The actual
132use of these two distinct values is up to the caller as this module
133does not link the two in any way.
134
135=head1 METHODS
136
137The following methods are available:
138
139=over
140
141=cut
142
143=item $d = Apache::ConfigParser::Directive->new;
144
145This creates a brand new C<Apache::ConfigParser::Directive> object.
146
147It is not recommended to pass any arguments to C<new> to set the
148internal state and instead use the following methods.
149
150There actually is no C<new> method in the
151C<Apache::ConfigParser::Directive> module.  Instead, due to
152C<Apache::ConfigParser::Directive> being a subclass of
153C<Tree::DAG_Node>, C<Tree::DAG_Node::new> will be used.
154
155=cut
156
157# The Apache::ConfigParser::Directive object still needs to be
158# initialized.  This is done here.  Tree::DAG_Node->new calls
159# Apache::ConfigParser::Directive->_init, which will call
160# Tree::DAG_Node->_init.
161sub _init {
162  my $self                  = shift;
163  $self->SUPER::_init;
164  $self->{name}             = '';
165  $self->{value}            = '';
166  $self->{value_array}      = [];
167  $self->{orig_value}       = '';
168  $self->{orig_value_array} = [];
169  $self->{filename}         = '';
170  $self->{line_number}      = -1;
171}
172
173=item $d->name
174
175=item $d->name($name)
176
177In the first form get the directive or context's name.  In the second
178form set the new name of the directive or context to the lowercase
179version of I<$name> and return the original name.
180
181=cut
182
183sub name {
184  unless (@_ < 3) {
185    confess "$0: Apache::ConfigParser::Directive::name ",
186            $INCORRECT_NUMBER_OF_ARGS;
187  }
188
189  my $self = shift;
190  if (@_) {
191    my $old       = $self->{name};
192    $self->{name} = lc($_[0]);
193    return $old;
194  } else {
195    return $self->{name};
196  }
197}
198
199=item $d->value
200
201=item $d->value($value)
202
203In the first form get the directive's value in string form.  In the
204second form, return the previous directive value in string form and
205set the new directive value to I<$value>.  I<$value> can be set to
206undef.
207
208If the value is being set, then I<$value> is saved so another call to
209C<value> will return I<$value>.  If I<$value> is defined, then
210I<$value> is also parsed into an array of elements that can be
211retrieved with the C<value_array_ref> or C<get_value_array> methods.
212The parser separates elements by whitespace, unless whitespace
213separated elements are enclosed by "'s.  Protected quotes, \", are
214honored to not begin or end a value element.
215
216=item $d->orig_value
217
218=item $d->orig_value($value)
219
220Identical behavior as C<value>, except that this applies to a the
221'original' value.  Use C<orig_value_ref> or C<get_orig_value_array> to
222get the value elements.
223
224=cut
225
226# This function manages getting and setting the string value for
227# either the 'value' or 'orig_value' hash keys.
228sub _get_set_value_string {
229  unless (@_ > 1 and @_ < 4) {
230    confess "$0: Apache::ConfigParser::Directive::_get_set_value_string ",
231            $INCORRECT_NUMBER_OF_ARGS;
232  }
233
234  my $self            = shift;
235  my $string_var_name = pop;
236  my $old_value       = $self->{$string_var_name};
237  unless (@_) {
238    return $old_value;
239  }
240
241  my $value           = shift;
242  my $array_var_name  = "${string_var_name}_array";
243
244  if (defined $value) {
245    # Keep the value as a string and also create an array of values.
246    # Keep content inside " as a single value and also protect \".
247    my @values;
248    if (length $value) {
249      my $v =  $value;
250      $v    =~ s/\\"/\200/g;
251      while (defined $v and length $v) {
252        if ($v =~ s/^"//) {
253          my $quote_index = index($v, '"');
254          if ($quote_index < 0) {
255            $v =~ s/\200/"/g;
256            push(@values, $v);
257            last;
258          } else {
259            my $v1 =  substr($v, 0, $quote_index, '');
260            $v     =~ s/^"\s*//;
261            $v1    =~ s/\200/"/g;
262            push(@values, $v1);
263          }
264        } else {
265          my ($v1, $v2) = $v =~ /^(\S+)(?:\s+(.*))?$/;
266          $v            = $v2;
267          $v1           =~ s/\200/"/g;
268          push(@values, $v1);
269        }
270      }
271    }
272    $self->{$string_var_name} = $value;
273    $self->{$array_var_name}  = \@values;
274  } else {
275    $self->{$string_var_name} = undef;
276    $self->{$array_var_name}  = undef;
277  }
278
279  $old_value;
280}
281
282sub value {
283  unless (@_ and @_ < 3) {
284    confess "$0: Apache::ConfigParser::Directive::value ",
285            $INCORRECT_NUMBER_OF_ARGS;
286  }
287
288  return _get_set_value_string(@_, 'value');
289}
290
291sub orig_value {
292  unless (@_ and @_ < 3) {
293    confess "$0: Apache::ConfigParser::Directive::orig_value ",
294            $INCORRECT_NUMBER_OF_ARGS;
295  }
296
297  return _get_set_value_string(@_, 'orig_value');
298}
299
300=item $d->value_array_ref
301
302=item $d->value_array_ref(\@array)
303
304In the first form get a reference to the value array.  This can return
305an undefined value if an undefined value was passed to C<value> or an
306undefined reference was passed to C<value_array_ref>.  In the second
307form C<value_array_ref> sets the value array and value string.  Both
308forms of C<value_array_ref> return the original array reference.
309
310If you modify the value array reference after getting it and do not
311use C<value_array_ref> C<set_value_array> to set the value, then the
312string returned from C<value> will not be consistent with the array.
313
314=item $d->orig_value_array_ref
315
316=item $d->orig_value_array_ref(\@array)
317
318Identical behavior as C<value_array_ref>, except that this applies to
319the 'original' value.
320
321=cut
322
323# This is a utility function that takes the hash key name to place the
324# value elements into, saves the array and creates a value string
325# suitable for placing into an Apache configuration file.
326sub _set_value_array {
327  unless (@_ > 1) {
328    confess "$0: Apache::ConfigParser::Directive::_set_value_array ",
329            $INCORRECT_NUMBER_OF_ARGS;
330  }
331
332  my $self            = shift;
333  my $string_var_name = pop;
334  my $array_var_name  = "${string_var_name}_array";
335  my @values          = @_;
336
337  my $value = '';
338  foreach my $s (@values) {
339    next unless length $s;
340
341    $value .= ' ' if length $value;
342
343    # Make a copy of the string so that the regex doesn't modify the
344    # contents of @values.
345    my $substring  =  $s;
346    $substring     =~ s/(["\\])/\\$1/g;
347    if ($substring =~ /\s/) {
348      $value .= "\"$substring\"";
349    } else {
350      $value .= $substring;
351    }
352  }
353
354  my $old_array_ref = $self->{$array_var_name};
355
356  $self->{$string_var_name} = $value;
357  $self->{$array_var_name}  = \@values;
358
359  $old_array_ref ? @$old_array_ref : ();
360}
361
362sub value_array_ref {
363  unless (@_ and @_ < 3) {
364    confess "$0: Apache::ConfigParser::Directive::value_array_ref ",
365            $INCORRECT_NUMBER_OF_ARGS;
366  }
367
368  my $self = shift;
369
370  my $old = $self->{value_array};
371
372  if (@_) {
373    my $ref = shift;
374    if (defined $ref) {
375      $self->_set_value_array(@$ref, 'value');
376    } else {
377      $self->{value}       = undef;
378      $self->{value_array} = undef;
379    }
380  }
381
382  $old;
383}
384
385sub orig_value_array_ref {
386  unless (@_ and @_ < 3) {
387    confess "$0: Apache::ConfigParser::Directive::orig_value_array_ref ",
388            $INCORRECT_NUMBER_OF_ARGS;
389  }
390
391  my $self = shift;
392
393  my $old = $self->{orig_value_array};
394
395  if (@_) {
396    my $ref = shift;
397    if (defined $ref) {
398      $self->_set_value_array(@$ref, 'orig_value');
399    } else {
400      $self->{value}       = undef;
401      $self->{value_array} = undef;
402    }
403  }
404
405  $old;
406}
407
408=item $d->get_value_array
409
410Get the value array elements.  If the value was set to an undefined
411value using C<value>, then C<get_value_array> will return an empty
412list in a list context, an undefined value in a scalar context, or
413nothing in a void context.
414
415=item $d->get_orig_value_array
416
417This has the same behavior of C<get_value_array> except that it
418operates on the 'original' value.
419
420=cut
421
422sub get_value_array {
423  unless (@_ == 1) {
424    confess "$0: Apache::ConfigParser::Directive::get_value_array ",
425            $INCORRECT_NUMBER_OF_ARGS;
426  }
427
428  my $ref = shift->{value_array};
429
430  if ($ref) {
431    return @$ref;
432  } else {
433    return;
434  }
435}
436
437sub get_orig_value_array {
438  unless (@_ == 1) {
439    confess "$0: Apache::ConfigParser::Directive::get_orig_value_array ",
440            $INCORRECT_NUMBER_OF_ARGS;
441  }
442
443  my $ref = shift->{orig_value_array};
444
445  if ($ref) {
446    return @$ref;
447  } else {
448    return;
449  }
450}
451
452=item $d->set_value_array(@values)
453
454Set the value array elements.  If no elements are passed in, then the
455value will be defined but empty and a following call to
456C<get_value_array> will return an empty array.  This returns the value
457of the array before this method was called.
458
459After setting the value elements with this method, the string returned
460from calling C<value> is a concatenation of each of the elements so
461that the output could be used for an Apache configuration file.  If
462any elements contain whitespace, then the "'s are placed around the
463element as the element is being concatenated into the value string and
464if any elements contain a " or a \, then a copy of the element is made
465and the character is protected, i.e. \" or \\, and then copied into
466the value string.
467
468=item $d->set_orig_value_array(@values)
469
470This has the same behavior as C<set_value_array> except that it
471operates on the 'original' value.
472
473=cut
474
475sub set_value_array {
476  return _set_value_array(@_, 'value');
477}
478
479sub set_orig_value_array {
480  return _set_value_array(@_, 'orig_value');
481}
482
483=item Note on $d->value_is_path, $d->value_is_abs_path,
484$d->value_is_rel_path, $d->orig_value_is_path,
485$d->orig_value_is_abs_path and $d->orig_value_is_rel_path
486
487These six methods are very similar.  They all check if the directive
488can take a file or directory path value argument in the appropriate
489index in the value array and then check the value.  For example, the
490C<LoadModule> directive, i.e.
491
492=over 4
493
494LoadModule cgi_module libexec/mod_cgi.so
495
496=back
497
498does not take a path element in its first (index 0) value array
499element.
500
501If there is no argument supplied to the method call, then the
502directive checks the first element of the value array that can legally
503contain path.  For C<LoadModule>, it would check element 1.  You could
504pass 0 to the method to check the first indexed value of
505C<LoadModule>, but it would always return false, because index 0 does
506not contain a path.
507
508These are the differences between the methods:
509
510=over 4
511
5121) The methods beginning with the string 'value_is' apply to the
513current value in the directive while the methods beginning with the
514string 'orig_value_is' apply to the original value of the directive.
515
5162) The methods '*value_is_path' test if the directive value is a path,
517either absolute or relative.  The methods '*value_is_abs_path' test if
518the path if an absolute path, and the methods '*value_is_rel_path'
519test if the path is not an absolute path.
520
521=back
522
523=item $d->value_is_path
524
525=item $d->value_is_path($index_into_value_array)
526
527Returns true if C<$d>'s directive can take a file or directory path in
528the specified value array element (indexed by $index_into_value_array
529or the first path element for the particular directive if
530$index_into_value_array is not provided) and if the value is either an
531absolute or relative file or directory path.  Both the directive name
532and the value is checked, because some directives such as ErrorLog,
533can take values that are not paths (i.e. a piped command or
534syslog:facility).  The /dev/null equivalent for the operating system
535is not treated as a path, since on some operating systems the
536/dev/null equivalent is not a file, such as nul on Windows.
537
538The method actually does not check if its value is a path, rather it
539checks if the value does not match all of the other possible non-path
540values for the specific directive because different operating systems
541have different path formats, such as Unix, Windows and Macintosh.
542
543=cut
544
545# Define these constant subroutines as the different types of paths to
546# check for in _value_is_path_or_abs_path_or_rel_path.
547sub CHECK_TYPE_ABS        () { 'abs' }
548sub CHECK_TYPE_REL        () { 'rel' }
549sub CHECK_TYPE_ABS_OR_REL () { 'abs_or_rel' }
550
551# This is a function that does the work for value_is_path,
552# orig_value_is_path, value_is_abs_path, orig_value_is_abs_path,
553# value_is_rel_path and orig_value_is_rel_path.
554sub _value_is_path_or_abs_path_or_rel_path {
555  unless (@_ == 4) {
556    confess "$0: Apache::ConfigParser::Directive::",
557            "_value_is_path_or_abs_path_or_rel_path ",
558            $INCORRECT_NUMBER_OF_ARGS;
559  }
560
561  my ($self,
562      $check_type,
563      $array_var_name,
564      $value_path_index) = @_;
565
566  unless ($check_type eq CHECK_TYPE_ABS or
567          $check_type eq CHECK_TYPE_REL or
568          $check_type eq CHECK_TYPE_ABS_OR_REL) {
569    confess "$0: Apache::ConfigParser::Directive::",
570            "_value_is_path_or_abs_path_or_rel_path ",
571            "passed invalid check_type value '$check_type'.\n";
572  }
573
574  if (defined $value_path_index and $value_path_index !~ /^\d+$/) {
575    confess "$0: Apache::ConfigParser::Directive::",
576            "_value_is_path_or_abs_path_or_rel_path ",
577            "passed invalid value_path_index value '$value_path_index'.\n";
578  }
579
580  my $array_ref = $self->{$array_var_name};
581
582  unless ($array_ref) {
583    return 0;
584  }
585
586  my $directive_name = $self->name;
587
588  unless (defined $directive_name and length $directive_name) {
589    return 0;
590  }
591
592  # Check if there is an index into the value array that can take a
593  # path.
594  my $first_value_path_index =
595    $directive_value_path_element_pos{$directive_name};
596  unless (defined $first_value_path_index and length $first_value_path_index) {
597    return 0;
598  }
599
600  # If the index into the value array was specified, then check if the
601  # value in the index can take a path.  If the index was not
602  # specified, then use the first value index that can contain a path.
603  if (defined $value_path_index) {
604    if (substr($first_value_path_index, 0, 1) eq '-') {
605      return 0 if $value_path_index <  abs($first_value_path_index);
606    } else {
607      return 0 if $value_path_index != $first_value_path_index;
608    }
609  } else {
610    $value_path_index = abs($first_value_path_index);
611  }
612  my $path = $array_ref->[$value_path_index];
613
614  unless (defined $path and length $path) {
615    return 0;
616  }
617
618  if (is_dev_null($path)) {
619    return 0;
620  }
621
622  # Get the subroutine that will check if the directive value is a
623  # path.  If there is no subroutine for the directive, then it
624  # doesn't take a path.
625  my $sub_ref;
626  if ($check_type eq CHECK_TYPE_ABS) {
627    $sub_ref = $directive_value_takes_abs_path{$directive_name};
628  } elsif ($check_type eq CHECK_TYPE_REL) {
629    $sub_ref = $directive_value_takes_rel_path{$directive_name};
630  } elsif ($check_type eq CHECK_TYPE_ABS_OR_REL) {
631    $sub_ref = $directive_value_takes_abs_path{$directive_name};
632    unless (defined $sub_ref) {
633      $sub_ref = $directive_value_takes_rel_path{$directive_name};
634    }
635  } else {
636    confess "$0: internal error: check_type case '$check_type' not handled.\n";
637  }
638
639  unless ($sub_ref) {
640    return 0;
641  }
642
643  my $result = &$sub_ref($path);
644  if ($result) {
645    return 1 if $check_type eq CHECK_TYPE_ABS_OR_REL;
646
647    if ($check_type eq CHECK_TYPE_ABS) {
648      return File::Spec->file_name_is_absolute($path) ? 1 : 0;
649    } elsif ($check_type eq CHECK_TYPE_REL) {
650      return File::Spec->file_name_is_absolute($path) ? 0 : 1;
651    } else {
652      confess "$0: internal error: check_type case ",
653              "'$check_type' not handled.\n";
654    }
655  } else {
656    return 0;
657  }
658}
659
660sub value_is_path {
661  unless (@_ < 3) {
662    confess "$0: Apache::ConfigParser::Directive::value_is_path ",
663            $INCORRECT_NUMBER_OF_ARGS;
664  }
665
666  _value_is_path_or_abs_path_or_rel_path($_[0],
667                                         CHECK_TYPE_ABS_OR_REL,
668                                         'value_array',
669                                         $_[1]);
670}
671
672=item $d->orig_value_is_path
673
674=item $d->orig_value_is_path($index_into_value_array)
675
676This has the same behavior as C<< $d->value_is_path >> except the results
677are applicable to C<$d>'s 'original' value array.
678
679=cut
680
681sub orig_value_is_path {
682  unless (@_ < 3) {
683    confess "$0: Apache::ConfigParser::Directive::orig_value_is_path ",
684            $INCORRECT_NUMBER_OF_ARGS;
685  }
686
687  _value_is_path_or_abs_path_or_rel_path($_[0],
688					 CHECK_TYPE_ABS_OR_REL,
689					 'orig_value_array',
690					 $_[1]);
691}
692
693=item $d->value_is_abs_path
694
695=item $d->value_is_abs_path($index_into_value_array)
696
697Returns true if C<$d>'s directive can take a file or directory path in
698the specified value array element (indexed by $index_into_value_array
699or the first path element for the particular directive if
700$index_into_value_array is not provided) and if the value is an
701absolute file or directory path.  Both the directive name and the
702value is checked, because some directives such as ErrorLog, can take
703values that are not paths (i.e. a piped command or syslog:facility).
704The /dev/null equivalent for the operating system is not treated as a
705path, since on some operating systems the /dev/null equivalent is not
706a file, such as nul on Windows.
707
708The method actually does not check if its value is a path, rather it
709checks if the value does not match all of the other possible non-path
710values for the specific directive because different operating systems
711have different path formats, such as Unix, Windows and Macintosh.
712
713=cut
714
715sub value_is_abs_path {
716  unless (@_ < 3) {
717    confess "$0: Apache::ConfigParser::Directive::value_is_abs_path ",
718            $INCORRECT_NUMBER_OF_ARGS;
719  }
720
721  _value_is_path_or_abs_path_or_rel_path($_[0],
722                                         CHECK_TYPE_ABS,
723                                         'value_array',
724                                         $_[1]);
725}
726
727=item $d->orig_value_is_abs_path
728
729=item $d->orig_value_is_abs_path($index_into_value_array)
730
731This has the same behavior as C<< $d->value_is_abs_path >> except the
732results are applicable to C<$d>'s 'original' value array.
733
734=cut
735
736sub orig_value_is_abs_path {
737  unless (@_ < 3) {
738    confess "$0: Apache::ConfigParser::Directive::orig_value_is_abs_path ",
739            $INCORRECT_NUMBER_OF_ARGS;
740  }
741
742  _value_is_path_or_abs_path_or_rel_path($_[0],
743					 CHECK_TYPE_ABS,
744					 'orig_value_array',
745					 $_[1]);
746}
747
748=item $d->value_is_rel_path
749
750=item $d->value_is_rel_path($index_into_value_array)
751
752Returns true if C<$d>'s directive can take a file or directory path in
753the specified value array element (indexed by $index_into_value_array
754or the first path element for the particular directive if
755$index_into_value_array is not provided) and if the value is a
756relative file or directory path.  Both the directive name and the
757value is checked, because some directives such as ErrorLog, can take
758values that are not paths (i.e. a piped command or syslog:facility).
759The /dev/null equivalent for the operating system is not treated as a
760path, since on some operating systems the /dev/null equivalent is not
761a file, such as nul on Windows.
762
763The method actually does not check if its value is a path, rather it
764checks if the value does not match all of the other possible non-path
765values for the specific directive because different operating systems
766have different path formats, such as Unix, Windows and Macintosh.
767
768=cut
769
770sub value_is_rel_path {
771  unless (@_ < 3) {
772    confess "$0: Apache::ConfigParser::Directive::value_is_rel_path ",
773            $INCORRECT_NUMBER_OF_ARGS;
774  }
775
776  _value_is_path_or_abs_path_or_rel_path($_[0],
777                                         CHECK_TYPE_REL,
778                                         'value_array',
779                                         $_[1]);
780}
781
782=item $d->orig_value_is_rel_path
783
784=item $d->orig_value_is_rel_path($index_into_value_array)
785
786This has the same behavior as C<< $d->value_is_rel_path >> except the
787results are applicable to C<$d>'s 'original' value array.
788
789=cut
790
791sub orig_value_is_rel_path {
792  unless (@_ < 3) {
793    confess "$0: Apache::ConfigParser::Directive::orig_value_is_rel_path ",
794            $INCORRECT_NUMBER_OF_ARGS;
795  }
796
797  _value_is_path_or_abs_path_or_rel_path($_[0],
798					 CHECK_TYPE_REL,
799					 'orig_value_array',
800					 $_[1]);
801}
802
803=item $d->filename
804
805=item $d->filename($filename)
806
807In the first form get the filename where this particular directive or
808context appears.  In the second form set the new filename of the
809directive or context and return the original filename.
810
811=cut
812
813sub filename {
814  unless (@_ < 3) {
815    confess "$0: Apache::ConfigParser::Directive::filename ",
816            $INCORRECT_NUMBER_OF_ARGS;
817  }
818
819  my $self = shift;
820  if (@_) {
821    my $old           = $self->{filename};
822    $self->{filename} = $_[0];
823    return $old;
824  } else {
825    return $self->{filename};
826  }
827}
828
829=item $d->line_number
830
831=item $d->line_number($line_number)
832
833In the first form get the line number where the directive or context
834appears in a filename.  In the second form set the new line number of
835the directive or context and return the original line number.
836
837=cut
838
839sub line_number {
840  unless (@_ < 3) {
841    confess "$0: Apache::ConfigParser::Directive::line_number ",
842            $INCORRECT_NUMBER_OF_ARGS;
843  }
844
845  my $self = shift;
846  if (@_) {
847    my $old              = $self->{line_number};
848    $self->{line_number} = $_[0];
849    return $old;
850  } else {
851    return $self->{line_number};
852  }
853}
854
855=back
856
857=head1 EXPORTED VARIABLES
858
859The following variables are exported via C<@EXPORT_OK>.
860
861=over 4
862
863=item DEV_NULL
864
865The string representation of the null device on this operating system.
866
867=item DEV_NULL_LC
868
869The lowercase version of DEV_NULL.
870
871=item is_dev_null($path)
872
873On a case sensitive system, compares $path to DEV_NULL and on a case
874insensitive system, compares lc($path) to DEV_NULL_LC.
875
876=item %directive_value_takes_abs_path
877
878This hash is keyed by the lowercase version of a directive name.  This
879hash is keyed by all directives that accept a file or directory path
880value as its first value array element. The hash value is a subroutine
881reference to pass the value array element containing the file,
882directory, pipe or syslog entry to.  If a hash entry exists for a
883particular entry, then the directive name can take either a relative
884or absolute path to either a file or directory.  The hash does not
885distinguish between directives that take only filenames, only
886directories or both, and it does not distinguish if the directive
887takes only absolute, only relative or both types of paths.
888
889The hash value for the lowercase directive name is a subroutine
890reference.  The subroutine returns 1 if its only argument is a path
891and 0 otherwise.  The /dev/null equivalent (C<< File::Spec->devnull >>)
892for the operating system being used is not counted as a path, since on
893some operating systems the /dev/null equivalent is not a filename,
894such as nul on Windows.
895
896The subroutine actually does not check if its argument is a path,
897rather it checks if the argument does not match one of the other
898possible non-path values for the specific directive because different
899operating systems have different path formats, such as Unix, Windows
900and Macintosh.  For example, ErrorLog can take a filename, such as
901
902  ErrorLog /var/log/httpd/error_log
903
904or a piped command, such as
905
906  ErrorLog "| cronolog /var/log/httpd/%Y/%m/%d/error.log"
907
908or a syslog entry of the two forms:
909
910  ErrorLog syslog
911  ErrorLog syslog:local7
912
913The particular subroutine for ErrorLog checks if the value is not
914equal to C<< File::Spec->devnull >>, does not begin with a | or does not
915match syslog(:[a-zA-Z0-9]+)?.
916
917These subroutines do not remove any "'s before checking on the type of
918value.
919
920This hash is used by C<value_is_path> and C<orig_value_is_path>.
921
922This is a list of directives and any special values to check for as of
923Apache 1.3.20 with the addition of IncludeOptional from 2.4.x.
924
925  AccessConfig
926  AgentLog          check for "| prog"
927  AuthDBGroupFile
928  AuthDBMGroupFile
929  AuthDBMUserFile
930  AuthDBUserFile
931  AuthDigestFile
932  AuthGroupFile
933  AuthUserFile
934  CacheRoot
935  CookieLog
936  CoreDumpDirectory
937  CustomLog         check for "| prog"
938  Directory
939  DocumentRoot
940  ErrorLog          check for "| prog", or syslog or syslog:facility
941  Include
942  IncludeOptional
943  LoadFile
944  LoadModule
945  LockFile
946  MimeMagicFile
947  MMapFile
948  PidFile
949  RefererLog        check for "| prog"
950  ResourceConfig
951  RewriteLock
952  ScoreBoardFile
953  ScriptLog
954  ServerRoot
955  TransferLog       check for "| prog"
956  TypesConfig
957
958=item %directive_value_takes_rel_path
959
960This hash is keyed by the lowercase version of a directive name.  This
961hash contains only those directive names that can accept both relative
962and absolute file or directory names.  The hash value is a subroutine
963reference to pass the value array element containing the file,
964directory, pipe or syslog entry to.  The hash does not distinguish
965between directives that take only filenames, only directories or both.
966
967The hash value for the lowercase directive name is a subroutine
968reference.  The subroutine returns 1 if its only argument is a path
969and 0 otherwise.  The /dev/null equivalent (C<< File::Spec->devnull >>)
970for the operating system being used is not counted as a path, since on
971some operating systems the /dev/null equivalent is not a filename,
972such as nul on Windows.
973
974The subroutine actually does not check if its argument is a path,
975rather it checks if the argument does not match one of the other
976possible non-path values for the specific directive because different
977operating systems have different path formats, such as Unix, Windows
978and Macintosh.  For example, ErrorLog can take a filename, such as
979
980  ErrorLog /var/log/httpd/error_log
981
982or a piped command, such as
983
984  ErrorLog "| cronolog /var/log/httpd/%Y/%m/%d/error.log"
985
986or a syslog entry of the two forms:
987
988  ErrorLog syslog
989  ErrorLog syslog:local7
990
991The particular subroutine for ErrorLog checks if the value is not
992equal to C<< File::Spec->devnull >>, does not begin with a | or does not
993match syslog(:[a-zA-Z0-9]+)?.
994
995These subroutines do not remove any "'s before checking on the type of
996value.
997
998This hash is used by C<value_is_rel_path> and
999C<orig_value_is_rel_path>.
1000
1001This is a list of directives and any special values to check for as of
1002Apache 1.3.20 with the addition of IncludeOptional from 2.4.x.
1003
1004AccessFileName is not a key in the hash because, while its value is
1005one or more relative paths, the ServerRoot is never prepended to it as
1006the AccessFileName values are looked up in every directory of the path
1007to the document being requested.
1008
1009  AccessConfig
1010  AuthGroupFile
1011  AuthUserFile
1012  CookieLog
1013  CustomLog         check for "| prog"
1014  ErrorLog          check for "| prog", or syslog or syslog:facility
1015  Include
1016  IncludeOptional
1017  LoadFile
1018  LoadModule
1019  LockFile
1020  MimeMagicFile
1021  PidFile
1022  RefererLog        check for "| prog"
1023  ResourceConfig
1024  ScoreBoardFile
1025  ScriptLog
1026  TransferLog       check for "| prog"
1027  TypesConfig
1028
1029=item %directive_value_path_element_pos
1030
1031This hash holds the indexes into the directive value array for the
1032value or values that can contain either absolute or relative file or
1033directory paths.  This hash is keyed by the lowercase version of a
1034directive name.  The hash value is a string representing an integer.
1035The string can take two forms:
1036
1037  /^\d+$/   The directive has only one value element indexed by \d+
1038            that takes a file or directory path.
1039
1040  /^-\d+$/  The directive takes any number of file or directory path
1041            elements beginning with the abs(\d+) element.
1042
1043For example:
1044
1045  # CustomLog logs/access_log common
1046  $directive_value_path_element_pos{customlog}  eq '0';
1047
1048  # LoadFile modules/mod_env.so libexec/mod_mime.so
1049  $directive_value_path_element_pos{loadfile}   eq '-0';
1050
1051  # LoadModule env_module modules/mod_env.so
1052  $directive_value_path_element_pos{loadmodule} eq '1';
1053
1054  # PidFile logs/httpd.pid
1055  $directive_value_path_element_pos{pidfile}    eq '0';
1056
1057=back
1058
1059=cut
1060
1061sub directive_value_is_not_dev_null {
1062  !is_dev_null($_[0]);
1063}
1064
1065sub directive_value_is_not_dev_null_and_pipe {
1066  if (is_dev_null($_[0])) {
1067    return 0;
1068  }
1069
1070  return $_[0] !~ /^\s*\|/;
1071}
1072
1073sub directive_value_is_not_dev_null_and_pipe_and_syslog {
1074  if (is_dev_null($_[0])) {
1075    return 0;
1076  }
1077
1078  return $_[0] !~ /^\s*(?:(?:\|)|(?:syslog(?::[a-zA-Z0-9]+)?))/;
1079}
1080
1081# This is a hash keyed by directive name and the value is an array
1082# reference.  The array element are
1083#   array    array
1084#   index    value
1085#       0    A string containing an integer that describes the element
1086#            position(s) that contains the file or directory path.
1087#            string =~ /^\d+/   a single element that contains a path
1088#            string =~ /^-\d+/  multiple elements, first is abs(\d+)
1089#       1    1 if the paths the directive accepts can be absolute and
1090#            relative, 0 if they can only be absolute
1091#       2    a subroutine reference to directive_value_is_not_dev_null,
1092#            directive_value_is_not_dev_null_and_pipe or
1093#            directive_value_is_not_dev_null_and_pipe_and_syslog.
1094
1095my %directive_info = (
1096  AccessConfig      => ['0',
1097                        1,
1098                        \&directive_value_is_not_dev_null],
1099  AuthDBGroupFile   => ['0',
1100                        0,
1101                        \&directive_value_is_not_dev_null],
1102  AuthDBMGroupFile  => ['0',
1103                        0,
1104                        \&directive_value_is_not_dev_null],
1105  AuthDBMUserFile   => ['0',
1106                        0,
1107                        \&directive_value_is_not_dev_null],
1108  AuthDBUserFile    => ['0',
1109                        0,
1110                        \&directive_value_is_not_dev_null],
1111  AuthDigestFile    => ['0',
1112                        0,
1113                        \&directive_value_is_not_dev_null],
1114  AgentLog          => ['0',
1115                        0,
1116                        \&directive_value_is_not_dev_null_and_pipe],
1117  AuthGroupFile     => ['0',
1118                        1,
1119                        \&directive_value_is_not_dev_null],
1120  AuthUserFile      => ['0',
1121                        1,
1122                        \&directive_value_is_not_dev_null],
1123  CacheRoot         => ['0',
1124                        0,
1125                        \&directive_value_is_not_dev_null],
1126  CookieLog         => ['0',
1127                        1,
1128                        \&directive_value_is_not_dev_null],
1129  CoreDumpDirectory => ['0',
1130                        0,
1131                        \&directive_value_is_not_dev_null],
1132  CustomLog         => ['0',
1133                        1,
1134                        \&directive_value_is_not_dev_null_and_pipe],
1135  Directory         => ['0',
1136                        0,
1137                        \&directive_value_is_not_dev_null],
1138  DocumentRoot      => ['0',
1139                        0,
1140                        \&directive_value_is_not_dev_null],
1141  ErrorLog          => ['0',
1142                        1,
1143                        \&directive_value_is_not_dev_null_and_pipe_and_syslog],
1144  Include           => ['0',
1145                        1,
1146                        \&directive_value_is_not_dev_null],
1147  IncludeOptional   => ['0',
1148                        1,
1149                        \&directive_value_is_not_dev_null],
1150  LoadFile          => ['-0',
1151                        1,
1152                        \&directive_value_is_not_dev_null],
1153  LoadModule        => ['1',
1154                        1,
1155                        \&directive_value_is_not_dev_null],
1156  LockFile          => ['0',
1157                        1,
1158                        \&directive_value_is_not_dev_null],
1159  MMapFile          => ['0',
1160                        0,
1161                        \&directive_value_is_not_dev_null],
1162  MimeMagicFile     => ['0',
1163                        1,
1164                        \&directive_value_is_not_dev_null],
1165  PidFile           => ['0',
1166                        1,
1167                        \&directive_value_is_not_dev_null],
1168  RefererLog        => ['0',
1169                        1,
1170                        \&directive_value_is_not_dev_null_and_pipe],
1171  ResourceConfig    => ['0',
1172                        1,
1173                        \&directive_value_is_not_dev_null],
1174  RewriteLock       => ['0',
1175                        0,
1176                        \&directive_value_is_not_dev_null],
1177  ScoreBoardFile    => ['0',
1178                        1,
1179                        \&directive_value_is_not_dev_null],
1180  ScriptLog         => ['0',
1181                        1,
1182                        \&directive_value_is_not_dev_null],
1183  ServerRoot        => ['0',
1184                        0,
1185                        \&directive_value_is_not_dev_null],
1186  TransferLog       => ['0',
1187                        1,
1188                        \&directive_value_is_not_dev_null_and_pipe],
1189  TypesConfig       => ['0',
1190                        1,
1191                        \&directive_value_is_not_dev_null]);
1192
1193# Set up the three exported hashes using the information in
1194# %directive_info.  Use lowercase directive names.
1195foreach my $key (keys %directive_info) {
1196  my $ref                                    = $directive_info{$key};
1197  my $lc_key                                 = lc($key);
1198  my ($index, $abs_and_rel, $sub_ref)        = @$ref;
1199  if ($abs_and_rel) {
1200    $directive_value_takes_rel_path{$lc_key} = $sub_ref;
1201  }
1202  $directive_value_takes_abs_path{$lc_key}   = $sub_ref;
1203  $directive_value_path_element_pos{$lc_key} = $index;
1204}
1205
1206=head1 SEE ALSO
1207
1208L<Apache::ConfigParser::Directive> and L<Tree::DAG_Node>.
1209
1210=head1 AUTHOR
1211
1212Blair Zajac <blair@orcaware.com>.
1213
1214=head1 COPYRIGHT
1215
1216Copyright (C) 2001-2005 Blair Zajac.  All rights reserved.  This
1217program is free software; you can redistribute it and/or modify it
1218under the same terms as Perl itself.
1219
1220=cut
1221
12221;
1223