File Coverage

blib/lib/Apache/Admin/Config.pm
Criterion Covered Total %
statement 364 457 79.6
branch 146 234 62.3
condition 72 135 53.3
subroutine 54 72 75.0
pod 2 2 100.0
total 638 900 70.8


line stmt bran cond sub pod time code
1             package Apache::Admin::Config;
2              
3 13     13   110597 use 5.005;
  13         52  
  13         1056  
4 13     13   627 use strict;
  13         380  
  13         772  
5 13     13   12780 use FileHandle;
  13         205153  
  13         101  
6              
7             $Apache::Admin::Config::VERSION = '0.95';
8             $Apache::Admin::Config::DEBUG = 0;
9              
10             =pod
11              
12             =head1 NAME
13              
14             Apache::Admin::Config - A module to read/write Apache like configuration files
15              
16             =head1 SYNOPSIS
17              
18             use Apache::Admin::Config;
19              
20             # Parse an apache configuration file
21              
22             my $conf = new Apache::Admin::Config "/path/to/config_file.conf"
23             or die $Apache::Admin::Config::ERROR;
24              
25             my $directive = $conf->directive('documentroot');
26              
27             print $directive->name; # "documentroot"
28             print $directive->value; # "/my/document/root"
29             print $directive->type; # "directive"
30              
31             $directive->isin($conf); # true
32              
33             $directive->delete;
34              
35             # print the directive list
36              
37             foreach($conf->directive())
38             {
39             print $_->name, "\n";
40             }
41              
42             # print the virtualhost list
43              
44             print $_->section('servername')->value(), "\n"
45             foreach $conf->section(-name => "virtualhost");
46              
47             # add a directive in all virtualhosts
48              
49             foreach($conf->section(-name => "virtualhost"))
50             {
51             $_->add_directive(php_admin_value => 'open_basedir "/path"');
52             }
53              
54             # Deleting all "AddType" directives
55              
56             $_->delete for $conf->directive("AddType");
57              
58             # saving changes in place
59              
60             $conf->save;
61              
62             =head1 DESCRIPTION
63              
64             C provides an object oriented interface for
65             reading and writing Apache-like configuration files without affecting
66             comments, indentation, or truncated lines.
67              
68             You can easily extract informations from the apache configuration, or
69             manage htaccess files.
70              
71             I wrote this class because I work for an IPP, and we often manipulate
72             apache configuration files for adding new clients, activate some
73             features or un/locking directories using htaccess, etc. It can also be
74             useful for writing some one-shoot migrations scripts in few lines.
75              
76             =head1 METHODES
77              
78             =head2 new
79              
80             $obj = new Apache::Admin::Config [/path/to/file|handle],
81             [-indent => $integer], ['-create'], ['-no-comment-grouping'],
82             ['-no-blank-grouping']
83              
84             Create or read, if given in argument, an apache like configuration
85             file, and return an Apache::Admin::Config instence.
86              
87             Arguments:
88              
89             =over 4
90              
91             =item I>
92              
93             Path to the configuration file to parse. If none given, create a new
94             one.
95              
96             =item I>
97              
98             Instead of specify a path to a file, you can give a reference to an
99             handle that point to an already openned file. You can do this like
100             this :
101              
102             my $obj = new Apache::Admin::Config (\*MYHANDLE);
103              
104             =item I> =E I<$integer>
105              
106             If greater than 0, activates the indentation on added lines, the
107             integer tell how many spaces you went per level of indentation
108             (suggest 4). A negative value means padding with tabulation(s).
109              
110             =item I>
111              
112             If present and path to an unexisting file is given, don't return an
113             error.
114              
115             =item I>
116              
117             When there are several successive comment-lines, if comment grouping
118             is enabled only one comment item is created.
119              
120             If present, disable comment grouping at parsing time. Enabled by
121             default.
122              
123             =item I>
124              
125             Same as comment grouping but for blank lines.
126              
127             =back
128              
129             =cut
130              
131             # We wrap the whole module part because we manipulate a tree with
132             # circular references. Because of the way perl's garbage collector
133             # works, we have to isolate circular reference in another package to
134             # be able to destroy circular reference before the garbage collector
135             # try to destroy the tree. Without this mechanism, the DESTROY event
136             # will never be called.
137              
138             sub new
139             {
140 15     15 1 19851 my $proto = shift;
141 15   33     141 my $class = ref $proto || $proto;
142 15         38 my $self = {};
143 15         55 bless $self, $class;
144              
145 15         34 my $htaccess = shift;
146              
147 15 50       179 my $tree = $self->{tree} = new Apache::Admin::Config::Tree(@_)
148             or return;
149              
150 15 100       110 if(defined $htaccess)
151             {
152 7 50       33 $tree->_load($htaccess) || return undef;
153             }
154             else # if htaccess doesn't exists, init new one
155             {
156 8 50       40 $tree->_init || return undef;
157             }
158            
159 15         87 return $self;
160             }
161              
162             =pod
163              
164             =head2 save
165              
166             $obj->save(['/path/to/file'|HANDLE], ['-reformat'])
167              
168             Write modifications to the configuration file. If a path to a file is
169             given, save the modification to this file instead. You also can give a
170             reference to a filehandle like this :
171              
172             $conf->save(\*MYHANDLE) or die($conf->error());
173              
174             Note: If you invoke save() on an object instantiated with a filehandle,
175             you should emptied it before. Keep in mind that the constructor don't
176             seek the FH to the begin neither before nor after reading it.
177              
178             =cut
179              
180             sub save
181             {
182 2     2 1 868 my $reformat =
183             Apache::Admin::Config::Tree::_get_arg(\@_, '-reformat!');
184              
185 2         5 my($self, $saveas) = @_;
186              
187 2 100       11 my $htaccess =
188             defined $saveas ? $saveas : $self->{tree}->{htaccess};
189              
190 2 50       8 return $self->_set_error("you have to specify a location for writing configuration")
191             unless defined $htaccess;
192              
193 2         3 my $fh;
194              
195 2 50       72 if(ref $htaccess eq 'GLOB')
196             {
197 2         3 $fh = $htaccess;
198             }
199             else
200             {
201 0 0       0 $fh = new FileHandle(">$htaccess")
202             or return $self->_set_error("can't open `$htaccess' file for read");
203             }
204              
205 2 50       20 print $fh $reformat ? $self->dump_reformat : $self->dump_raw;
206              
207 2         46 return 1;
208             }
209              
210              
211              
212             sub AUTOLOAD
213             {
214             # redirect all method to the right package
215 69     69   5509 my $self = shift;
216 69         475 my($func) = $Apache::Admin::Config::AUTOLOAD =~ /[^:]+$/g;
217 69         292 return $self->{tree}->$func(@_);
218             }
219              
220             sub DESTROY
221             {
222 15     15   40069 shift->{tree}->destroy;
223             }
224              
225             package Apache::Admin::Config::Tree;
226              
227 13     13   12971 use strict;
  13         30  
  13         586  
228 13     13   86 use Carp;
  13         34  
  13         870  
