File Coverage

blib/lib/Config/IniFiles.pm
Criterion Covered Total %
statement 802 882 90.9
branch 294 388 75.7
condition 64 117 54.7
subroutine 117 127 92.1
pod 39 39 100.0
total 1316 1553 84.7


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