Compare commits

..

1 Commits

Author SHA1 Message Date
iliajie
fd3e985cf8 Fix to work-around the bug with time offsets #552 2023-04-25 23:04:58 +03:00
633 changed files with 696 additions and 9237 deletions

File diff suppressed because one or more lines are too long

View File

@@ -207,7 +207,7 @@ if ($access{'lang'}) {
if ($access{'locale'}) {
# Current locale
eval "use DateTime; use DateTime::Locale; use DateTime::TimeZone;";
if (!$@ && $] > 5.011) {
if (!$@) {
my $locales = &list_locales();
my %localesrev = reverse %{$locales};
my $locale_auto = &parse_accepted_language();

View File

@@ -38,9 +38,7 @@ if ($module_name ne 'htaccess') {
# Need to build list of supported modules
local ($ver, $mods, $fullver) = &httpd_info($httpd);
if ($ver) {
my @allmods = &available_modules();
local @mods = map { "$_/$ver" }
&configurable_modules(\@allmods);
local @mods = map { "$_/$ver" } &configurable_modules();
foreach my $m (@mods) {
if ($m =~ /(\S+)\/(\S+)/) {
$httpd_modules{$1} = $2;
@@ -49,14 +47,10 @@ if ($module_name ne 'htaccess') {
# Call again now that known modules have been set, as
# sometimes there are dependencies due to LoadModule
# statements in an IfModule block
undef(@get_config_cache);
@allmods = &available_modules();
@mods = map { "$_/$ver" }
&configurable_modules(\@allmods);
@mods = map { "$_/$ver" } &configurable_modules();
local %site = ( 'size' => $st[7],
'path' => $httpd,
'modules' => join(' ', @mods),
'allmodules' => join(' ', @allmods),
'version' => $ver,
'fullversion' => $fullver,
'webmin' => &get_webmin_version() );
@@ -78,9 +72,6 @@ if (&read_file($site_file, \%site)) {
$httpd_modules{$1} = $2;
}
}
foreach $m (split(/\s+/, $site{'allmodules'})) {
$all_httpd_modules{$m} = $site{'version'};
}
foreach $m (keys %httpd_modules) {
if (!-r "$module_root_directory/$m.pl") {
delete($httpd_modules{$m});
@@ -1834,46 +1825,46 @@ for(my $i=0; $i<$secs; $i++) {
return 0;
}
# configurable_modules([&all-mods])
# configurable_modules()
# Returns a list of Apaches that are compiled in or dynamically loaded, and
# supported by Webmin.
sub configurable_modules
{
my ($allmods) = @_;
$allmods ||= [ &available_modules() ];
return grep { -r "$module_root_directory/$_.pl" } @$allmods;
}
# available_modules()
# Returns a list of Apaches that are compiled in or dynamically loaded
sub available_modules
{
my ($ver, $mods) = &httpd_info(&find_httpd());
my @rv;
local ($ver, $mods) = &httpd_info(&find_httpd());
local @rv;
local $m;
# Add compiled-in modules
push(@rv, @$mods);
foreach $m (@$mods) {
if (-r "$module_root_directory/$m.pl") {
push(@rv, $m);
}
}
# Add dynamically loaded modules
my $conf = &get_config();
foreach my $l (&find_directive_struct("LoadModule", $conf)) {
if ($l->{'words'}->[1] =~ /(mod_\S+)\.(so|dll)/) {
local $conf = &get_config();
foreach $l (&find_directive_struct("LoadModule", $conf)) {
if ($l->{'words'}->[1] =~ /(mod_\S+)\.(so|dll)/ &&
-r "$module_root_directory/$1.pl") {
push(@rv, $1);
}
elsif ($l->{'words'}->[1] =~ /libssl\.so/) {
elsif ($l->{'words'}->[1] =~ /libssl\.so/ &&
-r "$module_root_directory/mod_apachessl.pl") {
push(@rv, "mod_apachessl");
}
elsif ($l->{'words'}->[1] =~ /lib([^\/\s]+)\.(so|dll)/) {
elsif ($l->{'words'}->[1] =~ /lib([^\/\s]+)\.(so|dll)/ &&
-r "$module_root_directory/mod_$1.pl") {
push(@rv, "mod_$1");
}
}
undef(@get_config_cache); # Cache is no longer valid
# Add dynamically loaded modules
if ($config{'apachectl_path'}) {
&open_execute_command(APACHE,
"$config{'apachectl_path'} -M 2>/dev/null", 1);
while(<APACHE>) {
if (/(\S+)_module/) {
if (/(\S+)_module/ && -r "$module_root_directory/mod_${1}.pl") {
push(@rv, "mod_${1}");
}
}

View File

@@ -1,19 +0,0 @@
show_list=0
httpd_dir=/usr/local
httpd_path=/usr/local/sbin/httpd
apachectl_path=/usr/local/sbin/apachectl
httpd_conf=/usr/local/etc/apache24/httpd.conf
mime_types=/usr/local/etc/apache24/mime.types
srm_conf=/usr/local/etc/apache24/srm.conf
access_conf=/usr/local/etc/apache24/access.conf
show_order=0
max_servers=100
test_config=1
test_manual=0
test_always=0
test_apachectl=1
auto_mods=1
pid_file=/var/run/httpd.pid
show_names=0
allow_virtualmin=0
format_config=1

View File

@@ -1,11 +1,11 @@
show_list=0
httpd_dir=/usr/apache2/2.4
httpd_conf=/etc/apache2/2.4/httpd.conf
httpd_path=/usr/apache2/2.4/bin/httpd
apachectl_path=/usr/apache2/2.4/bin/apachectl
pid_file=/var/run/apache2/2.4/httpd.pid
start_cmd=svcadm enable svc:/network/http:apache24
stop_cmd=svcadm disable svc:/network/http:apache24
httpd_dir=/usr/apache2/2.2
httpd_conf=/etc/apache2/2.2/httpd.conf
httpd_path=/usr/apache2/2.2/bin/httpd
apachectl_path=/usr/apache2/2.2/bin/apachectl
pid_file=/var/run/apache2/2.2/httpd.pid
start_cmd=svcadm enable svc:/network/http:apache22
stop_cmd=svcadm disable svc:/network/http:apache22
mime_types=
srm_conf=
access_conf=

View File

@@ -1041,7 +1041,7 @@ sub edit_LimitRequestBody
{
return (1, $text{'core_maxbody'},
&opt_input($_[0]->{'value'}, "LimitRequestBody", $text{'core_default'}, 8)
.&ui_space(2).$text{'bytes'});
.$text{'bytes'});
}
sub save_LimitRequestBody
{
@@ -1052,7 +1052,7 @@ sub edit_LimitXMLRequestBody
{
return (1, $text{'core_maxxml'},
&opt_input($_[0]->{'value'}, "LimitXMLRequestBody",
$text{'core_default'}, 8).&ui_space(2).$text{'bytes'});
$text{'core_default'}, 8).$text{'bytes'});
}
sub save_LimitXMLRequestBody
{

View File

@@ -637,7 +637,6 @@ mod_proxy_preserve=Preserve original Host: header
mod_proxy_timeout=Proxy request timeout in seconds
mod_proxy_etimeout=Proxy request timeout must be a number of seconds
mod_proxy_via=Set Via: headers
mod_proxy_preserve=Preserve original HTTP host
mod_proxy_not=None
mod_log_agent_default=Default

View File

@@ -25,7 +25,6 @@ $rv = [ [ 'ProxyRequests', 0, 13, 'virtual', undef, 11 ],
[ 'ProxyMaxForwards', 0, 13, 'virtual', 2.0 ],
[ 'ProxyPreserveHost', 0, 13, 'virtual', 2.031 ],
[ 'ProxyTimeout', 0, 13, 'virtual', 2.031 ],
[ 'ProxyPreserveHost', 0, 13, 'virtual', 2.3 ],
[ 'ProxyVia', 0, 13, 'virtual', 2.0 ] ];
return &make_directives($rv, $_[0], "mod_proxy");
}
@@ -292,16 +291,7 @@ sub save_ProxyVia
return &parse_choice("ProxyVia", "");
}
sub edit_ProxyPreserveHost
{
return (1, $text{'mod_proxy_preserve'},
&choice_input($_[0]->{'value'}, "ProxyPreserveHost", "",
"$text{'yes'},on", "$text{'no'},off", "$text{'default'},"));
}
sub save_ProxyPreserveHost
{
return &parse_choice("ProxyPreserveHost", "");
}
1;

View File

@@ -13,7 +13,6 @@ sub edit_SuexecUserGroup
local $rv;
$rv .= sprintf "<input type=radio name=SuexecUserGroup_def value=1 %s> %s\n",
$_[0] ? "" : "checked", $text{'suexec_none'};
$rv .= &ui_newline();
$rv .= sprintf "<input type=radio name=SuexecUserGroup_def value=0 %s>\n",
$_[0] ? "checked" : "";
$rv .= sprintf "%s <input name=SuexecUserGroup_u size=8 value='%s'> %s\n",

View File

@@ -11,7 +11,7 @@ use File::Basename;
use File::Find;
use JSON::PP;
use HTTP::Tiny;
eval "use HTML::Entities";
use HTML::Entities;
use List::MoreUtils qw(any uniq);
use Cwd qw(cwd);
use Encode qw/encode decode/;
@@ -245,16 +245,7 @@ sub main
talk('affected', \%opt, \%data);
# Run in overwrite mode
if ($opt{'mode'} eq 'clean') {
# # Execute clean
talk('clean-pre', \%opt, \%data);
if (prompt('next')) {
go(\%opt, \%data);
}
}
# Run in overwrite mode
elsif ($opt{'mode'} eq 'full') {
if ($opt{'mode'} eq 'full') {
# Execute force transcode/translate
talk('overwrite-pre', \%opt, \%data);
@@ -958,7 +949,6 @@ sub go
my $verbose = $opt->{'verbose'} || @{$keys_test};
my $mode_sync = $opt->{'mode'} ne 'full';
my $mode_transcode = $opt->{'mode'} eq 'transcode';
my $mode_clean = $opt->{'mode'} eq 'clean';
my $allow_symlinks = $opt->{'allow-symlinks'};
my $verbose_silent_mode = $mode_sync && $verbose != 2;
@@ -975,12 +965,6 @@ sub go
# Check if there has been something to process, if not print a message
my $output;
# If cleaning called in this mode, throw an error
if ($mode_clean) {
say RED, "Error: Cleaning can only be performed when the target type is unset!", RESET;
exit;
}
# Build targets first
talk_log(("Transcoding/translating " . CYAN BOLD, $module, RESET . " module's help .."), $data, 1);
@@ -1216,7 +1200,6 @@ sub go
# Set message type
my $message_type_s1 = 'Transcoding/translating';
$message_type_s1 = 'Searching/replacing in' if (@{$values_fix});
$message_type_s1 = 'Cleaning in' if ($mode_clean);
talk_log(("$message_type_s1 " . BLUE BOLD, $module, RESET . " module .."), $data, 1);
foreach $language (@{ $data->{'languages_source_list'} }) {
@@ -1240,51 +1223,6 @@ sub go
my %language;
my %language_auto;
# If in clean mode delete the file and go next
if ($mode_clean) {
# Language files
my $cfile = "$mpath/$code";
my $cfileauto = "$cfile.auto";
unlink($cfile);
unlink($cfileauto);
# Module files
foreach ('module', 'config', 'uconfig') {
my %mdata = %{$data};
$mdata{'type'} = $_;
my (undef, undef, $ffile) = source_data($module, \%mdata, $opt);
$ffile =~ s/\/$_\//\//;
my $cxfile = "$ffile.$code";
my $cxfileauto = "$cxfile.auto";
unlink($cxfile);
unlink($cxfileauto);
}
# Help files
my %hdata = %{$data};
$hdata{'type'} = 'help';
my (undef, $hpath) = source_data($module, \%hdata, $opt);
my @hdelete_targets;
if (-d $hpath) {
find(
{
wanted => sub {
my $found = $File::Find::name;
if ($found =~ /\.$code\./) {
push(@hdelete_targets, $found);
}
},
},
$hpath);
unlink(@hdelete_targets);
}
# Go next, don't translate
$output++;
next;
}
my $message_type_s2 = "Processing";
$message_type_s2 = "Testing translations for selected keys with" if (@{$keys_test});
@@ -1794,10 +1732,6 @@ sub talk
say GREEN, "Affected languages" . RESET, DARK . " [$languages_count]" . RESET . ": ", YELLOW BOLD,
"" . $languages . "", RESET;
}
if ($what eq 'clean-pre') {
say RED, "Danger! ", RESET, WHITE,
"The following operation will delete all files related to the affected lang-\nuage, including machine-translated files in all the mentioned modules listed above.",
}
if ($what eq 'overwrite-pre') {
say RED, "Warning! ", RESET, WHITE,
"The following operation will force-translate and overwrite mentioned\nlanguages in all mentioned modules listed above, using ",
@@ -1895,13 +1829,9 @@ Test translations for "index_stopmsg,trusted_warning" keys, in Russian and Germa
- webmin language-manager -m=bind8 -t=ru,de -kt=index_stopmsg,trusted_warning
Clean build directory by removing all kind of language files except English.
- webmin language-manager --mode=clean
=item --mode, -x <sync|full|transcode>
Mode can be either <sync> or <full> or <transcode> or <clean>. Default is set to "sync" and will only keep the keys found on template language file, while missing keys in target languages (translations), will be deleted, and newly added keys to template language file, will be translated. Mode "full" is meant to perform full translation, keeping human translated strings and overwriting all machine translations done in the past (not recommended to run). Mode "transcode" is useful to fix human translated language files, which stored in "utf-8" encoding already, while still having "&#195;&#173;" or "&#195;&#169;" HTML entities. Mode "clean" is useful to clean build package by removing all kind of language files except source language.
Mode can be either <sync> or <full> or <transcode>. Default is set to "sync" and will only keep the keys found on template language file, while missing keys in target languages (translations), will be deleted, and newly added keys to template language file, will be translated. Mode "full" is meant to perform full translation, keeping human translated strings and overwriting all machine translations done in the past (not recommended to run). Mode "transcode" is useful to fix human translated language files, which stored in "utf-8" encoding already, while still having "&#195;&#173;" or "&#195;&#169;" HTML entities.
=item --type, -w <lang|ulang|help|config|uconfig|module>
@@ -1987,4 +1917,4 @@ Verbosely print processed files and provide detailed output. By detault, verbose
=head1 LICENSE AND COPYRIGHT
Copyright 2020 Ilia Rostovtsev <ilia@virtualmin.com>
Copyright 2022 Ilia Rostovtsev <ilia@virtualmin.com>

View File

@@ -65,10 +65,10 @@ our @dnssec_dlv_key = ( 257, 3, 5, '"BEAAAAPHMu/5onzrEE7z1egmhg/WPO0+juoZrW3euWE
my $rand_flag;
if ($gconfig{'os_type'} =~ /-linux$/ &&
$config{'force_random'} eq '0' &&
-r "/dev/urandom" &&
$bind_version =~ /^9\./ &&
&compare_version_numbers($bind_version, '<', '9.14.2')) {
!$config{'force_random'} &&
$bind_version &&
&compare_version_numbers($bind_version, '9.14') < 0) {
# Version: 9.14.2 deprecated the use of -r option
# in favor of using /dev/random [bugs:#5370]
$rand_flag = "-r /dev/urandom";
@@ -376,22 +376,9 @@ return @rv ? wantarray ? @rv : $rv[0]
sub find_value
{
my @v = &find($_[0], $_[1]);
if (!@v) {
return undef;
}
elsif (wantarray) {
return map { &extract_value($_) } @v;
}
else {
return &extract_value($v[0]);
}
}
sub extract_value
{
my ($dir) = @_;
return defined($dir->{'value'}) ? $dir->{'value'} :
defined($dir->{'values'}) && @{$dir->{'values'}} ? $dir->{'values'}->[0] : undef;
if (!@v) { return undef; }
elsif (wantarray) { return map { $_->{'value'} } @v; }
else { return $v[0]->{'value'}; }
}
# base_directory([&config], [no-cache])
@@ -513,8 +500,9 @@ for(my $i=0; $i<@oldv || $i<@newv; $i++) {
sub recursive_set_value
{
my ($dir) = @_;
if (!defined($dir->{'value'})) {
$dir->{'value'} = &extract_value($dir);
if ($dir->{'values'}) {
my @v = @{$dir->{'values'}};
$dir->{'value'} = @v ? $v[0] : undef;
}
if ($dir->{'type'} && $dir->{'type'} == 1 && $dir->{'members'}) {
foreach my $m (@{$dir->{'members'}}) {
@@ -3022,7 +3010,7 @@ my %on = map { $_, 1 } @{$_[0]};
&remote_error_setup(\&slave_error_handler);
my @slaveerrs;
foreach my $slave (&list_slave_servers()) {
next if (%on && !$on{$slave->{'nsname'}} && !$on{$slave->{'host'}});
next if (%on && !$on{$slave->{'host'}});
# Find the PID file
$slave_error = undef;

View File

@@ -17,14 +17,6 @@ my $dom = $zone->{'name'};
&ui_print_header(&zone_subhead($zone), $text{'master_title'}, "",
undef, undef, undef, undef, &restart_links($zone));
my $d = &get_virtualmin_domains($dom);
if ($d && $d->{'alias'}) {
print &ui_alert_box($text{'master_vminalias'}, 'danger');
}
elsif ($d) {
print &ui_alert_box($text{'master_vmin'}, 'warn');
}
# Find the record types
my (@rcodes, @recs);
if (!$config{'largezones'}) {

View File

@@ -147,8 +147,6 @@ master_defttl=Default time-to-live for records
master_edefttl='$1' is not a valid default time-to-live for records
master_esoagone=No SOA record found!
master_einclude=Additional template file does not exist
master_vmin=This zone is managed by Virtualmin. Records should be edited using the Virtualmin UI, to ensure they are consistent with other virtual server settings.
master_vminalias=This zone is an alias of a Virtualmin domain, which is kept in sync with it's target. Records should never be edited here, as any changes will be overwritten!
delete_title=Delete Zone
delete_mesg=Are you sure you want to delete the zone $1 ? All records and the zone file will be deleted.

View File

@@ -59,9 +59,9 @@ if ($access{'lang'}) {
# Old datetime format or a new locale
if ($access{'locale'}) {
&foreign_require('webmin');
eval "use DateTime; use DateTime::Locale; use DateTime::TimeZone;";
if (!$@ && $] > 5.011) {
&foreign_require('webmin');
if (!$@) {
my $locales = &list_locales();
my %localesrev = reverse %{$locales};
my $locale = $locale_auto || $gconfig{'locale'} || &get_default_system_locale();

View File

@@ -925,7 +925,7 @@ $table .= &ui_columns_row(\@cols, [ "valign=top", "valign=top", "valign=top",
"valign=top", "valign=top" ]);
$table .= &ui_columns_end();
$table .= $text{'edit_ctrl'};
$rv .= &ui_table_row(undef, $table, $width, undef, ['data-schedule-tr']);
$rv .= &ui_table_row(undef, $table, $width);
return $rv;
}

View File

@@ -74,12 +74,12 @@ open(FILE, "<".$_[0]);
while($line = <FILE>) {
# strip comments
$line =~ s/\r|\n//g;
$line =~ s/([^\\])\\"/$1\\042/g; # convert escaped quotes to \042
$line =~ s/^([^"#]*)#.*$/$1/g;
$line =~ s/^([^"]*)\/\/.*$/$1/g;
$line =~ s/^([^"]*)\s+#.*$/$1/g; # remove stuff after #, unless
$line =~ s/^(.*".*".*)\s+#.*$/$1/g; # it is inside quotes
$line =~ s/\\\\/\\134/g; # convert \\ into \134
$line =~ s/([^\\])\\"/$1\\042/g; # convert escaped quotes to \042
while(1) {
if (!$cmode && $line =~ /\/\*/ && $line !~ /\".*\/\*.*\"/) {
# start of a C-style comment

View File

@@ -566,15 +566,4 @@ if ($?) {
}
}
# Unblock all IPs in given jail
sub unblock_jail
{
my ($jail) = @_;
my $cmd = "$config{'client_cmd'} reload --unban ".quotemeta($jail)." 2>&1 </dev/null";
my $out = &backquote_logged($cmd);
if ($?) {
&error(&text('status_err_unbanjail', &html_escape($jail)) . " : $out");
}
}
1;

View File

@@ -1,72 +0,0 @@
#!/usr/local/bin/perl
# Show a status of all active jails
use strict;
use warnings;
no warnings 'redefine';
no warnings 'uninitialized';
require './fail2ban-lib.pl';
our (%in, %text, %config);
&ReadParse();
my $jail = $in{'jail'};
my $out = &backquote_logged("$config{'client_cmd'} status 2>&1 </dev/null");
my ($jail_list) = $out =~ /jail\s+list:\s*(.*)/im;
my @jails = split(/,\s*/, $jail_list);
&indexof($jail, @jails) > -1 || error($text{'status_err_unknownjail'});
&ui_print_header("$jail", $text{'status_title3'}, "");
my $fh = 'jailinfo';
my @jail_blocks;
&open_execute_command($fh, "$config{'client_cmd'} get @{[quotemeta($jail)]} banip --with-time 2>&1 </dev/null", 1);
while(<$fh>) {
if (/^(?<ip>.*?)\s+(?<start>.*?\s+.*?)\s+.*?\s+.*?\s+=\s+(?<end>.*)$/) {
my $ip = $+{ip};
my $start = $+{start};
my $end = $+{end};
if ($ip && $start && $end) {
push(@jail_blocks, [$ip, $start, $end]);
}
}
}
close($fh);
if (@jail_blocks) {
my $popts = \%in;
$popts->{'paginations'}->{'form'} = { 'jail' => $jail };
my $pagination = &ui_paginations(\@jail_blocks, $popts);
my @links = ( &select_all_link("ip"),
&select_invert_link("ip"));
print $pagination->{'search'}->{'form-data'};
print &ui_form_start("unblock_jailed_ip.cgi", "post");
print &ui_links_row(\@links);
print &ui_columns_start([ "",
$text{'status_head_blocks_ip'},
$text{'status_head_blocks_stime'},
$text{'status_head_blocks_etime'} ]);
if (@jail_blocks) {
foreach my $r (@jail_blocks) {
print &ui_checked_columns_row($r, [ 'width=5' ], "ip", $r->[0]);
}
}
else {
print $pagination->{'search'}->{'no-results'};
}
print &ui_columns_end();
print $pagination->{'paginator'}->{'form-data'};
print $pagination->{'paginator'}->{'form-scripts'};
print &ui_hidden("jail", $jail);
print &ui_hidden("return", 1);
print $pagination->{'form'};
print &ui_links_row(\@links);
print &ui_form_end([ [ undef, $text{'status_jail_unblock_ips'} ] ]);
print $pagination->{'search'}->{'form'};
print $pagination->{'paginator'}->{'form'};
}
else {
print &text('status_jail_noactiveips', $jail);
}
&ui_print_footer("list_status.cgi", $text{'status_return'},
"", $text{'index_return'});

View File

@@ -170,32 +170,23 @@ manual_efile=Selected file is not part of the Fail2Ban configuration!
manual_err=Failed to edit config file
manual_edata=No config file contents entered
status_title=Jails Status
status_title3=Jail Blocks
status_return=jails status
status_head_jail_blocks=Jail blocks
status_title=Jails Status And Actions
status_title2=Jails Status
status_head_jail_name=Jail name
status_head_currently_failed=Currently failed
status_head_total_failed=Total failed
status_head_file_list=File list
status_head_currently_banned=Currently banned
status_head_total_banned=Total banned
status_head_banned_ip_list=Banned IP list
status_head_blocks_ip=IP
status_head_blocks_stime=Start time
status_head_blocks_etime=End time
status_rules_plus_more=+ $1 more
status_jail_unblock_ip=Remove $1 from banned list
status_jail_unblock=Unblock Selected Jails
status_jail_unblock_ips=Unblock Selected IP
status_jail_unblock=Unblock All IPs for Selected Jails
status_jail_noactive=There are no active jails enabled yet.
status_jail_noactiveips=There are no blocked entries in jail <tt>$1</tt> found.
status_err_set=Failed set action
status_err_unblock=Failed to unblock action
status_err_nojail=No jails have been selected
status_err_noips=No IP has been selected
status_err_unban=Cannot un-ban $1 IP address
status_err_unbanjail=Cannot un-ban $1 jail
status_err_unknownjail=Unknown jail
syslog_logtarget=Fail2Ban action log

View File

@@ -8,7 +8,7 @@ no warnings 'uninitialized';
require './fail2ban-lib.pl';
our (%in, %text, %config);
&ui_print_header(undef, $text{'status_title'}, "");
&ui_print_header(undef, $text{'status_title2'}, "");
my $out = &backquote_logged("$config{'client_cmd'} status 2>&1 </dev/null");
my ($jail_list) = $out =~ /jail\s+list:\s*(.*)/im;
@@ -25,13 +25,13 @@ if (@jails) {
my $fh = 'cmdjail';
my $cmd = "$config{'client_cmd'} status ".quotemeta($jail);
my $jcmd = "$cmd 2>&1 </dev/null";
my @head = (undef, $text{"status_head_jail_blocks"});
my @body = &ui_link("jail_blocks.cgi?jail=".urlize($jail), "&nbsp;".&html_escape($jail), undef);
my @head = (undef, $text{"status_head_jail_name"});
my @body = (&ui_link("edit_jail.cgi?name=".urlize($jail), "&nbsp;".&html_escape($jail)));
my $br = '<br>';
my $nbsp = '&nbsp;';
my $ipslimit = sub {
my ($ips, $limit) = @_;
$limit ||= 10;
$limit ||= 15;
# Limit sanity check
$limit = 1 if ($limit < 1);
my $ipscount = () = $ips =~ /$br/g;
@@ -39,9 +39,7 @@ if (@jails) {
my @ips = split($br, $ips);
@ips = @ips[0 .. $limit];
$ips = join($br, @ips);
$ips .= "<small style='cursor: default;'>$br".
(&ui_link("jail_blocks.cgi?jail=".urlize($jail),
"&nbsp;".&text('status_rules_plus_more', $ipscount-$limit), undef))."</small>";
$ips .= "<small style='cursor: default;'>$br".&text('status_rules_plus_more', $ipscount-$limit)."</small>";
}
return $ips;
};
@@ -59,7 +57,7 @@ if (@jails) {
if ($col =~ /banned_ip_list/) {
$jips = $val;
my @ips = split(/\s+/, $val);
@ips = map { "<small $tal><tt><label $lwf>" . &ui_link("unblock_jailed_ip.cgi?ip=@{[&urlize($_)]}&jail=@{[&urlize($jail)]}", $_, undef,
@ips = map { "<small $tal><tt><label $lwf>" . &ui_link("unblock_jail.cgi?unblock=1&jips-@{[&urlize($jail)]}=@{[&urlize($_)]}&jail=@{[&urlize($jail)]}", $_, undef,
"title=\"@{[&text('status_jail_unblock_ip', &quote_escape($_))]}\" onmouseover=\"this.style.textDecoration='line-through'\" onmouseout=\"this.style.textDecoration='none'\""
) . "</label></tt></small>" } @ips;
$val = "<br>" if ($val);
@@ -84,6 +82,9 @@ if (@jails) {
if ($head) {
print &ui_columns_end();
print &ui_links_row(\@links);
foreach my $j (@jipsall) {
print &ui_hidden("jips-$j->[0]", "$j->[1]");
}
print &ui_form_end([ [ 'unblock', $text{'status_jail_unblock'} ] ]);
}
}

View File

@@ -1,5 +1,5 @@
#!/usr/local/bin/perl
# Unblock specific jail
# Create, update or delete a action
use strict;
use warnings;
@@ -18,8 +18,13 @@ my @jails = split(/\0/, $in{'jail'});
# Processes jails actions
my @jailsmod;
foreach my $jail (@jails) {
&unblock_jail($jail);
push(@jailsmod, $jail);
my @jailips = split(/\s+/, $in{"jips-$jail"});
if (@jailips) {
foreach my $ip (@jailips) {
&unblock_jailed_ip($jail, $ip);
push(@jailsmod, $jail);
}
}
}
# Log and redirect

View File

@@ -1,29 +0,0 @@
#!/usr/local/bin/perl
# Unblock specific IP in jail
use strict;
use warnings;
no warnings 'redefine';
no warnings 'uninitialized';
require './fail2ban-lib.pl';
our (%in, %text, %config);
&ReadParse();
&error_setup($text{'status_err_set'});
my $jail = $in{'jail'};
my @ips = split(/\0/, $in{'ip'});
# Error checks
$jail || &error($text{'status_err_nojail'});
@ips || &error($text{'status_err_noips'});
# Processes jails actions
my @jailips;
foreach my $ip (@ips) {
&unblock_jailed_ip($jail, $ip);
push(@jailips, $ip);
}
# Log and redirect
&webmin_log('update', 'jail', $jail) if (@jailips);
&redirect($in{'return'} ? &get_referer_relative() : "list_status.cgi");

1
file/xinha Symbolic link
View File

@@ -0,0 +1 @@
../mailboxes/xinha

Binary file not shown.

Before

Width:  |  Height:  |  Size: 907 B

View File

@@ -261,8 +261,7 @@ else {
# Generate the header
local (@hcols, @tds);
push(@hcols, "", $text{'index_action'});
push(@tds, "width=5", "width=10% nowrap",
"width=70%", "nowrap", "nowrap");
push(@tds, "width=5", "width=30% nowrap");
if ($config{'view_condition'}) {
push(@hcols, $text{'index_desc'});
push(@tds, "nowrap");

View File

@@ -1,3 +1,2 @@
firewall_cmd=firewall-cmd
init_name=firewalld
config_dir=/etc/firewalld

View File

@@ -1,3 +1,2 @@
firewall_cmd=Full path to firewall-cmd program,0
init_name=FirewallD init script name,0
config_dir=FirewallD configuration directory,0

View File

@@ -1,28 +0,0 @@
#!/usr/local/bin/perl
# Show a page for manually editing FirewallD config files
require './firewalld-lib.pl';
&ui_print_header(undef, $text{'manual_title'}, "");
&ReadParse();
my @files = &unique(&get_config_files());
my $file = $in{'file'} || $files[0];
&indexof($file, @files) >= 0 || &error($text{'manual_efile'});
# Show the file selector
print &ui_form_start("edit_manual.cgi");
print "<b>$text{'manual_editsel'}</b>\n";
print &ui_select("file", $file, \@files),"\n";
print &ui_submit($text{'manual_ok'});
print &ui_form_end();
# Show the file contents
print &ui_form_start("save_manual.cgi", "form-data");
print &ui_hidden("file", $file);
print &ui_table_start(undef, undef, 2);
$data = &read_file_contents($file);
print &ui_table_row(undef, ui_textarea("data", $data, 20, 80), 2);
print &ui_table_end();
print &ui_form_end([ [ "save", $text{'save'} ] ]);
&ui_print_footer("", $text{'index_return'});

View File

@@ -89,21 +89,18 @@ $service =~ s/[^A-Za-z0-9\-]//g;
# my $out = &backquote_command("$config{'firewall_cmd'} --service=".quotemeta($service)." --get-ports --permanent </dev/null 2>&1");
# Check for file in directory containing all services as xml files
my $services_dir = "/usr/lib/firewalld/services/";
my $service_file = "$services_dir/$service.xml";
my @ports;
my @protos;
foreach my $services_dir ("/usr/lib/firewalld/services",
"/etc/firewalld/services") {
my $service_file = "$services_dir/$service.xml";
if (-r $service_file) {
my $lref = &read_file_lines($service_file, 1);
foreach my $l (@{$lref}) {
if ($l =~ /<port\s+protocol=["'](?<proto>\S+)["']\s+port=["'](?<port>[\d-]+)["']\/>/) {
my $port = "$+{port}";
my $proto = "$+{proto}";
push(@ports, $port) if ($port);
push(@protos, $proto) if ($port && $proto);
}
}
if (-r $service_file) {
my $lref = &read_file_lines($service_file, 1);
foreach my $l (@{$lref}) {
$l =~ /<port\s+protocol=["'](?<proto>\S+)["']\s+port=["'](?<port>[\d-]+)["']\/>/;
my $port = "$+{port}";
my $proto = "$+{proto}";
push(@ports, $port) if ($port);
push(@protos, $proto) if ($port && $proto);
}
}
@ports = &unique(@ports);
@@ -498,21 +495,4 @@ $out = &backquote_logged(&$get_cmd('permanent')." 2>&1 </dev/null");
return $? ? $out : undef;
}
sub get_config_files
{
my $conf_dir = $config{'config_dir'} || '/etc/firewalld';
my @conf_files;
my @dirpath = ($conf_dir);
eval "use File::Find;";
if (!$@) {
find(sub {
my $file = $File::Find::name;
push(@conf_files, $file)
if (-f $file && $file =~ /\.(conf|xml)$/);
}, @dirpath);
}
push(@conf_files, "$conf_dir/direct.xml");
return @conf_files;
}
1;

View File

@@ -76,7 +76,6 @@ if ($ok) {
$text{'index_sadd'}),
&ui_link("edit_forward.cgi?new=1&zone=".&urlize($zone->{'name'}),
$text{'index_fadd'}),
&ui_link("edit_manual.cgi", $text{'index_manual'}),
);
if (@{$zone->{'services'}} || @{$zone->{'ports'}}) {
my @tds = ( "width=5" );

View File

@@ -38,14 +38,6 @@ index_restart_firewalld=Reload FirewallD
index_restart_firewallddesc=Reload the FirewallD server and apply the rules that were permanently created.
index_listrules_restartdesc=List details about existing rich and direct FirewallD rules in $1 zone.
index_dependent=Failed to restart $1 dependent service
index_manual=Edit Config Files.
manual_title=Edit Config Files
manual_editsel=Edit FirewallD configuration file
manual_err=Failed to save config file
manual_efile=Selected configuration file is not valid
manual_ok=Edit
port_edit=Edit Port
port_create=Add Port

View File

@@ -1,19 +0,0 @@
#!/usr/local/bin/perl
# Update the manually edited FirewallD config file
require './firewalld-lib.pl';
&ReadParseMime();
&error_setup($text{'manual_err'});
my @files = &unique(&get_config_files());
my $file = $in{'file'};
&indexof($file, @files) >= 0 || &error($text{'manual_efile'});
$in{'data'} =~ s/\r//g;
&open_lock_tempfile(my $data, ">$file");
&print_tempfile($data, $in{'data'});
&close_tempfile($data);
&webmin_log("manual", undef, $file);
&redirect("");

View File

@@ -70,7 +70,7 @@ dump_before=Command to run before backup
dump_after=Command to run after backup
dump_fok=Halt if command fails
dump_fok2=Report failure if command fails
dump_aok=Skip command if backup fails
dump_aok=Skip command even if backup fails
dump_extra=Extra command-line parameters
dump_rsh=Remote backup command
dump_rsh0=Default (RSH)
@@ -95,7 +95,6 @@ dump_bcomp=Buffer compressed data into blocks?
dump_xdev=Limit backup to one filesystem?
dump_update2=Just add new files to archive?
dump_ignoreread=Ignore read errors on files?
dump_ignorechanged=Ignore errors if files change?
dump_notape=Prompt for new tape if needed?
dump_rmt=Path to <tt>rmt</tt> on remote system
dump_links=Follow symbolic links?
@@ -122,7 +121,7 @@ edit_header2=Backup schedule
edit_header3=Backup options
edit_enabled=Scheduled backup enabled?
edit_enabled_no=Disabled
edit_enabled_yes=Enabled
edit_enabled_yes=Enabled, at times chosen below..
edit_enabled_af=Enabled, after:
edit_savenow=Save and Backup Now
edit_createnow=Create and Backup Now

View File

@@ -107,11 +107,6 @@ if ($_[0]->{'fs'} eq 'tar') {
&ui_yesno_radio("ignoreread",
int($_[0]->{'ignoreread'})),
1, $tds);
print &ui_table_row(&hlink($text{'dump_ignorechanged'},"ignorechanged"),
&ui_yesno_radio("ignorechanged",
int($_[0]->{'ignorechanged'})),
1, $tds);
}
elsif ($_[0]->{'fs'} eq 'xfs') {
# Display xfs dump options
@@ -255,7 +250,6 @@ if ($_[0]->{'fs'} eq 'tar') {
}
$_[0]->{'update'} = $in{'update'};
$_[0]->{'ignoreread'} = $in{'ignoreread'};
$_[0]->{'ignorechanged'} = $in{'ignorechanged'};
if ($in{'gzip'} && $in{'update'}) {
&error($text{'dump_egzip3'});
}
@@ -375,7 +369,6 @@ if ($_[0]->{'fs'} eq 'tar') {
$cmd .= " --rmt-command=".quotemeta($_[0]->{'rmt'})
if ($_[0]->{'rmt'});
$cmd .= " --ignore-failed-read" if ($_[0]->{'ignoreread'});
$cmd .= " --warning=no-file-changed" if ($_[0]->{'ignorechanged'});
if ($_[0]->{'exclude'}) {
foreach my $e (&split_quoted_string($_[0]->{'exclude'})) {
$cmd .= " --exclude ".quotemeta($e);

File diff suppressed because one or more lines are too long

View File

@@ -274,6 +274,12 @@ print "<script>\n";
print "var rowsel = new Array();\n";
print "</script>\n";
print "<script type='text/javascript' src='@{[&get_webprefix()]}/unauthenticated/sorttable.js'></script>\n";
if ($ENV{'HTTP_USER_AGENT'} =~ /Chrome/) {
print "<style type=\"text/css\">\n";
print "textarea,pre { font-size:120%; }\n";
print "textarea { font-family:monospace; }\n";
print "</style>\n";
}
}
sub theme_popup_prehead
@@ -717,14 +723,15 @@ sub theme_ui_checked_columns_row
$theme_ui_columns_row_toggle = $theme_ui_columns_row_toggle ? '0' : '1';
local ($cols, $tdtags, $checkname, $checkvalue, $checked, $disabled, $tags) = @_;
my $rv;
my $cbid = &quote_escape("${checkname}_${checkvalue}");
my $rid = &quote_escape("row_${checkname}_${checkvalue}");
my $cbid = &quote_escape(quotemeta("${checkname}_${checkvalue}"));
my $rid = &quote_escape(quotemeta("row_${checkname}_${checkvalue}"));
my $ridtr = &quote_escape("row_${checkname}_${checkvalue}");
my $mycb = $cb;
if ($checked) {
$mycb =~ s/mainbody/mainsel/g;
}
$mycb =~ s/class='/class='row$theme_ui_columns_row_toggle ui_checked_columns /;
$rv .= "<tr id=\"$rid\" $mycb onMouseOver=\"this.className = document.getElementById('$cbid').checked ? 'mainhighsel' : 'mainhigh'\" onMouseOut=\"this.className = document.getElementById('$cbid').checked ? 'mainsel' : 'mainbody row$theme_ui_columns_row_toggle'\">\n";
$rv .= "<tr id=\"$ridtr\" $mycb onMouseOver=\"this.className = document.getElementById('$cbid').checked ? 'mainhighsel' : 'mainhigh'\" onMouseOut=\"this.className = document.getElementById('$cbid').checked ? 'mainsel' : 'mainbody row$theme_ui_columns_row_toggle'\">\n";
$rv .= "<td class='ui_checked_checkbox' ".$tdtags->[0].">".
&ui_checkbox($checkname, $checkvalue, undef, $checked, $tags." "."onClick=\"document.getElementById('$rid').className = this.checked ? 'mainhighsel' : 'mainhigh';\"", $disabled).
"</td>\n";
@@ -749,15 +756,16 @@ sub theme_ui_radio_columns_row
{
local ($cols, $tdtags, $checkname, $checkvalue, $checked) = @_;
my $rv;
my $cbid = &quote_escape("${checkname}_${checkvalue}");
my $rid = &quote_escape("row_${checkname}_${checkvalue}");
my $cbid = &quote_escape(quotemeta("${checkname}_${checkvalue}"));
my $rid = &quote_escape(quotemeta("row_${checkname}_${checkvalue}"));
my $ridtr = &quote_escape("row_${checkname}_${checkvalue}");
my $mycb = $cb;
if ($checked) {
$mycb =~ s/mainbody/mainsel/g;
}
$mycb =~ s/class='/class='ui_radio_columns /;
$rv .= "<tr $mycb id=\"$rid\" onMouseOver=\"this.className = document.getElementById('$cbid').checked ? 'mainhighsel' : 'mainhigh'\" onMouseOut=\"this.className = document.getElementById('$cbid').checked ? 'mainsel' : 'mainbody'\">\n";
$rv .= "<tr $mycb id=\"$ridtr\" onMouseOver=\"this.className = document.getElementById('$cbid').checked ? 'mainhighsel' : 'mainhigh'\" onMouseOut=\"this.className = document.getElementById('$cbid').checked ? 'mainsel' : 'mainbody'\">\n";
$rv .= "<td ".$tdtags->[0]." class='ui_radio_radio'>".
&ui_oneradio($checkname, $checkvalue, undef, $checked, "onClick=\"for(i=0; i<form.$checkname.length; i++) { ff = form.${checkname}[i]; r = document.getElementById('row_'+ff.id); if (r) { r.className = 'mainbody' } } document.getElementById('$rid').className = this.checked ? 'mainhighsel' : 'mainhigh';\"").
"</td>\n";

View File

@@ -1,7 +0,0 @@
body blockquote:not([style*="border-left"]) {
border-left: 1px solid #ccc;
margin-left: 6px;
margin-top: 0;
margin-bottom: 0;
padding-left: 12px;
}

File diff suppressed because one or more lines are too long

View File

@@ -6,4 +6,4 @@ version: 2.6.0
*/
h1{font-size:138.5%;}h2{font-size:123.1%;}h3{font-size:108%;}h1,h2,h3{margin:1em 0;}h1,h2,h3,h4,h5,h6,strong{font-weight:bold;}abbr,acronym{border-bottom:1px dotted #000;cursor:help;} em{font-style:italic;}blockquote,ul,ol,dl{margin:1em;}ol,ul,dl{margin-left:2em;}ol li{list-style:decimal outside;}ul li{list-style:disc outside;}dl dd{margin-left:1em;}th,td{border:1px solid #000;padding:.5em;}th{font-weight:bold;text-align:center;}caption{margin-bottom:.5em;text-align:center;}p,fieldset,table,pre{margin-bottom:1em;}
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}del,ins{text-decoration:none;}body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}del,ins{text-decoration:none;}body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}

File diff suppressed because one or more lines are too long

View File

@@ -80,8 +80,8 @@ if ($in{'multi'}) {
if ($in{'group'} eq $u->[0]) { print "<tr class='filter_match' $cb>\n"; }
else { print "<tr class='filter_match'>\n"; }
$u->[0] =~ s/\\/\\\\/g;
print "<td width=20%><a href=\"\" onClick='return addgroup(\"@{[&quote_escape($u->[0], \"'\")]}\", \"@{[&quote_escape($u->[3], \"'\")]}\")'>@{[&html_escape($u->[0])]}</a></td>\n";
print "<td>@{[&html_escape($u->[3])]}</td> </tr>\n";
print "<td width=20%><a href=\"\" onClick='return addgroup(\"$u->[0]\", \"$u->[3]\")'>$u->[0]</a></td>\n";
print "<td>$u->[3]</td> </tr>\n";
$cnt++;
}
print "</table>\n";
@@ -172,8 +172,8 @@ else {
foreach $u (&get_groups_list()) {
if ($in{'group'} eq $u->[0]) { print "<tr class='filter_match' $cb>\n"; }
else { print "<tr class='filter_match'>\n"; }
print "<td width=20%><a href=\"\" onClick='return select(\"@{[&quote_escape($u->[0], \"'\")]}\")'>@{[&html_escape($u->[0])]}</a></td>\n";
print "<td>@{[&html_escape($u->[3])]}</td> </tr>\n";
print "<td width=20%><a href=\"\" onClick='return select(\"$u->[0]\")'>$u->[0]</a></td>\n";
print "<td>$u->[3]</td> </tr>\n";
$cnt++;
}
print "</table>\n";

View File

@@ -59,6 +59,42 @@ $help =~ s/<if\s+([^>]*)>([\000-\177]*?)<\/if>/ifhelp($1, $2)/ige;
print $help;
&popup_footer();
# read_help_file(module, file)
# Reads the contents of a help file, either unpacked or from a ZIP
sub read_help_file
{
my ($module, $file) = @_;
my $path = &help_file($module, $file);
if (-r $path) {
return &read_file_contents($path);
}
my $gzpath = $path.".gz";
if (-r $gzpath) {
my $out = &backquote_command(
"gunzip -c ".quotemeta($gzpath)." 2>/dev/null");
return $? ? undef : $out;
}
my $zip = $path;
$zip =~ s/\/[^\/]+$/\/help.zip/;
if (-r $zip) {
my @files;
foreach my $o (@lang_order_list) {
next if ($o eq "en");
push(@files, $file.".".$o.".auto.html");
push(@files, $file.".".$o.".html");
}
push(@files, $file.".html");
foreach my $f (@files) {
my $out = &backquote_command(
"unzip -p ".quotemeta($zip)." ".
quotemeta($f)." 2>/dev/null");
return $out if ($out && !$?);
}
return undef;
}
return undef;
}
# inchelp(path)
sub inchelp
{

View File

@@ -1,484 +0,0 @@
# html-editor-lib.pl
# Quill HTML editor related subs
sub html_editor_load_bundle
{
my ($opts) = @_;
$opts ||= {};
my $html_editor_load_scripts;
# Load extra modules first
$html_editor_load_scripts .=
&html_editor_load_modules($opts);
# Load Quill HTML editor files
$html_editor_load_scripts .=
<<EOF;
<link href="$opts->{'_'}->{'web'}->{'prefix'}/unauthenticated/css/quill.min.css?$opts->{'_'}->{'web'}->{'timestamp'}" rel="stylesheet">
<script type="text/javascript" src="$opts->{'_'}->{'web'}->{'prefix'}/unauthenticated/js/quill.min.js?$opts->{'_'}->{'web'}->{'timestamp'}"></script>
EOF
return $html_editor_load_scripts;
}
sub html_editor_load_modules
{
my ($opts) = @_;
my $html_editor_load_modules;
my $load_css_modules = sub {
my ($css_modules) = @_;
foreach my $module (@{$css_modules}) {
$html_editor_load_modules .=
"<link href='$opts->{'_'}->{'web'}->{'prefix'}/unauthenticated/css/$module.min.css?$opts->{'_'}->{'web'}->{'timestamp'}' rel='stylesheet'>\n";
}
};
my $load_js_modules = sub {
my ($js_modules) = @_;
foreach my $module (@{$js_modules}) {
$html_editor_load_modules .=
"<script type='text/javascript' src='$opts->{'_'}->{'web'}->{'prefix'}/unauthenticated/js/$module.min.js?$opts->{'_'}->{'web'}->{'timestamp'}'></script>\n";
}
};
# Load extra CSS modules
if ($opts->{'extra'}->{'css'}) {
&$load_css_modules($opts->{'extra'}->{'css'})
}
# Load extra JS modules
if ($opts->{'extra'}->{'js'}) {
&$load_js_modules($opts->{'extra'}->{'js'})
}
# Automatically load dependencies
# based on editor mode
if ($opts->{'type'} eq "advanced") {
my $highlight_bundle = ['highlight/highlight'];
my @highlight_bundle = @{$highlight_bundle};
if ($opts->{'_'}->{'client'}->{'palette'} eq 'dark') {
foreach (@highlight_bundle) {
$_ .= "-dark"
if (-e "$root_directory/unauthenticated/css/$_-dark.min.css");
}
}
&$load_css_modules(\@highlight_bundle);
&$load_js_modules($highlight_bundle);
}
return $html_editor_load_modules;
}
sub html_editor_template
{
my ($opts) = @_;
$opts ||= {};
$html_editor_template =
<<EOF;
$opts->{'before'}->{'container'}
<div class="ql-compose-container $opts->{'class'}->{'container'}">
$opts->{'before'}->{'editor'}
<div data-composer="html" class="ql-compose ql-container $opts->{'class'}->{'editor'}"></div>
$opts->{'after'}->{'editor'}
</div>
$opts->{'after'}->{'container'}
EOF
return $html_editor_template;
}
sub html_editor_styles
{
my ($type) = @_;
# HTML editor toolbar styles
if ($type eq 'toolbar') {
return
<<EOF;
<style>
.ql-compose-container .ql-snow .ql-formats:empty {
display: none;
}
.ql-compose-container .ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-compose-container .ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: '$text{'editor_fontfamily_default'}';
}
.ql-compose-container .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="0.75em"]::before,
.ql-compose-container .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="0.75em"]::before {
content: '$text{'editor_font_small'}';
}
.ql-compose-container .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="0.75em"]::before {
font-size: 0.75em;
}
.ql-compose-container .ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-compose-container .ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: '$text{'editor_font_normal'}';
}
.ql-compose-container .ql-snow .ql-picker.ql-size .ql-picker-item::before {
font-size: 1em;
}
.ql-compose-container .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="1.15em"]::before,
.ql-compose-container .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="1.15em"]::before {
content: '$text{'editor_font_medium'}';
}
.ql-compose-container .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="1.15em"]::before {
font-size: 1.15em;
}
.ql-compose-container .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="1.3em"]::before,
.ql-compose-container .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="1.3em"]::before {
content: '$text{'editor_font_large'}';
}
.ql-compose-container .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="1.3em"]::before {
font-size: 1.3em;
}
.ql-compose-container .ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-compose-container .ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: '$text{'editor_paragraph'}';
}
.ql-compose-container .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-compose-container .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: '$text{'editor_heading'} 1'
}
.ql-compose-container .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-compose-container .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: '$text{'editor_heading'} 2'
}
.ql-compose-container .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-compose-container .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: '$text{'editor_heading'} 3'
}
.ql-compose-container .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-compose-container .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: '$text{'editor_heading'} 4'
}
.ql-compose-container .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-compose-container .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: '$text{'editor_heading'} 5'
}
.ql-compose-container .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-compose-container .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: '$text{'editor_heading'} 6'
}
</style>
EOF
}
}
sub html_editor_toolbar
{
my ($opts) = @_;
# Toolbar modes
if ($opts->{'type'} eq 'basic') {
return
<<EOF;
[
['bold', 'italic'],
[{'color': []}],
['blockquote']
]
EOF
}
if ($opts->{'type'} eq 'simple') {
return
<<EOF;
[
[{'font': [false, 'monospace']},
{'size': ['0.75em', false, "1.15em", '1.3em']}],
['bold', 'italic', 'underline'],
[{'color': []}, {'background': []}],
[{'align': []}],
['blockquote'],
['link'],
['image'],
['clean']
]
EOF
}
if ($opts->{'type'} eq 'advanced') {
return
<<EOF;
[
[{'font': [false, 'monospace']},
{'size': ['0.75em', false, "1.15em", '1.3em']},
{'header': [1, 2, 3, 4, 5, 6, false]}],
['bold', 'italic', 'underline', 'strike'],
[{'script': 'sub'}, {'script': 'super'}],
[{'color': []}, {'background': []}],
[{'align': []}],
[{'list': 'ordered'}, {'list': 'bullet'}],
[{'indent': '-1'}, {'indent': '+1'}],
['blockquote'],
(typeof hljs === 'object' ? ['code-block'] : []),
['link'],
['image'],
[{'direction': 'rtl'}],
['clean']
]
EOF
}
}
sub html_editor_init_script
{
my ($opts) = @_;
# Get target name and selector type
my $target_text = $opts->{'textarea'}->{'target'};
my $target_attr = $target_text->{'attr'} || 'name';
my $target_type = $target_text->{'type'} || '=';
my $target_name = $target_text->{'name'};
# HTML editor toolbar mode
my $iframe_styles_mode = $opts->{'type'};
my $iframe_styles =
&quote_escape(
&read_file_contents("$root_directory/unauthenticated/css/_iframe/$iframe_styles_mode.min.css"), '"');
$iframe_styles =~ s/\n/ /g;
my $navigation_type = $ENV{'HTTP_X_NAVIGATION_TYPE'};
$navigation_type ||= 'reload';
my $html_editor_init_script =
<<EOF;
<script type="text/javascript">
function fn_${module_name}_html_editor_init() {
const targ = document.querySelector('[$target_attr$target_type"$target_name"]'),
qs = Quill.import('attributors/style/size'),
qf = Quill.import('attributors/style/font'),
isMac = navigator.userAgent.toLowerCase().includes('mac'),
navigation_type = '$navigation_type',
iframe_styles = "$iframe_styles";
qs.whitelist = ["0.75em", "1.15em", "1.3em"];
Quill.register(qs, true);
qf.whitelist = ["monospace"],
Quill.register(qf, true);
const editor = new Quill('.ql-container', {
modules: {
syntax: typeof hljs === 'object',
imageDrop: true,
imageResize: {
modules: [
'DisplaySize',
'Resize',
],
},
clipboard: {
matchVisual: false
},
toolbar: @{[&html_editor_toolbar($opts)]},
},
bounds: '.ql-compose-container',
theme: 'snow'
});
// Google Mail editor like keybind for quoting
editor.keyboard.addBinding({
key: '9',
shiftKey: true,
ctrlKey: !isMac,
metaKey: isMac,
format: ['blockquote'],
}, function(range, context) {
this.quill.format('blockquote', false);
});
editor.keyboard.addBinding({
key: '9',
shiftKey: true,
ctrlKey: !isMac,
metaKey: isMac,
}, function(range, context) {
this.quill.format('blockquote', true);
});
editor.on('text-change', function() {
// This should most probably go to onSubmit event
targ.value = editor.root.innerHTML + "<br>";
sessionStorage.setItem('$module_name/quill=last-message', editor.root.innerHTML);
let extraValue = String(),
sync = JSON.parse('@{[&convert_to_json($opts->{'textarea'}->{'sync'}->{'data'})]}'),
position = '@{[$opts->{'textarea'}->{'sync'}->{'position'}]}',
err = false;
try {
// Gather data from additional elements if given
if (sync.constructor === Array) {
sync.forEach(function(_) {
let content_document = document;
if (_.iframe) {
content_document =
document.querySelector(_.iframe).contentWindow.document;
}
_.elements.forEach(function(element) {
const element_ = content_document.querySelector(element);
(element_ && (extraValue += element_.innerHTML));
})
});
}
} catch(e) {
err = true;
}
if (!err) {
if (position === 'before') {
targ.value = extraValue + targ.value;
} else {
targ.value = targ.value + extraValue;
}
}
// Inject our styles (unless already injected) to be sent alongside
// with the message. These styles later can be optionally turned in
// inline styling to satisfy GMail strict rules about HTML emails
if (!targ.value.match(/data-iframe-mode=(.*?)$iframe_styles_mode(.*?)/)) {
targ.value = targ.value +
'<style data-iframe-mode="$iframe_styles_mode">' + iframe_styles + '</style>';
}
});
// Prevent loosing focus for toolbar selects (color picker, font select and etc)
editor.getModule("toolbar").container.addEventListener("mousedown", (e) => {
e.preventDefault();
});
// Don't loose message content if the page
// is reloaded or history back is clicked
let restore_message = false;
try {
restore_message = window.performance.getEntriesByType("navigation")[0].type !== 'navigate' &&
navigation_type !== 'navigate'
} catch(e) {
restore_message = false;
}
if (restore_message) {
const quill_last_message = sessionStorage.getItem('$module_name/quill=last-message');
if (quill_last_message) {
editor.pasteHTML(quill_last_message);
return;
}
}
// Update editor on initial load
editor.pasteHTML(targ.value);
sessionStorage.setItem('$module_name/quill=last-message', editor.root.innerHTML);
}
@{[$opts->{'load'} ? "fn_${module_name}_html_editor_init()" : '']}
</script>
EOF
return $html_editor_init_script;
}
sub html_editor
{
my ($opts) = @_;
# Populate defaults
&html_editor_opts_populate_defaults($opts);
# Get template
my $html_editor_template =
&html_editor_template($opts);
# Get toolbar styling
my $html_editor_styles_toolbar =
&html_editor_styles('toolbar');
# Load bundles
my ($html_editor_load_scripts);
my %tinfo = &get_theme_info($current_theme);
if (!$tinfo{'spa'}) {
# Load HTML editor files and dependencies
$html_editor_load_scripts =
&html_editor_load_bundle($opts);
}
# HTML editor init
$opts->{'load'} = !$tinfo{'spa'};
my $html_editor_init_scripts =
&html_editor_init_script($opts);
# Return complete HTML editor
return $html_editor_template .
$html_editor_styles_toolbar .
$html_editor_load_scripts .
$html_editor_init_scripts;
}
sub html_editor_opts_populate_defaults
{
my ($opts) = @_;
# Miniserv webprefix
$opts->{'_'}->{'web'}->{'prefix'} = &get_webprefix();
# Webmin version to timestamp
my $webmin_version = &get_webmin_version();
$webmin_version =~ s/[.-]+//g;
$opts->{'_'}->{'web'}->{'timestamp'} = $webmin_version;
# Client color palette
$opts->{'_'}->{'client'}->{'palette'} = $ENV{'HTTP_X_COLOR_PALETTE'};
}
sub html_editor_substitute_classes_with_styles
{
my ($styled_html_email) = @_;
my ($document_styles_string) = $styled_html_email =~ /<style\s+data-iframe-mode.*?>(.*)<\/style>/;
if ($document_styles_string) {
my (%document_styles_class_names) =
$document_styles_string =~ /(\.[\w\-\_\d\,\.]+)\s*\{\s*([^}]*?)\s*\}/migx;
my $class_string = sub {
return "class=\"$_[0]\"";
};
my $style_string = sub {
return "style=\"$_[0]\"";
};
my $style_format = sub {
my ($stl) = @_;
# Format style nicely, as Google Mail insists
# on having these formatted neatly
$stl =~ s/(:|;)\s*/$1 /g;
$stl =~ s/(?<!;)$/;/g;
$stl =~ s/[;\s]+$/;/g;
$stl =~ s/(\S)(\!important)/$1 $2/g;
$stl =~ s/\s+$//;
return $stl;
};
# Replace tags classes with inline styles
foreach my $classes (reverse sort { length($a) <=> length($b) } keys %document_styles_class_names) {
my @classes = split(/\s*,\s*/, $classes);
foreach my $class (reverse sort { length($a) <=> length($b) } @classes) {
my (@class_parts) = $class =~ /\.([\S][^\.]+)/migx;
my (@style_exact_full) =
map { &$style_format($document_styles_class_names{$_}) }
grep { $_ =~ /(?<!\.)(\Q$class\E)(?!\.)(?!\-)(?!\_)/}
keys %document_styles_class_names;
# Class full
if (@style_exact_full) {
my $r = &$class_string("@class_parts");
my $s = &$style_string("@style_exact_full");
$styled_html_email =~ s/\Q$r\E/$s/migx;
}
# Class parts
$class =~ s/^\.//g;
if ("@class_parts" ne $class) {
foreach my $class_part (@class_parts) {
my $style_exact_part = $document_styles_class_names{".$class_part"};
if ($style_exact_part) {
$style_exact_part = &$style_format($style_exact_part);
my $r = &$class_string($class_part);
my $s = &$style_string($style_exact_part);
$styled_html_email =~ s/\Q$r\E/$s/migx;
}
}
}
}
}
# Fill tags with our inline styles
my (@document_styles_tag_names) = $styled_html_email =~ /<(?!style)(?!script)(?!s)(\w+)\s*.*?>/migx;
foreach my $tag_name (&unique(@document_styles_tag_names)) {
my (%document_styles_tag_names) = $document_styles_string =~ /(\Q$tag_name\E)\s*\{\s*([^}]*?)\s*\}/migx;
foreach my $tag (keys %document_styles_tag_names) {
my $tag_style = &$style_format($document_styles_tag_names{$tag});
$styled_html_email =~ s/(<$tag)(?![^>]+style).*?>/$1 style="$tag_style">/mig;
}
}
}
return $styled_html_email;
}
1;

View File

@@ -306,7 +306,6 @@ ui_etime=Invalid time
ui_paging=Showing rows $1 to $2 of $3
ui_rowlabel=$2 in row $1 :
ui_filterbox=Type to filter..
ui_of=of
header_statusmsg=$1 logged into $2 $3 on $4 ($5)
@@ -380,10 +379,6 @@ nice_size_kB=kB
nice_size_kiB=KiB
nice_size_b=bytes
paginator_showing_start=Showing $1 to $2 of $3 items on page
paginator_showing_end=of $1 pages
paginator_nosearchrs=There are no results matching <tt>$1</tt> query
langauto_include=Include machine translations
file_truncated_message=fetched $1 of data, truncated $2 out of $3

View File

@@ -1,3 +1,4 @@
line1=Configurable options,11
lines=Default number of lines to display,0,6
refresh=Seconds between log view refreshes,3,Never
others=Show logs from other modules?,1,1-Yes,0-No

View File

@@ -86,14 +86,12 @@ if ($config{'others'} && $access{'others'}) {
foreach $o (@others) {
local @cols;
if ($o->{'file'}) {
push(@cols, &text('index_file',
"<tt>".&html_escape($o->{'file'})."</tt>"));
push(@cols, &text('index_file',"<tt>$o->{'file'}</tt>"));
}
else {
push(@cols, &text('index_cmd',
"<tt>".&html_escape($o->{'cmd'})."</tt>"));
push(@cols, &text('index_cmd', "<tt>".$o->{'cmd'}."</tt>"));
}
push(@cols, &html_escape($o->{'desc'}));
push(@cols, $o->{'desc'});
push(@cols, &ui_link("view_log.cgi?oidx=$o->{'mindex'}".
"&omod=$o->{'mod'}&view=1", $text{'index_view'}) );
push(@col2, \@cols);
@@ -104,16 +102,9 @@ if ($config{'others'} && $access{'others'}) {
# Display extra log files
foreach $e (&extra_log_files()) {
local @cols;
if ($e->{'file'}) {
push(@cols, &text('index_file',
"<tt>".&html_escape($e->{'file'})."</tt>"));
}
else {
push(@cols, &text('index_cmd',
"<tt>".&html_escape($e->{'cmd'})."</tt>"));
}
push(@cols, &html_escape($e->{'desc'}));
push(@cols, &ui_link("view_log.cgi?extra=".&urlize($e->{'file'} || $e->{'cmd'})."&view=1", $text{'index_view'}) );
push(@cols, &text('index_file', $e->{'file'}));
push(@cols, $e->{'desc'});
push(@cols, &ui_link("view_log.cgi?extra=$e->{'file'}&view=1", $text{'index_view'}) );
push(@col3, \@cols);
}

View File

@@ -129,12 +129,6 @@ foreach my $fd (split(/\t+/, $config{'extras'}), split(/\t+/, $access{'extras'})
push(@rv, { 'file' => $fd });
}
}
foreach my $f (@rv) {
if ($f->{'file'} =~ /^(.*)\s*\|$/) {
delete($f->{'file'});
$f->{'cmd'} = $1;
}
}
return @rv;
}

View File

@@ -77,12 +77,10 @@ if ($in{'view'}) {
}
elsif ($in{'extra'}) {
# Extra log file
($extra) = grep { $_->{'file'} eq $in{'extra'} ||
$_->{'cmd'} eq $in{'extra'} } @extras;
($extra) = grep { $_->{'file'} eq $in{'extra'} } @extras;
$extra || &error($text{'save_ecannot7'});
&can_edit_log($extra) || &error($text{'save_ecannot2'});
$file = $extra->{'file'};
$cmd = $extra->{'cmd'};
}
elsif ($in{'file'}) {
# Explicitly named file

View File

@@ -43,9 +43,9 @@ if (!&can_resize_lv_stat(@stat)) {
else {
# Details for new LV
if ($stat[2]) {
print &ui_table_row($text{'lv_name'},
$lv->{'name'}.
&ui_hidden("name", $lv->{'name'}));
print &ui_table_row($text{'lv_name'}, $lv->{'name'},
undef, [ "", "valign=top" ]);
print &ui_hidden("name", $lv->{'name'});
}
else {
print &ui_table_row($text{'lv_name'},

View File

@@ -1480,7 +1480,7 @@ if ($u) {
my $locale;
if ($userconfig{'date_fmt'} eq 'auto' || $config{'date_fmt'} eq 'auto') {
eval "use DateTime; use DateTime::Locale; use DateTime::TimeZone;";
if (!$@ && $] > 5.011) {
if (!$@) {
$locale++;
return &make_date($u, undef, $fmt);
}

View File

@@ -15,8 +15,7 @@ sort_mode=1
fwd_mode=0
delete_warn=y
top_buttons=2
view_html=2
view_images=3
view_html=0
mail_usermin=mail
sync_create=0
sync_modify=1
@@ -25,8 +24,7 @@ size_mode=1
no_crlf=0
sync_perms=0700
show_mail=0
html_edit=2
html_edit_mode=simple
html_edit=0
check_mod=1
spam_buttons=mail
show_delall=0

View File

@@ -10,9 +10,7 @@ show_sent=Show number of messages in sent mail folder?,1,1-Yes,0-No
fwd_mode=Forward messages with quoting?,1,0-Yes,1-No
delete_warn=Ask for confirmation before deleting?,10,y-Yes,n-No,For mbox files larger than
view_html=Show message body as,4,0-Always plain text,1-Text if possible&#44; HTML otherwise,2-HTML if possible&#44; text otherwise,3-Convert HTML to plain text
view_images=Show inline images by default?,1,0-Yes&#44; client fetched,3-Yes&#44; server fetched,1-No external images,2-No
html_edit=Use HTML editor for composing?,4,2-Always,1-When replying to HTML email,0-Never
html_edit_mode=HTML editor toolbar mode?,4,basic-Basic,simple-Simple,advanced-Advanced
html_quote=HTML quoting mode,1,1-Message below &lt;hr&gt;,0-Message inside &lt;blockquote&gt;
log_read=Record the reading of mail in the Webmin Actions Log?,1,1-Yes,0-No
bcc_to=Bcc: sent messages to,0

View File

@@ -2414,6 +2414,18 @@ $bodystuff = &safe_html($bodystuff) if ($bodystuff);
return wantarray ? ($html, $bodystuff) : $html;
}
# head_html(html)
# Returns HTML in the <head> section of a document
sub head_html
{
local $html = $_[0];
return undef if ($html !~ /<HEAD[^>]*>/i || $html !~ /<\/HEAD[^>]*>/i);
$html =~ s/^[\000-\377]*<HEAD[^>]*>//gi || &error("Failed to filter <pre>".&html_escape($html)."</pre>");
$html =~ s/<\/HEAD[^>]*>[\000-\377]*//gi || &error("Failed to filter <pre>".&html_escape($html)."</pre>");
$html =~ s/<base[^>]*>//i;
return &filter_javascript($html);
}
# safe_urls(html)
# Replaces dangerous-looking URLs in HTML
sub safe_urls
@@ -2482,15 +2494,14 @@ return $rv;
# Attempts to convert some HTML to text form
sub html_to_text
{
my ($html) = @_;
my ($h2, $lynx);
local ($h2, $lynx);
if (($h2 = &has_command("html2text")) || ($lynx = &has_command("lynx"))) {
# Can use a commonly available external program
local $temp = &transname().".html";
open(TEMP, ">", $temp);
print TEMP $html;
print TEMP $_[0];
close(TEMP);
open(OUT, ($lynx ? "$lynx --display_charset=utf-8 -dump $temp" : "$h2 $temp")." 2>/dev/null |");
open(OUT, ($lynx ? "$lynx -dump $temp" : "$h2 $temp")." 2>/dev/null |");
while(<OUT>) {
if ($lynx && $_ =~ /^\s*References\s*$/) {
# Start of Lynx references output
@@ -2509,35 +2520,13 @@ if (($h2 = &has_command("html2text")) || ($lynx = &has_command("lynx"))) {
return $text;
}
else {
# Can we use Perl HTML formatter
# for the better conversion
eval "use HTML::TreeBuilder";
if (!$@) {
eval "use HTML::FormatText";
if (!$@) {
my $html_parser = HTML::TreeBuilder->new();
eval "use utf8";
utf8::decode($html)
if (!$@);
$html_parser->parse($html);
my $formatter = HTML::FormatText->new(leftmargin => 1, rightmargin => 79);
return $formatter->format($html_parser);
}
}
# Do conversion manually :(
$html =~ s/(<|&lt;)(style|script).*?(>|&gt;).*?(<|&lt;)\/(style|script)(>|&gt;)//gs;
local $html = $_[0];
$html =~ s/\s+/ /g;
$html =~ s/<p>/\n\n/gi;
$html =~ s/<br>/\n/gi;
$html =~ s/<[^>]+>//g;
my $useutf8 = 0;
eval "use utf8";
$useutf8 = 1 if (!$@);
utf8::decode($html)
if ($useutf8);
$html = &entities_to_ascii($html);
utf8::encode($html)
if ($useutf8);
return $html;
}
}
@@ -2779,38 +2768,20 @@ else {
# 2=All images. Returns the URL of images found in &urls
sub disable_html_images
{
my ($html, $dis, $urls) = @_;
my $newhtml;
my $masked_img;
while($html =~ /^([\000-\377]*?)(<\s*img[^>]*src=('[^']*'|"[^"]*"|\S+)[^>]*>)([\000-\377]*)/i &&
# Inline images must be safe to skip
$3 !~ /^['"]*data:.*?\/.*?base64,/) {
my ($before, $allimg, $img, $after) = ($1, $2, $3, $4);
local ($html, $dis, $urls) = @_;
local $newhtml;
while($html =~ /^([\000-\377]*?)(<\s*img[^>]*src=('[^']*'|"[^"]*"|\S+)[^>]*>)([\000-\377]*)/i) {
local ($before, $allimg, $img, $after) = ($1, $2, $3, $4);
$img =~ s/^'(.*)'$/$1/ || $img =~ s/^"(.*)"$/$1/;
push(@$urls, $img) if ($urls);
if ($dis == 3) {
# Let server load it in async mode
if ($img !~ /^cid:/) {
my $imgcont = $allimg;
$imgcont =~ s/src=/data-presrc=/g;
$newhtml .= $before.$imgcont;
$masked_img++;
}
else {
$newhtml .= $before.$allimg;
}
}
elsif ($dis == 0) {
if ($dis == 0) {
# Don't harm image
$newhtml .= $before.$allimg;
}
elsif ($dis == 1) {
# Don't touch unless offsite
if ($img =~ /^(http|https|ftp):/) {
my $imgcont = $allimg;
$imgcont =~ s/src=/data-nosrc=/g;
$newhtml .= $before.$imgcont;
$masked_img++;
$newhtml .= $before;
}
else {
$newhtml .= $before.$allimg;
@@ -2823,305 +2794,9 @@ while($html =~ /^([\000-\377]*?)(<\s*img[^>]*src=('[^']*'|"[^"]*"|\S+)[^>]*>)([\
$html = $after;
}
$newhtml .= $html;
if ($masked_img) {
my $masked_img_style =
"<style>
img[data-nosrc]
{
border-radius: 0 !important;
background: #e1567833 !important;
border-color: transparent !important;
min-width: 16px;
min-height: 16px;
}
</style>";
$masked_img_style =~ s/[\n\r\s]+/ /g;
$masked_img_style = &trim($masked_img_style);
if ($newhtml =~ /<\/body>/) {
$newhtml =~ s/<\/body>/$masked_img_style<\/body>/;
}
else {
$newhtml .= $masked_img_style;
}
}
return $newhtml;
}
# iframe_body(body)
# Returns email message in an iframe HTML element
sub iframe_body
{
my ($body) = @_;
# Do we have theme styles to embed when
# viewing an email? It can be useful for
# themes with dark palettes
my $iframe_theme_file = sub {
my $f =
"$root_directory/$current_theme/unauthenticated/css/_iframe/$_[0].min.css";
return -r $f ? &read_file_contents($f) : '';
};
my $iframe_styles_theme =
&$iframe_theme_file($ENV{'HTTP_X_COLOR_PALETTE_FILE'}) ||
&$iframe_theme_file('quote');
# Mail iframe inner styles
my $iframe_styles = <<EOF;
<style>
html, body { overflow-y: hidden; }
$iframe_styles_theme
</style>
EOF
# Add inner styles to the email body
if ($body =~ /<\/body>/) {
$body =~ s/<\/body>/$iframe_styles<\/body>/;
}
else {
$body .= $iframe_styles;
}
$body = &trim(&quote_escape($body, '"'));
# Email iframe stuff
my $webprefix = &get_webprefix();
my $image_mode = int(defined($in{'images'}) ? $in{'images'} : $userconfig{'view_images'});
my $iframe_body = <<EOF;
<div id="mail-iframe-spinner"></div>
<style>
#mail-iframe {
border:0;
width:100%;
}
\@keyframes mail-iframe-spinner {
to {
transform: rotate(360deg);
}
}
#mail-iframe-spinner:before {
animation: mail-iframe-spinner .4s linear infinite;
border-radius: 50%;
border: 2px solid #bbbbbb;
border-top-color: #000000;
box-sizing: border-box;
content: '';
height: 18px;
margin-top: 3px;
position: absolute;
right: 15px;
width: 18px;
}
</style>
<script>
function mail_iframe_onload(iframe) {
if (typeof theme_mail_iframe_onload === 'function') {
theme_mail_iframe_onload(iframe);
return;
}
const iframe_spinner = document.querySelector('#mail-iframe-spinner'),
iframe_resize = function() {
const iframeobj = document.querySelector('#mail-iframe'),
iframe_height_bound = iframeobj.contentWindow.document.body.getBoundingClientRect().bottom,
iframe_scroll_height = iframeobj.contentWindow.document.body.scrollHeight,
iframe_height =
iframe_height_bound > iframe_scroll_height ?
iframe_height_bound : iframe_scroll_height;
iframeobj.style.height = Math.ceil(iframe_height) + "px";
};
iframe_spinner && iframe_spinner.remove();
iframe.classList.add("loaded");
setTimeout(iframe_resize);
setTimeout(function() {
const imgPresrc = iframe.contentWindow.document.querySelectorAll('img[data-presrc]');
imgPresrc.forEach(function(img) {
(async function() {
try {
const response = await fetch("$webprefix/$module_name/xhr.cgi?action=fetch&type=download&subtype=blob&url=" + encodeURIComponent(img.dataset.presrc) + "");
response.blob().then(function(blob) {
try {
const urlBlob = URL.createObjectURL(blob);
img.removeAttribute('data-presrc');
img.src = urlBlob;
img.addEventListener('load', iframe_resize, { once: true });
} catch(error) {
console.warn(\`Cannot load image: \$\{error.message\}\`);
}
});
} catch (e) {}
})();
});
}, 99);
}
</script>
<iframe
id="mail-iframe"
class="mail-iframe mode-$image_mode"
onload="mail_iframe_onload(this)"
sandbox="allow-same-origin allow-popups allow-popups-to-escape-sandbox"
src="about:blank" srcdoc="$body">
</iframe>
EOF
return &trim($iframe_body);
}
# iframe_quote(quote)
# Returns quoted message in an iframe HTML element
sub iframe_quote
{
my ($quote) = @_;
return $quote if (!$quote);
# Do we have theme styles to embed
# for local display purposes only
my $iframe_theme_file = sub {
my $f =
"$root_directory/$current_theme/unauthenticated/css/_iframe/$_[0].min.css";
return -r $f ? &read_file_contents($f) : '';
};
my $iframe_styles_theme =
&$iframe_theme_file($ENV{'HTTP_X_COLOR_PALETTE_FILE'}) ||
&$iframe_theme_file('quote');
# Quote mail iframe inner styles
my $iframe_styles = <<EOF;
<style>
html, body { overflow-y: hidden; }
div[contenteditable] { outline: none; }
$iframe_styles_theme
</style>
EOF
# Add inner styles to the email body
if ($quote =~ /<\/body>/) {
$quote =~ s/<\/body>/$iframe_styles<\/body>/;
}
else {
$quote .= $iframe_styles;
}
$quote = &trim(&quote_escape($quote, '"'));
# Email iframe stuff
my $iframe_body = <<EOF;
<style>
#quote-mail-iframe {
border: none;
width: calc(100% - 12px);
}
details.iframe_quote_details summary::-webkit-details-marker {
display:none;
}
details.iframe_quote_details summary {
display: block;
width: fit-content;
outline: none;
margin-left: 6px;
margin-bottom: 6px;
cursor: pointer;
}
details.iframe_quote_details iframe {
padding-left: 6px;
padding-bottom: 6px;
}
details.iframe_quote_details summary::after {
background-color: #e4e4e4;
border: 1px solid #cfcfcf;
border-radius: 18px;
content: "";
display: inline-block;
line-height: 0;
padding: 0;
width: 25px;
height: 11px;
}
details.iframe_quote_details summary:hover::after {
background-color: #d4d4d4;
border: 1px solid #bfbfbf;
}
details.iframe_quote_details summary > ul {
display: inline-flex;
margin: 0;
padding: 0;
position: absolute;
margin-left: 7px;
margin-top: 5px;
pointer-events: none;
}
details.iframe_quote_details summary > ul > li {
background-color: #000;
height: 3px;
width: 3px;
line-height: 0;
list-style: none;
margin-right: 2px;
margin-top: 0;
border-radius: 50%;
pointer-events: none;
}
details.iframe_quote_details[open] summary::after {
background-color: #ccc;
border: 1px solid #aaa;
}
</style>
<script>
function quote_mail_iframe_onload(iframe) {
if (typeof theme_quote_mail_iframe_onload === 'function') {
theme_quote_mail_iframe_onload(iframe);
return;
}
const iframe_resize = function() {
const iframeobj = document.querySelector('#quote-mail-iframe'),
iframe_height_bound = iframeobj.contentWindow.document.body.getBoundingClientRect().bottom,
iframe_scroll_height = iframeobj.contentWindow.document.body.scrollHeight,
iframe_height =
iframe_height_bound > iframe_scroll_height ?
iframe_height_bound : iframe_scroll_height;
iframeobj.style.height = Math.ceil(iframe_height) + "px";
};
setTimeout(iframe_resize);
document.querySelector('.iframe_quote_details').addEventListener("click", function() {
quote_mail_iframe_onload(this.querySelector('iframe'));
}, { once: true });
if (!iframe.dataset.imagesLoaded) {
iframe.dataset.imagesLoaded = 1;
setTimeout(function() {
const imgPresrc = iframe.contentWindow.document.querySelectorAll('img[data-presrc]');
imgPresrc.forEach(function(img) {
(async function() {
try {
const response = await fetch("$webprefix/$module_name/xhr.cgi?action=fetch&type=download&subtype=blob&url=" + encodeURIComponent(img.dataset.presrc) + "");
response.blob().then(function(blob) {
try {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
img.removeAttribute('data-presrc');
img.src = reader.result;
img.addEventListener('load', iframe_resize, { once: true });
}
} catch(error) {
console.warn(\`Cannot load image: \$\{error.message\}\`);
}
});
} catch (e) {}
})();
});
}, 99);
}
}
</script>
<iframe
id="quote-mail-iframe"
class="quote-mail-iframe"
onload="quote_mail_iframe_onload(this)"
sandbox="allow-same-origin allow-popups allow-popups-to-escape-sandbox"
src="about:blank" srcdoc="<div contenteditable='true' id='webmin-iframe-quote' class='iframe_quote'>$quote</div>">
</iframe>
EOF
$iframe_body = &ui_details({
html => 1,
title => "<ul><li></li><li></li><li></li></ul>",
content => $iframe_body,
class => 'iframe_quote_details'
});
return &trim($iframe_body);
}
# remove_body_attachments(&mail, &attach)
# Returns attachments except for those that make up the message body, and those
# that have sub-attachments.
@@ -3183,8 +2858,9 @@ if ($writers[0]->[1]) {
else {
$writer = &decode_mimewords($writers[0]->[0])." wrote ..";
}
my $tm = &parse_mail_date($_[0]->{'header'}->{'date'});
if ($tm) {
local $tm;
if ($cfg->{'reply_date'} &&
($tm = &parse_mail_date($_[0]->{'header'}->{'date'}))) {
local $tmstr = &make_date($tm);
$writer = "On $tmstr $writer";
}

View File

@@ -450,9 +450,3 @@ left_autoreply=Outomatiese antwoord
left_filter=E-posfilters
left_pass=Verander wagwoord
left_sig=Wysig handtekening
editor_fontfamily_default=Verstek
editor_font_small=Klein
editor_font_normal=Normaal
editor_font_medium=Medium
editor_font_large=Groot

View File

@@ -450,9 +450,3 @@ left_autoreply=رد آلي
left_filter=مرشحات البريد الإلكتروني
left_pass=تغيير كلمة السر
left_sig=تعديل التوقيع
editor_fontfamily_default=تقصير
editor_font_small=صغير
editor_font_normal=طبيعي
editor_font_medium=واسطة
editor_font_large=كبير

View File

@@ -450,9 +450,3 @@ left_autoreply=Аўтаматычны адказ
left_filter=Фільтры электроннай пошты
left_pass=Змена пароля
left_sig=Рэдагаваць подпіс
editor_fontfamily_default=Па змаўчанні
editor_font_small=Маленькі
editor_font_normal=Нармальны
editor_font_medium=Сярэдні
editor_font_large=Вялікі

View File

@@ -450,9 +450,3 @@ left_autoreply=Автоматичен отговор
left_filter=Имейл филтри
left_pass=Промяна на паролата
left_sig=Редактиране на подписа
editor_fontfamily_default=По подразбиране
editor_font_small=малък
editor_font_normal=нормално
editor_font_medium=Среден
editor_font_large=Голям

View File

@@ -1,7 +1 @@
index_return=llista d'usuaris
editor_fontfamily_default=Per defecte
editor_font_small=Petit
editor_font_normal=Normal
editor_font_medium=Mitjana
editor_font_large=Gran

View File

@@ -39,9 +39,3 @@ left_autoreply=Automatická odpověď
left_filter=E-mailové filtry
left_pass=Změnit heslo
left_sig=Upravit podpis
editor_fontfamily_default=Výchozí
editor_font_small=Malý
editor_font_normal=Normální
editor_font_medium=Střední
editor_font_large=Velký

View File

@@ -450,9 +450,3 @@ left_autoreply=Automatisk svar
left_filter=E-mail-filtre
left_pass=Skift kodeord
left_sig=Rediger underskrift
editor_fontfamily_default=Standard
editor_font_small=Lille
editor_font_normal=Normal
editor_font_medium=Medium
editor_font_large=Stor

View File

@@ -1,7 +1 @@
index_return=Benutzerliste
editor_fontfamily_default=Standard
editor_font_small=Klein
editor_font_normal=Normal
editor_font_medium=Mittel
editor_font_large=Groß

View File

@@ -81,9 +81,3 @@ left_autoreply=Αυτόματη απάντηση
left_filter=Φίλτρα ηλεκτρονικού ταχυδρομείου
left_pass=Άλλαξε κωδικό
left_sig=Επεξεργασία υπογραφής
editor_fontfamily_default=Προκαθορισμένο
editor_font_small=Μικρό
editor_font_normal=Κανονικός
editor_font_medium=Μεσαίο
editor_font_large=Μεγάλο

View File

@@ -451,12 +451,4 @@ left_filter=Email Filters
left_pass=Change Password
left_sig=Edit Signature
editor_heading=Heading
editor_paragraph=Paragraph
editor_fontfamily_default=Default
editor_font_small=Small
editor_font_normal=Normal
editor_font_medium=Medium
editor_font_large=Large
__norefs=1

View File

@@ -347,9 +347,3 @@ left_autoreply=Respuesta automática
left_filter=Filtros de correo electrónico
left_pass=Cambia la contraseña
left_sig=Editar firma
editor_fontfamily_default=Por defecto
editor_font_small=Pequeño
editor_font_normal=Normal
editor_font_medium=Medio
editor_font_large=Grande

View File

@@ -450,9 +450,3 @@ left_autoreply=Erantzun automatikoa
left_filter=Posta elektronikoko iragazkiak
left_pass=Aldatu pasahitza
left_sig=Editatu Sinadura
editor_fontfamily_default=Lehenetsia
editor_font_small=Txikia
editor_font_normal=Normala
editor_font_medium=Ertaina
editor_font_large=Handia

View File

@@ -450,9 +450,3 @@ left_autoreply=پاسخ خودکار
left_filter=فیلترهای ایمیل
left_pass=تغییر رمز عبور
left_sig=امضا را ویرایش کنید
editor_fontfamily_default=پیش فرض
editor_font_small=کم اهمیت
editor_font_normal=طبیعی
editor_font_medium=متوسط
editor_font_large=بزرگ

View File

@@ -176,9 +176,3 @@ left_autoreply=Automaattinen vastaus
left_filter=Sähköpostisuodattimet
left_pass=Vaihda salasana
left_sig=Muokkaa allekirjoitusta
editor_fontfamily_default=Oletus
editor_font_small=Pieni
editor_font_normal=Normaali
editor_font_medium=Keskikokoinen
editor_font_large=Suuri

View File

@@ -1,5 +0,0 @@
editor_fontfamily_default=Défaut
editor_font_small=Petit
editor_font_normal=Normal
editor_font_medium=Moyen
editor_font_large=Grand

View File

@@ -450,9 +450,3 @@ left_autoreply=מענה אוטומטי
left_filter=מסנני דוא"ל
left_pass=שנה סיסמא
left_sig=ערוך חתימה
editor_fontfamily_default=בְּרִירַת מֶחדָל
editor_font_small=קָטָן
editor_font_normal=נוֹרמָלִי
editor_font_medium=בינוני
editor_font_large=גָדוֹל

View File

@@ -450,9 +450,3 @@ left_autoreply=Automatski odgovor
left_filter=Filteri e-pošte
left_pass=Promijenite lozinku
left_sig=Uredi potpis
editor_fontfamily_default=Zadano
editor_font_small=Mali
editor_font_normal=Normalan
editor_font_medium=Srednji
editor_font_large=velika

View File

@@ -290,9 +290,3 @@ left_autoreply=Automatikus válasz
left_filter=E-mail szűrők
left_pass=Jelszó módosítása
left_sig=Aláírás szerkesztése
editor_fontfamily_default=Alapértelmezett
editor_font_small=Kicsi
editor_font_normal=Normál
editor_font_medium=Közepes
editor_font_large=Nagy

View File

@@ -16,9 +16,3 @@ left_autoreply=Risposta automatica
left_filter=Filtri email
left_pass=Cambia la password
left_sig=Modifica firma
editor_fontfamily_default=Predefinito
editor_font_small=Piccolo
editor_font_normal=Normale
editor_font_medium=medio
editor_font_large=Grande

View File

@@ -39,9 +39,3 @@ left_autoreply=自動返信
left_filter=メールフィルター
left_pass=パスワードを変更する
left_sig=署名を編集
editor_fontfamily_default=デフォルト
editor_font_small=小さい
editor_font_normal=普通
editor_font_medium=中くらい
editor_font_large=大きい

View File

@@ -52,9 +52,3 @@ left_autoreply=자동 회신
left_filter=이메일 필터
left_pass=비밀번호 변경
left_sig=서명 편집
editor_fontfamily_default=기본
editor_font_small=작은
editor_font_normal=정상
editor_font_medium=중간
editor_font_large=크기가 큰

View File

@@ -450,9 +450,3 @@ left_autoreply=Automatinis atsakymas
left_filter=El. Pašto filtrai
left_pass=Pakeisti slaptažodį
left_sig=Redaguoti parašą
editor_fontfamily_default=Numatytas
editor_font_small=Mažas
editor_font_normal=Normalus
editor_font_medium=Vidutinis
editor_font_large=Didelis

View File

@@ -450,9 +450,3 @@ left_autoreply=Automātiska atbilde
left_filter=E-pasta filtri
left_pass=Mainīt paroli
left_sig=Rediģēt parakstu
editor_fontfamily_default=Noklusējums
editor_font_small=Mazs
editor_font_normal=Normāls
editor_font_medium=Vidēja
editor_font_large=Liels

View File

@@ -450,9 +450,3 @@ left_autoreply=Balas Automatik
left_filter=Penapis E-mel
left_pass=Tukar kata laluan
left_sig=Edit Tandatangan
editor_fontfamily_default=Lalai
editor_font_small=Kecil
editor_font_normal=Biasalah
editor_font_medium=Sederhana
editor_font_large=besar

View File

@@ -450,9 +450,3 @@ left_autoreply=Risposta awtomatika
left_filter=Email Filtri
left_pass=Biddel il-password
left_sig=Editja Firma
editor_fontfamily_default=Default
editor_font_small=Żgħir
editor_font_normal=Normali
editor_font_medium=Medju
editor_font_large=Kbir

View File

@@ -14,9 +14,3 @@ left_autoreply=Automatisch antwoord
left_filter=E-mailfilters
left_pass=Verander wachtwoord
left_sig=Handtekening bewerken
editor_fontfamily_default=Standaard
editor_font_small=Klein
editor_font_normal=Normaal
editor_font_medium=Medium
editor_font_large=Groot

View File

@@ -1,5 +0,0 @@
editor_fontfamily_default=Misligholde
editor_font_small=Liten
editor_font_normal=Normal
editor_font_medium=Medium
editor_font_large=Stor

View File

@@ -280,9 +280,3 @@ left_autoreply=Automatyczna odpowiedź
left_filter=Filtry e-mail
left_pass=Zmień hasło
left_sig=Edytuj podpis
editor_fontfamily_default=Domyślny
editor_font_small=Mały
editor_font_normal=Normalna
editor_font_medium=Średni
editor_font_large=Duży

View File

@@ -413,9 +413,3 @@ left_autoreply=Resposta automática
left_filter=Filtros de Email
left_pass=Mudar senha
left_sig=editar assinatura
editor_fontfamily_default=Padrão
editor_font_small=Pequeno
editor_font_normal=Normal
editor_font_medium=Médio
editor_font_large=Grande

View File

@@ -447,9 +447,3 @@ left_autoreply=Resposta automática
left_filter=Filtros de Email
left_pass=Mudar senha
left_sig=editar assinatura
editor_fontfamily_default=Padrão
editor_font_small=Pequeno
editor_font_normal=Normal
editor_font_medium=Médio
editor_font_large=Grande

View File

@@ -450,9 +450,3 @@ left_autoreply=Raspuns automat
left_filter=Filtre de e-mail
left_pass=Schimbați parola
left_sig=Editează semnătură
editor_fontfamily_default=Mod implicit
editor_font_small=Mic
editor_font_normal=Normal
editor_font_medium=Mediu
editor_font_large=Mare

View File

@@ -450,9 +450,3 @@ left_autoreply=Автоматический ответ
left_filter=Фильтры электронной почты
left_pass=Изменить пароль
left_sig=Изменить подпись
editor_fontfamily_default=По умолчанию
editor_font_small=Маленький
editor_font_normal=Нормальный
editor_font_medium=Середина
editor_font_large=Большой

View File

@@ -450,9 +450,3 @@ left_autoreply=Automatická odpoveď
left_filter=E-mailové filtre
left_pass=Zmeniť heslo
left_sig=Upraviť podpis
editor_fontfamily_default=Predvolené
editor_font_small=Malý
editor_font_normal=Normálne
editor_font_medium=Stredná
editor_font_large=Veľký

View File

@@ -450,9 +450,3 @@ left_autoreply=Samodejni odgovor
left_filter=E-poštni filtri
left_pass=Spremeni geslo
left_sig=Uredi podpis
editor_fontfamily_default=Privzeto
editor_font_small=majhna
editor_font_normal=normalno
editor_font_medium=Srednje
editor_font_large=Velik

View File

@@ -374,9 +374,3 @@ left_autoreply=Automatisk svar
left_filter=E-postfilter
left_pass=Ändra lösenord
left_sig=Redigera signatur
editor_fontfamily_default=Standard
editor_font_small=Små
editor_font_normal=Vanligt
editor_font_medium=Medium
editor_font_large=Stor

View File

@@ -450,9 +450,3 @@ left_autoreply=ตอบกลับอัตโนมัติ
left_filter=ตัวกรองอีเมล
left_pass=เปลี่ยนรหัสผ่าน
left_sig=แก้ไขลายเซ็น
editor_fontfamily_default=ค่าเริ่มต้น
editor_font_small=เล็ก
editor_font_normal=ปกติ
editor_font_medium=ปานกลาง
editor_font_large=ใหญ่

View File

@@ -65,9 +65,3 @@ slide_prev=Önceki
slide_next=Sonraki
left_mail=Posta
editor_fontfamily_default=Varsayılan
editor_font_small=Küçük
editor_font_normal=Normal
editor_font_medium=Orta
editor_font_large=Büyük

View File

@@ -450,9 +450,3 @@ left_autoreply=Автоматична відповідь
left_filter=Фільтри електронної пошти
left_pass=Змінити пароль
left_sig=Редагувати підпис
editor_fontfamily_default=За замовчуванням
editor_font_small=Маленький
editor_font_normal=нормальний
editor_font_medium=Середній
editor_font_large=Великий

View File

@@ -450,9 +450,3 @@ left_autoreply=خودکار جواب
left_filter=ای میل کے فلٹرز
left_pass=پاس ورڈ تبدیل کریں
left_sig=دستخط میں ترمیم کریں
editor_fontfamily_default=طے شدہ
editor_font_small=چھوٹا
editor_font_normal=نارمل
editor_font_medium=درمیانہ
editor_font_large=بڑا

View File

@@ -450,9 +450,3 @@ left_autoreply=Trả lời tự động
left_filter=Bộ lọc email
left_pass=Đổi mật khẩu
left_sig=Chỉnh sửa chữ ký
editor_fontfamily_default=Mặc định
editor_font_small=Bé nhỏ
editor_font_normal=Bình thường
editor_font_medium=Trung bình
editor_font_large=Lớn

View File

@@ -343,9 +343,3 @@ left_autoreply=自动回复
left_filter=电子邮件过滤器
left_pass=更改密码
left_sig=编辑签名
editor_fontfamily_default=默认
editor_font_small=小的
editor_font_normal=普通的
editor_font_medium=中等的
editor_font_large=大的

View File

@@ -184,9 +184,3 @@ left_autoreply=自動回复
left_filter=電子郵件過濾器
left_pass=更改密碼
left_sig=編輯簽名
editor_fontfamily_default=默認
editor_font_small=小的
editor_font_normal=普通的
editor_font_medium=中等的
editor_font_large=大的

View File

@@ -1 +1 @@
allowed=wrap_width,wrap_compose,perpage,show_to,top_buttons,arrows,show_delall,show_sent,fwd_mode,delete_warn,delete_warn_free,view_html,html_edit,html_edit_mode,html_quote,log_read,show_body,open_mode,link_mode,date_fmt,date_tz_def,date_tz
allowed=wrap_width,wrap_compose,perpage,show_to,top_buttons,arrows,show_delall,show_sent,fwd_mode,delete_warn,delete_warn_free,view_html,html_edit,html_quote,log_read,show_body,open_mode,link_mode,date_fmt,date_tz_def,date_tz

View File

@@ -2,7 +2,6 @@
# Display a form for replying to or composing an email
require './mailboxes-lib.pl';
require '../html-editor-lib.pl';
&ReadParse();
&can_user($in{'user'}) || &error($text{'mail_ecannot'});
@uinfo = &get_mail_user($in{'user'});
@@ -20,16 +19,17 @@ if ($in{'new'}) {
$html_edit = $config{'html_edit'} == 2 ? 1 : 0;
}
$sig = &get_signature($in{'user'});
if ($html_edit && $sig) {
if ($html_edit) {
$sig =~ s/\n/<br>\n/g;
$quote = "<html><body>$sig</body></html>";
$quote = "<html><body></body></html>";
}
else {
$quote = "\n\n$sig" if ($sig);
}
$to = $in{'to'};
$main::force_charset = &get_charset();
&mail_page_header($text{'compose_title'}, undef, undef,
&mail_page_header($text{'compose_title'}, undef,
$html_edit ? "onload='xinha_init()'" : "",
&folder_link($in{'user'}, $folder));
}
else {
@@ -316,30 +316,19 @@ else {
# Construct the initial mail text
$sig = &get_signature($in{'user'});
($quote, $html_edit, $body) = &quoted_message($mail, $qu, $sig);
# Load images using server in replies
$quote = &disable_html_images($quote, 3);
# Don't include the original body as an attachment
@attach = &remove_body_attachments($mail, \@attach);
if (!$in{'forward'} && !$in{'enew'}) {
# When replying, lose non-cid attachments
@attach = grep { $_->{'header'}->{'content-id'} ||
$_->{'header'}->{'content-location'} } @attach;
if ($in{'forward'} || $in{'enew'}) {
@attach = grep { $_ ne $body } @attach;
}
# For a HTML reply or forward, fix up the cid: to refer to attachments
# in the original message.
if ($html_edit) {
my $uuser = &urlize($in{'user'});
$quote = &fix_cids($quote, \@attach,
"detach.cgi?user=$uuser&idx=$in{'idx'}&folder=$in{'folder'}$subs");
else {
undef(@attach);
}
# Show header
&mail_page_header(
$in{'forward'} || @mailforward ? $text{'forward_title'} :
$in{'enew'} ? $text{'enew_title'} :
$text{'reply_title'}, undef, undef,
$text{'reply_title'}, undef,
$html_edit ? "onload='xinha_init()'" : "",
&folder_link($in{'user'}, $folder));
}
@@ -455,35 +444,35 @@ if ($in{'new'}) {
# Output message body input
print &ui_table_start($text{'reply_body'}, "width=100%", 2, undef,
&ui_links_row(\@bodylinks));
# Process email quote
my $iframe_quote;
$iframe_quote = &iframe_quote($quote)
if (!$in{'new'});
if ($html_edit) {
# Get HTML editor and replies
my $html_editor = &html_editor(
{ textarea =>
{ target => { name => 'body', attr => 'name' },
sync =>
{ position => 'after',
data => [ { iframe => '#quote-mail-iframe',
elements => ['#webmin-iframe-quote'] } ] }
},
type => $config{'html_edit_mode'} || 'simple',
after =>
{ editor => $iframe_quote }
});
$sig =~ s/\n/<br>/g,
$sig =~ s/^\s+//g,
$sig = "<br><br>$sig<br><br>"
if ($sig);
if ($current_theme !~ /authentic-theme/) {
# Output HTML editor textarea
print <<EOF;
<script type="text/javascript">
_editor_url = "@{[&get_webprefix()]}/$module_name/xinha/";
_editor_lang = "en";
</script>
<script type="text/javascript" src="xinha/XinhaCore.js"></script>
<script type="text/javascript">
xinha_init = function()
{
xinha_editors = [ "body" ];
xinha_plugins = [ ];
xinha_config = new Xinha.Config();
xinha_config.hideSomeButtons(" print showhelp about killword toggleborders ");
xinha_editors = Xinha.makeEditors(xinha_editors, xinha_config, xinha_plugins);
Xinha.startEditors(xinha_editors);
}
</script>
EOF
}
else {
print '<script type="text/javascript">xinha_init = function(){}</script>';
}
print &ui_table_row(undef,
&ui_textarea("body", $sig, 12, 80, undef, 0,
"style='display: none' id=body data-html-mode='$config{'html_edit_mode'}'").
$html_editor, 2);
&ui_textarea("body", $quote, 40, 80, undef, 0,
"style='width:99%' id=body"), 2);
}
else {
# Show text editing area
@@ -491,13 +480,13 @@ else {
$wm =~ s/^wrap=//g;
$wcols = $config{'wrap_compose'};
print &ui_table_row(undef,
&ui_textarea("body", "\n\n$sig\n\n$quote", 12,
&ui_textarea("body", $quote, 20,
$wcols || 80,
$wcols ? "hard" : "",
0,
$wcols ? "" : "style='width:100%'"), 2);
}
if (&has_command("ispell") && $config{'ispell_enabled'}) {
if (&has_command("ispell")) {
print &ui_table_row(undef,
&ui_checkbox("spell", 1, $text{'reply_spell'}, 0), 2);
}
@@ -510,20 +499,10 @@ $viewurl = "view_mail.cgi?idx=$in{'idx'}&user=$euser&".
$detachurl = "detach.cgi?idx=$in{'idx'}&user=$euser&".
"&folder=$folder->{'index'}$subs";
$mailurl = "view_mail.cgi?user=$euser&folder=$folder->{'index'}$subs";
my @non_body_attach;
if (@attach) {
@non_body_attach = &remove_cid_attachments($mail, \@attach);
}
if (@non_body_attach) {
&attachments_table(\@non_body_attach, $folder, $viewurl, $detachurl,
&attachments_table(\@attach, $folder, $viewurl, $detachurl,
$mailurl, 'idx', "forward");
}
foreach my $a (@attach) {
if (&indexof($a, @non_body_attach) < 0) {
# Body attachment .. always include
print &ui_hidden("forward", $a->{'idx'});
}
}
}
# Display forwarded mails
if (@fwdmail) {

View File

@@ -3,7 +3,6 @@
# Send off an email message
require './mailboxes-lib.pl';
require '../html-editor-lib.pl';
&ReadParse(\%getin, "GET");
&ReadParseMime(undef, \&read_parse_mime_callback, [ $getin{'id'} ], 1);
foreach my $k (keys %in) {
@@ -47,8 +46,6 @@ if ($in{'from'} =~ /^(\S+)\@(\S+)$/ && $access{'fromname'}) {
}
@sub = split(/\0/, $in{'sub'});
$subs = join("", map { "&sub=$_" } @sub);
my @inline_images;
my %cidmap;
# Construct the email
$in{'from'} || &error($text{'send_efrom'});
@@ -70,42 +67,9 @@ if ($in{'bcc'}) {
push(@{$mail->{'headers'}}, [ 'X-Priority', $in{'pri'} ]) if ($in{'pri'});
$in{'body'} =~ s/\r//g;
if ($in{'body'} =~ /\S/) {
if ($in{'html_edit'}) {
$in{'body'} = &html_editor_substitute_classes_with_styles($in{'body'});
}
my $preplainbody = $in{'body'};
my $prehtmlbody = $in{'body'};
# Extract inline images if any
@inline_images = ($in{'body'} =~ /(data:image\/.*?;base64,)(.*?)"/g);
if (@inline_images) {
my $iid = 1;
for (my $i = 0; $i < scalar(@inline_images) - 1; $i += 2) {
if ($inline_images[$i] =~ /data:image/) {
my ($type) = $inline_images[$i] =~ /data:image\/(.*?);base64,/;
my $cid = "ii_".(time() + $i).'@'."$type";
my $replace_html = "$inline_images[$i]$inline_images[$i+1]";
my @data = split('@', $cid);
$inline_images[$i] = \@data;
$inline_images[$i+1] = decode_base64($inline_images[$i+1]);
# $cid = "cid:$cid\" style=\"width: 60%";
$cid = "cid:$cid";
# Replace for HTML
$in{'body'} =~ s/\Q$replace_html/$cid/;
# Replace for plain text
$preplainbody =~ s/<img[^>]*>/[image: inline-image$iid.$type]/;
$iid++;
}
}
$prehtmlbody = $in{'body'};
}
# Perform spell check on body if requested
local $plainbody = $in{'html_edit'} ? &html_to_text($preplainbody)
: $prehtmlbody;
local $plainbody = $in{'html_edit'} ? &html_to_text($in{'body'})
: $in{'body'};
if ($in{'spell'}) {
@errs = &spell_check_text($plainbody);
if (@errs) {
@@ -122,14 +86,6 @@ if ($in{'body'} =~ /\S/) {
exit;
}
}
# For a HTML body, replace images from detach.cgi on the original
# email with cid: references.
if ($in{'html_edit'}) {
$in{'body'} = &create_cids($in{'body'}, \%cidmap);
}
# Create the body attachment
local $mt = $in{'html_edit'} ? "text/html" : "text/plain";
if ($in{'charset'}) {
$mt .= "; charset=$in{'charset'}";
@@ -185,49 +141,29 @@ if ($in{'body'} =~ /\S/) {
}
}
# Add inline images
if (@inline_images) {
my $iid = 1;
for (my $i = 0; $i < scalar(@inline_images) - 1; $i += 2) {
my $cid = $inline_images[$i][0]."@".$inline_images[$i][1];
my $type = $inline_images[$i][1];
my $image_name = "inline-image$iid.$type";
my $data = $inline_images[$i + 1];
push(@attach,
{ 'data' => $data,
'headers' => [['Content-type', "image/$type; name=\"$image_name\""],
['Content-Disposition', "inline; filename=\"$image_name\""],
['Content-ID', "<$cid>"],
['Content-Transfer-Encoding', 'base64']
]
});
$iid++;
}
}
# Add uploaded attachment
$attachsize = 0;
for($i=0; defined($in{"attach$i"}); $i++) {
next if (!$in{"attach$i"});
for($j=0; $j<@{$in{"attach$i"}}; $j++) {
next if (!$in{"attach${i}"}->[$j]);
&test_max_attach(length($in{"attach${i}"}->[$j]));
local $filename = $in{"attach${i}_filename"}->[$j];
$filename =~ s/^.*(\\|\/)//;
local $type = $in{"attach${i}_content_type"}->[$j].
"; name=\"".$filename."\"";
local $disp = "attachment; filename=\"".$filename."\"";
push(@attach, { 'data' => $in{"attach${i}"}->[$j],
'headers' => [ [ 'Content-type', $type ],
[ 'Content-Disposition', $disp ],
[ 'Content-Transfer-Encoding',
'base64' ] ] });
$atotal += length($in{"attach${i}"}->[$j]);
}
}
# Add uploaded attachment
next if (!$in{"attach$i"});
for($j=0; $j<@{$in{"attach$i"}}; $j++) {
next if (!$in{"attach${i}"}->[$j]);
&test_max_attach(length($in{"attach${i}"}->[$j]));
local $filename = $in{"attach${i}_filename"}->[$j];
$filename =~ s/^.*(\\|\/)//;
local $type = $in{"attach${i}_content_type"}->[$j].
"; name=\"".$filename."\"";
local $disp = "attachment; filename=\"".$filename."\"";
push(@attach, { 'data' => $in{"attach${i}"}->[$j],
'headers' => [ [ 'Content-type', $type ],
[ 'Content-Disposition', $disp ],
[ 'Content-Transfer-Encoding',
'base64' ] ] });
$atotal += length($in{"attach${i}"}->[$j]);
}
}
# Add server-side attachment
for($i=0; defined($in{"file$i"}); $i++) {
# Add server-side attachment
next if (!$in{"file$i"} || !$access{'canattach'});
@uinfo = &get_mail_user($in{'user'});
@uinfo || &error($text{'view_eugone'});
@@ -253,10 +189,9 @@ for($i=0; defined($in{"file$i"}); $i++) {
'base64' ] ] });
$atotal += length($data);
}
# Add forwarded attachments
@fwd = split(/\0/, $in{'forward'});
if (@fwd) {
# Add forwarded attachments
@mail = &mailbox_list_mails($in{'idx'}, $in{'idx'}, $folder);
$fwdmail = $mail[$in{'idx'}];
&parse_mail($fwdmail);
@@ -268,26 +203,15 @@ if (@fwd) {
$fwdmail = $amail;
}
foreach my $f (@fwd) {
foreach $f (@fwd) {
&test_max_attach(length($fwdmail->{'attach'}->[$f]->{'data'}));
$a = $fwdmail->{'attach'}->[$f];
if ($cidmap{$f}) {
# This attachment has been inlined .. set a content-id
$a->{'headers'} = [
grep { lc($_->[0]) ne 'content-id' &&
lc($_->[0]) ne 'content-location' }
@{$a->{'headers'}} ];
push(@{$a->{'headers'}},
[ 'Content-Id', "<$cidmap{$f}>" ]);
}
push(@attach, $a);
push(@attach, $fwdmail->{'attach'}->[$f]);
$atotal += length($fwdmail->{'attach'}->[$f]->{'data'});
}
}
@mailfwd = split(/\0/, $in{'mailforward'});
# Add forwarded emails
if (@mailfwd) {
# Add forwarded emails
@mail = &mailbox_list_mails($mailfwd[0], $mailfwd[@mailfwd-1], $folder);
foreach $f (@mailfwd) {
$fwdmail = $mail[$f];

View File

@@ -56,6 +56,11 @@ $body = $htmlbody if ($in{'body'} == 2);
$body = $textbody if ($in{'body'} == 1);
@attach = @{$mail->{'attach'}};
# Show pre-body HTML
if ($body && $body eq $htmlbody) {
$headstuff = &head_html($body->{'data'});
}
$mail_charset = &get_mail_charset($mail, $body);
if ($body && &get_charset() eq 'UTF-8' &&
&can_convert_to_utf8(undef, $mail_charset)) {
@@ -67,7 +72,7 @@ else {
$main::force_charset = &get_mail_charset($mail, $body);
}
&mail_page_header($text{'view_title'}, undef, undef,
&mail_page_header($text{'view_title'}, $headstuff, undef,
&folder_link($in{'user'}, $folder));
&show_arrows();
@@ -156,28 +161,19 @@ if ($body && $body->{'data'} =~ /\S/) {
}
elsif ($body eq $htmlbody) {
# Attempt to show HTML
$bodycontents = $body->{'data'};
my @imageurls;
my $image_mode = int(defined($in{'images'}) ? $in{'images'} : $config{'view_images'});
$bodycontents = &disable_html_images($bodycontents, $image_mode, \@imageurls);
$bodycontents = &safe_html($body->{'data'});
$bodycontents = &fix_cids($bodycontents, \@attach,
"detach.cgi?user=$uuser&idx=$in{'idx'}&folder=$in{'folder'}$subs");
if ($textbody) {
push(@bodyright,
"<a href='$hbase&body=1'>$text{'view_astext'}</a>");
}
if (@imageurls && $image_mode && $image_mode != 3) {
# Link to show images
push(@bodyright, "<a href='$hbase&body=$in{'body'}&headers=$in{'headers'}&images=3'>$text{'view_images'}</a>");
}
}
$bodycontents = &iframe_body($bodycontents)
if ($bodycontents);
}
if ($bodycontents) {
print &ui_table_start($text{'view_body'}, "width=100%", 1,
undef, &ui_links_row(\@bodyright));
print &ui_table_row(undef, $bodycontents, undef, undef, ["data-contents='email'"]);
print &ui_table_row(undef, $bodycontents);
print &ui_table_end();
}
else {

Some files were not shown because too many files have changed in this diff Show More