Compare commits

..

27 Commits

Author SHA1 Message Date
Ilia Ross
5cf228d4a0 Add side by side UI form buttons API
Some checks are pending
webmin.dev: webmin/webmin / build (push) Waiting to run
https://github.com/webmin/webmin/issues/2659

[no-build]
2026-04-09 19:33:37 +02:00
Ilia Ross
0e45e0bcbd Update translations consistency
Some checks failed
webmin.dev: webmin/webmin / build (push) Has been cancelled
https://github.com/webmin/webmin/issues/2655
2026-04-09 00:11:17 +02:00
Ilia Ross
bdb98c49c9 Fix language
https://github.com/webmin/webmin/issues/2655
2026-04-09 00:08:07 +02:00
Ilia Ross
9369441fc5 Fix to avoid auto-fill for URL auth
https://github.com/webmin/webmin/issues/2655
2026-04-09 00:07:08 +02:00
Ilia Ross
77e488b4b6 filemin: reindent and add function comments 2026-04-08 19:53:49 +02:00
Ilia Ross
26faad0d39 Fix regression in previous refactor
Some checks failed
webmin.dev: webmin/webmin / build (push) Has been cancelled
2026-04-08 17:45:15 +02:00
Ilia Ross
886cf142db Fix indent (more) 2026-04-08 17:31:51 +02:00
Ilia Ross
d4439b445c Fix indent 2026-04-08 17:16:54 +02:00
Ilia Ross
5a336902f8 Add vars declarations 2026-04-08 17:09:16 +02:00
Jamie Cameron
19b0f187ba The [mysqld] section may be [mariadb]
https://github.com/webmin/webmin/issues/2650
2026-04-08 08:06:52 -07:00
Jamie Cameron
4a283d2180 Template description should be escaped 2026-04-08 07:56:12 -07:00
Jamie Cameron
670f33c872 Merge branch 'master' of github.com:webmin/webmin 2026-04-08 06:24:40 -07:00
Jamie Cameron
b5b65f06b7 Factor out function to get allowed paths 2026-04-08 06:24:32 -07:00
Ilia Ross
b02d797bc6 Fix the issue with disabled email for status report
Some checks failed
webmin.dev: webmin/webmin / build (push) Has been cancelled
https://github.com/virtualmin/virtualmin-gpl/issues/1202
2026-04-08 00:31:53 +02:00
Ilia Ross
b9fbf4b2c3 Fix status monitoring emails display 2026-04-08 00:31:14 +02:00
Jamie Cameron
ef1fb66954 Merge pull request #2657 from swelljoe/security-scan-core
Some checks failed
webmin.dev: webmin/webmin / build (push) Has been cancelled
typo s/actphost/acpthost/
2026-04-07 06:43:02 -07:00
Joe Cooper
316529c8ca typo s/actphost/acpthost/ 2026-04-06 22:27:52 -05:00
Jamie Cameron
d1e72c08a0 Merge branch 'master' of github.com:webmin/webmin
Some checks failed
webmin.dev: webmin/webmin / build (push) Has been cancelled
2026-04-06 08:01:56 -07:00
Jamie Cameron
7ed4763f00 Don't declare a filesystem to be too small if we don't know how small it is
https://github.com/webmin/webmin/issues/2653
2026-04-06 08:01:19 -07:00
Ilia Ross
fe90fb2479 Fix process nice level and IO controls switchable
Some checks failed
webmin.dev: webmin/webmin / build (push) Has been cancelled
https://github.com/webmin/webmin/issues/2652

[no-build]
2026-04-03 16:43:19 +02:00
Jamie Cameron
e44a25191f Add support for headers with multiple values
Some checks failed
webmin.dev: webmin/webmin / build (push) Has been cancelled
2026-04-02 07:31:51 -07:00
Jamie Cameron
3dbeb4e4db Don't trust proxy-provided SSL cert if it's flagged as not verified
Some checks failed
webmin.dev: webmin/webmin / build (push) Has been cancelled
2026-04-01 18:17:02 -07:00
Jamie Cameron
7c5d4087fc Quote params by default 2026-04-01 18:07:19 -07:00
Ilia Ross
83e4fed616 Fix to correctly preserve full quoted action params in Fail2Ban jail editor #2647 2026-04-02 00:48:13 +02:00
Jamie Cameron
5b8dba4a5f Obsolete scripts that no longer need to exist
Some checks failed
webmin.dev: webmin/webmin / build (push) Has been cancelled
2026-04-01 12:49:21 -07:00
Jamie Cameron
2404e1ddfc Permissions update
Some checks failed
webmin.dev: webmin/webmin / build (push) Has been cancelled
2026-03-29 22:28:47 -07:00
Jamie Cameron
3a75f0f3f8 Sometimes ntfs is in lower case
Some checks failed
webmin.dev: webmin/webmin / build (push) Has been cancelled
https://github.com/webmin/webmin/issues/2635
2026-03-29 21:19:03 -07:00
90 changed files with 2399 additions and 1428 deletions

View File

@@ -1,5 +1,8 @@
## Changelog ## Changelog
#### 2.631 (April, 2026)
* Fix to correctly preserve full quoted action parameters in the Fail2Ban jail editor [#2647](https://github.com/webmin/webmin/issues/2647)
#### 2.630 (March 24, 2026) #### 2.630 (March 24, 2026)
* Add improvements to user input validation across all modules * Add improvements to user input validation across all modules
* Update Authentic theme to the latest version with various improvements and fixes: * Update Authentic theme to the latest version with various improvements and fixes:

File diff suppressed because one or more lines are too long

0
bsdfdisk/change_slice_label.cgi Normal file → Executable file
View File

0
bsdfdisk/save_slice_label.cgi Normal file → Executable file
View File

0
bsdfdisk/zfs_create.cgi Normal file → Executable file
View File

0
bsdfdisk/zvol_create.cgi Normal file → Executable file
View File

View File

@@ -39,7 +39,7 @@ else {
} }
} }
print &ui_form_start("save_cron.cgi"); print &ui_form_start("save_cron.cgi", undef, undef, "id='edit_cron_form'");
print &ui_hidden("new", $in{'new'}); print &ui_hidden("new", $in{'new'});
print &ui_hidden("idx", $in{'idx'}); print &ui_hidden("idx", $in{'idx'});
print &ui_hidden("search", $in{'search'}); print &ui_hidden("search", $in{'search'});
@@ -122,41 +122,34 @@ if ($rangeable) {
} }
if (!$in{'new'}) { if (!$in{'new'}) {
# Save button my @rightbuttons;
print &ui_submit($text{'save'});
print &ui_submit($text{'edit_saverun'}, 'saverun');
print &ui_form_end();
# Run button
print "<table class='ui_table_end_submit_right'><tr>\n";
if (!$rpd) { if (!$rpd) {
print "<td>"; push(@rightbuttons,
print &ui_form_start("exec_cron.cgi"); &ui_form_start("exec_cron.cgi").
print &ui_hidden("idx", $in{'idx'}); &ui_hidden("idx", $in{'idx'}).
print &ui_submit($text{'edit_run'}); &ui_submit($text{'edit_run'}).
print &ui_form_end(); &ui_form_end(undef, undef, 1));
print "</td>\n";
} }
# Clone button push(@rightbuttons,
print "<td>"; &ui_form_start("edit_cron.cgi").
print &ui_form_start("edit_cron.cgi"); &ui_hidden("clone", $in{'idx'}).
print &ui_hidden("clone", $in{'idx'}); &ui_hidden("new", 1).
print &ui_hidden("new", 1); &ui_submit($text{'edit_clone'}).
print &ui_submit($text{'edit_clone'}); &ui_form_end(undef, undef, 1));
print &ui_form_end();
print "</td>";
# Delete button
if ($access{'delete'}) { if ($access{'delete'}) {
print "<td>"; push(@rightbuttons,
print &ui_form_start("delete_cron.cgi"); &ui_form_start("delete_cron.cgi").
print &ui_hidden("idx", $in{'idx'}); &ui_hidden("idx", $in{'idx'}).
print &ui_submit($text{'delete'}); &ui_submit($text{'delete'}).
print &ui_form_end(); &ui_form_end(undef, undef, 1));
print "</td>\n";
} }
print "</tr></table>\n"; print &ui_form_end_side_by_side(
"edit_cron_form",
[ [ undef, $text{'save'} ],
[ 'saverun', $text{'edit_saverun'} ] ],
\@rightbuttons);
} }
else { else {
print &ui_form_end([ [ undef, $text{'create'} ] ]); print &ui_form_end([ [ undef, $text{'create'} ] ]);

View File

@@ -341,7 +341,7 @@ local $ptable = &ui_columns_start([
$noquote ? ( ) : ( $text{'edit_quote'} ), $noquote ? ( ) : ( $text{'edit_quote'} ),
$text{'edit_must'}, $text{'edit_must'},
], 100, 0, undef, undef); ], 100, 0, undef, undef);
local @a = (@{$cmd->{'args'}}, { }); local @a = (@{$cmd->{'args'}}, { 'quote' => 1 });
for(my $i=0; $i<@a; $i++) { for(my $i=0; $i<@a; $i++) {
local @cols; local @cols;
push(@cols, &ui_textbox("name_$i", $a[$i]->{'name'}, 10)); push(@cols, &ui_textbox("name_$i", $a[$i]->{'name'}, 10));

View File

@@ -83,18 +83,12 @@ my $atable = &ui_columns_start([
]); ]);
my $i = 0; my $i = 0;
foreach my $a (@{$actionlist->{'words'}}, undef) { foreach my $a (@{$actionlist->{'words'}}, undef) {
my $action; my ($action, $opts) = $a ? &parse_action_definition($a) : (undef, []);
my %opts; my %opts = map { ($_->[0], $_->[1]) } @$opts;
if ($a && $a =~ /^(\S.*\S)\[(.*)\]$/) { my @oopts = grep { $_->[0] !~ /^(name|port|protocol)$/ } @$opts;
$action = $1; my $others = join("", map { $_->[2] } @oopts);
%opts = map { my ($n, $v) = split(/=/, $_); $others =~ s/^\s*,?\s*//;
$v =~ s/^"(.*)"/$1/; $others =~ s/\s*,?\s*$//;
($n, $v) } split(/,\s+/, $2);
}
else {
$action = $a;
}
my @oopts = grep { !/^(name|port|protocol)$/ } (keys %opts);
$atable .= &ui_columns_row([ $atable .= &ui_columns_row([
&ui_select("action_$i", $action, &ui_select("action_$i", $action,
[ [ "", "&nbsp;" ], [ [ "", "&nbsp;" ],
@@ -107,8 +101,7 @@ foreach my $a (@{$actionlist->{'words'}}, undef) {
[ 'tcp', 'TCP' ], [ 'tcp', 'TCP' ],
[ 'udp', 'UDP' ], [ 'udp', 'UDP' ],
[ 'icmp', 'ICMP' ] ]), [ 'icmp', 'ICMP' ] ]),
&ui_textbox("others_$i", &ui_textbox("others_$i", $others, 40),
join(" ", map { $_."=".$opts{$_} } @oopts), 40),
]); ]);
$i++; $i++;
} }

View File

@@ -222,6 +222,122 @@ while($v =~ /\S/) {
$dir->{'words'} = \@w; $dir->{'words'} = \@w;
} }
# parse_action_definition(string)
# Splits an action definition into a name and list of option triples,
# each containing a name, parsed value and raw text chunk
sub parse_action_definition
{
my ($str) = @_;
return (undef, []) if (!defined($str));
if ($str =~ /^(\S.*\S)\[(.*)\]$/) {
return ($1, [ &parse_action_options($2) ]);
}
return ($str, []);
}
# parse_action_options(string)
# Parses action options, handling quoted values and comma/space separators
sub parse_action_options
{
my ($str) = @_;
my @rv;
my $len = length($str);
my $i = 0;
while ($i < $len) {
while ($i < $len) {
my $ch = substr($str, $i, 1);
last if ($ch !~ /[\s,]/);
$i++;
}
last if ($i >= $len);
my $start = $i;
my $name = "";
while ($i < $len) {
my $ch = substr($str, $i, 1);
last if ($ch eq "=" || $ch =~ /[\s,]/);
$name .= $ch;
$i++;
}
last if (!length($name));
while ($i < $len && substr($str, $i, 1) =~ /\s/) {
$i++;
}
# Support option names without values, although most action
# parameters are expected to be name=value pairs.
if ($i >= $len || substr($str, $i, 1) ne "=") {
while ($i < $len && substr($str, $i, 1) =~ /\s/) {
$i++;
}
$i++ if ($i < $len && substr($str, $i, 1) eq ",");
push(@rv, [ $name, undef, substr($str, $start, $i - $start) ]);
next;
}
$i++;
while ($i < $len && substr($str, $i, 1) =~ /\s/) {
$i++;
}
my ($value, $ni) = &parse_action_option_value($str, $i);
push(@rv, [ $name, $value, substr($str, $start, $ni - $start) ]);
$i = $ni;
}
return @rv;
}
# parse_action_option_value(string, index)
# Returns an option value and the next parse position
sub parse_action_option_value
{
my ($str, $i) = @_;
my $len = length($str);
my $value = "";
if ($i < $len) {
my $quote = substr($str, $i, 1);
if ($quote eq "'" || $quote eq "\"") {
$i++;
while ($i < $len) {
my $ch = substr($str, $i, 1);
if ($ch eq "\\") {
if ($i+1 < $len) {
my $next = substr($str, $i+1, 1);
if ($next eq $quote || $next eq "\\") {
$value .= $next;
$i += 2;
next;
}
}
$value .= $ch;
$i++;
next;
}
if ($ch eq $quote) {
$i++;
last;
}
$value .= $ch;
$i++;
}
}
else {
while ($i < $len) {
my $ch = substr($str, $i, 1);
last if ($ch eq "," || $ch =~ /\s/);
$value .= $ch;
$i++;
}
}
}
while ($i < $len && substr($str, $i, 1) =~ /\s/) {
$i++;
}
$i++ if ($i < $len && substr($str, $i, 1) eq ",");
return ($value, $i);
}
# create_section(file, &section) # create_section(file, &section)
# Add a new section to a file # Add a new section to a file
sub create_section sub create_section

View File