229 13     13   71 use FileHandle;
  13         25  
  13         66  
230 13     13   32735 use overload nomethod => \&to_string;
  13         16372  
  13         106  
231              
232              
233             sub new
234             {
235 15     15   40 my $proto = shift;
236 15   33     106 my $class = ref $proto || $proto;
237 15         38 my $self = {};
238 15         52 bless($self, $class);
239              
240 15         85 $self->{indent} = _get_arg(\@_, '-indent');
241 15         70 $self->{create} = _get_arg(\@_, '-create!');
242              
243 15         56 $self->{'comment-grouping'} =
244             ! _get_arg(\@_, '-no-comment-grouping!');
245 15         69 $self->{'blank-grouping'} =
246             ! _get_arg(\@_, '-no-blank-grouping!');
247              
248             # init the tree
249 15         47 $self->{type} = 'section';
250 15         44 $self->{parent} = undef;
251 15         51 $self->{children} = [];
252              
253 15         163 return($self);
254             }
255              
256             =pod
257              
258             =head2 dump_raw
259              
260             $obj->dump_raw
261              
262             Returns the configuration file as same as it will be if it was saved
263             in a file with the B method. If you don't call this method
264             from the top level section, it returns the part of the configuration
265             file that is under the object's context.
266              
267             =cut
268              
269             sub dump_raw
270             {
271 3     3   5 my($self) = @_;
272 3   50     31 return join '', $self->{raw}||'', $self->_deploy(), $self->{raw2}||'';
      50        
273             }
274              
275             =pod
276              
277             =head2 dump_reformat
278              
279             $obj->dump_raw
280              
281             Same as dump_raw(), but reformat each line. Usefull used with -indent
282             constructor parameter.
283              
284             =cut
285              
286             sub dump_reformat
287             {
288 0     0   0 my($self) = @_;
289 0         0 my $string = '';
290 0         0 foreach($self->select())
291             {
292 0 0       0 if($_->type eq 'section')
293             {
294 0         0 $string .= $self->write_section($_->name, $_->value);
295 0         0 $string .= $_->dump_reformat();
296 0         0 $string .= $self->write_section_closing($_->name);
297             }
298             else
299             {
300             # is it perl 5.0004 compatible ??
301 0         0 my $method = "write_".$_->type;
302 0         0 my $name;
303 0 0       0 if($_->type eq 'directive')
    0          
    0          
304             {
305 0         0 $name = $_->name;
306             }
307             elsif($_->type eq 'comment')
308             {
309 0         0 $name = $_->value;
310             }
311             elsif($_->type eq 'blank')
312             {
313 0         0 $name = $_->{length};
314             }
315              
316 0 0       0 my $value = defined $_->value ? $_->value : '';
317 0   0     0 $string .= $self->$method($name||'', $value);
318             }
319             }
320              
321 0         0 return $string;
322             }
323              
324             =pod
325              
326             =head2 select
327              
328             @result = $obj->select
329             (
330             [-type => $type],
331             [-name => $name],
332             [-value => $value],
333             [-which => $index],
334             );
335              
336             @directives = $obj->select('directive');
337             @sections_foo = $obj->select('section', 'Foo');
338              
339             This method search in the current context for items (directives, sections,
340             comments...) that correspond to a properties given by arguments. It returns
341             a B of matched nods.
342              
343             This method can only be called on an object of type "section". This
344             method search only for elements in the section pointed by object, and
345             isn't recursive. So elements B sub-sections of current section
346             aren's seek (it's not a bug).
347              
348             Arguments:
349              
350             =over 4
351              
352             =item B>
353              
354             Selects item(s) of C type.
355              
356             =item B>
357              
358             Selects item(s) with C name.
359              
360             =item B>
361              
362             Selects item(s) with C value.
363              
364             =item B>
365              
366             Instead of returning a list of items, returns only a single one
367             pointed by index given to the -which option. Caution, returns an empty
368             string if none selected, so don't cascade your methodes calls like
369             $obj->select(-which=>0)->name. Index starts at 0.
370              
371             =back
372              
373             Method returns a list of item(s) founds. Each items is an
374             Apache::Admin::Config object with same methods but pointing to a
375             different part of the tree.
376              
377             =cut
378              
379             sub select
380             {
381 32     32   48 my $self = shift;
382              
383 32         110 my $which = _get_arg(\@_, '-which');
384              
385 32         57 my %args;
386 32   50     87 $args{type} = _get_arg(\@_, '-type') || undef;
387 32   50     107 $args{name} = _get_arg(\@_, '-name') || undef;
388 32   100     100 $args{value} = _get_arg(\@_, '-value') || undef;
389              
390             # accepting old style arguments for backward compatibilitie
391 32 50       113 $args{type} = shift unless defined $args{type};
392 32 50       122 $args{name} = shift unless defined $args{name};
393 32 100       102 $args{value} = shift unless defined $args{value};
394              
395             # _get_arg return undef on error or empty string on not founded rule
396 32 50       92 return $self->_set_error('malformed arguments')
397             if not defined $which;
398             # $which isn't an integer
399 32 50       112 return $self->_set_error('error in -which argument: not an integer')
400             if $which =~ /[^\d\-]/;
401 32 50       95 return $self->_set_error('too many arguments')
402             if @_;
403 32 50       126 return $self->_set_error('method not allowed')
404             unless $self->{type} eq 'section';
405              
406 32 100       192 $args{name} = lc($args{name}) if defined $args{name};
407 32 100       125 $args{value} = lc($args{value}) if defined $args{value};
408              
409 32         59 my @children = @{$self->{children}};
  32         587  
410              
411 32         96 my $n = 0;
412 32         75 my @items;
413             # pre-select fields to test on each objects
414 32         151 my @field_to_test =
415             grep(defined $args{$_}, qw(type name value));
416              
417 32         72 foreach my $item (@children)
418             {
419 3579         4442 my $match = 1;
420             # for all given arguments, we test if it matched
421             # for missing aguments, match is always true
422 3579         4785 foreach(@field_to_test)
423             {
424 3985 50       9562 if(defined $item->{$_})
425             {
426 3985         8129 $match = $args{$_} eq lc($item->{$_});
427             }
428             else
429             {
430 0         0 $match = 0;
431             }
432 3985 100       8457 last unless $match;
433             }
434              
435 3579 100       9672 if($match)
436             {
437 495         935 push(@items, $item);
438             }
439             }
440              
441 32 100       99 if(length $which)
442             {
443 2 50       13 return defined overload::StrVal($items[$which]) ? $items[$which] : '';
444             }
445             else
446             {
447             # We don't return just @items but transfort it in a list
448             # because in scalar context, returning an array is same as
449             # returning the number of ellements in it, but we want return
450             # the _last_ element like a list do une scalar context. If you
451             # have a better/nicer idea...
452 30 50       813 return(@items ? @items[0 .. $#items] : ());
453             }
454             }
455              
456             =pod
457              
458             =head2 directive
459              
460             @directives = $obj->directive(args...)
461              
462             Same as calling select('directive', args...)
463              
464             =cut
465              
466             sub directive
467             {
468 12     12   23 my $self = shift;
469 12         44 $self->select('directive', @_);
470             }
471              
472             =pod
473              
474             =head2 section
475              
476             @sections = $obj->section(args...)
477              
478             Same as calling select('section', args...)
479              
480             =cut
481              
482             sub section
483             {
484 10     10   19 my $self = shift;
485 10         32 $self->select('section', @_);
486             }
487              
488             =pod
489              
490             =head2 comment
491              
492             @comments = $obj->comment(args...)
493              
494             Same as calling select('comment', args...)
495              
496             =cut
497              
498             sub comment
499             {
500 7     7   337 my $self = shift;
501 7         49 $self->select('comment', undef, @_);
502             }
503              
504             =pod
505              
506             =head2 blank
507              
508             @blanks = $obj->blank(args...)
509              
510             Same as calling select('blank', args...)
511              
512             =cut
513              
514             sub blank
515             {
516 0     0   0 my $self = shift;
517 0         0 $self->select('blank', @_);
518             }
519              
520             sub indent
521             {
522 51     51   73 my($self) = @_;
523 51         99 my $parent = $self->parent;
524 51         69 my $level = 0;
525 51   50     100 my $indent = $self->top->{indent} || 0;
526 51         130 while(defined $parent)
527             {
528 6         13 $parent = $parent->parent;
529 6         15 $level++;
530             }
531              
532 51 50       317 return($level
    100          
533             ? (($indent > 0 ? ' ' : "\t") x (abs $indent)) x $level
534             : '');
535             }
536              
537             =pod
538              
539             =head2 set_write_directive
540              
541             $conf->set_write_directive($code);
542              
543             Replace the directive writing engine by you own code. Code is call for
544             adding new directives, or when you tell Apache::Admin::Config to
545             reformat the whole configuration file. See B and
546             B methods for more details.
547              
548             Your handler receives 3 arguments : $self, $name and $value. You can
549             call the C method to get the number of spaces to put before
550             the current line (see B methods for more details)
551              
552             $conf->set_write_directive(sub
553             {
554             my($self, $name, $value) = @_;
555             return $self->indent . "$name $value\n";
556             }
557              
558             =cut
559              
560             sub write_directive
561             {
562 12     12   19 my($self) = @_;
563 12   50     35 my $code = $self->_get_var('_write_directive') || \&default_write_directive;
564 12         36 &$code(@_);
565             }
566              
567             sub set_write_directive
568             {
569 0     0   0 my($self, $code) = @_;
570 0         0 $self->{_write_directive} = $code;
571             }
572              
573             sub default_write_directive
574             {
575 12     12   21 my($self, $name, $value) = @_;
576 12 50       26 return undef unless defined $name;
577 12 100       31 $value = defined $value ? $value : '';
578 12         35 return($self->indent."$name $value\n");
579             }
580              
581             =pod
582              
583             =head2 set_write_section
584              
585             $conf->set_write_section($code);
586              
587             Same as set_write_directive() but for section.
588              
589             Your handler receives 3 arguments: $self, $name and $value. You can
590             call the C method to get the number of spaces to put before
591             the current line (see B methods for more details)
592              
593             $conf->set_write_section(sub
594             {
595             my($self, $name, $value) = @_;
596             return $self->indent . "<$name $value>\n";
597             }
598              
599             =cut
600              
601             sub write_section
602             {
603 14     14   26 my($self) = @_;
604 14   50     46 my $code = $self->_get_var('_write_section') || \&default_write_section;
605 14         39 &$code(@_);
606             }
607              
608             sub set_write_section
609             {
610 0     0   0 my($self, $code) = @_;
611 0         0 $self->{_write_section} = $code;
612             }
613              
614             sub default_write_section
615             {
616 14     14   26 my($self, $name, $value) = @_;
617 14         53 return($self->indent."<$name $value>\n");
618             }
619              
620             =pod
621              
622             =head2 set_write_section_closing
623              
624             $conf->set_write_section_closing($code);
625              
626             Same as set_write_directive() but for end of sections.
627              
628             Your handler receives 2 arguments: $self and $name. You can call the
629             C method to get the number of spaces to put before the
630             current line (see B methods for more details)
631              
632             $conf->set_write_section_closing(sub
633             {
634             my($self, $name) = @_;
635             return $self->indent . "\n";
636             }
637              
638             =cut
639              
640             sub write_section_closing
641             {
642 14     14   28 my($self) = @_;
643 14   50     36 my $code = $self->_get_var('_write_section_closing') || \&default_write_section_closing;
644 14         40 &$code(@_);
645             }
646              
647             sub set_write_section_closing
648             {
649 0     0   0 my($self, $code) = @_;
650 0         0 $self->{_write_section_closing} = $code;
651             }
652              
653             sub default_write_section_closing
654             {
655 14     14   22 my($self, $name) = @_;
656 14         30 return($self->indent."\n");
657             }
658              
659             =pod
660              
661             =head2 set_write_comment
662              
663             $conf->set_write_comment($code);
664              
665             Same as set_write_directive() but for comments.
666              
667             Your handler receives 2 arguments: $self and $value. You can call the
668             C method to get the number of spaces to put before the
669             current line (see B methods for more details)
670              
671             $conf->set_write_comment(sub
672             {
673             my($self, $value) = @_;
674             # handle comment grouping
675             $value =~ s/\n/\n# /g;
676             return $self->indent . join('#', split(/\n/, $value));
677             }
678              
679             =cut
680              
681             sub write_comment
682             {
683 11     11   14 my($self) = @_;
684 11   50     31 my $code = $self->_get_var('_write_comment') || \&default_write_comment;
685 11         29 &$code(@_);
686             }
687              
688             sub set_write_comment
689             {
690 0     0   0 my($self, $code) = @_;
691 0         0 $self->{_write_comment} = $code;
692             }
693              
694             sub default_write_comment
695             {
696 11     11   17 my($self, $value) = @_;
697 11         14 $value =~ s/\n/\n# /g;
698 11         23 return $self->indent."# $value\n";
699             }
700              
701              
702             =pod
703              
704             =head2 set_write_blank
705              
706             $conf->set_write_blank($code);
707              
708             Same as set_write_directive() but for blank lines.
709              
710             Your handler receives 2 arguments: $self and $number.
711              
712             $conf->set_write_blank(sub
713             {
714             my($self, $number) = @_;
715             return $number x "\n";
716             }
717              
718             =cut
719              
720             sub write_blank
721             {
722 0     0   0 my($self) = @_;
723 0   0     0 my $code = $self->_get_var('_write_blank') || \&default_write_blank;
724 0         0 &$code(@_);
725             }
726              
727             sub set_write_blank
728             {
729 0     0   0 my($self, $code) = @_;
730 0         0 $self->{_write_blank} = $code;
731             }
732              
733             sub default_write_blank
734             {
735 0     0   0 my($self, $number) = @_;
736 0         0 return "\n" x $number;
737             }
738              
739              
740             =pod
741              
742             =head2 add
743              
744             $item = $obj->add
745             (
746             $type|$item, [$name], [$value],
747             [-before => $target | -after => $target | '-ontop' | '-onbottom']
748             );
749              
750             $item = $obj->add('section', foo => 'bar', -after => $conf_item_object);
751             $item = $obj->add('comment', 'a simple comment', '-ontop');
752              
753             Add a line of type I<$type> with name I and value I in the
754             context pointed by B<$object>.
755              
756             Aguments:
757              
758             =over 4
759              
760             =item B>
761              
762             Type of object to add (directive, section, comment or blank).
763              
764             =item B>
765              
766             Only relevant for directives and sections.
767              
768             =item B>
769              
770             For directive and section, it defines the value, for comments it
771             defined the text.
772              
773             =item B> =E I
774              
775             Inserts item one line before I. I _have_ to be in the
776             same context
777              
778             =item B> =E I
779              
780             Inserts item one line after I. I _have_ to be in the
781             same context
782              
783             =item B>
784              
785             Insert item on the fist line of current context;
786              
787             =item B>
788              
789             Iinsert item on the last line of current context;
790              
791             =back
792              
793             Returns the added item
794              
795             =cut
796              
797             sub add
798             {
799 37     37   57 my $self = shift;
800              
801 37         113 my($target, $where) = _get_arg(\@_, '-before|-after|-ontop!|-onbottom!');
802              
803 37 50       123 $target = $target->{tree} if ref $target eq 'Apache::Admin::Config';
804              
805             # _get_arg return undef on error or empty string on not founded rule
806 37 50       92 return($self->_set_error('malformed arguments'))
807             if(not defined $target);
808 37 50       100 return($self->_set_error('too many arguments'))
809             if(@_ > 3);
810 37         74 my($type, $name, $value) = @_;
811              
812 37 50       125 return($self->_set_error('wrong type for destination'))
813             unless($self->{type} eq 'section');
814              
815 37 100       90 $where = defined $where ? $where : '-onbottom'; # default behavior
816 37 100 66     232 if(($where eq '-before' || $where eq '-after') && defined $target)
      66        
817             {
818 3 50 33     75 return $self->_set_error("target `$target' isn\'t an object")
819             unless ref $target && $target->isa('Apache::Admin::Config::Tree');
820 3 50       15 return $self->_set_error('invalid target context')
821             unless $target->isin($self);
822             }
823              
824 37         91 my $index;
825              
826 37 50 33     319 if($where eq '-before')
    100          
    100          
    50          
827             {
828 0         0 $index = $target->_get_index;
829             }
830             elsif($where eq '-after')
831             {
832 3         14 $index = $target->_get_index + 1;
833             }
834             elsif($where eq '-ontop')
835             {
836 6         10 $index = 0;
837             }
838             elsif($where eq '-onbottom' || $where eq '')
839             {
840 28         48 $index = -1;
841             }
842             else
843             {
844 0         0 return $self->_set_error('malformed arguments');
845             }
846              
847 37         65 my $item;
848              
849 37 50       157 if(ref $type)
    100          
    100          
    50          
    0          
850             {
851 0         0 $item = $type;
852 0         0 $self->_add_child($item, $index);
853             }
854             elsif($type eq 'section')
855             {
856 14 50 33     83 return $self->_set_error('to few arguments')
857             unless(defined $name and defined $value);
858 14         45 my $raw = $self->write_section($name, $value);
859 14         55 my $length = () = $raw =~ /\n/g;
860 14         54 $item = $self->_insert_section($name, $value, $raw, $length, $index);
861 14         39 $item->{raw2} = $self->write_section_closing($name);
862 14         76 $item->{length2} = () = $item->{raw2} =~ /\n/g;
863             }
864             elsif($type eq 'directive')
865             {
866 12 50       29 return $self->_set_error('to few arguments')
867             unless(defined $name);
868 12         40 my $raw = $self->write_directive($name, $value);
869 12         41 my $length = () = $raw =~ /\n/g;
870 12         48 $item = $self->_insert_directive($name, $value, $raw, $length, $index);
871             }
872             elsif($type eq 'comment')
873             {
874             # $name contents value here
875 11 50       22 return $self->_set_error('to few arguments')
876             unless(defined $name);
877 11 100 66     41 my $group = defined $value && $value ? 1 : 0;
878 11         43 $item = $self->_insert_comment($name,
879             $self->write_comment($name), $index, $group);
880             }
881             elsif($type eq 'blank')
882             {
883             # enabled by default
884 0 0       0 my $group = defined $name ? ($name ? 1 : 0) : 1;
    0          
885 0         0 $item = $self->_insert_blank($self->write_blank(1), $index, $group);
886             }
887             else
888             {
889 0         0 return $self->_set_error("invalid type `$type'");
890             }
891              
892 37         171 return $item;
893             }
894              
895             =pod
896              
897             =head2 add_section
898              
899             $section = $obj->add_section($name, $value)
900              
901             Same as calling add('section', $name, $value)
902              
903             =cut
904              
905             sub add_section
906             {
907 13     13   741 my $self = shift;
908 13         40 return $self->add('section', @_);
909             }
910              
911             =pod
912              
913             =head2 add_directive
914              
915             $directive = $obj->add_directive($name, $value)
916              
917             Same as calling add('directive', $name, $value)
918              
919             =cut
920              
921             sub add_directive
922             {
923 11     11   16 my $self = shift;
924 11         33 return $self->add('directive', @_);
925             }
926              
927             =pod
928              
929             =head2 add_comment
930              
931             $comment = $obj->add_comment("string", [$group])
932              
933             Same as calling add('comment', 'string', )
934              
935             $group is a boolean value that control grouping of consecutive comment
936             lines. Disabled by default.
937              
938             =cut
939              
940             sub add_comment
941             {
942 10     10   14 my $self = shift;
943 10         25 return $self->add('comment', @_);
944             }
945              
946             =pod
947              
948             =head2 add_blank
949              
950             $blank = $obj->add_blank([$group])
951              
952             Same as calling add('blank')
953              
954             $group is a boolean value that control grouping of consecutive blank
955             lines. Enabled by default.
956              
957             =cut
958              
959             sub add_blank
960             {
961 0     0   0 my $self = shift;
962 0         0 return $self->add('blank', @_);
963             }
964              
965              
966             =pod
967              
968             =head2 set_value
969              
970             $obj->set_value($newvalue)
971              
972             Change the value of a directive or section. If no argument given,
973             return the value.
974              
975             =head2 value
976              
977             Returns the value of item pointed by the object if any.
978              
979             (Actually C and C are the same method)
980              
981             =cut
982              
983             *set_value = \&value;
984              
985             sub value
986             {
987 26     26   736 my $self = shift;
988 26   100     116 my $newvalue = shift || return $self->{value};
989              
990 9         12 my $type = $self->{type};
991            
992 9 100 100     35 if($type eq 'directive' or $type eq 'section')
    50          
993             {
994             # keep indentation
995 6         26 (my $indent = $self->{raw}) =~ s/^(\s*).*$/$1/s;
996 6 50       13 if($newvalue =~ /\n/)
997             {
998             # new value is multilines
999             # write the raw version
1000 0 0       0 $self->{raw} = sprintf
1001             (
1002             $indent . ($type eq 'directive' ? '%s %s' : '<%s %s>')."\n",
1003             $self->{name},
1004             join(" \\\n", split(/\n/, $newvalue)),
1005             );
1006             # clean it
1007 0         0 $self->{value} = join(' ', map {s/^\s*|\s*$//g; $_} split(/\n/, $newvalue));
  0         0  
  0         0  
1008             # count lines
1009 0         0 $self->{length} = 1 + $newvalue =~ s/\n//g;
1010             }
1011             else
1012             {
1013 6 100       11 if($type eq 'directive')
1014             {
1015 3         9 $self->{raw} = "$indent$self->{name} $newvalue\n";
1016             }
1017             else
1018             {
1019 3         17 $self->{raw} = "$indent<$self->{name} $newvalue>\n";
1020             }
1021 6         7 $self->{value} = $newvalue;
1022 6         8 $self->{length} = 1;
1023             }
1024             }
1025             elsif($type eq 'comment')
1026             {
1027 3         8 $newvalue = join(' ', split(/\n/, $newvalue));
1028             # keep spaces before and after the sharp comment and the
1029             # number of sharps used (it's pure cosmetic) and put it on
1030             # front of the new comment
1031 3         20 $self->{raw} =~ s/^(\s*\#+\s*).*$/$1$newvalue\n/s;
1032 3         6 $self->{value} = $newvalue
1033             }
1034             else
1035             {
1036 0         0 return($self->_set_error('method not allowed'));
1037             }
1038              
1039 9         15 return($newvalue);
1040             }
1041              
1042             =pod
1043              
1044             =head2 move
1045              
1046             $obj->move
1047             (
1048             $dest_section,
1049             -before => target |
1050             -after => $target |
1051             '-ontop' |
1052             '-onbottom'
1053             )
1054              
1055             Move item into given section. See C method for options
1056             description.
1057              
1058             =cut
1059              
1060             sub move
1061             {
1062 0     0   0 my $self = shift;
1063 0         0 my $dest = shift;
1064 0 0       0 return $self->_set_error("cannot move this section in a subsection of itself")
1065             if($dest->isin($self, '-recursif'));
1066 0         0 $self->unlink();
1067 0         0 $dest->add($self, @_);
1068 0         0 return;
1069             }
1070              
1071             =pod
1072              
1073             =head2 copy
1074              
1075             $item->copy
1076             (
1077             $dest_section,
1078             -before => target |
1079             -after => $target |
1080             '-ontop' |
1081             '-onbottom'
1082             )
1083              
1084             Copy item into given section. See C method for options
1085             description.
1086              
1087             =cut
1088              
1089             sub copy
1090             {
1091 0     0   0 my $self = shift;
1092 0         0 my $dest = shift;
1093             # clone item
1094 0         0 my $clone = $self->clone();
1095             # insert into destination
1096 0         0 return $dest->add($clone, @_);
1097             }
1098              
1099             =pod
1100              
1101             =head2 clone
1102              
1103             $clone = $item->clone();
1104              
1105             Clone item and all its children. Returns the cloned item.
1106              
1107             =cut
1108              
1109             sub clone
1110             {
1111 0     0   0 my($self) = @_;
1112              
1113 0         0 my $clone = bless({});
1114 0         0 foreach(keys %$self)
1115             {
1116 0 0       0 next if $_ eq 'parent';
1117 0         0 $clone->{$_} = $self->{$_};
1118             }
1119              
1120 0 0       0 if($self->type() eq 'section')
1121             {
1122             # initialize children list
1123 0         0 $clone->{children} = [];
1124             # clone each children
1125 0         0 foreach($self->select())
1126             {
1127 0         0 $clone->_add_child($_->clone());
1128             }
1129             }
1130              
1131 0         0 return $clone;
1132             }
1133              
1134             =pod
1135              
1136             =head2 first_line
1137              
1138             =cut
1139              
1140             sub first_line
1141             {
1142 40     40   88 my($self) = @_;
1143 40 50       86 return 1 unless $self->parent;
1144 40         251 return ($self->top->_count_lines($self))[0];
1145             }
1146              
1147             =pod
1148              
1149             =head2 last_line
1150              
1151             =cut
1152              
1153             sub last_line
1154             {
1155 0     0   0 my($self) = @_;
1156 0 0       0 return ($self->top->_count_lines($self))[0]
1157             unless $self->parent;
1158 0         0 return ($self->top->_count_lines_last($self))[0];
1159             }
1160              
1161             =pod
1162              
1163             =head2 count_lines
1164              
1165             =cut
1166              
1167             sub count_lines
1168             {
1169 0     0   0 my($self) = @_;
1170 0 0       0 if($self->type eq 'section')
1171             {
1172 0         0 return $self->last_line - $self->first_line + 1;
1173             }
1174             else
1175             {
1176 0         0 return $self->{length};
1177             }
1178             }
1179              
1180             =pod
1181              
1182             =head2 isin
1183              
1184             $boolean = $obj->($section_obj, ['-recursif'])
1185              
1186             Returns true if object point to a rule that is in the section
1187             represented by $section_obj. If C<-recursif> option is present, true
1188             is also return if object is a sub-section of target.
1189              
1190            
1191            
1192             directive test
1193            
1194            
1195              
1196             $test_directive->isin($target_section) => return false
1197             $test_directive->isin($sub_section) => return true
1198             $test_directive->isin($target_section, '-recursif') => return true
1199             $target_section->isin($target_section) => return true
1200              
1201             =cut
1202              
1203             sub isin
1204             {
1205 9     9   894 my $self = shift;
1206 9         34 my $recursif = _get_arg(\@_, '-recursif!');
1207 9   50     31 my $target = shift || return $self->_set_error('too few arguments');
1208 9 100       48 $target = $target->{tree} if ref $target eq 'Apache::Admin::Config';
1209 9 50       34 return 0 unless(defined $self->{parent});
1210 9 50 33     78 return($self->_set_error('target is not an object of myself'))
1211             unless(ref $target && $target->isa('Apache::Admin::Config::Tree'));
1212 9 50       38 return($self->_set_error('wrong type for target'))
1213             unless($target->{type} eq 'section');
1214 9 50       34 return 1 if overload::StrVal($self) eq overload::StrVal($target);
1215              
1216 9 100       95 if($recursif)
1217             {
1218 3         9 my $parent = $self->{parent};
1219 3         10 while(overload::StrVal($parent) ne overload::StrVal($target))
1220             {
1221 3   50     32 $parent = $parent->{parent} || return 0;
1222             }
1223 3         43 return 1;
1224             }
1225             else
1226             {
1227 6         29 return(overload::StrVal($self->{parent}) eq overload::StrVal($target))
1228             }
1229             }
1230              
1231             sub to_string
1232             {
1233 155     155   972 my($self, $other, $inv, $meth) = @_;
1234              
1235 155 100       754 if($meth eq 'eq')
    100          
    100          
    100          
    100          
1236             {
1237 12 50 0     28 if($^W and (!defined $other or !defined $self->{value}))
      33        
1238             {
1239 0         0 carp "Use of uninitialized value in string eq";
1240             }
1241 12         21 local $^W;
1242 12         53 return($other eq $self->{value});
1243             }
1244             elsif($meth eq 'ne')
1245             {
1246 3 50 0     9 if($^W and (!defined $other or !defined $self->{value}))
      33        
1247             {
1248 0         0 carp "Use of uninitialized value in string ne";
1249             }
1250 3         6 local $^W;
1251 3         14 return($other ne $self->{value});
1252             }
1253             elsif($meth eq '==')
1254             {
1255 3 50 0     13 if($^W and (!defined $other or !defined $self->{value}))
      33        
1256             {
1257 0         0 carp "Use of uninitialized value in numeric eq (==)";
1258             }
1259 3         6 local $^W;
1260 3         13 return($other == $self->{value});
1261             }
1262             elsif($meth eq '!=')
1263             {
1264 3 50 0     8 if($^W and (!defined $other or !defined $self->{value}))
      33        
1265             {
1266 0         0 carp "Use of uninitialized value in numeric ne (!=)";
1267             }
1268 3         6 local $^W;
1269 3         10 return($other != $self->{value});
1270             }
1271             elsif(!defined $self->{value})
1272             {
1273 126         366 return overload::StrVal($self);
1274             }
1275             else
1276             {
1277 8         364 return $self->{value};
1278             }
1279             }
1280              
1281              
1282             =pod
1283              
1284             =head2 name
1285              
1286             Returns the name of the current pointed object if any
1287              
1288             =head2 parent
1289              
1290             Returns the parent context of object. This method on the top level
1291             object returns C.
1292              
1293             =head2 type
1294              
1295             Returns the type of object.
1296              
1297             =cut
1298              
1299             sub name
1300             {
1301 8     8   985 return $_[0]->{name};
1302             }
1303             sub parent
1304             {
1305 339     339   1179 return $_[0]->{parent};
1306             }
1307             sub top
1308             {
1309 91     91   136 my $top = shift;
1310 91         188 while(defined $top->parent())
1311             {
1312 47         97 $top = $top->parent();
1313             }
1314 91         419 return $top;
1315             }
1316             sub type
1317             {
1318 5356     5356   21907 return $_[0]->{type};
1319             }
1320              
1321             =pod
1322              
1323             =head2 remove
1324              
1325             Synonym for unlink (deprecated). See B.
1326              
1327             =head2 unlink
1328              
1329             $boolean = $item->unlink();
1330              
1331             Unlinks item from the tree, resulting in two separate trees. The item
1332             to unlink becomes the root of a new tree.
1333              
1334             =cut
1335              
1336             *remove = \&unlink;
1337              
1338             sub unlink
1339             {
1340 3     3   7 my($self) = @_;
1341              
1342 3 50       49 if(defined $self->{parent})
1343             {
1344 3         21 my $index = $self->_get_index;
1345 3 50       26 if(defined $index)
1346             {
1347 3         38 splice(@{$self->{parent}->{children}}, $index, 1);
  3         12  
1348             }
1349             }
1350              
1351 3         21 return 1;
1352             }
1353              
1354             =pod
1355              
1356             =head2 destroy
1357              
1358             $boolean = $item->destroy();
1359              
1360             Destroy item and its children. Caution, you should call delete()
1361             method instead if you want destroy a part of a tree. This method don't
1362             notice item's parents of its death.
1363              
1364             =cut
1365              
1366             sub destroy
1367             {
1368 2090     2090   2570 my($self) = @_;
1369 2090         3545 delete $self->{parent};
1370 2090         2222 foreach(@{$self->{children}})
  2090         4881  
1371             {
1372 2072         3735 $_->destroy;
1373             }
1374 2090         6702 return 1;
1375             }
1376              
1377             =pod
1378              
1379             =head2 delete
1380              
1381             $booleen = $item->delete;
1382              
1383             Remove the current item from it's parent children list and destroy it
1384             and all its children (remove() + destroy()).
1385              
1386             =cut
1387              
1388             sub delete
1389             {
1390 3     3   8 my($self) = @_;
1391 3   33     24 return $self->unlink() && $self->destroy();
1392             }
1393              
1394             =pod
1395              
1396             =head2 error
1397              
1398             Return the last appended error.
1399              
1400             =cut
1401              
1402             sub error
1403             {
1404 0     0   0 return $_[0]->top()->{__last_error__};
1405             }
1406              
1407             #
1408             # Private methods
1409             #
1410              
1411             sub _get_var
1412             {
1413 51     51   75 my($self, $name) = @_;
1414              
1415 51         100 my $value = $self->{$name};
1416 51         122 until(defined $value)
1417             {
1418 57 100       156 $self = $self->parent() or last;
1419             }
1420              
1421 51         265 return $value;
1422             }
1423              
1424             sub _get_index
1425             {
1426 6     6   12 my($self) = @_;
1427 6 50       29 return unless defined $self->{parent}; # if called by top node
1428 6         10 my @pchildren = @{$self->{parent}->{children}};
  6         30  
1429 6         71 for(my $i = 0; $i < @pchildren; $i++)
1430             {
1431 12 100       85 return $i if overload::StrVal($pchildren[$i]) eq overload::StrVal($self);
1432             }
1433             }
1434              
1435             sub _deploy
1436             {
1437             join '',
1438             map
1439             {
1440 874 100       1720 if($_->{type} eq 'section')
  21         59  
1441             {
1442 18         43 ($_->{raw}, _deploy($_), $_->{raw2});
1443             }
1444             else
1445             {
1446 856         2979 $_->{raw};
1447             }
1448 21     21   24 } @{$_[0]->{children}};
1449             }
1450              
1451             sub _count_lines
1452             {
1453 173   100 173   544 my $c = $_[0]->{'length'} || 0;
1454 173         200 foreach my $i (@{$_[0]->{children}})
  173         485  
1455             {
1456 173 100       439 return($c+1, 1) if(overload::StrVal($_[1]) eq overload::StrVal($i));
1457 133         1221 my($rv, $found) = $i->_count_lines($_[1]);
1458 133         179 $c += $rv;
1459 133 100       318 return($c, 1) if defined $found;
1460             }
1461 132 100       434 return $c + (defined $_[0]->{length2} ? $_[0]->{length2} : 0);
1462             }
1463              
1464             sub _count_lines_last
1465             {
1466 0     0   0 my $c = $_[0]->{'length'};
1467 0         0 foreach my $i (@{$_[0]->{children}})
  0         0  
1468             {
1469 0         0 $c += ($i->_count_lines($_[1]))[0];
1470 0 0       0 return $c if($_[1] eq $i);
1471             }
1472 0         0 return $c + $_[0]->{length2};
1473             }
1474              
1475             sub _add_child
1476             {
1477 2075     2075   2993 my($self, $item, $index) = @_;
1478              
1479 2075         3941 $item->{parent} = $self;
1480 2075 100 100     5398 if(defined $index && $index != -1)
1481             {
1482 9         12 splice(@{$self->{children}}, $index, 0, $item);
  9         39  
1483             }
1484             else
1485             {
1486 2066         2215 push(@{$self->{children}}, $item);
  2066         6165  
1487             }
1488             }
1489              
1490             sub _insert_directive
1491             {
1492 748     748   2130 my($tree, $directive_name, $value, $line, $length, $index) = @_;
1493              
1494 748 100       1680 $value = defined $value ? $value : '';
1495 748         4070 $value =~ s/^\s+|\s+$//g;
1496              
1497 748         1381 my $directive = bless({});
1498 748         1845 $directive->{type} = 'directive';
1499 748         1764 $directive->{name} = $directive_name;
1500 748         1786 $directive->{value} = $value;
1501 748         1394 $directive->{raw} = $line;
1502 748         1285 $directive->{'length'} = $length;
1503              
1504 748         1709 $tree->_add_child($directive, $index);
1505              
1506 748         7138 return $directive;
1507             }
1508              
1509             sub _insert_section
1510             {
1511 56     56   168 my($tree, $section_name, $value, $line, $length, $index) = @_;
1512              
1513 56 50       123 $value = defined $value ? $value : '';
1514 56         269 $value =~ s/^\s+|\s+$//g;
1515              
1516 56         110 my $section = bless({});
1517 56         161 $section->{type} = 'section';
1518 56         143 $section->{name} = $section_name;
1519 56         119 $section->{value} = $value;
1520 56         132 $section->{children} = [];
1521 56         126 $section->{raw} = $line;
1522 56         103 $section->{'length'} = $length;
1523              
1524 56         151 $tree->_add_child($section, $index);
1525              
1526 56         120 return $section;
1527             }
1528              
1529             sub _insert_comment
1530             {
1531 4736     4736   11399 my($tree, $value, $line, $index, $group) = @_;
1532              
1533 4736         7591 my $comment = bless({});
1534              
1535             # if last item is a comment, group next comment with it to make
1536             # multi-line comment instead of several single-line comment items
1537 4736 100       9006 my $_index = defined $index ? $index : -1;
1538 4736 100 66     44943 if(defined $group && $group
      100        
      100        
1539             && defined $tree->{children}->[$_index]
1540             && $tree->{children}->[$_index]->type eq 'comment')
1541             {
1542 4109         7260 $comment = $tree->{children}->[$_index];
1543 4109         9692 $value = "\n$value";
1544             }
1545             else
1546             {
1547 627         1422 $comment->{type} = 'comment';
1548 627         1203 $tree->_add_child($comment, $index);
1549             }
1550              
1551 4736         11796 $comment->{value} .= $value;
1552 4736         9497 $comment->{raw} .= $line;
1553 4736         6447 $comment->{'length'}++;
1554              
1555 4736         50241 return $comment;
1556             }
1557              
1558             sub _insert_blank
1559             {
1560 644     644   1076 my($tree, $line, $index, $group) = @_;
1561              
1562 644         971 my $blank = bless({});
1563              
1564             # if last item is a blank line, group next blank line with it to
1565             # make multi-line blank item instead of several single-line blank
1566             # items
1567 644 50       1278 my $_index = defined $index ? $index : -1;
1568 644 50 33     5529 if(defined $group && $group
      66        
      66        
1569             && defined $tree->{children}->[$_index]
1570             && $tree->{children}->[$_index]->type eq 'blank')
1571             {
1572 0         0 $blank = $tree->{children}->[$_index];
1573             }
1574             else
1575             {
1576 644         1641 $blank->{type} = 'blank';
1577 644         1360 $tree->_add_child($blank, $index);
1578             }
1579              
1580 644         1756 $blank->{raw} .= $line;
1581 644         1024 $blank->{'length'}++;
1582              
1583 644         5470 return $blank;
1584             }
1585              
1586             sub _parse
1587             {
1588 15     15   60 my($self, $fh) = @_;
1589 15   100     133 my $file = $self->{htaccess} || '[inline]';
1590              
1591 15         38 my $cgroup = $self->{'comment-grouping'};
1592 15         39 my $bgroup = $self->{'blank-grouping'};
1593             # level is used to stock reference to the curent level, level[0] is the root level
1594 15         38 my @level = ($self);
1595 15         192 my($line, $raw_line);
1596 15         34 my $n = 0;
1597 15   100     311 while((defined $fh) && ($line = scalar <$fh>) && (defined $line))
      66        
1598             {
1599 6189         6739 $n++;
1600 6189         7172 my $length = 1;
1601 6189         7957 $raw_line = $line;
1602              
1603 6189   100     27519 while($line !~ /^\s*#/ && $line =~ s/\\$//)
1604             {
1605             # line is truncated, we want the entire line
1606 7         16 $n++;
1607 7         21 $length++;
1608 7         24 chomp($line);
1609 7 50       40 my $next .= <$fh>
1610             or return $self->_set_error(sprintf('%s: syntax error at line %d', $file, $n));
1611 7         13 $raw_line .= $next;
1612 7         78 $next =~ s/^\s*|\s*$//g;
1613 7         49 $line .= $next;
1614             }
1615              
1616 6189         78510 $line =~ s/^\s*|\s*$//g;
1617              
1618 6189 100       46876 if($line =~ /^\s*#\s?(.*?)\s*$/)
    100          
    100          
    100          
    50          
1619             {
1620             # it's a comment
1621 4725         10162 _insert_comment($level[-1], $1, $raw_line, undef, $cgroup);
1622             }
1623             elsif($line eq '')
1624             {
1625             # it's a blank line
1626 644         1468 _insert_blank($level[-1], $raw_line, undef, $bgroup);
1627             }
1628             elsif($line =~ /^(\w+)(?:\s+(.*?)|)$/)
1629             {
1630             # it's a directive
1631 736         1840 _insert_directive($level[-1], $1, $2, $raw_line, $length);
1632             }
1633             elsif($line =~ /^<\s*(\w+)(?:\s+([^>]+)|\s*)>$/)
1634             {
1635             # it's a section opening
1636 42         127 my $section = _insert_section($level[-1], $1, $2, $raw_line, $length);
1637 42         343 push(@level, $section);
1638             }
1639             elsif($line =~ /^<\/\s*(\w+)\s*>$/)
1640             {
1641             # it's a section closing
1642 42         104 my $section_name = lc $1;
1643 42 50 33     258 return $self->_set_error(sprintf('%s: syntax error at line %d', $file, $n))
1644             if(!@level || $section_name ne lc($level[-1]->{name}));
1645 42         229 $level[-1]->{raw2} = $raw_line;
1646 42         113 $level[-1]->{length2} = $length;
1647 42         320 pop(@level);
1648             }
1649             else
1650             {
1651 0         0 return $self->_set_error(sprintf('%s: syntax error at line %d', $file, $n));
1652             }
1653             }
1654              
1655 15 50       67 eval('use Data::Dumper; print Data::Dumper::Dumper($self), "\n";') if($Apache::Admin::Config::DEBUG);
1656              
1657 15         263 return 1;
1658             }
1659              
1660             sub _get_arg
1661             {
1662 236     236   378 my($args, $motif) = @_;
1663             # motif is a list of searched argument separated by a pipe
1664             # each arguments can be ended by a ! for specifing that it don't wait for a value
1665             # (ex: "-arg1|-arg2!" here -arg2 is boolean)
1666             # return (value, argname)
1667              
1668 236 100       1355 return '' unless(@$args);
1669 176         439 for(my $n = 0; $n < @$args; $n++)
1670             {
1671 427         983 foreach my $name (split(/\|/, $motif))
1672             {
1673 742         1546 my $boolean = ($name =~ s/\!$//);
1674 742 100 100     12243 if(defined $args->[$n] && !ref($args->[$n]) && $args->[$n] eq $name)
      100        
1675             {
1676 20 50 66     99 return(undef) if(!$boolean && $n+1 >= @$args); # malformed argument
1677 20 100       92 my $value = splice(@$args, $n, ($boolean?1:2));
1678 20 50       59 $value = '' unless defined $value;
1679 20 100       95 return(wantarray ? ($value, $name) : $value); # suppres argument name and its value from the arglist and return the value
1680             }
1681             }
1682             }
1683 156         638 return '';
1684             }
1685              
1686             sub _init
1687             {
1688 8     8   23 my $self = shift;
1689 8         44 return $self->_parse;
1690             }
1691              
1692             sub _load
1693             {
1694 7     7   13 my($self, $htaccess) = @_;
1695 7         12 my @htaccess;
1696             my $fh;
1697              
1698 7         31 $self->{htaccess} = $htaccess;
1699              
1700 7 100       38 if(ref $htaccess eq 'GLOB')
1701             {
1702 3         6 $fh = $htaccess;
1703             }
1704             else
1705             {
1706             # just return true if file doesn't exist and -create was enabled
1707 4 50 33     79 return 1 if(not -f $htaccess and $self->{create});
1708            
1709 4 50       64 return $self->_set_error("`$htaccess' not readable") unless(-r $htaccess);
1710 4 50       41 $fh = new FileHandle($htaccess) or return $self->_set_error("can't open `$htaccess' file for reading");
1711             }
1712            
1713 7         497 return $self->_parse($fh);
1714             }
1715              
1716             sub _set_error
1717             {
1718 0     0     my $self = shift;
1719 0           $Apache::Admin::Config::ERROR = $self->top->{__last_error__} = join('', (caller())[0].': ', @_);
1720 0           return;
1721             }
1722              
1723             1;
1724              
1725             =pod
1726              
1727             =head1 EXAMPLES
1728              
1729             #
1730             # Reindent configuration file properly
1731             #
1732              
1733             my $conf = Apache::Admin::Config
1734             (
1735             '/etc/apache/httpd.conf',
1736             -indent => 2
1737             );
1738              
1739             $conf->save('-reformat');
1740              
1741             #
1742             # Managing virtual-hosts:
1743             #
1744              
1745             my $conf = new Apache::Admin::Config "/etc/apache/httpd.conf";
1746              
1747             # adding a new virtual-host:
1748             my $vhost = $conf->add_section(VirtualHost=>'127.0.0.1');
1749             $vhost->add_directive(ServerAdmin=>'webmaster@localhost.localdomain');
1750             $vhost->add_directive(DocumentRoot=>'/usr/share/www');
1751             $vhost->add_directive(ServerName=>'www.localhost.localdomain');
1752             $vhost->add_directive(ErrorLog=>'/var/log/apache/www-error.log');
1753             my $location = $vhost->add_section(Location=>'/admin');
1754             $location->add_directive(AuthType=>'basic');
1755             $location->add_directive(Require=>'group admin');
1756             $conf->save;
1757              
1758             # selecting a virtual-host:
1759             my $vhost;
1760             foreach my $vh (@{$conf->section('VirtualHost')})
1761             {
1762             if($vh->directive('ServerName')->value eq 'www.localhost.localdomain')
1763             {
1764             $vhost = $vh;
1765             last;
1766             }
1767             }
1768              
1769             #
1770             # Suppress all comments in the file
1771             #
1772              
1773             sub delete_comments
1774             {
1775             foreach(shift->comment)
1776             {
1777             $_->delete;
1778             }
1779             }
1780              
1781             sub delete_all_comments
1782             {
1783             foreach($_[0]->section)
1784             {
1785             delete_all_comments($_);
1786             }
1787             delete_comments($_[0]);
1788             }
1789              
1790             delete_all_comments($conf);
1791              
1792             #
1793             # Transform configuration file into XML format
1794             #
1795              
1796             my $c = new Apache::Admin::Config "/path/to/file", -indent => 2
1797             or die $Apache::Admin::Config::ERROR;
1798              
1799             $c->set_write_directive(sub {
1800             my($self, $name, $value) = @_;
1801             return($self->indent.qq( 1802             });
1803             $c->set_write_section(sub {
1804             my($self, $name, $value) = @_;
1805             return($self->indent.qq(
\n));
1806             });
1807             $c->set_write_section_closing(sub {
1808             my($self, $name) = @_;
1809             return($self->indent."\n");
1810             });
1811             $c->set_write_comment(sub {
1812             my($self, $value) = @_;
1813             $value =~ s/\n//g;
1814             return($self->indent."");
1815             });
1816             print $c->dump_reformat();
1817              
1818              
1819             =head1 AUTHOR
1820              
1821             Olivier Poitrey Ers@rhapsodyk.netE
1822              
1823             =head1 AVAILABILITY
1824              
1825             The official FTP location is:
1826              
1827             B
1828              
1829             Also available on CPAN.
1830              
1831             anonymous CVS repository:
1832              
1833             CVS_RSH=ssh cvs -d anonymous@cvs.rhapsodyk.net:/devel co Apache-Admin-Config
1834              
1835             (supply an empty string as password)
1836              
1837             CVS repository on the web:
1838              
1839             http://www.rhapsodyk.net/cgi-bin/cvsweb/Apache-Admin-Config/
1840              
1841             =head1 BUGS
1842              
1843             Please send bug-reports to aac@list.rhapsodyk.net. You can subscribe to the list
1844             by sending an empty mail to aac-subscribe@list.rhapsodyk.net.
1845              
1846             =head1 LICENCE
1847              
1848             This library is free software; you can redistribute it and/or
1849             modify it under the terms of the GNU Lesser General Public
1850             License as published by the Free Software Foundation; either
1851             version 2.1 of the License, or (at your option) any later version.
1852              
1853             This library is distributed in the hope that it will be useful,
1854             but WITHOUT ANY WARRANTY; without even the implied warranty of
1855             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1856             Lesser General Public License for more details.
1857              
1858             You should have received a copy of the GNU Lesser General Public
1859             License along with this library; if not, write to the Free Software
1860             Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1861              
1862             =head1 COPYRIGHT
1863              
1864             Copyright (C) 2001 - Olivier Poitrey