1 # Functions for reading and writing sarg.conf
3 BEGIN { push(@INC, ".."); };
7 $cron_cmd = "$module_config_directory/generate.pl";
8 %needs_quotes = map { $_, 1 } ("title", "logo_text", "user_invalid_char",
9 "privacy_string", "include_users",
10 "exclude_string", "datafile_delimiter");
13 # Parses the sarg config file into directives
16 if (!scalar(@get_config_cache)) {
18 open(CONF, $config{'sarg_conf'});
21 if (/^\s*(#*)\s*(\S+)\s+"([^"]*)"/ ||
22 /^\s*(#*)\s*(\S+)\s+'([^"]*)'/ ||
23 /^\s*(#*)\s*(\S+)\s+(.*\S)/) {
24 push(@get_config_cache,
34 return \@get_config_cache;
37 # find(name, &config, [and-disabled])
42 foreach $c (@{$_[1]}) {
43 if (lc($c->{'name'}) eq lc($_[0])) {
44 if ($c->{'enabled'} && $_[2] == 0 ||
45 !$c->{'enabled'} && $_[2] == 2 ||
51 return wantarray ? @rv : $rv[0];
54 # find_value(name, &config)
57 local @rv = map { $_->{'value'} } &find(@_);
58 return wantarray ? @rv : $rv[0];
61 # save_directive(&config, name, &values)
62 # Update the config file with some new values for an option
65 local ($conf, $name, $values) = @_;
66 local $lref = &read_file_lines($config{'sarg_conf'});
67 local @old = &find($name, $conf);
68 local @new = @$values;
71 for($i=0; $i<@old || $i<@new; $i++) {
74 if ($needs_quotes{$name}) {
75 $newline = $name." \"".$new[$i]."\"";
78 $newline = $name." ".$new[$i];
82 if ($i<@old && $i<@new) {
83 # Updating some directive
84 $lref->[$old[$i]->{'line'}] = $newline;
85 $old[$i]->{'value'} = $new[$i];
89 # Removing some directive (need to renumber)
90 splice(@$lref, $old[$i]->{'line'}, 1);
91 splice(@$conf, $old[$i]->{'index'}, 1);
92 &renumber($conf, 'line', $old[$i]->{'line'}, -1);
93 &renumber($conf, 'index', $old[$i]->{'index'}, -1);
96 # Adding some directive (perhaps after comment)
97 local $nd = { 'name' => $name,
98 'value' => $new[$i] };
99 local $cmt = &find($name, $conf, 1);
100 if ($cmt && !$cmt->{'enabled'}) {
101 # Add after comment line
102 $nd->{'line'} = $cmt->{'line'} + 1;
103 $nd->{'index'} = $cmt->{'index'} + 1;
104 &renumber($conf, 'line', $nd->{'line'}-1, 1);
105 &renumber($conf, 'index', $nd->{'index'}-1, 1);
106 splice(@$lref, $nd->{'line'}, 0, $newline);
107 splice(@$conf, $nd->{'index'}, 0, $nd);
111 $nd->{'line'} = scalar(@$lref);
112 $nd->{'index'} = scalar(@$conf);
113 push(@$lref, $newline);
120 # renumber(&conf, field, pos, offset)
123 local ($conf, $field, $pos, $offset) = @_;
125 foreach $c (@$conf) {
126 if ($c->{$field} > $pos) {
127 $c->{$field} += $offset;
134 # config_textbox(&config, name, size, cols, [prefix])
135 # Returns HTML for a table row for some text field
138 local ($conf, $name, $size, $cols, $prefix) = @_;
140 local $val = join(" ", &find_value($name, $conf));
141 return &ui_table_row($text{$config_prefix.$name},
142 &ui_textbox($name, $val, $size)." ".$prefix,
146 # save_textbox(config, name, [function])
149 local ($conf, $name, $func) = @_;
150 local @vals = $split ? split(/\s+/, $in{$name}) : ( $in{$name} );
153 &error_check($name, $func, $v);
155 &save_directive($conf, $name, \@vals);
158 # error_check(name, func, value)
161 local ($name, $func, $val) = @_;
163 local $err = &$func($val);
164 &error($text{$config_prefix.$name}." : ".$err) if ($err);
167 # config_opt_textbox(&config, name, size, cols, [default])
168 # Returns HTML for a table row for some optional text field
169 sub config_opt_textbox
171 local ($conf, $name, $size, $cols, $default) = @_;
173 local $val = &find_value($name, $conf);
174 local $defstr = &find($name, $conf, 2);
175 local $def = $defstr && $defstr->{'value'} ? " ($defstr->{'value'})" : undef;
176 return &ui_table_row($text{$config_prefix.($name eq "title" ? "title2" :$name)},
177 &ui_radio($name."_def", $val ? 0 : 1,
178 [ [ 1, $default || $text{'default'}.$def ],
180 &ui_textbox($name, $val, $size), $cols, \@ui_tds);
183 # save_opt_textbox(config, name, [function], [split])
186 local ($conf, $name, $func, $split) = @_;
187 if ($in{$name."_def"}) {
188 &save_directive($conf, $name, [ ]);
195 # config_yesno(&config, name, [yes], [no], [&others])
196 # Returns HTML for a table row for yes/no checkboxes
199 local ($conf, $name, $yes, $no, $others, $width) = @_;
200 local $val = &find_value($name, $conf);
201 local $default = &find($name, $conf, 2);
202 #local $defstr = $default ? " ($default->{'value'})" : "";
203 return &ui_table_row($text{$config_prefix.$name},
204 &ui_radio($name, $val,
205 [ [ "yes", $yes || $text{'yes'} ],
206 [ "no", $no || $text{'no'} ],
208 [ "", $text{'default'}.$defstr ] ]),
212 # save_yesno(&config, name)
215 local ($conf, $name) = @_;
217 &save_directive($conf, $name, [ ]);
220 &save_directive($conf, $name, [ $in{$name} ]);
224 # config_radio(&config, name, [&options], [width])
225 # Returns HTML for a table row for a bunch of checkboxes
228 local ($conf, $name, $others, $width) = @_;
229 local $val = &find_value($name, $conf);
230 local $default = &find($name, $conf, 2);
231 #local $defstr = $default ? " ($default->{'value'})" : "";
232 return &ui_table_row($text{$config_prefix.$name},
233 &ui_radio($name, $val,
235 [ "", $text{'default'}.$defstr ] ]),
241 &save_yesno(@_); # same logic works
244 # config_sortfield(&config, name, &opts, [&sort-opts])
245 # Returns HTML for a table row for selecting a sort mode
248 local ($conf, $name, $opts, $sort) = @_;
249 local $val = &find_value($name, $conf);
250 local $default = &find($name, $conf, 2);
251 #local $defstr = $default ? " ($default->{'value'})" : "";
252 local @vals = split(/\s+/, $val);
253 $sort ||= [ [ "reverse", $text{'report_reverse'} ],
254 [ "forward", $text{'report_forward'} ] ];
255 return &ui_table_row($text{$config_prefix.$name},
256 &ui_oneradio($name."_def", 1, $text{'default'}.$defstr, !$val)."\n".
257 &ui_oneradio($name."_def", 0, $text{'report_field'}, $val)."\n".
258 &ui_select($name."_field", $vals[0],
259 [ map { [ $_, $text{'report_by_'.lc($_)} ] } @$opts ])."\n".
260 &ui_select($name."_order", $vals[1], $sort), 3);
265 local ($conf, $name) = @_;
266 if ($in{$name."_def"}) {
267 &save_directive($conf, $name, [ ]);
270 &save_directive($conf, $name, [ $in{$name."_field"}." ".
271 $in{$name."_order"} ]);
275 # config_language(&config, name, width, file)
278 local ($conf, $name, $width, $file) = @_;
279 local $val = &find_value($name, $conf);
280 local $default = &find($name, $conf, 2);
281 local $defstr = $default ? " ($default->{'value'})" : "";
283 local @langs = ( [ "", $text{'default'}.$defstr ] );
287 if (/^(\S+)\t+(\S.*)/) {
288 push(@langs, [ $1, "$1 - $2" ]);
291 push(@langs, [ $1 ]);
293 $found++ if ($val eq $_);
296 push(@langs, [ $val ]) if (!$found && $val);
297 return &ui_table_row($text{$config_prefix.$name},
298 &ui_select($name, $val, \@langs), $width);
301 # save_language(&config, name)
304 &save_yesno(@_); # same logic works
307 # config_select(&config, name, &options, default, width)
310 local ($conf, $name, $others, $default, $width) = @_;
311 local $val = &find_value($name, $conf);
312 local @vals = split(/\s+/, $val);
313 return &ui_table_row($text{$config_prefix.$name},
314 &ui_radio($name."_def", $val ? 0 : 1,
315 [ [ 1, $default || $text{'default'} ],
316 [ 0, $text{'report_below'} ] ])."<br>".
317 &ui_select($name, \@vals, $others, "5 ", 1),
324 local ($conf, $name) = @_;
325 $in{$name} =~ s/\0/ /g;
326 $in{$name."_def"} || $in{$name} || &error($text{'report_eselect'});
327 &save_opt_textbox(@_); # same logic works
330 # config_colons(&config, name, separator, default, width)
333 local ($conf, $name, $sep, $default, $width) = @_;
334 local $val = &find_value($name, $conf);
335 return &ui_table_row($text{$config_prefix.$name},
336 &ui_radio($name."_def", $val ? 0 : 1,
337 [ [ 1, $default || $text{'default'} ],
338 [ 0, $text{'report_below2'} ] ])."<br>".
339 &ui_textarea($name, join("\n", split($sep, $val)),
344 # save_colons(&config, name, separator)
347 local ($conf, $name, $sep) = @_;
348 $in{$name} =~ s/\r//g;
349 $in{$name} =~ s/\s+$//;
350 $in{$name} =~ s/^\s+//;
351 $in{$name} =~ s/\n/$sep/g;
352 $in{$name."_def"} || $in{$name} || &error($text{'report_eenter'});
353 &save_opt_textbox($conf, $name); # same logic works
356 # config_range(&config, name, start, end, width)
359 local ($conf, $name, $start, $end, $width) = @_;
360 local $val = &find_value($name, $conf);
361 local (%sel, $v, $vn);
362 foreach $v (split(/,/, $val)) {
363 if ($v =~ /^(\d+)\-(\d+)$/) {
364 foreach $vn ($1 .. $2) { $sel{$vn}++; }
368 local $table = "<table>\n";
370 for($i=$start; $i<=$end; $i++) {
371 $table .= "<tr>\n" if ($i%12 == 0);
372 $table .= "<td>".&ui_checkbox($name, $i,
373 $text{$config_prefix.$name.$i} || $i, $sel{$i})."</td>\n";
374 $table .= "</tr>\n" if ($i%12 == 11);
376 $table .= "</tr>\n" if ($i%12 != 0);
377 $table .= "</table>\n";
378 return &ui_table_row($text{$config_prefix.$name},
379 &ui_radio($name."_def", $val ? 0 : 1,
380 [ [ 1, $text{'default'} ],
381 [ 0, $text{'report_below'} ] ]).
382 "<br>".$table, $width);
385 # save_range(&config, name)
388 local ($conf, $name) = @_;
389 if ($in{$name."_def"}) {
390 &save_directive($conf, $name, [ ]);
393 local @vals = split(/\0/, $in{$name});
394 &save_directive($conf, $name, [ join(",", @vals) ]);
398 # generate_report(handle, escape, clear-output, from, to)
399 # Immediately generate a report
402 local ($h, $esc, $clear, $from, $to) = @_;
403 local $conf = &get_config();
404 local $odir = &find_value("output_dir", $conf);
405 $odir ||= &find_value("output_dir", $conf, 1);
408 # Delete all old files
409 unlink("$odir/index.html");
411 while($f = readdir(DIR)) {
412 if (-r "$odir/$f/usuarios") {
413 &system_logged("rm -rf ".quotemeta("$odir/$f"));
419 # Work out date range
423 ($from, $to) = ($to, $from);
426 local @fromtm = localtime($now - $from*24*60*60);
427 local @totm = localtime($now - $to*24*60*60);
428 $rangearg = sprintf "-d %2.2d/%2.2d/%4.4d-%2.2d/%2.2d/%4.4d",
429 $fromtm[3], $fromtm[4]+1, $fromtm[5]+1900,
430 $totm[3], $totm[4]+1, $totm[5]+1900;
433 local $sfile = &find_value("access_log", $conf);
434 local @all = &all_log_files($sfile);
435 foreach $file (@all) {
436 local $cmd = "$config{'sarg'} -l $file $rangearg";
438 open(OUT, "$cmd 2>&1 |");
440 print $h $esc ? &html_escape($_) : $_;
444 &additional_log("exec", undef, $cmd);
449 # all_log_files(file)
452 $_[0] =~ /^(.*)\/([^\/]+)$/;
457 foreach $f (readdir(DIR)) {
458 if ($f =~ /^\Q$base\E/ && -f "$dir/$f") {
459 push(@rv, "$dir/$f");
468 return &ui_radio("clear", int($config{'clear'}),
469 [ [ 1, $text{'yes'} ],
470 [ 0, $text{'no'} ] ]);
475 local ($rfrom, $rto) = split(/\s+/, $config{'range'});
476 local $range = &text('sched_rsel',
477 &ui_textbox("rfrom", $rfrom, 3),
478 &ui_textbox("rto", $rto, 3));
479 return &ui_radio("range_def", $config{'range'} ? 0 : 1,
480 [ [ 1, $text{'sched_rall'} ],
486 &lock_file($config{'sarg_conf'});
489 sub unlock_sarg_files
491 &unlock_file($config{'sarg_conf'});