File Coverage

blib/lib/Asterisk/config.pm
Criterion Covered Total %
statement 183 349 52.4
branch 71 184 38.5
condition 30 102 29.4
subroutine 15 30 50.0
pod 19 19 100.0
total 318 684 46.4


line stmt bran cond sub pod time code
1             package Asterisk::config;
2             #--------------------------------------------------------------
3             #
4             # Asterisk::config - asterisk config files read and write
5             #
6             # Copyright (C) 2005 - 2008, Sun bing.
7             #
8             # Sun bing
9             #
10             #
11             # LICENSE
12             # The Asterisk::config is licensed under the GNU 2.0 GPL.
13             # Asterisk::config carries no restrictions on re-branding
14             # and people are free to commercially re-distribute it.
15             #
16             #
17             #--------------------------------------------------------------
18             $Asterisk::config::VERSION='0.97';
19              
20 2     2   16912 use strict;
  2         5  
  2         76  
21 2     2   10 use Fcntl ':flock';
  2         4  
  2         9957  
22              
23             ##############################
24             # CLASS METHOD
25             sub new {
26 2     2 1 165 my $class = shift;
27 2         10 my %args = @_;
28 2         4 my (@resource_list,$resource_list,$parsed_conf,$parsed_section_chunk,$comment_flag);
29              
30             #try read
31 2 50       9 return(0) if (!defined $args{file});
32 2 50       43 return(0) if (!-e $args{file});
33 2 50       10 if (defined $args{'stream_data'}) {
34 0         0 @resource_list = split(/\n/,$args{'stream_data'});
35             } else {
36 2 50       67 open(DATA,"<$args{'file'}") or die "Asterisk-config Can't Open file : $!";
37 2         74 @resource_list = ;
38 2         21 close(DATA);
39             }
40 2         7 chomp(@resource_list);
41             #try parse
42 2         4 $comment_flag = '\;|\#';
43 2         14 ($parsed_conf,$parsed_section_chunk) = &_parse(\@resource_list,$comment_flag,$args{'section_chunk'});
44              
45             #try define default variable
46 2 50       11 $args{'keep_resource_array'} = 1 if (!defined $args{'keep_resource_array'});
47 2 50 33     27 if (defined $args{'keep_resource_array'} && $args{'keep_resource_array'}) {
48 2         4 $resource_list = \@resource_list;
49             }
50 2 50       9 if (!defined $args{'clean_when_reload'}) {
51 2         6 $args{'clean_when_reload'} = 1;
52             }
53 2 50       13 if (!defined $args{'reload_when_save'}) {
54 2         5 $args{'reload_when_save'} = 1;
55             }
56              
57 2         20 my $self = {
58             #user input
59             file=> $args{'file'},
60             keep_resource_array=> $args{'keep_resource_array'},
61             clean_when_reload=> $args{'clean_when_reload'},
62             reload_when_save=> $args{'reload_when_save'},
63              
64             #internal
65             commit_list => [],
66             parsed_conf=> $parsed_conf,
67             parsed_section_chunk=> $parsed_section_chunk,
68             resource_list=> $resource_list,
69             comment_flag=> $comment_flag,
70             };
71 2         7 bless $self,$class;
72 2         10 return $self;
73             }
74              
75             ##############################
76             # INTERNAL SUBROUTE _parse
77             # parse conf
78             sub _parse {
79 4     4   7 my $resource_list = $_[0];
80 4         6 my $comment_flag = $_[1];
81 4         9 my $section_chunk = $_[2];
82              
83 4         6 my (%DATA,$last_section_name,%DATA_CHUNK);
84 4 50       9 $DATA{'[unsection]'}={}; $DATA_CHUNK{'[unsection]'}={} if ($section_chunk);
  4         14  
85 4         10 foreach my $one_line (@$resource_list) {
86 45         76 my $line_sp=&_clean_string($one_line,$comment_flag);
87              
88             #format : Find New Section ???
89 45 100       138 if ($line_sp =~ /^\[(.+)\]/) {
    50          
90 8         23 $DATA{$1}={}; $last_section_name = $1;
  8         15  
91 8 50       41 $DATA_CHUNK{$1}=[] if ($section_chunk);
92 8         14 next;
93              
94             #save source chunk to data_chunk
95             } elsif ($section_chunk) {
96 0 0       0 next if ($one_line eq '');
97 0         0 my $section_name = $last_section_name;
98 0 0       0 $section_name = '[unsection]' if (!$section_name);
99             #copying source chunk to data_chunk
100 0         0 push(@{$DATA_CHUNK{$section_name}},$one_line);
  0         0  
101             }
102              
103 37 100       74 next if ($line_sp eq '');#next if just comment
104              
105             #fromat : Include "#" ???
106 31 100       58 if ($line_sp =~ /^\#/) {
107 2         3 my $section_name = $last_section_name;
108 2 50       5 $section_name = '[unsection]' if (!$section_name);
109 2 50       9 $DATA{$section_name}{$line_sp}=[] if (!$DATA{$section_name}{$line_sp});
110 2         2 push(@{$DATA{$section_name}{$line_sp}},$line_sp);
  2         4  
111 2         4 next;
112             }
113              
114             #format : Key=Value ???
115 29 50       78 if ($line_sp =~ /\=/) {
116             #split data and key
117 29         56 my ($key,$value)=&_clean_keyvalue($line_sp);
118              
119 29         40 my $section_name = $last_section_name;
120 29 100       55 $section_name = '[unsection]' if (!$section_name);
121 29 100       103 $DATA{$section_name}{$key}=[] if (!$DATA{$section_name}{$key});
122 29         36 push(@{$DATA{$section_name}{$key}},$value);
  29         69  
123 29         58 next;
124             }
125             }
126              
127 4         14 return(\%DATA,\%DATA_CHUNK);
128             }
129              
130             ##############################
131             # INTERNAL SUBROUTE _clean_string
132             # clean strings
133             sub _clean_string {
134 51     51   69 my $string = shift;
135 51         52 my $comment_flag = shift;
136 51 100       107 return '' unless $string;
137 45 100       119 if ($string !~ /^\#/) {
138 43         267 ($string,undef)=split(/$comment_flag/,$string);
139             }
140 45         98 $string =~ s/^\s+//;
141 45         78 $string =~ s/\s+$//;
142 45         93 return($string);
143             }
144              
145             ##############################
146             # INTERNAL SUBROUTE _clean_string
147             # split key value of data
148             sub _clean_keyvalue {
149 29     29   32 my $string = shift;
150 29         110 my ($key,$value)=split(/\=(.*)/,$string);
151 29         595 $key =~ s/^(\s+)//; $key =~ s/(\s+)$//;
  29         67  
152 29 50       53 if ($value) {
153 29         41 $value=~ s/^\>//g; $value =~ s/^(\s+)//; $value =~ s/(\s+)$//;
  29         53  
  29         44  
154             }
155              
156 29         70 return($key,$value);
157             }
158              
159             ##############################
160             # READ METHOD
161             sub get_objvar
162             {
163 0     0 1 0 my $self = shift;
164 0         0 my $varname = shift;
165 0 0       0 if (defined $self->{$varname}) {
166 0         0 return($self->{$varname});
167             } else {
168 0         0 return(0);
169             }
170             }
171              
172             sub fetch_sections_list
173             {
174 0     0 1 0 my $self = shift;
175 0         0 my @sections_list = grep(!/^\[unsection\]/, keys %{$self->{parsed_conf}});
  0         0  
176 0         0 return(\@sections_list);
177             }
178              
179             sub fetch_sections_hashref
180             {
181 0     0 1 0 my $self = shift;
182 0         0 return($self->{parsed_conf});
183             }
184              
185             sub fetch_keys_list
186             {
187 0     0 1 0 my $self = shift;
188 0         0 my %args = @_;
189 0 0       0 return(0) if (!defined $args{section});
190 0 0       0 return(0) if (!defined $self->{parsed_conf}{$args{section}});
191              
192 0         0 my @keys_list = grep(!/^\[unsection\]/, keys %{$self->{parsed_conf}{$args{section}}});
  0         0  
193 0         0 return(\@keys_list);
194             }
195              
196             sub fetch_keys_hashref
197             {
198 0     0 1 0 my $self = shift;
199 0         0 my %args = @_;
200 0 0       0 return(0) if (!defined $args{section});
201 0 0       0 return(0) if (!defined $self->{parsed_conf}{$args{section}});
202              
203 0         0 return($self->{parsed_conf}{$args{section}});
204             }
205              
206             sub fetch_values_arrayref
207             {
208 8     8 1 20 my $self = shift;
209 8         33 my %args = @_;
210 8 50       26 return(0) if (!defined $args{section});
211 8 50       33 return(0) if (!defined $self->{parsed_conf}{$args{section}});
212 8 50       20 return(0) if (!defined $args{key});
213 8 50       28 return(0) if (!defined $self->{parsed_conf}{$args{section}}{$args{key}});
214              
215 8         59 return($self->{parsed_conf}{$args{section}}{$args{key}});
216             }
217              
218             sub reload
219             {
220 2     2 1 6 my $self = shift;
221              
222             #try read
223 2 50       8 return(0) if (!defined $self->{file});
224 2 50       30 return(0) if (!-e $self->{file});
225 2 50       57 open(DATA,"<$self->{'file'}") or die "Asterisk-config Can't Open file : $!";
226 2         52 my @resource_list = ;
227 2         20 close(DATA);
228 2         5 chomp(@resource_list);
229              
230             # save to parsed_conf
231 2         8 my ($parsed_conf,$conf_chunk_ignored) = &_parse(\@resource_list,$self->{comment_flag});
232 2         5 $self->{parsed_conf} = $parsed_conf;
233              
234             # save to resource_list
235 2         7 my $resource_list;
236 2 50 33     17 if (defined $self->{'keep_resource_array'} && $self->{'keep_resource_array'}) {
237 2         4 $resource_list = \@resource_list;
238             }
239 2         3 $self->{resource_list} = $resource_list;
240              
241             # save to commit_list / do clean_when_reload ?
242 2 50 33     17 if (defined $self->{'clean_when_reload'} && $self->{'clean_when_reload'}) {
243 2         6 &clean_assign($self);
244             }
245              
246              
247 2         5 return(1);
248             }
249              
250             ##############################
251             # WRITE METHOD
252              
253             sub clean_assign
254             {
255 2     2 1 3 my $self = shift;
256             # undef($self->{commit_list});
257 2         4 $self->{commit_list}=[];
258 2         10 return(1);
259             }
260              
261             sub set_objvar
262             {
263 0     0 1 0 my $self = shift;
264 0         0 my $key = shift;
265 0         0 my $value = shift;
266              
267 0 0       0 return(0) if (!defined $value);
268 0 0       0 return(0) if (!exists $self->{$key});
269 0         0 $self->{$key} = $value;
270              
271 0         0 return(1);
272             }
273              
274             #-----------------------------------------------------------
275             # assign method to commit_list
276             sub assign_cleanfile
277             {
278 0     0 1 0 my $self = shift;
279 0         0 my %hash = @_;
280 0         0 $hash{'action'}='cleanfile';
281 0         0 push(@{$self->{commit_list}},\%hash);
  0         0  
282             }
283              
284             sub assign_matchreplace
285             {
286 0     0 1 0 my $self = shift;
287 0         0 my %hash = @_;
288 0         0 $hash{'action'}='matchreplace';
289 0         0 push(@{$self->{commit_list}},\%hash);
  0         0  
290             }
291              
292             sub assign_append
293             {
294 4     4 1 25 my $self = shift;
295 4         17 my %hash = @_;
296 4         5 $hash{'action'}='append';
297 4         4 push(@{$self->{commit_list}},\%hash);
  4         31  
298             }
299              
300             sub assign_replacesection
301             {
302 0     0 1 0 my $self = shift;
303 0         0 my %hash = @_;
304 0         0 $hash{'action'}='replacesection';
305 0         0 push(@{$self->{commit_list}},\%hash);
  0         0  
306             }
307              
308             sub assign_delsection
309             {
310 0     0 1 0 my $self = shift;
311 0         0 my %hash = @_;
312 0         0 $hash{'action'}='delsection';
313 0         0 push(@{$self->{commit_list}},\%hash);
  0         0  
314             }
315              
316             sub assign_addsection
317             {
318 2     2 1 10 my $self = shift;
319 2         6 my %hash = @_;
320 2         4 $hash{action} = 'addsection';
321 2         2 push(@{$self->{commit_list}}, \%hash);
  2         12  
322             }
323              
324             sub assign_editkey
325             {
326 0     0 1 0 my $self = shift;
327 0         0 my %hash = @_;
328 0         0 $hash{'action'}='editkey';
329 0         0 push(@{$self->{commit_list}},\%hash);
  0         0  
330             }
331              
332             sub assign_delkey
333             {
334 0     0 1 0 my $self = shift;
335 0         0 my %hash = @_;
336 0         0 $hash{'action'}='delkey';
337 0         0 push(@{$self->{commit_list}},\%hash);
  0         0  
338             }
339              
340             #-----------------------------------------------------------
341             # save method and save internal method
342             # filename: run assign rules and save to file
343             # save_file();
344             sub save_file
345             {
346 1     1 1 5 my $self = shift;
347 1         3 my %opts = @_;
348              
349 1 50       1 return if ($#{$self->{commit_list}} < 0);
  1         5  
350              
351 1         2 my $used_resource;
352             #check to use resource_list?
353 1 50 33     8 if (defined $self->{'keep_resource_array'} && $self->{'keep_resource_array'}) {
354             # $used_resource = $self->{resource_list};
355 1         2 $used_resource = [ @{ $self->{resource_list} } ];
  1         3  
356             }
357              
358 1 50       4 if (!defined $used_resource) {
359 0 0       0 open(DATA,"<$self->{'file'}") or die "Asterisk-config can't read from $self->{file} : $!";
360 0         0 my @DATA = ;
361 0         0 close(DATA);
362 0         0 chomp(@DATA);
363 0         0 $used_resource = \@DATA;
364             }
365              
366 1         2 foreach my $one_case (@{$self->{commit_list}}) {
  1         3  
367 6 50 33     32 $used_resource = &_do_editkey($one_case,$used_resource,$self) if ($one_case->{'action'} eq 'editkey' || $one_case->{'action'} eq 'delkey');
368 6 50 33     26 $used_resource = &_do_delsection($one_case,$used_resource,$self) if ($one_case->{'action'} eq 'delsection' || $one_case->{'action'} eq 'replacesection');
369 6 100       17 $used_resource = &_do_addsection($one_case,$used_resource,$self) if ($one_case->{'action'} eq 'addsection');
370 6 100       25 $used_resource = &_do_append($one_case,$used_resource,$self) if ($one_case->{'action'} eq 'append');
371 6 50       15 $used_resource = &_do_matchreplace($one_case,$used_resource,$self) if ($one_case->{'action'} eq 'matchreplace');
372 6 50       15 if ($one_case->{'action'} eq 'cleanfile') {
373 0         0 undef($used_resource);
374 0         0 last;
375             }
376             }
377              
378              
379             #save file and check new_file
380 1 50 33     5 if (defined $opts{'new_file'} && $opts{'new_file'} ne '') {
381 0 0       0 open(SAVE,">$opts{'new_file'}") or die "Asterisk-config Save_file can't write : $!";
382             } else {
383 1 50       60 open(SAVE,">$self->{'file'}") or die "Asterisk-config Save_file can't write : $!";
384             }
385 1         14 flock(SAVE,LOCK_EX);
386 1         2 print SAVE grep{$_.="\n"} @{$used_resource};
  8         34  
  1         3  
387 1         44 flock(SAVE,LOCK_UN);
388 1         11 close(SAVE);
389              
390             #reload when save
391 1 50 33     10 if (defined $self->{'reload_when_save'} && $self->{'reload_when_save'}) {
392 1         4 &reload($self);
393             }
394              
395 1         5 return();
396             }
397              
398             sub _do_editkey
399             {
400 0     0   0 my $one_case = shift;
401 0         0 my $data = shift;
402 0         0 my $class_self = shift;
403              
404 0         0 my @NEW;
405 0         0 my $last_section_name='[unsection]';
406 0         0 my $auto_save=0;
407              
408 0         0 foreach my $one_line (@$data) {
409              
410             #tune on auto save
411 0 0       0 if ($auto_save) { push(@NEW,$one_line); next; }
  0         0  
  0         0  
412              
413 0         0 my $line_sp=&_clean_string($one_line,$class_self->{comment_flag});
414              
415             #income new section
416 0 0 0     0 if ($line_sp =~ /^\[(.+)\]/) {
    0          
417 0         0 $last_section_name = $1;
418             } elsif ($last_section_name eq $one_case->{section} && $line_sp =~ /\=/) {
419              
420             #split data and key
421 0         0 my ($key,$value)=&_clean_keyvalue($line_sp);
422              
423 0 0 0     0 if ($key eq $one_case->{'key'} && $one_case->{'value_regexp'} && !$one_case->{'value'}) {
    0 0        
    0 0        
      0        
424 0         0 $value =~ /(.+?)\,/;
425 0 0 0     0 if ($one_case->{'action'} eq 'delkey' && $1 eq $one_case->{'value_regexp'}){ undef($one_line); }
  0         0  
426              
427             } elsif ($key eq $one_case->{'key'} && !$one_case->{'value'}) { #处理全部匹配的key的value值
428 0 0       0 if ($one_case->{'action'} eq 'delkey') { undef($one_line); }
  0         0  
429 0         0 else { $one_line = "$key=".$one_case->{'new_value'}; }
430             # $one_line = "$key=".$one_case->{'new_value'};
431             # undef($one_line) if ($one_case->{'action'} eq 'delkey');
432             } elsif ($key eq $one_case->{'key'} && $one_case->{'value'} eq $value) { #处理唯一匹配的key的value值
433 0 0       0 if ($one_case->{'action'} eq 'delkey') { undef($one_line); }
  0         0  
434 0         0 else { $one_line = "$key=".$one_case->{'new_value'}; }
435             # $one_line = "$key=".$one_case->{'new_value'};
436             # undef($one_line) if ($one_case->{'action'} eq 'delkey');
437 0         0 $auto_save = 1;
438             }
439             }
440              
441 0 0       0 push(@NEW,$one_line) if (defined $one_line);
442             }
443              
444 0         0 return(\@NEW);
445             }
446              
447             sub _do_delsection
448             {
449 0     0   0 my $one_case = shift;
450 0         0 my $data = shift;
451 0         0 my $class_self = shift;
452              
453 0         0 my @NEW;
454 0         0 my $last_section_name='[unsection]';
455 0         0 my $auto_save=0;
456              
457 0 0 0     0 push(@NEW,&_format_convert($one_case->{'data'}))
458             if ($one_case->{'section'} eq '[unsection]' and $one_case->{'action'} eq 'replacesection');
459              
460 0         0 foreach my $one_line (@$data) {
461              
462             #tune on auto save
463 0 0       0 if ($auto_save) { push(@NEW,$one_line); next; }
  0         0  
  0         0  
464              
465 0         0 my $line_sp=&_clean_string($one_line,$class_self->{comment_flag});
466              
467 0 0 0     0 if ($last_section_name eq $one_case->{'section'} && $line_sp =~ /^\[(.+)\]/) {
    0          
    0          
468             #when end of compared section and come new different section
469 0         0 $auto_save = 1;
470             } elsif ($last_section_name eq $one_case->{'section'}) {
471 0         0 next;
472             } elsif ($line_sp =~ /^\[(.+)\]/) {
473             #is this new section?
474 0 0       0 if ($one_case->{'section'} eq $1) {
475 0         0 $last_section_name = $1;
476 0 0       0 next if ($one_case->{'action'} eq 'delsection');
477 0         0 push(@NEW,$one_line);
478 0         0 $one_line=&_format_convert($one_case->{'data'});
479             }
480             }
481              
482 0         0 push(@NEW,$one_line);
483             }
484              
485 0         0 return(\@NEW);
486             }
487              
488             sub _do_addsection
489             {
490 2     2   3 my $one_case = shift;
491 2         3 my $data = shift;
492 2         11 my $class_self = shift;
493              
494 2         3 my $exists = 0;
495 2         5 my $section = '[' . $one_case->{section} . ']';
496            
497 2         14 foreach my $one_line(@$data) {
498              
499 2         5 my $line_sp=&_clean_string($one_line,$class_self->{comment_flag});
500 2 100       16 if($line_sp =~ /^\[.+\]/) {
501              
502 1 50       4 if ($section eq $line_sp) {
503 0         0 $exists = 1;
504 0         0 last;
505             }
506             }
507             }
508 2 50       6 unless($exists) {
509              
510 2         4 push(@$data, $section);
511             }
512              
513 2         19 return $data;
514             }
515              
516             sub _do_append
517             {
518 4     4   5 my $one_case = shift;
519 4         5 my $data = shift;
520 4         6 my $class_self = shift;
521 4         4 my @NEW;
522              
523 4 100 66     25 if ((not exists $one_case->{'section'}) || ($one_case->{'section'} eq '')) {
    50 33        
524             #Append data head of source data/foot of source data
525 2 50       5 if ($one_case->{'point'} eq 'up') {
526 2         14 push(@NEW,&_format_convert($one_case->{'data'}),@$data);
527             } else {
528 0         0 push(@NEW,@$data,&_format_convert($one_case->{'data'}));
529             }
530              
531             } elsif (!defined $one_case->{'comkey'} || $one_case->{'comkey'} eq '') {
532             #Append data head/foot of section_name
533 2         3 my $auto_save=0;
534 2         3 my $save_tmpmem=0;
535 2         3 my $offset=0;
536 2         4 foreach my $one_line (@$data) {
537             #tune on auto save
538 4 50       8 if ($auto_save) { push(@NEW,$one_line); $offset++; next; }
  0         0  
  0         0  
  0         0  
539             #check section
540 4         13 my $line_sp=&_clean_string($one_line,$class_self->{comment_flag});
541 4         40 my ($section_name) = $line_sp =~ /^\[(.+)\]/;
542              
543             # for up / down
544 4 50 100     79 if (defined $section_name && $one_case->{'section'} eq $section_name && $one_case->{'point'} eq 'up') {
    50 66        
    100 100        
    50 66        
      100        
      66        
      33        
      33        
545 0         0 push(@NEW,&_format_convert($one_case->{'data'})); $auto_save=1;
  0         0  
546             } elsif (defined $section_name && $one_case->{'section'} eq $section_name && $one_case->{'point'} eq 'down') {
547 0         0 push(@NEW,$one_line); $one_line = join "\n", &_format_convert($one_case->{'data'}); $auto_save=1;
  0         0  
  0         0  
548             # for foot matched section
549             } elsif (defined $section_name && $one_case->{'section'} eq $section_name && $one_case->{'point'} eq 'foot') {
550 2         5 $save_tmpmem=1;
551             # for foot 发现要从匹配的section换成新section
552             } elsif ($save_tmpmem == 1 && $section_name && $one_case->{'section'} ne $section_name) {
553 0         0 push(@NEW,&_format_convert($one_case->{'data'})); $auto_save=1; $save_tmpmem=0;
  0         0  
  0         0  
554             # for foot 发现匹配的section已经到达整个结尾
555             }
556 4 100 66     10 if ($save_tmpmem == 1 && $offset==$#{$data}) {
  2         8  
557 2         3 push(@NEW,$one_line); $one_line = join "\n", &_format_convert($one_case->{'data'});
  2         7  
558 2         9 $auto_save=1; $save_tmpmem=0;
  2         3  
559             }
560              
561 4         5 push(@NEW,$one_line);
562 4         11 $offset++;
563             }
564              
565             } else {
566              
567 0         0 my $last_section_name='[unsection]';
568 0         0 my $auto_save=0;
569 0         0 foreach my $one_line (@$data) {
570              
571             #tune on auto save
572 0 0       0 if ($auto_save) { push(@NEW,$one_line); next; }
  0         0  
  0         0  
573              
574 0         0 my $line_sp=&_clean_string($one_line,$class_self->{comment_flag});
575             #income new section
576 0 0 0     0 if ($line_sp =~ /^\[(.+)\]/) {
    0          
577 0         0 $last_section_name = $1;
578             } elsif ($last_section_name eq $one_case->{'section'} && $line_sp =~ /\=/) {
579             #split data and key
580 0         0 my ($key,$value)=&_clean_keyvalue($line_sp);
581 0 0 0     0 if ($key eq $one_case->{comkey}[0] && $value eq $one_case->{comkey}[1] && $one_case->{'point'} eq 'up') {
    0 0        
    0 0        
      0        
      0        
      0        
582 0         0 push(@NEW,&_format_convert($one_case->{'data'})); $auto_save=1;
  0         0  
583             } elsif ($key eq $one_case->{comkey}[0] && $value eq $one_case->{comkey}[1] && $one_case->{'point'} eq 'down') {
584 0         0 push(@NEW,$one_line); $one_line=&_format_convert($one_case->{'data'});
  0         0  
585 0         0 $auto_save=1;
586             } elsif ($key eq $one_case->{comkey}[0] && $value eq $one_case->{comkey}[1] && $one_case->{'point'} eq 'over') {
587 0         0 $one_line=&_format_convert($one_case->{'data'}); $auto_save=1;
  0         0  
588             }
589             }
590 0         0 push(@NEW,$one_line);
591             }
592              
593             }
594              
595 4         9 return(\@NEW);
596             }
597              
598             # income scalar,array ref,hash ref output array data
599             sub _format_convert
600             {
601 4     4   6 my $string = shift;
602 4 100       13 if (ref($string) eq 'ARRAY') {
    50          
603 2         15 return(@$string);
604             } elsif (ref($string) eq 'HASH') {
605 2         2 my @tmp;
606 2         8 foreach (keys(%$string)) {
607 4         12 push(@tmp,"$_=".$string->{$_});
608             }
609 2         9 return(@tmp);
610             } else {
611 0           return($string);
612             }
613             }
614              
615             sub _do_matchreplace
616             {
617 0     0     my $one_case = shift;
618 0           my $data = shift;
619 0           my $class_self = shift;
620 0           my @NEW;
621              
622 0           foreach my $one_line (@$data) {
623 0 0         if ($one_line =~ /$one_case->{'match'}/) {
624 0           $one_line = $one_case->{'replace'};
625             }
626 0           push(@NEW,$one_line);
627             }
628              
629 0           return(\@NEW);
630             }
631              
632             =head1 NAME
633              
634             Asterisk::config - the Asterisk config read and write module.
635              
636             =head1 SYNOPSIS
637              
638             use Asterisk::config;
639              
640             my $sip_conf = new Asterisk::config(file=>'/etc/asterisk/sip.conf');
641             my $conference = new Asterisk::config(file=>'/etc/asterisk/meetme.conf',
642             keep_resource_array=>0);
643              
644             $allow = $sip_conf->fetch_values_arrayref(section=>'general',key=>'allow');
645             print $allow->[0];
646              
647             $sip_conf->assign_append(point=>'down',data=>"[userb]\ntype=friend\n");
648              
649             $sip_conf->save();
650              
651              
652             =head1 DESCRIPTION
653              
654             Asterisk::config can parse and saving data with Asterisk config
655             files. this module support asterisk 1.0 1.2 1.4 1.6, and it also
656             support Zaptel config files.
657              
658             =head1 Note
659              
660             Version 0.9 syntax incompitable with 0.8.
661              
662             =head1 CLASS METHOD
663              
664             =head2 new
665              
666             $sip_conf = new Asterisk::config(file=>'file name',
667             [stream_data=>$string],
668             [object variable]);
669              
670             Instantiates a new object of file. Reads data from stream_data or
671             file.
672              
673              
674             =head1 OBJECT VARIABLES
675              
676             FIXME: should all of those be documented in the POD (rather than
677             in comments in the code?)
678              
679             =head2 file
680              
681             Config file name and path. Must be set.
682             If file does exists (exp. data from C), you will not
683             be able to save using L.
684              
685             =head2 keep_resource_array
686              
687             use resource array when save make fast than open file, but need
688             more memory, default enabled. use set_objvar to change it.
689              
690             =head2 reload_when_save
691              
692             When save done, auto call .
693              
694             Enabled by default. Use set_variable to change it.
695              
696             FIXME: what is C?
697              
698             =head2 clean_when_reload
699              
700             When reload done, auto clean_assign with current object.
701              
702             Enabled by default. Use L to change it.
703              
704             =head2 commit_list
705              
706             Internal variable listed all command.
707              
708             =head2 parsed_conf
709              
710             Internal variable of parsed.
711              
712              
713             =head1 OBJECT READ METHOD
714              
715             =head2 get_objvar
716              
717             $sip_conf->get_objvar(var_name);
718              
719             Return defined object variables.
720              
721             =head2 fetch_sections_list
722              
723             $sip_conf->fetch_sections_list();
724              
725             List of sections (not including C) in a file.
726              
727             =head2 fetch_sections_hashref
728              
729             $sip_conf->fetch_sections_hashref();
730              
731             Returns the config file parsed as a hash (section name -> section)
732             of lists (list of lines).
733              
734             =head2 fetch_keys_list
735              
736             $sip_conf->fetch_keys_list(section=>[section name|unsection]);
737              
738             Returns list of the kes in the keys in I
(or
739             I).
740              
741             =head2 fetch_keys_hashref
742              
743             $sip_conf->fetch_keys_hashref(section=>[section name|unsection]);
744              
745             Returns the section as a hash of key=>value pairs.
746              
747             =head2 fetch_values_arrayref
748              
749             $sip_conf->fetch_values_arrayref(section=>[section name|unsection],
750             key=>key name);
751              
752             Returns a (reference to a) list of all the values a specific keys have
753             in a specific section. referenced value list, Returns 0 if section
754             was not found or key was not found in the section.
755              
756             =head2 reload
757              
758             $sip_conf->reload();
759              
760             Reloads and parses the config file.
761              
762             If L is true, will also do L.
763              
764             =head1 OBJECT WRITE METHOD
765              
766             =head2 set_objvar
767              
768             $sip_conf->set_objvar('var_name'=>'value');
769              
770             Set the object variables to new value.
771              
772             =head2 assign_cleanfile
773              
774             $sip_conf->assign_cleanfile();
775              
776             Resets all the non-saved changes (from other assign_* functions).
777              
778             =head2 assign_matchreplace
779              
780             $sip_conf->assign_matchreplace(match=>[string],replace=>[string]);
781              
782             replace new data when matched.
783              
784             =over 2
785              
786             =item * match -> string of matched data.
787              
788             =item * replace -> new data string.
789              
790             =back
791              
792             =head2 assign_append
793              
794             Used to add extra data to an existing section or to edit it.
795              
796             $sip_conf->assign_append(point=>['up'|'down'|'foot'],
797             section=>[section name],
798             data=>'key=value'|['key=value','key=value']|{key=>'value',key=>'value'});
799              
800             This form is used to merely append new data.
801              
802             =over 3
803              
804             =item point
805              
806             Append data C / C / C with section.
807              
808             =item section
809              
810             Matched section name, expect 'unsection'. If ommited, data will be
811             placed above first setcion, as in 'unsection', but then you cannot
812             use C"foot">.
813              
814             =item data
815              
816             New replace data in string/array/hash.
817              
818             =back
819              
820             $sip_conf->assign_append(point=>['up'|'down'|'over'],
821             section=>[section name],
822             comkey=>[key,value],
823             data=>'key=value'|['key=value','key=value']|{key=>'value',key=>'value'};
824              
825             Appends data before, after or instead a given line. The line is
826             the first line in C
where the key is C and the value
827             is C (from C.
828              
829             =over 2
830              
831             =item point
832              
833             C will overwrite with key/value matched.
834              
835             =item comkey
836              
837             Match key and value.
838              
839             =back
840              
841             =head2 assign_replacesection
842              
843             $sip_conf->assign_replacesection(section=>[section name|unsection],
844             data=>'key=value'|['key=value','key=value']|{key=>'value',key=>'value'});
845              
846             replace the section body data.
847              
848             =over 1
849              
850             =item * section -> all section name and 'unsection'.
851              
852             =back
853              
854             =head2 assign_delsection
855              
856             $sip_conf->assign_delsection(section=>[section name|unsection]);
857              
858             erase section name and section data.
859              
860             =over 1
861              
862             =item * section -> all section and 'unsection'.
863              
864             =back
865              
866             =head2 assign_addsection
867              
868             $sip_conf->assign_addsection(section=>[section]);
869              
870             add section with name.
871              
872             =over 1
873              
874             =item * section -> name of new section.
875              
876             =back
877              
878             =head2 assign_editkey
879              
880             $sip_conf->assign_editkey(section=>[section name|unsection],key=>[keyname],value=>[value],new_value=>[new_value]);
881              
882             modify value with matched section.if don't assign value=> will replace all matched key.
883              
884             warnning example script:
885              
886             $sip_conf->assign_editkey(section=>'990001',key=>'all',new_value=>'gsm');
887              
888             data:
889              
890             all=g711
891             all=ilbc
892              
893             will convert to:
894              
895             all=gsm
896             all=gsm
897              
898              
899             =head2 assign_delkey
900              
901             $sip_conf->assign_delkey(section=>[section name|unsection],key=>[keyname],value=>[value]);
902              
903             erase all matched C in section or in 'unsection'.
904              
905             $sip_conf->assign_delkey(section=>[section name|unsection],key=>[keyname],value_regexp=>[exten_number]);
906              
907             erase when matched exten number.
908              
909             exten => 100,n,...
910             exten => 102,n,...
911              
912             =head2 save_file
913              
914             $sip_conf->save_file([new_file=>'filename']);
915              
916             process commit list and save to file.
917             if reload_when_save true will do reload.
918             if no object variable file or file not exists or can't be
919             save return failed.
920             if defined new_file will save to new file, default overwrite
921             objvar 'file'.
922              
923             =head2 clean_assign
924              
925             $sip_conf->clean_assign();
926              
927             clean all assign rules.
928              
929             =head1 EXAMPLES
930              
931             see example in source tree.
932              
933             =head1 AUTHORS
934              
935             Asterisk::config by Sun bing
936              
937             Version 0.7 patch by Liu Hailong.
938              
939             =head1 COPYRIGHT
940              
941             The Asterisk::config module is Copyright (c) Sun bing
942             All rights reserved.
943              
944             You may distribute under the terms of either the GNU General Public
945             License or the Artistic License, as specified in the Perl README file.
946              
947             =head1 WARRANTY
948              
949             The Asterisk::config is free Open Source software.
950              
951             IT COMES WITHOUT WARRANTY OF ANY KIND.
952              
953             =head1 SUPPORT
954              
955             Sun bing
956              
957             The Asterisk::config be Part of FreeIris opensource Telephony Project
958             Access http://www.freeiris.org for more details.
959              
960             =cut
961              
962             1;