diff -U 3 -H -d -r -N -- usermin-1.080/web-lib.pl usermin-1.090/web-lib.pl --- usermin-1.080/web-lib.pl 2004-06-04 02:18:07.000000000 +0300 +++ usermin-1.090/web-lib.pl 2004-09-05 15:37:25.000000000 +0300 @@ -47,16 +47,17 @@ #__DATA__ -# read_file(file, &assoc, [&order], [lowercase]) +# read_file(file, &assoc, [&order], [lowercase], [split-char]) # Fill an associative array with name=value pairs from a file sub read_file { local $_; +local $split = defined($_[4]) ? $_[4] : "="; open(ARFILE, $_[0]) || return 0; while() { chomp; local $hash = index($_, "#"); - local $eq = index($_, "="); + local $eq = index($_, $split); if ($hash != 0 && $eq >= 0) { local $n = substr($_, 0, $eq); local $v = substr($_, $eq+1); @@ -80,28 +81,29 @@ } else { local %d; - &read_file($_[0], \%d); + &read_file($_[0], \%d, $_[2], $_[3], $_[4]); %{$main::read_file_cache{$_[0]}} = %d; %{$_[1]} = ( %{$_[1]}, %d ); } } -# write_file(file, array) +# write_file(file, array, [join-char]) # Write out the contents of an associative array as name=value lines sub write_file { local(%old, @order); +local $join = defined($_[2]) ? $_[2] : "="; &read_file($_[0], \%old, \@order); open(ARFILE, ">$_[0]") || &error(&text("efilewrite", $_[0], $!)); foreach $k (@order) { if (exists($_[1]->{$k})) { - (print ARFILE $k,"=",$_[1]->{$k},"\n") || + (print ARFILE $k,$join,$_[1]->{$k},"\n") || &error(&text("efilewrite", $_[0], $!)); } } foreach $k (keys %{$_[1]}) { if (!exists($old{$k})) { - (print ARFILE $k,"=",$_[1]->{$k},"\n") || + (print ARFILE $k,$join,$_[1]->{$k},"\n") || &error(&text("efilewrite", $_[0], $!)); } } @@ -145,17 +147,19 @@ @remote_user_info ? $tmp_base."-".$remote_user : $< != 0 ? $tmp_base."-".getpwuid($<) : $tmp_base; -while(1) { +local $tries = 0; +while($tries++ < 10) { local @st = lstat($tmp_dir); last if ($st[4] == $< && (-d _) && ($st[2] & 0777) == 0755); if (@st) { unlink($tmp_dir) || rmdir($tmp_dir) || - system("/bin/rm -rf \"$tmp_dir\""); + system("/bin/rm -rf ".quotemeta($tmp_dir)); } mkdir($tmp_dir, 0755) || next; chown($<, $(, $tmp_dir); chmod(0755, $tmp_dir); } +&error("Failed to create temp directory $tmp_dir") if ($tries >= 10); if (defined($_[0]) && $_[0] !~ /\.\./) { return "$tmp_dir/$_[0]"; } @@ -182,15 +186,15 @@ return $str; } -# indexof +# indexof(string, array) # Returns the index of some value in an array, or -1 sub indexof { local($i); for($i=1; $i <= $#_; $i++) { if ($_[$i] eq $_[0]) { return $i - 1; } - } - return -1; } + return -1; +} # unique # Returns the unique elements of some array @@ -560,8 +564,8 @@ if (!$_[4] && !$tconfig{'nomoduleindex'}) { local $idx = $module_info{'index_link'}; local $mi = $module_index_link || "/$module_name/$idx"; - print "", - "$text{'header_module'}
\n"; + local $mt = $module_index_name || $text{'header_module'}; + print "$mt
\n"; } if (ref($_[2]) eq "ARRAY" && !$ENV{'ANONYMOUS_USER'}) { print &hlink($text{'header_help'}, $_[2]->[0], $_[2]->[1]), @@ -701,13 +705,16 @@ $prot = uc($ENV{'HTTPS'}) eq "ON" ? "https" : "http"; local $wp = $gconfig{'webprefixnoredir'} ? undef : $gconfig{'webprefix'}; if ($_[0] =~ /^(http|https|ftp|gopher):/) { + # Absolute URL (like http://...) $url = $_[0]; } elsif ($_[0] =~ /^\//) { + # Absolute path (like /foo/bar.cgi) $url = "$prot://$ENV{'SERVER_NAME'}$port$wp$_[0]"; } elsif ($ENV{'SCRIPT_NAME'} =~ /^(.*)\/[^\/]*$/) { - $url = "$prot://$ENV{'SERVER_NAME'}$port$1/$wp$_[0]"; + # Relative URL (like foo.cgi) + $url = "$prot://$ENV{'SERVER_NAME'}$port$wp$1/$_[0]"; } else { $url = "$prot://$ENV{'SERVER_NAME'}$port/$wp$_[0]"; @@ -1226,6 +1233,12 @@ if ($_[3]) { ${$_[3]} = "Failed to lookup IP address for $_[0]"; return 0; } else { &error("Failed to lookup IP address for $_[0]"); } } +if ($gconfig{'bind_proxy'}) { + if (!bind($h, pack_sockaddr_in(0, inet_aton($gconfig{'bind_proxy'})))) { + if ($_[3]) { ${$_[3]} = "Failed to bind to source address : $!"; return 0; } + else { &error("Failed to bind to source address : $!"); } + } + } if (!connect($h, pack_sockaddr_in($_[1], $addr))) { if ($_[3]) { ${$_[3]} = "Failed to connect to $_[0]:$_[1] : $!"; return 0; } else { &error("Failed to connect to $_[0]:$_[1] : $!"); } @@ -1320,7 +1333,7 @@ if ($i%$cols == 0) { print "\n"; } print "\n"; &generate_icon($_[2]->[$i], $_[1]->[$i], $_[0]->[$i], - $_[4], $_[5], $_[6]); + ref($_[4]) ? $_[4]->[$i] : $_[4], $_[5], $_[6]); print "\n"; if ($i%$cols == $cols-1) { print "\n"; } } @@ -1570,6 +1583,22 @@ { local $u = defined($_[1]) ? $_[1] : $base_remote_user; local $m = defined($_[2]) ? $_[2] : $module_name; +if (&foreign_check("acl")) { + # Check if this user is a member of a group, and if he gets the + # module from a group. If so, update its ACL as well + &foreign_require("acl", "acl-lib.pl"); + local ($g, $group); + foreach $g (&acl::list_groups()) { + if (&indexof($u, @{$g->{'members'}}) >= 0 && + &indexof($m, @{$g->{'modules'}}) >= 0) { + $group = $g; + last; + } + } + if ($group) { + &save_module_acl($_[0], $group->{'name'}, $m); + } + } &write_file("$config_directory/$m/$u.acl", $_[0]); } @@ -2209,7 +2238,7 @@ } } -# webmin_log(action, type, object, ¶ms, [module]) +# webmin_log(action, type, object, ¶ms, [module], [host, script-on-host, client-ip]) # Log some action taken by a user sub webmin_log { @@ -2253,8 +2282,8 @@ $id, $tm[3], $text{"smonth_".($tm[4]+1)}, $tm[5]+1900, $tm[2], $tm[1], $tm[0], $remote_user, $main::session_id ? $main::session_id : '-', - $ENV{'REMOTE_HOST'}, - $m, $script_name, + $_[7] || $ENV{'REMOTE_HOST'}, + $m, $_[5] ? "$_[5]:$_[6]" : $script_name, $_[0], $_[1] ne '' ? $_[1] : '-', $_[2] ne '' ? $_[2] : '-'; foreach $k (sort { $a cmp $b } keys %{$_[3]}) { local $v = $_[3]->{$k}; @@ -2278,6 +2307,9 @@ open(WEBMINLOG, ">>$webmin_logfile"); print WEBMINLOG $line,"\n"; close(WEBMINLOG); +if ($gconfig{'logperms'}) { + chmod(oct($gconfig{'logperms'}), $webmin_logfile); + } if ($gconfig{'logfiles'}) { # Find and record the changes made to any locked files @@ -2288,6 +2320,10 @@ print DIFFLOG "$d->{'type'} $d->{'object'}\n"; print DIFFLOG $d->{'data'}; close(DIFFLOG); + if ($gconfig{'logperms'}) { + chmod(oct($gconfig{'logperms'}), + "$ENV{'WEBMIN_VAR'}/diffs/$id.$i"); + } $i++; } @main::locked_file_diff = undef; @@ -2894,6 +2930,7 @@ local $error; if ($gconfig{'http_proxy'} =~ /^http:\/\/(\S+):(\d+)/ && !&no_proxy($_[0])) { + # Via a proxy &open_socket($1, $2, $rv->{'fh'}, \$error); return $error if ($error); local $fh = $rv->{'fh'}; @@ -2906,6 +2943,7 @@ } } else { + # Connecting directly &open_socket($_[0], $_[1], $rv->{'fh'}, \$error); return $error if ($error); local $fh = $rv->{'fh'}; @@ -3123,6 +3161,7 @@ $rv =~ s/<\s*script[^>]*>([\000-\377]*?)<\s*\/script\s*>//gi; $rv =~ s/(on(Abort|Blur|Change|Click|DblClick|DragDrop|Error|Focus|KeyDown|KeyPress|KeyUp|Load|MouseDown|MouseMove|MouseOut|MouseOver|MouseUp|Move|Reset|Resize|Select|Submit|Unload)=)/x$1/gi; $rv =~ s/(javascript:)/x$1/gi; +$rv =~ s/(vbscript:)/x$1/gi; return $rv; } @@ -3310,10 +3349,10 @@ # Relative URLs can also be parsed, if the base information is provided sub parse_http_url { -if ($_[0] =~ /^(http|https):\/\/([^:\/]+)(:(\d+))?(\/\S*)$/) { +if ($_[0] =~ /^(http|https):\/\/([^:\/]+)(:(\d+))?(\/\S*)?$/) { # An absolute URL local $ssl = $1 eq 'https'; - return ($2, $3 ? $4 : $ssl ? 443 : 80, $5, $ssl); + return ($2, $3 ? $4 : $ssl ? 443 : 80, $5 || "/", $ssl); } elsif (!$_[1]) { # Could not parse @@ -3436,18 +3475,18 @@ &write_file("$config_directory/$m/config", $c); } -# nice_size(bytes) +# nice_size(bytes, [min]) # Converts a number of bytes into a number of bytes, kb, mb or gb sub nice_size { -if ($_[0] > 10*1024*1024*1024) { - return int($_[0]/1024/1024/1024)." GB"; +if ($_[0] > 10*1024*1024*1024 || $_[1] >= 1024*1024*1024) { + return int(($_[0]+1024*1024*1024-1)/1024/1024/1024)." GB"; } -elsif ($_[0] > 10*1024*1024) { - return int($_[0]/1024/1024)." MB"; +elsif ($_[0] > 10*1024*1024 || $_[1] >= 1024*1024) { + return int(($_[0]+1024*1024-1)/1024/1024)." MB"; } -elsif ($_[0] > 10*1024) { - return int($_[0]/1024)." kB"; +elsif ($_[0] > 10*1024 || $_[1] >= 1024) { + return int(($_[0]+1024-1)/1024)." kB"; } else { return int($_[0])." bytes"; @@ -3484,5 +3523,27 @@ return undef; } +# select_all_link(field, form, text) +# Returns HTML for a 'Select all' link that uses Javascript to select +# multiple checkboxes with the same name +sub select_all_link +{ +local ($field, $form, $text) = @_; +$form = int($form); +$text ||= "Select all"; +return "$text"; +} + +# select_all_link(field, form, text) +# Returns HTML for a 'Select all' link that uses Javascript to invert the +# selection on multiple checkboxes with the same name +sub select_invert_link +{ +local ($field, $form, $text) = @_; +$form = int($form); +$text ||= "Invert selection"; +return "$text"; +} + 1; # return true?