📄 squid-lib.pl
字号:
# squid-lib.pl# Functions for configuring squid.confdo '../web-lib.pl';&init_config();# Get the squid versionif (open(VERSION, "$module_config_directory/version")) { chop($squid_version = <VERSION>); close(VERSION); }# get_config()# Parses squid.conf into an array of data structuressub get_config{local($lnum, $_);if (!@get_config_cache) { open(CONF, $config{'squid_conf'}); $lnum = 0; while(<CONF>) { s/\r|\n//g; # strip newlines and comments s/#.*$//g; if (/^\s*(\S+)\s*(.*)$/) { local(%dir); $dir{'name'} = $1; $dir{'value'} = $2; $dir{'values'} = [ split(/\s+/, $2) ]; $dir{'line'} = $lnum; $dir{'index'} = scalar(@get_config_cache); push(@get_config_cache, \%dir); } $lnum++; } close(CONF); }return \@get_config_cache;}# find_config(name, &config)# Returns the structure(s) with some namesub find_config{local($c, @rv);foreach $c (@{$_[1]}) { if ($c->{'name'} eq $_[0]) { push(@rv, $c); } }return @rv ? wantarray ? @rv : $rv[0] : wantarray ? () : undef;}# icons_table(&links, &titles, &icons)sub icons_table{local($i);print "<table width=100% cellpadding=5> <tr>\n";for($i=0; $i<@{$_[0]}; $i++) { if ($i%4 == 0) { print "<tr>\n"; } print "<td width=25% align=center valign=top>\n"; &generate_icon($_[2]->[$i], $_[1]->[$i], $_[0]->[$i]); print "</td>\n"; if ($i%4 == 3) { print "</tr>\n"; } }while($i++%4) { print "<td width=25%></td>\n"; }print "</table><p>\n";}# choice_input(text, name, &config, default, [display, option]+)# Display a number of radio buttons for selecting some optionsub choice_input{local($v, $vv, $rv, $i);$v = &find_config($_[1], $_[2]);$vv = $v ? $v->{'value'} : $_[3];$rv = "<td><b>$_[0]</b></td> <td valign=top>";for($i=4; $i<@_; $i+=2) { $rv .= "<input type=radio name=$_[1] value=\"".$_[$i+1]."\" ". ($vv eq $_[$i+1] ? "checked" : "")."> $_[$i]\n"; }return $rv."</td>\n";}# save_choice(name, default, &config)# Save a selection from choice_input()sub save_choice{if ($in{$_[0]} eq $_[1]) { &save_directive($_[2], $_[0], [ ]); }else { &save_directive($_[2], $_[0], [{ 'name' => $_[0], 'values' => [ $in{$_[0]} ] }]); }}# list_input(text, name, &config, type, [default])# Display a list of valuessub list_input{local($v, $rv, @av);foreach $v (&find_config($_[1], $_[2])) { push(@av, @{$v->{'values'}}); }if ($_[4]) { $opt = sprintf "<input type=radio name=$_[1]_def value=1 %s> $_[4]\n", @av ? "" : "checked"; $opt .= sprintf "<input type=radio name=$_[1]_def value=0 %s>\n", @av ? "checked" : ""; }if ($_[3] == 0) { # text area $rv = "<td valign=top><b>$_[0]</b></td> <td valign=top>"; if ($opt) { $rv .= "$opt Listed..<br>\n"; } $rv .= "<textarea name=$_[1] rows=3 cols=15>". join("\n", @av)."</textarea></td>\n"; }else { # one long text field $rv = "<td valign=top><b>$_[0]</b></td> <td colspan=3 valign=top>$opt"; $rv .= "<input name=$_[1] size=50 value=\"".join(' ',@av)."\"></td>\n"; }return $rv;}# save_list(name, &checkfunc, &config)sub save_list{local($v, @vals, $err);if (!$in{"$_[0]_def"}) { @vals = split(/\s+/, $in{$_[0]}); if ($_[1]) { foreach $v (@vals) { &check_error($_[1], $v); } } }if (@vals) { &save_directive($_[2], $_[0], [{ 'name' => $_[0], values => \@vals }]); }else { &save_directive($_[2], $_[0], [ ]); }}# check_error(&function, value)sub check_error{return if (!$_[0]);local $err = &{$_[0]}($_[1]);if ($err) { &error($err); }}# address_input(text, name, &config, type)# Display a text area for entering 0 or more addressessub address_input{local($v, $rv, @av);foreach $v (&find_config($_[1], $_[2])) { push(@av, @{$v->{'values'}}); }if ($_[3] == 0) { # text area $rv = "<td valign=top><b>$_[0]</b></td> <td valign=top>"; $rv .= "<textarea name=$_[1] rows=3 cols=15>". join("\n", @av)."</textarea></td>\n"; }else { # one long text field $rv = "<td valign=top><b>$_[0]</b></td> <td colspan=3 valign=top>"; $rv .= "<input name=$_[1] size=50 value=\"".join(' ',@av)."\"></td>\n"; }return $rv;}# save_address(name, config)sub save_address{local($addr, @vals);foreach $addr (split(/\s+/, $in{$_[0]})) { &check_ipaddress($addr) || &error("'$addr' is not a valid IP address"); push(@vals, $addr); }if (@vals) { &save_directive($_[1], $_[0], [{ 'name' => $_[0], values => \@vals }]); }else { &save_directive($_[1], $_[0], [ ]); }}# opt_input(text, name, &config, default, size, units)# Display an optional field for entering somethingsub opt_input{local($v, $rv);$v = &find_config($_[1], $_[2]);$rv = "<td valign=top><b>$_[0]</b></td> <td valign=top nowrap";$rv .= $_[4] > 30 ? " colspan=3>\n" : ">\n";$rv .= sprintf "<input type=radio name=$_[1]_def value=1 %s> $_[3]\n", $v ? "" : "checked";$rv .= sprintf "<input type=radio name=$_[1]_def value=0 %s> ", $v ? "checked" : "";$rv .= sprintf "<input name=$_[1] size=$_[4] value=\"%s\"> %s</td>\n", $v ? $v->{'value'} : "", $_[5];return $rv;}# save_opt(name, &function, &config)# Save an input from opt_input()sub save_opt{if ($in{"$_[0]_def"}) { &save_directive($_[2], $_[0], [ ]); }else { &check_error($_[1], $in{$_[0]}); local $dir = { 'name' => $_[0], 'values' => [ $in{$_[0]} ] }; &save_directive($_[2], $_[0], [ $dir ]); }}# opt_time_input(text, name, &config, default, size)sub opt_time_input{local($v, $rv, $u);$v = &find_config($_[1], $_[2]);$rv = "<td valign=top><b>$_[0]</b></td> <td valign=top nowrap>\n";$rv .= sprintf "<input type=radio name=$_[1]_def value=1 %s> $_[3]\n", $v ? "" : "checked";$rv .= sprintf "<input type=radio name=$_[1]_def value=0 %s> ", $v ? "checked" : "";$rv .= sprintf "<input name=$_[1] size=$_[4] value=\"%s\">\n", $v ? $v->{'values'}->[0] : "";$rv .= "<select name=$_[1]_u>\n";foreach $u ("second", "minute", "hour", "day", "week", "fortnight", "month", "year", "decade") { $rv .= sprintf "<option value=$u %s>${u}s\n", $v && $v->{'values'}->[1] =~ /^$u/ ? "selected" : ""; }$rv .= "</select></td>\n";return $rv;}# save_opt_time(name, &config)sub save_opt_time{if ($in{"$_[0]_def"}) { &save_directive($_[1], $_[0], [ ]); }elsif ($in{$_[0]} !~ /^[0-9\.]+$/) { &error("'$in{$_[0]}' is not a valid number of ",$in{"$_[0]_u"},"s"); }else { local $dir = { 'name' => $_[0], 'values' => [ $in{$_[0]}, $in{"$_[0]_u"} ] }; &save_directive($_[1], $_[0], [ $dir ]); }}# opt_bytes_input(text, name, &config, default, size)sub opt_bytes_input{local($v, $rv, $u);$v = &find_config($_[1], $_[2]);$rv = "<td valign=top><b>$_[0]</b></td> <td valign=top nowrap>\n";$rv .= sprintf "<input type=radio name=$_[1]_def value=1 %s> $_[3]\n", $v ? "" : "checked";$rv .= sprintf "<input type=radio name=$_[1]_def value=0 %s> ", $v ? "checked" : "";$rv .= sprintf "<input name=$_[1] size=$_[4] value=\"%s\">\n", $v ? $v->{'values'}->[0] : "";$rv .= "<select name=$_[1]_u>\n";foreach $u ("KB", "MB", "GB") { $rv .= sprintf "<option value=$u %s>${u}\n", $v && $v->{'values'}->[1] eq $u ? "selected" : ""; }$rv .= "</select></td>\n";return $rv;}# save_opt_bytes(name, &config)sub save_opt_bytes{if ($in{"$_[0]_def"}) { &save_directive($_[1], $_[0], [ ]); }elsif ($in{$_[0]} !~ /^[0-9\.]+$/) { &error("'$in{$_[0]}' is not a valid number of ",$in{"$_[0]_u"},"s"); }else { local $dir = { 'name' => $_[0], 'values' => [ $in{$_[0]}, $in{"$_[0]_u"} ] }; &save_directive($_[1], $_[0], [ $dir ]); }}# save_directive(&config, name, &values)# Given a structure containing a directive name, type, values and members# add, update or remove that directive in config structure and data files.sub save_directive{local(@oldv, @newv, $i, $o, $n, $lref, $nl, $change);@oldv = &find_config($_[1], $_[0]);@newv = @{$_[2]};$lref = &read_file_lines($config{'squid_conf'});for($i=0; $i<@oldv || $i<@newv; $i++) { if ($i >= @oldv) { # a new directive is being added.. put it at the end of the file $nl = &directive_line($newv[$i]); if ($change) { # put it after any directives of the same type $newv[$i]->{'line'} = $change->{'line'}+1; splice(@$lref, $newv[$i]->{'line'}, 0, $nl); &renumber($_[0], $newv[$i]->{'line'}, 1); splice(@{$_[0]}, &indexof($change, @{$_[0]}), 0, $newv[$i]); $change = $newv[$i]; } else { # put it at the end of the file $newv[$i]->{'line'} = scalar(@$lref); push(@$lref, $nl); push(@{$_[0]}, $newv[$i]); } } elsif ($i >= @newv) { # a directive was deleted splice(@$lref, $oldv[$i]->{'line'}, 1); &renumber($_[0], $oldv[$i]->{'line'}, -1); splice(@{$_[0]}, &indexof($oldv[$i], @{$_[0]}), 1); } else { # updating some directive $nl = &directive_line($newv[$i]); splice(@$lref, $oldv[$i]->{'line'}, 1, $nl); $newv[$i]->{'line'} = $oldv[$i]->{'line'}; $_[0]->[&indexof($oldv[$i], @{$_[0]})] = $newv[$i]; $change = $newv[$i]; } }}# directive_line(&details)sub directive_line{local(@v) = @{$_[0]->{'values'}};return $_[0]->{'name'}.(@v ? " ".join(' ',@v) : "");}# renumber(&directives, line, count)# Runs through the given array of directives and increases the line numbers# of all those greater than some line by the given countsub renumber{local($d);foreach $d (@{$_[0]}) { if ($d->{'line'} > $_[1]) { $d->{'line'} += $_[2]; } }}%acl_types = ("src", "Client Address", "dst", "Web Server Address", "srcdomain", "Client Hostname", "dstdomain", "Web Server Hostname", "time", "Date and Time", "url_regex", "URL Regexp", "urlpath_regex", "URL Path Regexp", "port", "URL Port", "proto", "URL Protocol", "method", "Request Method", "browser", "Browser Regexp", "user", "Proxy Login");if ($squid_version >= 2.0) { $acl_types{'src_as'} = "Source AS Number"; $acl_types{'dst_as'} = "Dest AS Number"; $acl_types{'proxy_auth'} = "External Auth"; $acl_types{'srcdom_regex'} = "Client Regexp"; $acl_types{'dstdom_regex'} = "Web Server Regexp"; }if ($squid_version >= 2.2) { $acl_types{'ident'} = "RFC931 User"; $acl_types{'myip'} = "Proxy IP Address"; }# restart_button()# Returns HTML for a link to put in the top-right corner of every pagesub restart_button{local($conf, $pidstruct, $pidfile, $pid, $args);$conf = &get_config();if ($pidstruct = &find_config("pid_filename", $conf)) { $pidfile = $pidstruct->{'values'}->[0]; }else { $pidfile = $config{'pid_file'}; }if (open(PID, $pidfile)) { <PID> =~ /(\d+)/; $pid = $1; close(PID); }$args = "redir=".&urlize(&this_url())."&pid=$pid";if ($pid && kill(0, $pid)) { return "<a href=\"restart.cgi?$args\">Apply Changes</a><br>\n". "<a href=\"stop.cgi?$args\">Stop Squid</a>\n"; }else { return "<a href=\"start.cgi?$args\">Start Squid</a><br>\n"; }close(PID);}# this_url()# Returns the URL in the apache directory of the current scriptsub this_url{local($url);$url = $ENV{'SCRIPT_NAME'};if (defined($ENV{'QUERY_STRING'})) { $url .= "?$ENV{'QUERY_STRING'}"; }return $url;}# list_auth_users(file)sub list_auth_users{local(@rv, $lnum); $lnum = 0;open(USERS, $_[0]);while(<USERS>) { if (/^([^:]+):(\S+)/) { push(@rv, { 'user' => $1, 'pass' => $2, 'line' => $lnum }); } $lnum++; }close(USERS);return @rv;}# get_squid_user(&config)# Returns the effective user and group (if any)sub get_squid_user{if ($squid_version < 2) { local $ceu = &find_config("cache_effective_user", $_[0]); if ($ceu) { return ($ceu->{'values'}->[0], $ceu->{'values'}->[1]); } return (undef, undef); }else { local $ceu = &find_config("cache_effective_user", $_[0]); local $ceg = &find_config("cache_effective_group", $_[0]); return ($ceu->{'values'}->[0], $ceg ? $ceg->{'values'}->[0] : $ceu->{'values'}->[1]); }}# chown_files(user, group, config)# Change ownership of all squid log and cache directoriessub chown_files{local(@list, $pidstruct, $pidfile);@list = ( $config{'log_dir'} );# add pidfileif ($str = &find_config("pid_filename", $_[2])) { $pidfile = $str->{'values'}->[0]; }else { $pidfile = $config{'pid_file'}; }push(@list, $pidfile);# add other log directoriesforeach $d ("cache_access_log","cache_log","cache_store_log","cache_swap_log") { if (($str = &find_config($d, $_[2])) && $str->{'values'}->[0] =~ /^(\S+)\/[^\/]+$/) { push(@list, $1); } }# add cache directoriesif (@str = &find_config("cache_dir", $_[2])) { foreach $str (@str) { push(@list, $str->{'values'}->[0]); } }else { push(@list, $config{'cache_dir'}); }system("chown -Rf $_[0]:$_[1] ".join(" ",@list)." >/dev/null 2>&1");}1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -