File Coverage

blib/lib/Config/IniFiles.pm
Criterion Covered Total %
statement 804 885 90.8
branch 301 398 75.6
condition 64 117 54.7
subroutine 117 127 92.1
pod 39 39 100.0
total 1325 1566 84.6


line stmt bran cond sub pod time code
1             package Config::IniFiles;
2              
3             require 5.008;
4 38     38   2333806 use strict;
  38         370  
  38         988  
5 38     38   177 use warnings;
  38         64  
  38         1294  
6              
7             our $VERSION = '3.000003';
8 38     38   184 use Carp;
  38         59  
  38         1991  
9 38     38   15872 use Symbol 'gensym', 'qualify_to_ref'; # For the 'any data type' hack
  38         26527  
  38         2235  
10 38     38   257 use Fcntl qw( SEEK_SET SEEK_CUR );
  38         65  
  38         1869  
11              
12 38     38   208 use List::Util 1.33 qw(any none);
  38         674  
  38         3664  
13              
14 38     38   287 use File::Basename qw( dirname );
  38         68  
  38         2605  
15 38     38   25655 use File::Temp qw/ tempfile /;
  38         680547  
  38         276795  
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   5649 my $self = shift;
25              
26 4845 100       7268 if (@_)
27             {
28 96 100       291 $self->{nocase} = ( shift(@_) ? 1 : 0 );
29             }
30              
31 4845         8343 return $self->{nocase};
32             }
33              
34             sub _is_parm_in_sect
35             {
36 1568     1568   2409 my ( $self, $sect, $parm ) = @_;
37              
38 1568     2987   3774 return any { $_ eq $parm } @{ $self->{myparms}{$sect} };
  2987         5097  
  1568         4084  
39             }
40              
41             sub new
42             {
43 86     86 1 52434 my $class = shift;
44 86         291 my %parms = @_;
45              
46 86         194 my $errs = 0;
47 86         166 my @groups = ();
48              
49 86         592 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     529 if ( ref( $parms{-import} )
    50          
61             && ( $parms{-import}->isa('Config::IniFiles') ) )
62             {
63 9         17 $self->{imported} = $parms{-import}; # ReadConfig will load the data
64 9         18 $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         151 delete $parms{-import};
71              
72             # Copy the original parameters so we
73             # can use them when we build new sections
74 86         208 %{ $self->{startup_settings} } = %parms;
  86         357  
75              
76             # Parse options
77 86         169 my ( $k, $v );
78 86         267 $self->_nocase(0);
79              
80             # Handle known parameters first in this order,
81             # because each() could return parameters in any order
82 86 100       262 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         135 $self->{cf} = $v;
87             }
88 86 100       229 if ( defined( $v = delete $parms{'-nocase'} ) )
89             {
90 10         22 $self->_nocase($v);
91             }
92 86 100       225 if ( defined( $v = delete $parms{'-default'} ) )
93             {
94 7 50       18 $self->{default} = $self->_nocase ? lc($v) : $v;
95             }
96 86 100       266 if ( defined( $v = delete $parms{'-fallback'} ) )
97             {
98 1 50       2 $self->{fallback} = $self->_nocase ? lc($v) : $v;
99             }
100 86 50       212 if ( defined( $v = delete $parms{'-reloadwarn'} ) )
101             {
102 0 0       0 $self->{reloadwarn} = $v ? 1 : 0;
103             }
104 86 100       203 if ( defined( $v = delete $parms{'-nomultiline'} ) )
105             {
106 1 50       4 $self->{nomultiline} = $v ? 1 : 0;
107             }
108 86 100       194 if ( defined( $v = delete $parms{'-allowcontinue'} ) )
109             {
110 1 50       4 $self->{allowcontinue} = $v ? 1 : 0;
111             }
112 86 100       195 if ( defined( $v = delete $parms{'-allowempty'} ) )
113             {
114 11 50       35 $self->{allowempty} = $v ? 1 : 0;
115             }
116 86 50       198 if ( defined( $v = delete $parms{'-negativedeltas'} ) )
117             {
118 0 0       0 $self->{negativedeltas} = $v ? 1 : 0;
119             }
120 86 100       226 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         5 $self->{comment_char} = $v;
136             }
137             }
138 86 100       209 if ( defined( $v = delete $parms{'-allowedcommentchars'} ) )
139             {
140             # must not be square bracket, equal sign or alphanumeric
141 2 50 33     13 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 86 100       191 if ( defined( $v = delete $parms{'-handle_trailing_comment'} ) )
153             {
154 4 100       50 $self->{handle_trailing_comment} = $v ? 1 : 0;
155             }
156 86 100       207 if ( defined( $v = delete $parms{'-php_compat'} ) )
157             {
158 1 50       3 $self->{php_compat} = $v ? 1 : 0;
159             }
160              
161 86 100       258 $self->{comment_char} = '#' unless exists $self->{comment_char};
162             $self->{allowed_comment_char} = ';'
163 86 100       217 unless exists $self->{allowed_comment_char};
164              
165             # make sure that comment character is always allowed
166 86         185 $self->{allowed_comment_char} .= $self->{comment_char};
167              
168 86         173 $self->{_comments_at_end_of_file} = [];
169              
170             # Any other parameters are unknown
171 86         311 while ( ( $k, $v ) = each %parms )
172             {
173 0         0 carp "Unknown named parameter $k=>$v";
174 0         0 $errs++;
175             }
176              
177 86 50       181 return undef if $errs;
178              
179 86 100       231 if ( $self->ReadConfig )
180             {
181 81         615 return $self;
182             }
183             else
184             {
185 5         74 return undef;
186             }
187             }
188              
189              
190             sub _caseify
191             {
192 4741     4741   6730 my ( $self, @refs ) = @_;
193              
194 4741 100       6861 if ( $self->_nocase )
195             {
196 1348         2119 foreach my $ref ( grep { defined } @refs[ 0 .. 1 ] )
  2696         4526  
197             {
198 1774         1901 ${$ref} = lc( ${$ref} );
  1774         2611  
  1774         2157  
199             }
200             }
201              
202 4741 100       7484 if ( $self->{php_compat} )
203             {
204 27         47 foreach my $ref ( grep { defined } @refs[ 1 .. 1 ] )
  27         75  
205             {
206 17         21 ${$ref} =~ s{\[\]$}{};
  17         50  
207             }
208 27         59 foreach my $ref ( grep { defined } @refs[ 2 .. $#refs ] )
  4         9  
209             {
210 4 100       6 if ( length( ${$ref} ) >= 2 )
  4         12  
211             {
212 2         2 my $quote = substr( ${$ref}, 0, 1 );
  2         7  
213 2 50 66     10 if ( ( $quote eq q{"} or $quote eq q{'} )
      33        
214 2         8 and substr( ${$ref}, -1, 1 ) eq $quote )
215             {
216 2         2 ${$ref} = substr( ${$ref}, 1, -1 );
  2         3  
  2         5  
217 2         4 ${$ref} =~ s{$quote$quote}{}g;
  2         33  
218 2 100       8 ${$ref} =~ s{\\$quote}{$quote}g if $quote eq q{"};
  1         13  
219             }
220             }
221             }
222             }
223              
224 4741         6174 return;
225             }
226              
227             sub val
228             {
229 107     107 1 14037 my ( $self, $sect, $parm, $def ) = @_;
230              
231             # Always return undef on bad parameters
232 107 50 33     460 if ( not( defined($sect) && defined($parm) ) )
233             {
234 0         0 return;
235             }
236              
237 107         322 $self->_caseify( \$sect, \$parm );
238              
239             my $val_sect =
240             defined( $self->{v}{$sect}{$parm} )
241             ? $sect
242 107 100       392 : $self->{default};
243              
244 107         221 my $val = $self->{v}{$val_sect}{$parm};
245              
246             # If the value is undef, make it $def instead (which could just be undef)
247 107 100       215 if ( !defined($val) )
248             {
249 7         11 $val = $def;
250             }
251              
252             # Return the value in the desired context
253 107 100       296 if (wantarray)
    100          
254             {
255 34 100       135 if ( ref($val) eq "ARRAY" )
    100          
256             {
257 12         49 return @$val;
258             }
259             elsif ( defined($val) )
260             {
261 20         77 return $val;
262             }
263             else
264             {
265 2         7 return;
266             }
267             }
268             elsif ( ref($val) eq "ARRAY" )
269             {
270 5 50       31 return join( ( defined($/) ? $/ : "\n" ), @$val );
271             }
272             else
273             {
274 68         279 return $val;
275             }
276             }
277              
278              
279             sub exists
280             {
281 2     2 1 13 my ( $self, $sect, $parm ) = @_;
282              
283 2         8 $self->_caseify( \$sect, \$parm );
284              
285 2         15 return ( exists $self->{v}{$sect}{$parm} );
286             }
287              
288              
289             sub push
290             {
291 92     92 1 211 my ( $self, $sect, $parm, @vals ) = @_;
292              
293 92 50       176 return undef if not defined $sect;
294 92 50       179 return undef if not defined $parm;
295              
296 92         219 $self->_caseify( \$sect, \$parm );
297              
298 92 50       204 return undef if ( !defined( $self->{v}{$sect}{$parm} ) );
299              
300 92 50       229 return 1 if ( !@vals );
301              
302 92         213 $self->_touch_parameter( $sect, $parm );
303              
304             $self->{EOT}{$sect}{$parm} = 'EOT'
305 92 100       279 if ( !defined $self->{EOT}{$sect}{$parm} );
306              
307             $self->{v}{$sect}{$parm} = [ $self->{v}{$sect}{$parm} ]
308 92 100       277 unless ( ref( $self->{v}{$sect}{$parm} ) eq "ARRAY" );
309              
310 92         122 CORE::push @{ $self->{v}{$sect}{$parm} }, @vals;
  92         232  
311 92         163 return 1;
312             }
313              
314              
315             sub setval
316             {
317 1     1 1 997 my $self = shift;
318 1         2 my $sect = shift;
319 1         2 my $parm = shift;
320 1         3 my @val = @_;
321              
322 1 50       4 return undef if not defined $sect;
323 1 50       3 return undef if not defined $parm;
324              
325 1         3 $self->_caseify( \$sect, \$parm );
326              
327 1 50       4 if ( defined( $self->{v}{$sect}{$parm} ) )
328             {
329 0         0 $self->_touch_parameter( $sect, $parm );
330 0 0       0 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 0         0 $self->{v}{$sect}{$parm} = shift @val;
338             }
339 0         0 return 1;
340             }
341             else
342             {
343 1         3 return undef;
344             }
345             }
346              
347              
348             sub newval
349             {
350 638     638 1 4052 my $self = shift;
351 638         800 my $sect = shift;
352 638         759 my $parm = shift;
353 638         1098 my @val = @_;
354              
355 638 50       1061 return undef if not defined $sect;
356 638 50       965 return undef if not defined $parm;
357              
358 638         1334 $self->_caseify( \$sect, \$parm );
359              
360 638         1490 $self->AddSection($sect);
361              
362 638 100   896   1911 if ( none { $_ eq $parm } @{ $self->{parms}{$sect} } )
  896         1261  
  638         2092  
363             {
364 611         733 CORE::push( @{ $self->{parms}{$sect} }, $parm );
  611         1245  
365             }
366              
367 638         2167 $self->_touch_parameter( $sect, $parm );
368 638 100       1231 if ( @val > 1 )
369             {
370 112         306 $self->{v}{$sect}{$parm} = \@val;
371 112 100       290 if ( !defined $self->{EOT}{$sect}{$parm} )
372             {
373 105         201 $self->{EOT}{$sect}{$parm} = 'EOT';
374             }
375             }
376             else
377             {
378 526         1174 $self->{v}{$sect}{$parm} = shift @val;
379             }
380 638         1028 return 1;
381             }
382              
383              
384             sub delval
385             {
386 6     6 1 1857 my $self = shift;
387 6         11 my $sect = shift;
388 6         10 my $parm = shift;
389              
390 6 50       28 return undef if not defined $sect;
391 6 50       15 return undef if not defined $parm;
392              
393 6         25 $self->_caseify( \$sect, \$parm );
394              
395 6         10 $self->{parms}{$sect} = [ grep { $_ ne $parm } @{ $self->{parms}{$sect} } ];
  24         50  
  6         17  
396 6         21 $self->_touch_parameter( $sect, $parm );
397 6         14 delete $self->{v}{$sect}{$parm};
398              
399 6         11 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   509 my $ref = shift;
409              
410 411 100       608 if ( !ref($ref) )
411             {
412 206         453 return $ref;
413             }
414              
415 205 100       376 if ( UNIVERSAL::isa( $ref, "ARRAY" ) )
416             {
417 64         111 return [ map { _deepcopy($_) } @$ref ];
  118         171  
418             }
419              
420 141 50       233 if ( UNIVERSAL::isa( $ref, "HASH" ) )
421             {
422 141         165 my $return = {};
423 141         280 foreach my $k ( keys %$ref )
424             {
425 178         276 $return->{$k} = _deepcopy( $ref->{$k} );
426             }
427 141         258 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 2061     2061   2669 my ( $self, $fh ) = @_;
437 2061         2473 my $s = '';
438 2061 100       3316 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 83         114 local $/ = \1;
  83         382  
444 83         125 my $nextchar;
445             do
446 83         128 {
447 1115         2411 $nextchar = <$fh>;
448 1115 100       2305 return undef if ( !defined $nextchar );
449 1103         2361 $s .= $nextchar;
450             } until ( $s =~ m/((\015|\012|\025|\n)$)/s );
451 71         338 $self->{line_ends} = $1;
452 71 100       402 if ( $nextchar eq "\x0d" )
453             {
454             # peek at the next char
455 4         25 $nextchar = <$fh>;
456 4 100       20 if ( $nextchar eq "\x0a" )
457             {
458 3         14 $self->{line_ends} .= "\x0a";
459             }
460             else
461             {
462 1         15 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 71         359 $s =~ s/\A//;
471              
472 71         208 return $s;
473             }
474             else
475             {
476 1978         5307 local $/ = $self->{line_ends};
477 1978         6951 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 83     83   228 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 83 100       234 if ( !ref( $self->{cf} ) )
490             {
491 71 50       828 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 12         78 seek( $fh, 0, SEEK_SET() );
497             } # end if
498             }
499              
500             sub _no_filename
501             {
502 116     116   172 my $self = shift;
503              
504 116         183 my $fn = $self->{cf};
505              
506 116   66     646 return ( not( defined($fn) && length($fn) ) );
507             }
508              
509             sub _read_line_num
510             {
511 4178     4178   4711 my $self = shift;
512              
513 4178 100       6190 if (@_)
514             {
515 2063         2547 $self->{_read_line_num} = shift;
516             }
517              
518 4178         6809 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 2061     2061   3063 my ( $self, $fh ) = @_;
525              
526 2061         3268 my $line = $self->_nextline($fh);
527              
528 2061 100       4120 if ( !defined($line) )
529             {
530 81         265 return undef;
531             }
532              
533 1980         2947 $self->_read_line_num( $self->_read_line_num() + 1 );
534              
535             # Remove line ending char(s)
536 1980         7946 $line =~ s/(\015\012?|\012|\025|\n)\z//;
537              
538 1980         4745 return $line;
539             }
540              
541             sub _add_error
542             {
543 7     7   15 my ( $self, $msg ) = @_;
544              
545 7         12 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 5583     5583   6214 my $self = shift;
554              
555 5583 100       8243 if (@_)
556             {
557 418         603 $self->{_curr_sect} = shift;
558             }
559              
560 5583         10405 return $self->{_curr_sect};
561             }
562              
563             # The current parameter - used for parsing.
564             sub _curr_parm
565             {
566 3768     3768   4258 my $self = shift;
567              
568 3768 100       5291 if (@_)
569             {
570 773         1082 $self->{_curr_parm} = shift;
571             }
572              
573 3768         6973 return $self->{_curr_parm};
574             }
575              
576             # Current location - section and parameter.
577             sub _curr_loc
578             {
579 2306     2306   2567 my $self = shift;
580              
581 2306         3029 return ( $self->_curr_sect, $self->_curr_parm );
582             }
583              
584             # The current value - used in parsing.
585             sub _curr_val
586             {
587 2087     2087   2421 my $self = shift;
588              
589 2087 100       3104 if (@_)
590             {
591 806         1181 $self->{_curr_val} = shift;
592             }
593              
594 2087         3803 return $self->{_curr_val};
595             }
596              
597             sub _curr_cmts
598             {
599 2326     2326   2698 my $self = shift;
600              
601 2326 100       3580 if (@_)
602             {
603 1106         1597 $self->{_curr_cmts} = shift;
604             }
605              
606 2326         4392 return $self->{_curr_cmts};
607             }
608              
609             sub _curr_end_comment
610             {
611 1941     1941   2221 my $self = shift;
612              
613 1941 100       2925 if (@_)
614             {
615 1252         1706 $self->{_curr_end_comment} = shift;
616             }
617              
618 1941         3020 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   187 my ( $self, $line ) = @_;
627              
628 120 100 66     304 if ( $self->{negativedeltas}
629             and my ($to_delete) =
630             $line =~ m/\A$self->{comment_char} (.*) is deleted\z/ )
631             {
632 2 100       8 if ( my ($sect) = $to_delete =~ m/\A\[(.*)\]\z/ )
633             {
634 1         3 $self->DeleteSection($sect);
635             }
636             else
637             {
638 1         3 $self->delval( $self->_curr_sect, $to_delete );
639             }
640             }
641             else
642             {
643 118         137 CORE::push( @{ $self->_curr_cmts }, $line );
  118         175  
644             }
645              
646 120         399 return $RET_CONTINUE;
647             }
648              
649             sub _ReadConfig_new_section
650             {
651 334     334   522 my ( $self, $sect ) = @_;
652              
653 334         780 $self->_caseify( undef, \$sect );
654              
655 334         676 $self->_curr_sect($sect);
656 334         517 $self->AddSection( $self->_curr_sect );
657 334         639 $self->SetSectionComment( $self->_curr_sect, @{ $self->_curr_cmts } );
  334         539  
658 334         827 $self->_curr_cmts( [] );
659              
660 334         1098 return $RET_CONTINUE;
661             }
662              
663             sub _handle_fallback_sect
664             {
665 692     692   894 my ($self) = @_;
666              
667 692 100 100     1021 if ( ( !defined( $self->_curr_sect ) ) and defined( $self->{fallback} ) )
668             {
669 1         3 $self->_curr_sect( $self->{fallback} );
670 1         2 $self->{fallback_used}++;
671             }
672              
673 692         935 return;
674             }
675              
676             sub _ReadConfig_load_value
677             {
678 689     689   883 my ( $self, $val_aref ) = @_;
679              
680             # Now load value
681 689 100 100     1144 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         184 $self->push( $self->_curr_loc, @$val_aref );
686             }
687             else
688             {
689             # Loaded parameters shadow imported ones, instead of appending
690             # to them
691 597         1011 $self->newval( $self->_curr_loc, @$val_aref );
692             }
693              
694 689         1124 return;
695             }
696              
697             sub _test_for_fallback_or_no_sect
698             {
699 692     692   981 my ( $self, $fh ) = @_;
700              
701 692         1358 $self->_handle_fallback_sect;
702              
703 692 100       1046 if ( !defined $self->_curr_sect )
704             {
705 2         8 $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         7 return $RET_BREAK;
712             }
713              
714 690         1274 return $RET_CONTINUE;
715             }
716              
717             sub _ReadConfig_handle_here_doc_param
718             {
719 130     130   228 my ( $self, $fh, $eotmark, $val_aref ) = @_;
720              
721 130         206 my $foundeot = 0;
722 130         228 my $startline = $self->_read_line_num();
723              
724             HERE_DOC_LOOP:
725 130         283 while ( defined( my $line = $self->_read_next_line($fh) ) )
726             {
727 498 100       782 if ( $line eq $eotmark )
728             {
729 129         153 $foundeot = 1;
730 129         228 last HERE_DOC_LOOP;
731             }
732             else
733             {
734             # Untaint
735 369         903 my ($contents) = $line =~ /(.*)/ms;
736 369         852 CORE::push( @$val_aref, $contents );
737             }
738             }
739              
740 130 100       283 if ( !$foundeot )
741             {
742 1         9 $self->_add_error(
743             sprintf( '%d: %s',
744             $startline, qq#no end marker ("$eotmark") found# )
745             );
746 1         4 $self->_rollback($fh);
747 1         4 return $RET_BREAK;
748             }
749              
750 129         265 return $RET_CONTINUE;
751             }
752              
753             sub _ReadConfig_handle_non_here_doc_param
754             {
755 560     560   801 my ( $self, $fh, $val_aref ) = @_;
756              
757 560         761 my $allCmt = $self->{allowed_comment_char};
758 560         706 my $end_commenthandle = $self->{handle_trailing_comment};
759              
760             # process continuation lines, if any
761 560         1168 $self->_process_continue_val($fh);
762              
763             # we should split value and comments if there is any comment
764 560 100 66     1036 if ( $end_commenthandle
765             and my ( $value_to_assign, $end_comment_to_assign ) =
766             $self->_curr_val =~ /(.*?)\s*[$allCmt]\s*(.*)$/ )
767             {
768 4         17 $self->_curr_val($value_to_assign);
769 4         10 $self->_curr_end_comment($end_comment_to_assign);
770             }
771             else
772             {
773 556         847 $self->_curr_end_comment(q{});
774             }
775              
776 560         805 @{$val_aref} = ( $self->_curr_val );
  560         784  
777              
778 560         851 return;
779             }
780              
781             sub _ReadConfig_populate_values
782             {
783 689     689   1138 my ( $self, $val_aref, $eotmark ) = @_;
784              
785 689         1345 $self->_ReadConfig_load_value($val_aref);
786              
787 689         1198 $self->SetParameterComment( $self->_curr_loc, @{ $self->_curr_cmts } );
  689         1030  
788 689         1786 $self->_curr_cmts( [] );
789 689 100       1129 if ( defined $eotmark )
790             {
791 129         247 $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 689         1057 $self->SetParameterTrailingComment( $self->_curr_loc,
796             $self->_curr_end_comment );
797              
798 689         1006 return;
799             }
800              
801             sub _ReadConfig_param_assignment
802             {
803 692     692   1584 my ( $self, $fh, $line, $parm, $value_to_assign ) = @_;
804              
805 692         1644 $self->_caseify( undef, \$parm, \$value_to_assign );
806              
807 692         1470 $self->_curr_val($value_to_assign);
808 692         1336 $self->_curr_end_comment( undef() );
809              
810 692 100       1171 if ( !defined( $self->_test_for_fallback_or_no_sect($fh) ) )
811             {
812              
813 2         7 return $RET_BREAK;
814             }
815              
816 690         1359 $self->_curr_parm($parm);
817              
818 690         916 my @val = ();
819 690         767 my $eotmark;
820              
821 690 100       999 if ( ($eotmark) = $self->_curr_val =~ /\A<<(.*)$/ )
822             {
823 130 100       301 if (
824             !defined(
825             $self->_ReadConfig_handle_here_doc_param(
826             $fh, $eotmark, \@val
827             )
828             )
829             )
830             {
831 1         6 return $RET_BREAK;
832             }
833             }
834             else
835             {
836 560         1065 $self->_ReadConfig_handle_non_here_doc_param( $fh, \@val );
837             }
838              
839 689         1588 $self->_ReadConfig_populate_values( \@val, $eotmark );
840              
841 689         2525 return $RET_CONTINUE;
842             }
843              
844             # Return 1 to continue - undef to terminate the loop.
845             sub _ReadConfig_handle_line
846             {
847 1480     1480   2241 my ( $self, $fh, $line ) = @_;
848              
849 1480         2063 my $allCmt = $self->{allowed_comment_char};
850              
851             # ignore blank lines
852 1480 100       3722 if ( $line =~ /\A\s*\z/ )
853             {
854 331         888 return $RET_CONTINUE;
855             }
856              
857             # collect comments
858 1149 100       4731 if ( $line =~ /\A\s*[$allCmt]/ )
859             {
860 120         249 return $self->_ReadConfig_handle_comment($line);
861             }
862              
863             # New Section
864 1029 100       2989 if ( my ($sect) = $line =~ /\A\s*\[\s*(\S|\S.*\S)\s*\]\s*\z/ )
865             {
866 334         674 return $self->_ReadConfig_new_section($sect);
867             }
868              
869             # New parameter
870 695 100       3321 if ( my ( $parm, $value_to_assign ) =
871             $line =~ /^\s*([^=]*?[^=\s])\s*=\s*(.*)$/ )
872             {
873 692         1393 return $self->_ReadConfig_param_assignment( $fh, $line, $parm,
874             $value_to_assign );
875             }
876              
877             $self->_add_error(
878 3         9 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         8 return $RET_CONTINUE;
886             }
887              
888             sub _ReadConfig_lines_loop
889             {
890 83     83   191 my ( $self, $fh ) = @_;
891              
892 83         234 $self->_curr_sect( undef() );
893 83         236 $self->_curr_parm( undef() );
894 83         206 $self->_curr_val( undef() );
895 83         224 $self->_curr_cmts( [] );
896              
897 83         218 while ( defined( my $line = $self->_read_next_line($fh) ) )
898             {
899 1480 100       2568 if (
900             !defined( scalar( $self->_ReadConfig_handle_line( $fh, $line ) ) ) )
901             {
902 3         12 return undef;
903             }
904             }
905              
906 80         270 return 1;
907             }
908              
909             sub ReadConfig
910             {
911 100     100 1 189 my $self = shift;
912              
913 100         183 @Config::IniFiles::errors = ();
914              
915             # Initialize (and clear out) storage hashes
916 100         241 $self->{sects} = [];
917 100         248 $self->{parms} = {};
918 100         300 $self->{group} = {};
919 100         266 $self->{v} = {};
920 100         183 $self->{sCMT} = {};
921 100         188 $self->{pCMT} = {};
922 100         180 $self->{EOT} = {};
923             $self->{mysects} =
924 100         166 []; # A pair of hashes to remember which params are loaded
925 100         196 $self->{myparms} = {}; # or set using the API vs. imported - useful for
926             $self->{peCMT} =
927 100         189 {}; # this will store trailing comments at the end of single-line params
928 100         165 $self->{e} = {}; # If a section already exists
929 100         165 $self->{mye} = {}; # If a section already exists
930             # import shadowing, see below, and WriteConfig($fn, -delta=>1)
931              
932 100 100       240 if ( defined $self->{imported} )
933             {
934 13         26 foreach my $field (qw(sects parms group v sCMT pCMT EOT e))
935             {
936 104         177 $self->{$field} = _deepcopy( $self->{imported}->{$field} );
937             }
938             }
939              
940 100 100       255 if ( $self->_no_filename )
941             {
942 17         49 return 1;
943             }
944              
945             # If we want warnings, then send one to the STDERR log
946 83 50       238 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 83         251 my $fh = $self->_make_filehandle( $self->{cf} );
956 83 50       459 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 83 100 100     993 if ( ref($fh) ne "IO::Scalar" && -e $fh )
965             {
966 79 100       293 if ( not exists $self->{file_mode} )
967             {
968 66         637 my @stats = stat $fh;
969 66 50       479 $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 83         170 my $first = '';
976              
977 83         148 delete $self->{line_ends}; # Marks start of parsing for _nextline()
978              
979 83         276 $self->_read_line_num(0);
980              
981 83 100       537 if ( !defined( $self->_ReadConfig_lines_loop($fh) ) )
982             {
983 3         16 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 80 100 100     142 if ( !keys %{ $self->{v} } && !$self->{allowempty} )
  80         406  
989             {
990 1         3 $self->_add_error("Empty file treated as error");
991 1         4 $self->_rollback($fh);
992 1         4 return undef;
993             }
994              
995 79 100       281 if ( defined( my $defaultsect = $self->{startup_settings}->{-default} ) )
996             {
997 11         30 $self->AddSection($defaultsect);
998             }
999              
1000 79         131 $self->_SetEndComments( @{ $self->_curr_cmts } );
  79         215  
1001              
1002 79         280 $self->_rollback($fh);
1003 79 100       491 return ( @Config::IniFiles::errors ? undef : 1 );
1004             }
1005              
1006              
1007             sub Sections
1008             {
1009 4     4 1 16 my $self = shift;
1010              
1011 4         6 return @{ _aref_or_empty( $self->{sects} ) };
  4         13  
1012             }
1013              
1014              
1015             sub SectionExists
1016             {
1017 995     995 1 1452 my $self = shift;
1018 995         1239 my $sect = shift;
1019              
1020 995 50       1556 return undef if not defined $sect;
1021              
1022 995         1923 $self->_caseify( \$sect );
1023              
1024 995 100       2488 return ( ( exists $self->{e}{$sect} ) ? 1 : 0 );
1025             }
1026              
1027              
1028             sub _AddSection_Helper
1029             {
1030 355     355   597 my ( $self, $sect ) = @_;
1031 355         653 $self->{e}{$sect} = 1;
1032 355         414 CORE::push @{ $self->{sects} }, $sect;
  355         792  
1033 355         804 $self->_touch_section($sect);
1034              
1035 355         781 $self->SetGroupMember($sect);
1036              
1037             # Set up the parameter names and values lists
1038 355   50     1717 $self->{parms}{$sect} ||= [];
1039              
1040 355 100       746 if ( !defined( $self->{v}{$sect} ) )
1041             {
1042 354         626 $self->{sCMT}{$sect} = [];
1043 354         662 $self->{pCMT}{$sect} = {}; # Comments above parameters
1044 354         582 $self->{parms}{$sect} = [];
1045 354         572 $self->{v}{$sect} = {};
1046             }
1047              
1048 355         522 return;
1049             }
1050              
1051             sub AddSection
1052             {
1053 989     989 1 1480 my ( $self, $sect ) = @_;
1054              
1055 989 50       1638 return undef if not defined $sect;
1056              
1057 989         1998 $self->_caseify( \$sect );
1058              
1059 989 100       1803 if ( $self->SectionExists($sect) )
1060             {
1061 636         840 return;
1062             }
1063              
1064 353         692 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 1892     1892   2541 my ( $self, $sect ) = @_;
1071              
1072 1892   50     3554 $self->{mysects} ||= [];
1073              
1074 1892 100       3135 unless ( exists $self->{mye}{$sect} )
1075             {
1076 364         455 CORE::push @{ $self->{mysects} }, $sect;
  364         601  
1077 364         629 $self->{mye}{$sect} = 1;
1078             }
1079              
1080 1892         2308 return;
1081             }
1082              
1083             # Marks a parameter as modified by us (this includes deleted by us).
1084             sub _touch_parameter
1085             {
1086 1458     1458   2287 my ( $self, $sect, $parm ) = @_;
1087              
1088 1458         2757 $self->_touch_section($sect);
1089 1458 50       2423 return if ( !exists $self->{v}{$sect} );
1090 1458   100     3201 $self->{myparms}{$sect} ||= [];
1091              
1092 1458 100       2370 if ( !$self->_is_parm_in_sect( $sect, $parm ) )
1093             {
1094 637         794 CORE::push @{ $self->{myparms}{$sect} }, $parm;
  637         1192  
1095             }
1096              
1097 1458         3164 return;
1098             }
1099              
1100              
1101             sub DeleteSection
1102             {
1103 7     7 1 13 my $self = shift;
1104 7         12 my $sect = shift;
1105              
1106 7 50       17 return undef if not defined $sect;
1107              
1108 7         19 $self->_caseify( \$sect );
1109              
1110             # This is done the fast way, change if data structure changes!!
1111 7         19 delete $self->{v}{$sect};
1112 7         19 delete $self->{sCMT}{$sect};
1113 7         11 delete $self->{pCMT}{$sect};
1114 7         13 delete $self->{EOT}{$sect};
1115 7         12 delete $self->{parms}{$sect};
1116 7         13 delete $self->{myparms}{$sect};
1117 7         11 delete $self->{e}{$sect};
1118              
1119 7         12 $self->{sects} = [ grep { $_ ne $sect } @{ $self->{sects} } ];
  29         49  
  7         15  
1120 7         26 $self->_touch_section($sect);
1121              
1122 7         20 $self->RemoveGroupMember($sect);
1123              
1124 7         15 return 1;
1125             } # end DeleteSection
1126              
1127              
1128             sub RenameSection
1129             {
1130 1     1 1 2 my $self = shift;
1131 1         2 my $old_sect = shift;
1132 1         1 my $new_sect = shift;
1133 1         2 my $include_groupmembers = shift;
1134             return undef
1135 1 50       3 unless $self->CopySection( $old_sect, $new_sect,
1136             $include_groupmembers );
1137 1         4 return $self->DeleteSection($old_sect);
1138              
1139             } # end RenameSection
1140              
1141              
1142             sub CopySection
1143             {
1144 2     2 1 5 my $self = shift;
1145 2         3 my $old_sect = shift;
1146 2         3 my $new_sect = shift;
1147 2         4 my $include_groupmembers = shift;
1148              
1149 2 50 33     12 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         6 $self->_caseify( \$new_sect );
1158 2         7 $self->_AddSection_Helper($new_sect);
1159              
1160             # This is done the fast way, change if data structure changes!!
1161 2         6 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         18 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   61 my ($aref) = @_;
1185              
1186 32 100 66     209 return ( ( defined($aref) and ref($aref) eq 'ARRAY' ) ? $aref : [] );
1187             }
1188              
1189             sub Parameters
1190             {
1191 22     22 1 590 my $self = shift;
1192 22         31 my $sect = shift;
1193              
1194 22 50       50 return undef if not defined $sect;
1195              
1196 22         51 $self->_caseify( \$sect );
1197              
1198 22         30 return @{ _aref_or_empty( $self->{parms}{$sect} ) };
  22         43  
1199             }
1200              
1201              
1202             sub Groups
1203             {
1204 2     2 1 11 my $self = shift;
1205              
1206 2 50       8 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 362     362   561 my ( $self, $sect, $method ) = @_;
1220              
1221 362 50       610 return undef if not defined $sect;
1222              
1223 362 100       1415 if ( !( my ($group) = ( $sect =~ /\A(\S+)\s+\S/ ) ) )
1224             {
1225 235         393 return 1;
1226             }
1227             else
1228             {
1229 127         353 return $self->$method( $sect, $group );
1230             }
1231             }
1232              
1233             sub _SetGroupMember_helper
1234             {
1235 127     127   220 my ( $self, $sect, $group ) = @_;
1236              
1237 127 100       258 if ( not exists( $self->{group}{$group} ) )
1238             {
1239 69         181 $self->{group}{$group} = [];
1240             }
1241              
1242 127 50   86   377 if ( none { $_ eq $sect } @{ $self->{group}{$group} } )
  86         143  
  127         458  
1243             {
1244 127         171 CORE::push @{ $self->{group}{$group} }, $sect;
  127         227  
1245             }
1246              
1247 127         375 return;
1248             }
1249              
1250             sub SetGroupMember
1251             {
1252 355     355 1 551 my ( $self, $sect ) = @_;
1253              
1254 355         689 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         15 return $self->_group_member_handling_skeleton( $sect,
1279             '_RemoveGroupMember_helper' );
1280             }
1281              
1282              
1283             sub GroupMembers
1284             {
1285 6     6 1 455 my ( $self, $group ) = @_;
1286              
1287 6 50       16 return undef if not defined $group;
1288              
1289 6         19 $self->_caseify( \$group );
1290              
1291 6         10 return @{ _aref_or_empty( $self->{group}{$group} ) };
  6         19  
1292             }
1293              
1294              
1295             sub SetWriteMode
1296             {
1297 5     5 1 34 my ( $self, $mode ) = @_;
1298              
1299 5 50 33     44 if ( not( defined($mode) && ( $mode =~ m/[0-7]{3}/ ) ) )
1300             {
1301 0         0 return undef;
1302             }
1303              
1304 5         14 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 23     23   68 my ( $self, $filename, %parms ) = @_;
1319              
1320 23 100       482 if ( -e $filename )
1321             {
1322 7 50       101 if ( not( -w $filename ) )
1323             {
1324             #carp "File $filename is not writable. Refusing to write config";
1325 0         0 return undef;
1326             }
1327 7 100       30 if ( not exists $self->{file_mode} )
1328             {
1329 1         12 my $mode = ( stat $filename )[2];
1330 1         8 $self->{file_mode} = sprintf "%04o", ( $mode & 0777 );
1331             }
1332              
1333             #carp "Using mode $self->{file_mode} for file $file";
1334             }
1335              
1336 23         110 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 23         49 eval {
1343 23         1385 ( $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 23 50       8166 if ( $^O =~ m/\AMSWin/ )
1352             {
1353 0         0 binmode $fh, ':crlf';
1354             }
1355             };
1356              
1357 23 50       112 if ($@)
1358             {
1359 0         0 carp("Unable to write temp config file: $!");
1360 0         0 return undef;
1361             }
1362              
1363 23         154 $self->OutputConfigToFileHandle( $fh, $parms{-delta} );
1364 23 50       882 close($fh) or Carp::confess("close failed: $!");
1365 23 50       1436 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 23 100       110 if ( exists $self->{file_mode} )
1371             {
1372 19 50       335 if ( not chmod( oct( $self->{file_mode} ), $filename ) )
1373             {
1374 0         0 carp "Unable to chmod $filename!";
1375             }
1376             }
1377              
1378 23         172 return 1;
1379             }
1380              
1381             sub _write_config_with_a_made_fh
1382             {
1383 3     3   8 my ( $self, $fh, %parms ) = @_;
1384              
1385             # Only roll back if it's not STDIN (if it is, Carp)
1386 3 50       8 if ( $fh == \*STDIN )
1387             {
1388 0         0 carp "Cannot write configuration file to STDIN.";
1389             }
1390             else
1391             {
1392 3         24 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         131 truncate( $fh, 0 );
1398 3         22 $self->OutputConfigToFileHandle( $fh, $parms{-delta} );
1399 3         92 seek( $fh, 0, SEEK_SET() );
1400             } # end if
1401              
1402 3         19 return 1;
1403             }
1404              
1405             sub _write_config_to_fh
1406             {
1407 3     3   12 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       10 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         10 return $self->_write_config_with_a_made_fh( $fh, %parms );
1422             }
1423              
1424             sub WriteConfig
1425             {
1426 26     26 1 1466 my ( $self, $file, %parms ) = @_;
1427              
1428 26 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 26 100       82 if ( !ref($file) )
1433             {
1434 23         97 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         11 return $self->_write_config_to_fh( $file, %parms );
1442             }
1443             }
1444              
1445              
1446             sub RewriteConfig
1447             {
1448 16     16 1 1625 my $self = shift;
1449              
1450 16 50       65 if ( $self->_no_filename )
1451             {
1452 0         0 return 1;
1453             }
1454              
1455 16         56 return $self->WriteConfig( $self->{cf} );
1456             }
1457              
1458              
1459             sub GetFileName
1460             {
1461 5     5 1 11 my $self = shift;
1462              
1463 5         22 return $self->{cf};
1464             }
1465              
1466              
1467             sub SetFileName
1468             {
1469 12     12 1 1295 my ( $self, $new_filename ) = @_;
1470              
1471 12 50       84 if ( length($new_filename) > 0 )
1472             {
1473 12         63 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   116 my ( $self, $sect, $parm, $val ) = @_;
1485              
1486 65   100     167 my $eotmark = $self->{EOT}{$sect}{$parm} || 'EOT';
1487              
1488             # Make sure the $eotmark does not occur inside the string.
1489 65         307 my @letters = ( 'A' .. 'Z' );
1490 65         168 my $joined_val = join( q{ }, @$val );
1491 65         172 while ( index( $joined_val, $eotmark ) >= 0 )
1492             {
1493 2         13 $eotmark .= $letters[ rand(@letters) ];
1494             }
1495              
1496 65         191 return $eotmark;
1497             }
1498              
1499             sub _OutputParam
1500             {
1501 212     212   418 my ( $self, $sect, $parm, $val, $end_comment, $output_cb ) = @_;
1502              
1503             my $line_loop = sub {
1504 202     202   290 my ($mapper) = @_;
1505              
1506 202         331 foreach my $line ( @{$val}[ 0 .. $#$val - 1 ] )
  202         381  
1507             {
1508 135         175 $output_cb->( $mapper->($line) );
1509             }
1510 202 100       327 $output_cb->(
1511             $mapper->( $val->[-1] ),
1512             ( $end_comment ? (" $self->{comment_char} $end_comment") : () ),
1513             );
1514 202         250 return;
1515 212         645 };
1516              
1517 212 100 66     647 if ( !@$val )
    100          
1518             {
1519             # An empty variable - see:
1520             # https://rt.cpan.org/Public/Bug/Display.html?id=68554
1521 10         37 $output_cb->("$parm=");
1522             }
1523             elsif ( ( @$val == 1 ) or $self->{nomultiline} )
1524             {
1525 137     138   408 $line_loop->( sub { my ($line) = @_; return "$parm=$line"; } );
  138         200  
  138         420  
1526             }
1527             else
1528             {
1529 65         142 my $eotmark = $self->_calc_eot_mark( $sect, $parm, $val );
1530              
1531 65         179 $output_cb->("$parm= <<$eotmark");
1532 65     199   204 $line_loop->( sub { my ($line) = @_; return $line; } );
  199         336  
  199         342  
1533 65         171 $output_cb->($eotmark);
1534             }
1535              
1536 212         766 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 370     370   634 my ( $self, $print_line, $comments_aref ) = @_;
1549              
1550 370 100       687 if ( ref($comments_aref) eq 'ARRAY' )
1551             {
1552 167         267 foreach my $comment (@$comments_aref)
1553             {
1554 34         54 $print_line->($comment);
1555             }
1556             }
1557              
1558 370         462 return;
1559             }
1560              
1561             sub _process_continue_val
1562             {
1563 560     560   794 my ( $self, $fh ) = @_;
1564              
1565 560 100       1026 if ( not $self->{allowcontinue} )
1566             {
1567 533         778 return;
1568             }
1569              
1570 27         36 my $val = $self->_curr_val;
1571              
1572 27         58 while ( $val =~ s/\\\z// )
1573             {
1574 2         4 $val .= $self->_read_next_line($fh);
1575             }
1576              
1577 27         50 $self->_curr_val($val);
1578              
1579 27         32 return;
1580             }
1581              
1582             sub _output_param_total
1583             {
1584 213     213   399 my ( $self, $sect, $parm, $print_line, $split_val, $delta ) = @_;
1585 213 100       434 if ( !defined $self->{v}{$sect}{$parm} )
1586             {
1587 1 50       3 if ($delta)
1588             {
1589 1         5 $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         2 return;
1596             }
1597              
1598 212         589 $self->_output_comments( $print_line, $self->{pCMT}{$sect}{$parm} );
1599              
1600 212         419 my $val = $self->{v}{$sect}{$parm};
1601 212         349 my $end_comment = $self->{peCMT}{$sect}{$parm};
1602              
1603 212 50       369 return if !defined($val); # No parameter exists !!
1604              
1605 212 100       350 $self->_OutputParam( $sect, $parm, $split_val->($val),
1606             ( defined($end_comment) ? $end_comment : "" ), $print_line, );
1607              
1608 212         353 return;
1609             }
1610              
1611             sub _output_section
1612             {
1613 132     132   249 my ( $self, $sect, $print_line, $split_val, $delta, $position ) = @_;
1614              
1615 132 100       290 if ( !defined $self->{v}{$sect} )
1616             {
1617 1 50       2 if ($delta)
1618             {
1619 1         5 $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 131 50       255 return if not defined $self->{v}{$sect};
1628 131 100       315 $print_line->() if ( $position > 0 );
1629 131         395 $self->_output_comments( $print_line, $self->{sCMT}{$sect} );
1630              
1631 131 100 100     288 if ( !( $self->{fallback_used} and $sect eq $self->{fallback} ) )
1632             {
1633 130         285 $print_line->("[$sect]");
1634             }
1635 131 50       315 return if ref( $self->{v}{$sect} ) ne 'HASH';
1636              
1637 131 100       153 foreach my $parm ( @{ $self->{ $delta ? "myparms" : "parms" }{$sect} } )
  131         350  
1638             {
1639 213         395 $self->_output_param_total( $sect, $parm, $print_line, $split_val,
1640             $delta );
1641             }
1642              
1643 131         197 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 38     38   371 no strict 'refs';
  38         91  
  38         65392  
1651 27     27 1 153 my ( $self, $fh, $delta ) = @_;
1652              
1653             my $ors =
1654             $self->{line_ends}
1655 27   50     134 || $\
1656             || "\n"; # $\ is normally unset, but use input by default
1657             my $print_line = sub {
1658 749 50   749   797 print {$fh} ( @_, $ors )
  749         1652  
1659             or die
1660             "Config-IniFiles cannot print to filehandle (out-of-space?). Aborting!";
1661 749         1002 return;
1662 27         126 };
1663             my $split_val = sub {
1664 212     212   293 my ($val) = @_;
1665              
1666             return (
1667 212 100       1225 ( ref($val) eq 'ARRAY' )
1668             ? $val
1669             : [ split /[$ors]/, $val, -1 ]
1670             );
1671 27         89 };
1672              
1673 27         49 my $position = 0;
1674              
1675 27 100       52 foreach my $sect ( @{ $self->{ $delta ? "mysects" : "sects" } } )
  27         120  
1676             {
1677 132         296 $self->_output_section( $sect, $print_line, $split_val, $delta,
1678             $position++ );
1679             }
1680              
1681 27         138 $self->_output_comments( $print_line, [ $self->_GetEndComments() ] );
1682              
1683 27         162 return 1;
1684             }
1685              
1686              
1687             sub SetSectionComment
1688             {
1689 336     336 1 633 my ( $self, $sect, @comment ) = @_;
1690              
1691 336 100 66     1454 if ( not( defined($sect) && @comment ) )
1692             {
1693 266         395 return undef;
1694             }
1695              
1696 70         186 $self->_caseify( \$sect );
1697              
1698 70         156 $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         150 $self->{sCMT}{$sect} = $self->_markup_comments( \@comment );
1703              
1704 70         146 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   161 my ( $self, $comment_aref ) = @_;
1712              
1713 101         148 my $allCmt = $self->{allowed_comment_char};
1714 101         149 my $cmtChr = $self->{comment_char};
1715              
1716 101         671 my $is_comment = qr/\A\s*[$allCmt]/;
1717              
1718             # TODO : Maybe create a qr// out of it.
1719 101 100       215 return [ map { ( $_ =~ $is_comment ) ? $_ : "$cmtChr $_" } @$comment_aref ];
  117         928  
1720             }
1721              
1722              
1723             sub _return_comment
1724             {
1725 9     9   14 my ( $self, $comment_aref ) = @_;
1726              
1727 9 50       24 my $delim = defined($/) ? $/ : "\n";
1728              
1729 9 100       39 return wantarray() ? @$comment_aref : join( $delim, @$comment_aref );
1730             }
1731              
1732             sub GetSectionComment
1733             {
1734 8     8 1 922 my ( $self, $sect ) = @_;
1735              
1736 8 50       43 return undef if not defined $sect;
1737              
1738 8         22 $self->_caseify( \$sect );
1739              
1740 8 100       19 if ( !exists $self->{sCMT}{$sect} )
1741             {
1742 3         12 return undef;
1743             }
1744              
1745 5         15 return $self->_return_comment( $self->{sCMT}{$sect} );
1746             }
1747              
1748              
1749             sub DeleteSectionComment
1750             {
1751 2     2 1 621 my $self = shift;
1752 2         4 my $sect = shift;
1753              
1754 2 50       7 return undef if not defined $sect;
1755              
1756 2         8 $self->_caseify( \$sect );
1757 2         6 $self->_touch_section($sect);
1758              
1759 2         6 delete $self->{sCMT}{$sect};
1760              
1761 2         4 return;
1762             }
1763              
1764              
1765             sub SetParameterComment
1766             {
1767 690     690 1 1227 my ( $self, $sect, $parm, @comment ) = @_;
1768              
1769 690 100 33     2772 if ( not( defined($sect) && defined($parm) && @comment ) )
      66        
1770             {
1771 659         1008 return undef;
1772             }
1773              
1774 31         91 $self->_caseify( \$sect, \$parm );
1775              
1776 31         76 $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         66 $self->{pCMT}{$sect}{$parm} = $self->_markup_comments( \@comment );
1781              
1782 31         68 return scalar @comment;
1783             }
1784              
1785             sub _SetEndComments
1786             {
1787 79     79   129 my $self = shift;
1788 79         186 my @comments = @_;
1789              
1790 79         168 $self->{_comments_at_end_of_file} = \@comments;
1791              
1792 79         140 return 1;
1793             }
1794              
1795             sub _GetEndComments
1796             {
1797 27     27   86 my $self = shift;
1798              
1799 27         42 return @{ $self->{_comments_at_end_of_file} };
  27         138  
1800             }
1801              
1802              
1803             sub GetParameterComment
1804             {
1805 4     4 1 1163 my ( $self, $sect, $parm ) = @_;
1806              
1807 4 50 33     17 if ( not( defined($sect) && defined($parm) ) )
1808             {
1809 0         0 return undef;
1810             }
1811              
1812 4         20 $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     7 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     6 if ( exists( $self->{pCMT}{$sect} )
1839             && exists( $self->{pCMT}{$sect}{$parm} ) )
1840             {
1841 1         3 $self->_touch_parameter( $sect, $parm );
1842 1         3 delete $self->{pCMT}{$sect}{$parm};
1843             }
1844              
1845 1         3 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 277 my ( $self, $sect, $parm, $EOT ) = @_;
1867              
1868 129 50 33     523 if ( not( defined($sect) && defined($parm) && defined($EOT) ) )
      33        
1869             {
1870 0         0 return undef;
1871             }
1872              
1873 129         316 $self->_caseify( \$sect, \$parm );
1874              
1875 129         290 $self->_touch_parameter( $sect, $parm );
1876              
1877 129         242 $self->{EOT}{$sect}{$parm} = $EOT;
1878              
1879 129         185 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 690     690 1 1175 my ( $self, $sect, $parm, $cmt ) = @_;
1904              
1905 690 100 33     2532 if ( not( defined($sect) && defined($parm) && defined($cmt) ) )
      66        
1906             {
1907 129         192 return undef;
1908             }
1909              
1910 561         1339 $self->_caseify( \$sect, \$parm );
1911              
1912             # confirm the parameter exist
1913 561 50       1101 return undef if not exists $self->{v}{$sect}{$parm};
1914              
1915 561         1169 $self->_touch_parameter( $sect, $parm );
1916 561         1236 $self->{peCMT}{$sect}{$parm} = $cmt;
1917              
1918 561         750 return 1;
1919             }
1920              
1921              
1922             sub GetParameterTrailingComment
1923             {
1924 5     5 1 15 my ( $self, $sect, $parm ) = @_;
1925              
1926 5 50 33     28 if ( not( defined($sect) && defined($parm) ) )
1927             {
1928 0         0 return undef;
1929             }
1930              
1931 5         18 $self->_caseify( \$sect, \$parm );
1932              
1933             # confirm the parameter exist
1934 5 50       17 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 3 my $self = shift;
1942              
1943 1         10 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   1704 my $class = shift;
1974 6         24 my %parms = @_;
1975              
1976             # Get a new object
1977 6         31 my $self = $class->new(%parms);
1978              
1979 6         33 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   4050 my $self = shift;
1990 33         53 my ($key) = @_;
1991              
1992 33   100     110 $self->{_section_cache} ||= {};
1993              
1994 33         84 $self->_caseify( \$key );
1995 33 100       74 return if ( !$self->{v}{$key} );
1996              
1997             return $self->{_section_cache}->{$key}
1998 32 100       149 if exists $self->{_section_cache}->{$key};
1999              
2000 11         18 my %retval;
2001 11         63 tie %retval, 'Config::IniFiles::_section', $self, $key;
2002 11         68 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   768 my $self = shift;
2016 4         10 my ( $key, $ref ) = @_;
2017              
2018 4 50       13 return undef unless ref($ref) eq 'HASH';
2019              
2020 4         12 $self->_caseify( \$key );
2021              
2022 4         13 $self->AddSection($key);
2023 4         12 $self->{v}{$key} = {%$ref};
2024 4         12 $self->{parms}{$key} = [ keys %$ref ];
2025 4         11 $self->{myparms}{$key} = [ keys %$ref ];
2026              
2027 4         12 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   480 my $self = shift;
2040 1         4 my ($key) = @_;
2041              
2042 1         4 my $retval = $self->FETCH($key);
2043 1         4 $self->DeleteSection($key);
2044 1         3 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   14 my $self = shift;
2080 11         12 my ($last) = @_;
2081              
2082 11         15 my $i = $self->{tied_enumerator}++;
2083 11         13 my $key = $self->{sects}[$i];
2084 11 100       20 return if ( !defined $key );
2085 10 50       24 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 86     86   132 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 38     38   310 no strict 'refs';
  38         83  
  38         7599  
2138 86         136 my $thing = shift;
2139              
2140 86 100       236 if ( ref($thing) eq "SCALAR" )
2141             {
2142 3 50       7 if ( eval { require IO::Scalar; $IO::Scalar::VERSION >= 2.109; } )
  3         886  
  3         6879  
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 83 100       394 return $thing if defined( fileno $thing );
2156              
2157             # otherwise try qualifying it into caller's package
2158 70         299 my $fh = qualify_to_ref( $thing, caller(1) );
2159 70 50       1844 return $fh if defined( fileno $fh );
2160              
2161             # otherwise treat it as a file to open
2162 70         190 $fh = gensym;
2163 70 50       3062 open( $fh, $thing ) || return;
2164              
2165 70         325 return $fh;
2166             } # end _make_filehandle
2167              
2168             ############################################################
2169             #
2170             # INTERNAL PACKAGE: Config::IniFiles::_section
2171             #
2172             # Description:
2173             # This package is used to provide a single-level TIEHASH
2174             # interface to the sections in the IniFile. When tied, the
2175             # user wants to look at thinks like $ini{sec}{parm}, but the
2176             # TIEHASH only provides one level of hash interface, so the
2177             # root object gets asked for a $ini{sec} and must return a
2178             # has reference that accurately covers the '{parm}' part.
2179             #
2180             # This package is only used when tied and is inter-woven
2181             # between the sections and their parameters when the TIEHASH
2182             # method is called by Perl. It's a very simple implementation
2183             # of a tied hash object that simply maps onto the object API.
2184             #
2185             ############################################################
2186             # Date Modification Author
2187             # ----------------------------------------------------------
2188             # 2000.May.09 Created to excapsulate TIEHASH interface JW
2189             ############################################################
2190             package Config::IniFiles::_section;
2191              
2192 38     38   320 use strict;
  38         80  
  38         1010  
2193 38     38   232 use warnings;
  38         98  
  38         1362  
2194 38     38   240 use Carp;
  38         97  
  38         2397  
2195 38     38   260 use vars qw( $VERSION );
  38         86  
  38         18052  
2196              
2197             $Config::IniFiles::_section::VERSION = 2.16;
2198              
2199             # ----------------------------------------------------------
2200             # Sub: Config::IniFiles::_section::TIEHASH
2201             #
2202             # Args: $class, $config, $section
2203             # $class The class that this is being tied to.
2204             # $config The parent Config::IniFiles object
2205             # $section The section this tied object refers to
2206             #
2207             # Description: Builds the object that implements accesses to
2208             # the tied hash.
2209             # ----------------------------------------------------------
2210             # Date Modification Author
2211             # ----------------------------------------------------------
2212             # ----------------------------------------------------------
2213             sub TIEHASH
2214             {
2215 11     11   21 my $proto = shift;
2216 11   33     40 my $class = ref($proto) || $proto;
2217 11         25 my ( $config, $section ) = @_;
2218              
2219             # Make a new object
2220 11         45 return bless { config => $config, section => $section }, $class;
2221             } # end TIEHASH
2222              
2223             # ----------------------------------------------------------
2224             # Sub: Config::IniFiles::_section::FETCH
2225             #
2226             # Args: $key
2227             # $key The name of the key whose value to get
2228             #
2229             # Description: Returns the value associated with $key. If
2230             # the value is a list, returns a list reference.
2231             # ----------------------------------------------------------
2232             # Date Modification Author
2233             # ----------------------------------------------------------
2234             # 2000Jun15 Fixed bugs in -default handler JW
2235             # 2000Dec07 Fixed another bug in -deault handler JW
2236             # 2002Jul04 Returning scalar values (Bug:447532) AS
2237             # ----------------------------------------------------------
2238             sub FETCH
2239             {
2240 22     22   98 my ( $self, $key ) = @_;
2241 22         55 my @retval = $self->{config}->val( $self->{section}, $key );
2242 22 100       99 return ( @retval <= 1 ) ? $retval[0] : \@retval;
2243             } # end FETCH
2244              
2245             # ----------------------------------------------------------
2246             # Sub: Config::IniFiles::_section::STORE
2247             #
2248             # Args: $key, @val
2249             # $key The key under which to store the value
2250             # @val The value to store, either an array or a scalar
2251             #
2252             # Description: Sets the value for the specified $key
2253             # ----------------------------------------------------------
2254             # Date Modification Author
2255             # ----------------------------------------------------------
2256             # 2001Apr04 Fixed -nocase bug JW
2257             # ----------------------------------------------------------
2258             sub STORE
2259             {
2260 11     11   26 my ( $self, $key, @val ) = @_;
2261 11         40 return $self->{config}->newval( $self->{section}, $key, @val );
2262             } # end STORE
2263              
2264             # ----------------------------------------------------------
2265             # Sub: Config::IniFiles::_section::DELETE
2266             #
2267             # Args: $key
2268             # $key The key to remove from the hash
2269             #
2270             # Description: Removes the specified key from the hash and
2271             # returns its former value.
2272             # ----------------------------------------------------------
2273             # Date Modification Author
2274             # ----------------------------------------------------------
2275             # 2001Apr04 Fixed -nocase bug JW
2276             # ----------------------------------------------------------
2277             sub DELETE
2278             {
2279 1     1   3 my ( $self, $key ) = @_;
2280 1         4 my $retval = $self->{config}->val( $self->{section}, $key );
2281 1         4 $self->{config}->delval( $self->{section}, $key );
2282 1         2 return $retval;
2283             } # end DELETE
2284              
2285             # ----------------------------------------------------------
2286             # Sub: Config::IniFiles::_section::CLEAR
2287             #
2288             # Args: (None)
2289             #
2290             # Description: Empties the entire hash
2291             # ----------------------------------------------------------
2292             # Date Modification Author
2293             # ----------------------------------------------------------
2294             # ----------------------------------------------------------
2295             sub CLEAR
2296             {
2297 1     1   3 my ($self) = @_;
2298 1         3 return $self->{config}->DeleteSection( $self->{section} );
2299             } # end CLEAR
2300              
2301             # ----------------------------------------------------------
2302             # Sub: Config::IniFiles::_section::EXISTS
2303             #
2304             # Args: $key
2305             # $key The key to look for
2306             #
2307             # Description: Returns whether the key exists
2308             # ----------------------------------------------------------
2309             # Date Modification Author
2310             # ----------------------------------------------------------
2311             # 2001Apr04 Fixed -nocase bug JW
2312             # ----------------------------------------------------------
2313             sub EXISTS
2314             {
2315 0     0   0 my ( $self, $key ) = @_;
2316 0         0 return $self->{config}->exists( $self->{section}, $key );
2317             } # end EXISTS
2318              
2319             # ----------------------------------------------------------
2320             # Sub: Config::IniFiles::_section::FIRSTKEY
2321             #
2322             # Args: (None)
2323             #
2324             # Description: Returns the first key in the hash
2325             # ----------------------------------------------------------
2326             # Date Modification Author
2327             # ----------------------------------------------------------
2328             # ----------------------------------------------------------
2329             sub FIRSTKEY
2330             {
2331 4     4   23 my $self = shift;
2332              
2333 4         21 $self->{tied_enumerator} = 0;
2334 4         12 return $self->NEXTKEY();
2335             } # end FIRSTKEY
2336              
2337             # ----------------------------------------------------------
2338             # Sub: Config::IniFiles::_section::NEXTKEY
2339             #
2340             # Args: $last
2341             # $last The last key accessed by the iterator
2342             #
2343             # Description: Returns the next key in line
2344             # ----------------------------------------------------------
2345             # Date Modification Author
2346             # ----------------------------------------------------------
2347             # ----------------------------------------------------------
2348             sub NEXTKEY
2349             {
2350 13     13   18 my $self = shift;
2351 13         22 my ($last) = @_;
2352              
2353 13         20 my $i = $self->{tied_enumerator}++;
2354 13         26 my @keys = $self->{config}->Parameters( $self->{section} );
2355 13         22 my $key = $keys[$i];
2356 13 100       35 return if ( !defined $key );
2357 10 50       45 return wantarray ? ( $key, $self->FETCH($key) ) : $key;
2358             } # end NEXTKEY
2359              
2360             # ----------------------------------------------------------
2361             # Sub: Config::IniFiles::_section::DESTROY
2362             #
2363             # Args: (None)
2364             #
2365             # Description: Called on cleanup
2366             # ----------------------------------------------------------
2367             # Date Modification Author
2368             # ----------------------------------------------------------
2369             # ----------------------------------------------------------
2370             sub DESTROY
2371       0     {
2372             # my $self = shift
2373             } # end DESTROY
2374              
2375             1;
2376              
2377              
2378              
2379             1;
2380              
2381             # Please keep the following within the last four lines of the file
2382             #[JW for editor]:mode=perl:tabSize=8:indentSize=2:noTabs=true:indentOnEnter=true:
2383              
2384             __END__