@@ -28,7 +28,7 @@ foreach my $j (@jails) {
my $action_dir = &find("action", $j); my $action_dir = &find("action", $j);
my $action = ""; my $action = "";
if ($action_dir) { if ($action_dir) {
$action = join("&nbsp;|&nbsp;", $action = join(",&nbsp;",
map { /^([^\[]+)/; &html_escape("$1") } map { /^([^\[]+)/; &html_escape("$1") }
@{$action_dir->{'words'}}); @{$action_dir->{'words'}});
} }

View File

@@ -85,12 +85,15 @@ else {
if ($in{"protocol_$i"}) { if ($in{"protocol_$i"}) {
push(@opts, "protocol=".$in{"protocol_$i"}); push(@opts, "protocol=".$in{"protocol_$i"});
} }
foreach my $oo (split(/\s+/, $in{"others_$i"})) { if ($in{"others_$i"}) {
my ($n, $v) = split(/=/, $oo, 2); my $others = $in{"others_$i"};
$v = "\"$v\"" if ($v =~ /\s|,|=/ && $v !~ /['"]/); $others =~ s/^\s+//;
push(@opts, "$n=$v"); $others =~ s/\s+$//;
push(@opts, $others) if (length($others));
} }
push(@actions, $in{"action_$i"}."[".join(", ", @opts)."]"); my $action = $in{"action_$i"};
$action .= "[".join(", ", @opts)."]" if (@opts);
push(@actions, $action);
} }
# Split and validate log file paths # Split and validate log file paths

View File

@@ -1602,6 +1602,7 @@ else { return " $_[2] ".quotemeta($in{$_[0]}); }
'HFS', 'MacOS HFS', 'HFS', 'MacOS HFS',
'linux-swap', 'Linux Swap', 'linux-swap', 'Linux Swap',
'NTFS', 'Windows NTFS', 'NTFS', 'Windows NTFS',
'ntfs', 'Windows NTFS',
'reiserfs', 'ReiserFS', 'reiserfs', 'ReiserFS',
'ufs', 'FreeBSD UFS', 'ufs', 'FreeBSD UFS',
); );

View File

@@ -1,70 +1,120 @@
require 'filemin-lib.pl'; require 'filemin-lib.pl';
sub acl_security_form { # acl_security_form(&access)
my ($access) = @_; # Output HTML for ACL security form fields
sub acl_security_form
{
my ($access) = @_;
# Directories the user can access # Directories the user can access
print &ui_table_row($text{'acl_allowed_paths'} . print &ui_table_row(
&ui_help($text{'acl_allowed_paths_explain'}), $text{'acl_allowed_paths'} .
ui_textarea("allowed_paths", &ui_help($text{'acl_allowed_paths_explain'}),
join("\n", split(/\s+/, $access->{'allowed_paths'})), ui_textarea(
10, 80, undef, undef, "style='width: 100%'"), 2); "allowed_paths",
join("\n",
split(/\s+/,
$access->{'allowed_paths'})),
10, 80, undef, undef,
"style='width: 100%'"),
2);
# Mimetypes allowed to be edited # Mimetypes allowed to be edited
print &ui_table_row($text{'acl_allowed_for_edit'}, print &ui_table_row(
ui_textarea("allowed_for_edit", $text{'acl_allowed_for_edit'},
join("\n", split(/\s+/, $access->{'allowed_for_edit'})), ui_textarea(
10, 80, undef, undef, "style='width: 100%'"), 2); "allowed_for_edit",
join("\n",
split(/\s+/,
$access->{'allowed_for_edit'})),
10, 80, undef, undef,
"style='width: 100%'"),
2);
# Run as Unix user # Run as Unix user
print &ui_table_row($text{'acl_work_as'}, print &ui_table_row(
ui_radio_table("user_mode", $access->{'work_as_root'} ? 0 : $text{'acl_work_as'},
$access->{'work_as_user'} ? 2 : 1, ui_radio_table(
[ [ 0, $text{'acl_root'} ], "user_mode",
[ 1, $text{'acl_same'} ], $access->{'work_as_root'} ? 0 :
[ 2, $text{'acl_user'}, $access->{'work_as_user'} ? 2 : 1,
ui_user_textbox("acl_user", $access->{'work_as_user'})."&nbsp;". [ [ 0, $text{'acl_root'} ],
&ui_checkbox("acl_user_strict", 1, $text{'acl_user_strict'}. [ 1, $text{'acl_same'} ],
&ui_help($text{'acl_user_strict_desc'}), [ 2, $text{'acl_user'},
$access->{'work_as_user_strict'}) ] ]), ui_user_textbox(
"acl_user",
$access->{'work_as_user'}) .
"&nbsp;" .
&ui_checkbox(
"acl_user_strict", 1,
$text{'acl_user_strict'} .
&ui_help(
$text{'acl_user_strict_desc'}),
$access->{'work_as_user_strict'}) ] ]),
3); 3);
# Upload max # Upload max
print &ui_table_row($text{'acl_max'}, print &ui_table_row(
&ui_opt_textbox("max", $access->{'max'}, 10, $text{'acl_unlimited'}). $text{'acl_max'},
" ".$text{'acl_bytes'}, 3); &ui_opt_textbox(
"max", $access->{'max'}, 10,
$text{'acl_unlimited'}) .
" " . $text{'acl_bytes'},
3);
} }
sub acl_security_save { # acl_security_save(&access, &in)
my ($access, $in) = @_; # Parse the ACL security form and save values
local @allowed_paths = split(/\s+/, $in->{'allowed_paths'}); sub acl_security_save
if (scalar(@allowed_paths) == 0) { &error("No allowed paths defined"); } {
for $path(@allowed_paths) { my ($access, $in) = @_;
if (!-e $path && $path ne '$HOME' && $path ne '$ROOT') { local @allowed_paths =
&error(&text('acl_epath', &html_escape($path))); split(/\s+/, $in->{'allowed_paths'});
} if (scalar(@allowed_paths) == 0) {
} &error("No allowed paths defined");
$access->{'allowed_paths'} = join(" ", @allowed_paths); }
for $path (@allowed_paths) {
if (!-e $path && $path ne '$HOME' &&
$path ne '$ROOT') {
&error(&text('acl_epath',
&html_escape($path)));
}
}
$access->{'allowed_paths'} =
join(" ", @allowed_paths);
local @allowed_for_edit = split(/\s+/, $in->{'allowed_for_edit'}); local @allowed_for_edit =
if (scalar(@allowed_for_edit) == 0) { &error("No mimetypes allowed for edit defined"); } split(/\s+/, $in->{'allowed_for_edit'});
$access->{'allowed_for_edit'} = join(" ", @allowed_for_edit); if (scalar(@allowed_for_edit) == 0) {
&error("No mimetypes allowed for ".
"edit defined");
}
$access->{'allowed_for_edit'} =
join(" ", @allowed_for_edit);
if ($in->{'user_mode'} == 0) { if ($in->{'user_mode'} == 0) {
$access->{'work_as_root'} = 1; $access->{'work_as_root'} = 1;
$access->{'work_as_user'} = undef; $access->{'work_as_user'} = undef;
} elsif ($in->{'user_mode'} == 1) { }
$access->{'work_as_root'} = 0; elsif ($in->{'user_mode'} == 1) {
$access->{'work_as_user'} = undef; $access->{'work_as_root'} = 0;
} else { $access->{'work_as_user'} = undef;
defined(getpwnam($in->{'acl_user'})) || &error($text{'acl_euser'}); }
$access->{'work_as_root'} = 0; else {
$access->{'work_as_user'} = $in->{'acl_user'}; defined(getpwnam($in->{'acl_user'})) ||
$access->{'work_as_user_strict'} = $in->{'acl_user_strict'}; &error($text{'acl_euser'});
} $access->{'work_as_root'} = 0;
$access->{'max'} = $in->{'max_def'} ? undef : $in{'max'}; $access->{'work_as_user'} = $in->{'acl_user'};
$access->{'work_as_user_strict'} =
$in->{'acl_user_strict'};
}
$access->{'max'} =
$in->{'max_def'} ? undef : $in{'max'};
} }
sub acl_security_noconfig { # acl_security_noconfig()
return 1; # Returns 1 to indicate no module config is needed
sub acl_security_noconfig
{
return 1;
} }

View File

@@ -6,9 +6,9 @@ require './filemin-lib.pl';
&get_paths(); &get_paths();
if(!-e "$confdir/.bookmarks") { if (!-e "$confdir/.bookmarks") {
utime time, time, "$configdir/.bookmarks"; utime time, time, "$configdir/.bookmarks";
} }
$bookmarks = &read_file_lines($confdir.'/.bookmarks'); $bookmarks = &read_file_lines($confdir.'/.bookmarks');
push @$bookmarks, $path; push @$bookmarks, $path;

View File

@@ -7,42 +7,45 @@ require './filemin-lib.pl';
get_paths(); get_paths();
my $recursive; my $recursive;
if ($in{'recursive'} eq 'true') {
if ( $in{'recursive'} eq 'true' ) { $recursive = '-R'; } $recursive = '-R';
else { $recursive = ''; } }
else {
$recursive = '';
}
my @errors; my @errors;
if ( !$in{'label'} ) { if (!$in{'label'}) {
push @errors, "$text{'attr_label_error'}"; push @errors, "$text{'attr_label_error'}";
} }
my $label = quotemeta("$in{'label'}"); my $label = quotemeta("$in{'label'}");
$label =~ s/\\-/-/g; $label =~ s/\\-/-/g;
$label =~ s/\\+//g; $label =~ s/\\+//g;
$label =~ tr/a-zA-Z\-\+ //dc; $label =~ tr/a-zA-Z\-\+ //dc;
if ( scalar(@errors) > 0 ) { if (scalar(@errors) > 0) {
print_errors(@errors); print_errors(@errors);
} }
else { else {
foreach my $file ( split( /\0/, $in{'name'} ) ) { foreach my $file (split(/\0/, $in{'name'})) {
$file =~ s/\.\.//g; $file =~ s/\.\.//g;
$file = &simplify_path($file); $file = &simplify_path($file);
if ( if (system_logged(
system_logged( "chattr $recursive ".$label.
"chattr $recursive " . $label . " " . quotemeta("$cwd/$file") " ".quotemeta("$cwd/$file")
) != 0 ) != 0) {
) push @errors,
{ (html_escape($file).
push @errors, " - $text{'attr_label_error_proc'}: $?");
( html_escape($file) . " - $text{'attr_label_error_proc'}: $?" ); }
} }
}
if ( scalar(@errors) > 0 ) { if (scalar(@errors) > 0) {
print_errors(@errors); print_errors(@errors);
} }
else { else {
&redirect("index.cgi?path=".&urlize($path)); &redirect(
} "index.cgi?path=".&urlize($path));
} }
}

View File

@@ -7,41 +7,42 @@ require './filemin-lib.pl';
get_paths(); get_paths();
my $recursive; my $recursive;
if ($in{'recursive'} eq 'true') {
if ( $in{'recursive'} eq 'true' ) { $recursive = '-R'; } $recursive = '-R';
else { $recursive = ''; } }
else {
$recursive = '';
}
my @errors; my @errors;
if ( !$in{'label'} ) { if (!$in{'label'}) {
push @errors, "$text{'context_label_error'}"; push @errors, "$text{'context_label_error'}";
} }
if ( scalar(@errors) > 0 ) { if (scalar(@errors) > 0) {
print_errors(@errors); print_errors(@errors);
} }
else { else {
foreach my $file ( split( /\0/, $in{'name'} ) ) { foreach my $file (split(/\0/, $in{'name'})) {
$file =~ s/\.\.//g; $file =~ s/\.\.//g;
$file = &simplify_path($file); $file = &simplify_path($file);
if ( if (system_logged(
system_logged( "chcon $recursive ".
"chcon $recursive " quotemeta($in{'label'}).
. quotemeta( $in{'label'} ) . " " " ".quotemeta("$cwd/$file")
. quotemeta("$cwd/$file") ) != 0) {
) != 0 push @errors,
) (html_escape($file).
{ " - $text{'context_label_error_proc'}: $?");
push @errors, }
( html_escape($file) }
. " - $text{'context_label_error_proc'}: $?" );
}
}
if ( scalar(@errors) > 0 ) { if (scalar(@errors) > 0) {
print_errors(@errors); print_errors(@errors);
} }
else { else {
&redirect("index.cgi?path=".&urlize($path)); &redirect(
} "index.cgi?path=".&urlize($path));
} }
}

View File

@@ -11,68 +11,114 @@ my @errors;
my $perms = $in{'perms'}; my $perms = $in{'perms'};
# Selected directories and files only # Selected directories and files only
if($in{'applyto'} eq '1') { if ($in{'applyto'} eq '1') {
foreach $name (split(/\0/, $in{'name'})) { foreach $name (split(/\0/, $in{'name'})) {
if (system_logged("chmod ".quotemeta($perms)." ".quotemeta("$cwd/$name")) != 0) { if (system_logged(
push @errors, "$name - $text{'error_chmod'}: $?"; "chmod " . quotemeta($perms) . " " .
} quotemeta("$cwd/$name")) != 0) {
} push @errors,
} "$name - $text{'error_chmod'}: $?";
}
}
}
# Selected files and directories and files in selected directories # Selected files and directories and files in
if($in{'applyto'} eq '2') { # selected directories
foreach $name (split(/\0/, $in{'name'})) { if ($in{'applyto'} eq '2') {
if(system_logged("chmod ".quotemeta($perms)." ".quotemeta("$cwd/$name")) != 0) { foreach $name (split(/\0/, $in{'name'})) {
push @errors, "$name - $text{'error_chmod'}: $?"; if (system_logged(
} "chmod " . quotemeta($perms) . " " .
if(-d "$cwd/$name") { quotemeta("$cwd/$name")) != 0) {
if(system_logged("find ".quotemeta("$cwd/$name")." -maxdepth 1 -type f -exec chmod ".quotemeta($perms)." {} \\;") != 0) { push @errors,
push @errors, "$name - $text{'error_chmod'}: $?"; "$name - $text{'error_chmod'}: $?";
} }
} if (-d "$cwd/$name") {
} if (system_logged(
} "find " .
quotemeta("$cwd/$name") .
" -maxdepth 1 -type f" .
" -exec chmod " .
quotemeta($perms) .
" {} \\;") != 0) {
push @errors,
"$name - " .
"$text{'error_chmod'}: $?";
}
}
}
}
# All (recursive) # All (recursive)
if($in{'applyto'} eq '3') { if ($in{'applyto'} eq '3') {
foreach $name (split(/\0/, $in{'name'})) { foreach $name (split(/\0/, $in{'name'})) {
if(system_logged("chmod -R ".quotemeta($perms)." ".quotemeta("$cwd/$name")) != 0) { if (system_logged(
push @errors, "$name - $text{'error_chmod'}: $?"; "chmod -R " . quotemeta($perms) .
} " " .
} quotemeta("$cwd/$name")) != 0) {
} push @errors,
"$name - $text{'error_chmod'}: $?";
}
}
}
# Selected files and files under selected directories and subdirectories # Selected files and files under selected directories
if($in{'applyto'} eq '4') { # and subdirectories
foreach $name (split(/\0/, $in{'name'})) { if ($in{'applyto'} eq '4') {
if(-f "$cwd/$name") { foreach $name (split(/\0/, $in{'name'})) {
if(system_logged("chmod ".quotemeta($perms)." ".quotemeta("$cwd/$name")) != 0) { if (-f "$cwd/$name") {
push @errors, "$name - $text{'error_chmod'}: $?"; if (system_logged(
} "chmod " .
} else { quotemeta($perms) . " " .
if(system_logged("find ".quotemeta("$cwd/$name")." -type f -exec chmod ".quotemeta($perms)." {} \\;") != 0) { quotemeta("$cwd/$name")) != 0) {
push @errors, "$name - $text{'error_chmod'}: $?"; push @errors,
} "$name - " .
} "$text{'error_chmod'}: $?";
} }
} }
else {
if (system_logged(
"find " .
quotemeta("$cwd/$name") .
" -type f -exec chmod " .
quotemeta($perms) .
" {} \\;") != 0) {
push @errors,
"$name - " .
"$text{'error_chmod'}: $?";
}
}
}
}
# Selected directories and subdirectories # Selected directories and subdirectories
if($in{'applyto'} eq '5') { if ($in{'applyto'} eq '5') {
foreach $name (split(/\0/, $in{'name'})) { foreach $name (split(/\0/, $in{'name'})) {
if(-d "$cwd/$name") { if (-d "$cwd/$name") {
if(system_logged("chmod ".quotemeta($perms)." ".quotemeta("$cwd/$name")) != 0) { if (system_logged(
push @errors, "$name - $text{'error_chmod'}: $?"; "chmod " .
} quotemeta($perms) . " " .
if(system_logged("find ".quotemeta("$cwd/$name")." -type d -exec chmod ".quotemeta($perms)." {} \\;") != 0) { quotemeta("$cwd/$name")) != 0) {
push @errors, "$name - $text{'error_chmod'}: $?"; push @errors,
} "$name - " .
} "$text{'error_chmod'}: $?";
} }
} if (system_logged(
"find " .
quotemeta("$cwd/$name") .
" -type d -exec chmod " .
quotemeta($perms) .
" {} \\;") != 0) {
push @errors,
"$name - " .
"$text{'error_chmod'}: $?";
}
}
}
}
if (scalar(@errors) > 0) { if (scalar(@errors) > 0) {
print_errors(@errors); print_errors(@errors);
} else { }
&redirect("index.cgi?path=".&urlize($path)); else {
} &redirect("index.cgi?path=" . &urlize($path));
}

View File

@@ -10,7 +10,8 @@ if (!$in{'owner'} || !$in{'group'}) {
&redirect("index.cgi?path=".&urlize($path)); &redirect("index.cgi?path=".&urlize($path));
} }
(my $login, my $pass, my $uid, my $gid) = getpwnam($in{'owner'}); (my $login, my $pass, my $uid, my $gid) =
getpwnam($in{'owner'});
my $grid = getgrnam($in{'group'}); my $grid = getgrnam($in{'group'});
my $recursive; my $recursive;
if ($in{'recursive'} eq 'true') { if ($in{'recursive'} eq 'true') {
@@ -23,11 +24,15 @@ else {
my @errors; my @errors;
if (!defined($login)) { if (!defined($login)) {
push @errors, "<b>".&html_escape($in{'owner'})."</b> $text{'error_user_not_found'}"; push @errors,
"<b>".&html_escape($in{'owner'})."</b> ".
$text{'error_user_not_found'};
} }
if (!defined($grid)) { if (!defined($grid)) {
push @errors, "<b>".&html_escape($in{'group'})."</b> $text{'error_group_not_found'}"; push @errors,
"<b>".&html_escape($in{'group'})."</b> ".
$text{'error_group_not_found'};
} }
if (scalar(@errors) > 0) { if (scalar(@errors) > 0) {
@@ -35,15 +40,19 @@ if (scalar(@errors) > 0) {
} }
else { else {
foreach $name (split(/\0/, $in{'name'})) { foreach $name (split(/\0/, $in{'name'})) {
if (system_logged("chown $recursive $uid:$grid ". if (system_logged(
quotemeta("$cwd/$name")) != 0) { "chown $recursive $uid:$grid ".
push @errors, "$name - $text{'error_chown'}: $?"; quotemeta("$cwd/$name")) != 0) {
push @errors,
"$name - " .
"$text{'error_chown'}: $?";
} }
} }
if (scalar(@errors) > 0) { if (scalar(@errors) > 0) {
print_errors(@errors); print_errors(@errors);
} }
else { else {
&redirect("index.cgi?path=".&urlize($path)); &redirect(
"index.cgi?path=".&urlize($path));
} }
} }

View File

@@ -4,7 +4,7 @@ require './filemin-lib.pl';
&ReadParse(); &ReadParse();
get_paths(); get_paths();
if(!$in{'arch'}) { if (!$in{'arch'}) {
&redirect("index.cgi?path=".&urlize($path)); &redirect("index.cgi?path=".&urlize($path));
return; return;
} }
@@ -13,23 +13,29 @@ my $command;
if ($in{'method'} eq 'plain-tar') { if ($in{'method'} eq 'plain-tar') {
$full = "$cwd/$in{'arch'}.tar"; $full = "$cwd/$in{'arch'}.tar";
$command = "tar cf ".quotemeta($full)." -C ".quotemeta($cwd); $command = "tar cf ".quotemeta($full).
" -C ".quotemeta($cwd);
} }
elsif ($in{'method'} eq 'xz-tar') { elsif ($in{'method'} eq 'xz-tar') {
$full = "$cwd/$in{'arch'}.tar.xz"; $full = "$cwd/$in{'arch'}.tar.xz";
$command = "tar cJf ".quotemeta($full)." -C ".quotemeta($cwd); $command = "tar cJf ".quotemeta($full).
" -C ".quotemeta($cwd);
} }
elsif ($in{'method'} eq 'zstd-tar') { elsif ($in{'method'} eq 'zstd-tar') {
$full = "$cwd/$in{'arch'}.zst"; $full = "$cwd/$in{'arch'}.zst";
$command = "ZSTD_CLEVEL=19 tar --zstd -cf ".quotemeta($full)." -C ".quotemeta($cwd); $command = "ZSTD_CLEVEL=19 tar --zstd -cf ".
quotemeta($full).
" -C ".quotemeta($cwd);
} }
elsif ($in{'method'} eq 'tar') { elsif ($in{'method'} eq 'tar') {
$full = "$cwd/$in{'arch'}.tar.gz"; $full = "$cwd/$in{'arch'}.tar.gz";
$command = "tar czf ".quotemeta($full)." -C ".quotemeta($cwd); $command = "tar czf ".quotemeta($full).
" -C ".quotemeta($cwd);
} }
elsif ($in{'method'} eq 'zip') { elsif ($in{'method'} eq 'zip') {
$full = "$cwd/$in{'arch'}.zip"; $full = "$cwd/$in{'arch'}.zip";
$command = "cd ".quotemeta($cwd)." && zip -r ".quotemeta($full); $command = "cd ".quotemeta($cwd).
" && zip -r ".quotemeta($full);
} }
else { else {
&error("Unknown method!"); &error("Unknown method!");
@@ -43,7 +49,8 @@ foreach my $name (split(/\0/, $in{'name'})) {
my @st = stat($cwd); my @st = stat($cwd);
&system_logged($command); &system_logged($command);
if ($newfile) { if ($newfile) {
&set_ownership_permissions($st[4], $st[5], undef, $full); &set_ownership_permissions(
$st[4], $st[5], undef, $full);
} }
&redirect("index.cgi?path=".&urlize($path)); &redirect("index.cgi?path=".&urlize($path));

View File

@@ -7,43 +7,93 @@ require './filemin-lib.pl';
get_paths(); get_paths();
&ui_print_header(&text('config_dir', $module_info{'desc'}), &ui_print_header(&text('config_dir', $module_info{'desc'}),
$text{'config_title'}, "", $help, 0, 1); $text{'config_title'}, "", $help, 0, 1);
$head = "<link rel='stylesheet' type='text/css' href='unauthenticated/css/style.css' />"; $head = "<link rel='stylesheet' type='text/css' " .
"href='unauthenticated/css/style.css' />";
print $head; print $head;
if(!-e "$confdir/.config") { if (!-e "$confdir/.config") {
&read_file("$module_root_directory/defaultuconf", \%config); &read_file("$module_root_directory/defaultuconf",
} else { \%config);
&read_file("$confdir/.config", \%config); }
} else {
&read_file("$confdir/.config", \%config);
}
# Load module config user custom manually due to non-standard config # Load module config user custom manually due to
# non-standard config
&load_module_preferences($module_name, \%config); &load_module_preferences($module_name, \%config);
if(!-e "$confdir/.bookmarks") { my $detect_encoding =
$bookmarks = ''; $config{
} else { 'config_portable_module_filemanager_editor_detect_encoding'}
$bookmarks = &read_file_contents($confdir.'/.bookmarks', 1); ne 'false' ? 'true' : 'false';
} my $show_hidden_files =
$config{
'config_portable_module_filemanager_show_dot_files'}
ne 'false' ? 'true' : 'false';
if (!-e "$confdir/.bookmarks") {
$bookmarks = '';
}
else {
$bookmarks =
&read_file_contents($confdir . '/.bookmarks', 1);
}
print &ui_form_start("save_config.cgi", "post"); print &ui_form_start("save_config.cgi", "post");
print &ui_table_start(&text('config_header', $module_info{'desc'}), print &ui_table_start(
"width=100%", 2); &text('config_header', $module_info{'desc'}),
"width=100%", 2);
print &ui_table_row($text{'config_columns_to_display'}, print &ui_table_row($text{'config_columns_to_display'},
&ui_checkbox('columns', 'type', $text{'type'}, $config{'columns'} =~ /type/). &ui_checkbox(
&ui_checkbox('columns', 'size', $text{'size'}, $config{'columns'} =~ /size/). 'columns', 'type', $text{'type'},
&ui_checkbox('columns', 'owner_user', $text{'ownership'}, $config{'columns'} =~ /owner_user/). $config{'columns'} =~ /type/) .
&ui_checkbox('columns', 'permissions', $text{'permissions'}, $config{'columns'} =~ /permissions/). &ui_checkbox(
(get_acls_status() ? &ui_checkbox('columns', 'acls', $text{'acls'}, $config{'columns'} =~ /acls/) : undef). 'columns', 'size', $text{'size'},
(get_attr_status() ? &ui_checkbox('columns', 'attributes', $text{'attributes'}, $config{'columns'} =~ /attributes/) : undef). $config{'columns'} =~ /size/) .
(get_selinux_status() ? &ui_checkbox('columns', 'selinux', $text{'selinux'}, $config{'columns'} =~ /selinux/) : undef). &ui_checkbox(
&ui_checkbox('columns', 'last_mod_time', $text{'last_mod_time'}, $config{'columns'} =~ /last_mod_time/) 'columns', 'owner_user', $text{'ownership'},
$config{'columns'} =~ /owner_user/) .
&ui_checkbox(
'columns', 'permissions', $text{'permissions'},
$config{'columns'} =~ /permissions/) .
(get_acls_status() ? &ui_checkbox(
'columns', 'acls', $text{'acls'},
$config{'columns'} =~ /acls/) : undef) .
(get_attr_status() ? &ui_checkbox(
'columns', 'attributes',
$text{'attributes'},
$config{'columns'} =~ /attributes/)
: undef) .
(get_selinux_status() ? &ui_checkbox(
'columns', 'selinux', $text{'selinux'},
$config{'columns'} =~ /selinux/)
: undef) .
&ui_checkbox(
'columns', 'last_mod_time',
$text{'last_mod_time'},
$config{'columns'} =~ /last_mod_time/)
); );
print &ui_table_row($text{'config_per_page'}, ui_textbox("per_page", $config{'per_page'}, 80)); print &ui_table_row(
print &ui_table_row($text{'file_detect_encoding'}, &ui_yesno_radio('config_portable_module_filemanager_editor_detect_encoding', $config{'config_portable_module_filemanager_editor_detect_encoding'} ne 'false' ? 'true' : 'false', 'true', 'false')); $text{'config_per_page'},
print &ui_table_row($text{'file_showhiddenfiles'}, &ui_yesno_radio('config_portable_module_filemanager_show_dot_files', $config{'config_portable_module_filemanager_show_dot_files'} ne 'false' ? 'true' : 'false', 'true', 'false')); ui_textbox("per_page", $config{'per_page'}, 80));
print &ui_table_row($text{'config_bookmarks'}, &ui_textarea("bookmarks", $bookmarks, 5, 40)); print &ui_table_row(
$text{'file_detect_encoding'},
&ui_yesno_radio(
'config_portable_module_filemanager_editor_detect_encoding',
$detect_encoding,
'true', 'false'));
print &ui_table_row(
$text{'file_showhiddenfiles'},
&ui_yesno_radio(
'config_portable_module_filemanager_show_dot_files',
$show_hidden_files,
'true', 'false'));
print &ui_table_row(
$text{'config_bookmarks'},
&ui_textarea("bookmarks", $bookmarks, 5, 40));
print &ui_table_end(); print &ui_table_end();
@@ -51,4 +101,5 @@ print &ui_hidden('path', $path);
print &ui_form_end([ [ save, $text{'save'} ] ]); print &ui_form_end([ [ save, $text{'save'} ] ]);
&ui_print_footer("index.cgi?path=".&urlize($path), $text{'previous_page'}); &ui_print_footer("index.cgi?path=" . &urlize($path),
$text{'previous_page'});

View File

@@ -11,8 +11,8 @@ print $fh "$path\n";
#$info = "Copied ".scalar(@list)." files to buffer"; #$info = "Copied ".scalar(@list)." files to buffer";
foreach $name (split(/\0/, $in{'name'})) { foreach $name (split(/\0/, $in{'name'})) {
print $fh "$name\n"; print $fh "$name\n";
} }
close($fh); close($fh);

View File

@@ -12,18 +12,21 @@ if (!$in{'name'}) {
my $full = "$cwd/$in{'name'}"; my $full = "$cwd/$in{'name'}";
if (-e $full) { if (-e $full) {
print_errors(&html_escape($in{'name'})." ".$text{'error_exists'}); print_errors(&html_escape($in{'name'}).
" ".$text{'error_exists'});
} }
else { else {
my @st = stat($cwd); my @st = stat($cwd);
if (open(my $fh, ">$full")) { if (open(my $fh, ">$full")) {
close($fh); close($fh);
&set_ownership_permissions($st[4], $st[5], undef, $full); &set_ownership_permissions(
&redirect("index.cgi?path=".&urlize($path)); $st[4], $st[5], undef, $full);
&redirect("index.cgi?path=".
&urlize($path));
} }
else { else {
print_errors($text{'error_create'}." ". print_errors($text{'error_create'}." ".
&html_escape($in{'name'})." : ".$!); &html_escape($in{'name'}).
" : ".$!);
} }
} }

View File

@@ -12,17 +12,20 @@ if (!$in{'name'}) {
my $full = "$cwd/$in{'name'}"; my $full = "$cwd/$in{'name'}";
if (-e $full) { if (-e $full) {
print_errors(&html_escape($in{'name'})." ".$text{'error_exists'}); print_errors(&html_escape($in{'name'}).
" ".$text{'error_exists'});
} }
else { else {
my @st = stat($cwd); my @st = stat($cwd);
if (&make_dir($full, oct(755)) ) { if (&make_dir($full, oct(755))) {
&set_ownership_permissions($st[4], $st[5], undef, $full); &set_ownership_permissions(
&redirect("index.cgi?path=".&urlize($path)); $st[4], $st[5], undef, $full);
&redirect("index.cgi?path=".
&urlize($path));
} }
else { else {
print_errors($text{'error_create'}." ". print_errors($text{'error_create'}." ".
&html_escape($in{'name'})." : ".$!); &html_escape($in{'name'}).
" : ".$!);
} }
} }

View File

@@ -11,8 +11,8 @@ print $fh "$path\n";
#$info = "Copied ".scalar(@list)." files to buffer"; #$info = "Copied ".scalar(@list)." files to buffer";
foreach $name (split(/\0/, $in{'name'})) { foreach $name (split(/\0/, $in{'name'})) {
print $fh "$name\n"; print $fh "$name\n";
} }
close($fh); close($fh);

View File

@@ -8,17 +8,20 @@ get_paths();
my @errors; my @errors;
foreach $name (split(/\0/, $in{'name'})) { foreach $name (split(/\0/, $in{'name'})) {
if(!can_write($cwd.'/'.$name)) { if (!can_write($cwd.'/'.$name)) {
push @errors, "$name - $text{'error_write'}"; push @errors,
next; "$name - $text{'error_write'}";
} next;
if(!&unlink_file($cwd.'/'.$name)) { }
push @errors, "$name - $text{'error_delete'}: $!"; if (!&unlink_file($cwd.'/'.$name)) {
} push @errors,
} "$name - $text{'error_delete'}: $!";
}
}
if (scalar(@errors) > 0) { if (scalar(@errors) > 0) {
print_errors(@errors); print_errors(@errors);
} else { }
&redirect("index.cgi?path=".&urlize($path)); else {
} &redirect("index.cgi?path=".&urlize($path));
}

View File

@@ -9,24 +9,28 @@ use Cwd 'abs_path';
get_paths(); get_paths();
my $file = &resolve_links(&simplify_path($cwd.'/'.$in{'file'})); my $file = &resolve_links(
&simplify_path($cwd.'/'.$in{'file'}));
my $error = 1; my $error = 1;
for $allowed_path (@allowed_paths) { for $allowed_path (@allowed_paths) {
if (&is_under_directory($allowed_path, $file)) { if (&is_under_directory($allowed_path, $file)) {
$error = 0; $error = 0;
} }
} }
$error && &error(&text('notallowed', &html_escape($file), $error && &error(&text('notallowed',
&html_escape(join(" , ", @allowed_paths)))); &html_escape($file),
&html_escape(join(" , ", @allowed_paths))));
my $size = -s "$file"; my $size = -s "$file";
(my $name, my $dir, my $ext) = fileparse($file, qr/\.[^.]*/); (my $name, my $dir, my $ext) =
fileparse($file, qr/\.[^.]*/);
print "Content-Type: application/x-download\n"; print "Content-Type: application/x-download\n";
print "Content-Disposition: attachment; filename=\"$name$ext\"\n"; print "Content-Disposition: attachment; ".
"filename=\"$name$ext\"\n";
print "Content-Length: $size\n\n"; print "Content-Length: $size\n\n";
open (FILE, "< $file") or die "can't open $file: $!"; open(FILE, "< $file") or die "can't open $file: $!";
binmode FILE; binmode FILE;
local $/ = \&get_buffer_size_binary(); local $/ = \&get_buffer_size_binary();
while (<FILE>) { while (<FILE>) {
print $_; print $_;
} }
close FILE; close FILE;

View File

@@ -8,39 +8,61 @@ get_paths();
my $file = &simplify_path($cwd . '/' . $in{'file'}); my $file = &simplify_path($cwd . '/' . $in{'file'});
&check_allowed_path($file); &check_allowed_path($file);
my $data = &ui_read_file_contents_limit( my $data = &ui_read_file_contents_limit(
{ 'file', $file, { 'file', $file,
'limit', $in{'limit'}, 'limit', $in{'limit'},
'reverse', $in{'reverse'}, 'reverse', $in{'reverse'},
'head', $in{'head'}, 'head', $in{'head'},
'tail', $in{'tail'} 'tail', $in{'tail'}
}); });
my $encoding_name; my $encoding_name;
eval "use Encode::Detect::Detector;"; eval "use Encode::Detect::Detector;";
if (!$@) { if (!$@) {
$encoding_name = Encode::Detect::Detector::detect($data); $encoding_name =
} Encode::Detect::Detector::detect($data);
if ($userconfig{'config_portable_module_filemanager_editor_detect_encoding'} ne 'false') { }
my $forced = ($data =~ /(.*\n)(.*\n)(.*\n)/); if ($userconfig{
$forced = (($1 . $2 . $3) =~ /coding[=:]\s*([-\w.]+)/); 'config_portable_module_filemanager_editor_detect_encoding'
if ((lc(get_charset()) eq "utf-8" && ($encoding_name && lc($encoding_name) ne "utf-8")) || $forced) { } ne 'false') {
if ($forced) { my $forced = ($data =~ /(.*\n)(.*\n)(.*\n)/);
$encoding_name = "$1"; $forced = (($1 . $2 . $3) =~ /coding[=:]\s*([-\w.]+)/);
} if ((lc(get_charset()) eq "utf-8" &&
eval {$data = Encode::encode('utf-8', Encode::decode($encoding_name, $data))}; ($encoding_name &&
} lc($encoding_name) ne "utf-8")) ||
} $forced) {
if ($forced) {
$encoding_name = "$1";
}
eval {
$data = Encode::encode(
'utf-8',
Encode::decode(
$encoding_name, $data))
};
}
}
my $file_binary = -s $file >= 128 && -B $file; my $file_binary = -s $file >= 128 && -B $file;
my %tinfo = &get_theme_info($current_theme); my %tinfo = &get_theme_info($current_theme);
&ui_print_header(undef, $text{'edit_file'}, ""); &ui_print_header(undef, $text{'edit_file'}, "");
print "<style>textarea {padding: 4px;}</style>" print "<style>textarea {padding: 4px;}</style>"
if (!$tinfo{'bootstrap'}); if (!$tinfo{'bootstrap'});
print &ui_table_start(&html_escape("$path/$in{'file'}"), "width=100%;", 1); print &ui_table_start(
print &ui_form_start("save_file.cgi", "post", undef, "data-encoding=\"$encoding_name\" data-binary=\"$file_binary\""); &html_escape("$path/$in{'file'}"),
"width=100%;", 1);
print &ui_form_start(
"save_file.cgi", "post", undef,
"data-encoding=\"$encoding_name\" " .
"data-binary=\"$file_binary\"");
print &ui_hidden("file", $in{'file'}), "\n"; print &ui_hidden("file", $in{'file'}), "\n";
print &ui_hidden("encoding", $encoding_name), "\n"; print &ui_hidden("encoding", $encoding_name), "\n";
print &ui_textarea("data", $data, 30, undef, undef, undef, " style='width: 100%' id='data'"); print &ui_textarea(
"data", $data, 30, undef, undef, undef,
" style='width: 100%' id='data'");
print &ui_hidden("path", $path); print &ui_hidden("path", $path);
print &ui_form_end([[save, $text{'save'}], [save_close, $text{'save_close'}]]); print &ui_form_end(
[[save, $text{'save'}],
[save_close, $text{'save_close'}]]);
print &ui_table_end(); print &ui_table_end();
&ui_print_footer("index.cgi?path=" . &urlize($path), $text{'previous_page'}); &ui_print_footer(
"index.cgi?path=" . &urlize($path),
$text{'previous_page'});

View File

@@ -9,37 +9,50 @@ get_paths();
$archive_type = clean_mimetype($cwd.'/'.$in{'file'}); $archive_type = clean_mimetype($cwd.'/'.$in{'file'});
if ($archive_type =~ /x-bzip/) { if ($archive_type =~ /x-bzip/) {
$cmd = "tar xvjfp ".quotemeta("$cwd/$in{'file'}"). $cmd = "tar xvjfp ".
" -C ".quotemeta($cwd); quotemeta("$cwd/$in{'file'}").
" -C ".quotemeta($cwd);
} }
elsif ($archive_type =~ /x-tar|\/gzip|x-xz|zstd|x-compressed-tar/) { elsif ($archive_type =~
$cmd = "tar xfp ".quotemeta("$cwd/$in{'file'}"). /x-tar|\/gzip|x-xz|zstd|x-compressed-tar/) {
" -C ".quotemeta($cwd); $cmd = "tar xfp ".
quotemeta("$cwd/$in{'file'}").
" -C ".quotemeta($cwd);
} }
elsif ($archive_type =~ /x-7z/ || elsif ($archive_type =~ /x-7z/ ||
$archive_type =~ /x-raw-disk-image/ || $archive_type =~ /x-raw-disk-image/ ||
$archive_type =~ /x-cd-image/) { $archive_type =~ /x-cd-image/) {
$cmd = "7z x ".quotemeta("$cwd/$in{'file'}")." -o" .quotemeta($cwd); $cmd = "7z x ".
quotemeta("$cwd/$in{'file'}").
" -o".quotemeta($cwd);
} }
elsif ($archive_type =~ /\/zip/) { elsif ($archive_type =~ /\/zip/) {
my $unzip_out = `unzip --help`; my $unzip_out = `unzip --help`;
my $uu = ($unzip_out =~ /-UU/ ? '-UU' : undef); my $uu = ($unzip_out =~ /-UU/ ? '-UU' : undef);
$cmd = "unzip $uu -q -o ".quotemeta("$cwd/$in{'file'}")." -d ".quotemeta($cwd); $cmd = "unzip $uu -q -o ".
quotemeta("$cwd/$in{'file'}").
" -d ".quotemeta($cwd);
} }
elsif ($archive_type =~ /\/x-rar|\/vnd\.rar/) { elsif ($archive_type =~ /\/x-rar|\/vnd\.rar/) {
$cmd = "unrar x -r -y ".quotemeta("$cwd/$in{'file'}"). $cmd = "unrar x -r -y ".
" ".quotemeta($cwd); quotemeta("$cwd/$in{'file'}").
" ".quotemeta($cwd);
} }
elsif ($archive_type =~ /(\/x-rpm|\/x-deb)/) { elsif ($archive_type =~ /(\/x-rpm|\/x-deb)/) {
my $dir = fileparse( "$cwd/$name", qr/\.[^.]*/ ); my $dir = fileparse(
"$cwd/$name", qr/\.[^.]*/);
my $path = quotemeta("$cwd/$dir"); my $path = quotemeta("$cwd/$dir");
&make_dir($path, 0755); &make_dir($path, 0755);
if ($archive_type =~ /\/x-rpm/) { if ($archive_type =~ /\/x-rpm/) {
$cmd = "(rpm2cpio ".quotemeta("$cwd/$name"). $cmd = "(rpm2cpio ".
" | (cd ".quotemeta($path)."; cpio -idmv))"; quotemeta("$cwd/$name").
" | (cd ".quotemeta($path).
"; cpio -idmv))";
} }
else { else {
$cmd = "dpkg -x ".quotemeta("$cwd/$name")." ".quotemeta($path); $cmd = "dpkg -x ".
quotemeta("$cwd/$name").
" ".quotemeta($path);
} }
} }
else { else {
@@ -47,7 +60,8 @@ else {
} }
# Run the extraction command # Run the extraction command
$out = &backquote_logged("$cmd 2>&1 >/dev/null </dev/null"); $out = &backquote_logged(
"$cmd 2>&1 >/dev/null </dev/null");
if ($?) { if ($?) {
&error(&html_escape($out)); &error(&html_escape($out));
} }

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,8 @@ if (!$in{'link'}) {
my $mode; my $mode;
my @errors; my @errors;
my ($host, $port, $page, $ssl) = &parse_http_url($in{'link'}); my ($host, $port, $page, $ssl) =
&parse_http_url($in{'link'});
if (!$host) { if (!$host) {
# Not an HTTP or FTP URL # Not an HTTP or FTP URL
push(@errors, $text{'error_invalid_uri'}); push(@errors, $text{'error_invalid_uri'});
@@ -26,31 +27,46 @@ else {
$full = "$cwd/$file"; $full = "$cwd/$file";
if (-e $full) { if (-e $full) {
push @errors, "<i>$file</i> $text{'file_already_exists'} <i>$path</i>"; push @errors,
"<i>$file</i> " .
"$text{'file_already_exists'} " .
"<i>$path</i>";
} }
else { else {
&ui_print_header(undef, $text{'http_downloading'}, ""); &ui_print_header(
undef,
$text{'http_downloading'}, "");
$progress_callback_url = $in{'link'}; $progress_callback_url = $in{'link'};
my @st = stat($cwd); my @st = stat($cwd);
if ($ssl == 0 || $ssl == 1) { if ($ssl == 0 || $ssl == 1) {
# HTTP or HTTPS download # HTTP or HTTPS download
&http_download($host, $port, $page, $full, undef, &http_download(
\&progress_callback, $ssl, $host, $port, $page,
$in{'username'}, $in{'password'}); $full, undef,
\&progress_callback,
$ssl, $in{'username'},
$in{'password'});
} }
else { else {
# Actually an FTP download # Actually an FTP download
&ftp_download($host, $page, $full, undef, &ftp_download(
\&progress_callback, $host, $page, $full,
$in{'username'}, $in{'password'}, $port); undef,
\&progress_callback,
$in{'username'},
$in{'password'}, $port);
} }
&set_ownership_permissions($st[4], $st[5], undef, $full); &set_ownership_permissions(
$st[4], $st[5], undef, $full);
@st = stat($cwd); @st = stat($cwd);
print &text('http_done', &nice_size($st[7]), print &text('http_done',
"<tt>".&html_escape($full)."</tt>"),"<p>\n"; &nice_size($st[7]),
&ui_print_footer("index.cgi?path=".&urlize($path), "<tt>".&html_escape($full).
$text{'previous_page'}); "</tt>"),"<p>\n";
&ui_print_footer(
"index.cgi?path=".&urlize($path),
$text{'previous_page'});
} }
} }

View File

@@ -6,86 +6,138 @@ require './filemin-lib.pl';
&ReadParse(); &ReadParse();
get_paths(); get_paths();
unless (opendir ( DIR, $cwd )) { unless (opendir(DIR, $cwd)) {
$path=""; $path = "";
print_errors($text{'error_opendir'}." ".&html_escape($cwd)." ".$!); print_errors($text{'error_opendir'} . " " .
} else { &html_escape($cwd) . " " . $!);
&ui_print_header(undef, $module_info{'name'}, "", undef, 0 , 0, 0, "<a href='config.cgi?path=".&urlize($path)."' data-config-pagination='$userconfig{'per_page'}'>$text{'module_config'}</a>"); }
else {
&ui_print_header(
undef, $module_info{'name'}, "", undef, 0, 0, 0,
"<a href='config.cgi?path=" . &urlize($path) .
"' data-config-pagination='$userconfig{'per_page'}'>" .
"$text{'module_config'}</a>");
my %acls; my %acls;
my %attributes; my %attributes;
my $setype = get_selinux_command_type(); my $setype = get_selinux_command_type();
my %secontext; my %secontext;
# Push file names with full paths to array, filtering out "." and ".." # Push file names with full paths to array,
my $show_dot_files = $userconfig{'config_portable_module_filemanager_show_dot_files'} ne 'false'; # filtering out "." and ".."
@list = map { &simplify_path("$cwd/$_") } grep { $_ ne '.' && $_ ne '..' && ($show_dot_files || ($_ !~ /^\./ && $_ !~ /\/\./)) } readdir(DIR); my $show_dot_files =
closedir(DIR); $userconfig{
'config_portable_module_filemanager_show_dot_files'}
ne 'false';
@list = map { &simplify_path("$cwd/$_") }
grep {
$_ ne '.' && $_ ne '..' &&
($show_dot_files ||
($_ !~ /^\./ && $_ !~ /\/\./))
} readdir(DIR);
closedir(DIR);
# Filter out not allowed paths # Filter out not allowed paths
if (&test_allowed_paths()) { if (&test_allowed_paths()) {
for $path (@allowed_paths) { for $path (@allowed_paths) {
my $slashed = $path; my $slashed = $path;
$slashed .= "/" if ($slashed !~ /\/$/); $slashed .= "/"
push @tmp_list, grep { $slashed =~ /^\Q$_\E\// || if ($slashed !~ /\/$/);
$_ =~ /\Q$slashed\E/ } @list; push @tmp_list,
} grep { $slashed =~ /^\Q$_\E\// ||
# Remove duplicates $_ =~ /\Q$slashed\E/ } @list;
my %hash = map { $_, 1 } @tmp_list; }
@list = keys %hash; # Remove duplicates
} my %hash = map { $_, 1 } @tmp_list;
@list = keys %hash;
}
# List ACLs # List ACLs
if ($userconfig{'columns'} =~ /acls/ && get_acls_status()) { if ($userconfig{'columns'} =~ /acls/ &&
my $command = get_list_acls_command() . " " . join(' ', map {quotemeta("$_")} @list); get_acls_status()) {
my $output = `$command`; my $command = get_list_acls_command() . " " .
my @aclsArr; join(' ',
foreach my $aclsStr (split(/\n\n/, $output)) { map { quotemeta("$_") } @list);
$aclsStr =~ /#\s+file:\s*(.*)/; my $output = `$command`;
my ($file) = ($aclsStr =~ /#\s+file:\s*(.*)/); my @aclsArr;
my @aclsA = ($aclsStr =~ /^(?!(#|user::|group::|other::))([\w\:\-\_]+)/gm); foreach my $aclsStr (split(/\n\n/, $output)) {
push(@aclsArr, [$file, \@aclsA]); $aclsStr =~ /#\s+file:\s*(.*)/;
} my ($file) =
%acls = map {$_->[0] => ('<span data-acls>' . join("<br>", (grep /\S/, @{ $_->[1] })) . '</span>')} @aclsArr; ($aclsStr =~ /#\s+file:\s*(.*)/);
} my @aclsA =
($aclsStr =~
/^(?!(#|user::|group::|other::))([\w:_-]+)/gm);
push(@aclsArr, [$file, \@aclsA]);
}
%acls = map {
$_->[0] => (
'<span data-acls>' .
join("<br>",
(grep /\S/, @{ $_->[1] })) .
'</span>')
} @aclsArr;
}
# List attributes # List attributes
if ( $userconfig{'columns'} =~ /attributes/ && get_attr_status() ) { if ($userconfig{'columns'} =~ /attributes/ &&
my $command = get_attr_command() . join( ' ', map { quotemeta("$_") } @list ); get_attr_status()) {
my $output = `$command`; my $command = get_attr_command() .
my @attributesArr = join(' ',
map { [ split( /\s+/, $_, 2 ) ] } split( /\n/, $output ); map { quotemeta("$_") } @list);
%attributes = map { $_->[1] => ('<span data-attributes>' . $_->[0] . '</span>') } @attributesArr; my $output = `$command`;
} my @attributesArr =
map { [ split(/\s+/, $_, 2) ] }
split(/\n/, $output);
%attributes = map {
$_->[1] => (
'<span data-attributes>' .
$_->[0] . '</span>')
} @attributesArr;
}
# List security context # List security context
if ( $userconfig{'columns'} =~ /selinux/ && get_selinux_status() ) { if ($userconfig{'columns'} =~ /selinux/ &&
my $command = get_selinux_command() . join( ' ', map { quotemeta("$_") } @list ); get_selinux_status()) {
my $output = `$command`; my $command = get_selinux_command() .
( !$setype && ( $output =~ s/\n//g, $output =~ s/,\s/,/g ) ); join(' ',
my $delimiter = ( $setype ? '\n' : ',' ); map { quotemeta("$_") } @list);
my @searray = my $output = `$command`;
map { [ split( /\s+/, $_, 2 ) ] } split( /$delimiter/, $output ); (!$setype &&
%secontext = map { $_->[1] => ($_->[0] eq "?" ? undef : ('<span data-secontext>' . $_->[0] . '</span>') ) } @searray; ($output =~ s/\n//g,
} $output =~ s/,\s/,/g));
my $delimiter = ($setype ? '\n' : ',');
my @searray =
map { [ split(/\s+/, $_, 2) ] }
split(/$delimiter/, $output);
%secontext = map {
$_->[1] => (
$_->[0] eq "?" ? undef :
'<span data-secontext>' .
$_->[0] . '</span>'
)
} @searray;
}
# Get info about directory entries # Get info about directory entries
@info = map { [ $_, lstat($_), &clean_mimetype($_), -d, -l $_, $secontext{$_}, $attributes{$_}, $acls{$_} ] } @list; @info = map {
[ $_, lstat($_), &clean_mimetype($_), -d, -l $_,
$secontext{$_}, $attributes{$_}, $acls{$_} ]
} @list;
# Filter out folders # Filter out folders
@folders = map {$_} grep {$_->[15] == 1 } @info; @folders = map { $_ } grep { $_->[15] == 1 } @info;
# Filter out files # Filter out files
@files = map {$_} grep {$_->[15] != 1 } @info; @files = map { $_ } grep { $_->[15] != 1 } @info;
# Sort stuff by name # Sort stuff by name
@folders = sort { $a->[0] cmp $b->[0] } @folders; @folders = sort { $a->[0] cmp $b->[0] } @folders;
@files = sort { $a->[0] cmp $b->[0] } @files; @files = sort { $a->[0] cmp $b->[0] } @files;
# Recreate list # Recreate list
undef(@list); undef(@list);
push @list, @folders, @files; push @list, @folders, @files;
print_interface(); print_interface();
&ui_print_footer("/", $text{'index'}); &ui_print_footer("/", $text{'index'});
} }

View File

@@ -77,7 +77,7 @@ chmod_all=الكل (تكراري)
chmod_dir_files_and_subs_files=الملفات المحددة والملفات تحت الدلائل والدلائل الفرعية المحددة chmod_dir_files_and_subs_files=الملفات المحددة والملفات تحت الدلائل والدلائل الفرعية المحددة
chmod_dir_and_subs=الدلائل المختارة والدلائل الفرعية chmod_dir_and_subs=الدلائل المختارة والدلائل الفرعية
dialog_file_url=عنوان URL لملف لتنزيله dialog_file_url=عنوان URL لملف لتنزيله
dialog_user_name=اسم مستخدم الخادم البعيد (إذا كان مطلوبًا) dialog_user_name=اسم مستخدم الخادم البعيد
dialog_user_pass=كلمة مرور الخادم البعيد (إذا كانت مطلوبة) dialog_user_pass=كلمة مرور الخادم البعيد (إذا كانت مطلوبة)
dialog_download=تحميل dialog_download=تحميل
error_invalid_uri=خطأ: لم يتم تقديم عنوان URL صالح! error_invalid_uri=خطأ: لم يتم تقديم عنوان URL صالح!

View File

@@ -78,7 +78,7 @@ chmod_all=Всички (рекурсивни)
chmod_dir_files_and_subs_files=Избрани файлове и файлове в избрани директории и поддиректории chmod_dir_files_and_subs_files=Избрани файлове и файлове в избрани директории и поддиректории
chmod_dir_and_subs=Избрани директории и поддиректории chmod_dir_and_subs=Избрани директории и поддиректории
dialog_file_url=URL адрес на файла за изтегляне dialog_file_url=URL адрес на файла за изтегляне
dialog_user_name=Потребителско име за отдалечен сървър (ако е необходимо) dialog_user_name=Потребителско име за отдалечен сървър
dialog_user_pass=Отдалечена парола за сървър (ако има такава) dialog_user_pass=Отдалечена парола за сървър (ако има такава)
dialog_download=Изтегли dialog_download=Изтегли
error_invalid_uri=Грешка: Не е предоставен валиден URL адрес! error_invalid_uri=Грешка: Не е предоставен валиден URL адрес!

View File

@@ -77,7 +77,7 @@ chmod_all=Tot (recursiu)
chmod_dir_files_and_subs_files=Als fitxers seleccionats i als fitxers dins dels directoris i subdirectoris seleccionats chmod_dir_files_and_subs_files=Als fitxers seleccionats i als fitxers dins dels directoris i subdirectoris seleccionats
chmod_dir_and_subs=Als directoris i subdirectoris seleccionats chmod_dir_and_subs=Als directoris i subdirectoris seleccionats
dialog_file_url=URL del fitxer a descarregar dialog_file_url=URL del fitxer a descarregar
dialog_user_name=Usuari del servidor remot (si cal) dialog_user_name=Usuari del servidor remot
dialog_user_pass=Contrasenya del servidor remot (si cal) dialog_user_pass=Contrasenya del servidor remot (si cal)
dialog_download=Descarrega dialog_download=Descarrega
error_invalid_uri=Error: No has donat un URL vàlid! error_invalid_uri=Error: No has donat un URL vàlid!

View File

@@ -78,7 +78,7 @@ chmod_all=Vše (rekurzivní)
chmod_dir_files_and_subs_files=Vybrané soubory a soubory pod vybranými adresáři a podadresáři chmod_dir_files_and_subs_files=Vybrané soubory a soubory pod vybranými adresáři a podadresáři
chmod_dir_and_subs=Vybrané adresáře a podadresáře chmod_dir_and_subs=Vybrané adresáře a podadresáře
dialog_file_url=URL souboru ke stažení dialog_file_url=URL souboru ke stažení
dialog_user_name=Uživatelské jméno vzdáleného serveru (pokud je vyžadováno) dialog_user_name=Uživatelské jméno vzdáleného serveru
dialog_user_pass=Heslo vzdáleného serveru (pokud je vyžadováno) dialog_user_pass=Heslo vzdáleného serveru (pokud je vyžadováno)
dialog_download=Stažení dialog_download=Stažení
error_invalid_uri=Chyba: Nebyla zadána žádná platná adresa URL! error_invalid_uri=Chyba: Nebyla zadána žádná platná adresa URL!

View File

@@ -78,7 +78,7 @@ chmod_all=Alle (rekursive)
chmod_dir_files_and_subs_files=Valgte filer og filer under valgte mapper og undermapper chmod_dir_files_and_subs_files=Valgte filer og filer under valgte mapper og undermapper
chmod_dir_and_subs=Udvalgte mapper og undermapper chmod_dir_and_subs=Udvalgte mapper og undermapper
dialog_file_url=URL til filen, der skal downloades dialog_file_url=URL til filen, der skal downloades
dialog_user_name=Brugernavn til ekstern server (hvis nødvendigt) dialog_user_name=Brugernavn til ekstern server
dialog_user_pass=Ekstern serveradgangskode (hvis nødvendigt) dialog_user_pass=Ekstern serveradgangskode (hvis nødvendigt)
dialog_download=Hent dialog_download=Hent
error_invalid_uri=Fejl: Ingen gyldig URL leveret! error_invalid_uri=Fejl: Ingen gyldig URL leveret!

View File

@@ -78,7 +78,7 @@ chmod_all=Alle (rekursiv)
chmod_dir_files_and_subs_files=Ausgewählte Dateien und Dateien unter ausgewählten Verzeichnissen und Unterverzeichnissen chmod_dir_files_and_subs_files=Ausgewählte Dateien und Dateien unter ausgewählten Verzeichnissen und Unterverzeichnissen
chmod_dir_and_subs=Ausgewählte Verzeichnisse und Unterverzeichnisse chmod_dir_and_subs=Ausgewählte Verzeichnisse und Unterverzeichnisse
dialog_file_url=URL der herunterzuladenden Datei dialog_file_url=URL der herunterzuladenden Datei
dialog_user_name=Benutzername des entfernten Servers (falls erforderlich) dialog_user_name=Benutzername des entfernten Servers
dialog_user_pass=Passwort des entfernten Servers (falls erforderlich) dialog_user_pass=Passwort des entfernten Servers (falls erforderlich)
dialog_download=Herunterladen dialog_download=Herunterladen
error_invalid_uri=Fehler: Keine gültige URL angegeben! error_invalid_uri=Fehler: Keine gültige URL angegeben!

View File

@@ -78,7 +78,7 @@ chmod_all=Όλα (αναδρομικά)
chmod_dir_files_and_subs_files=Επιλεγμένα αρχεία και αρχεία σε επιλεγμένους καταλόγους και υποκαταλόγους chmod_dir_files_and_subs_files=Επιλεγμένα αρχεία και αρχεία σε επιλεγμένους καταλόγους και υποκαταλόγους
chmod_dir_and_subs=Επιλεγμένοι κατάλογοι και υποκαταλόγους chmod_dir_and_subs=Επιλεγμένοι κατάλογοι και υποκαταλόγους
dialog_file_url=URL του αρχείου για λήψη dialog_file_url=URL του αρχείου για λήψη
dialog_user_name=Απομακρυσμένο όνομα χρήστη διακομιστή (εάν απαιτείται) dialog_user_name=Απομακρυσμένο όνομα χρήστη διακομιστή
dialog_user_pass=Κωδικός πρόσβασης απομακρυσμένου διακομιστή (εάν απαιτείται) dialog_user_pass=Κωδικός πρόσβασης απομακρυσμένου διακομιστή (εάν απαιτείται)
dialog_download=Κατεβάστε dialog_download=Κατεβάστε
error_invalid_uri=Σφάλμα: Δεν παρέχεται έγκυρη διεύθυνση URL! error_invalid_uri=Σφάλμα: Δεν παρέχεται έγκυρη διεύθυνση URL!

View File

@@ -78,8 +78,8 @@ chmod_all=All (recursive)
chmod_dir_files_and_subs_files=Selected files and files under selected directories and subdirectories chmod_dir_files_and_subs_files=Selected files and files under selected directories and subdirectories
chmod_dir_and_subs=Selected directories and subdirectories chmod_dir_and_subs=Selected directories and subdirectories
dialog_file_url=URL of file to download dialog_file_url=URL of file to download
dialog_user_name=Remote server username(if any required) dialog_user_name=Remote server username
dialog_user_pass=Remote server password(if any required) dialog_user_pass=Remote server password
dialog_download=Download dialog_download=Download
error_invalid_uri=Error: No valid URL supplied! error_invalid_uri=Error: No valid URL supplied!
file_already_exists=already exists in file_already_exists=already exists in

View File

@@ -78,7 +78,7 @@ chmod_all=Todo (recursivo)
chmod_dir_files_and_subs_files=Archivos seleccionados y archivos en directorios y subdirectorios seleccionados chmod_dir_files_and_subs_files=Archivos seleccionados y archivos en directorios y subdirectorios seleccionados
chmod_dir_and_subs=Directorios y subdirectorios seleccionados chmod_dir_and_subs=Directorios y subdirectorios seleccionados
dialog_file_url=URL del archivo a descargar dialog_file_url=URL del archivo a descargar
dialog_user_name=Nombre de usuario del servidor remoto (si es necesario) dialog_user_name=Nombre de usuario del servidor remoto
dialog_user_pass=Contraseña del servidor remoto (si se requiere) dialog_user_pass=Contraseña del servidor remoto (si se requiere)
dialog_download=Descargar dialog_download=Descargar
error_invalid_uri=Error: ¡No se ha proporcionado una URL válida! error_invalid_uri=Error: ¡No se ha proporcionado una URL válida!

View File

@@ -78,7 +78,7 @@ chmod_all=Guztiak (errekurtsiboa)
chmod_dir_files_and_subs_files=Hautatutako fitxategiak eta fitxategiak aukeratutako direktorio eta azpidirektorioetan chmod_dir_files_and_subs_files=Hautatutako fitxategiak eta fitxategiak aukeratutako direktorio eta azpidirektorioetan
chmod_dir_and_subs=Hautatutako direktorio eta azpidirektorioak chmod_dir_and_subs=Hautatutako direktorio eta azpidirektorioak
dialog_file_url=Deskargatzeko fitxategiaren URLa dialog_file_url=Deskargatzeko fitxategiaren URLa
dialog_user_name=Urruneko zerbitzariaren erabiltzaile izena (beharrezkoa izanez gero) dialog_user_name=Urruneko zerbitzariaren erabiltzaile izena
dialog_user_pass=Urruneko zerbitzariaren pasahitza (beharrezkoa izanez gero) dialog_user_pass=Urruneko zerbitzariaren pasahitza (beharrezkoa izanez gero)
dialog_download=Deskarga dialog_download=Deskarga
error_invalid_uri=Errorea: ez da baliozko URLrik eman! error_invalid_uri=Errorea: ez da baliozko URLrik eman!

View File

@@ -78,7 +78,7 @@ chmod_all=همه (بازگشتی)
chmod_dir_files_and_subs_files=پرونده ها و پرونده ها در زیر فهرست ها و زیر شاخه های انتخاب شده انتخاب شده اند chmod_dir_files_and_subs_files=پرونده ها و پرونده ها در زیر فهرست ها و زیر شاخه های انتخاب شده انتخاب شده اند
chmod_dir_and_subs=دایرکتوری ها و زیر شاخه های انتخاب شده chmod_dir_and_subs=دایرکتوری ها و زیر شاخه های انتخاب شده
dialog_file_url=URL فایل برای بارگیری dialog_file_url=URL فایل برای بارگیری
dialog_user_name=نام کاربری سرور از راه دور (در صورت لزوم) dialog_user_name=نام کاربری سرور از راه دور
dialog_user_pass=رمز عبور سرور از راه دور (در صورت لزوم) dialog_user_pass=رمز عبور سرور از راه دور (در صورت لزوم)
dialog_download=دانلود dialog_download=دانلود
error_invalid_uri=خطا: هیچ URL معتبری ارائه نشده است! error_invalid_uri=خطا: هیچ URL معتبری ارائه نشده است!

View File

@@ -78,7 +78,7 @@ chmod_all=Kaikki (rekursiivinen)
chmod_dir_files_and_subs_files=Valitut tiedostot ja tiedostot valituissa hakemistoissa ja alihakemistoissa chmod_dir_files_and_subs_files=Valitut tiedostot ja tiedostot valituissa hakemistoissa ja alihakemistoissa
chmod_dir_and_subs=Valitut hakemistot ja alihakemistot chmod_dir_and_subs=Valitut hakemistot ja alihakemistot
dialog_file_url=Ladattavan tiedoston URL-osoite dialog_file_url=Ladattavan tiedoston URL-osoite
dialog_user_name=Etäpalvelimen käyttäjänimi (tarvittaessa) dialog_user_name=Etäpalvelimen käyttäjänimi
dialog_user_pass=Etäpalvelimen salasana (jos vaaditaan) dialog_user_pass=Etäpalvelimen salasana (jos vaaditaan)
dialog_download=ladata dialog_download=ladata
error_invalid_uri=Virhe: ei kelpaa URL-osoitetta! error_invalid_uri=Virhe: ei kelpaa URL-osoitetta!

View File

@@ -77,7 +77,7 @@ chmod_all=Tout (récursif)
chmod_dir_files_and_subs_files=Fichiers sélectionnés et fichiers sous les répertoires et sous-répertoires sélectionnés chmod_dir_files_and_subs_files=Fichiers sélectionnés et fichiers sous les répertoires et sous-répertoires sélectionnés
chmod_dir_and_subs=Répertoires et sous-répertoires sélectionnés chmod_dir_and_subs=Répertoires et sous-répertoires sélectionnés
dialog_file_url=URL du fichier à télécharger dialog_file_url=URL du fichier à télécharger
dialog_user_name=Nom d'utilisateur du serveur distant (le cas échéant) dialog_user_name=Nom d'utilisateur du serveur distant
dialog_user_pass=Mot de passe du serveur distant (le cas échéant) dialog_user_pass=Mot de passe du serveur distant (le cas échéant)
dialog_download=Télécharger dialog_download=Télécharger
error_invalid_uri=Erreur: aucune URL valide fournie! error_invalid_uri=Erreur: aucune URL valide fournie!

View File

@@ -78,7 +78,7 @@ chmod_all=Sve (rekurzivno)
chmod_dir_files_and_subs_files=Odabrane datoteke i datoteke u odabranim direktorijima i podmapama chmod_dir_files_and_subs_files=Odabrane datoteke i datoteke u odabranim direktorijima i podmapama
chmod_dir_and_subs=Odabrani direktoriji i poddirektoriji chmod_dir_and_subs=Odabrani direktoriji i poddirektoriji
dialog_file_url=URL datoteke koju želite preuzeti dialog_file_url=URL datoteke koju želite preuzeti
dialog_user_name=Korisničko ime udaljenog poslužitelja (ako je potrebno) dialog_user_name=Korisničko ime udaljenog poslužitelja
dialog_user_pass=Udaljena lozinka poslužitelja (ako je potrebna) dialog_user_pass=Udaljena lozinka poslužitelja (ako je potrebna)
dialog_download=preuzimanje datoteka dialog_download=preuzimanje datoteka
error_invalid_uri=Pogreška: nije dostavljen valjani URL! error_invalid_uri=Pogreška: nije dostavljen valjani URL!

View File

@@ -78,7 +78,7 @@ chmod_all=Összes (rekurzív)
chmod_dir_files_and_subs_files=Kiválasztott fájlok és fájlok a kiválasztott könyvtárakban és alkönyvtárakban chmod_dir_files_and_subs_files=Kiválasztott fájlok és fájlok a kiválasztott könyvtárakban és alkönyvtárakban
chmod_dir_and_subs=Kiválasztott könyvtárak és alkönyvtárak chmod_dir_and_subs=Kiválasztott könyvtárak és alkönyvtárak
dialog_file_url=A letölthető fájl URL-je dialog_file_url=A letölthető fájl URL-je
dialog_user_name=Távoli szerver felhasználóneve (ha szükséges) dialog_user_name=Távoli szerver felhasználóneve
dialog_user_pass=Távoli szerver jelszava (ha szükséges) dialog_user_pass=Távoli szerver jelszava (ha szükséges)
dialog_download=Letöltés dialog_download=Letöltés
error_invalid_uri=Hiba: Nincs érvényes URL! error_invalid_uri=Hiba: Nincs érvényes URL!

View File

@@ -77,7 +77,7 @@ chmod_all=Tutto (ricorsivo)
chmod_dir_files_and_subs_files=File selezionati e file nelle cartelle e sottocartelle selezionate chmod_dir_files_and_subs_files=File selezionati e file nelle cartelle e sottocartelle selezionate
chmod_dir_and_subs=Cartelle e sottocartelle selezionate chmod_dir_and_subs=Cartelle e sottocartelle selezionate
dialog_file_url=URL del file da scaricare dialog_file_url=URL del file da scaricare
dialog_user_name=Nome utente del server remoto (se richiesto) dialog_user_name=Nome utente del server remoto
dialog_user_pass=Password del server remoto (se richiesta) dialog_user_pass=Password del server remoto (se richiesta)
dialog_download=Scarica dialog_download=Scarica
error_invalid_uri=Errore: nessun URL valido fornito! error_invalid_uri=Errore: nessun URL valido fornito!

View File

@@ -78,7 +78,7 @@ chmod_all=すべて(再帰的)
chmod_dir_files_and_subs_files=選択したファイルおよび選択したディレクトリとサブディレクトリの下のファイル chmod_dir_files_and_subs_files=選択したファイルおよび選択したディレクトリとサブディレクトリの下のファイル
chmod_dir_and_subs=選択したディレクトリとサブディレクトリ chmod_dir_and_subs=選択したディレクトリとサブディレクトリ
dialog_file_url=ダウンロードするファイルのURL dialog_file_url=ダウンロードするファイルのURL
dialog_user_name=リモートサーバーのユーザー名(必要な場合) dialog_user_name=リモートサーバーのユーザー名
dialog_user_pass=リモートサーバーのパスワード(必要な場合) dialog_user_pass=リモートサーバーのパスワード(必要な場合)
dialog_download=ダウンロード dialog_download=ダウンロード
error_invalid_uri=エラー有効なURLが指定されていません error_invalid_uri=エラー有効なURLが指定されていません

View File

@@ -78,7 +78,7 @@ chmod_all=모두 (재귀)
chmod_dir_files_and_subs_files=선택된 디렉토리 및 서브 디렉토리에서 선택된 파일 및 파일 chmod_dir_files_and_subs_files=선택된 디렉토리 및 서브 디렉토리에서 선택된 파일 및 파일
chmod_dir_and_subs=선택된 디렉토리 및 서브 디렉토리 chmod_dir_and_subs=선택된 디렉토리 및 서브 디렉토리
dialog_file_url=다운로드 할 파일의 URL dialog_file_url=다운로드 할 파일의 URL
dialog_user_name=원격 서버 사용자 이름 (필요한 경우) dialog_user_name=원격 서버 사용자 이름
dialog_user_pass=원격 서버 비밀번호 (필요한 경우) dialog_user_pass=원격 서버 비밀번호 (필요한 경우)
dialog_download=다운로드 dialog_download=다운로드
error_invalid_uri=오류 : 유효한 URL이 제공되지 않았습니다! error_invalid_uri=오류 : 유효한 URL이 제공되지 않았습니다!

View File

@@ -78,7 +78,7 @@ chmod_all=Semua (rekursif)
chmod_dir_files_and_subs_files=Fail dan fail terpilih di bawah direktori dan subdirektori yang dipilih chmod_dir_files_and_subs_files=Fail dan fail terpilih di bawah direktori dan subdirektori yang dipilih
chmod_dir_and_subs=Direktori dan subdirektori yang dipilih chmod_dir_and_subs=Direktori dan subdirektori yang dipilih
dialog_file_url=URL fail untuk dimuat turun dialog_file_url=URL fail untuk dimuat turun
dialog_user_name=Nama pengguna pelayan jauh (jika ada yang diperlukan) dialog_user_name=Nama pengguna pelayan jauh
dialog_user_pass=Kata laluan pelayan jauh (jika ada yang diperlukan) dialog_user_pass=Kata laluan pelayan jauh (jika ada yang diperlukan)
dialog_download=Muat turun dialog_download=Muat turun
error_invalid_uri=Ralat: Tiada URL yang sah dibekalkan! error_invalid_uri=Ralat: Tiada URL yang sah dibekalkan!

View File

@@ -78,7 +78,7 @@ chmod_all=Allemaal (recursief)
chmod_dir_files_and_subs_files=Geselecteerde bestanden en bestanden onder geselecteerde mappen en submappen chmod_dir_files_and_subs_files=Geselecteerde bestanden en bestanden onder geselecteerde mappen en submappen
chmod_dir_and_subs=Geselecteerde mappen en submappen chmod_dir_and_subs=Geselecteerde mappen en submappen
dialog_file_url=URL van te downloaden bestand dialog_file_url=URL van te downloaden bestand
dialog_user_name=Gebruikersnaam externe server (indien vereist) dialog_user_name=Gebruikersnaam externe server
dialog_user_pass=Wachtwoord externe server (indien nodig) dialog_user_pass=Wachtwoord externe server (indien nodig)
dialog_download=Downloaden dialog_download=Downloaden
error_invalid_uri=Fout: geen geldige URL opgegeven! error_invalid_uri=Fout: geen geldige URL opgegeven!

View File

@@ -77,7 +77,7 @@ chmod_all=Alle (rekursiv)
chmod_dir_files_and_subs_files=Valgte filer og filer under valgte kataloger og underkataloger chmod_dir_files_and_subs_files=Valgte filer og filer under valgte kataloger og underkataloger
chmod_dir_and_subs=Valgte kataloger og underkataloger chmod_dir_and_subs=Valgte kataloger og underkataloger
dialog_file_url=URL for fil som skal lastes ned dialog_file_url=URL for fil som skal lastes ned
dialog_user_name=Brukernavn for ekstern tjener (hvis nødvendig) dialog_user_name=Brukernavn for ekstern tjener
dialog_user_pass=Passord for ekstern tjener (hvis nødvendig) dialog_user_pass=Passord for ekstern tjener (hvis nødvendig)
dialog_download=Last ned dialog_download=Last ned
error_invalid_uri=Feil: Ingen gyldig URL angitt!!! error_invalid_uri=Feil: Ingen gyldig URL angitt!!!

View File

@@ -78,7 +78,7 @@ chmod_all=Wszystko (rekurencyjnie)
chmod_dir_files_and_subs_files=Wybrane pliki i pliki w podkatalogach chmod_dir_files_and_subs_files=Wybrane pliki i pliki w podkatalogach
chmod_dir_and_subs=Wybrane katalogi i podkatalogi chmod_dir_and_subs=Wybrane katalogi i podkatalogi
dialog_file_url=URL pliku do pobrania dialog_file_url=URL pliku do pobrania
dialog_user_name=Nazwa użytkownika serwera zdalnego (jeśli wymagana) dialog_user_name=Nazwa użytkownika serwera zdalnego
dialog_user_pass=Hasło serwera zdalnego (jeśli wymagane) dialog_user_pass=Hasło serwera zdalnego (jeśli wymagane)
dialog_download=Pobierz dialog_download=Pobierz
error_invalid_uri=Błąd: Nie podano prawidłowego adresu URL! error_invalid_uri=Błąd: Nie podano prawidłowego adresu URL!

View File

@@ -78,7 +78,7 @@ chmod_all=Tudo (recursivo)
chmod_dir_files_and_subs_files=Arquivos e arquivos selecionados em diretórios e subdiretórios selecionados chmod_dir_files_and_subs_files=Arquivos e arquivos selecionados em diretórios e subdiretórios selecionados
chmod_dir_and_subs=Diretórios e subdiretórios selecionados chmod_dir_and_subs=Diretórios e subdiretórios selecionados
dialog_file_url=URL do arquivo a ser baixado dialog_file_url=URL do arquivo a ser baixado
dialog_user_name=Nome de usuário do servidor remoto (se necessário) dialog_user_name=Nome de usuário do servidor remoto
dialog_user_pass=Senha do servidor remoto (se necessário) dialog_user_pass=Senha do servidor remoto (se necessário)
dialog_download=Baixar dialog_download=Baixar
error_invalid_uri=Erro: nenhum URL válido foi fornecido! error_invalid_uri=Erro: nenhum URL válido foi fornecido!

View File

@@ -78,7 +78,7 @@ chmod_all=Tudo (recursivo)
chmod_dir_files_and_subs_files=Arquivos e arquivos selecionados em diretórios e subdiretórios selecionados chmod_dir_files_and_subs_files=Arquivos e arquivos selecionados em diretórios e subdiretórios selecionados
chmod_dir_and_subs=Diretórios e subdiretórios selecionados chmod_dir_and_subs=Diretórios e subdiretórios selecionados
dialog_file_url=URL do arquivo a ser baixado dialog_file_url=URL do arquivo a ser baixado
dialog_user_name=Nome de usuário do servidor remoto (se necessário) dialog_user_name=Nome de usuário do servidor remoto
dialog_user_pass=Senha do servidor remoto (se necessário) dialog_user_pass=Senha do servidor remoto (se necessário)
dialog_download=Baixar dialog_download=Baixar
error_invalid_uri=Erro: nenhum URL válido foi fornecido! error_invalid_uri=Erro: nenhum URL válido foi fornecido!

View File

@@ -78,7 +78,7 @@ chmod_all=Все (рекурсивно)
chmod_dir_files_and_subs_files=Выбранные файлы и файлы в выбранных каталогах и подкаталогах chmod_dir_files_and_subs_files=Выбранные файлы и файлы в выбранных каталогах и подкаталогах
chmod_dir_and_subs=Избранные каталоги и подкаталоги chmod_dir_and_subs=Избранные каталоги и подкаталоги
dialog_file_url=URL файла для скачивания dialog_file_url=URL файла для скачивания
dialog_user_name=Имя пользователя удаленного сервера (если требуется) dialog_user_name=Имя пользователя удаленного сервера
dialog_user_pass=Пароль удаленного сервера (если требуется) dialog_user_pass=Пароль удаленного сервера (если требуется)
dialog_download=Скачать dialog_download=Скачать
error_invalid_uri=Ошибка: действительный URL не указан! error_invalid_uri=Ошибка: действительный URL не указан!

View File

@@ -78,7 +78,7 @@ chmod_all=Všetko (rekurzívne)
chmod_dir_files_and_subs_files=Vybrané súbory a súbory pod vybratými adresármi a podadresármi chmod_dir_files_and_subs_files=Vybrané súbory a súbory pod vybratými adresármi a podadresármi
chmod_dir_and_subs=Vybrané adresáre a podadresáre chmod_dir_and_subs=Vybrané adresáre a podadresáre
dialog_file_url=URL súboru na stiahnutie dialog_file_url=URL súboru na stiahnutie
dialog_user_name=Používateľské meno vzdialeného servera (ak je požadované) dialog_user_name=Používateľské meno vzdialeného servera
dialog_user_pass=Heslo vzdialeného servera (ak sa vyžaduje) dialog_user_pass=Heslo vzdialeného servera (ak sa vyžaduje)
dialog_download=Stiahnuť ▼ dialog_download=Stiahnuť ▼
error_invalid_uri=Chyba: Nebola zadaná žiadna platná adresa URL! error_invalid_uri=Chyba: Nebola zadaná žiadna platná adresa URL!

View File

@@ -78,7 +78,7 @@ chmod_all=Alla (rekursiva)
chmod_dir_files_and_subs_files=Valda filer och filer under valda kataloger och underkataloger chmod_dir_files_and_subs_files=Valda filer och filer under valda kataloger och underkataloger
chmod_dir_and_subs=Valda kataloger och underkataloger chmod_dir_and_subs=Valda kataloger och underkataloger
dialog_file_url=URL till filen som ska laddas ner dialog_file_url=URL till filen som ska laddas ner
dialog_user_name=Användarnamn för fjärrserver (om nödvändigt) dialog_user_name=Användarnamn för fjärrserver
dialog_user_pass=Lösenord för fjärrserver (om nödvändigt) dialog_user_pass=Lösenord för fjärrserver (om nödvändigt)
dialog_download=Ladda ner dialog_download=Ladda ner
error_invalid_uri=Fel: Ingen giltig webbadress levereras! error_invalid_uri=Fel: Ingen giltig webbadress levereras!

View File

@@ -78,7 +78,7 @@ chmod_all=Tümü (özyinelemeli)
chmod_dir_files_and_subs_files=Seçilen dosyalar ve seçilen dizinler ve alt dizinler altındaki dosyalar chmod_dir_files_and_subs_files=Seçilen dosyalar ve seçilen dizinler ve alt dizinler altındaki dosyalar
chmod_dir_and_subs=Seçili dizinler ve alt dizinler chmod_dir_and_subs=Seçili dizinler ve alt dizinler
dialog_file_url=İndirilecek dosyanın URL'si dialog_file_url=İndirilecek dosyanın URL'si
dialog_user_name=Uzak sunucu kullanıcı adı (gerekirse) dialog_user_name=Uzak sunucu kullanıcı adı
dialog_user_pass=Uzak sunucu şifresi (gerekirse) dialog_user_pass=Uzak sunucu şifresi (gerekirse)
dialog_download=İndir dialog_download=İndir
error_invalid_uri=Hata: Geçerli bir URL sağlanmadı! error_invalid_uri=Hata: Geçerli bir URL sağlanmadı!

View File

@@ -78,7 +78,7 @@ chmod_all=Усі (рекурсивно)
chmod_dir_files_and_subs_files=Обрані файли та файли у обраних каталогах та підкаталогах chmod_dir_files_and_subs_files=Обрані файли та файли у обраних каталогах та підкаталогах
chmod_dir_and_subs=Обрані каталоги та підкаталоги chmod_dir_and_subs=Обрані каталоги та підкаталоги
dialog_file_url=URL-адреса файлу для завантаження dialog_file_url=URL-адреса файлу для завантаження
dialog_user_name=Ім'я користувача віддаленого сервера (за необхідності) dialog_user_name=Ім'я користувача віддаленого сервера
dialog_user_pass=Віддалений пароль сервера (за необхідності) dialog_user_pass=Віддалений пароль сервера (за необхідності)
dialog_download=Завантажити dialog_download=Завантажити
error_invalid_uri=Помилка: не вказана дійсна URL-адреса! error_invalid_uri=Помилка: не вказана дійсна URL-адреса!

View File

@@ -78,7 +78,7 @@ chmod_all=全部(递归)
chmod_dir_files_and_subs_files=所选文件以及所选目录和子目录下的文件 chmod_dir_files_and_subs_files=所选文件以及所选目录和子目录下的文件
chmod_dir_and_subs=所选目录和子目录 chmod_dir_and_subs=所选目录和子目录
dialog_file_url=下载文件的URL dialog_file_url=下载文件的URL
dialog_user_name=远程服务器用户名(如果需要) dialog_user_name=远程服务器用户名
dialog_user_pass=远程服务器密码(如果需要) dialog_user_pass=远程服务器密码(如果需要)
dialog_download=下载 dialog_download=下载
error_invalid_uri=错误:未提供有效的网址! error_invalid_uri=错误:未提供有效的网址!

View File

@@ -78,7 +78,7 @@ chmod_all=全部(遞歸)
chmod_dir_files_and_subs_files=所選文件以及所選目錄和子目錄下的文件 chmod_dir_files_and_subs_files=所選文件以及所選目錄和子目錄下的文件
chmod_dir_and_subs=所選目錄和子目錄 chmod_dir_and_subs=所選目錄和子目錄
dialog_file_url=下載文件的URL dialog_file_url=下載文件的URL
dialog_user_name=遠程服務器用戶名(如果需要) dialog_user_name=遠程服務器用戶名
dialog_user_pass=遠程服務器密碼(如果需要) dialog_user_pass=遠程服務器密碼(如果需要)
dialog_download=下載 dialog_download=下載
error_invalid_uri=錯誤:未提供有效的網址! error_invalid_uri=錯誤:未提供有效的網址!

View File

@@ -6,7 +6,8 @@ use Cwd 'abs_path';
get_paths(); get_paths();
open(my $fh, "<".&get_paste_buffer_file()) or die "Error: $!"; open(my $fh, "<".&get_paste_buffer_file())
or die "Error: $!";
my @arr = <$fh>; my @arr = <$fh>;
close($fh); close($fh);
my $act = $arr[0]; my $act = $arr[0];
@@ -15,34 +16,61 @@ chomp($act);
chomp($dir); chomp($dir);
$from = abs_path($base.$dir); $from = abs_path($base.$dir);
if ($cwd eq $from) { if ($cwd eq $from) {
print_errors($text{'error_pasting_nonsence'}); print_errors($text{'error_pasting_nonsence'});
} else { }
my @errors; else {
for(my $i = 2;$i <= scalar(@arr)-1;$i++) { my @errors;
chomp($arr[$i]); for (my $i = 2; $i <= scalar(@arr) - 1; $i++) {
if ($act eq "copy") { chomp($arr[$i]);
if (-e "$cwd/$arr[$i]") { if ($act eq "copy") {
push @errors, "$cwd/$arr[$i] $text{'error_exists'}"; if (-e "$cwd/$arr[$i]") {
} else { push @errors,
system("cp -r ".quotemeta("$from/$arr[$i]"). "$cwd/$arr[$i] " .
" ".quotemeta($cwd)) == 0 or push @errors, "$from/$arr[$i] $text{'error_copy'} $!"; "$text{'error_exists'}";
} }
} else {
elsif ($act eq "cut") { system("cp -r ".
if (!can_move("$from/$arr[$i]", $cwd, $from)) { quotemeta(
push @errors, "$from/$arr[$i] - $text{'error_move'}"; "$from/$arr[$i]").
} " ".quotemeta($cwd)
elsif (-e "$cwd/$arr[$i]") { ) == 0 ||
push @errors, "$cwd/$arr[$i] $text{'error_exists'}"; push @errors,
} else { "$from/$arr[$i] " .
system("mv ".quotemeta("$from/$arr[$i]"). "$text{'error_copy'}" .
" ".quotemeta($cwd)) == 0 or push @errors, "$from/$arr[$i] $text{'error_cut'} $!"; " $!";
} }
} }
} elsif ($act eq "cut") {
if (scalar(@errors) > 0) { if (!can_move("$from/$arr[$i]",
print_errors(@errors); $cwd, $from)) {
} else { push @errors,
&redirect("index.cgi?path=".&urlize($path)); "$from/$arr[$i]" .
} " - " .
} "$text{'error_move'}";
}
elsif (-e "$cwd/$arr[$i]") {
push @errors,
"$cwd/$arr[$i] " .
"$text{'error_exists'}";
}
else {
system("mv ".
quotemeta(
"$from/$arr[$i]").
" ".quotemeta($cwd)
) == 0 ||
push @errors,
"$from/$arr[$i] " .
"$text{'error_cut'}" .
" $!";
}
}
}
if (scalar(@errors) > 0) {
print_errors(@errors);
}
else {
&redirect(
"index.cgi?path=".&urlize($path));
}
}

View File

@@ -3,20 +3,26 @@
require './filemin-lib.pl'; require './filemin-lib.pl';
&ReadParse(); &ReadParse();
if(!$in{'name'}) { if (!$in{'name'}) {
&redirect("index.cgi?path=".&urlize($path)); &redirect("index.cgi?path=".&urlize($path));
} }
get_paths(); get_paths();
if (-e "$cwd/$in{'name'}") { if (-e "$cwd/$in{'name'}") {
print_errors("$in{'name'} $text{'error_exists'}"); print_errors("$in{'name'} $text{'error_exists'}");
} else { }
if(!can_move("$cwd/$in{'file'}", $cwd)) { else {
print_errors("$in{'file'} - $text{'error_move'}"); if (!can_move("$cwd/$in{'file'}", $cwd)) {
} print_errors(
elsif(&rename_file($cwd.'/'.$in{'file'}, $cwd.'/'.$in{'name'})) { "$in{'file'} - $text{'error_move'}");
&redirect("index.cgi?path=".&urlize($path)); }
} else { elsif (&rename_file($cwd.'/'.$in{'file'},
print_errors("$text{'error_rename'} $in{'file'}: $!"); $cwd.'/'.$in{'name'})) {
} &redirect("index.cgi?path=".
} &urlize($path));
}
else {
print_errors(
"$text{'error_rename'} $in{'file'}: $!");
}
}

View File

@@ -8,17 +8,24 @@ get_paths();
$columns = $in{'columns'}; $columns = $in{'columns'};
$columns =~ s/\0/,/g; $columns =~ s/\0/,/g;
&error("$text{'config_per_page'} $text{'error_numeric'}") unless($in{'per_page'} eq int($in{'per_page'})); &error("$text{'config_per_page'} $text{'error_numeric'}")
unless ($in{'per_page'} eq int($in{'per_page'}));
my $detect_encoding =
$in{'config_portable_module_filemanager_editor_detect_encoding'};
my $show_dot_files =
$in{'config_portable_module_filemanager_show_dot_files'};
%config = ( %config = (
'columns' => $columns, 'columns' => $columns,
'per_page' => $in{'per_page'}, 'per_page' => $in{'per_page'},
'config_portable_module_filemanager_editor_detect_encoding' => $in{'config_portable_module_filemanager_editor_detect_encoding'}, 'config_portable_module_filemanager_editor_detect_encoding' =>
'config_portable_module_filemanager_show_dot_files' => $in{'config_portable_module_filemanager_show_dot_files'}, $detect_encoding,
); 'config_portable_module_filemanager_show_dot_files' =>
$show_dot_files,
);
my $max_allowed = $in{'max_allowed'}; my $max_allowed = $in{'max_allowed'};
if($max_allowed) { if ($max_allowed) {
$config{'max_allowed'} = $max_allowed; $config{'max_allowed'} = $max_allowed;
} }
&write_file("$confdir/.config", \%config); &write_file("$confdir/.config", \%config);
&save_module_preferences($module_name, \%config); &save_module_preferences($module_name, \%config);

View File

@@ -10,22 +10,30 @@ my @errors;
# Validate inputs # Validate inputs
my $file = &simplify_path($cwd.'/'.$in{'file'}); my $file = &simplify_path($cwd.'/'.$in{'file'});
&check_allowed_path($file); &check_allowed_path($file);
&error($text{'error_saving_file'}." : ".ucfirst($text{'error_write'})) &error($text{'error_saving_file'}." : ".
if (!can_write($file)); ucfirst($text{'error_write'}))
if (!can_write($file));
$data = $in{'data'}; $data = $in{'data'};
$data =~ s/\r\n/\n/g; $data =~ s/\r\n/\n/g;
if ( $in{'encoding'} && lc( $in{'encoding'} ) ne "utf-8" ) { if ($in{'encoding'} &&
eval { $data = Encode::encode( $in{'encoding'}, Encode::decode( 'utf-8', $data ) ) }; lc($in{'encoding'}) ne "utf-8") {
} eval {
$data = Encode::encode(
$in{'encoding'},
Encode::decode('utf-8', $data))
};
}
&open_tempfile(SAVE, ">$file") || &open_tempfile(SAVE, ">$file") ||
&error($text{'error_saving_file'}." : ".&html_escape("$!")); &error($text{'error_saving_file'}." : ".
&html_escape("$!"));
&print_tempfile(SAVE, $data); &print_tempfile(SAVE, $data);
&close_tempfile(SAVE); &close_tempfile(SAVE);
if ($in{'save_close'}) { if ($in{'save_close'}) {
&redirect("index.cgi?path=".&urlize($path)); &redirect("index.cgi?path=".&urlize($path));
} else { }
&redirect("edit_file.cgi?path=".&urlize($path). else {
"&file=".&urlize($in{'file'})); &redirect("edit_file.cgi?path=".&urlize($path).
} "&file=".&urlize($in{'file'}));
}

View File

@@ -8,19 +8,28 @@ get_paths();
$query = $in{'query'}; $query = $in{'query'};
&ui_print_header(undef, $text{'search_results'}." '". &ui_print_header(
&html_escape($query)."'", ""); undef,
$text{'search_results'} . " '" .
&html_escape($query) . "'", "");
print $head; print $head;
if($in{'caseins'}) { if ($in{'caseins'}) {
$criteria = '-iname'; $criteria = '-iname';
} else { }
$criteria = '-name' else {
} $criteria = '-name'
}
@list = split('\n', &backquote_logged( @list = split('\n', &backquote_logged(
"find ".quotemeta($cwd)." $criteria ".quotemeta("*$in{'query'}*"))); "find ".quotemeta($cwd).
@list = map { [ $_, stat($_), &clean_mimetype($_), -d $_ ] } @list; " $criteria ".
quotemeta("*$in{'query'}*")));
@list = map {
[$_, stat($_), &clean_mimetype($_), -d $_]
} @list;
print_interface(); print_interface();
&ui_print_footer("index.cgi?path=".&urlize($path), $text{'previous_page'}); &ui_print_footer(
"index.cgi?path=".&urlize($path),
$text{'previous_page'});

View File

@@ -27,41 +27,45 @@ $perms = "" if ($action eq '-x');
# Build params # Build params
my @types; my @types;
foreach my $type (@apply_to) { foreach my $type (@apply_to) {
if ($user && $type eq 'u') { if ($user && $type eq 'u') {
push(@types, "u:${user}:${perms}"); push(@types, "u:${user}:${perms}");
} }
if ($group && $type eq 'g') { if ($group && $type eq 'g') {
push(@types, "g:${group}:${perms}"); push(@types, "g:${group}:${perms}");
} }
if ($type =~ /^m|o$/) { if ($type =~ /^m|o$/) {
push(@types, "${type}::${perms}"); push(@types, "${type}::${perms}");
} }
} }
my $cmd = &has_command('setfacl'); my $cmd = &has_command('setfacl');
error($text{'acls_error'}) if (!$cmd); error($text{'acls_error'}) if (!$cmd);
# Params are not accepted in clear mode # Params are not accepted in clear mode
my $types; my $types;
if ($action ne '-b' && $action ne '-k') { if ($action ne '-b' && $action ne '-k') {
$types = quotemeta(join(',',@types)) if (@types); $types = quotemeta(join(',',@types))
if ($extra) { if (@types);
my @extra = split(/\s/, $extra); if ($extra) {
@extra = map { quotemeta($_) } @extra; my @extra = split(/\s/, $extra);
$types .= " ".join(' ', @extra) ; @extra = map { quotemeta($_) } @extra;
} $types .= " ".join(' ', @extra);
} }
my $args = quotemeta($action)." ".$types." ".$recursive; }
my $args = quotemeta($action).
" ".$types." ".$recursive;
$args =~ s/\s+/ /g; $args =~ s/\s+/ /g;
$args = &trim($args); $args = &trim($args);
foreach my $file (@files) { foreach my $file (@files) {
my $qfile = quotemeta("$cwd/$file"); my $qfile = quotemeta("$cwd/$file");
next if (!-r "$cwd/$file"); next if (!-r "$cwd/$file");
my $fullcmd = "$cmd $args $qfile"; my $fullcmd = "$cmd $args $qfile";
my $out = &backquote_logged("$fullcmd 2>&1 >/dev/null </dev/null"); my $out = &backquote_logged(
if ($?) { "$fullcmd 2>&1 >/dev/null </dev/null");
$out =~ s/^setfacl: //; if ($?) {
&error(&html_escape("$cmd $args $cwd/$file : $out")); $out =~ s/^setfacl: //;
} &error(&html_escape(
} "$cmd $args $cwd/$file : $out"));
}
}
&redirect("index.cgi?path=".&urlize($path)); &redirect("index.cgi?path=".&urlize($path));

View File

@@ -381,16 +381,19 @@
<div class="modal-body"> <div class="modal-body">
<form id="downFromUrlForm" action="http_download.cgi" method="post"> <form id="downFromUrlForm" action="http_download.cgi" method="post">
<div class="form-group"> <div class="form-group">
<label>$text{'dialog_file_url'}</label> <label style="display: block;">$text{'dialog_file_url'} <sup class="text-danger">&nbsp;*</sup>
<input name="link" type="url" class="form-control" data-placement="top" data-content="$text{'provide_url'}" data-trigger="manual"> <input name="link" type="url" class="form-control" data-placement="top" data-content="$text{'provide_url'}" data-trigger="manual" autocomplete="url" style="font-weight: normal;">
</label>
</div> </div>
<div class="form-group"> <div class="form-group">
<label>$text{'dialog_user_name'}</label> <label style="display: block;">$text{'dialog_user_name'}
<input name="username" type="text" class="form-control"> <input name="username" type="text" class="form-control" autocomplete="off" style="font-weight: normal;">
</label>
</div> </div>
<div class="form-group"> <div class="form-group">
<label>$text{'dialog_user_pass'}</label> <label style="display: block;">$text{'dialog_user_pass'}
<input name="password" type="password" class="form-control"> <input name="password" type="password" class="form-control" autocomplete="new-password" style="font-weight: normal;">
</label>
</div> </div>
<input type='hidden' name='path' value='$quote_escaped_path'> <input type='hidden' name='path' value='$quote_escaped_path'>
</form> </form>

View File

@@ -142,12 +142,15 @@
<div id="downFromUrlDialog" class="modal"> <div id="downFromUrlDialog" class="modal">
<form id="downFromUrlForm" action="http_download.cgi" method="post"> <form id="downFromUrlForm" action="http_download.cgi" method="post">
<div class="form-group"> <div class="form-group">
<label>$text{'dialog_file_url'}</label> <label style="display: block;">$text{'dialog_file_url'} <sup class="text-danger">&nbsp;*</sup><br>
<input name="link" type="url"><br> <input name="link" type="url" data-placement="top" data-content="$text{'provide_url'}" data-trigger="manual" autocomplete="url" style="font-weight: normal;">
<label>$text{'dialog_user_name'}</label> </label>
<input name="username" type="text"><br> <label style="display: block;">$text{'dialog_user_name'}<br>
<label>$text{'dialog_user_pass'}</label> <input name="username" type="text" autocomplete="off" style="font-weight: normal;">
<input name="password" type="password"> </label>
<label style="display: block;">$text{'dialog_user_pass'}<br>
<input name="password" type="password" autocomplete="new-password" style="font-weight: normal;">
</label>
<input type='hidden' name='path' value='$quote_escaped_path'> <input type='hidden' name='path' value='$quote_escaped_path'>
</div> </div>
</form> </form>

View File

@@ -22,8 +22,8 @@ $boundary = $1;
# Initialize progress tracker # Initialize progress tracker
&$cbfunc(0, $ENV{'CONTENT_LENGTH'}, undef, $in{'id'}); &$cbfunc(0, $ENV{'CONTENT_LENGTH'}, undef, $in{'id'});
#Read the data # Read the data
MAINLOOP: while(index($line,"$boundary--") == -1) { MAINLOOP: while (index($line, "$boundary--") == -1) {
# Reset vars on each loop # Reset vars on each loop
$file = undef; $file = undef;
$rest = undef; $rest = undef;
@@ -34,16 +34,19 @@ MAINLOOP: while(index($line,"$boundary--") == -1) {
if ($upload_max && $got > $upload_max) { if ($upload_max && $got > $upload_max) {
&error(&text('error_upload_emax', &nice_size($upload_max))); &error(&text('error_upload_emax', &nice_size($upload_max)));
} }
&$cbfunc($got, $ENV{'CONTENT_LENGTH'}, undef, $in{'id'}); &$cbfunc($got, $ENV{'CONTENT_LENGTH'},
undef, $in{'id'});
if ($line =~ /(\S+):\s*form-data(.*)$/) { if ($line =~ /(\S+):\s*form-data(.*)$/) {
$rest = $2; # We found form data definition, let`s check it # We found form data definition, let's check it
$rest = $2;
} }
else { else {
next; next;
} }
# Check if current form data part is file # Check if current form data part is file
while ($rest =~ /([a-zA-Z]*)=\"([^\"]*)\"(.*)/) { while ($rest =~
/([a-zA-Z]*)=\"([^\"]*)\"(.*)/) {
if ($1 eq 'filename') { if ($1 eq 'filename') {
$file = $2; $file = $2;
} }
@@ -52,40 +55,55 @@ MAINLOOP: while(index($line,"$boundary--") == -1) {
if (defined($file)) { if (defined($file)) {
my @st = stat($cwd); my @st = stat($cwd);
# If we have a dir, parse it and create a sub-tree first # If we have a dir, parse it and create a
# sub-tree first
if ($file =~ /\//) { if ($file =~ /\//) {
my ($dir) = $file =~ /^(.*)\/[^\/]+$/; my ($dir) =
$file =~ /^(.*)\/[^\/]+$/;
if ($dir) { if ($dir) {
my @dirs = split('/', $dir); my @dirs = split('/', $dir);
$dir = '/'; $dir = '/';
# If overwriting is not allowed check for dupes # If overwriting is not allowed
# check for dupes
if (!$in{'overwrite_existing'}) { if (!$in{'overwrite_existing'}) {
if ($dirs[0] && -e "$cwd/$dirs[0]") { if ($dirs[0] &&
# As only one directory upload at a time allowed -e "$cwd/$dirs[0]") {
# check if parent exists and if it does add # As only one directory upload
# predictable suffix, like `dir(1)` or `dir(2)` # at a time allowed check if
# parent exists and if it does
# add predictable suffix, like
# `dir(1)` or `dir(2)`
if (!$uploaded_dir) { if (!$uploaded_dir) {
my $__ = 1; my $__ = 1;
for (;;) { for (;;) {
my $new_dir_name = "$dirs[0](" . $__++ . ")"; my $n =
if (!-e "$cwd/$new_dir_name") { "$dirs[0](" .
$uploaded_dir = $new_dir_name; $__++ . ")";
last; if (!-e
} "$cwd/$n") {
$uploaded_dir =
$n;
last;
}
} }
} }
} }
else { else {
$uploaded_dir = $dirs[0]; $uploaded_dir =
$dirs[0];
} }
$file =~ s/^(\Q$dirs[0]\E)/$uploaded_dir/; $file =~
$dirs[0] = $uploaded_dir; s/^(\Q$dirs[0]\E)/$uploaded_dir/;
} $dirs[0] =
$uploaded_dir;
}
foreach my $updir (@dirs) { foreach my $updir (@dirs) {
$dir .= "$updir/"; $dir .= "$updir/";
if (!-e "$cwd$dir") { if (!-e "$cwd$dir") {
mkdir("$cwd$dir"); mkdir("$cwd$dir");
&set_ownership_permissions($st[4], $st[5], undef, "$cwd$dir"); set_ownership_permissions(
$st[4], $st[5],
undef, "$cwd$dir");
} }
} }
} }
@@ -93,85 +111,121 @@ MAINLOOP: while(index($line,"$boundary--") == -1) {
# In case of a regular file check for dupes # In case of a regular file check for dupes
if (!$in{'overwrite_existing'}) { if (!$in{'overwrite_existing'}) {
if ($file && -e "$cwd/$file") { if ($file && -e "$cwd/$file") {
# If file exists add predictable suffix, like `file(1)` or `file(2)` # If the file exists, add a suffix
my ($file_name, $file_extension) = $file =~ /(?|(.*)\.((?|tar|wbm|wbt)\..*)|(.*)\.([a-zA-Z]+\.(?|gpg|pgp))|(.*)\.(?=(.*))|(.*)())/; my ($file_name,
$file_extension = ".$file_extension" if ($file_extension); $file_extension) =
$file =~ /(?|
(.*)\.((?|tar|wbm|wbt)\..*) |
(.*)\.([a-zA-Z]+\.(?|gpg|pgp)) |
(.*)\.(?=(.*)) |
(.*)()
)/x;
$file_extension =
".$file_extension"
if ($file_extension);
my $__ = 1; my $__ = 1;
for (;;) { for (;;) {
my $new_file_name = "$file_name(" . $__++ . ")"; my $n = "$file_name(" .
if (!-e "$cwd/$new_file_name$file_extension") { $__++ . ")";
$file = "$new_file_name$file_extension"; if (!-e "$cwd/$n" .
"$file_extension") {
$file =
"$n$file_extension";
last; last;
} }
} }
} }
} }
# OK, we have a file, let`s save it # OK, we have a file, let's save it
my $full = "$cwd/$file"; my $full = "$cwd/$file";
my $newfile = !-e $full; my $newfile = !-e $full;
if (!open(OUTFILE, ">$full")) { if (!open(OUTFILE, ">$full")) {
push @errors, "$text{'error_opening_file_for_writing'} $path/$file - $!"; push @errors,
"$text{'error_opening_file_for_writing'}" .
" $path/$file - $!";
next; next;
} }
else { else {
binmode(OUTFILE); binmode(OUTFILE);
if ($newfile) { if ($newfile) {
# Copy ownership from parent dir # Copy ownership from parent dir
&set_ownership_permissions($st[4], $st[5], undef, $full); &set_ownership_permissions(
$st[4], $st[5],
undef, $full);
} }
# Skip "content-type" as we work in binmode anyway and # Skip "content-type" as we work in
# skip empty line # binmode anyway and skip empty line
<STDIN>; <STDIN>;
<STDIN>; <STDIN>;
# Read all lines until next boundary or form data end # Read all lines until next boundary
while(1) { # or form data end
while (1) {
$line = <STDIN>; $line = <STDIN>;
if (!defined($line)) { if (!defined($line)) {
push @errors, "Unexpected end of input"; push @errors,
"Unexpected " .
"end of input";
last MAINLOOP; last MAINLOOP;
} }
# Inform progress tracker about our actions # Inform progress tracker
$got += length($line); # about our actions
&$cbfunc($got, $ENV{'CONTENT_LENGTH'}, $file, $in{'id'}); $got += length($line);
&$cbfunc(
$got,
$ENV{'CONTENT_LENGTH'},
$file, $in{'id'});
# Some brainf###ing to deal with last CRLF # Some brainf###ing to deal
if (index($line,"$boundary") != -1 || # with last CRLF
index($line,"$boundary--") != -1) { if (index($line,
chop($prevline); "$boundary") != -1 ||
chop($prevline); index($line,
if (!print OUTFILE $prevline) { "$boundary--") != -1) {
push @errors, "text{'error_writing_file'} $path/$file"; chop($prevline);
last MAINLOOP; chop($prevline);
} if (!print OUTFILE
$prevline) {
push @errors,
"$text{'error_writing_file'} " .
"$path/$file";
last MAINLOOP;
}
last; last;
} }
else { else {
if (!print OUTFILE $prevline) { if (!print OUTFILE
push @errors, "text{'error_writing_file'} $path/$file"; $prevline) {
last MAINLOOP; push @errors,
"$text{'error_writing_file'} " .
"$path/$file";
last MAINLOOP;
} }
$prevline = $line; $prevline = $line;
} }
} }
# File saved, let`s go further # File saved, let's go further
close(OUTFILE); close(OUTFILE);
# Store which file were uploaded # Store which file were uploaded
my $fpath = $cwd; my $fpath = $cwd;
my $ffile = $file; my $ffile = $file;
my @subdirs = split('/', $ffile); my @subdirs = split('/', $ffile);
if (@subdirs > 1) { if (@subdirs > 1) {
$ffile = pop(@subdirs); $ffile = pop(@subdirs);
$fpath .= ("/" . join('/', @subdirs)); $fpath .= ("/" .
} join('/', @subdirs));
push(@uploaded_files, {'path' => $fpath, 'file' => $ffile}); }
} push(@uploaded_files,
{'path' => $fpath,
'file' => $ffile});
}
} }
else { else {
# Just skip everything until next boundary or form end # Just skip everything until next boundary
# or form end
while (index($line, "$boundary") == -1 || while (index($line, "$boundary") == -1 ||
index($line, "$boundary--") == -1) { index($line, "$boundary--") == -1) {
$line = <STDIN>; $line = <STDIN>;
@@ -181,16 +235,18 @@ MAINLOOP: while(index($line,"$boundary--") == -1) {
# Extract and delete uploaded files # Extract and delete uploaded files
if ($in{'extract_uploaded'}) { if ($in{'extract_uploaded'}) {
my @eerrors = &extract_files(\@uploaded_files, 1); my @eerrors =
&extract_files(\@uploaded_files, 1);
@errors = (@eerrors, @errors) @errors = (@eerrors, @errors)
if (@eerrors); if (@eerrors);
} }
# Everything finished, inform progress tracker # Everything finished, inform progress tracker
&$cbfunc(-1, $ENV{'CONTENT_LENGTH'}, undef, $in{'id'}); &$cbfunc(-1, $ENV{'CONTENT_LENGTH'},
undef, $in{'id'});
if (scalar(@errors) > 0) { if (scalar(@errors) > 0) {
print_errors(@errors); print_errors(@errors);
} }
else { else {
&redirect("index.cgi?path=".&urlize($path)); &redirect("index.cgi?path=" . &urlize($path));
} }

View File

@@ -20,7 +20,7 @@ else {
$lconf = $log->{'members'}; $lconf = $log->{'members'};
} }
print &ui_form_start("save_log.cgi", "post"); print &ui_form_start("save_log.cgi", "post", undef, "id='edit_log_form'");
print &ui_hidden("new", $in{'new'}),"\n"; print &ui_hidden("new", $in{'new'}),"\n";
print &ui_hidden("idx", $in{'idx'}),"\n"; print &ui_hidden("idx", $in{'idx'}),"\n";
print &ui_hidden("global", $in{'global'}),"\n"; print &ui_hidden("global", $in{'global'}),"\n";
@@ -176,16 +176,16 @@ elsif ($in{'new'}) {
print &ui_form_end([ [ 'create', $text{'create'} ] ], "100%"); print &ui_form_end([ [ 'create', $text{'create'} ] ], "100%");
} }
else { else {
print &ui_form_end([ [ 'save', $text{'save'} ], print &ui_form_end_side_by_side(
[ 'now', $text{'edit_now'} ], "edit_log_form",
[ 'delete', $text{'delete'} ] ], "100%"); [ [ 'save', $text{'save'} ],
[ 'now', $text{'edit_now'} ],
print &ui_form_start("edit_log.cgi", [ 'delete', $text{'delete'} ] ],
undef, undef, undef, 'ui_form ui_table_end_submit_right'); [ &ui_form_start("edit_log.cgi").
print &ui_hidden("clone", $in{'idx'}); &ui_hidden("clone", $in{'idx'}).
print &ui_hidden("new", 1); &ui_hidden("new", 1).
print &ui_submit($text{'edit_clone'}); &ui_submit($text{'edit_clone'}).
print &ui_form_end(); &ui_form_end(undef, undef, 1) ]);
} }
&ui_print_footer("", $text{'index_return'}); &ui_print_footer("", $text{'index_return'});

View File

@@ -1721,7 +1721,8 @@ if ($header{'user-agent'} =~ /webmin/i ||
# Check for SSL authentication # Check for SSL authentication
my $trust_ssl = $config{'trust_real_ip'} && !$config{'no_trust_ssl'}; my $trust_ssl = $config{'trust_real_ip'} && !$config{'no_trust_ssl'};
if ($use_ssl && $verified_client || if ($use_ssl && $verified_client ||
$trust_ssl && $header{'x-ssl-client-dn'}) { $trust_ssl && $header{'x-ssl-client-dn'} &&
$header{'x-ssl-client-verifiy'} !~ /^(failed|none)/i) {
if ($use_ssl && $verified_client) { if ($use_ssl && $verified_client) {
$peername = Net::SSLeay::X509_NAME_oneline( $peername = Net::SSLeay::X509_NAME_oneline(
Net::SSLeay::X509_get_subject_name( Net::SSLeay::X509_get_subject_name(
@@ -1817,7 +1818,7 @@ if ($config{'session'} && !$deny_authentication &&
} }
&run_logout_script($louser, $sid, &run_logout_script($louser, $sid,
$loghost, $localip); $loghost, $localip);
&write_logout_utmp($louser, $actphost); &write_logout_utmp($louser, $acpthost);
} }
} }
elsif ($in{'session'}) { elsif ($in{'session'}) {

View File

@@ -91,7 +91,7 @@ if (!$gconfig{'tempdir'} && &foreign_available("webmin")) {
foreach my $disk (sort { length($b->{'dir'}) <=> foreach my $disk (sort { length($b->{'dir'}) <=>
length($a->{'dir'}) } @$disks) { length($a->{'dir'}) } @$disks) {
if (&is_under_directory($disk->{'dir'}, $tmp)) { if (&is_under_directory($disk->{'dir'}, $tmp)) {
if ($disk->{'total'} <= $small) { if ($disk->{'total'} && $disk->{'total'} <= $small) {
# Too small # Too small
push(@rv, { 'type' => 'warning', push(@rv, { 'type' => 'warning',
'level' => 'info', 'level' => 'info',

View File

@@ -13,7 +13,8 @@ if (!$conf) {
&ui_print_footer("", $text{'index_return'}); &ui_print_footer("", $text{'index_return'});
exit; exit;
} }
($mysqld) = grep { $_->{'name'} eq 'mysqld' } @$conf; ($mysqld) = grep { $_->{'name'} eq 'mysqld' ||
$_->{'name'} eq 'mariadb' } @$conf;
$mysqld || &error($text{'cnf_emysqld'}); $mysqld || &error($text{'cnf_emysqld'});
$mems = $mysqld->{'members'}; $mems = $mysqld->{'members'};

View File

@@ -13,7 +13,8 @@ if (!$conf) {
&ui_print_footer("", $text{'index_return'}); &ui_print_footer("", $text{'index_return'});
exit; exit;
} }
($mysqld) = grep { $_->{'name'} eq 'mysqld' } @$conf; ($mysqld) = grep { $_->{'name'} eq 'mysqld' ||
$_->{'name'} eq 'mariadb' } @$conf;
$mysqld || &error($text{'cnf_emysqld'}); $mysqld || &error($text{'cnf_emysqld'});
$mems = $mysqld->{'members'}; $mems = $mysqld->{'members'};

View File

@@ -11,7 +11,8 @@ foreach my $l (&get_all_mysqld_files()) {
&lock_file($l); &lock_file($l);
} }
$conf = &get_mysql_config(); $conf = &get_mysql_config();
($mysqld) = grep { $_->{'name'} eq 'mysqld' } @$conf; ($mysqld) = grep { $_->{'name'} eq 'mysqld' ||
$_->{'name'} eq 'mariadb' } @$conf;
$mysqld || &error($text{'cnf_emysqld'}); $mysqld || &error($text{'cnf_emysqld'});
$mems = $mysqld->{'members'}; $mems = $mysqld->{'members'};

View File

@@ -11,7 +11,8 @@ foreach my $l (&get_all_mysqld_files()) {
&lock_file($l); &lock_file($l);
} }
$conf = &get_mysql_config(); $conf = &get_mysql_config();
($mysqld) = grep { $_->{'name'} eq 'mysqld' } @$conf; ($mysqld) = grep { $_->{'name'} eq 'mysqld' ||
$_->{'name'} eq 'mariadb' } @$conf;
$mysqld || &error($text{'cnf_emysqld'}); $mysqld || &error($text{'cnf_emysqld'});
if ($in{'gen'}) { if ($in{'gen'}) {

View File

@@ -14,6 +14,8 @@ if (!%pinfo) {
exit; exit;
} }
print &ui_form_start("renice_proc.cgi");
print &ui_hidden("pid", $ARGV[0]);
print &ui_table_start($text{'edit_title'}, "width=100%", 4, print &ui_table_start($text{'edit_title'}, "width=100%", 4,
[ "width=20%", "width=30%", "width=20%", "width=30%" ]); [ "width=20%", "width=30%", "width=20%", "width=30%" ]);
@@ -49,16 +51,29 @@ print &ui_table_row($text{'size'}, $pinfo{'bytes'} ? &nice_size($pinfo{'bytes'})
print &ui_table_row($text{'runtime'}, $pinfo{'time'}); print &ui_table_row($text{'runtime'}, $pinfo{'time'});
# Nice level # Nice level
print &ui_form_start("renice_proc.cgi"); local $nice_value = $pinfo{'nice'};
print &ui_hidden("pid", $ARGV[0]); $nice_value =~ s/^\s+// if (defined($nice_value));
$nice_value =~ s/\s+$// if (defined($nice_value));
$nice_value =~ s/^\+// if (defined($nice_value));
local $submitjs =
"onchange='this.parentNode.getElementsByTagName(\"input\")[0].click()'";
local $l = scalar(@nice_range);
print &ui_table_row(&hlink($text{'nice'},"nice"), print &ui_table_row(&hlink($text{'nice'},"nice"),
&indexof($pinfo{nice}, @nice_range) < 0 ? $pinfo{nice} : &ui_select("nice", $nice_value,
&nice_selector("nice", $pinfo{nice}). [ map { [ $_, $_.($_ == $nice_range[0] ? " ($text{'edit_prihigh'})" :
&ui_submit($text{'proc_submit'}), 3); $_ == 0 ? " ($text{'edit_pridef'})" :
$_ == $nice_range[$l-1]
? " ($text{'edit_prilow'})"
: "") ] } @nice_range ],
1, 0, 1, 0, $submitjs).
&ui_submit("", "nice_submit_hidden", 0, "style='display:none'"), 3);
# IO scheduling class, if support # IO scheduling class, if support
if (defined(&os_list_scheduling_classes) && local @classes;
(@classes = &os_list_scheduling_classes())) { local ($class, $prio);
local $has_sched = defined(&os_list_scheduling_classes) &&
(@classes = &os_list_scheduling_classes());
if ($has_sched) {
($class, $prio) = &os_get_scheduling_class($pinfo{'pid'}); ($class, $prio) = &os_get_scheduling_class($pinfo{'pid'});
($got) = grep { $_->[0] == $class } @classes; ($got) = grep { $_->[0] == $class } @classes;
if (!$got) { if (!$got) {
@@ -66,14 +81,18 @@ if (defined(&os_list_scheduling_classes) &&
unshift(@classes, [ $class, $text{'default'} ]); unshift(@classes, [ $class, $text{'default'} ]);
} }
print &ui_table_row(&hlink($text{'sclass'},"sclass"), print &ui_table_row(&hlink($text{'sclass'},"sclass"),
&ui_select("sclass", $class, \@classes)); &ui_select("sclass", $class, \@classes, 1, 0, 0, 0,
$submitjs).
&ui_submit("", "sclass_submit_hidden", 0,
"style='display:none'"));
print &ui_table_row(&hlink($text{'sprio'},"sprio"), print &ui_table_row(&hlink($text{'sprio'},"sprio"),
&ui_select("sprio", $prio, &ui_select("sprio", $prio,
[ &os_list_scheduling_priorities() ], 1, 0, 1)); [ &os_list_scheduling_priorities() ], 1, 0, 1, 0,
$submitjs).
&ui_submit("", "sprio_submit_hidden", 0,
"style='display:none'"));
} }
print &ui_form_end();
# Extra OS-specific info # Extra OS-specific info
foreach $k (keys %pinfo) { foreach $k (keys %pinfo) {
if ($k =~ /^_/ && $info_arg_map{$k}) { if ($k =~ /^_/ && $info_arg_map{$k}) {
@@ -81,6 +100,7 @@ foreach $k (keys %pinfo) {
} }
} }
print &ui_table_end(); print &ui_table_end();
print &ui_form_end();
print "<table width=100%><tr>\n"; print "<table width=100%><tr>\n";
if ($access{'simple'}) { if ($access{'simple'}) {

View File

@@ -1,58 +0,0 @@
#!/usr/local/bin/perl
# edit_ffile.cgi
# Allow editing of a filter config file
require './qmail-lib.pl';
&ReadParse();
&ui_print_header(undef, $text{'ffile_title'}, "");
open(FILE, "<$in{'file'}");
while(<FILE>) {
s/\r|\n//g;
if (/^(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) {
push(@filter, [ $1, $2, $3, $4 ]);
}
elsif (/^(2)\s+(\S+)$/) {
$other = $2;
}
}
close(FILE);
print "<b>",&text('ffile_desc', "<tt>$in{'file'}</tt>"),"</b><p>\n";
print "<form action=save_ffile.cgi method=post enctype=multipart/form-data>\n";
print "<input type=hidden name=file value=\"$in{'file'}\">\n";
print "<input type=hidden name=name value=\"$in{'name'}\">\n";
$i = 0;
foreach $f (@filter, [ 1, '', '', '' ]) {
$field = "<select name=field_$i>\n";
foreach $ft ('', 'from', 'to', 'subject', 'cc', 'body') {
$field .= sprintf "<option value='%s' %s>%s</option>\n",
$ft, $f->[2] eq $ft ? "selected" : "",
$ft ? $text{"ffile_$ft"} : "&nbsp";
}
$field .= "</select>\n";
$what = "<select name=what_$i>\n";
$what .= sprintf "<option value=0 %s>%s</option>\n",
$f->[0] == 0 ? "selected" : "", $text{"ffile_what0"};
$what .= sprintf "<option value=1 %s>%s</option>\n",
$f->[0] == 1 ? "selected" : "", $text{"ffile_what1"};
$what .= "</select>\n";
$match = "<input name=match_$i size=20 value='$f->[3]'>\n";
$action = "<input name=action_$i size=30 value='$f->[1]'>\n";
print &text('ffile_line', $field, $what, $match, $action),"<br>\n";
$i++;
}
print &text('ffile_other',
"<input name=other size=30 value='$other'>"),"<br>\n";
print "<input type=submit value=\"$text{'save'}\">\n";
print "</form>\n";
&ui_print_footer("edit_alias.cgi?name=$in{'name'}", $text{'aform_return'});

View File

@@ -1,53 +0,0 @@
#!/usr/local/bin/perl
# edit_rfile.cgi
# Display the contents of an autoreply file
require './qmail-lib.pl';
&ReadParse();
&ui_print_header(undef, $text{'rfile_title'}, "");
open(FILE, "<$in{'file'}");
while(<FILE>) {
if (/^Reply-Tracking:\s*(.*)/) {
$replies = $1;
}
elsif (/^Reply-Period:\s*(.*)/) {
$period = $1;
}
else {
push(@lines, $_);
}
}
close(FILE);
print "<b>",&text('rfile_desc', "<tt>$in{'file'}</tt>"),"</b><p>\n";
print "$text{'rfile_desc2'}<p>\n";
print "<form action=save_rfile.cgi method=post enctype=multipart/form-data>\n";
print "<input type=hidden name=file value=\"$in{'file'}\">\n";
print "<input type=hidden name=name value=\"$in{'name'}\">\n";
print "<textarea name=text rows=20 cols=80 $config{'wrap_mode'}>",
join("", @lines),"</textarea><p>\n";
print $text{'rfile_replies'},"\n";
printf "<input type=radio name=replies_def value=1 %s> %s\n",
$replies eq '' ? "checked" : "", $text{'rfile_none'};
printf "<input type=radio name=replies_def value=0 %s> %s\n",
$replies eq '' ? "" :"checked", $text{'rfile_file'};
printf "<input name=replies size=30 value='%s'> %s<br>\n",
$replies, &file_chooser_button("replies");
print "&nbsp;" x 3;
print $text{'rfile_period'},"\n";
printf "<input type=radio name=period_def value=1 %s> %s\n",
$period eq '' ? "checked" : "", $text{'rfile_default'};
printf "<input type=radio name=period_def value=0 %s>\n",
$period eq '' ? "" :"checked";
printf "<input name=period size=5 value='%s'> %s<p>\n",
$period, $text{'rfile_secs'};
print "<input type=submit value=\"$text{'save'}\"> ",
"<input type=reset value=\"$text{'rfile_undo'}\">\n";
print "</form>\n";
&ui_print_footer("edit_alias.cgi?name=$in{'name'}", $text{'aform_return'});

View File

@@ -1,27 +0,0 @@
#!/usr/local/bin/perl
# save_afile.cgi
# Save a filter file
require './qmail-lib.pl';
&ReadParseMime();
&error_setup($text{'ffile_err'});
my %access = &get_module_acl();
my $base = &simplify_path($access{'apath'} || $qmail_alias_dir);
my $file = &simplify_path($in{'file'});
&is_under_directory($base, $file) || &error(&text('ffile_efile', $in{'file'}));
$in{'file'} = $file;
for($i=0; defined($in{"field_$i"}); $i++) {
next if (!$in{"field_$i"});
$in{"match_$i"} || &error($text{'ffile_ematch'});
$in{"action_$i"} || &error($text{'ffile_eaction'});
push(@filter, $in{"what_$i"}." ".$in{"action_$i"}." ".
$in{"field_$i"}." ".$in{"match_$i"}."\n");
}
push(@filter, "2 ".$in{'other'}."\n") if ($in{'other'});
&open_lock_tempfile(FILE, ">$in{'file'}");
&print_tempfile(FILE, @filter);
&close_tempfile(FILE);
&redirect("edit_alias.cgi?name=$in{'name'}");

View File

@@ -1,29 +0,0 @@
#!/usr/local/bin/perl
# save_rfile.cgi
# Save an autoreply file
require './qmail-lib.pl';
&ReadParseMime();
my %access = &get_module_acl();
my $base = &simplify_path($access{'apath'} || $qmail_alias_dir);
my $file = &simplify_path($in{'file'});
&is_under_directory($base, $file) || &error(&text('rfile_efile', $in{'file'}));
$in{'file'} = $file;
$in{'replies_def'} || $in{'replies'} =~ /^\/\S+/ ||
&error($text{'rfile_ereplies'});
$in{'period_def'} || $in{'period'} =~ /^\d+$/ ||
&error($text{'rfile_eperiod'});
$in{'text'} =~ s/\r//g;
&open_lock_tempfile(FILE, ">$in{'file'}");
if (!$in{'replies_def'}) {
&print_tempfile(FILE, "Reply-Tracking: $in{'replies'}\n");
}
if (!$in{'period_def'}) {
&print_tempfile(FILE, "Reply-Period: $in{'period'}\n");
}
&print_tempfile(FILE, $in{'text'});
&close_tempfile(FILE);
&redirect("edit_alias.cgi?name=$in{'name'}");

View File

@@ -4,6 +4,8 @@
require './status-lib.pl'; require './status-lib.pl';
$access{'sched'} || &error($text{'sched_ecannot'}); $access{'sched'} || &error($text{'sched_ecannot'});
&foreign_require("mailboxes");
my %mconfig = &foreign_config("mailboxes");
&ui_print_header(undef, $text{'sched_title'}, ""); &ui_print_header(undef, $text{'sched_title'}, "");
print &ui_form_start("save_sched.cgi", "post"); print &ui_form_start("save_sched.cgi", "post");
@@ -52,21 +54,33 @@ print &ui_table_row($text{'sched_warn'},
# Send email to # Send email to
my $e = $config{'sched_email'}; my $e = $config{'sched_email'};
my @opts = ( [ 1, $text{'sched_none'} ], my $edef = (!$e || $e eq '*' && !$gconfig{'webmin_email_to'}) ? 1 :
[ 0, &ui_textbox("email", $e eq '*' ? undef : $e, 30) ] ); $e eq '*' ? 2 : 0;
my $edis = &js_disable_inputs([ "email" ], [ ], "onClick");
my $een = &js_disable_inputs([ ], [ "email" ], "onClick");
my @opts = (
[ 1, $text{'sched_none'}."<br>", $edis ],
[ 0, $text{'sched_email_custom'}." ".
&ui_textbox("email", $e eq '*'
? undef
: $e, 30, $edef != 0), $een
] );
if ($gconfig{'webmin_email_to'}) { if ($gconfig{'webmin_email_to'}) {
splice(@opts, 1, 0, [ 2, &text('sched_email_def', splice(@opts, 1, 0, [ 2, &text('sched_email_def',
"<tt>$gconfig{'webmin_email_to'}</tt>") ]); "<tt>$gconfig{'webmin_email_to'}</tt>")."<br>",
$edis ]);
} }
print &ui_table_row($text{'sched_email'}, print &ui_table_row($text{'sched_email'},
&ui_radio("email_def", &ui_radio("email_def", $edef, \@opts));
!$e ? 1 : $e eq '*' ? 2 : 0,
\@opts));
# From: address # From: address
my $fromdef = $mconfig{'webmin_from'} =~ /\@/ ? $mconfig{'webmin_from'} :
!$mconfig{'webmin_from'}
? "webmin-noreply\@".&mailboxes::get_from_domain()
: "$mconfig{'webmin_from'}\@".&mailboxes::get_from_domain();
print &ui_table_row($text{'sched_from'}, print &ui_table_row($text{'sched_from'},
&ui_opt_textbox("from", $config{'sched_from'}, 30, &ui_opt_textbox("from", $config{'sched_from'}, 30,
"$text{'default'} (webmin)"), 3); &text('sched_from_def', "<tt>$fromdef</tt>")), 3);
# SMTP server # SMTP server
print &ui_table_row($text{'sched_smtp'}, print &ui_table_row($text{'sched_smtp'},

View File

@@ -148,11 +148,13 @@ sched_title=Scheduled Monitoring
sched_header=Scheduled background monitoring options sched_header=Scheduled background monitoring options
sched_mode=Scheduled checking enabled? sched_mode=Scheduled checking enabled?
sched_email=Email status report to sched_email=Email status report to
sched_email_custom=Custom address
sched_email_def=System default ($1) sched_email_def=System default ($1)
sched_pager=Page status report to number sched_pager=Page status report to number
sched_none=Don't send email sched_none=Don't send email
sched_pnone=Don't send pages sched_pnone=Don't send pages
sched_from=From: address for email sched_from=From address for the email
sched_from_def=System default ($1)
sched_int=Check every sched_int=Check every
sched_period_0=minutes sched_period_0=minutes
sched_period_1=hours sched_period_1=hours

View File

@@ -18,7 +18,8 @@ if (@tmpls) {
$msg = $tmpl->{'email'}; $msg = $tmpl->{'email'};
$msg = substr($msg, 0, 80)." ..." if (length($msg) > 80); $msg = substr($msg, 0, 80)." ..." if (length($msg) > 80);
print &ui_checked_columns_row( print &ui_checked_columns_row(
[ &ui_link("edit_tmpl.cgi?id=$tmpl->{'id'}","$tmpl->{'desc'}"), &html_escape($msg) ], [ &ui_link("edit_tmpl.cgi?id=$tmpl->{'id'}",
&html_escape($tmpl->{'desc'})), &html_escape($msg) ],
\@tds, "d", $tmpl->{'id'}); \@tds, "d", $tmpl->{'id'});
} }
print &ui_columns_end(); print &ui_columns_end();

View File

@@ -8,7 +8,10 @@ $access{'sched'} || &error($text{'sched_ecannot'});
&error_setup($text{'sched_err'}); &error_setup($text{'sched_err'});
# Parse and save inputs # Parse and save inputs
if ($in{'email_def'} == 1) { if ($in{'email_def'} == 2 && !$gconfig{'webmin_email_to'}) {
$in{'email_def'} = 1;
}
if ($in{'email_def'} == 0) {
$in{'email'} =~ /\S/ || &error($text{'sched_eemail'}); $in{'email'} =~ /\S/ || &error($text{'sched_eemail'});
} }
$config{'sched_email'} = $in{'email_def'} == 1 ? '' : $config{'sched_email'} = $in{'email_def'} == 1 ? '' :

150
ui-lib.pl
View File

@@ -1,5 +1,6 @@
use vars qw($theme_no_table $ui_radio_selector_donejs $module_name use vars qw($theme_no_table $ui_radio_selector_donejs $module_name
$ui_multi_select_donejs, $ui_formcount); $ui_multi_select_donejs, $ui_formcount,
$ui_form_end_side_by_side_donecss);
=head1 ui-lib.pl =head1 ui-lib.pl
@@ -761,38 +762,137 @@ return &theme_ui_form_end(@_) if (defined(&theme_ui_form_end));
my ($buttons, $width, $nojs) = @_; my ($buttons, $width, $nojs) = @_;
my $rv; my $rv;
if ($buttons && @$buttons) { if ($buttons && @$buttons) {
$rv .= "<table class='ui_form_end_buttons' ".($width ? " width='$width'" : "")."><tr>\n"; $rv .= &_ui_form_end_buttons_table($buttons, $width);
my $b;
foreach $b (@$buttons) {
if (ref($b)) {
$rv .= "<td".(!$width ? "" :
$b eq $buttons->[0] ? " align='left'" :
$b eq $buttons->[@$buttons-1] ?
" align='right'" : " align='center'").">".
&ui_submit($b->[1], $b->[0], $b->[3], $b->[4]).
($b->[2] ? " ".$b->[2] : "")."</td>\n";
}
elsif ($b) {
$rv .= "<td>$b</td>\n";
}
else {
$rv .= "<td>&nbsp;&nbsp;</td>\n";
}
}
$rv .= "</tr></table>\n";
} }
$rv .= "</form>\n"; $rv .= "</form>\n";
return $rv.&_ui_form_end_nojs($nojs);
}
=head2 ui_form_end_side_by_side(form-id, [&leftbuttons], [&rightbuttons], [width], [nojs])
Returns HTML for the end of a form with button groups aligned to the left
and right. The left buttons use the same format as ui_form_end and are linked
back to the main form by the HTML5 C<form> attribute, allowing the right side
to contain separate forms or custom HTML without invalid nesting.
=item form-id - HTML id of the form started by ui_form_start.
=item leftbuttons - Buttons for the left side, in the same format as ui_form_end.
=item rightbuttons - Optional buttons or HTML for the right side. Each element
may be either a ui_form_end button array ref or raw HTML.
=item width - Optional CSS width for the action bar. Defaults to 100%.
=item nojs - Set to 1 to suppress ui_opt_textbox re-enable JavaScript.
=cut
sub ui_form_end_side_by_side
{
$ui_formcount++;
return &theme_ui_form_end_side_by_side(@_)
if (defined(&theme_ui_form_end_side_by_side));
my ($formid, $leftbuttons, $rightbuttons, $width, $nojs) = @_;
my $rv;
$rv .= "</form>\n";
if (($leftbuttons && @$leftbuttons) || ($rightbuttons && @$rightbuttons)) {
$rv .= &_ui_form_end_side_by_side_css();
$rv .= "<div class='ui_form_end_side_by_side'".
" style='width:".&quote_escape($width || "100%")."'>\n";
if ($leftbuttons && @$leftbuttons) {
$rv .= "<div class='ui_form_end_side ui_form_end_side_left'>\n".
&_ui_form_end_buttons_table($leftbuttons, undef, $formid,
"ui_form_end_buttons_left").
"</div>\n";
}
if ($rightbuttons && @$rightbuttons) {
$rv .= "<div class='ui_form_end_side ui_form_end_side_right'>\n".
&_ui_form_end_buttons_table($rightbuttons, undef, undef,
"ui_form_end_buttons_right").
"</div>\n";
}
$rv .= "</div>\n";
}
$rv .= &_ui_form_end_nojs($nojs);
return $rv;
}
sub _ui_form_end_buttons_table
{
my ($buttons, $width, $formid, $class) = @_;
return "" if (!$buttons || !@$buttons);
my $rv = "<table class='ui_form_end_buttons".
($class ? " $class" : "")."' ".
($width ? "width='$width'" : "")."><tr>\n";
my $b;
foreach $b (@$buttons) {
if (ref($b)) {
my $tags = $b->[4];
if ($formid && (!$tags || $tags !~ /\bform\s*=/i)) {
$tags .= ($tags ? " " : "").
"form=\"".&quote_escape($formid)."\"";
}
$rv .= "<td".(!$width ? "" :
$b eq $buttons->[0] ? " align='left'" :
$b eq $buttons->[@$buttons-1] ?
" align='right'" : " align='center'").">".
&ui_submit($b->[1], $b->[0], $b->[3], $tags).
($b->[2] ? " ".$b->[2] : "")."</td>\n";
}
elsif ($b) {
$rv .= "<td>$b</td>\n";
}
else {
$rv .= "<td>&nbsp;&nbsp;</td>\n";
}
}
$rv .= "</tr></table>\n";
return $rv;
}
sub _ui_form_end_side_by_side_css
{
return "" if ($ui_form_end_side_by_side_donecss++);
return <<'EOF';
<style type='text/css'>
.ui_form_end_side_by_side {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: space-between;
gap: 0 5px;
}
.ui_form_end_side_by_side .ui_form_end_side_left {
flex: 1 1 auto;
min-width: 0;
}
.ui_form_end_side_by_side .ui_form_end_side_right {
flex: 0 0 auto;
}
.ui_form_end_side_by_side .ui_form_end_buttons {
width: auto;
}
</style>
EOF
}
sub _ui_form_end_nojs
{
my ($nojs) = @_;
if ( !$nojs ) { if ( !$nojs ) {
# When going back to a form, re-enable any text fields generated by # When going back to a form, re-enable any text fields generated by
# ui_opt_textbox that aren't in the default state. # ui_opt_textbox that aren't in the default state.
$rv .= "<script type='text/javascript'>\n"; my $rv = "<script type='text/javascript'>\n";
$rv .= "var opts = document.getElementsByClassName('ui_opt_textbox');\n"; $rv .= "(function () {\n";
$rv .= "for(var i=0; i<opts.length; i++) {\n"; $rv .= "const opts = document.getElementsByClassName('ui_opt_textbox');\n";
$rv .= "for(let i=0; i<opts.length; i++) {\n";
$rv .= " opts[i].disabled = document.getElementsByName(opts[i].name+'_def')[0].checked;\n"; $rv .= " opts[i].disabled = document.getElementsByName(opts[i].name+'_def')[0].checked;\n";
$rv .= "}\n"; $rv .= "}\n";
$rv .= "})();\n";
$rv .= "</script>\n"; $rv .= "</script>\n";
} return $rv;
return $rv; }
return "";
} }
=head2 ui_textbox(name, value, size, [disabled?], [maxlength], [tags], [class]) =head2 ui_textbox(name, value, size, [disabled?], [maxlength], [tags], [class])

View File

@@ -3179,7 +3179,11 @@ if ($user) {
push(@headers, [ "Authorization", "Basic $auth" ]); push(@headers, [ "Authorization", "Basic $auth" ]);
} }
foreach my $hname (keys %$headers) { foreach my $hname (keys %$headers) {
push(@headers, [ $hname, $headers->{$hname} ]); my $hv = $headers->{$hname};
$hv = [ $hv ] if (!ref($hv));
foreach my $v (@$hv) {
push(@headers, [ $hname, $v ]);
}
} }
# Actually download it # Actually download it
@@ -3393,7 +3397,11 @@ if ($user) {
} }
@headers = grep { !$headers->{$_->[0]} } @headers; @headers = grep { !$headers->{$_->[0]} } @headers;
foreach my $hname (keys %$headers) { foreach my $hname (keys %$headers) {
push(@headers, [ $hname, $headers->{$hname} ]); my $hv = $headers->{$hname};
$hv = [ $hv ] if (!ref($hv));
foreach my $v (@$hv) {
push(@headers, [ $hname, $v ]);
}
} }
# Actually download it # Actually download it