File Coverage

blib/lib/Config/IniFiles.pm
Criterion Covered Total %
statement 808 885 91.3
branch 304 398 76.3
condition 64 117 54.7
subroutine 117 127 92.1
pod 39 39 100.0
total 1332 1566 85.0


line stmt bran cond sub pod time code
1             package Config::IniFiles;
2              
3             require 5.008;
4 41     41   3379096 use strict;
  41         66  
  41         1367  
5 41     41   147 use warnings;
  41         61  
  41         2290  
6              
7             our $VERSION = '3.002000';
8 41     41   202 use Carp;
  41         61  
  41         2965  
9 41     41   14761 use Symbol 'gensym', 'qualify_to_ref'; # For the 'any data type' hack
  41         40080  
  41         2588  
10 41     41   249 use Fcntl qw( SEEK_SET SEEK_CUR );
  41         58  
  41         1877  
11              
12 41     41   161 use List::Util 1.33 qw(any none);
  41         779  
  41         2532  
13              
14 41     41   222 use File::Basename qw( dirname );
  41         58  
  41         2503  
15 41     41   32483 use File::Temp qw/ tempfile /;
  41         711142  
  41         325332  
16              
17             @Config::IniFiles::errors = ();
18              
19             # $Header: /home/shlomi/progs/perl/cpan/Config/IniFiles/config-inifiles-cvsbackup/config-inifiles/IniFiles.pm,v 2.41 2003-12-08 10:50:56 domq Exp $
20              
21              
22             sub _nocase
23             {
24 4871     4871   5016 my $self = shift;
25              
26 4871 100       6574 if (@_)
27             {
28 98 100       274 $self->{nocase} = ( shift(@_) ? 1 : 0 );
29             }
30              
31 4871         7589 return $self->{nocase};
32             }
33              
34             sub _is_parm_in_sect
35             {
36 1573     1573   2330 my ( $self, $sect, $parm ) = @_;
37              
38 1573     2990   3159 return any { $_ eq $parm } @{ $self->{myparms}{$sect} };
  2990         4332  
  1573         3508  
39             }
40              
41             sub new
42             {
43 88     88 1 7505649 my $class = shift;
44 88         333 my %parms = @_;
45              
46 88         137 my $errs = 0;
47 88         155 my @groups = ();
48              
49 88         698 my $self = bless {
50             default => '',
51             fallback => undef,
52             fallback_used => 0,
53             imported => undef,
54             v => {},
55             cf => undef,
56             nomultiline => 0,
57             handle_trailing_comment => 0,
58             }, $class;
59              
60 88 100 66     563 if ( ref( $parms{-import} )
    50          
61             && ( $parms{-import}->isa('Config::IniFiles') ) )
62             {
63 9         15 $self->{imported} = $parms{-import}; # ReadConfig will load the data
64 9         15 $self->{negativedeltas} = 1;
65             }
66             elsif ( defined $parms{-import} )
67             {
68 0         0 carp "Invalid -import value \"$parms{-import}\" was ignored.";
69             } # end if
70 88         160 delete $parms{-import};
71              
72             # Copy the original parameters so we
73             # can use them when we build new sections
74 88         166 %{ $self->{startup_settings} } = %parms;
  88         342  
75              
76             # Parse options
77 88         151 my ( $k, $v );
78 88         309 $self->_nocase(0);
79              
80             # Handle known parameters first in this order,
81             # because each() could return parameters in any order
82 88 100       219 if ( defined( $v = delete $parms{'-file'} ) )
83             {
84             # Should we be pedantic and check that the file exists?
85             # .. no, because now it could be a handle, IO:: object or something else
86 71         149 $self->{cf} = $v;
87             }
88 88 100       222 if ( defined( $v = delete $parms{'-nocase'} ) )
89             {
90 10         20 $self->_nocase($v);
91             }
92 88 100       202 if ( defined( $v = delete $parms{'-default'} ) )
93             {
94 7 50       16 $self->{default} = $self->_nocase ? lc($v) : $v;
95             }
96 88 100       242 if ( defined( $v = delete $parms{'-fallback'} ) )
97             {
98 1 50       2 $self->{fallback} = $self->_nocase ? lc($v) : $v;
99             }
100 88 50       194 if ( defined( $v = delete $parms{'-reloadwarn'} ) )
101             {
102 0 0       0 $self->{reloadwarn} = $v ? 1 : 0;
103             }
104 88 100       222 if ( defined( $v = delete $parms{'-nomultiline'} ) )
105             {
106 1 50       3 $self->{nomultiline} = $v ? 1 : 0;
107             }
108 88 100       198 if ( defined( $v = delete $parms{'-allowcontinue'} ) )
109             {
110 1 50       4 $self->{allowcontinue} = $v ? 1 : 0;
111             }
112 88 100       205 if ( defined( $v = delete $parms{'-allowempty'} ) )
113             {
114 11 50       31 $self->{allowempty} = $v ? 1 : 0;
115             }
116 88 50       195 if ( defined( $v = delete $parms{'-negativedeltas'} ) )
117             {
118 0 0       0 $self->{negativedeltas} = $v ? 1 : 0;
119             }
120 88 100       211 if ( defined( $v = delete $parms{'-commentchar'} ) )
121             {
122 2 50 33     17 if ( !defined $v || length($v) != 1 )
    50          
123             {
124 0         0 carp "Comment character must be unique.";
125 0         0 $errs++;
126             }
127             elsif ( $v =~ /[\[\]=\w]/ )
128             {
129             # must not be square bracket, equal sign or alphanumeric
130 0         0 carp "Illegal comment character.";
131 0         0 $errs++;
132             }
133             else
134             {
135 2         8 $self->{comment_char} = $v;
136             }
137             }
138 88 100       207 if ( defined( $v = delete $parms{'-allowedcommentchars'} ) )
139             {
140             # must not be square bracket, equal sign or alphanumeric
141 2 50 33     14 if ( !defined $v || $v =~ /[\[\]=\w]/ )
142             {
143 0         0 carp "Illegal value for -allowedcommentchars.";
144 0         0 $errs++;
145             }
146             else
147             {
148 2         5 $self->{allowed_comment_char} = $v;
149             }
150             }
151              
152 88 100       176 if ( defined( $v = delete $parms{'-handle_trailing_comment'} ) )
153             {
154 4 100       11 $self->{handle_trailing_comment} = $v ? 1 : 0;
155             }
156 88 100       178 if ( defined( $v = delete $parms{'-php_compat'} ) )
157             {
158 1 50       3 $self->{php_compat} = $v ? 1 : 0;
159             }
160              
161 88 100       287 $self->{comment_char} = '#' unless exists $self->{comment_char};
162             $self->{allowed_comment_char} = ';'
163 88 100       253 unless exists $self->{allowed_comment_char};
164              
165             # make sure that comment character is always allowed
166 88         204 $self->{allowed_comment_char} .= $self->{comment_char};
167              
168 88         183 $self->{_comments_at_end_of_file} = [];
169              
170             # Any other parameters are unknown
171 88         283 while ( ( $k, $v ) = each %parms )
172             {
173 0         0 carp "Unknown named parameter $k=>$v";
174 0         0 $errs++;
175             }
176              
177 88 50       170 return undef if $errs;
178              
179 88 100       342 if ( $self->ReadConfig )
180             {
181 83         785 return $self;
182             }
183             else
184             {
185 5         89 return undef;
186             }
187             }
188              
189              
190             sub _caseify
191             {
192 4765     4765   6299 my ( $self, @refs ) = @_;
193              
194 4765 100       6295 if ( $self->_nocase )
195             {
196 1348         1656 foreach my $ref ( grep { defined } @refs[ 0 .. 1 ] )
  2696         3536  
197             {
198 1774         1594 ${$ref} = lc( ${$ref} );
  1774         2194  
  1774         1877  
199             }
200             }
201              
202 4765 100       6611 if ( $self->{php_compat} )
203             {
204 27         39 foreach my $ref ( grep { defined } @refs[ 1 .. 1 ] )
  27         43  
205             {
206 17         15 ${$ref} =~ s{\[\]$}{};
  17         30  
207             }
208 27         41 foreach my $ref ( grep { defined } @refs[ 2 .. $#refs ] )
  4         6  
209             {
210 4 100       3 if ( length( ${$ref} ) >= 2 )
  4         9  
211             {
212 2         2 my $quote = substr( ${$ref}, 0, 1 );
  2         5  
213 2 50 66     8 if ( ( $quote eq q{"} or $quote eq q{'} )
      33        
214 2         5 and substr( ${$ref}, -1, 1 ) eq $quote )
215             {
216 2         2 ${$ref} = substr( ${$ref}, 1, -1 );
  2         2  
  2         4  
217 2         3 ${$ref} =~ s{$quote$quote}{}g;
  2         28  
218 2 100       7 ${$ref} =~ s{\\$quote}{$quote}g if $quote eq q{"};
  1         9  
219             }
220             }
221             }
222             }
223              
224 4765         5347 return;
225             }
226              
227             sub val
228             {
229 110     110 1 13999 my ( $self, $sect, $parm, $def ) = @_;
230              
231             # Always return undef on bad parameters
232 110 50 33     435 if ( not( defined($sect) && defined($parm) ) )
233             {
234 0         0 return;
235             }
236              
237 110         312 $self->_caseify( \$sect, \$parm );
238              
239             my $val_sect =
240             defined( $self->{v}{$sect}{$parm} )
241             ? $sect
242 110 100       335 : $self->{default};
243              
244 110         186 my $val = $self->{v}{$val_sect}{$parm};
245              
246             # If the value is undef, make it $def instead (which could just be undef)
247 110 100       212 if ( !defined($val) )
248             {
249 7         9 $val = $def;
250             }
251              
252             # Return the value in the desired context
253 110 100       307 if (wantarray)
    100          
254             {
255 34 100       82 if ( ref($val) eq "ARRAY" )
    100          
256             {
257 12         56 return @$val;
258             }
259             elsif ( defined($val) )
260             {
261 20         45 return $val;
262             }
263             else
264             {
265 2         6 return;
266             }
267             }
268             elsif ( ref($val) eq "ARRAY" )
269             {
270 5 50       34 return join( ( defined($/) ? $/ : "\n" ), @$val );
271             }
272             else
273             {
274 71         254 return $val;
275             }
276             }
277              
278              
279             sub exists
280             {
281 4     4 1 14 my ( $self, $sect, $parm ) = @_;
282              
283 4         13 $self->_caseify( \$sect, \$parm );
284              
285 4         19 return ( exists $self->{v}{$sect}{$parm} );
286             }
287              
288              
289             sub push
290             {
291 92     92 1 190 my ( $self, $sect, $parm, @vals ) = @_;
292              
293 92 50       145 return undef if not defined $sect;
294 92 50       135 return undef if not defined $parm;
295              
296 92         328 $self->_caseify( \$sect, \$parm );
297              
298 92 50       217 return undef if ( !defined( $self->{v}{$sect}{$parm} ) );
299              
300 92 50       169 return 1 if ( !@vals );
301              
302 92         190 $self->_touch_parameter( $sect, $parm );
303              
304             $self->{EOT}{$sect}{$parm} = 'EOT'
305 92 100       267 if ( !defined $self->{EOT}{$sect}{$parm} );
306              
307             $self->{v}{$sect}{$parm} = [ $self->{v}{$sect}{$parm} ]
308 92 100       316 unless ( ref( $self->{v}{$sect}{$parm} ) eq "ARRAY" );
309              
310 92         135 CORE::push @{ $self->{v}{$sect}{$parm} }, @vals;
  92         236  
311 92         146 return 1;
312             }
313              
314              
315             sub setval
316             {
317 2     2 1 1991 my $self = shift;
318 2         2 my $sect = shift;
319 2         4 my $parm = shift;
320 2         6 my @val = @_;
321              
322 2 50       6 return undef if not defined $sect;
323 2 50       5 return undef if not defined $parm;
324              
325 2         6 $self->_caseify( \$sect, \$parm );
326              
327 2 100       9 if ( defined( $self->{v}{$sect}{$parm} ) )
328             {
329 1         4 $self->_touch_parameter( $sect, $parm );
330 1 50       3 if ( @val > 1 )
331             {
332 0         0 $self->{v}{$sect}{$parm} = \@val;
333 0         0 $self->{EOT}{$sect}{$parm} = 'EOT';
334             }
335             else
336             {
337 1         3 $self->{v}{$sect}{$parm} = shift @val;
338             }
339 1         2 return 1;
340             }
341             else
342             {
343 1         2 return undef;
344             }
345             }
346              
347              
348             sub newval
349             {
350 640     640 1 4531 my $self = shift;
351 640         720 my $sect = shift;
352 640         734 my $parm = shift;
353 640         1071 my @val = @_;
354              
355 640 50       997 return undef if not defined $sect;
356 640 50       992 return undef if not defined $parm;
357              
358 640         1425 $self->_caseify( \$sect, \$parm );
359              
360 640         1271 $self->AddSection($sect);
361              
362 640 100   896   1770 if ( none { $_ eq $parm } @{ $self->{parms}{$sect} } )
  896         1104  
  640         2008  
363             {
364 613         703 CORE::push( @{ $self->{parms}{$sect} }, $parm );
  613         1050  
365             }
366              
367 640         1999 $self->_touch_parameter( $sect, $parm );
368 640 100       1010 if ( @val > 1 )
369             {
370 112         253 $self->{v}{$sect}{$parm} = \@val;
371 112 100       313 if ( !defined $self->{EOT}{$sect}{$parm} )
372             {
373 105         214 $self->{EOT}{$sect}{$parm} = 'EOT';
374             }
375             }
376             else
377             {
378 528         1199 $self->{v}{$sect}{$parm} = shift @val;
379             }
380 640         1061 return 1;
381             }
382              
383              
384             sub delval
385             {
386 6     6 1 2163 my $self = shift;
387 6         13 my $sect = shift;
388 6         52 my $parm = shift;
389              
390 6 50       20 return undef if not defined $sect;
391 6 50       13 return undef if not defined $parm;
392              
393 6         24 $self->_caseify( \$sect, \$parm );
394              
395 6         8 $self->{parms}{$sect} = [ grep { $_ ne $parm } @{ $self->{parms}{$sect} } ];
  24         43  
  6         18  
396 6         21 $self->_touch_parameter( $sect, $parm );
397 6         12 delete $self->{v}{$sect}{$parm};
398              
399 6         12 return 1;
400             }
401              
402              
403             # Auxiliary function to make deep (aliasing-free) copies of data
404             # structures. Ignores blessed objects in tree (could be taught not
405             # to, if needed)
406             sub _deepcopy
407             {
408 411     411   414 my $ref = shift;
409              
410 411 100       485 if ( !ref($ref) )
411             {
412 206         391 return $ref;
413             }
414              
415 205 100       321 if ( UNIVERSAL::isa( $ref, "ARRAY" ) )
416             {
417 64         98 return [ map { _deepcopy($_) } @$ref ];
  118         135  
418             }
419              
420 141 50       200 if ( UNIVERSAL::isa( $ref, "HASH" ) )
421             {
422 141         133 my $return = {};
423 141         193 foreach my $k ( keys %$ref )
424             {
425 178         203 $return->{$k} = _deepcopy( $ref->{$k} );
426             }
427 141         235 return $return;
428             }
429              
430 0         0 carp "Unhandled data structure in $ref, cannot _deepcopy()";
431             }
432              
433             # Internal method, gets the next line, taking proper care of line endings.
434             sub _nextline
435             {
436 2069     2069   2386 my ( $self, $fh ) = @_;
437 2069         2176 my $s = '';
438 2069 100       2837 if ( !exists $self->{line_ends} )
439             {
440             # no $self->{line_ends} is a hint set by caller that we are at
441             # the first line (kludge kludge).
442             {
443 85         102 local $/ = \1;
  85         378  
444 85         106 my $nextchar;
445             do
446 85         106 {
447 1135         3258 $nextchar = <$fh>;
448 1135 100       2041 return undef if ( !defined $nextchar );
449 1123         2034 $s .= $nextchar;
450             } until ( $s =~ m/((\015|\012|\025|\n)$)/s );
451 73         218 $self->{line_ends} = $1;
452 73 100       286 if ( $nextchar eq "\x0d" )
453             {
454             # peek at the next char
455 4         9 $nextchar = <$fh>;
456 4 100       11 if ( $nextchar eq "\x0a" )
457             {
458 3         12 $self->{line_ends} .= "\x0a";
459             }
460             else
461             {
462 1         9 seek $fh, -1, SEEK_CUR();
463             }
464             }
465             }
466              
467             # If there's a UTF BOM (Byte-Order-Mark) in the first
468             # character of the first line then remove it before processing
469             # ( http://www.unicode.org/unicode/faq/utf_bom.html#22 )
470 73         166 $s =~ s/\A//;
471              
472 73         227 return $s;
473             }
474             else
475             {
476 1984         4758 local $/ = $self->{line_ends};
477 1984         6018 return scalar <$fh>;
478             }
479             }
480              
481             # Internal method, closes or resets the file handle. To be called
482             # whenever ReadConfig() returns.
483             sub _rollback
484             {
485 85     85   136 my ( $self, $fh ) = @_;
486              
487             # Only close if this is a filename, if it's
488             # an open handle, then just roll back to the start
489 85 100       285 if ( !ref( $self->{cf} ) )
490             {
491 71 50       983 close($fh) or Carp::confess("close failed: $!");
492             }
493             else
494             {
495             # Attempt to rollback to beginning, no problem if this fails (e.g. STDIN)
496 14         78 seek( $fh, 0, SEEK_SET() );
497             } # end if
498             }
499              
500             sub _no_filename
501             {
502 118     118   141 my $self = shift;
503              
504 118         872 my $fn = $self->{cf};
505              
506 118   66     644 return ( not( defined($fn) && length($fn) ) );
507             }
508              
509             sub _read_line_num
510             {
511 4192     4192   4266 my $self = shift;
512              
513 4192 100       5492 if (@_)
514             {
515 2071         2319 $self->{_read_line_num} = shift;
516             }
517              
518 4192         6096 return $self->{_read_line_num};
519             }
520              
521             # Reads the next line and removes the end of line from it.
522             sub _read_next_line
523             {
524 2069     2069   2671 my ( $self, $fh ) = @_;
525              
526 2069         2951 my $line = $self->_nextline($fh);
527              
528 2069 100       3531 if ( !defined($line) )
529             {
530 83         246 return undef;
531             }
532              
533 1986         2704 $self->_read_line_num( $self->_read_line_num() + 1 );
534              
535             # Remove line ending char(s)
536 1986         6574 $line =~ s/(\015\012?|\012|\025|\n)\z//;
537              
538 1986         4136 return $line;
539             }
540              
541             sub _add_error
542             {
543 7     7   12 my ( $self, $msg ) = @_;
544              
545 7         11 CORE::push( @Config::IniFiles::errors, $msg );
546              
547 7         10 return;
548             }
549              
550             # The current section - used for parsing.
551             sub _curr_sect
552             {
553 5603     5603   5545 my $self = shift;
554              
555 5603 100       7224 if (@_)
556             {
557 422         762 $self->{_curr_sect} = shift;
558             }
559              
560 5603         9533 return $self->{_curr_sect};
561             }
562              
563             # The current parameter - used for parsing.
564             sub _curr_parm
565             {
566 3780     3780   3738 my $self = shift;
567              
568 3780 100       4797 if (@_)
569             {
570 777         976 $self->{_curr_parm} = shift;
571             }
572              
573 3780         6840 return $self->{_curr_parm};
574             }
575              
576             # Current location - section and parameter.
577             sub _curr_loc
578             {
579 2312     2312   2423 my $self = shift;
580              
581 2312         2755 return ( $self->_curr_sect, $self->_curr_parm );
582             }
583              
584             # The current value - used in parsing.
585             sub _curr_val
586             {
587 2095     2095   2186 my $self = shift;
588              
589 2095 100       2685 if (@_)
590             {
591 810         996 $self->{_curr_val} = shift;
592             }
593              
594 2095         3447 return $self->{_curr_val};
595             }
596              
597             sub _curr_cmts
598             {
599 2338     2338   2454 my $self = shift;
600              
601 2338 100       3125 if (@_)
602             {
603 1112         1429 $self->{_curr_cmts} = shift;
604             }
605              
606 2338         4173 return $self->{_curr_cmts};
607             }
608              
609             sub _curr_end_comment
610             {
611 1947     1947   2049 my $self = shift;
612              
613 1947 100       2609 if (@_)
614             {
615 1256         1530 $self->{_curr_end_comment} = shift;
616             }
617              
618 1947         2932 return $self->{_curr_end_comment};
619             }
620              
621             my $RET_CONTINUE = 1;
622             my $RET_BREAK;
623              
624             sub _ReadConfig_handle_comment
625             {
626 120     120   189 my ( $self, $line ) = @_;
627              
628 120 100 66     321 if ( $self->{negativedeltas}
629             and my ($to_delete) =
630             $line =~ m/\A$self->{comment_char} (.*) is deleted\z/ )
631             {
632 2 100       9 if ( my ($sect) = $to_delete =~ m/\A\[(.*)\]\z/ )
633             {
634 1         5 $self->DeleteSection($sect);
635             }
636             else
637             {
638 1         2 $self->delval( $self->_curr_sect, $to_delete );
639             }
640             }
641             else
642             {
643 118         135 CORE::push( @{ $self->_curr_cmts }, $line );
  118         172  
644             }
645              
646 120         340 return $RET_CONTINUE;
647             }
648              
649             sub _ReadConfig_new_section
650             {
651 336     336   506 my ( $self, $sect ) = @_;
652              
653 336         731 $self->_caseify( undef, \$sect );
654              
655 336         638 $self->_curr_sect($sect);
656 336         438 $self->AddSection( $self->_curr_sect );
657 336         572 $self->SetSectionComment( $self->_curr_sect, @{ $self->_curr_cmts } );
  336         505  
658 336         641 $self->_curr_cmts( [] );
659              
660 336         1004 return $RET_CONTINUE;
661             }
662              
663             sub _handle_fallback_sect
664             {
665 694     694   879 my ($self) = @_;
666              
667 694 100 100     906 if ( ( !defined( $self->_curr_sect ) ) and defined( $self->{fallback} ) )
668             {
669 1         4 $self->_curr_sect( $self->{fallback} );
670 1         2 $self->{fallback_used}++;
671             }
672              
673 694         937 return;
674             }
675              
676             sub _ReadConfig_load_value
677             {
678 691     691   818 my ( $self, $val_aref ) = @_;
679              
680             # Now load value
681 691 100 100     1031 if ( exists $self->{v}{ $self->_curr_sect }{ $self->_curr_parm }
      100        
682             && exists $self->{myparms}{ $self->_curr_sect }
683             && $self->_is_parm_in_sect( $self->_curr_loc ) )
684             {
685 92         145 $self->push( $self->_curr_loc, @$val_aref );
686             }
687             else
688             {
689             # Loaded parameters shadow imported ones, instead of appending
690             # to them
691 599         919 $self->newval( $self->_curr_loc, @$val_aref );
692             }
693              
694 691         1189 return;
695             }
696              
697             sub _test_for_fallback_or_no_sect
698             {
699 694     694   857 my ( $self, $fh ) = @_;
700              
701 694         1292 $self->_handle_fallback_sect;
702              
703 694 100       900 if ( !defined $self->_curr_sect )
704             {
705 2         5 $self->_add_error(
706             sprintf( '%d: %s',
707             $self->_read_line_num(),
708             qq#parameter found outside a section# )
709             );
710 2         5 $self->_rollback($fh);
711 2         6 return $RET_BREAK;
712             }
713              
714 692         1215 return $RET_CONTINUE;
715             }
716              
717             sub _ReadConfig_handle_here_doc_param
718             {
719 130     130   229 my ( $self, $fh, $eotmark, $val_aref ) = @_;
720              
721 130         145 my $foundeot = 0;
722 130         194 my $startline = $self->_read_line_num();
723              
724             HERE_DOC_LOOP:
725 130         232 while ( defined( my $line = $self->_read_next_line($fh) ) )
726             {
727 498 100       681 if ( $line eq $eotmark )
728             {
729 129         137 $foundeot = 1;
730 129         222 last HERE_DOC_LOOP;
731             }
732             else
733             {
734             # Untaint
735 369         634 my ($contents) = $line =~ /(.*)/ms;
736 369         703 CORE::push( @$val_aref, $contents );
737             }
738             }
739              
740 130 100       234 if ( !$foundeot )
741             {
742 1         7 $self->_add_error(
743             sprintf( '%d: %s',
744             $startline, qq#no end marker ("$eotmark") found# )
745             );
746 1         3 $self->_rollback($fh);
747 1         2 return $RET_BREAK;
748             }
749              
750 129         264 return $RET_CONTINUE;
751             }
752              
753             sub _ReadConfig_handle_non_here_doc_param
754             {
755 562     562   730 my ( $self, $fh, $val_aref ) = @_;
756              
757 562         714 my $allCmt = $self->{allowed_comment_char};
758 562         695 my $end_commenthandle = $self->{handle_trailing_comment};
759              
760             # process continuation lines, if any
761 562         1115 $self->_process_continue_val($fh);
762              
763             # we should split value and comments if there is any comment
764 562 100 66     1072 if ( $end_commenthandle
765             and my ( $value_to_assign, $end_comment_to_assign ) =
766             $self->_curr_val =~ /(.*?)\s*[$allCmt]\s*(.*)$/ )
767             {
768 4         12 $self->_curr_val($value_to_assign);
769 4         8 $self->_curr_end_comment($end_comment_to_assign);
770             }
771             else
772             {
773 558         792 $self->_curr_end_comment(q{});
774             }
775              
776 562         756 @{$val_aref} = ( $self->_curr_val );
  562         714  
777              
778 562         769 return;
779             }
780              
781             sub _ReadConfig_populate_values
782             {
783 691     691   985 my ( $self, $val_aref, $eotmark ) = @_;
784              
785 691         1275 $self->_ReadConfig_load_value($val_aref);
786              
787 691         1096 $self->SetParameterComment( $self->_curr_loc, @{ $self->_curr_cmts } );
  691         1040  
788 691         1448 $self->_curr_cmts( [] );
789 691 100       1027 if ( defined $eotmark )
790             {
791 129         224 $self->SetParameterEOT( $self->_curr_loc, $eotmark );
792             }
793              
794             # if handle_trailing_comment is off, this line makes no sense, since all $end_comment=""
795 691         1023 $self->SetParameterTrailingComment( $self->_curr_loc,
796             $self->_curr_end_comment );
797              
798 691         913 return;
799             }
800              
801             sub _ReadConfig_param_assignment
802             {
803 694     694   1234 my ( $self, $fh, $line, $parm, $value_to_assign ) = @_;
804              
805 694         1533 $self->_caseify( undef, \$parm, \$value_to_assign );
806              
807 694         1337 $self->_curr_val($value_to_assign);
808 694         1254 $self->_curr_end_comment( undef() );
809              
810 694 100       1071 if ( !defined( $self->_test_for_fallback_or_no_sect($fh) ) )
811             {
812              
813 2         6 return $RET_BREAK;
814             }
815              
816 692         1257 $self->_curr_parm($parm);
817              
818 692         796 my @val = ();
819 692         697 my $eotmark;
820              
821 692 100       948 if ( ($eotmark) = $self->_curr_val =~ /\A<<(.*)$/ )
822             {
823 130 100       272 if (
824             !defined(
825             $self->_ReadConfig_handle_here_doc_param(
826             $fh, $eotmark, \@val
827             )
828             )
829             )
830             {
831 1         4 return $RET_BREAK;
832             }
833             }
834             else
835             {
836 562         1036 $self->_ReadConfig_handle_non_here_doc_param( $fh, \@val );
837             }
838              
839 691         1471 $self->_ReadConfig_populate_values( \@val, $eotmark );
840              
841 691         2461 return $RET_CONTINUE;
842             }
843              
844             # Return 1 to continue - undef to terminate the loop.
845             sub _ReadConfig_handle_line
846             {
847 1486     1486   2074 my ( $self, $fh, $line ) = @_;
848              
849 1486         1843 my $allCmt = $self->{allowed_comment_char};
850              
851             # ignore blank lines
852 1486 100       3236 if ( $line =~ /\A\s*\z/ )
853             {
854 333         793 return $RET_CONTINUE;
855             }
856              
857             # collect comments
858 1153 100       6100 if ( $line =~ /\A\s*[$allCmt]/ )
859             {
860 120         259 return $self->_ReadConfig_handle_comment($line);
861             }
862              
863             # New Section
864 1033 100       2924 if ( my ($sect) = $line =~ /\A\s*\[\s*(\S|\S.*\S)\s*\]\s*\z/ )
865             {
866 336         625 return $self->_ReadConfig_new_section($sect);
867             }
868              
869             # New parameter
870 697 100       3366 if ( my ( $parm, $value_to_assign ) =
871             $line =~ /^\s*([^=]*?[^=\s])\s*=\s*(.*)$/ )
872             {
873 694         1243 return $self->_ReadConfig_param_assignment( $fh, $line, $parm,
874             $value_to_assign );
875             }
876              
877             $self->_add_error(
878 3         6 sprintf(
879             "Line %d in file %s is malformed:\n\t\%s",
880             $self->_read_line_num(),
881             $self->GetFileName(), $line
882             )
883             );
884              
885 3         9 return $RET_CONTINUE;
886             }
887              
888             sub _ReadConfig_lines_loop
889             {
890 85     85   183 my ( $self, $fh ) = @_;
891              
892 85         273 $self->_curr_sect( undef() );
893 85         228 $self->_curr_parm( undef() );
894 85         219 $self->_curr_val( undef() );
895 85         229 $self->_curr_cmts( [] );
896              
897 85         212 while ( defined( my $line = $self->_read_next_line($fh) ) )
898             {
899 1486 100       2409 if (
900             !defined( scalar( $self->_ReadConfig_handle_line( $fh, $line ) ) ) )
901             {
902 3         9 return undef;
903             }
904             }
905              
906 82         266 return 1;
907             }
908              
909             sub ReadConfig
910             {
911 102     102 1 259 my $self = shift;
912              
913 102         212 @Config::IniFiles::errors = ();
914              
915             # Initialize (and clear out) storage hashes
916 102         229 $self->{sects} = [];
917 102         248 $self->{parms} = {};
918 102         196 $self->{group} = {};
919 102         252 $self->{v} = {};
920 102         185 $self->{sCMT} = {};
921 102         192 $self->{pCMT} = {};
922 102         186 $self->{EOT} = {};
923             $self->{mysects} =
924 102         189 []; # A pair of hashes to remember which params are loaded
925 102         202 $self->{myparms} = {}; # or set using the API vs. imported - useful for
926             $self->{peCMT} =
927 102         206 {}; # this will store trailing comments at the end of single-line params
928 102         200 $self->{e} = {}; # If a section already exists
929 102         181 $self->{mye} = {}; # If a section already exists
930             # import shadowing, see below, and WriteConfig($fn, -delta=>1)
931              
932 102 100       263 if ( defined $self->{imported} )
933             {
934 13         28 foreach my $field (qw(sects parms group v sCMT pCMT EOT e))
935             {
936 104         176 $self->{$field} = _deepcopy( $self->{imported}->{$field} );
937             }
938             }
939              
940 102 100       272 if ( $self->_no_filename )
941             {
942 17         37 return 1;
943             }
944              
945             # If we want warnings, then send one to the STDERR log
946 85 50       201 if ( $self->{reloadwarn} )
947             {
948 0         0 my ( $ss, $mm, $hh, $DD, $MM, $YY ) = ( localtime(time) )[ 0 .. 5 ];
949             printf STDERR
950             "PID %d reloading config file %s at %d.%02d.%02d %02d:%02d:%02d\n",
951 0         0 $$, $self->{cf}, $YY + 1900, $MM + 1, $DD, $hh, $mm, $ss;
952             }
953              
954             # Get a filehandle, allowing almost any type of 'file' parameter
955 85         284 my $fh = $self->_make_filehandle( $self->{cf} );
956 85 50       416 if ( !$fh )
957             {
958 0         0 carp "Failed to open $self->{cf}: $!";
959 0         0 return undef;
960             }
961              
962             # Get mod time of file so we can retain it (if not from STDIN)
963             # also check if it's a real file (could have been a filehandle made from a scalar).
964 85 100 100     867 if ( ref($fh) ne "IO::Scalar" && -e $fh )
965             {
966 81 100       214 if ( not exists $self->{file_mode} )
967             {
968 68         413 my @stats = stat $fh;
969 68 50       457 $self->{file_mode} = sprintf( "%04o", $stats[2] )
970             if defined $stats[2];
971             }
972             }
973              
974             # The first lines of the file must be blank, comments or start with [
975 85         165 my $first = '';
976              
977 85         159 delete $self->{line_ends}; # Marks start of parsing for _nextline()
978              
979 85         323 $self->_read_line_num(0);
980              
981 85 100       223 if ( !defined( $self->_ReadConfig_lines_loop($fh) ) )
982             {
983 3         24 return undef;
984             }
985              
986             # Special case: return undef if file is empty. (suppress this line to
987             # restore the more intuitive behaviour of accepting empty files)
988 82 100 100     130 if ( !keys %{ $self->{v} } && !$self->{allowempty} )
  82         301  
989             {
990 1         3 $self->_add_error("Empty file treated as error");
991 1         3 $self->_rollback($fh);
992 1         5 return undef;
993             }
994              
995 81 100       259 if ( defined( my $defaultsect = $self->{startup_settings}->{-default} ) )
996             {
997 11         26 $self->AddSection($defaultsect);
998             }
999              
1000 81         125 $self->_SetEndComments( @{ $self->_curr_cmts } );
  81         182  
1001              
1002 81         207 $self->_rollback($fh);
1003 81 100       529 return ( @Config::IniFiles::errors ? undef : 1 );
1004             }
1005              
1006              
1007             sub Sections
1008             {
1009 4     4 1 13 my $self = shift;
1010              
1011 4         5 return @{ _aref_or_empty( $self->{sects} ) };
  4         13  
1012             }
1013              
1014              
1015             sub SectionExists
1016             {
1017 1001     1001 1 4256 my $self = shift;
1018 1001         1128 my $sect = shift;
1019              
1020 1001 50       1371 return undef if not defined $sect;
1021              
1022 1001         1720 $self->_caseify( \$sect );
1023              
1024 1001 100       2270 return ( ( exists $self->{e}{$sect} ) ? 1 : 0 );
1025             }
1026              
1027              
1028             sub _AddSection_Helper
1029             {
1030 357     357   510 my ( $self, $sect ) = @_;
1031 357         666 $self->{e}{$sect} = 1;
1032 357         401 CORE::push @{ $self->{sects} }, $sect;
  357         683  
1033 357         721 $self->_touch_section($sect);
1034              
1035 357         829 $self->SetGroupMember($sect);
1036              
1037             # Set up the parameter names and values lists
1038 357   50     1392 $self->{parms}{$sect} ||= [];
1039              
1040 357 100       669 if ( !defined( $self->{v}{$sect} ) )
1041             {
1042 356         594 $self->{sCMT}{$sect} = [];
1043 356         505 $self->{pCMT}{$sect} = {}; # Comments above parameters
1044 356         545 $self->{parms}{$sect} = [];
1045 356         534 $self->{v}{$sect} = {};
1046             }
1047              
1048 357         485 return;
1049             }
1050              
1051             sub AddSection
1052             {
1053 993     993 1 1289 my ( $self, $sect ) = @_;
1054              
1055 993 50       1417 return undef if not defined $sect;
1056              
1057 993         1801 $self->_caseify( \$sect );
1058              
1059 993 100       1565 if ( $self->SectionExists($sect) )
1060             {
1061 638         840 return;
1062             }
1063              
1064 355         663 return $self->_AddSection_Helper($sect);
1065             }
1066              
1067             # Marks a section as modified by us (this includes deleted by us).
1068             sub _touch_section
1069             {
1070 1899     1899   2373 my ( $self, $sect ) = @_;
1071              
1072 1899   50     2873 $self->{mysects} ||= [];
1073              
1074 1899 100       2929 unless ( exists $self->{mye}{$sect} )
1075             {
1076 366         392 CORE::push @{ $self->{mysects} }, $sect;
  366         527  
1077 366         591 $self->{mye}{$sect} = 1;
1078             }
1079              
1080 1899         2186 return;
1081             }
1082              
1083             # Marks a parameter as modified by us (this includes deleted by us).
1084             sub _touch_parameter
1085             {
1086 1463     1463   2045 my ( $self, $sect, $parm ) = @_;
1087              
1088 1463         2715 $self->_touch_section($sect);
1089 1463 50       2246 return if ( !exists $self->{v}{$sect} );
1090 1463   100     2974 $self->{myparms}{$sect} ||= [];
1091              
1092 1463 100       2210 if ( !$self->_is_parm_in_sect( $sect, $parm ) )
1093             {
1094 639         687 CORE::push @{ $self->{myparms}{$sect} }, $parm;
  639         1105  
1095             }
1096              
1097 1463         2800 return;
1098             }
1099              
1100              
1101             sub DeleteSection
1102             {
1103 7     7 1 12 my $self = shift;
1104 7         30 my $sect = shift;
1105              
1106 7 50       19 return undef if not defined $sect;
1107              
1108 7         20 $self->_caseify( \$sect );
1109              
1110             # This is done the fast way, change if data structure changes!!
1111 7         20 delete $self->{v}{$sect};
1112 7         13 delete $self->{sCMT}{$sect};
1113 7         13 delete $self->{pCMT}{$sect};
1114 7         12 delete $self->{EOT}{$sect};
1115 7         13 delete $self->{parms}{$sect};
1116 7         12 delete $self->{myparms}{$sect};
1117 7         10 delete $self->{e}{$sect};
1118              
1119 7         10 $self->{sects} = [ grep { $_ ne $sect } @{ $self->{sects} } ];
  29         47  
  7         14  
1120 7         19 $self->_touch_section($sect);
1121              
1122 7         18 $self->RemoveGroupMember($sect);
1123              
1124 7         14 return 1;
1125             } # end DeleteSection
1126              
1127              
1128             sub RenameSection
1129             {
1130 1     1 1 2 my $self = shift;
1131 1         1 my $old_sect = shift;
1132 1         2 my $new_sect = shift;
1133 1         1 my $include_groupmembers = shift;
1134             return undef
1135 1 50       3 unless $self->CopySection( $old_sect, $new_sect,
1136             $include_groupmembers );
1137 1         12 return $self->DeleteSection($old_sect);
1138              
1139             } # end RenameSection
1140              
1141              
1142             sub CopySection
1143             {
1144 2     2 1 3 my $self = shift;
1145 2         3 my $old_sect = shift;
1146 2         2 my $new_sect = shift;
1147 2         2 my $include_groupmembers = shift;
1148              
1149 2 50 33     11 if ( not defined $old_sect
      33        
1150             or not defined $new_sect
1151             or !$self->SectionExists($old_sect)
1152             or $self->SectionExists($new_sect) )
1153             {
1154 0         0 return undef;
1155             }
1156              
1157 2         3 $self->_caseify( \$new_sect );
1158 2         4 $self->_AddSection_Helper($new_sect);
1159              
1160             # This is done the fast way, change if data structure changes!!
1161 2         3 foreach my $key (qw(v sCMT pCMT EOT parms myparms e))
1162             {
1163 14 100       25 next unless exists $self->{$key}{$old_sect};
1164             $self->{$key}{$new_sect} =
1165 11         15 Config::IniFiles::_deepcopy( $self->{$key}{$old_sect} );
1166             }
1167              
1168 2 50       4 if ($include_groupmembers)
1169             {
1170 0         0 foreach my $old_groupmember ( $self->GroupMembers($old_sect) )
1171             {
1172 0         0 my $new_groupmember = $old_groupmember;
1173 0         0 $new_groupmember =~ s/\A\Q$old_sect\E/$new_sect/;
1174 0         0 $self->CopySection( $old_groupmember, $new_groupmember );
1175             }
1176             }
1177              
1178 2         5 return 1;
1179             } # end CopySection
1180              
1181              
1182             sub _aref_or_empty
1183             {
1184 32     32   48 my ($aref) = @_;
1185              
1186 32 100 66     185 return ( ( defined($aref) and ref($aref) eq 'ARRAY' ) ? $aref : [] );
1187             }
1188              
1189             sub Parameters
1190             {
1191 22     22 1 666 my $self = shift;
1192 22         26 my $sect = shift;
1193              
1194 22 50       37 return undef if not defined $sect;
1195              
1196 22         47 $self->_caseify( \$sect );
1197              
1198 22         22 return @{ _aref_or_empty( $self->{parms}{$sect} ) };
  22         40  
1199             }
1200              
1201              
1202             sub Groups
1203             {
1204 2     2 1 11 my $self = shift;
1205              
1206 2 50       6 if ( ref( $self->{group} ) eq 'HASH' )
1207             {
1208 2         3 return keys %{ $self->{group} };
  2         11  
1209             }
1210             else
1211             {
1212 0         0 return ();
1213             }
1214             }
1215              
1216              
1217             sub _group_member_handling_skeleton
1218             {
1219 364     364   552 my ( $self, $sect, $method ) = @_;
1220              
1221 364 50       524 return undef if not defined $sect;
1222              
1223 364 100       1300 if ( !( my ($group) = ( $sect =~ /\A(\S+)\s+\S/ ) ) )
1224             {
1225 237         365 return 1;
1226             }
1227             else
1228             {
1229 127         322 return $self->$method( $sect, $group );
1230             }
1231             }
1232              
1233             sub _SetGroupMember_helper
1234             {
1235 127     127   189 my ( $self, $sect, $group ) = @_;
1236              
1237 127 100       251 if ( not exists( $self->{group}{$group} ) )
1238             {
1239 69         139 $self->{group}{$group} = [];
1240             }
1241              
1242 127 50   86   285 if ( none { $_ eq $sect } @{ $self->{group}{$group} } )
  86         140  
  127         376  
1243             {
1244 127         136 CORE::push @{ $self->{group}{$group} }, $sect;
  127         181  
1245             }
1246              
1247 127         325 return;
1248             }
1249              
1250             sub SetGroupMember
1251             {
1252 357     357 1 480 my ( $self, $sect ) = @_;
1253              
1254 357         693 return $self->_group_member_handling_skeleton( $sect,
1255             '_SetGroupMember_helper' );
1256             }
1257              
1258              
1259             sub _RemoveGroupMember_helper
1260             {
1261 0     0   0 my ( $self, $sect, $group ) = @_;
1262              
1263 0 0       0 if ( !exists $self->{group}{$group} )
1264             {
1265 0         0 return;
1266             }
1267              
1268             $self->{group}{$group} =
1269 0         0 [ grep { $_ ne $sect } @{ $self->{group}{$group} } ];
  0         0  
  0         0  
1270              
1271 0         0 return;
1272             }
1273              
1274             sub RemoveGroupMember
1275             {
1276 7     7 1 12 my ( $self, $sect ) = @_;
1277              
1278 7         33 return $self->_group_member_handling_skeleton( $sect,
1279             '_RemoveGroupMember_helper' );
1280             }
1281              
1282              
1283             sub GroupMembers
1284             {
1285 6     6 1 453 my ( $self, $group ) = @_;
1286              
1287 6 50       12 return undef if not defined $group;
1288              
1289 6         18 $self->_caseify( \$group );
1290              
1291 6         6 return @{ _aref_or_empty( $self->{group}{$group} ) };
  6         22  
1292             }
1293              
1294              
1295             sub SetWriteMode
1296             {
1297 5     5 1 24 my ( $self, $mode ) = @_;
1298              
1299 5 50 33     69 if ( not( defined($mode) && ( $mode =~ m/[0-7]{3}/ ) ) )
1300             {
1301 0         0 return undef;
1302             }
1303              
1304 5         26 return ( $self->{file_mode} = $mode );
1305             }
1306              
1307              
1308             sub GetWriteMode
1309             {
1310 0     0 1 0 my $self = shift;
1311              
1312 0         0 return $self->{file_mode};
1313             }
1314              
1315              
1316             sub _write_config_to_filename
1317             {
1318 24     24   52 my ( $self, $filename, %parms ) = @_;
1319              
1320 24 100       669 if ( -e $filename )
1321             {
1322 8 50       76 if ( not( -w $filename ) )
1323             {
1324             #carp "File $filename is not writable. Refusing to write config";
1325 0         0 return undef;
1326             }
1327 8 100       27 if ( not exists $self->{file_mode} )
1328             {
1329 1         7 my $mode = ( stat $filename )[2];
1330 1         7 $self->{file_mode} = sprintf "%04o", ( $mode & 0777 );
1331             }
1332              
1333             #carp "Using mode $self->{file_mode} for file $file";
1334             }
1335              
1336 24         66 my ( $fh, $new_file );
1337              
1338             # We need to trap the exception that tempfile() may throw and instead
1339             # carp() and return undef() because that was the previous behaviour:
1340             #
1341             # See RT #77039 ( https://rt.cpan.org/Ticket/Display.html?id=77039 )
1342 24         36 eval {
1343 24         1384 ( $fh, $new_file ) =
1344             tempfile( "temp.ini-XXXXXXXXXX", DIR => dirname($filename) );
1345              
1346             # Convert the filehandle to a "text" filehandle suitable for use
1347             # on Windows (and other platforms).
1348             #
1349             # This may break compatibility for ultra-old perls (ones before 5.6.0)
1350             # so I say - Good Riddance!
1351 24 50       11868 if ( $^O =~ m/\AMSWin/ )
1352             {
1353 0         0 binmode $fh, ':crlf';
1354             }
1355             };
1356              
1357 24 50       70 if ($@)
1358             {
1359 0         0 carp("Unable to write temp config file: $!");
1360 0         0 return undef;
1361             }
1362              
1363 24         139 $self->OutputConfigToFileHandle( $fh, $parms{-delta} );
1364 24 50       1438 close($fh) or Carp::confess("close failed: $!");
1365 24 50       3336 if ( !rename( $new_file, $filename ) )
1366             {
1367 0         0 carp "Unable to rename temp config file ($new_file) to ${filename}: $!";
1368 0         0 return undef;
1369             }
1370 24 100       126 if ( exists $self->{file_mode} )
1371             {
1372 20 50       430 if ( not chmod( oct( $self->{file_mode} ), $filename ) )
1373             {
1374 0         0 carp "Unable to chmod $filename!";
1375             }
1376             }
1377              
1378 24         239 return 1;
1379             }
1380              
1381             sub _write_config_with_a_made_fh
1382             {
1383 3     3   5 my ( $self, $fh, %parms ) = @_;
1384              
1385             # Only roll back if it's not STDIN (if it is, Carp)
1386 3 50       18 if ( $fh == \*STDIN )
1387             {
1388 0         0 carp "Cannot write configuration file to STDIN.";
1389             }
1390             else
1391             {
1392 3         30 seek( $fh, 0, SEEK_SET() );
1393              
1394             # Make sure to keep the previous junk out.
1395             # See:
1396             # https://rt.cpan.org/Public/Bug/Display.html?id=103496
1397 3         157 truncate( $fh, 0 );
1398 3         19 $self->OutputConfigToFileHandle( $fh, $parms{-delta} );
1399 3         80 seek( $fh, 0, SEEK_SET() );
1400             } # end if
1401              
1402 3         13 return 1;
1403             }
1404              
1405             sub _write_config_to_fh
1406             {
1407 3     3   5 my ( $self, $file, %parms ) = @_;
1408              
1409             # Get a filehandle, allowing almost any type of 'file' parameter
1410             ## NB: If this were a filename, this would fail because _make_file
1411             ## opens a read-only handle, but we have already checked that case
1412             ## so re-using the logic is ok [JW/WADG]
1413 3         8 my $fh = $self->_make_filehandle($file);
1414              
1415 3 50       7 if ( !$fh )
1416             {
1417 0         0 carp "Could not find a filehandle for the input stream ($file): $!";
1418 0         0 return undef;
1419             }
1420              
1421 3         9 return $self->_write_config_with_a_made_fh( $fh, %parms );
1422             }
1423              
1424             sub WriteConfig
1425             {
1426 27     27 1 1458 my ( $self, $file, %parms ) = @_;
1427              
1428 27 50       68 return undef unless defined $file;
1429              
1430             # If we are using a filename, then do mode checks and write to a
1431             # temporary file to avoid a race condition
1432 27 100       87 if ( !ref($file) )
1433             {
1434 24         98 return $self->_write_config_to_filename( $file, %parms );
1435             }
1436              
1437             # Otherwise, reset to the start of the file and write, unless we are using
1438             # STDIN
1439             else
1440             {
1441 3         8 return $self->_write_config_to_fh( $file, %parms );
1442             }
1443             }
1444              
1445              
1446             sub RewriteConfig
1447             {
1448 16     16 1 1771 my $self = shift;
1449              
1450 16 50       42 if ( $self->_no_filename )
1451             {
1452 0         0 return 1;
1453             }
1454              
1455 16         51 return $self->WriteConfig( $self->{cf} );
1456             }
1457              
1458              
1459             sub GetFileName
1460             {
1461 5     5 1 10 my $self = shift;
1462              
1463 5         17 return $self->{cf};
1464             }
1465              
1466              
1467             sub SetFileName
1468             {
1469 12     12 1 1176 my ( $self, $new_filename ) = @_;
1470              
1471 12 50       38 if ( length($new_filename) > 0 )
1472             {
1473 12         35 return ( $self->{cf} = $new_filename );
1474             }
1475             else
1476             {
1477 0         0 return undef;
1478             }
1479             }
1480              
1481              
1482             sub _calc_eot_mark
1483             {
1484 65     65   120 my ( $self, $sect, $parm, $val ) = @_;
1485              
1486 65   100     156 my $eotmark = $self->{EOT}{$sect}{$parm} || 'EOT';
1487              
1488             # Make sure the $eotmark does not occur inside the string.
1489 65         355 my @letters = ( 'A' .. 'Z' );
1490 65         143 my $joined_val = join( q{ }, @$val );
1491 65         148 while ( index( $joined_val, $eotmark ) >= 0 )
1492             {
1493 2         8 $eotmark .= $letters[ rand(@letters) ];
1494             }
1495              
1496 65         193 return $eotmark;
1497             }
1498              
1499             sub _OutputParam
1500             {
1501 213     213   378 my ( $self, $sect, $parm, $val, $end_comment, $output_cb ) = @_;
1502              
1503             my $line_loop = sub {
1504 203     203   335 my ($mapper) = @_;
1505              
1506 203         310 foreach my $line ( @{$val}[ 0 .. $#$val - 1 ] )
  203         354  
1507             {
1508 135         232 $output_cb->( $mapper->($line) );
1509             }
1510 203 100       307 $output_cb->(
1511             $mapper->( $val->[-1] ),
1512             ( $end_comment ? (" $self->{comment_char} $end_comment") : () ),
1513             );
1514 203         247 return;
1515 213         635 };
1516              
1517 213 100 66     562 if ( !@$val )
    100          
1518             {
1519             # An empty variable - see:
1520             # https://rt.cpan.org/Public/Bug/Display.html?id=68554
1521 10         41 $output_cb->("$parm=");
1522             }
1523             elsif ( ( @$val == 1 ) or $self->{nomultiline} )
1524             {
1525 138     139   323 $line_loop->( sub { my ($line) = @_; return "$parm=$line"; } );
  139         180  
  139         341  
1526             }
1527             else
1528             {
1529 65         155 my $eotmark = $self->_calc_eot_mark( $sect, $parm, $val );
1530              
1531 65         159 $output_cb->("$parm= <<$eotmark");
1532 65     199   170 $line_loop->( sub { my ($line) = @_; return $line; } );
  199         256  
  199         349  
1533 65         173 $output_cb->($eotmark);
1534             }
1535              
1536 213         783 return;
1537             }
1538              
1539             sub OutputConfig
1540             {
1541 0     0 1 0 my ( $self, $delta ) = @_;
1542              
1543 0         0 return $self->OutputConfigToFileHandle( select(), $delta );
1544             }
1545              
1546             sub _output_comments
1547             {
1548 373     373   629 my ( $self, $print_line, $comments_aref ) = @_;
1549              
1550 373 100       604 if ( ref($comments_aref) eq 'ARRAY' )
1551             {
1552 169         232 foreach my $comment (@$comments_aref)
1553             {
1554 34         50 $print_line->($comment);
1555             }
1556             }
1557              
1558 373         433 return;
1559             }
1560              
1561             sub _process_continue_val
1562             {
1563 562     562   723 my ( $self, $fh ) = @_;
1564              
1565 562 100       948 if ( not $self->{allowcontinue} )
1566             {
1567 535         723 return;
1568             }
1569              
1570 27         37 my $val = $self->_curr_val;
1571              
1572 27         69 while ( $val =~ s/\\\z// )
1573             {
1574 2         4 $val .= $self->_read_next_line($fh);
1575             }
1576              
1577 27         43 $self->_curr_val($val);
1578              
1579 27         36 return;
1580             }
1581              
1582             sub _output_param_total
1583             {
1584 214     214   358 my ( $self, $sect, $parm, $print_line, $split_val, $delta ) = @_;
1585 214 100       384 if ( !defined $self->{v}{$sect}{$parm} )
1586             {
1587 1 50       3 if ($delta)
1588             {
1589 1         3 $print_line->("$self->{comment_char} $parm is deleted");
1590             }
1591             else
1592             {
1593 0 0       0 warn "Weird unknown parameter $parm" if $^W;
1594             }
1595 1         3 return;
1596             }
1597              
1598 213         589 $self->_output_comments( $print_line, $self->{pCMT}{$sect}{$parm} );
1599              
1600 213         365 my $val = $self->{v}{$sect}{$parm};
1601 213         335 my $end_comment = $self->{peCMT}{$sect}{$parm};
1602              
1603 213 50       321 return if !defined($val); # No parameter exists !!
1604              
1605 213 100       297 $self->_OutputParam( $sect, $parm, $split_val->($val),
1606             ( defined($end_comment) ? $end_comment : "" ), $print_line, );
1607              
1608 213         360 return;
1609             }
1610              
1611             sub _output_section
1612             {
1613 133     133   289 my ( $self, $sect, $print_line, $split_val, $delta, $position ) = @_;
1614              
1615 133 100       321 if ( !defined $self->{v}{$sect} )
1616             {
1617 1 50       3 if ($delta)
1618             {
1619 1         4 $print_line->("$self->{comment_char} [$sect] is deleted");
1620             }
1621             else
1622             {
1623 0 0       0 warn "Weird unknown section $sect" if $^W;
1624             }
1625 1         2 return;
1626             }
1627 132 50       244 return if not defined $self->{v}{$sect};
1628 132 100       301 $print_line->() if ( $position > 0 );
1629 132         358 $self->_output_comments( $print_line, $self->{sCMT}{$sect} );
1630              
1631 132 100 100     301 if ( !( $self->{fallback_used} and $sect eq $self->{fallback} ) )
1632             {
1633 131         280 $print_line->("[$sect]");
1634             }
1635 132 50       289 return if ref( $self->{v}{$sect} ) ne 'HASH';
1636              
1637 132 100       140 foreach my $parm ( @{ $self->{ $delta ? "myparms" : "parms" }{$sect} } )
  132         343  
1638             {
1639 214         353 $self->_output_param_total( $sect, $parm, $print_line, $split_val,
1640             $delta );
1641             }
1642              
1643 132         222 return;
1644             }
1645              
1646             sub OutputConfigToFileHandle
1647             {
1648             # We need no strict 'refs' to be able to print to $fh if it points
1649             # to a glob filehandle.
1650 41     41   376 no strict 'refs';
  41         54  
  41         60468  
1651 28     28 1 234 my ( $self, $fh, $delta ) = @_;
1652              
1653             my $ors =
1654             $self->{line_ends}
1655 28   50     192 || $\
1656             || "\n"; # $\ is normally unset, but use input by default
1657             my $print_line = sub {
1658 751 50   751   736 print {$fh} ( @_, $ors )
  751         1523  
1659             or die
1660             "Config-IniFiles cannot print to filehandle (out-of-space?). Aborting!";
1661 751         860 return;
1662 28         124 };
1663             my $split_val = sub {
1664 213     213   275 my ($val) = @_;
1665              
1666             return (
1667 213 100       1297 ( ref($val) eq 'ARRAY' )
1668             ? $val
1669             : [ split /[$ors]/, $val, -1 ]
1670             );
1671 28         99 };
1672              
1673 28         72 my $position = 0;
1674              
1675 28 100       42 foreach my $sect ( @{ $self->{ $delta ? "mysects" : "sects" } } )
  28         115  
1676             {
1677 133         283 $self->_output_section( $sect, $print_line, $split_val, $delta,
1678             $position++ );
1679             }
1680              
1681 28         95 $self->_output_comments( $print_line, [ $self->_GetEndComments() ] );
1682              
1683 28         118 return 1;
1684             }
1685              
1686              
1687             sub SetSectionComment
1688             {
1689 338     338 1 559 my ( $self, $sect, @comment ) = @_;
1690              
1691 338 100 66     917 if ( not( defined($sect) && @comment ) )
1692             {
1693 268         370 return undef;
1694             }
1695              
1696 70         159 $self->_caseify( \$sect );
1697              
1698 70         123 $self->_touch_section($sect);
1699              
1700             # At this point it's possible to have a comment for a section that
1701             # doesn't exist. This comment will not get written to the INI file.
1702 70         165 $self->{sCMT}{$sect} = $self->_markup_comments( \@comment );
1703              
1704 70         115 return scalar @comment;
1705             }
1706              
1707             # this helper makes sure that each line is preceded with the correct comment
1708             # character
1709             sub _markup_comments
1710             {
1711 101     101   144 my ( $self, $comment_aref ) = @_;
1712              
1713 101         139 my $allCmt = $self->{allowed_comment_char};
1714 101         128 my $cmtChr = $self->{comment_char};
1715              
1716 101         926 my $is_comment = qr/\A\s*[$allCmt]/;
1717              
1718             # TODO : Maybe create a qr// out of it.
1719 101 100       207 return [ map { ( $_ =~ $is_comment ) ? $_ : "$cmtChr $_" } @$comment_aref ];
  117         828  
1720             }
1721              
1722              
1723             sub _return_comment
1724             {
1725 9     9   16 my ( $self, $comment_aref ) = @_;
1726              
1727 9 50       23 my $delim = defined($/) ? $/ : "\n";
1728              
1729 9 100       42 return wantarray() ? @$comment_aref : join( $delim, @$comment_aref );
1730             }
1731              
1732             sub GetSectionComment
1733             {
1734 8     8 1 971 my ( $self, $sect ) = @_;
1735              
1736 8 50       17 return undef if not defined $sect;
1737              
1738 8         20 $self->_caseify( \$sect );
1739              
1740 8 100       19 if ( !exists $self->{sCMT}{$sect} )
1741             {
1742 3         10 return undef;
1743             }
1744              
1745 5         11 return $self->_return_comment( $self->{sCMT}{$sect} );
1746             }
1747              
1748              
1749             sub DeleteSectionComment
1750             {
1751 2     2 1 529 my $self = shift;
1752 2         4 my $sect = shift;
1753              
1754 2 50       8 return undef if not defined $sect;
1755              
1756 2         6 $self->_caseify( \$sect );
1757 2         5 $self->_touch_section($sect);
1758              
1759 2         4 delete $self->{sCMT}{$sect};
1760              
1761 2         4 return;
1762             }
1763              
1764              
1765             sub SetParameterComment
1766             {
1767 692     692 1 1101 my ( $self, $sect, $parm, @comment ) = @_;
1768              
1769 692 100 33     2411 if ( not( defined($sect) && defined($parm) && @comment ) )
      66        
1770             {
1771 661         1098 return undef;
1772             }
1773              
1774 31         101 $self->_caseify( \$sect, \$parm );
1775              
1776 31         72 $self->_touch_parameter( $sect, $parm );
1777              
1778             # Note that at this point, it's possible to have a comment for a parameter,
1779             # without that parameter actually existing in the INI file.
1780 31         77 $self->{pCMT}{$sect}{$parm} = $self->_markup_comments( \@comment );
1781              
1782 31         66 return scalar @comment;
1783             }
1784              
1785             sub _SetEndComments
1786             {
1787 81     81   132 my $self = shift;
1788 81         157 my @comments = @_;
1789              
1790 81         193 $self->{_comments_at_end_of_file} = \@comments;
1791              
1792 81         135 return 1;
1793             }
1794              
1795             sub _GetEndComments
1796             {
1797 28     28   58 my $self = shift;
1798              
1799 28         43 return @{ $self->{_comments_at_end_of_file} };
  28         137  
1800             }
1801              
1802              
1803             sub GetParameterComment
1804             {
1805 4     4 1 1541 my ( $self, $sect, $parm ) = @_;
1806              
1807 4 50 33     18 if ( not( defined($sect) && defined($parm) ) )
1808             {
1809 0         0 return undef;
1810             }
1811              
1812 4         27 $self->_caseify( \$sect, \$parm );
1813              
1814 4 50 33     17 if (
1815             not( exists( $self->{pCMT}{$sect} )
1816             && exists( $self->{pCMT}{$sect}{$parm} ) )
1817             )
1818             {
1819 0         0 return undef;
1820             }
1821              
1822 4         9 return $self->_return_comment( $self->{pCMT}{$sect}{$parm} );
1823             }
1824              
1825              
1826             sub DeleteParameterComment
1827             {
1828 1     1 1 3 my ( $self, $sect, $parm ) = @_;
1829              
1830 1 50 33     5 if ( not( defined($sect) && defined($parm) ) )
1831             {
1832 0         0 return undef;
1833             }
1834              
1835 1         4 $self->_caseify( \$sect, \$parm );
1836              
1837             # If the parameter doesn't exist, our goal has already been achieved
1838 1 50 33     5 if ( exists( $self->{pCMT}{$sect} )
1839             && exists( $self->{pCMT}{$sect}{$parm} ) )
1840             {
1841 1         4 $self->_touch_parameter( $sect, $parm );
1842 1         3 delete $self->{pCMT}{$sect}{$parm};
1843             }
1844              
1845 1         2 return 1;
1846             }
1847              
1848              
1849             sub GetParameterEOT
1850             {
1851 0     0 1 0 my ( $self, $sect, $parm ) = @_;
1852              
1853 0 0 0     0 if ( not( defined($sect) && defined($parm) ) )
1854             {
1855 0         0 return undef;
1856             }
1857              
1858 0         0 $self->_caseify( \$sect, \$parm );
1859              
1860 0         0 return $self->{EOT}{$sect}{$parm};
1861             }
1862              
1863              
1864             sub SetParameterEOT
1865             {
1866 129     129 1 208 my ( $self, $sect, $parm, $EOT ) = @_;
1867              
1868 129 50 33     529 if ( not( defined($sect) && defined($parm) && defined($EOT) ) )
      33        
1869             {
1870 0         0 return undef;
1871             }
1872              
1873 129         295 $self->_caseify( \$sect, \$parm );
1874              
1875 129         301 $self->_touch_parameter( $sect, $parm );
1876              
1877 129         267 $self->{EOT}{$sect}{$parm} = $EOT;
1878              
1879 129         162 return;
1880             }
1881              
1882              
1883             sub DeleteParameterEOT
1884             {
1885 0     0 1 0 my ( $self, $sect, $parm ) = @_;
1886              
1887 0 0 0     0 if ( not( defined($sect) && defined($parm) ) )
1888             {
1889 0         0 return undef;
1890             }
1891              
1892 0         0 $self->_caseify( \$sect, \$parm );
1893              
1894 0         0 $self->_touch_parameter( $sect, $parm );
1895 0         0 delete $self->{EOT}{$sect}{$parm};
1896              
1897 0         0 return;
1898             }
1899              
1900              
1901             sub SetParameterTrailingComment
1902             {
1903 692     692 1 1034 my ( $self, $sect, $parm, $cmt ) = @_;
1904              
1905 692 100 33     2268 if ( not( defined($sect) && defined($parm) && defined($cmt) ) )
      66        
1906             {
1907 129         184 return undef;
1908             }
1909              
1910 563         1224 $self->_caseify( \$sect, \$parm );
1911              
1912             # confirm the parameter exist
1913 563 50       1092 return undef if not exists $self->{v}{$sect}{$parm};
1914              
1915 563         1060 $self->_touch_parameter( $sect, $parm );
1916 563         1083 $self->{peCMT}{$sect}{$parm} = $cmt;
1917              
1918 563         701 return 1;
1919             }
1920              
1921              
1922             sub GetParameterTrailingComment
1923             {
1924 5     5 1 13 my ( $self, $sect, $parm ) = @_;
1925              
1926 5 50 33     23 if ( not( defined($sect) && defined($parm) ) )
1927             {
1928 0         0 return undef;
1929             }
1930              
1931 5         14 $self->_caseify( \$sect, \$parm );
1932              
1933             # confirm the parameter exist
1934 5 50       16 return undef if not exists $self->{v}{$sect}{$parm};
1935 5         22 return $self->{peCMT}{$sect}{$parm};
1936             }
1937              
1938              
1939             sub Delete
1940             {
1941 1     1 1 2 my $self = shift;
1942              
1943 1         3 foreach my $section ( $self->Sections() )
1944             {
1945 1         3 $self->DeleteSection($section);
1946             }
1947              
1948 1         4 return 1;
1949             } # end Delete
1950              
1951              
1952             ############################################################
1953             #
1954             # TIEHASH Methods
1955             #
1956             # Description:
1957             # These methods allow you to tie a hash to the
1958             # Config::IniFiles object. Note that, when tied, the
1959             # user wants to look at thinks like $ini{sec}{parm}, but the
1960             # TIEHASH only provides one level of hash interface, so the
1961             # root object gets asked for a $ini{sec}, which this
1962             # implements. To further tie the {parm} hash, the internal
1963             # class Config::IniFiles::_section, is provided, below.
1964             #
1965             ############################################################
1966             # ----------------------------------------------------------
1967             # Date Modification Author
1968             # ----------------------------------------------------------
1969             # 2000May09 Created method JW
1970             # ----------------------------------------------------------
1971             sub TIEHASH
1972             {
1973 6     6   853684 my $class = shift;
1974 6         21 my %parms = @_;
1975              
1976             # Get a new object
1977 6         43 my $self = $class->new(%parms);
1978              
1979 6         45 return $self;
1980             } # end TIEHASH
1981              
1982             # ----------------------------------------------------------
1983             # Date Modification Author
1984             # ----------------------------------------------------------
1985             # 2000May09 Created method JW
1986             # ----------------------------------------------------------
1987             sub FETCH
1988             {
1989 33     33   4802 my $self = shift;
1990 33         48 my ($key) = @_;
1991              
1992 33   100     102 $self->{_section_cache} ||= {};
1993              
1994 33         100 $self->_caseify( \$key );
1995 33 100       79 return if ( !$self->{v}{$key} );
1996              
1997             return $self->{_section_cache}->{$key}
1998 32 100       141 if exists $self->{_section_cache}->{$key};
1999              
2000 11         15 my %retval;
2001 11         57 tie %retval, 'Config::IniFiles::_section', $self, $key;
2002 11         113 return $self->{_section_cache}->{$key} = \%retval;
2003              
2004             } # end FETCH
2005              
2006             # ----------------------------------------------------------
2007             # Date Modification Author
2008             # ----------------------------------------------------------
2009             # 2000Jun14 Fixed bug where wrong ref was saved JW
2010             # 2000Oct09 Fixed possible but in %parms with defaults JW
2011             # 2001Apr04 Fixed -nocase problem in storing JW
2012             # ----------------------------------------------------------
2013             sub STORE
2014             {
2015 4     4   923 my $self = shift;
2016 4         9 my ( $key, $ref ) = @_;
2017              
2018 4 50       11 return undef unless ref($ref) eq 'HASH';
2019              
2020 4         11 $self->_caseify( \$key );
2021              
2022 4         10 $self->AddSection($key);
2023 4         12 $self->{v}{$key} = {%$ref};
2024 4         8 $self->{parms}{$key} = [ keys %$ref ];
2025 4         9 $self->{myparms}{$key} = [ keys %$ref ];
2026              
2027 4         9 return 1;
2028             } # end STORE
2029              
2030             # ----------------------------------------------------------
2031             # Date Modification Author
2032             # ----------------------------------------------------------
2033             # 2000May09 Created method JW
2034             # 2000Dec17 Now removes comments, groups and EOTs too JW
2035             # 2001Arp04 Fixed -nocase problem JW
2036             # ----------------------------------------------------------
2037             sub DELETE
2038             {
2039 1     1   688 my $self = shift;
2040 1         3 my ($key) = @_;
2041              
2042 1         2 my $retval = $self->FETCH($key);
2043 1         5 $self->DeleteSection($key);
2044 1         4 return $retval;
2045             } # end DELETE
2046              
2047             # ----------------------------------------------------------
2048             # Date Modification Author
2049             # ----------------------------------------------------------
2050             # 2000May09 Created method JW
2051             # ----------------------------------------------------------
2052             sub CLEAR
2053             {
2054 0     0   0 my $self = shift;
2055              
2056 0         0 return $self->Delete();
2057             } # end CLEAR
2058              
2059             # ----------------------------------------------------------
2060             # Date Modification Author
2061             # ----------------------------------------------------------
2062             # 2000May09 Created method JW
2063             # ----------------------------------------------------------
2064             sub FIRSTKEY
2065             {
2066 1     1   7 my $self = shift;
2067              
2068 1         3 $self->{tied_enumerator} = 0;
2069 1         4 return $self->NEXTKEY();
2070             } # end FIRSTKEY
2071              
2072             # ----------------------------------------------------------
2073             # Date Modification Author
2074             # ----------------------------------------------------------
2075             # 2000May09 Created method JW
2076             # ----------------------------------------------------------
2077             sub NEXTKEY
2078             {
2079 11     11   11 my $self = shift;
2080 11         31 my ($last) = @_;
2081              
2082 11         10 my $i = $self->{tied_enumerator}++;
2083 11         14 my $key = $self->{sects}[$i];
2084 11 100       15 return if ( !defined $key );
2085 10 50       23 return wantarray ? ( $key, $self->FETCH($key) ) : $key;
2086             } # end NEXTKEY
2087              
2088             # ----------------------------------------------------------
2089             # Date Modification Author
2090             # ----------------------------------------------------------
2091             # 2000May09 Created method JW
2092             # 2001Apr04 Fixed -nocase bug and false true bug JW
2093             # ----------------------------------------------------------
2094             sub EXISTS
2095             {
2096 0     0   0 my $self = shift;
2097 0         0 my ($key) = @_;
2098 0         0 return $self->SectionExists($key);
2099             } # end EXISTS
2100              
2101             # ----------------------------------------------------------
2102             # DESTROY is used by TIEHASH and the Perl garbage collector,
2103             # ----------------------------------------------------------
2104             # Date Modification Author
2105             # ----------------------------------------------------------
2106             # 2000May09 Created method JW
2107             # ----------------------------------------------------------
2108             sub DESTROY
2109       0     {
2110             # my $self = shift;
2111             } # end if
2112              
2113             # ----------------------------------------------------------
2114             # Sub: _make_filehandle
2115             #
2116             # Args: $thing
2117             # $thing An input source
2118             #
2119             # Description: Takes an input source - a filehandle,
2120             # filehandle glob, reference to a filehandle glob, IO::File
2121             # object or scalar filename - and returns a file handle to
2122             # read from it with.
2123             # ----------------------------------------------------------
2124             # Date Modification Author
2125             # ----------------------------------------------------------
2126             # 06Dec2001 Added to support input from any source JW
2127             # ----------------------------------------------------------
2128             sub _make_filehandle
2129             {
2130 93     93   291304 my $self = shift;
2131              
2132             #
2133             # This code is 'borrowed' from Lincoln D. Stein's GD.pm module
2134             # with modification for this module. Thanks Lincoln!
2135             #
2136              
2137 41     41   307 no strict 'refs';
  41         66  
  41         7688  
2138 93         130 my $thing = shift;
2139              
2140 93 100       242 if ( ref($thing) eq "SCALAR" )
2141             {
2142 3 50       6 if ( eval { require IO::Scalar; $IO::Scalar::VERSION >= 2.109; } )
  3         1134  
  3         6860  
2143             {
2144 3         16 return IO::Scalar->new($thing);
2145             }
2146             else
2147             {
2148 0 0       0 warn "SCALAR reference as file descriptor requires IO::stringy "
2149             . "v2.109 or later"
2150             if ($^W);
2151 0         0 return;
2152             }
2153             }
2154              
2155 90 100       443 return $thing if defined( fileno $thing );
2156              
2157             # otherwise try qualifying it into caller's package
2158 75         445 my $fh = qualify_to_ref( $thing, caller(1) );
2159 75 50       1866 return $fh if defined( fileno $fh );
2160              
2161             # otherwise treat it as a file to open; 3-arg open so the filename is
2162             # not interpreted as a command or redirect
2163 75         209 $fh = gensym;
2164 75 100       4335 open( $fh, '<', $thing ) || return;
2165              
2166 71         241 return $fh;
2167             } # end _make_filehandle
2168              
2169             ############################################################
2170             #
2171             # INTERNAL PACKAGE: Config::IniFiles::_section
2172             #
2173             # Description:
2174             # This package is used to provide a single-level TIEHASH
2175             # interface to the sections in the IniFile. When tied, the
2176             # user wants to look at thinks like $ini{sec}{parm}, but the
2177             # TIEHASH only provides one level of hash interface, so the
2178             # root object gets asked for a $ini{sec} and must return a
2179             # has reference that accurately covers the '{parm}' part.
2180             #
2181             # This package is only used when tied and is inter-woven
2182             # between the sections and their parameters when the TIEHASH
2183             # method is called by Perl. It's a very simple implementation
2184             # of a tied hash object that simply maps onto the object API.
2185             #
2186             ############################################################
2187             # Date Modification Author
2188             # ----------------------------------------------------------
2189             # 2000.May.09 Created to excapsulate TIEHASH interface JW
2190             ############################################################
2191             package Config::IniFiles::_section;
2192              
2193 41     41   242 use strict;
  41         54  
  41         837  
2194 41     41   134 use warnings;
  41         50  
  41         2041  
2195 41     41   165 use Carp;
  41         49  
  41         2601  
2196 41     41   234 use vars qw( $VERSION );
  41         65  
  41         23877  
2197              
2198             $Config::IniFiles::_section::VERSION = 2.16;
2199              
2200             # ----------------------------------------------------------
2201             # Sub: Config::IniFiles::_section::TIEHASH
2202             #
2203             # Args: $class, $config, $section
2204             # $class The class that this is being tied to.
2205             # $config The parent Config::IniFiles object
2206             # $section The section this tied object refers to
2207             #
2208             # Description: Builds the object that implements accesses to
2209             # the tied hash.
2210             # ----------------------------------------------------------
2211             # Date Modification Author
2212             # ----------------------------------------------------------
2213             # ----------------------------------------------------------
2214             sub TIEHASH
2215             {
2216 11     11   16 my $proto = shift;
2217 11   33     35 my $class = ref($proto) || $proto;
2218 11         20 my ( $config, $section ) = @_;
2219              
2220             # Make a new object
2221 11         41 return bless { config => $config, section => $section }, $class;
2222             } # end TIEHASH
2223              
2224             # ----------------------------------------------------------
2225             # Sub: Config::IniFiles::_section::FETCH
2226             #
2227             # Args: $key
2228             # $key The name of the key whose value to get
2229             #
2230             # Description: Returns the value associated with $key. If
2231             # the value is a list, returns a list reference.
2232             # ----------------------------------------------------------
2233             # Date Modification Author
2234             # ----------------------------------------------------------
2235             # 2000Jun15 Fixed bugs in -default handler JW
2236             # 2000Dec07 Fixed another bug in -deault handler JW
2237             # 2002Jul04 Returning scalar values (Bug:447532) AS
2238             # ----------------------------------------------------------
2239             sub FETCH
2240             {
2241 22     22   118 my ( $self, $key ) = @_;
2242 22         56 my @retval = $self->{config}->val( $self->{section}, $key );
2243 22 100       93 return ( @retval <= 1 ) ? $retval[0] : \@retval;
2244             } # end FETCH
2245              
2246             # ----------------------------------------------------------
2247             # Sub: Config::IniFiles::_section::STORE
2248             #
2249             # Args: $key, @val
2250             # $key The key under which to store the value
2251             # @val The value to store, either an array or a scalar
2252             #
2253             # Description: Sets the value for the specified $key
2254             # ----------------------------------------------------------
2255             # Date Modification Author
2256             # ----------------------------------------------------------
2257             # 2001Apr04 Fixed -nocase bug JW
2258             # ----------------------------------------------------------
2259             sub STORE
2260             {
2261 11     11   28 my ( $self, $key, @val ) = @_;
2262 11         40 return $self->{config}->newval( $self->{section}, $key, @val );
2263             } # end STORE
2264              
2265             # ----------------------------------------------------------
2266             # Sub: Config::IniFiles::_section::DELETE
2267             #
2268             # Args: $key
2269             # $key The key to remove from the hash
2270             #
2271             # Description: Removes the specified key from the hash and
2272             # returns its former value.
2273             # ----------------------------------------------------------
2274             # Date Modification Author
2275             # ----------------------------------------------------------
2276             # 2001Apr04 Fixed -nocase bug JW
2277             # ----------------------------------------------------------
2278             sub DELETE
2279             {
2280 1     1   3 my ( $self, $key ) = @_;
2281 1         3 my $retval = $self->{config}->val( $self->{section}, $key );
2282 1         4 $self->{config}->delval( $self->{section}, $key );
2283 1         2 return $retval;
2284             } # end DELETE
2285              
2286             # ----------------------------------------------------------
2287             # Sub: Config::IniFiles::_section::CLEAR
2288             #
2289             # Args: (None)
2290             #
2291             # Description: Empties the entire hash
2292             # ----------------------------------------------------------
2293             # Date Modification Author
2294             # ----------------------------------------------------------
2295             # ----------------------------------------------------------
2296             sub CLEAR
2297             {
2298 1     1   3 my ($self) = @_;
2299 1         3 return $self->{config}->DeleteSection( $self->{section} );
2300             } # end CLEAR
2301              
2302             # ----------------------------------------------------------
2303             # Sub: Config::IniFiles::_section::EXISTS
2304             #
2305             # Args: $key
2306             # $key The key to look for
2307             #
2308             # Description: Returns whether the key exists
2309             # ----------------------------------------------------------
2310             # Date Modification Author
2311             # ----------------------------------------------------------
2312             # 2001Apr04 Fixed -nocase bug JW
2313             # ----------------------------------------------------------
2314             sub EXISTS
2315             {
2316 0     0   0 my ( $self, $key ) = @_;
2317 0         0 return $self->{config}->exists( $self->{section}, $key );
2318             } # end EXISTS
2319              
2320             # ----------------------------------------------------------
2321             # Sub: Config::IniFiles::_section::FIRSTKEY
2322             #
2323             # Args: (None)
2324             #
2325             # Description: Returns the first key in the hash
2326             # ----------------------------------------------------------
2327             # Date Modification Author
2328             # ----------------------------------------------------------
2329             # ----------------------------------------------------------
2330             sub FIRSTKEY
2331             {
2332 4     4   4 my $self = shift;
2333              
2334 4         16 $self->{tied_enumerator} = 0;
2335 4         23 return $self->NEXTKEY();
2336             } # end FIRSTKEY
2337              
2338             # ----------------------------------------------------------
2339             # Sub: Config::IniFiles::_section::NEXTKEY
2340             #
2341             # Args: $last
2342             # $last The last key accessed by the iterator
2343             #
2344             # Description: Returns the next key in line
2345             # ----------------------------------------------------------
2346             # Date Modification Author
2347             # ----------------------------------------------------------
2348             # ----------------------------------------------------------
2349             sub NEXTKEY
2350             {
2351 13     13   21 my $self = shift;
2352 13         17 my ($last) = @_;
2353              
2354 13         17 my $i = $self->{tied_enumerator}++;
2355 13         24 my @keys = $self->{config}->Parameters( $self->{section} );
2356 13         15 my $key = $keys[$i];
2357 13 100       24 return if ( !defined $key );
2358 10 50       39 return wantarray ? ( $key, $self->FETCH($key) ) : $key;
2359             } # end NEXTKEY
2360              
2361             # ----------------------------------------------------------
2362             # Sub: Config::IniFiles::_section::DESTROY
2363             #
2364             # Args: (None)
2365             #
2366             # Description: Called on cleanup
2367             # ----------------------------------------------------------
2368             # Date Modification Author
2369             # ----------------------------------------------------------
2370             # ----------------------------------------------------------
2371             sub DESTROY
2372       0     {
2373             # my $self = shift
2374             } # end DESTROY
2375              
2376             1;
2377              
2378              
2379              
2380             1;
2381              
2382             # Please keep the following within the last four lines of the file
2383             #[JW for editor]:mode=perl:tabSize=8:indentSize=2:noTabs=true:indentOnEnter=true:
2384              
2385             __END__