2 # Functions for reading and writing the squid config file
5 # Parses squid.conf into an array of data structures
9 if (!@get_config_cache) {
10 open(CONF, $config{'squid_conf'});
13 s/\r|\n//g; # strip newlines and comments
14 if (/^\s*(\#?\s*|\#\s+TAG:\s+)(\S+)\s*(.*)$/) {
18 $dir{'enabled'} = !$1;
21 while($str =~ /^\s*("[^"]*")(.*)$/ ||
22 $str =~ /^\s*(\S+)(.*)$/) {
25 if ($v !~ /^"/ && $v =~ /^(.*)#/ &&
27 # A comment .. end of values
29 $dir{'postcomment'} = $str;
33 push(@{$dir{'values'}}, $v);
36 $dir{'index'} = scalar(@get_config_cache);
37 if ($dir{'comment'} =~ /TAG/) {
40 push(@get_config_cache, \%dir);
46 return \@get_config_cache;
49 # find_config(name, &config, [disabled-mode])
50 # Returns the structure(s) with some name
51 # disabled mode 0 = only enabled, 1 = both, 2 = only disabled,
52 # 3 = disabled and tags
56 foreach $c (@{$_[1]}) {
57 if ($c->{'name'} eq $_[0]) {
62 @rv = grep { $_->{'enabled'} && !$_->{'tag'} } @rv;
65 @rv = grep { !$_->{'tag'} } @rv;
68 @rv = grep { !$_->{'enabled'} && !$_->{'tag'} } @rv;
71 @rv = grep { !$_->{'enabled'} } @rv;
73 return @rv ? wantarray ? @rv : $rv[0]
74 : wantarray ? () : undef;
77 # find_value(name, &config, [disabled-mode])
78 # Returns the value of some directive
81 local $rv = &find_config(@_);
82 return $rv ? $rv->{'value'} : undef;
85 # find_values(name, &config, [disabled-mode])
86 # Returns the value of some directive
89 local $rv = &find_config(@_);
90 return $rv ? $rv->{'values'} : undef;
93 # save_value(&config, name, value*)
96 local @v = map { { 'name' => $_[1],
97 'values' => [ $_ ] } } @_[2..@_-1];
98 &save_directive($_[0], $_[1], \@v);
101 # save_directive(&config, name, &values, [after])
102 # Given a structure containing a directive name, type, values and members
103 # add, update or remove that directive in config structure and data files.
106 local(@oldv, @newv, $i, $o, $n, $lref, $nl, $change);
107 @oldv = &find_config($_[1], $_[0]);
108 @newv = map { local %n = %$_; \%n } @{$_[2]};
109 $lref = &read_file_lines($config{'squid_conf'});
110 for($i=0; $i<@oldv || $i<@newv; $i++) {
112 # a new directive is being added..
113 $nl = &directive_line($newv[$i]);
114 local @after = ref($_[3]) ? ( $_[3] ) :
115 $_[3] ? &find_config($_[3], $_[0]) : ( );
116 local $after = @after ? @after[$#after] : undef;
117 local @comment = &find_config($_[1], $_[0], 3);
118 local $comment = @comment ? $comment[$#comment] : undef;
120 (!$after || $after->{'line'} < $change->{'line'})) {
121 # put it after any directives of the same type
122 $newv[$i]->{'line'} = $change->{'line'}+1;
123 splice(@$lref, $newv[$i]->{'line'}, 0, $nl);
124 &renumber($_[0], $change->{'line'}, 1);
125 splice(@{$_[0]}, &indexof($change, @{$_[0]}),
130 # put it after commented line
131 $newv[$i]->{'line'} = $comment->{'line'}+1;
132 splice(@$lref, $newv[$i]->{'line'}, 0, $nl);
133 &renumber($_[0], $comment->{'line'}, 1);
134 splice(@{$_[0]}, &indexof($comment, @{$_[0]}),
138 # put it at the end of the file
139 $newv[$i]->{'line'} = scalar(@$lref);
141 push(@{$_[0]}, $newv[$i]);
144 elsif ($i >= @newv) {
145 # a directive was deleted
146 splice(@$lref, $oldv[$i]->{'line'}, 1);
147 &renumber($_[0], $oldv[$i]->{'line'}, -1);
148 splice(@{$_[0]}, &indexof($oldv[$i], @{$_[0]}), 1);
151 # updating some directive
152 $newv[$i]->{'postcomment'} = $oldv[$i]->{'postcomment'};
153 $nl = &directive_line($newv[$i]);
154 local @after = $change && $_[3] ? ( $change ) :
155 # After last one updated
156 ref($_[3]) ? ( $_[3] ) : # After specific
157 $_[3] ? &find_config($_[3], $_[0]) : ( );
158 local $after = @after ? @after[$#after] : undef;
159 if ($after && $oldv[$i]->{'line'} < $after->{'line'}) {
160 # Need to move it after some directive
161 splice(@$lref, $oldv[$i]->{'line'}, 1);
162 splice(@{$_[0]}, &indexof($oldv[$i], @{$_[0]}), 1);
163 &renumber($_[0], $oldv[$i]->{'line'}, -1);
165 splice(@$lref, $after->{'line'}+1, 0, $nl);
166 $newv[$i]->{'line'} = $after->{'line'}+1;
167 splice(@{$_[0]}, &indexof($after, @{$_[0]})+1, 0,
169 &renumber($_[0], $newv[$i]->{'line'}, 1);
173 # Can just update at the same line
174 splice(@$lref, $oldv[$i]->{'line'}, 1, $nl);
175 $newv[$i]->{'line'} = $oldv[$i]->{'line'};
176 $_[0]->[&indexof($oldv[$i], @{$_[0]})] = $newv[$i];
183 # directive_line(&details)
186 local @v = @{$_[0]->{'values'}};
187 return $_[0]->{'name'}.(@v ? " ".join(' ',@v) : "").
188 ($_[0]->{'postcomment'} ? " #".$_[0]->{'postcomment'} : "");
191 # renumber(&directives, line, count, [end])
192 # Runs through the given array of directives and increases the line numbers
193 # of all those greater than some line by the given count
197 foreach $d (@{$_[0]}) {
198 if ($d->{'line'} > $_[1] && (!$_[3] || $d->{'line'} < $_[3])) {
199 $d->{'line'} += $_[2];