File: /usr/local/www/apache24/cgi-bin/easytecc4/index.pl
#!/usr/iports/bin/perl
BEGIN {
if(-e '/etc/sudoers'){
my $osversion = `/usr/bin/uname -K`;
chomp $osversion;
my $perl;
if($osversion >= 1300000){
$perl = '5.34';
} elsif($osversion >= 1200000){
$perl = '5.26';
} elsif($osversion >= 1003000){
$perl = '5.24';
} else {
$perl = '5.20';
}
@INC = (
"/usr/iports/lib/perl5/site_perl",
"/usr/iports/lib/perl5/amd64-freebsd-thread-multi",
"/usr/iports/lib/perl5/$perl",
"/usr/iports/lib/perl5/$perl/mach",
"/usr/iports/lib/perl5/site_perl/mach/$perl",
"/usr/local/lib/perl5/site_perl",
"/usr/local/lib/perl5/amd64-freebsd-thread-multi",
"/usr/local/lib/perl5/$perl",
"/usr/local/lib/perl5/$perl/mach",
"/usr/local/lib/perl5/site_perl/mach/$perl",
"/usr/local/www/apache24/cgi-bin/easytecc4"
);
} else {
push @INC, '/home/httpd/cgi-bin/easytecc4';
}
}
my $fb = ""; ### Mario: /etc/sudoers existiert nur auf unseren FreeBSD-Servern ###
if (-e '/etc/sudoers') {
$fb = '1';
$ENV{'SHELL'} = '/bin/sh';
}
my ($easytecc_prefix, $droot_prefix, $droot_regex, $awstats_updateall, $awstats_conf_prefix, $lang_basedir);
if ($fb) {
#'use lib' does not care about codelevel conditions...
#use lib '/usr/local/www/apache24/cgi-bin/easytecc4';
$easytecc_prefix = '/usr/local/www/apache24/cgi-bin/easytecc4';
$droot_prefix = '/usr/local/www/apache24/noexec';
$droot_regex = '\/usr\/local\/www\/apache24\/noexec\/';
$cgi_prefix = '/usr/local/www/apache24/cgi-bin';
$awstats_updateall = '/usr/local/www/awstats/tools/awstats_updateall.pl -configdir=/usr/local/etc/awstats';
$mysqlbackup_dir = '/usr/local/etc/easytecc/mysqlbackup';
$mysql = '/usr/iports/bin/mysql';
$awstats_conf_prefix = '/usr/local/etc/awstats';
$lang_basedir = '/usr/local/www/apache24/cgi-bin/easytecc4/lang';
$autoresponder = '/usr/sbin/autoresponder';
}
else{
#'use lib' does not care about codelevel conditions...
#use lib '/home/httpd/cgi-bin/easytecc4';
$easytecc_prefix = '/home/httpd/cgi-bin/easytecc4';
$droot_prefix = '/home/httpd/docs';
$droot_regex = '\/home\/httpd\/docs\/';
$cgi_prefix = '/home/httpd/cgi-bin';
$awstats_updateall = '/usr/local/awstats/tools/awstats_updateall.pl';
$mysqlbackup_dir = '/var/lib/mysqlbackup';
$mysql = '/usr/local/mysql/bin/mysql';
$awstats_conf_prefix = '/etc/awstats';
$lang_basedir = '/home/httpd/cgi-bin/easytecc4/lang';
$autoresponder = '/usr/local/bin/autoresponder';
}
our $easytecc_version='07.09.2022';
use Data::Dumper;
use CGI qw(:all);
use CGI::Carp "fatalsToBrowser";
use easytecc_class;
use easytecc3 qw(ascii_domain is_domain is_email);
use validator qw(validate_input);
use HTML::Template;
use CGI::Cookie;
use CGI::Session;
use DBI;
use HTML::Entities qw(encode_entities decode_entities encode_entities_numeric);
use Encode;
use JSON;
use Encode::Guess;
use Data::FormValidator;
use HTTP::Request;
use LWP::UserAgent;
use Net::IDN::Encode ':all';
use URI::Escape;
use Socket qw(inet_aton);
use Digest::MD5 qw(md5_hex);
#perl zu alt
#use MIME::Base64 qw(encode_base64 decode_base64 encode_base64url decode_base64url);
use MIME::Base64 qw(encode_base64 decode_base64);
$| = 1;
#Jimmy: Log around the world
use Log::Dispatch;
use Log::Dispatch::File;
use File::Spec;
use Time::Format qw(%time %strftime);
use constant LOG_DIR => '/home/web/log';
use constant LOG_FILE => 'easytecc4.log';
our $loglevel = 'debug'; #'debug','info','notice','warning','error','critical','alert','emergency' # most reasonable is 'warning' or 'error' for production
sub dienice ($);
sub logline($$);
#
# Begin setup logging agent
#
our $log = new Log::Dispatch(
callbacks => sub {
my %h=@_;
my ($package, $filename, $line) = caller;
my $level = sprintf '%-8.8s', $h{level};
return $strftime{'%b %e %T'}." \[$$]: ".$level." => ".$h{message}."\n";
}
);
our $debug = 0;
$debug = 1 if(-e '/etc/easytecc'); #run logline("debug",...) only when $debug=1
my $debug_content = 0; #spam the log with html content
if ($debug) {
$log->add( Log::Dispatch::File->new( name => 'logfile',
min_level => $loglevel,
mode => 'append',
filename => File::Spec->catfile(LOG_DIR, LOG_FILE),
)
);
}
#
# End setup logging agent
#
logline("notice","#############################################################");
logline("notice"," $$ NEW REQUEST $$");
logline("notice","#############################################################");
my $cgi = new CGI;
our %input = $cgi->Vars;
logline("debug","input was:" . Data::Dumper->Dump([\%input]));
foreach(keys %input){
$input{$_} = decode("utf-8", $input{$_});
$input{$_} =~ s/^\s+//;
$input{$_} =~ s/\s+$//;
}
if(exists($input{dir})){
$input{dir} = decode_base64url($input{dir});
}
if(exists($input{file})){
$input{file} = decode_base64url($input{file});
}
if(exists($input{full_file})){
$input{full_file} = decode_base64url($input{full_file});
}
logline("debug","input is:" . Data::Dumper->Dump([\%input]));
my $action = 'login';
my $results = '';
my $success_text = '';
my $success_text2 = '';
my $success_text3 = '';
my $success_text4 = '';
my $success_text5 = '';
my $validation_result = '';
my %lang_dict;
my $lang = '';
our $session = '';
my $lang_cookie = cookie( -name => 'LANG' );
my $new_lang_cookie = '';
my $session_id = cookie( -name => 'LOGIN' );
# bricht autonistaller
#if($session_id){
# $session_id = easytecc3::decrypt($session_id);
#}
my $lang_new = $input{'lang_new'};
my %available_lang;
# tjahmm, doppeln wir das mal. ich wusste gar nicht, dass man scheisse so hoch stapeln kann.
my @lang_array;
# noch ne lang!
my $lang_selected = $lang_new || $lang_cookie || 'deu';
opendir (DIR, $lang_basedir) or die $!;
while (my $language_file = readdir(DIR)) {
next if ($language_file !~ m/^([a-z][a-z][a-z])\.csv$/);
my ($lang_code) = $language_file =~ m/^([a-z][a-z][a-z])\.csv$/;
my $lang = {};
$lang->{'lang_code'} = $lang_code;
if($lang_code eq $lang_selected){
$lang->{'lang_selected'} = "SELECTED";
}
push(@lang_array, $lang);
$available_lang{$lang_code} = $lang_code;
}
closedir(DIR);
@lang_array = sort { $a->{'lang_code'} cmp $b->{'lang_code'} } @lang_array;
#logline("debug"," -M A R I O- --> available_lang is:" . Data::Dumper->Dump([\%available_lang]));
my %json_output = ();
our %error_fields;
my $image_basedir = '/easytecc3/images';
my %actions = ( 'login' => 'login',
'exec_login' => 'start',
'logout' => 'logout',
'change_lang' => 'start',
'change_user' => 'start',
'start' => 'start',
'error' => 'error',
'show_cloneworx' => 'show_cloneworx',
'show_vhosts' => 'show_vhosts',
'show_email' => 'show_email',
'show_ftpuser' => 'show_ftpuser',
'show_adminuser' => 'show_adminuser',
'show_quota' => 'show_quota',
'show_special_spamfilter' => 'show_special_spamfilter',
'show_virusfilter' => 'show_virusfilter',
'show_scan_antivirus' => 'show_scan_antivirus',
'show_dbbackup' => 'show_dbbackup',
'show_mysqlbackup_details' => 'show_mysqlbackup_details',
'show_cronjobs' => 'show_cronjobs',
'show_frontpage' => 'show_frontpage',
'show_filemanager' => 'show_filemanager',
'show_htpasswd' => 'show_htpasswd',
'show_logfiles' => 'show_logfiles',
'domainsearch' => 'domainsearch',
'change_errordocs' => 'change_errordocs',
'show_webmailer' => 'show_webmailer',
'new_vhost' => 'new_vhost',
'change_vhost' => 'change_vhost',
'delete_vhost' => 'delete_vhost',
'change_popuser' => 'change_popuser',
'change_forward' => 'change_forward',
'change_forward_single_edit' => 'change_forward_single_edit',
'new_autoreply' => 'new_autoreply',
'change_autoreply' => 'change_autoreply',
'delete_autoreply' => 'delete_autoreply',
'new_ftpuser' => 'new_ftpuser',
'change_ftpuser' => 'change_ftpuser',
'delete_ftpuser' => 'delete_ftpuser',
'new_adminuser' => 'new_adminuser',
'change_adminuser' => 'change_adminuser',
'delete_adminuser' => 'delete_adminuser',
'change_spamfilter' => 'change_spamfilter',
'new_special_spamfilter' => 'new_special_spamfilter',
'change_special_spamfilter' => 'change_special_spamfilter',
'delete_special_spamfilter' => 'delete_special_spamfilter',
'change_virusfilter' => 'change_virusfilter',
'auto_cronjob' => 'auto_cronjob',
'new_cronjob' => 'new_cronjob',
'change_cronjob' => 'change_cronjob',
'delete_cronjob' => 'delete_cronjob',
'new_fileman' => 'new_fileman',
'change_fileman' => 'change_fileman',
'new_htaccess' => 'new_htaccess',
'change_htaccess' => 'change_htaccess',
'delete_htaccess' => 'delete_htaccess',
'new_frontpage' => 'new_frontpage',
'delete_frontpage' => 'delete_frontpage',
'delete_logfiles' => 'delete_logfiles',
'instant_mysqlbackup' => 'instant_mysqlbackup',
'change_mysqlbackup' => 'change_mysqlbackup',
'confirm_restore_mysqlbackup' => 'confirm_restore_mysqlbackup',
'download_mysqlbackup' => 'download_mysqlbackup',
'delete_mysql_auto_backup' => 'delete_mysql_auto_backup',
'exec_restore_mysqlbackup' => 'exec_restore_mysqlbackup',
'exec_delete_mysql_auto_backup' => 'exec_delete_mysql_auto_backup',
'new_mysqluser' => 'new_mysqluser',
'change_mysqluser' => 'change_mysqluser',
'exec_new_vhost' => 'exec_new_vhost',
'exec_delete_vhost' => 'exec_delete_vhost',
'exec_change_vhost' => 'exec_change_vhost',
'exec_delete_popuser' => 'exec_delete_popuser',
'exec_change_popuser' => 'exec_change_popuser',
'exec_delete_forward' => 'exec_delete_forward',
'exec_change_forward' => 'exec_change_forward',
'exec_change_forward_single_edit' => 'exec_change_forward_single_edit',
'exec_new_autoreply' => 'exec_new_autoreply',
'exec_change_autoreply' => 'exec_change_autoreply',
'exec_delete_autoreply' => 'exec_delete_autoreply',
'exec_new_ftpuser' => 'exec_new_ftpuser',
'exec_delete_ftpuser' => 'exec_delete_ftpuser',
'exec_change_ftpuser' => 'exec_change_ftpuser',
'exec_new_adminuser' => 'exec_new_adminuser',
'exec_delete_adminuser' => 'exec_delete_adminuser',
'exec_change_adminuser' => 'exec_change_adminuser',
'exec_change_spamfilter' => 'exec_change_spamfilter',
'exec_new_special_spamfilter' => 'exec_new_special_spamfilter',
'exec_change_special_spamfilter' => 'exec_change_special_spamfilter',
'exec_delete_special_spamfilter' => 'exec_delete_special_spamfilter',
'exec_change_virusfilter' => 'exec_change_virusfilter',
'exec_scan_antivirus' => 'exec_scan_antivirus',
'exec_new_cronjob' => 'exec_new_cronjob',
'exec_auto_cronjob' => 'exec_auto_cronjob',
'exec_delete_cronjob' => 'exec_delete_cronjob',
'exec_change_cronjob' => 'exec_change_cronjob',
'exec_change_errordocs' => 'exec_change_errordocs',
'exec_new_htaccess' => 'exec_new_htaccess',
'exec_delete_htaccess' => 'exec_delete_htaccess',
'exec_change_htaccess' => 'exec_change_htaccess',
'exec_new_frontpage' => 'exec_new_frontpage',
'exec_delete_frontpage' => 'exec_delete_frontpage',
'exec_delete_logfiles' => 'exec_delete_logfiles',
'exec_delete_mysqlbackup' => 'exec_delete_mysqlbackup',
'exec_change_mysqlbackup' => 'exec_change_mysqlbackup',
'exec_new_mysqluser' => 'exec_new_mysqluser',
'exec_delete_mysqluser' => 'exec_delete_mysqluser',
'exec_change_mysqluser' => 'exec_change_mysqluser',
'exec_domainsearch' => 'exec_domainsearch',
'write_db_pass' => 'write_db_pass',
'add_mysql_password' => 'add_mysql_password',
'exec_add_mysql_password' => 'exec_add_mysql_password',
'modify_dir' => 'modify_dir',
'exec_modify_dir' => 'exec_modify_dir',
'modify_file' => 'modify_file',
'exec_modify_file' => 'exec_modify_file',
'download_file' => 'download_file',
'new_sendmail_cw' => 'new_sendmail_cw',
'exec_new_sendmail_cw' => 'exec_new_sendmail_cw',
'delete_sendmail_cw' => 'delete_sendmail_cw',
'exec_delete_sendmail_cw' => 'exec_delete_sendmail_cw',
'awstats_migration' => 'awstats_migration',
'exec_awstats_migration' => 'exec_awstats_migration',
'roundcube_migration' => 'roundcube_migration',
'exec_roundcube_migration' => 'exec_roundcube_migration',
'confirm_delete_forward' => 'confirm_delete_forward',
'confirm_delete_mysqlbackup' => 'confirm_delete_mysqlbackup',
'exec_delete_alert' => 'exec_delete_alert',
'show_single_edit_email' => 'show_single_edit_email',
'new_forward_single_edit' => 'new_forward_single_edit',
'exec_new_forward_single_edit' => 'exec_new_forward_single_edit',
'new_install' => 'new_install',
'confirm_new_install' => 'confirm_new_install',
'exec_new_install' => 'exec_new_install',
'add_ssl_vhost' => 'add_ssl_vhost',
'exec_add_ssl_vhost' => 'exec_add_ssl_vhost',
'change_ssl_vhost' => 'change_ssl_vhost',
'exec_change_ssl_vhost' => 'exec_change_ssl_vhost',
'show_save_note' => 'show_save_note',
'exec_show_save_note' => 'exec_show_save_note',
'new_quotamessage' => 'new_quotamessage',
'exec_new_quotamessage' => 'exec_new_quotamessage',
'new_mailserver_cert' => 'new_mailserver_cert',
'exec_new_mailserver_cert' => 'exec_new_mailserver_cert',
'info_mailuser' => 'info_mailuser',
'confirm_expunge_mailbox' => 'confirm_expunge_mailbox',
'exec_expunge_mailbox' => 'exec_expunge_mailbox',
'new_dir' => 'new_dir',
'exec_new_dir' => 'exec_new_dir',
'change_firewall' => 'change_firewall',
'list_add_ip' => 'list_add_ip',
'exec_list_add_ip' => 'exec_list_add_ip',
'search_logs' => 'search_logs',
'web2ban_edit_rule' => 'web2ban_edit_rule',
'exec_web2ban_edit_rule' => 'exec_web2ban_edit_rule',
'web2ban_add_rule' => 'web2ban_add_rule',
'exec_web2ban_add_rule' => 'exec_web2ban_add_rule',
'logrotate' => 'logrotate',
'exec_logrotate' => 'exec_logrotate',
'whois' => 'whois',
'show_create_dkim' => 'show_create_dkim',
'scan2ban_add_port' => 'scan2ban_add_port',
'exec_scan2ban_add_port' => 'exec_scan2ban_add_port',
'import_mailuser' => 'import_mailuser',
'exec_import_mailuser' => 'exec_import_mailuser',
'stop_import_mailuser' => 'stop_import_mailuser',
'showlog_import_mailuser' => 'showlog_import_mailuser',
'mailuser_interface' => 'mailuser_interface',
'change_autoresponder_sieve' => 'change_autoresponder_sieve',
'exec_change_autoresponder_sieve' => 'exec_change_autoresponder_sieve',
'change_forward_sieve' => 'change_forward_sieve',
'exec_change_forward_sieve' => 'exec_change_forward_sieve'
);
#bei diesen Aktionen wird Fehlermeldung über ajax an Browser gesendet anstatt neue Seite zu laden
my %ajax_actions = ( 'new_forward_single_edit' => 'new_forward_single_edit',
'exec_new_forward_single_edit' => 'exec_new_forward_single_edit',
'exec_edit_forward' => 'exec_edit_forward',
'new_vhost' => 'new_vhost',
'exec_new_vhost' => 'exec_new_vhost',
'change_vhost' => 'change_vhost',
'exec_change_vhost' => 'exec_change_vhost',
'delete_vhost' => 'delete_vhost',
'exec_delete_vhost' => 'exec_delete_vhost',
'change_popuser' => 'change_popuser',
'exec_change_popuser' => 'exec_change_popuser',
'change_forward' => 'change_forward',
'change_forward_single_edit' => 'change_forward_single_edit',
'exec_change_forward' => 'exec_change_forward',
'exec_change_forward_single_edit' => 'exec_change_forward_single_edit',
'exec_delete_popuser' => 'exec_delete_popuser',
'exec_delete_forward' => 'exec_delete_forward',
'new_autoreply' => 'new_autoreply',
'exec_new_autoreply' => 'exec_new_autoreply',
'change_autoreply' => 'change_autoreply',
'exec_change_autoreply' => 'exec_change_autoreply',
'delete_autoreply' => 'delete_autoreply',
'exec_delete_autoreply' => 'exec_delete_autoreply',
'new_ftpuser' => 'new_ftpuser',
'exec_new_ftpuser' => 'exec_new_ftpuser',
'change_ftpuser' => 'change_ftpuser',
'exec_change_ftpuser' => 'exec_change_ftpuser',
'delete_ftpuser' => 'delete_ftpuser',
'exec_delete_ftpuser' => 'exec_delete_ftpuser',
'new_adminuser' => 'new_adminuser',
'exec_new_adminuser' => 'exec_new_adminuser',
'change_adminuser' => 'change_adminuser',
'exec_change_adminuser' => 'exec_change_adminuser',
'delete_adminuser' => 'delete_adminuser',
'exec_delete_adminuser' => 'exec_delete_adminuser',
'change_special_spamfilter' => 'change_special_spamfilter',
'exec_change_special_spamfilter' => 'exec_change_special_spamfilter',
'delete_special_spamfilter' => 'delete_special_spamfilter',
'exec_delete_special_spamfilter' => 'exec_delete_special_spamfilter',
'delete_logfiles' => 'delete_logfiles',
'exec_delete_logfiles' => 'exec_delete_logfiles',
'auto_cronjob' => 'auto_cronjob',
'exec_auto_cronjob' => 'exec_auto_cronjob',
'change_mysqlbackup' => 'change_mysqlbackup',
'exec_change_mysqlbackup' => 'exec_change_mysqlbackup',
'show_mysqlbackup_details' => 'show_mysqlbackup_details',
'instant_mysqlbackup' => 'instant_mysqlbackup',
'confirm_delete_mysqlbackup' => 'confirm_delete_mysqlbackup',
'confirm_restore_mysqlbackup' => 'confirm_restore_mysqlbackup',
'exec_restore_mysqlbackup' => 'exec_restore_mysqlbackup',
'exec_delete_mysqlbackup' => 'exec_delete_mysqlbackup',
'delete_mysql_auto_backup' => 'delete_mysql_auto_backup',
'exec_delete_mysql_auto_backup' => 'exec_delete_mysql_auto_backup',
'new_cronjob' => 'new_cronjob',
'change_cronjob' => 'change_cronjob',
'delete_cronjob' => 'delete_cronjob',
'exec_new_cronjob' => 'exec_new_cronjob',
'exec_delete_cronjob' => 'exec_delete_cronjob',
'exec_change_cronjob' => 'exec_change_cronjob',
'delete_sendmail_cw' => 'delete_sendmail_cw',
'exec_delete_sendmail_cw' => 'exec_delete_sendmail_cw',
'exec_delete_alert' => 'exec_delete_alert',
'modify_file' => 'modify_file',
'exec_modify_file' => 'exec_modify_file',
'modify_dir' => 'modify_dir',
'exec_modify_dir' => 'exec_modify_dir',
'new_htaccess' => 'new_htaccess',
'exec_new_htaccess' => 'exec_new_htaccess',
'change_htaccess' => 'change_htaccess',
'delete_htaccess' => 'delete_htaccess',
'exec_change_htaccess' => 'exec_change_htaccess',
'exec_delete_htaccess' => 'exec_delete_htaccess',
'confirm_new_install' => 'confirm_new_install',
'add_ssl_vhost' => 'add_ssl_vhost',
'exec_add_ssl_vhost' => 'exec_add_ssl_vhost',
'change_ssl_vhost' => 'change_ssl_vhost',
'exec_change_ssl_vhost' => 'exec_change_ssl_vhost',
'show_save_note' => 'show_save_note',
'exec_show_save_note' => 'exec_show_save_note',
'info_mailuser' => 'info_mailuser',
'confirm_expunge_mailbox' => 'confirm_expunge_mailbox',
'exec_expunge_mailbox' => 'exec_expunge_mailbox',
'new_dir' => 'new_dir',
'exec_new_dir' => 'exec_new_dir',
'list_add_ip' => 'list_add_ip',
'exec_list_add_ip' => 'exec_list_add_ip',
'search_logs' => 'search_logs',
'web2ban_edit_rule' => 'web2ban_edit_rule',
'exec_web2ban_edit_rule' => 'exec_web2ban_edit_rule',
'web2ban_add_rule' => 'web2ban_add_rule',
'exec_web2ban_add_rule' => 'exec_web2ban_add_rule',
'logrotate' => 'logrotate',
'exec_logrotate' => 'exec_logrotate',
'whois' => 'whois',
'show_create_dkim' => 'show_create_dkim',
'scan2ban_add_port' => 'scan2ban_add_port',
'exec_scan2ban_add_port' => 'exec_scan2ban_add_port',
'import_mailuser' => 'import_mailuser',
'exec_import_mailuser' => 'exec_import_mailuser',
'stop_import_mailuser' => 'stop_import_mailuser',
'showlog_import_mailuser' => 'showlog_import_mailuser',
'change_autoresponder_sieve' => 'change_autoresponder_sieve',
'exec_change_autoresponder_sieve' => 'exec_change_autoresponder_sieve',
'change_forward_sieve' => 'change_forward_sieve',
'exec_change_forward_sieve' => 'exec_change_forward_sieve'
);
my %no_header_actions = ('download_mysqlbackup' => '1',
'download_file' => '1');
## als erstes gucken, ob er einen Sprachcookie hat, wenn nicht, dann eines setzen
unless($lang_cookie){
logline("info","Neues Sprachcookie.");
$new_lang_cookie = cookie(-name => 'LANG', -expires => '+12M', -value => 'deu');
$lang = 'deu';
}
# hat schon ein Cookie, gucken ob auch verwendbare Sprache drin ist und ob Sprache geändert werden soll
# Cookies werden von Browser akzeptiert, ansonsten hätte er ja kein vorhandenes ;-)
else{
# Sprache soll geändert werden
# defined und exists, um "Use of uninitialized value" in Log zu verhindern
if(defined $lang_new && exists $available_lang{$lang_new}){
logline("info","Neue Sprache = $lang_new.");
$new_lang_cookie = cookie(-name => 'LANG', -expires => '+12M', -value => $available_lang{$lang_new});
$lang = $lang_new;
}
# ist Sprache in Cookie wirklich anwendbar? Wenn ja dann vorhandenes Cookie weiterverwenden
elsif(exists $available_lang{$lang_cookie}){
logline("info","Vorhandenes Sprachcookie OK = $lang_cookie.");
$lang = $lang_cookie;
}
# wenn nicht, dann Default-Sprache de setzen
else{
logline("warning","Sprachcookie UNGÜLTIG = $lang_cookie.");
$new_lang_cookie = cookie(-name => 'LANG', -expires => '+12M', -value => 'deu');
$lang = 'deu';
}
}
logline("info","\$input{'action'} = " . $input{'action'});
if($session_id && $input{'action'} ne 'exec_login'){
#Falls mit gültiger Session auf Startseite( z.B. Logo) geklickt wird, dann gibt es kein $input{'action'}
#in diesem Fall die Hauptseite anzeigen
$input{'action'} = 'start' if $input{'action'} eq '';
# cookie ziehen
# wenn session_check einen Rückgabewert hat, dann ist etwas faul im Staate Dänemark.
# Daher Cookie löschen und Loginseite anzeigen. Cookie wird gelöscht, indem es mit
# expiredate in der Vergangenheit neu gesetzt wird. Cookie wird dann vom Browser
# automatisch gelöscht.
CGI::Session->name("LOGIN");
#$session = CGI::Session->new("driver:file", $session_id, {Directory=>'/tmp'});
$session = CGI::Session->load("driver:file", $session_id, {Directory=>'/tmp'});
#$session = CGI::Session->load();
my $remote_ip = $session->remote_addr();
my $id = $session->id();
logline("debug","Remote ip=$remote_ip id=$id.");
if($session->param('auth_domains')){
logline("warning","Zugriff auf easytecc mit session aus usertool");
$input{'action'} = 'login';
$session->delete();
}
if ($session->is_expired){
logline("notice","Session abgelaufen");
$input{'action'} = 'login';
$session->delete();
}
if ($session->is_empty){
logline("error","Session konnte nicht geladen werden");
$input{'action'} = 'login';
}
}
elsif($input{'action'} eq 'exec_login'){
my $remote_ip = $cgi->remote_addr();
logline("notice","Loginversuch von $remote_ip");
#nix
}
else{
my $remote_ip = $cgi->remote_addr();
logline("warning","Kein Session-Cookie gefunden für $remote_ip");
$input{'action'} = 'login';
}
# bei Logout Session von Server löschen. Cookie von Browser löschen schenken wir uns
if(exists $input{'action'} && $input{'action'} eq 'logout'){
logline("debug","Logout");
$session->delete();
$session->flush();
$session = undef;
#print header( -type=>'text/html',
# -charset=>'utf-8',
# -cookie=>cookie(-name => 'LOGIN', -expires => '-1d', -value => '')
#);
}
### Mario: i am looking for a future-way for enabling/disabling wanted/unwanted features
### with two config files
### default config file: easytecc.default.conf (which will be overwritten on update)
### custom config file: easytecc.custom.conf (which does not exist in our source code,
### therefore will not overwrite custom configuration from our
### customers)
### Decisive for this decision are recurring problems such as
### "fjuers: Display passwords (DSGVO) unwanted",
### "dgoels: Autoresponder without umlauts unwanted",
### "dgoels: unfiltered forwarding unwanted".
### pico -w /usr/local/etc/easytecc/easytecc.custom.conf
# ShowMailuserPasswords=NO
# ShowASCIIAutoresponder=NO
if ($fb) {
my $easytecc_default_conf = '/usr/local/www/apache24/cgi-bin/easytecc4/config/easytecc.default.conf';
} else {
my $easytecc_default_conf = '/home/httpd/cgi-bin/easytecc4/config/easytecc.default.conf';
}
my $easytecc_custom_conf = '/usr/local/etc/easytecc/easytecc.custom.conf';
our %easytecc_custom_conf_entries;
if (-e $easytecc_custom_conf) {
#my $username = getpwuid( $< );
#my $fileowner = getpwuid((stat($easytecc_custom_conf))[4]);
#if ($username ne $fileowner) {
# logline("error","file $easytecc_custom_conf belongs to $fileowner, but owner should be $username.");
#}
open(my $CUSTOMCONF, "<", "$easytecc_custom_conf") or die "Can't open < $easytecc_custom_conf: $!";
if (length($easytecc_custom_conf)) {
logline("info", "length(file $easytecc_custom_conf) true");
while (my $line = <$CUSTOMCONF>) {
chomp($line);
my ($custom_conf_key, $custom_conf_value) = split /=/, $line;
$easytecc_custom_conf_entries{$custom_conf_key} = $custom_conf_value;
logline("info", "\$easytec_custom_conf: $custom_conf_key= ###$custom_conf_value###");
}
}
close($CUSTOMCONF) && logline("info","closed ") || logline("error","close failed: $!");
} else {
logline("error", "file $easytecc_custom_conf does not exist.");
}
# new vhost logic. well, logic is the wrong word, actually.
if(exists $input{'action'} && $input{'action'} eq 'exec_new_vhost'){
if(!$input{'ftp'}){
$input{'ftpuser'} = '';
$input{'ftppass'} = '';
$input{'ftppass'} = '';
$input{'ftpquota'} = '';
$input{'suexec'} = '';
$input{'ssh'} = '';
}
if(!$input{'mysql_db'}){
$input{'db'} = '';
$input{'dbuser'} = '';
$input{'dbpass'} = '';
}
}
# disallow add new adminusers via description
# should be empty if adminuser edits adminuser >> force reading from existing passwd entry
# if some fake action is taken, reset it to FTP
if($session
&& $session->param('user') ne 'admin'
&& exists $input{'action'}
&& $input{'action'} =~ m/(exec_new_ftpuser|exec_change_ftpuser)/
&& length($input{'gecos'})
&& $input{'gecos'} =~ m/^CUST/
){
$input{'gecos'} = 'FTP';
}
# workaround for hardcoded default_home...
if(exists $input{'action'} && $input{'action'} =~ m/(exec_new_ftpuser|exec_new_adminuser)/){
if(!length($input{'home'}) && length($input{'default_home'}) > 0){
$input{'home'} = $input{'default_home'};
$input{'home'} =~ s/\/benutzer$/\/$input{'ftpuser'}/;
}
}
if(exists $input{'action'} && $input{'action'} eq 'change_user' && length($input{'user_new'}) && $session->param('is_admin_session') eq '1'){
$session->param('user',$input{'user_new'});
$session->flush();
if($input{'user_new'} eq 'admin'){
$input{'action'} = 'show_adminuser';
} else {
$input{'action'} = 'start';
}
}
# workaround for cert stuff
if(exists $input{'action'} && $input{'action'} =~ m/exec_(add|change)_ssl_vhost/){
if(length($input{'letsencrypt'}) && $input{'letsencrypt'}){
}
else {
my $prefix;
if($fb){
$prefix = '/etc/apache24/';
}
else {
$prefix = '/etc/httpd/conf/';
}
if(length($input{'csr'}) && $input{'csr'}){
my $csr_dir = $prefix . 'ssl.csr/';
if(! -d $csr_dir){
if($fb){
system("/usr/iports/bin/sudo /usr/sbin/webmkdir -p $csr_dir");
}
else {
system("/usr/sbin/admmkdir -p $csr_dir");
}
}
$input{'csr_file'} = $csr_dir . $input{'domain'} . '.cert.csr';
my $key_dir = $prefix . 'ssl.key/';
if(! -d $key_dir){
if($fb){
system("/usr/iports/bin/sudo /usr/sbin/webmkdir -p $key_dir");
}
else {
system("/usr/sbin/admmkdir -p $key_dir");
}
}
$input{'key_file'} = $key_dir . $input{'domain'} . '.cert.key';
if(length($input{'csr_country'})){
$input{'csr_country'} = uc $input{'csr_country'};
}
}
else {
my $cert_dir = $prefix . 'ssl.crt/';
my $key_dir = $prefix . 'ssl.key/';
my $chain_dir = $prefix . 'ssl.crt/';
if(
length($input{'cert'}) && $input{'cert'} =~ m/[\r\n]/ ||
length($input{'cert_file'})
){
if(! -d $cert_dir){
if($fb){
system("/usr/iports/bin/sudo /usr/sbin/webmkdir -p $cert_dir");
}
else {
system("/usr/sbin/admmkdir -p $cert_dir");
}
}
my $cert_file = $cert_dir . $input{'domain'} . '.cert.crt';
if(open(my $fh, '>', $cert_file)){
binmode($fh);
if(length($input{'cert_file'})){
my $infh = $cgi->upload('cert_file');
#logline("debug","infh is:" . Data::Dumper->Dump([$infh]));
while(read($infh, my $data, 1024)) {
print $fh $data;
}
close $infh;
}
else {
print $fh $input{'cert'};
}
close $fh;
}
$input{'cert'} = $cert_file;
}
if(
length($input{'key'}) && $input{'key'} =~ m/[\r\n]/ ||
length($input{'key_file'})
){
if(! -d $key_dir){
if($fb){
system("/usr/iports/bin/sudo /usr/sbin/webmkdir -p $key_dir");
}
else {
system("/usr/sbin/admmkdir -p $key_dir");
}
}
my $key_file = $key_dir . $input{'domain'} . '.cert.key';
if(open(my $fh, '>', $key_file)){
binmode($fh);
if(length($input{'key_file'})){
my $infh = $cgi->upload('key_file');
while(read($infh, my $data, 1024)) {
print $fh $data;
}
close $infh;
}
else {
print $fh $input{'key'};
}
close $fh;
}
$input{'key'} = $key_file;
}
if(
length($input{'chain'}) && $input{'chain'} =~ m/[\r\n]/ ||
length($input{'chain_file'})
){
if(! -d $chain_dir){
if($fb){
system("/usr/iports/bin/sudo /usr/sbin/webmkdir -p $chain_dir");
}
else {
system("/usr/sbin/admmkdir -p $chain_dir");
}
}
my $chain_file = $chain_dir . $input{'domain'} . '.chain.crt';
if(open(my $fh, '>', $chain_file)){
binmode($fh);
if(length($input{'chain_file'})){
my $infh = $cgi->upload('chain_file');
while(read($infh, my $data, 1024)) {
print $fh $data;
}
close $infh;
}
else {
print $fh $input{'chain'};
}
close $fh;
}
$input{'chain'} = $chain_file;
}
}
}
}
#fix idn
# erschreckend, einfach nur erschreckend
if(exists $input{'special_spam_user_domain'}){
if($input{'special_spam_user_domain'} =~ m/@/){
$input{'special_spam_user_domain'} = email_to_ascii($input{'special_spam_user_domain'});
} else {
$input{'special_spam_user_domain'} = ascii_domain($input{'special_spam_user_domain'});
}
}
if(exists $input{'domain'}){
$input{'domain'} = ascii_domain($input{'domain'});
}
#foreach(keys(%ENV)) {
# logline("debug","env: " . $_ . $ENV{$_} . "\n");
#}
# mailuser hack map actions forward before validation
# reverse mapping below or in called functions
if($session && $session->param('is_mailuser')){
if($input{'action'} eq 'mailuser_interface'){
if($input{'active_tab'} eq '_password'){
# 2fa part
if(defined($input{'2fa'})){
$input{'action'} = "mailuser_interface";
} else {
$input{'action'} = 'exec_change_popuser';
$input{'old_user1'} = $input{'user1'} = $session->param('user');
$input{'old_pass1'} = '';
# quota
my $mailquota = {};
if (easytecc3::extern_mx() || $fb) {
$mailpasswd = easytecc3::get_mailpasswd();
my %passwd = %{$mailpasswd->file_parsed_hash()};
($mailquota, undef, undef, undef) = easytecc3::getquota_mail(\%passwd);
}
else{
($mailquota, undef, undef, undef) = easytecc3::getquota_ftp();
}
$input{'old_quota1'} = $input{'quota1'} = $mailquota->{$session->param('user')}{'quota'} / 1024;
$input{'domain'} = $session->param('user');
$input{'domain'} =~ s/^[^\@]+\@//;
$input{'domain'} = 'www.' . $input{'domain'};
logline("debug","is_mailuser=1, setting action=exec_change_popuser from tab _password");
}
}
elsif($input{'active_tab'} eq '_mailbox'){
$input{'action'} = 'confirm_expunge_mailbox';
$input{'mailuser'} = $session->param('user');
logline("debug","is_mailuser=1, setting action=confirm_expunge_mailbox from tab _mailbox");
}
elsif($input{'active_tab'} eq '_spamfilter'){
$input{'special_spam_user_domain'} = $session->param('user');
if(-f "/home/" . $session->param('user') . "/.spamproc"){
$input{'action'} = 'exec_change_special_spamfilter';
} else {
$input{'action'} = 'exec_new_special_spamfilter';
}
}
elsif($input{'active_tab'} eq '_forward'){
$input{'action'} = "mailuser_interface";
}
elsif($input{'active_tab'} eq '_autoresponder'){
$input{'action'} = "mailuser_interface";
}
}
elsif($input{'action'} eq 'exec_expunge_mailbox'){
logline("debug","is_mailuser=1, leaving action=exec_expunge_mailbox");
}
else {
$input{'action'} = 'mailuser_interface';
logline("debug","is_mailuser=1, setting action=mailuser_interface");
}
}
if(exists($input{'action'}) && exists($actions{$input{'action'}})){
logline("debug","Going to validate input data if any.");
logline("debug","input is:" . Dumper(%input));
$action = $actions{$input{'action'}};
$results = validate_input(\%input, \$session);
$validation_result = easytecc3::result_debug($results) if ref($results);
logline("error","validation_result = $validation_result") if $validation_result; #TODO JIMMY: das ist ein fucking hash - schön machen für log
}
# erfolgloser Loginversuch
if($input{'action'} eq 'exec_login' && $validation_result){
logline("debug","exec_login + validation_result");
$action = 'login';
print header( -type=>'text/html',
-charset=>'utf-8',
'-X-easytecc-login'=>'failed') unless $new_lang_cookie;
print header( -type=>'text/html',
-charset=>'utf-8',
-cookie=>$new_lang_cookie,
'-X-easytecc-login'=>'failed') if $new_lang_cookie;
}
# wenn login erfolgreich dann Cookie setzen
elsif($input{'action'} eq 'exec_login' && ! $validation_result){
# validator.pm guckt nur, ob user mit korrektem Passwort angemeldet.
# usertool und easytecc3 teilen sich validator, daher hier gucken, ob username wirklich admin
# da sich sonst endkunde mit normalem ftpuser in easytecc einloggen könnte
# user logic
#if($input{'user'} ne 'admin'){
# logline("warning","Zugriff auf easytecc nicht mit user admin.");
# $action = 'login';
# print header( -type=>'text/html',
# -charset=>'utf-8') unless $new_lang_cookie;
# print header( -type=>'text/html',
# -charset=>'utf-8',
# -cookie=>$new_lang_cookie) if $new_lang_cookie;
#}
#else{
$session = CGI::Session->new("driver:file", undef, {Directory=>'/tmp'});
# bricht autonistaller
#my $login_cookie = new CGI::Cookie(-name=>'LOGIN', -value=>easytecc3::encrypt("",$session->id), -expires => "12h");
$session->name('LOGIN');
$session->expire("12h");
print $session->header( -type=>'text/html',
-charset=>'utf-8',
'-X-easytecc-login'=>'ok') unless $new_lang_cookie;
print $session->header( -type=>'text/html',
-charset=>'utf-8',
-cookie=>$new_lang_cookie,
'-X-easytecc-login'=>'ok') if $new_lang_cookie;
# bricht autoinstaller
#if($new_lang_cookie){
# print $cgi->header( -type=>'text/html', -charset=>'utf-8', cookie=>[$login_cookie,$new_lang_cookie]);
#} else {
# print $cgi->header( -type=>'text/html', -charset=>'utf-8', cookie=>$login_cookie);
#}
$session->param('user', $input{'login_user'});
if($input{'login_user'} eq 'admin'){
$session->param('is_admin_session', '1');
}
if(-e '/usr/local/etc/easytecc/mailuser/' . $input{'login_user'}){
$session->param('is_mailuser', '1');
$action = 'mailuser_interface';
logline("debug","setting is_mailuser=1 action=mailuser_interface");
} else {
$action = 'start';
}
if(exists($input{'display_server_name'})){
$display_server_name = $input{'display_server_name'};
$session->param(-name=>'display_server_name',-value=>$display_server_name);
logline("debug","display_server_name from param:" . $display_server_name);
}
$session->flush();
logline("notice","Login erfolgreich.");
#}
}
# Funktionen wie download_mysqlbackup liefern Download direkt mit anderem http-Header aus
elsif(defined $no_header_actions{$action}){
#nix
logline("debug","\$no_header_actions{\$action} = " . $no_header_actions{$action});
}
else{
logline("debug","Common header printed.");
print header( -type=>'text/html',
-charset=>'utf-8') unless $new_lang_cookie;
print header( -type=>'text/html',
-charset=>'utf-8',
-cookie=>$new_lang_cookie) if $new_lang_cookie;
}
# workaround for easytecc iframe in domains
my $display_server_name = undef;
if($session){
$display_server_name = $session->param('display_server_name');
logline("debug","display_server_name from session:" . $display_server_name);
}
if(!$display_server_name){
$display_server_name = $ENV{'HTTP_X_FORWARDED_HOST'};
}
if(!$display_server_name){
$display_server_name = $ENV{'SERVER_NAME'};
}
$display_server_name =~ s/^www\.//;
# special layout
# search user,domain,role
my $template_user = '';
my $template_domain = $display_server_name;
my $template_role = 'CUSTOMER';
if($session){
$template_user = $session->param('user');
if($session->param('is_mailuser')){
$template_role = 'MAILUSER';
}
elsif($template_user eq 'admin'){
$template_role = 'ADMIN';
}
}
my $template_base = "$easytecc_prefix/html-templates";
if(length($template_user) && -d "$template_base/$template_user"){
HTML::Template->config(path => "$template_base/$template_user");
logline("debug","added $template_base/$template_user to template search path");
}
if(-d "$template_base/$template_domain"){
HTML::Template->config(path => "$template_base/$template_domain");
logline("debug","added $template_base/$template_domain to template search path");
}
if(-d "$template_base/$template_role"){
HTML::Template->config(path => "$template_base/$template_role");
logline("debug","added $template_base/$template_role to template search path");
}
HTML::Template->config(path => "$template_base");
HTML::Template->config(die_on_bad_params => 0);
my $nav_sidebar = HTML::Template->new(filename => 'nav_sidebar.html');
$nav_sidebar->param('FB' => $fb);
our $header = HTML::Template->new(filename => 'header.html');
$header->param('FB' => $fb);
$header->param('lang' => $lang);
$header->param('selected_lang_' . $lang => 'selected');
$header->param('lang_select' => \@lang_array);
my $whoami = '';
# decide about left menue
if($session && $session->param('user')){
if($session->param('user') eq 'admin'){
$header->param('is_admin' => '1');
$nav_sidebar->param('is_admin' => '1');
$header->param('show_vhosts' => '1');
$nav_sidebar->param('show_vhosts' => '1');
$session->param('show_vhosts','1');
$header->param('show_email' => '1');
$nav_sidebar->param('show_email' => '1');
$session->param('show_email','1');
$header->param('show_ftp' => '1');
$nav_sidebar->param('show_ftp' => '1');
$session->param('show_ftp','1');
$header->param('show_quota' => '1');
$nav_sidebar->param('show_quota' => '1');
$session->param('show_quota','1');
$header->param('show_spam' => '1');
$nav_sidebar->param('show_spam' => '1');
$session->param('show_spam','1');
$header->param('show_fileman' => '1');
$nav_sidebar->param('show_fileman' => '1');
$session->param('show_fileman','1');
$header->param('show_logs' => '1');
$nav_sidebar->param('show_logs' => '1');
$session->param('show_logs','1');
$header->param('show_db' => '1');
$nav_sidebar->param('show_db' => '1');
$session->param('show_db','1');
$header->param('show_cron' => '1');
$nav_sidebar->param('show_cron' => '1');
$session->param('show_cron','1');
$header->param('show_inst' => '1');
$nav_sidebar->param('show_inst' => '1');
$session->param('show_inst','1');
if(-d '/usr/local/etc/easytecc/shell2ban'){
$header->param('show_firewall' => '1');
$nav_sidebar->param('show_firewall' => '1');
$session->param('show_firewall','1');
}
} elsif($session->param('is_mailuser')){
my $mailuser = $session->param('user');
my @addresses;
my @aliases;
my $virtmaps_lhs;
my $virtmaps_rhs;
if($fb){
$virtmaps_rhs = `sed '/procmail -a $mailuser/!d ; s/:.*//' /etc/mail/aliases 2>/dev/null`;
chomp($virtmaps_rhs);
} else {
$virtmaps_rhs = `sed 's/:.*[\t,]$mailuser/#MATCH#/ ; s/#MATCH#,.*/#MATCH#/ ; /#MATCH#\$/!d ; s/#MATCH#//' /etc/mail/aliases 2>/dev/null`;
chomp($virtmaps_rhs);
if(!length($virtmaps_rhs)){
$virtmaps_rhs = $mailuser
}
}
foreach $virtmaps_rhs(split(/\n/,$virtmaps_rhs)){
$virtmaps_lhs = `grep '[^[:print:]]$virtmaps_rhs\$' /etc/mail/virtmaps 2>/dev/null | cut -f 1 2>/dev/null`;
chomp($virtmaps_lhs);
if(length($virtmaps_lhs)){
push(@addresses,split('\n',$virtmaps_lhs));
}
}
#unique
@addresses = keys %{{ map { $_ => 1 } @addresses }};
if(!@addresses){
$header->param('addresses' => 'L__Keine gültige E-Mail-Adresse__L');
} else {
$header->param('addresses' => join(', ',@addresses));
}
if(scalar(@addresses) == 1){
$session->param('mailaddress' => shift @addresses);
$session->flush();
}
#if($mailuser !~ /\@/){
#
# my $passwd = file->new({file_name => '/etc/passwd'});
# $passwd->read_file;
# my %passwd = %{$passwd->file_parsed_hash()};
#
# my $domain = $passwd{$session->param('user')}{'gecos'};
# $domain=~ s/\s.*$//;
#
# $mailuser .= '@' . $domain;
#
#}
$header->param('user' => $mailuser);
$header->param('act_mailuser_interface' => '1');
logline("debug","is_mailuser=1, setting header act_mailuser_interface=1, user=" . $session->param('user'));
} else {
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
# Mario: gecos field = "General information about the user."
my $gecos = $passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.vhost-1.email-1.ftp-2.quota.spam.fileman-1.logs-1';
}
if($gecos =~ m/\.vhost/){
$header->param('show_vhosts' => '1');
$nav_sidebar->param('show_vhosts' => '1');
$session->param('show_vhosts','1');
}
if($gecos =~ m/\.email/){
$header->param('show_email' => '1');
$nav_sidebar->param('show_email' => '1');
$session->param('show_email','1');
}
if($gecos =~ m/\.ftp/){
$header->param('show_ftp' => '1');
$nav_sidebar->param('show_ftp' => '1');
$session->param('show_ftp','1');
}
if($gecos =~ m/\.quota/){
$header->param('show_quota' => '1');
$nav_sidebar->param('show_quota' => '1');
$session->param('show_quota','1');
}
if($gecos =~ m/\.spam/){
$header->param('show_spam' => '1');
$nav_sidebar->param('show_spam' => '1');
$session->param('show_spam','1');
}
if($gecos =~ m/\.fileman/){
$header->param('show_fileman' => '1');
$nav_sidebar->param('show_fileman' => '1');
my $dir_encoded = encode_base64url($passwd{$session->param('user')}{'home'});
$nav_sidebar->param('dir_encoded' => $dir_encoded);
$session->param('show_fileman','1');
}
if($gecos =~ m/\.logs/){
$header->param('show_logs' => '1');
$nav_sidebar->param('show_logs' => '1');
$session->param('show_logs','1');
}
if($gecos =~ m/\.db/){
$header->param('show_db' => '1');
$nav_sidebar->param('show_db' => '1');
$session->param('show_db','1');
}
if($gecos =~ m/\.cron/){
$header->param('show_cron' => '1');
$nav_sidebar->param('show_cron' => '1');
$session->param('show_cron','1');
}
if($gecos =~ m/\.inst/){
$header->param('show_inst' => '1');
$nav_sidebar->param('show_inst' => '1');
$session->param('show_inst','1');
}
$whoami = $session->param('user') . '@';
}
if($session && $session->param('is_admin_session') eq '1'){
$header->param('is_admin_session' => '1');
}
$header->param('is_logged_in' => '1');
}
# mailuser hack map actions reverse after validation
if($session && $session->param('is_mailuser')){
if($validation_result){
if($input{'action'} eq 'exec_change_popuser'){
$action = $input{'action'} = 'mailuser_interface';
$input{'active_tab'} = '_password';
logline("debug","is_mailuser=1, error from validation, setting action=mailuser_interface from exec_change_popuser, tab=_password");
}
elsif($input{'action'} eq 'exec_new_special_spamfilter'){
$action = $input{'action'} = 'mailuser_interface';
$input{'active_tab'} = '_spamfilter';
logline("debug","is_mailuser=1, error from validation, setting action=mailuser_interface from exec_new_special_spamfilter, tab=_spamfilter");
}
}
}
if($validation_result){
if($input{'action'} eq 'exec_new_sendmail_cw' || $input{'action'} eq 'exec_new_quotamessage' || $input{'action'} eq 'exec_new_mailserver_cert'){
$action = 'show_email';
}
elsif($input{'action'} eq 'exec_new_mysqluser'){
$action = 'show_dbbackup';
}
$action =~ s/^exec_//;
}
my $baseaction = $action;
$baseaction =~ s/^exec_//;
if($baseaction =~ m/special_spamfilter/ && !$session->param('is_mailuser')){
$baseaction = 'change_spamfilter';
} elsif($baseaction =~ m/single_edit_email/){
$baseaction = 'show_email';
}
$header->param('act_' . $baseaction => 'class="active hidden-sm"');
$header->param('server_name' => $whoami . $display_server_name);
my $footer = HTML::Template->new(filename => 'footer.html');
$footer->param('is_admin' => $fb);
$footer->param('easytecc_version' => $easytecc_version);
$nav_sidebar->param('act_' . $baseaction => 'class="active"');
# no sidebar with installer and mailusers
if (($action =~ /new_install/ && !$input{'error'}) || ($session && $session->param('is_mailuser'))) {
# $footer->param('nav_sidebar' => $nav_sidebar->output);
} else {
$header->param('container' => '
<div class="col-sm-9 col-sm-push-3 col-lg-10 col-lg-push-2 main-content">
');
$footer->param('nav_sidebar' => $nav_sidebar->output);
$footer->param('container_end' => '</div>');
}
#navigation(\$header);
# workaround for mailuser_interface
#if($session && $session->param('is_mailuser')){
# if($action ne 'confirm_expunge_mailbox'){
# $action = $input{'action'} = 'mailuser_interface';
# }
#}
#if(!exists($input{'action'}) || $input{'action'} !~ /(mailuser_interface|info_mailuser|exec_change_popuser|confirm_expunge_mailbox|exec_expunge_mailbox|exec_change_special_spamfilter)/){
logline("info","action = $action");
# jump to action code
$html = &$action;
## mailuser hack, reverse mapping after exec
#if($session && $session->param('is_mailuser')){
#
# if($input{'action'} eq 'exec_change_popuser'){
#
# $action = $input{'action'} = 'mailuser_interface';
# $input{'active_tab'} = '_password';
# logline("debug","is_mailuser=1 after exec setting action=mailuser_interface from exec_change_popuser, tab=_password");
#
# }
#
#}
$$html->param('header' => $header->output);
$$html->param('footer' => $footer->output);
# wenn Formular fehlerhaft ausgefüllt erneut anzeigen und Werte wieder einfgen + CSS-Fehlerklasse als Markierung
# wenn also bei exec_new_ftpuser Fehler aufgetreten, dann wird $action auf new_ftpuser gesetzt und Fomrular wird mit Fehlermeldungen
# und bereits eingegebenen Formulardaten erneut angezeigt
if($validation_result) {
logline("error","Calling html_error().");
html_error();
}
logline("debug","Calling html_out().");
html_out();
logline("alert","<<< Exiting index.pl - should never happen to reach this....");
exit(0);
#
# _
# ___ _ _| |_ ___
# / __| | | | '_ \/ __|
# \__ \ |_| | |_) \__ \
# |___/\__,_|_.__/|___/
#
#
#
sub html_out {
# my $html_ref = shift;
# $html = $html_ref if ref($html_ref);
# ausgewhälte Sprache anzeigen. Im html-Output sind sämtliche umzuwandelnde Strings markiert, so daß
# mit Hilfe von CSV Suchen und Ersetzen erfolgen kann. Z.B. ich bin doof steht in en.csv
# "ich bin doof","I am silly"
# in html-Output ist deutsch, d.h. wenn Ausgabe auch auf deutsch erfolgen soll, dann braucht keine csv geladen zu werden, sondern nur
# die entfernt werden.
$$html->param('FB' => $fb);
$$html->param('easytecc_version' => $easytecc_version);
$$html->param('show_progress' => 1) if $input{'show_progress'};
$success_text = $input{'success_text'} ? decode_base64url($input{'success_text'}) : $success_text;
$success_text2 = $input{'success_text2'} ? decode_base64url($input{'success_text2'}) : $success_text2;
$success_text3 = $input{'success_text3'} ? decode_base64url($input{'success_text3'}) : $success_text3;
$success_text4 = $input{'success_text4'} ? decode_base64url($input{'success_text4'}) : $success_text4;
$success_text5 = $input{'success_text5'} ? decode_base64url($input{'success_text5'}) : $success_text5;
my $success_template = '';
my $html_with_lang_prefix = '';
if ($success_text) {
$success_template = HTML::Template->new(filename => 'success_div.html');
$success_template->param('success_text' => $success_text);
$success_template->param('success_text2' => $success_text2);
$success_template->param('success_text3' => $success_text3);
$success_template->param('success_text4' => $success_text4);
$success_template->param('success_text5' => $success_text5);
if (length($input{'active_tab'}) && $input{'active_tab'} != '1') {
$$html->param('success_tab'.$input{'active_tab'} => $success_template->output);
}
else{
$$html->param('success' => $success_template->output);
}
}
logline("debug","action = $input{'action'}");
if(exists $ajax_actions{$input{'action'}} && $json_output{'success_message'}){
$html_with_lang_prefix = $success_template->output;
}
else{
$html_with_lang_prefix = $$html->output;
}
logline("debug","success_text = $success_text");
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
logline("debug","lang:$lang html=$html_with_lang_prefix") if $debug_content;
# \n = LF
# \r = CR
# \f = FF
#$var =~ s/\n|\r//g;
#UNIX has '\n' end of line;
#Windows family has '\r\n' instead;
#Mac OS has '\r';
# convert all to \n
#windows, nur \r entfernen
if($html_with_lang_prefix =~ /\r\n/){
$html_with_lang_prefix =~ s/\r//g;
}
#appel, \r gegen \n ersetzen
elsif($html_with_lang_prefix =~ /\r/){
$html_with_lang_prefix =~ s/\r/\n/g;
}
#$html_with_lang_prefix = encode("utf-8", $html_with_lang_prefix);
#if(-e "$lang_basedir/$lang.csv"){
if( -e ("$lang_basedir/$lang.csv")){
logline("debug","Ausgabe: $lang.csv");
my $lang_file = `cat $lang_basedir/$lang.csv`;
#$lang_file = encode("utf-8", $lang_file);
#windows
if($lang_file =~ /\r\n/){
$lang_file =~ s/\r//g;
}
#appel
elsif($lang_file =~ /\r/){
$lang_file =~ s/\r/\n/g;
}
my @lang_array = split /\n\n/, $lang_file;
foreach(@lang_array){
my($lh,$rh) = split /",[\n]{0,1}"/, $_;
$lh =~ s/^"//;
$rh =~ s/"$//;
$lang_dict{$lh} = $rh;
#logline("warning","lh=$lh\trh=$rh");
}
$html_with_lang_prefix =~ s/L__(.*?)__L/{®ex_lang($1)}/gcse;
}
else{
logline("warning","No $lang*.csv file");
}
#on critical errors sub error() ist called and sets $json_output{'critical_error'} = 1
#without executing action and showing html again. Show just the error message, otherwise user would click again
#which could end in a mess from multiple form submission
if(exists $ajax_actions{$input{'action'}} || $json_output{'critical_error'} == '1'){
$json_output{'ajax_html'} = $html_with_lang_prefix;
if ($validation_result) {
$json_output{'error'} = '1';
}
logline("debug","result is json");
print to_json(\%json_output);
}
else{
#binmode(STDOUT, ":utf8");
logline("debug","result is html");
print $html_with_lang_prefix;
}
logline("debug","Flush session.");
$session->flush() if $session;
logline("debug","<<< Exiting index.pl in ".(caller(0))[3]."().");
exit(0);
}
sub regex_lang{
my $lang_value = shift;
return($lang_dict{$lang_value}) if exists $lang_dict{$lang_value};
#for easier detection of missing translation
#return('LANG NOT FOUND') if not exists $lang_dict{$lang_value};
#to show defalut .de translation if lang not found
return("L__ $lang_value __L") if not exists $lang_dict{$lang_value};
#just remove L__...__L wrapper and always use .de if lang not found
#return("$lang_value") if not exists $lang_dict{$lang_value};
if (exists $lang_dict{$lang_value}) {
logline("debug","Translation for '$lang_value' is available.");
return ( $lang_dict{$lang_value} );
} else {
logline("error","NO translation for '$lang_value' is available.");
return ("L__ $lang_value __L");
}
}
sub html_error {
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
# Fehlermeldung kann von Validator oder aus Ausführung exec_... kommen, wenn bei Ausführung von Änderung
# oder Überprüfungen, die mit dem Validator zu kompliziert wären ein Problem festgestellt wird. %error_fields
# wird von validator generiert oder wir erstellen es selbst in exec_...
my $from_sub = shift;
my $html_error = '';
if(ref($from_sub)){
logline("error","Error from sub.");
%error_fields = %$from_sub;
$action =~ s/^exec_//;
#Fehlerauflistung - html_error MUSS hier gefüllt werden, nach '&$action' sonst verloren
foreach(keys %error_fields){
logline("error","html_error field=$_ error_fields = ".$error_fields{$_});
$html_error .= qq~<li>$error_fields{$_}</li>~;
}
#um Endlosschleife zu verhindern, wenn Fehler nicht bei exec_ sondern schon für Anzeige von Formular auftritt
if (defined $error_fields{'template'}) {
$html = $error_fields{'template'};
}
else{
$html = &$action;
}
}
else{
%error_fields = %$validation_result;
logline("error","Error from validation.");
#Fehlerauflistung
foreach(keys %error_fields){
logline("error","html_error field=$_ error_fields = ".$error_fields{$_});
$html_error .= qq~<li>$error_fields{$_}</li>~;
$$html->param('error_class_' . $_ => 'has-error');
$$html->param('error_text_' . $_ => qq~<span class="help-block">~ . encode_entities($error_fields{$_}, '<>&"') . qq~</span>~);
}
}
#wenn Fehler, dann muss FB hier gesetzt werden, da in html_out() nicht mehr möglich
$$html->param('FB' => $fb);
#Formularfelder wieder ausfüllen
foreach(keys %input){
#kaputt logline("info","### keys ###\n".%input{$_});
# select-Boxen können nicht ausgefüllt werden
next if /^.*_select/;
# $input{'special'} enthält Sonderzeichen, diese nicht erneut rein
next if /^special$/;
#$$html->param($_ => $input{$_});
$$html->param($_ => encode('utf-8', $input{$_}));
$$html->param('checked_' . $_ => ' checked');
}
$html_error = qq~<ul class="form-error">$html_error</ul>~ if length($html_error);
my $error_template = HTML::Template->new(filename => 'error.html');
if ($error_fields{'non_specific'} && ! $html_error) {
$error_template->param('error_text' => qq~ ~ . $error_fields{'non_specific'});
}
elsif ($error_fields{'non_specific'} && $html_error) {
if(keys %error_fields > 1){
$error_template->param('error_text' => qq~L__Ein Fehler ist aufgetreten, bitte beachten Sie die Warnmeldungen.__L<br><br><p>~ . $error_fields{'non_specific'} . qq~</p>$html_error~);
} else {
$error_template->param('error_text' => qq~L__Ein Fehler ist aufgetreten, bitte beachten Sie die Warnmeldungen.__L<br><br><p></p>$html_error~);
}
}
elsif ($input{'action'} eq 'exec_modify_file' || $input{'action'} eq 'exec_modify_dir') {
$error_template->param('error_text' => $error_fields{'type'});
}
else{
$error_template->param('error_text' => qq~L__Ein Fehler ist aufgetreten, bitte beachten Sie die Warnmeldungen.__L $html_error~);
}
#1 is default
if (length($input{'active_tab'}) && $input{'active_tab'} != '1') {
$$html->param('error_tab'.$input{'active_tab'} => $error_template->output);
}
else{
#change_htaccess has three forms
if ($input{'action'} eq 'exec_change_htaccess' && $input{'type'} eq 'newuser') {
$$html->param('error_newuser' => $error_template->output);
}
elsif ($input{'action'} eq 'exec_change_htaccess' && $input{'type'} eq 'changepass') {
$$html->param('error_changepass' => $error_template->output);
}
else{
$$html->param('error' => $error_template->output);
}
}
# wenn Fehler aus sub kommt
if(ref($from_sub)){
logline("error","Error from sub 2.");
#my $header = HTML::Template->new(filename => 'header.html');
#my $footer = HTML::Template->new(filename => 'footer.html');
#$header->param('FB' => $fb);
#$footer->param('FB' => $fb);
$$html->param('header' => $header->output);
$$html->param('footer' => $footer->output);
#$header->param('act_' . $baseaction => 'class="active hidden-sm"');
# wenn z.B. in exec_change_popuser ein fehler, dann wird html mit Templatevariablen error_class im html-quelltext
# zurckgeliefert. Darum diesen Output erneut als html-Template einlesen, um Variable nachtrglich setzen zu können
# Ansonsten würde im hmtl was an Browser geschickt wird z.B. <TMPL_VAR NAME=quota1> stehen
my $html_tmp = $$html->output;
#logline("debug","$html_tmp");
my $html_tmp2 = HTML::Template->new(scalarref => \$html_tmp);
foreach(keys %error_fields){
$html_error .= qq~<li>$_: $error_fields{$_}</li>~;
#$html_tmp2->param('error_class_' . $_ => qq~class="form-error-label"~);
$html_tmp2->param('error_class_' . $_ => "has-error");
}
#print $html->output;
$html = \$html_tmp2;
## wenn z.B. in exec_change_popuser ein fehler, dann wird html mit Templatevariablen error_class im html-quelltext
## zurckgeliefert. Darum diesen Output erneut als html-Template einlesen, um Variable nachtrglich setzen zu können
## Ansonsten würde im hmtl was an Browser geschickt wird z.B. <TMPL_VAR NAME=quota1> stehen
##my $html_tmp = $$html->output;
##my $html_tmp2 = HTML::Template->new(scalarref => \$html_tmp);
#
#foreach(keys %error_fields){
# $html_error .= qq~<li>$_: $error_fields{$_}</li>~;
# #$html_tmp2->param('error_class_' . $_ => qq~class="form-error-label"~);
# $$html->param('error_class_' . $_ => "has-error");
#}
##print $html->output;
##$html = \$html_tmp2;
logline("debug","<<< Leaving ".(caller(0))[3]."().");
html_out();
}
# $html ist die globale Variable die HTML::Templateobjekt entählt. An html_out muss Referenz auf dieses Objekt übergeben werden und
# vorher müssen Templatevariablen ersetzt werden.
# also erstmal html-Ausgabe die Templatevariablen enthlt in Variable $html_tmp rein
my $html_tmp = $$html->output;
# in zweite Variable kommt Referenz auf html-Ausgabevariable, so da auf Templatevariablen zugegriffen werden kann
my $html_tmp2 = HTML::Template->new(scalarref => \$html_tmp);
foreach(keys %error_fields){
# z.B. tritt bei exec_change_pop3user ein Fehler auf. Es wird wieder change_pop3user aufgerufen
# und value von ftpquota wird ber Funktion value() + error_class
#
# return(qq~"$input{$input}" <TMPL_VAR NAME=error_class_$input> ~);
#
# zurckgegeben. Nun befindet sich im htmlquelltext TMPL_VAR was sonst angezeigt werden würde. Darum wird die Ausgabe
# nochmal als htmltemplate eingelesen (als scalarref), so da auf TMPL_VAR zugegriffen werden kann
$html_tmp2->param('error_class_' . $_ => qq~class="form-error-label"~);
}
#$html_tmp2 ist nun html-Ausgabe die Fehlermeldungen und Fehlerklassen enthlt. Weiter an html_out wo abhängig von der Spache
#die Ausgabe erfolgt
$html = \$html_tmp2;
##my $html_tmp = $$html->output;
## in zweite Variable kommt Referenz auf html-Ausgabevariable, so da auf Templatevariablen zugegriffen werden kann
##my $html_tmp2 = HTML::Template->new(scalarref => \$html_tmp);
#foreach(keys %error_fields){
# # z.B. tritt bei exec_change_pop3user ein Fehler auf. Es wird wieder change_pop3user aufgerufen
# # und value von ftpquota wird ber Funktion value() + error_class
# #
# # return(qq~"$input{$input}" <TMPL_VAR NAME=error_class_$input> ~);
# #
# # zurckgegeben. Nun befindet sich im htmlquelltext TMPL_VAR was sonst angezeigt werden würde. Darum wird die Ausgabe
# # nochmal als htmltemplate eingelesen (als scalarref), so da auf TMPL_VAR zugegriffen werden kann
# $$html->param('error_class_' . $_ => qq~has-error~);
#}
##$html_tmp2 ist nun html-Ausgabe die Fehlermeldungen und Fehlerklassen enthlt. Weiter an html_out wo abhängig von der Spache
##die Ausgabe erfolgt
##$html = \$html_tmp2;
logline("debug","<<< Leaving ".(caller(0))[3]."().");
html_out();
}
sub navigation{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template_ref = shift;
my $template = $$template_ref;
opendir(DIR, "$awstats_conf_prefix");
my @allfiles = grep !/^\.\.?$/, readdir DIR;
closedir DIR;
my $awstats = scalar(@allfiles);
#wenn Statistik noch auf Webalizer läuft, dann Migration auf awstats anbieten, also wenn awstats-conf-dir leer und kein cronjob vorhanden
if($awstats == '0' && ! `grep awstats_updateall /home/web/cronfile` && `grep webalizer /home/web/cronfile`){
$mainnav->param('awstats_migration' => qq~<br /><a href="/cgi-bin/easytecc3/index.pl?action=awstats_migration"><b>L__Webalizer-AWStats-Migration__L</b></a>~);
}
#twig-roundcube-migration: Button nur anzeigen, wenn /home/httpd/docs/twig existiert und nicht Rechte 700 hat
if(! -e '/usr/local/etc/easytecc/twig-migration-done'){
logline("debug","Still twig, offering roundcube.");
$mainnav->param('twig_migration' => qq~<br /><a href="/cgi-bin/easytecc3/index.pl?action=roundcube_migration"><b>L__Twig-Roundcube-Migration__L</b></a>~);
$mainnav->param('webmail' => '/twig');
}
else{
$mainnav->param('webmail' => '/webmail');
}
$template->param(mainnav => $mainnav->output);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
}
sub ajax_error_handler{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
# $error_hash_ref ist referenz auf Hash, der die Formularfelder mit Fehlermeldungen enthält
# mailvalidator liefert Ergebnis und das wird in easytecc3::result_debug aufbereitet
my $error_hash_ref = shift;
my %error_hash = %$error_hash_ref;
my $error_text = '';
my %callback = ('error' => \%error_hash);
#foreach(keys %error_hash){
# $error_text .= "$_:" . $error_hash{$_} . '<br>';
#}
$error_text = to_json(\%callback);
logline("error","ajax_error_handler error_text: $error_text.");
my $template = HTML::Template->new( scalarref => \$error_text,
option => 'value'
);
$html = \$template;
print header( -type=>'text/html',
-charset=>'utf-8');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(html_out()); # Jimmy: Kann das gehen? html_out() schmeisst ein exit(0) im gleichen prozess... html_out() sollte reichen
}
sub login{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'login.html');
$template->param('server_name' => $display_server_name);
my $cmd = '/bin/ls -l ' . $droot_prefix . '/easytecc4/img/login-bg-*|/usr/bin/wc -l';
my $login_bg_image_count = `$cmd`;
chomp $login_bg_image_count;
$login_bg_image_count =~ s/[^0-9]//g;
$template->param('login_img_random' => int(rand($login_bg_image_count)) +1);
$template->param('selected_lang_' . $lang => 'selected');
$template->param('lang_select' => \@lang_array);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub logout{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'login.html');
$template->param('server_name' => $display_server_name);
#my $cmd = 'ls -l ' . $droot_prefix . '/easytecc/img/login-bg-*|wc -l';
#my $login_bg_image_count = `$cmd`;
#chomp $login_bg_image_count;
#$login_bg_image_count =~ s/[^0-9]//g;
#$template->param('login_img_random' => int(rand($login_bg_image_count)) +1);
#$template->param('selected_lang_' . $lang => 'selected');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl';
return login();
#return(\$template);
#return '';
}
sub start{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
# mailuser
#if($session->param('user') =~ /\@/){
# return mailuser_start();
#}
my $template = HTML::Template->new(filename => 'index.html');
my $template_dashboard_box_cloneworkx = HTML::Template->new(filename => 'dashboard_box_cloneworkx.html');
my $template_dashboard_box_domains = HTML::Template->new(filename => 'dashboard_box_domains.html');
my $template_dashboard_box_emailadresses = HTML::Template->new(filename => 'dashboard_box_emailadresses.html');
my $template_dashboard_box_filemanager = HTML::Template->new(filename => 'dashboard_box_filemanager.html');
my $template_dashboard_box_ftpuser = HTML::Template->new(filename => 'dashboard_box_ftpuser.html');
my $template_dashboard_box_clients = HTML::Template->new(filename => 'dashboard_box_clients.html');
my $template_dashboard_box_logfiles = HTML::Template->new(filename => 'dashboard_box_logfiles.html');
# my $template_dashboard_box_order_webmail = HTML::Template->new(filename => 'dashboard_box_order_webmail.html');
my $template_dashboard_installer = HTML::Template->new(filename => 'dashboard_box_installer.html');
my $template_dashboard_2fa = HTML::Template->new(filename => 'dashboard_box_2fa.html');
my $template_dashboard_box_otheractions = HTML::Template->new(filename => 'dashboard_box_otheractions.html');
my $template_dashboard_box_support = HTML::Template->new(filename => 'dashboard_box_support.html');
$show_vhosts = '';
$show_email = '';
$show_ftp = '';
$show_quota = '';
$show_spam = '';
$show_fileman = '';
$show_logs = '';
$show_db = '';
$show_cron = '';
$show_inst = '';
$show_firewall = '';
if($session->param('user') eq 'admin'){
$show_vhosts = '1';
$show_email = '1';
$show_ftp = '1';
$show_quota = '1';
$show_spam = '1';
$show_fileman = '1';
$show_logs = '1';
$show_db = '1';
$show_cron = '1';
$show_inst = '1';
$show_firewall = '1';
} else {
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my $gecos = $passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.vhost-1.email-1.ftp-2.quota.spam.fileman-1.logs-1.db-2.cron-2.inst';
}
if($gecos =~ m/\.vhost/){
$show_vhosts = '1';
}
if($gecos =~ m/\.email/){
$show_email = '1';
}
if($gecos =~ m/\.ftp/){
$show_ftp = '1';
}
if($gecos =~ m/\.quota/){
$show_quota = '1';
}
if($gecos =~ m/\.spam/){
$show_spam = '1';
}
if($gecos =~ m/\.fileman/){
$show_fileman = '1';
}
if($gecos =~ m/\.logs/){
$show_logs = '1';
}
if($gecos =~ m/\.db/){
$show_db = '1';
}
if($gecos =~ m/\.cron/){
$show_cron = '1';
}
if($gecos =~ m/\.inst/){
$show_inst = '1';
}
}
#$template->param('dashboard_box_cloneworkx' => $template_dashboard_box_cloneworkx->output);
if($show_vhosts eq '1'){
$template->param('dashboard_box_domains' => $template_dashboard_box_domains->output);
}
if($show_email eq '1'){
$template->param('dashboard_box_emailadresses' => $template_dashboard_box_emailadresses->output);
}
if($show_fileman eq '1'){
$template->param('dashboard_box_filemanager' => $template_dashboard_box_filemanager->output);
}
if($show_ftp eq '1'){
$template->param('dashboard_box_ftpuser' => $template_dashboard_box_ftpuser->output);
}
if($show_logs eq '1'){
$template->param('dashboard_box_logfiles' => $template_dashboard_box_logfiles->output);
}
# $template->param('dashboard_box_order_webmail' => $template_dashboard_box_order_webmail->output);
if($show_inst eq '1'){
$template->param('dashboard_box_installer' => $template_dashboard_installer->output);
}
#if($fb && $show_ftp eq '1' && ! -f '/usr/local/etc/easytecc/2fa/' . $session->param('user') ){
# $template_dashboard_2fa->param('user' => $session->param('user'));
# $template->param('dashboard_box_2fa' => $template_dashboard_2fa->output);
#}
# if($show_firewall eq '1'){
# $template->param('dashboard_box_firewall' => $template_dashboard_firewall->output);
# }
if($show_quota eq '1' && $show_spam eq '1' && $show_db eq '1' && $show_cron eq '1'){
$template->param('dashboard_box_otheractions' => $template_dashboard_box_otheractions->output);
}
$session->param('show_vhosts',$show_vhosts);
$session->param('show_email',$show_email);
$session->param('show_ftp',$show_ftp);
$session->param('show_quota',$show_quota);
$session->param('show_spam',$show_spam);
$session->param('show_fileman',$show_fileman);
$session->param('show_logs',$show_logs);
$session->param('show_db',$show_db);
$session->param('show_cron',$show_cron);
$session->param('show_inst',$show_inst);
if($session->param('user') eq 'admin'){
$template->param('dashboard_box_support' => $template_dashboard_box_support->output);
$template->param('dashboard_box_clients' => $template_dashboard_box_clients->output);
}
# Warninformationen:
# Serverquota < 100MB frei
# Quota von User weniger als 10%
# Logfiles für Webserver nehmen mehr als 50% von Webspeicher ein
# admin-Postfach mehr als 500MB voll
# kein cronjob zum automatischen Löschen von Logs
my $has_warning = '';
my $extern_mx = easytecc3::extern_mx();
my @serverquota = ();
my $admin_mail_used = '';
my %mailpasswd = ();
my %mailquota = ();
my ($mailquotaref, $sum_maillimit, $sum_mailuse, $mailserverlimit);
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
# Zum gucken, ob es FTP-User gibt, die passwd vom Webserver auslesen, und gucken ob es zum
# document root der Domain einen FTP-User mit passendem home-Verzeichnis gibt
logline("debug","Creating File Object \%webserver_passwd.");
my $webserver_passwd = file->new({file_name => '/etc/passwd'});
$webserver_passwd->read_file;
my %webserver_passwd = %{$webserver_passwd->file_parsed_hash()};
my %home_lookup = %{$webserver_passwd->lookup2_hash()};
my ($quotaref, $sum_ftplimit, $sum_ftpuse, $ftpserverlimit) = easytecc3::getquota_ftp();
my %quota = %$quotaref;
if ($extern_mx || $fb){
$mailpasswd = easytecc3::get_mailpasswd();
%mailpasswd = %{$mailpasswd->file_parsed_hash()};
($mailquotaref, $sum_maillimit, $sum_mailuse, $mailserverlimit) = easytecc3::getquota_mail(\%mailpasswd);
%mailquota = %$mailquotaref;
}
else{
%mailpasswd = %webserver_passwd;
%mailquota = %quota;
$sum_maillimit = $sum_ftplimit;
$sum_mailuse = $sum_ftpuse;
$mailserverlimit = $ftpserverlimit;
}
my $userregex;
my %domain_home;
my %allowed_domains;
my $admins;
foreach(keys %domains){
# filter domains
if($session->param('user') ne 'admin'){
$admins = $domains{$_}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $session->param('user') . '#';
logline("debug"," M A R I O - admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
}
logline("info","domain_home=" . $domains{$_}{'droot'});
$domain_home{$domains{$_}{'droot'}} = $domains{$_}{'domains'};
$allowed_domains{$_} = 1;
}
####################################################
############# SSL-Warning if certificate expires within 30 days
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
# Mario: Die folgenden beiden Variablen werden in der easytecc_class.pm ausgewertet.
my %config = %{$httpd_conf->config_hash()};
my $ssl_warning_text="";
foreach my $domain (sort keys %allowed_domains){
# an dieser Stelle wird die Variable $domain noch mit www.domain.tld übergeben..
if($config{'ssl_enabled'} && $domains{$domain}{'ssl'}){
logline("debug","cert:" . $domains{$domain}{'ssl_cert'} . "\n");
my $has_letsencrypt = $domains{$domain}{'special_ssl'} =~ m/letsencrypt/;
my $ssl_expire_date = "";
my $ssl_expires_within_x_days;
my ($ssl_expire_date, $ssl_expires_within_x_days) = https_cert_expire($domains{$domain}{'ssl_cert'});
if(length($ssl_expire_date)){
$domain =~ s/^www.//;
if ($ssl_expires_within_x_days < 0){
$ssl_warning_text.='L__Das SSL-Zertifikat für__L <a href="index.pl?action=show_vhosts">'.$domain.'</a> L__ist abgelaufen__L.<br />';
} elsif ($has_letsencrypt && $ssl_expires_within_x_days < 25 || $ssl_expires_within_x_days < 25){
$ssl_warning_text.='L__Das SSL-Zertifikat für__L <a href="index.pl?action=show_vhosts">'.$domain.'</a> L__ist noch gültig bis zum__L '.$ssl_expire_date.'.<br />';
}
}
}
}
unless ($ssl_warning_text eq ""){
my $template_dashboard_box_alert_quota_100MB_free = HTML::Template->new(filename => 'dashboard_box_alert.html');
$template_dashboard_box_alert_quota_100MB_free->param('box_alert_text' => qq~$ssl_warning_text~);
$template->param('dashboard_alert_quota_100MB_free' => $template_dashboard_box_alert_quota_100MB_free->output);
$has_warning = '1';
}
####################################################
############# Quotawarnung Webserver weniger als 100 MB frei
my $webserver_100MB = sprintf("%.0f", $ftpserverlimit - $sum_ftpuse);
if($webserver_100MB < 100 && $session->param('user') eq 'admin'){
$webserver_100MB = '0' if $webserver_100MB < 0;
my $template_dashboard_box_alert_quota_100MB_free = HTML::Template->new(filename => 'dashboard_box_alert.html');
$template_dashboard_box_alert_quota_100MB_free->param('box_alert_text' => qq~L__Speichergrenze von Webserver fast erreicht__L:L__Freier Speicher:__L $webserver_100MB. L__Bitte löschen Sie nicht mehr benötigte Daten. Möglich ist auch ein Speicherupgrade des Servers gemäß unserer Preisliste, das einfach per Fax bestellt werden kann. Die aktuelle Preisliste finden Sie hier__L: <a href="http://www.hostnet.de/uebersicht-server.html" target="_blank">L__Preisliste__L</a><br />~);
$template->param('dashboard_alert_quota_100MB_free' => $template_dashboard_box_alert_quota_100MB_free->output);
$has_warning = '1';
}
####################################################
############# Quotawarnung FTP-user
my @ftp_user = ();
my @user = ();
foreach my $ftpuser (sort keys %webserver_passwd){
next if $ftpuser eq 'ftp';
my $ftpquota = '';
my $ftpquota_sized = '';
my $ftpused = '';
my $quotabalken = '';
my $domain = '';
$ftpquota = $quota{$ftpuser}{'quota'};
$ftpquota_sized = easytecc3::getsize($ftpquota);
$ftpused = $quota{$ftpuser}{'use'};
#nur die User anzeigen, die weniger als 10% Quota zur Verfgung haben
my $percentval = ($ftpused/$ftpquota)*100 if $ftpquota > 0;
$percentval = 0 if $ftpquota == 0;
next if $percentval < 90;
next unless $ftpused;
next if $webserver_passwd{$ftpuser}{'gecos'} =~ /- POP/;
$quotabalken = easytecc3::quotabar($ftpquota, $ftpused, 'used');
if(exists $domain_home{$webserver_passwd{$ftpuser}{'home'}}){
#$domain = @{$domain_home{$passwd{$ftpuser}{'home'}}};
$domain = join '<br />', @{$domain_home{$webserver_passwd{$ftpuser}{'home'}}};
}
else {
# filter domains
if($session->param('user') ne 'admin'){
my $home = $webserver_passwd{$ftpuser}{'home'};
my $self_home = $webserver_passwd{$session->param('user')}{'home'};
my $allowed = 0;
if($home ne $self_home && $home !~ m#^$self_home/#){
foreach my $dir (keys %domain_home){
if($home eq $dir || $home =~ m#^$dir/#){
$allowed = '1';
}
}
if($allowed != 1){
next;
}
}
}
}
#if($ftpuser eq 'admin' || $ftpuser eq 'web'){
# push(@ftp_user, $ftpuser . '|' .
# $domain . '|' .
# $webserver_passwd{$ftpuser}{'gecos'} . '|' .
# $webserver_passwd{$ftpuser}{'home'} . '|' .
# $ftpquota_sized . '|' .
# $quotabalken . '|' .
# qq~<a href='/cgi-bin/easytecc3/index.pl?action=change_ftpuser&ftpuser=$ftpuser'>L__Editieren__L</a>~);
#}
#else{
# push(@ftp_user, $ftpuser . '|' .
# $domain . '|' .
# $webserver_passwd{$ftpuser}{'gecos'} . '|' .
# $webserver_passwd{$ftpuser}{'home'} . '|' .
# $ftpquota_sized . '|' .
# $quotabalken . '|' .
# qq~<a href='/cgi-bin/easytecc3/index.pl?action=change_ftpuser&ftpuser=$ftpuser'>L__Editieren__L</a><br /><a href='/cgi-bin/easytecc3/index.pl?action=delete_ftpuser&ftpuser=$ftpuser'>L__Löschen__L</a>~);
#}
# if($ftpuser eq 'admin' || $ftpuser eq 'web'){
# push(@ftp_user, $ftpuser . ' ' .
# qq~<a href="#" class="tooltip1 modal-form-horizontal" data-toggle="modal" data-original-title="Bearbeiten" onclick="modal_popup(this, 'change_ftpuser&ftpuser=$ftpuser'); return false;"><i class="fa fa-pencil fa-lg"></i></a>~);
# }
# else{
push(@ftp_user, $ftpuser . ' ' .
qq~<a href="#" class="tooltip1 modal-form-horizontal" data-toggle="modal" data-original-title="Bearbeiten" onclick="modal_popup(this, 'change_ftpuser&ftpuser=$ftpuser'); return false;"><i class="fa fa-pencil fa-lg"></i></a>~);
# }
}
#$template->param('warning_ftpuser_quota' => '<br /><h1>L__Achtung! Folgende FTP-User nutzen mindestens 90% ihrer Quota:__L</h1>') if scalar @ftp_user > 0;
#easytecc3::table(\$template,'<td>L__FTP-User__L</td><td>L__Domain__L</td><td>L__Beschreibung__L</td><td>L__Homeverzeichnis__L</td><td>L__FTP-Quota__L</td><td>L__Quotanutzung__L</td><td>L__Aktionen__L</td>', \@ftp_user, 'table_ftpuser') if scalar @ftp_user > 0;
if (scalar @ftp_user > 0 && $show_ftp eq '1'){
my $template_dashboard_box_alert_ftpuser_less_10percent_free = HTML::Template->new(filename => 'dashboard_box_alert.html');
$template_dashboard_box_alert_ftpuser_less_10percent_free->param('box_alert_text' => 'L__Folgende FTP-Benutzer nutzen mindestens 90% ihrer Quota:__L<br>' . join(qq~<br>~, @ftp_user));
$template_dashboard_box_alert_ftpuser_less_10percent_free->param('box_alert_href' => '/cgi-bin/easytecc4/index.pl?action=show_quota');
$template_dashboard_box_alert_ftpuser_less_10percent_free->param('box_alert_href_text' => 'L__Quota bearbeiten__L');
$template->param('dashboard_alert_ftpuser_less_10percent_free' => $template_dashboard_box_alert_ftpuser_less_10percent_free->output);
$has_warning = '1';
}
my $servername = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
chomp $servername;
####################################################
############# Quotawarnung Email-user
foreach my $user(sort keys %mailpasswd){
#&& $user ne 'admin' damit admin bei externem Mailserver angezeigt wird. Er hat kein POP in Beschreibung
if($mailpasswd{$user}{'gecos'} !~ / - POP$/ && $user ne 'admin' && ($user ne 'admin@' . $servername || $session->param('user') ne 'admin')){
next;
}
# wenn admin Quotagrenze erreicht und kein externer Mailserver, dann taucht admin schon bei FTP-User auf die Quotagrenze erreicht haben.
next if ($user eq 'admin' && ! $extern_mx);
my $domain = $mailpasswd{$user}{'gecos'};
$domain =~ s/ - POP$//;
my $mailquota_sized = $mailquota{$user}{'quota'} / 1024;
#genutzte Quota vom User admin auf externem Mailserver
#wird spter evtl. gebraucht. Wenn kein externer Mailserver, dann /var/spool/mail/admin von Webserver nehmen
$admin_mail_used = $mailquota{$user}{'use'} / 1024 if ($user eq 'admin' && $extern_mx);
#nur die User anzeigen, die weniger als 10% Quota zur Verfgung haben
my $percentval = ($mailquota{$user}{'use'}/$mailquota{$user}{'quota'})*100 if $mailquota{$user}{'quota'} > 0;
$percentval = 0 if $mailquota{$user}{'quota'} == 0;
next if $percentval < 90;
# filter domains
if($session->param('user') ne 'admin'){
my $admins = $domains{'www.' . $domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $session->param('user') . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
}
my $quotabalken = easytecc3::quotabar($mailquota{$user}{'quota'}, $mailquota{$user}{'use'}, 'used');
my $wwwdomain = 'www.' . $domain;
if($user eq 'admin@' . $servername){
$wwwdomain = $servername;
}
push(@user, $user . ' ' .
qq~<a href="#" data-dismiss="modal" class="tooltip1 modal-form-inline" data-toggle="modal" data-original-title="E-Mail-Benutzer bearbeiten" onclick="modal_popup(this, 'change_popuser&domain=$wwwdomain'); return false;"><i class="fa fa-pencil fa-lg"></i></a>~);
}
#$template->param('warning_mailuser_quota' => '<br /><h1>L__Achtung! Folgende E-Mail-User nutzen mindestens 90% ihrer Quota:__L</h1>') if scalar @user > 0;
#easytecc3::table(\$template,'<td>L__Username__L</td><td>L__Domain__L</td><td>L__E-Mail-Quota__L</td><td>L__Quotanutzung__L</td><td colspan="3">L__Aktionen__L</td>', \@user, 'table_mailuser') if scalar @user > 0;
if (scalar @user > 0 && $show_email eq '1'){
my $template_dashboard_box_alert_mailuser_less_10percent_free = HTML::Template->new(filename => 'dashboard_box_alert.html');
$template_dashboard_box_alert_mailuser_less_10percent_free->param('box_alert_text' => 'L__Folgende E-Mail-Benutzer nutzen mindestens 90% ihrer Quota:__L<br>' . join(qq~<br>~, @user));
$template_dashboard_box_alert_mailuser_less_10percent_free->param('box_alert_href' => '/cgi-bin/easytecc4/index.pl?action=show_quota');
$template_dashboard_box_alert_mailuser_less_10percent_free->param('box_alert_href_text' => 'L__Quota bearbeiten__L');
$template->param('dashboard_alert_mailuser_less_10percent_free' => $template_dashboard_box_alert_mailuser_less_10percent_free->output);
$has_warning = '1';
}
####################################################
############# Logfiles für Webserver nehmen mehr als 50% von Webspeicher ein
my @logs = ();
if ($fb) {
@logs = `/usr/iports/bin/sudo /usr/sbin/dellogs`;
}
else{
@logs = `/usr/sbin/dellogs`;
}
my $all_logs_size = '';
my $quota = `cat /etc/vsd/quota`;
chomp $quota;
foreach(@logs){
my ($domain, $logfile, $size) = split /\|/, $_;
$logfile =~ s/^\s+(.*)\s+$/$1/g;
$size =~ s/^\s+(.*)\s+$/$1/g;
if($logfile =~ /^(Access Logs|Error Logs|Messages|Maillogs)/){
logline("info","log = $logfile size = $size");
$size =~ /^(.*)\s(.*)$/;
# Grösse kann in kB oder MB angegeben werden, alles auf MB umrechnen und summieren
my $size_unscaled = $1;
my $scale = $2;
$size_unscaled = $size_unscaled/1024 if $scale eq 'kB';
$all_logs_size += $size_unscaled;
}
}
logline("info","all_logs_size = $all_logs_size M");
my $percentval = ($all_logs_size/$quota)*100;
##kaufm. Rundung
$percentval = sprintf("%.0f", $percentval);
my $balken_usage = $percentval;
my $balken_free = 100 - $balken_usage;
if($percentval >= 50 && $session->param('user') eq 'admin'){
logline("warning","percentval = $percentval");
#$quotabalken = qq|<img src="/easytecc3/images/red.gif" width="$balken_usage" height="15" align="bottom" alt="$balken_usage % genutzt" border="0" /><img src="/easytecc3/images/grey.gif" width="$balken_free" height="15" align="bottom" alt="$balken_free % frei" border="0" />|;
#$template->param('in_use' => sprintf "%.2f", $all_logs_size);
#$template->param('percent' => ' (' . $percentval . '%)');
#$template->param('bar' => $quotabalken);
#$template->param('warning_logfiles_half_webserver_quota' => qq~<br /><h1>L__Achtung!__L $percentval % L__der Serverquota werden nur für Logfiles verwendet__L!</h1> $quotabalken ~ . sprintf("%.2f", $all_logs_size) . qq~ MB Logfiles vorhanden. <b><a href="/cgi-bin/easytecc3/index.pl?action=delete_logfiles&logfile=all">L__Alle Logs löschen__L</a></b>~)
my $template_dashboard_box_alert_logs_more_50percent_use = HTML::Template->new(filename => 'dashboard_box_alert.html');
$template_dashboard_box_alert_logs_more_50percent_use->param('box_alert_text' => qq~$percentval % L__der Serverquota werden nur für Logfiles verwendet__L!~);
$template_dashboard_box_alert_logs_more_50percent_use->param('box_alert_href' => '/cgi-bin/easytecc4/index.pl?action=show_logfiles');
$template_dashboard_box_alert_logs_more_50percent_use->param('box_alert_href_text' => 'L__Logfiles ansehen__L');
$template->param('dashboard_alert_logs_more_50percent_use' => $template_dashboard_box_alert_logs_more_50percent_use->output);
$has_warning = '1';
}
####################################################
############# kein cronjob zum automatischen löschen von Logs
# warum nur unter linux? auf den bsds funktioniert das dellogs nicht weniger oder mehr...
if($session->param('user') eq 'admin' && !$fb){
unless(`grep 'dellogs -a' /home/web/cronfile`){
my $template_dashboard_box_alert_logs_no_delete_cronjob = HTML::Template->new(filename => 'dashboard_box_warning.html');
#$template_dashboard_box_alert_logs_no_delete_cronjob->param('box_alert_text' => qq~L__Die Logs werden aktuell nicht automatisch gelöscht!__L~);
#$template_dashboard_box_alert_logs_no_delete_cronjob->param('box_alert_href' => '/cgi-bin/easytecc4/index.pl?action=auto_cronjob&cronjob=delete_all_logs');
$template_dashboard_box_alert_logs_no_delete_cronjob->param('box_alert_text' => qq~L__Die Logs werden aktuell nicht automatisch gelöscht!__L<br>
<a href="#" class="modal-form-horizontal" data-toggle="modal" onclick="modal_popup(this, 'delete_logfiles&logfile=add_cron'); return false;">L__Logs zukünftig automatisch löschen__L</a>
~);
$template->param('dashboard_alert_logs_no_delete_cronjob' => $template_dashboard_box_alert_logs_no_delete_cronjob->output);
$has_warning = '1';
#$template->param('warning_logfiles_no_cron' => qq~<br /><h1>L__Achtung! Die Logs werden aktuell nicht automatisch gelöscht!__L</h1><a href="/cgi-bin/easytecc3/index.pl?action=auto_cronjob&cronjob=delete_all_logs">L__Logs zukünftig automatisch löschen__L</a>~);
}
}
if($session->param('user') eq 'admin' && $fb && ! -f '/usr/local/etc/newsyslog.conf.d/apache_mysql_mail.conf' ){
my $template_dashboard_box_alert_logs_no_delete_cronjob = HTML::Template->new(filename => 'dashboard_box_warning.html');
#$template_dashboard_box_alert_logs_no_delete_cronjob->param('box_alert_text' => qq~L__Die Logs werden aktuell nicht automatisch gelöscht!__L~);
#$template_dashboard_box_alert_logs_no_delete_cronjob->param('box_alert_href' => '/cgi-bin/easytecc4/index.pl?action=auto_cronjob&cronjob=delete_all_logs');
$template_dashboard_box_alert_logs_no_delete_cronjob->param('box_alert_text' => qq~L__Es ist keine Logrotation eingerichtet, Logdateien werden aktuell nicht automatisch gelöscht!__L<br>
<a href="#" class="modal-form-horizontal" data-toggle="modal" onclick="modal_popup(this, 'logrotate'); return false;">L__Logrotation einrichten__L</a>
~);
$template->param('dashboard_alert_logs_no_delete_cronjob' => $template_dashboard_box_alert_logs_no_delete_cronjob->output);
$has_warning = '1';
#$template->param('warning_logfiles_no_cron' => qq~<br /><h1>L__Achtung! Die Logs werden aktuell nicht automatisch gelöscht!__L</h1><a href="/cgi-bin/easytecc3/index.pl?action=auto_cronjob&cronjob=delete_all_logs">L__Logs zukünftig automatisch löschen__L</a>~);
}
if($fb && $show_ftp eq '1' && ! -f '/usr/local/etc/easytecc/2fa/' . $session->param('user') ){
my $user = $session->param('user');
my $template_dashboard_box_alert_2fa = HTML::Template->new(filename => 'dashboard_box_warning.html');
#$template_dashboard_box_alert_logs_no_delete_cronjob->param('box_alert_text' => qq~L__Die Logs werden aktuell nicht automatisch gelöscht!__L~);
#$template_dashboard_box_alert_logs_no_delete_cronjob->param('box_alert_href' => '/cgi-bin/easytecc4/index.pl?action=auto_cronjob&cronjob=delete_all_logs');
$template_dashboard_box_alert_2fa->param('box_alert_text' => qq~L__Dieser Account ist noch nicht durch Zwei-Faktor-Authentifizierung abgesichert!__L<br>
<a href="#" class="modal-form-horizontal" data-toggle="modal" onclick="modal_popup(this, 'change_ftpuser&ftpuser=$user'); return false;">L__Zwei-Faktor-Authentifizierung einrichten__L</a>
~);
$template->param('dashboard_alert_2fa' => $template_dashboard_box_alert_2fa->output);
$has_warning = '1';
#$template->param('warning_logfiles_no_cron' => qq~<br /><h1>L__Achtung! Die Logs werden aktuell nicht automatisch gelöscht!__L</h1><a href="/cgi-bin/easytecc3/index.pl?action=auto_cronjob&cronjob=delete_all_logs">L__Logs zukünftig automatisch löschen__L</a>~);
}
if($session->param('user') eq 'admin' && $fb && -f '/usr/local/etc/easytecc/shell2ban/.disabled' ){
my $template_dashboard_box_alert_firewall = HTML::Template->new(filename => 'dashboard_box_warning.html');
#$template_dashboard_box_alert_logs_no_delete_cronjob->param('box_alert_text' => qq~L__Die Logs werden aktuell nicht automatisch gelöscht!__L~);
#$template_dashboard_box_alert_logs_no_delete_cronjob->param('box_alert_href' => '/cgi-bin/easytecc4/index.pl?action=auto_cronjob&cronjob=delete_all_logs');
$template_dashboard_box_alert_firewall->param('box_alert_text' => qq~L__Die Firewall ist deaktiviert!__L<br>
<a href="/cgi-bin/easytecc4/index.pl?action=change_firewall">L__Firewall aktivieren__L</a>
~);
$template->param('dashboard_alert_firewall' => $template_dashboard_box_alert_firewall->output);
$has_warning = '1';
#$template->param('warning_logfiles_no_cron' => qq~<br /><h1>L__Achtung! Die Logs werden aktuell nicht automatisch gelöscht!__L</h1><a href="/cgi-bin/easytecc3/index.pl?action=auto_cronjob&cronjob=delete_all_logs">L__Logs zukünftig automatisch löschen__L</a>~);
}
my $admin_mail_used;
####################################################
############# admin-Postfach mehr als 500MB voll
if($extern_mx){
#nix wurde vorher schon ausgelesen
}
else{
if ($fb) {
#hmtja, dateien zählen wenn wir imap-quota haben und dann ohne timeout... kriegt ein TODO tag!
#TODO: s.o.
#my $servername = `grep -m1 han-solo.net /etc/hosts | awk '{print \$2}'`;
my $servername = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
chomp($servername);
my $dir = '/home/admin@' . $servername;
# und das gleich zweimal...
#$admin_mail_used = `/usr/iports/bin/sudo /usr/bin/du -Ams $dir`;
$admin_mail_used = `/usr/iports/bin/sudo /usr/sbin/doveadm -f flow quota get -u "admin\@$servername" | sed '/Type=MESSAGE/d ; s/^.*Type=STORAGE Value=// ; s/ Limit=.*//'`;
chomp $admin_mail_used;
$admin_mail_used /= 1024;
}
else{
$admin_mail_used = `du -ms /root/mail`;
}
logline("debug","admin_mail_used1=$admin_mail_used");
$admin_mail_used =~ /^([0-9]{1,20})\s+/;
$admin_mail_used = $1; # in Megabyte
logline("debug","admin_mail_used2=$admin_mail_used");
}
if($admin_mail_used >= 500 && $session->param('user') eq 'admin' && ! (`grep 'rm .*/root/mail' /home/web/cronfile` || `grep 'rm .*/home/admin@$servername' /home/web/cronfile`)){
$admin_mail_used = sprintf("%.0f", $admin_mail_used);
logline("warning","admin_mail_used3 = $admin_mail_used");
my $template_dashboard_box_alert_admin_mail_more_500MB_use = HTML::Template->new(filename => 'dashboard_box_alert.html');
$template_dashboard_box_alert_admin_mail_more_500MB_use->param('box_alert_text' => qq~L__Im Postfach des Users admin befinden sich__L $admin_mail_used MB L__E-Mails__L.<br>
<a href="#" class="modal-form-horizontal" data-toggle="modal" onclick="modal_popup(this, 'auto_cronjob&cronjob=delete_admin_email'); return false;">L__Inhalt von admin-Postfach zukünftig automatisch löschen__L</a>
~);
#$template_dashboard_box_alert_admin_mail_more_500MB_use->param('box_alert_href' => '/cgi-bin/easytecc4/index.pl?action=auto_cronjob&cronjob=delete_admin_email');
#$template_dashboard_box_alert_admin_mail_more_500MB_use->param('box_alert_href_text' => 'L__Inhalt von admin-Postfach zukünftig automatisch löschen__L');
$template->param('dashboard_alert_admin_mail_more_500MB_use' => $template_dashboard_box_alert_admin_mail_more_500MB_use->output);
$has_warning = '1';
#$template->param('warning_admin_mail' => qq~<br /><h1>L__Achtung! Im Postfach des Users admin befinden sich__L $admin_mail_used MB L__E-Mails__L.</h1><a href="/cgi-bin/easytecc3/index.pl?action=auto_cronjob&cronjob=delete_admin_email">L__Inhalt von admin-Postfach zukünftig automatisch löschen__L</a>~);
}
if ($has_warning) {
$template->param('has_warning' => '1');
}
add_dobackup_cron();
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub error{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $error = shift;
logline("debug","######################################### got error $error");
my $template = '';
if(exists $ajax_actions{$input{'action'}}){
$template = HTML::Template->new(filename => 'error_div.html');
$json_output{'critical_error'} = '1';
}
else{
$template = HTML::Template->new(filename => 'error.html');
}
logline("error","Throwing error = ".$error);
$template->param('error_text' => $error);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub modal_error{
#this is for functions where a modal should popup but there was an error,
#e.g. filemanager -> modify_file -> edit and file is binary so it can't be edited
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $error = shift;
my $template = HTML::Template->new(filename => 'modal_error.html');
logline("error","Throwing error = ".$error);
$template->param('error_text' => $error);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub modal_message{
#this is for functions where a modal should popup but there was an error,
#e.g. filemanager -> modify_file -> edit and file is binary so it can't be edited
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my ($title,$message) = @_;
my $template = HTML::Template->new(filename => 'modal_message.html');
$template->param('message_title' => $title);
$template->param('message_text' => $message);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub awstats_migration{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'awstats_migration.html');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub roundcube_migration{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'roundcube_migration.html');
my $apache = `grep httpd_enable /etc/rc.conf`;
chomp $apache;
my $php_error_text = '';
my $php_version = `egrep '^extension_dir' /etc/php.ini`;
if($php_version !~ /php5\.(2|3|4|5|6|7|8|9)/){
$php_error_text = 'L__Die PHP-Version ist zu alt. Für Roundcube ist mindestens PHP5.2 notwendig, bitte führen Sie ein PHP-Update gemäß <a href="http://www.hostnet.de/faq" target="_blank">PHP-Updateanleitung</a> durch oder wenden sich an den Support um das Update durchführen zu lassen.__L';
}
if($apache =~ /"1"/s){
return(error('L__Die Apacheversion ist zu alt. Bitte führen Sie ein Apacheupdate gemäß <a href="http://www.hostnet.de/faq" target="_blank">Apache-Updateanleitung</a> durch oder wenden sich an den Support um ein Apacheupdate durchführen zu lassen und Roundcube nutzen zu können.__L<br />' . $php_error_text));
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_awstats_migration{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
foreach my $domain (sort keys %domains){
if($domains{$domain}{'access_log'} ne ''){
my $got = `$easytecc_prefix/gen_awstats.pl $domain`;
return(error("L__Fehler beim Anlegen der Statistik für Domain__L $domain:$got")) if $got;
}
}
logline("debug","Creating File Object \$cronfile.");
my $cronfile = file->new({file_name => '/home/web/cronfile'});
$cronfile->read_file;
my $min = int(rand('50'));
push @{$cronfile->file_content}, qq~$min 23 * * * /usr/local/awstats/tools/awstats_updateall.pl now 1>/dev/null 2>/dev/null\n~;
# alte webalizer cronjobs entfernen
my @new_cronfile = ();
foreach($cronfile->file_content){
#cronjob löschen
if (/webalizer -c/){
logline("debug","cronjob löschen:$_");
next;
}
# alles andere in zu schreibendes cronfile
push @new_cronfile, $_;
}
$cronfile->file_content(\@new_cronfile);
my $got = $cronfile->write_file;
if ($got) {
logline("error","cronfile->write_file = ".$got);
return(error($got));
}
$template->param('result' => 'Die AWStats-Auswertungen wurden erfolgreich angelegt und werden tglich zwischen 00:00-01:00 automatisch aktualisiert');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_roundcube_migration{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my @new_httpd_conf = ();
#Alias /twig auf Redirect /twig /webmail ändern und zusätzlichen Alias Alias /webmail /home/httpd/docs/roundcube
foreach($httpd_conf->file_content){
if(/^Alias\s+\/twig/){
push @new_httpd_conf, qq~Alias /webmail $droot_prefix/roundcube~;
}
elsif(/^Alias\s+\/easytecc\s+/){
push @new_httpd_conf, qq~<Directory $droot_prefix/twig>
RewriteEngine On
RewriteRule ^(.*) http://%{SERVER_NAME}/webmail [R,L]
</Directory>
Alias /twig $droot_prefix/twig
~;
push @new_httpd_conf, $_;
}
elsif(m/^ServerName.*\.han-solo\.net/){
push @new_httpd_conf, $_;
push @new_httpd_conf, qq~Alias /webmail $droot_prefix/roundcube~;
}
else{
push @new_httpd_conf, $_;
}
}
$httpd_conf->file_content(\@new_httpd_conf);
my $got = $httpd_conf->write_file;
if ($got) {
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(error($got))
}
system("touch /usr/local/etc/easytecc/twig-migration-done");
$template->param('result' => qq~L__Die Roundcube-Umstellung wurde erfolgreich durchgeführt.__L<br /> <a href="/webmail" target="_blank"><b>L__Zum Webmailer__L</b></a>~);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_cloneworx{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_cloneworx.html');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_vhosts{
logline("debug","sub show_vhosts STARTS NOW");
if($session->param('show_vhosts') ne '1'){
return start();
}
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_vhosts.html');
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my %config = %{$httpd_conf->config_hash()};
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my %home_lookup = %{$passwd->lookup2_hash()};
my ($quotaref, $sum_ftplimit, $sum_ftpuse, $ftpserverlimit) = easytecc3::getquota_ftp();
my %quota = %$quotaref;
my $table_data = {};
my $gecos = '';
# hide new vhost non admin
if($session->param('user') eq 'admin'){
$template->param('show_new_vhost' => '1');
} else {
$gecos = $passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.vhost-1';
}
if($gecos =~ m/\.vhost-[1-9]/){
$template->param('show_new_vhost' => '1');
}
}
my @domains = ();
foreach my $domain (sort keys %domains){
logline("debug"," Domain: $domain");
# filter domains
if($session->param('user') ne 'admin'){
my $admins = $domains{$domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$readuserregex = '#' . $session->param('user') . '#';
$writeuserregex = '#' . uc $session->param('user') . '#';
if($admins =~ m/$writeuserregex/){
$table_data->{$domain}{'show_edit'} = '1';
$table_data->{$domain}{'show_delete'} = '1';
} elsif($admins =~ m/$readuserregex/){
$table_data->{$domain}{'show_edit'} = '1';
} else {
next;
}
} else {
$table_data->{$domain}{'show_edit'} = '1';
$table_data->{$domain}{'show_delete'} = '1';
}
my $ftpuser = '';
my $ftpquota = '';
my $ftpquota_sized = '';
my $ftpused = '';
my $quotabalken = '';
my $ssl = '';
my $ip = '';
my $domain_ohne_www = $domain;
$domain_ohne_www =~ s/^www\.//;
if(exists $home_lookup{$domains{$domain}{'droot'}}){
$ftpuser = $home_lookup{$domains{$domain}{'droot'}};
$ftpquota = $quota{$ftpuser}{'quota'};
$ftpquota_sized = easytecc3::getsize($ftpquota);
$ftpused = $quota{$ftpuser}{'use'};
$quotabalken = easytecc3::quotabar($ftpquota, $ftpused);
}
#logline("debug","$domain ssl_enabled=" . $config{'ssl_enabled'} . 'ssl=' . $domains{$domain}{'ssl'});
my $alias_domain;
my %alias_domains;
foreach $alias_domain (@{$domains{$domain}{'domains'}}){
$alias_domain =~ s/^www\.//;
if($alias_domain ne $domain_ohne_www){
$alias_domains{$alias_domain} = 1;
}
}
$table_data->{$domain}{'alias_domains'} = join(', ',keys %alias_domains);
# wenn SSL-Domain, dann Icon in vHost-Liste
if($config{'ssl_enabled'} && $domains{$domain}{'ssl'}){
$ssl = 1;
my ($cert_expire_date,$cert_expire_days)= https_cert_expire($domains{$domain}{'ssl_cert'});
if(length($cert_expire_date)){
my $cert_expire = "$cert_expire_date ($cert_expire_days Tage)";
$table_data->{$domain}{'cert_expire'} = $cert_expire;
if($cert_expire_days < 25){
$table_data->{$domain}{'cert_warning'} = '1';
}
if($cert_expire_days < 0){
$table_data->{$domain}{'cert_failure'} = '1';
}
}
}
# wenn separate IP, dann ebenfalls Icon
if($config{'main_ip'} ne $domains{$domain}{'ip'}){
$ip = $domains{$domain}{'ip'};
}
logline("debug","show_vhosts_domain=" . $domain);
$table_data->{$domain}{'idn_domain_no_www'} = encode('utf-8', domain_to_unicode($domain_ohne_www));
if($domain_ohne_www ne $table_data->{$domain}{'idn_domain_no_www'}){
$table_data->{$domain}{'domain_no_www'} = $domain_ohne_www;
}
$table_data->{$domain}{'domain'} = $domain;
$table_data->{$domain}{'idn_domain'} = encode('utf-8', domain_to_unicode($domain));
$table_data->{$domain}{'ssl'} = $ssl;
$table_data->{$domain}{'ip'} = $ip;
#$table_data->{$domain}{'droot'} = $domains{$domain}{'droot'};
$table_data->{$domain}{'droot'} = easytecc3::substr_e4($domains{$domain}{'droot'});
$table_data->{$domain}{'droot_tooltip'} = $domains{$domain}{'droot'};
if(-d $domains{$domain}{'droot'}){
$table_data->{$domain}{'dir_encoded'} = encode_base64url($domains{$domain}{'droot'});
}
$table_data->{$domain}{'pop'} = $domains{$domain}{'pop'};
$table_data->{$domain}{'for'} = $domains{$domain}{'for'};
$table_data->{$domain}{'aut'} = $domains{$domain}{'aut'};
# $table_data->{$domain}{'quota'} = $domains{$domain}{'quota'};
# show units
$table_data->{$domain}{'quota'} = easytecc3::getsize($domains{$domain}{'quota'} * 1024);
$table_data->{$domain}{'statslink'} = $domains{$domain}{'statslink'};
$table_data->{$domain}{'custom_tag'} = $domains{$domain}{'custom_tag'};
# default
if($domains{$domain}{'custom_tag'}){
$table_data->{$domain}{'note_title'} = $domains{$domain}{'custom_tag'};
$table_data->{$domain}{'note_text'} = '';
}
my @keys = ('DOMAIN',$domain);
my $note = note_from_hashfile(\@keys);
if($note->{title}){
$table_data->{$domain}{'note_title'} = $note->{title};
$table_data->{$domain}{'note_text'} = $note->{text};
}
$table_data->{$domain}{'admin_users'} = $domains{$domain}{'admin_users'};
}
my $table_data_sorted = {};
foreach $domain (keys %{$table_data}){
$table_data_sorted->{$table_data->{$domain}{'idn_domain'}} = $table_data->{$domain};
}
easytecc3::table_e4($template, $table_data_sorted, 'table_tr_show_vhosts_template.html');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_email{
if($session->param('show_email') ne '1'){
return start();
}
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_email.html');
my $email = '';
my $quotabalken = '';
my @domains = ();
my %passwd = ();
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
$mailpasswd = easytecc3::get_mailpasswd();
%passwd = %{$mailpasswd->file_parsed_hash()};
#key=domain, value anzahl user
my %domain_count_lookup = %{$mailpasswd->lookup_hash_domain_count()};
logline("debug","Creating File Object \$virtmaps.");
my $virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %email = %{$virtmaps->file_parsed_hash()};
my %virtmaps_domain_count_lookup = %{$virtmaps->lookup_hash_domain_count()};
my %domain_autoreply_count_lookup = %{$virtmaps->lookup_hash_autoreply_count()};
logline("debug","email is:" . Data::Dumper->Dump([\%email]));
logline("debug","virtmaps_domain_count_lookup is:" . Data::Dumper->Dump([\%virtmaps_domain_count_lookup]));
logline("debug","domain_autoreply_count_lookup is:" . Data::Dumper->Dump([\%domain_autoreply_count_lookup]));
foreach( sort keys %domain_autoreply_count_lookup){
logline("debug","Foreach domain_autoreply_count_lookup=$_ count=" . $domain_autoreply_count_lookup{$_});
}
logline("debug","Creating File Object \$aliases.");
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
logline("debug","Creating File Object \$passwd.");
my $passwd_ftp = file->new({file_name => '/etc/passwd'});
$passwd_ftp->read_file;
my %passwd_ftp = %{$passwd_ftp->file_parsed_hash()};
my %home_lookup = %{$passwd_ftp->lookup2_hash()};
my ($quotaref, $sum_ftplimit, $sum_ftpuse, $ftpserverlimit) = easytecc3::getquota_ftp();
my %quota = %$quotaref;
# hide mailserver domains for non admin, show edit
my $show_email = '';
my $show_edit_email = '';
my $show_vhosts = '';
my $servername = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
chomp $servername;
if($session->param('user') eq 'admin'){
$template->param('show_mailserver_domains' => '1');
$template->param('show_quotamessage' => '1');
# mailserver cert - derzeit zu gefährlich wegen reverse dns etc.
#$template->param('show_mailserver_cert' => '1');
#
##my $mailserver_certs=`ls -1 /etc/letsencrypt/archive/ | while read DOMAIN; do grep -qE "^[^#]*Server(Name|Alias).* (www\\.)?\$DOMAIN" /etc/apache24/httpd.conf && echo "\$DOMAIN"; done | sort`;
#
##my $mailserver_certs=`find /etc/letsencrypt/renewal/ -name "*.conf" -exec sed '1,/^\\[\\[webroot_map\\]\\]\$/d ; /^www\\./d ; s/ =.*//' {} \\; | while read DOMAIN; do grep -qE "^[^#]*ServerName (www\\.)?\$DOMAIN" /etc/apache24/httpd.conf && echo "\$DOMAIN"; done | sort -u`;
#
#my $mailserver_certs=`grep -Eh '^[^#]*SSLCertificateKeyFile' /etc/apache24/httpd.conf /etc/apache24/extra/httpd-ssl.conf | sed 's/\\/[^\\/]*\$// ; s/^.*\\///' | sort -u`;
#chomp($mailserver_certs);
#
#logline("debug","###############mailserver certs: #$mailserver_certs#");
#
#my @mailserver_certs = split(/[\r\n]/,$mailserver_certs);
#
#my $current_mailserver_cert = `readlink /usr/ssl/wild.han.pem | sed 's/\\/[^\/]*\$// ; s/^.*\\///'`;
#chomp $current_mailserver_cert;
#
#logline("debug","###############mailserver cert: $current_mailserver_cert");
#
#my $template_mailserver_cert_select = HTML::Template->new(filename => 'mailserver_cert_select.html');
#easytecc3::template_loop(\%input,\$template_mailserver_cert_select, \@mailserver_certs, 'mailserver_cert_select', $current_mailserver_cert);
#$template->param('mailserver_cert_select' => $template_mailserver_cert_select->output);
#
$show_email = '1';
$show_edit_email = '1';
$show_vhosts = '1';
$domains{$servername}{'pop'} = 1;
$domains{$servername}{'for'} = 0;
$domains{$servername}{'aut'} = 0;
} else {
my $gecos = $passwd_ftp{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.vhost-1.email-1';
}
if($gecos =~ m/\.vhost/){
$show_vhosts = '1';
}
if($gecos =~ m/\.email/){
$show_email = '1';
if($gecos =~ m/\.email-[1-9]/){
$show_edit_email = '1';
}
}
}
if(!$fb){
delete($domains{$servername});
}
my $table_data = {};
foreach my $domain (sort keys %domains){
# filter domains
if($session->param('user') ne 'admin'){
my $admins = $domains{$domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$readuserregex = '#' . $session->param('user') . '#';
$writeuserregex = '#' . uc $session->param('user') . '#';
if($admins =~ m/$writeuserregex/){
if($show_vhosts eq '1'){
$table_data->{$domain}{'show_edit_vhost'} = '1';
}
} elsif($admins =~ m/$readuserregex/){
if($show_vhosts eq '1'){
$table_data->{$domain}{'show_vhost'} = '1';
}
} else {
next;
}
} elsif($domain ne $servername) {
$table_data->{$domain}{'show_edit_vhost'} = '1';
}
$table_data->{$domain}{'show_edit_email'} = $show_edit_email;
$table_data->{$domain}{'show_email'} = $show_email;
my $popcount = '0';
my $forcount = '0';
my $autcount = '0';
my $mailquota = '';
if($domain eq $servername){
$mailquota = $quota{'admin'}{'quota'} / 1024;
$domains{$domain}{'aut'} = 0;
$domains{$domain}{'for'} = 0;
$domains{$domain}{'pop'} = 1;
$popcount = '1';
}
else{
$mailquota = $domains{$domain}{'quota'};
my $ftpdir = $domains{$domain}{'droot'};
while(length($ftpdir) && $ftpdir !~ /\/(data|noexec)$/){
if(exists $home_lookup{$ftpdir}){
my $ftpuser = $home_lookup{$ftpdir};
$mailquota = (($domains{$domain}{'quota'} * 1024 ) - $quota{$ftpuser}{'quota'}) / 1024;
last;
}
$ftpdir =~ s/\/[^\/]*$//;
}
}
$mailquota = easytecc3::getsize($mailquota * 1024);
logline("debug","Foreach Domain: $domain.");
my $domain_ohne_www = $domain;
$domain_ohne_www =~ s/^www\.//;
my $serveralias = '<br />';
#foreach(@{$domains{$domain}{'domains'}}){
# next if /^www\./;
# next if /^$domain_ohne_www$/;
# $serveralias .= encode('utf-8', domain_to_unicode($_)) . '<br />';
#}
foreach(@{$domains{$domain}{'domains'}}){
if (defined $domain_autoreply_count_lookup{$_}) {
$autcount = $autcount + $domain_autoreply_count_lookup{$_};
}
}
my $splitted_domains = join '|', @{$domains{$domain}{'domains'}};
#$splitted_domains = quotemeta($splitted_domains);
#$splitted_domains =~ s/\\/\\\\/g;
$splitted_domains =~ s/\*/\\*/g;
logline("debug","splitted_domains = $splitted_domains");
foreach my $virtmaps_domain( keys %virtmaps_domain_count_lookup) {
if($virtmaps_domain =~ /^($splitted_domains)$/){
$forcount = $forcount + $virtmaps_domain_count_lookup{$virtmaps_domain};
}
}
#todo: unbedingt optimieren und Iterationen weg mit lookup hash aus parsingfunktion von virtmaps
#foreach my $virtmaps_lhs(keys %email){
# my $virtmaps_rhs = $email{$virtmaps_lhs};
# my $line = $virtmaps_lhs . ' ' . $virtmaps_rhs;
# #logline("debug","line = $line");
#
# #if($line =~ /@(?:$splitted_domains)(?: |\t)+[a-zA-Z_\.\-0-9]+[^_aut](.+)$/){
# if($virtmaps_lhs =~ /@(?:$splitted_domains)$/){
# #logline("debug","match $1");
#
# #if ($1 eq '_aut'){
# if ($aliases{$virtmaps_rhs} =~ /\/autoresponder/){
# logline("debug","match aut");
# $autcount++;
# }
# $forcount++;
# }
#}
#if (defined $domain_count_lookup{$domain_ohne_www}) {
# $popcount = $popcount + $domain_count_lookup{$domain_ohne_www};
#}
foreach(@{$domains{$domain}{'domains'}}){
$_ =~ s/^www\.//;
if (defined $domain_count_lookup{$_}) {
$popcount = $popcount + $domain_count_lookup{$_};
}
}
#foreach my $line (keys %passwd){
# if($passwd{$line}{'gecos'} =~ /^(?:$splitted_domains) - POP/){
# logline("debug","passwd pop: " . $passwd{$line}{'gecos'});
# $popcount++;
# }
#}
$table_data->{$domain}{'domain'} = $domain;
$table_data->{$domain}{'idn_domain'} = encode('utf-8', domain_to_unicode($domain));
$table_data->{$domain}{'idn_domain_no_www'} = encode('utf-8', domain_to_unicode($domain_ohne_www));
$table_data->{$domain}{'pop'} = $domains{$domain}{'pop'};
$table_data->{$domain}{'popcount'} = $popcount;
$table_data->{$domain}{'for'} = $domains{$domain}{'for'};
$table_data->{$domain}{'forcount'} = $forcount;
$table_data->{$domain}{'aut'} = $domains{$domain}{'aut'};
$table_data->{$domain}{'autcount'} = $autcount;
$table_data->{$domain}{'mailquota_MB'} = $mailquota;
if ($domains{$domain}{'pop'} >= 1 ||
$domains{$domain}{'for'} >= 1 ||
$domains{$domain}{'aut'} >= 1) {
$table_data->{$domain}{'edit_email_icons'} = 1;
}
# href to list of email adresses for single edit
if ($domains{$domain}{'for'} >= 1) {
if(-e '/usr/local/etc/easytecc/showsingleeditemail'){
$table_data->{$domain}{'href_single_edit_email'} = 1;
}
}
}
my $table_data_sorted = {};
foreach $domain (keys %{$table_data}){
$table_data_sorted->{$table_data->{$domain}{'idn_domain'}} = $table_data->{$domain};
}
easytecc3::table_e4($template, $table_data_sorted, 'table_tr_show_email_template.html');
if (length($input{'active_tab'})) {
$template->param('show_email_active_tab'.$input{'active_tab'} => 1);
}
else{
$template->param('show_email_active_tab1' => 1);
}
#dkim
if(-f '/etc/opendkim.conf'){
$template->param('dkim_available' => 1);
}
#separate function for mailserver domains
new_sendmail_cw($template);
#quotamessagestuff
my $quotasender;
if(-e '/etc/mail/quotafrom'){
$quotasender = `/bin/cat /etc/mail/quotafrom 2>/dev/null`;
chomp($quotasender);
} elsif(-e '/etc/mail/quotamessage'){
$quotasender = `/usr/bin/grep -i -m1 '^From: ' /etc/mail/quotamessage`;
chomp($quotasender);
$quotasender =~ s/^From:\s+//gi;
} else {
$quotasender = 'MAIL_FROM';
}
if(!length($quotasender) || $quotasender eq 'MAIL_FROM'){
$quotasender = 'Mailserver Warning <mailserver@${MAIL_DOMAIN}>';
}
$quotasender =~ s/\"?\$\{//g;
$quotasender =~ s/\}\"?//g;
my $quotasubject;
if(-e '/etc/mail/quotamessage'){
$quotasubject = `/usr/bin/grep -i -m1 '^Subject: ' /etc/mail/quotamessage`;
chomp($quotasubject);
$quotasubject =~ s/^Subject:\s+//gi;
} else {
$quotasubject = 'MAIL_SUBJECT';
}
if(!length($quotasubject) || $quotasubject eq 'MAIL_SUBJECT'){
$quotasubject = 'Ihre Mailbox ist zu "${MAIL_QUOTA_PERCENT}"% voll!';
}
$quotasubject =~ s/\"?\$\{//g;
$quotasubject =~ s/\}\"?//g;
my $quotamessage;
if(-e '/etc/mail/quotamessage'){
$quotamessage = `/bin/cat /etc/mail/quotamessage 2>/dev/null`;
$quotamessage =~ s/^(From|Subject):\s.*$//gmi;
$quotamessage =~ s/^\s*//gs;
$quotamessage =~ s/\s*$//gs;
} elsif(-e '/usr/sbin/quota-warning.sh'){
$quotamessage = `/bin/cat /usr/sbin/quota-warning.sh 2>/dev/null`;
$quotamessage =~ s/^.*Content-Transfer-Encoding: 8bit//gs;
$quotamessage =~ s/EOF.*$//gs;
$quotamessage =~ s/^\s*//gs;
$quotamessage =~ s/\s*$//gs;
} else {
$quotamessage = '';
}
$quotamessage =~ s/\"?\$\{//g;
$quotamessage =~ s/\}\"?//g;
$template->param('quotasender' => $quotasender);
$template->param('quotasubject' => $quotasubject);
$template->param('quotamessage' => $quotamessage);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_ftpuser{
if($session->param('show_ftp') ne '1'){
return start();
}
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_ftpuser.html');
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my %domain_home;
my %admin_users;
foreach(keys %domains){
# filter domains
if($session->param('user') ne 'admin'){
my $admins = $domains{$_}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $session->param('user') . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
}
# gather admin users
else {
my @admins = split(/[\s,]+/, $domains{$_}{'admin_users'});
foreach my $admin (@admins){
$admin_users{$admin} = $admin;
}
}
logline("debug","domain_home=" . $domains{$_}{'droot'});
logline("debug","domain_domains=" . $domains{$_}{'domains'});
$domain_home{$domains{$_}{'droot'}} = $domains{$_}{'domains'};
}
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my $show_new_ftp = '';
my $show_edit_ftp = '';
if($session->param('user') eq 'admin'){
$show_new_ftp = '1';
$show_edit_ftp = '1';
} else {
my $gecos = $passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.ftp-2';
}
if($gecos =~ m/\.ftp-1/){
$show_edit_ftp = '1';
} elsif($gecos =~ m/\.ftp-2/){
$show_new_ftp = '1';
$show_edit_ftp = '1';
}
}
$template->param('show_new_ftp' => $show_new_ftp);
$template->param('show_edit_ftp' => $show_edit_ftp);
my ($quotaref, $sum_ftplimit, $sum_ftpuse, $ftpserverlimit) = easytecc3::getquota_ftp();
my %quota = %$quotaref;
#Zähler für Tabelle wenn es zu FTP-User keine Domain gibt, z.B. alle Systemuser
my $count = 1;
my @ftp_user = ();
my $table_data = {};
foreach my $ftpuser (sort keys %passwd){
# User web und ftp nicht bei ftpusern anzeigen. Stiftet nur Verwirrung
next if $ftpuser eq 'web';
next if $ftpuser eq 'ftp';
next if $ftpuser eq 'cyrus';
next if $ftpuser eq 'dovecot';
next if $ftpuser eq 'dovenull';
next if $ftpuser eq 'mysql';
next if $ftpuser eq 'pgsql';
next if $ftpuser eq 'virtmail';
next if $ftpuser eq 'svn';
next if $ftpuser eq 'haproxy';
my $ftpquota = '';
my $ftpquota_sized = '';
my $ftpused = '';
my $quotabalken = '';
my $domain = '';
my $has_domain = '';
$ftpquota = $quota{$ftpuser}{'quota'};
$ftpquota_sized = easytecc3::getsize($ftpquota);
$ftpused = $quota{$ftpuser}{'use'};
logline("debug","ftpuser=$ftpuser\tftpused=$ftpused");
next unless $ftpused;
next if $passwd{$ftpuser}{'gecos'} =~ /- POP/;
if($session->param('user') eq 'admin' && $passwd{$ftpuser}{'gecos'} =~ /^CUST/){
next;
}
$quotabalken = easytecc3::quotabar($ftpquota, $ftpused, 'table');
if(exists $domain_home{$passwd{$ftpuser}{'home'}}){
#$domain = @{$domain_home{$passwd{$ftpuser}{'home'}}};
foreach(@{$domain_home{$passwd{$ftpuser}{'home'}}}){
$domain .= encode('utf-8', domain_to_unicode($_)) . '<br />';
}
$has_domain = 1;
} else {
# filter domains
if($session->param('user') ne 'admin'){
my $home = $passwd{$ftpuser}{'home'};
my $self_home = $passwd{$session->param('user')}{'home'};
my $allowed = 0;
if($home ne $self_home && $home !~ m#^$self_home/#){
foreach my $dir (keys %domain_home){
if($home eq $dir || $home =~ m#^$dir/#){
$allowed = '1';
}
}
if($allowed != 1){
next;
}
}
}
}
if($session->param('user') eq 'admin'){
$table_data->{$ftpuser}{'is_admin_user'} = '1';
}
#wenn keiner domain zugeordnet, dann nicht no_domain... ausgeben sondern mit Hilfe von Flag leeres Feld
$domain = "no_domain$count" unless $domain;
$count++;
$table_data->{$ftpuser}{'has_domain'} = $domain if $has_domain;
$table_data->{$ftpuser}{'domain'} = $domain;
$table_data->{$ftpuser}{'ftpuser'} = $ftpuser;
$table_data->{$ftpuser}{'gecos'} = $passwd{$ftpuser}{'gecos'};
$table_data->{$ftpuser}{'home_tooltip'} = $passwd{$ftpuser}{'home'};
$table_data->{$ftpuser}{'home'} = easytecc3::substr_e4($passwd{$ftpuser}{'home'});
$table_data->{$ftpuser}{'ftpquota_MB'} = $ftpquota_sized;
$table_data->{$ftpuser}{'ftpquota_used_MB'} = easytecc3::getsize($quota{$ftpuser}{'use'});
$table_data->{$ftpuser}{'ftpquota_used_percent'} = $quota{$ftpuser}{'use'} > 0 ? sprintf("%.0f",($quota{$ftpuser}{'use'} / $quota{$ftpuser}{'quota'}) * 100) : '0';
$table_data->{$ftpuser}{'alert_ftpuser_quota'} = easytecc3::quota_alert($quota{$ftpuser}{'quota'}, $quota{$ftpuser}{'use'}, '.8');
$table_data->{$ftpuser}{'show_edit_ftp'} = $show_edit_ftp;
my @keys = ('FTPUSER',$ftpuser);
my $note = note_from_hashfile(\@keys);
if($note->{title}){
$table_data->{$ftpuser}{'note_title'} = $note->{title};
$table_data->{$ftpuser}{'note_text'} = $note->{text};
}
if ($ftpuser !~ /^(admin|cyrus|dovecot|dovenull|mysql|pgsql|virtmail|svn|haproxy)$/ && $ftpuser ne $session->param('user') && $show_edit_ftp eq '1') {
$table_data->{$ftpuser}{'icon_delete_ftpuser'} = 1;
}
}
easytecc3::table_e4($template, $table_data, 'table_tr_show_ftpuser_template.html');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_adminuser{
if($session->param('user') ne 'admin'){
return start();
}
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_adminuser.html');
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my %admin_domains;
my %full_admin_domains;
foreach my $domain(keys %domains){
my @admins = split(/[\s,]+/, $domains{$domain}{'admin_users'});
foreach my $admin (@admins){
my $domainlist = $admin_domains{lc($admin)};
if($domainlist ne ''){
$domainlist .= ', ';
}
$domain = encode('utf-8', domain_to_unicode($domain));
$domain =~ s/^www\.//;
$domainlist .= $domain;
# want this for tooltip
$full_admin_domains{lc($admin)} = $domainlist;
if(length($domainlist) > 23){
$domainlist = substr($domainlist,0,20) . '...';
}
$admin_domains{lc($admin)} = $domainlist;
}
}
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my %home_lookup = %{$passwd->lookup2_hash()};
my ($quotaref, $sum_ftplimit, $sum_ftpuse, $ftpserverlimit) = easytecc3::getquota_ftp();
my %quota = %$quotaref;
#Zähler für Tabelle wenn es zu FTP-User keine Domain gibt, z.B. alle Systemuser
my $count = 1;
my @ftp_user = ();
my $table_data = {};
foreach my $ftpuser (sort keys %passwd){
next if $passwd{$ftpuser}{'gecos'} !~ /^CUST/;
my $ftpquota = '';
my $ftpquota_sized = '';
my $ftpused = '';
my $quotabalken = '';
my $domain = '';
my $has_domain = '';
$ftpquota = $quota{$ftpuser}{'quota'};
$ftpquota_sized = easytecc3::getsize($ftpquota);
$ftpused = $quota{$ftpuser}{'use'};
logline("debug","ftpuser=$ftpuser\tftpused=$ftpused");
next unless $ftpused;
next if $passwd{$ftpuser}{'gecos'} =~ /- POP/;
$quotabalken = easytecc3::quotabar($ftpquota, $ftpused, 'table');
#if($admin_users{$ftpuser} ne $ftpuser){
# next;
#}
$table_data->{$ftpuser}{'is_admin_user'} = '1';
if(exists $admin_domains{$ftpuser}){
$domain .= $admin_domains{$ftpuser} . '<br />';
$has_domain = 1;
}
#wenn keiner domain zugeordnet, dann nicht no_domain... ausgeben sondern mit Hilfe von Flag leeres Feld
$domain = "no_domain$count" unless $domain;
$count++;
$table_data->{$ftpuser}{'has_domain'} = $domain if $has_domain;
$table_data->{$ftpuser}{'domain_tooltip'} = $full_admin_domains{$ftpuser};
$table_data->{$ftpuser}{'domain'} = $domain;
$table_data->{$ftpuser}{'idn_domain'} = $domain;
$table_data->{$ftpuser}{'ftpuser'} = $ftpuser;
$table_data->{$ftpuser}{'gecos'} = $passwd{$ftpuser}{'gecos'};
$table_data->{$ftpuser}{'home_tooltip'} = $passwd{$ftpuser}{'home'};
$table_data->{$ftpuser}{'home'} = easytecc3::substr_e4($passwd{$ftpuser}{'home'});
$table_data->{$ftpuser}{'ftpquota_MB'} = $ftpquota_sized;
$table_data->{$ftpuser}{'ftpquota_used_MB'} = easytecc3::getsize($quota{$ftpuser}{'use'});
$table_data->{$ftpuser}{'ftpquota_used_percent'} = $quota{$ftpuser}{'use'} > 0 ? sprintf("%.0f",($quota{$ftpuser}{'use'} / $quota{$ftpuser}{'quota'}) * 100) : '0';
$table_data->{$ftpuser}{'alert_ftpuser_quota'} = easytecc3::quota_alert($quota{$ftpuser}{'quota'}, $quota{$ftpuser}{'use'}, '.8');
my @keys = ('ADMINUSER',$ftpuser);
my $note = note_from_hashfile(\@keys);
if($note->{title}){
$table_data->{$ftpuser}{'note_title'} = $note->{title};
$table_data->{$ftpuser}{'note_text'} = $note->{text};
}
if ($ftpuser !~ /^(admin|cyrus|dovecot|dovenull|mysql|pgsql|virtmail|svn|haproxy)$/) {
$table_data->{$ftpuser}{'icon_delete_ftpuser'} = 1;
}
}
if(length($input{'adminuser'}) > 0 && $passwd{$input{'adminuser'}}{'gecos'} =~ /^CUST/){
$template->param('adminuser' => $input{'adminuser'});
my $ftp_table_data = {};
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my %config = %{$httpd_conf->config_hash()};
if (easytecc3::extern_mx() || $fb){
$mailpasswd = easytecc3::get_mailpasswd();
%mailpasswd = %{$mailpasswd->file_parsed_hash()};
#%mailpasswd = %{easytecc3::get_mailpasswd()};
($mailquotaref, $sum_maillimit, $sum_mailuse, $mailserverlimit) = easytecc3::getquota_mail(\%mailpasswd);
logline("debug","show_quota mailquotaref=$mailquotaref");
%mailquota = %$mailquotaref;
}
else{
%mailpasswd = %passwd;
%mailquota = %quota;
$sum_maillimit = $sum_ftplimit;
$sum_mailuse = $sum_ftpuse;
$mailserverlimit = $ftpserverlimit;
}
my($active_user_chars_ref, $active_domain_chars_ref, $active_users_ref, $active_domains_ref) = easytecc3::get_userchars();
my %active_users = %$active_users_ref;
my %active_domains = %$active_domains_ref;
my %domain_home;
my %allowed_domains;
my $domain_table_data = {};
foreach my $domain (sort keys %domains){
# filter domains
my $admins = $domains{$domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $input{'adminuser'} . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
foreach my $alias_domain (@{$domains{$domain}{'domains'}}){
$alias_domain =~ s/^www\.//;
$alias_domain =~ s/^\*\.//;
$allowed_domains{$alias_domain} = 1;
logline("debug","allowed_domain:$alias_domain");
}
my $sanitized_domain = $domain;
$sanitized_domain =~ s/^www\.//;
$sanitized_domain =~ s/^\*\.//;
$allowed_domains{$sanitized_domain} = 1;
logline("debug","domain_home=" . $domains{$domain}{'droot'});
logline("debug","domain_domains=" . $domains{$domain}{'domains'});
$domain_home{$domains{$domain}{'droot'}} = $domains{$domain}{'domains'};
$domain_table_data->{$domain}{'show_edit'} = '1';
$domain_table_data->{$domain}{'show_delete'} = '1';
my $ftpuser = '';
my $ftpquota = '';
my $ftpquota_sized = '';
my $ftpused = '';
my $quotabalken = '';
my $ssl = '';
my $ip = '';
my $domain_ohne_www = $domain;
$domain_ohne_www =~ s/^www\.//;
if(exists $home_lookup{$domains{$domain}{'droot'}}){
$ftpuser = $home_lookup{$domains{$domain}{'droot'}};
$ftpquota = $quota{$ftpuser}{'quota'};
$ftpquota_sized = easytecc3::getsize($ftpquota);
$ftpused = $quota{$ftpuser}{'use'};
$quotabalken = easytecc3::quotabar($ftpquota, $ftpused);
}
logline("debug","$domain ssl_enabled=" . $config{'ssl_enabled'} . 'ssl=' . $domains{$domain}{'ssl'});
# wenn SSL-Domain, dann Icon in vHost-Liste
if($config{'ssl_enabled'} && $domains{$domain}{'ssl'}){
$ssl = 1;
}
# wenn separate IP, dann ebenfalls Icon
if($config{'main_ip'} ne $domains{$domain}{'ip'}){
$ip = $domains{$domain}{'ip'};
}
logline("debug","show_vhosts_domain=" . $domain);
$domain_table_data->{$domain}{'idn_domain_no_www'} = encode('utf-8', domain_to_unicode($domain_ohne_www));
$domain_table_data->{$domain}{'domain'} = $domain;
$domain_table_data->{$domain}{'idn_domain'} = encode('utf-8', domain_to_unicode($domain));
$domain_table_data->{$domain}{'ssl'} = $ssl;
$domain_table_data->{$domain}{'ip'} = $ip;
#$table_data->{$domain}{'droot'} = $domains{$domain}{'droot'};
$domain_table_data->{$domain}{'droot'} = easytecc3::substr_e4($domains{$domain}{'droot'});
$domain_table_data->{$domain}{'droot_tooltip'} = $domains{$domain}{'droot'};
if(-d $domains{$domain}{'droot'}){
$domain_table_data->{$domain}{'dir_encoded'} = encode_base64url($domains{$domain}{'droot'});
}
$domain_table_data->{$domain}{'pop'} = $domains{$domain}{'pop'};
$domain_table_data->{$domain}{'for'} = $domains{$domain}{'for'};
$domain_table_data->{$domain}{'aut'} = $domains{$domain}{'aut'};
# $table_data->{$domain}{'quota'} = $domains{$domain}{'quota'};
# show units
$domain_table_data->{$domain}{'quota'} = easytecc3::getsize($domains{$domain}{'quota'} * 1024);
$domain_table_data->{$domain}{'statslink'} = $domains{$domain}{'statslink'};
$domain_table_data->{$domain}{'custom_tag'} = $domains{$domain}{'custom_tag'};
$domain_table_data->{$domain}{'admin_users'} = $domains{$domain}{'admin_users'};
$domain_table_data->{$domain}{'hide_note'} = 1;
}
easytecc3::table_e4($template, $domain_table_data, 'table_tr_show_vhosts_template.html');
foreach my $ftpuser (sort keys %passwd){
# do NOT show system users here
next if $ftpuser eq 'ftp';
next if $ftpuser eq 'cyrus';
next if $ftpuser eq 'dovecot';
next if $ftpuser eq 'dovenull';
next if $ftpuser eq 'virtmail';
next if $ftpuser eq 'svn';
next if $ftpuser eq 'haproxy';
my $ftpquota = '';
my $ftpquota_sized = '';
my $ftpused = '';
my $quotabalken = '';
my $domain = '';
logline("debug","foreach ftpuser = $ftpuser");
$ftpquota = $quota{$ftpuser}{'quota'};
$ftpquota_sized = easytecc3::getsize($ftpquota);
$ftpused = $quota{$ftpuser}{'use'};
next unless $ftpused;
next if $passwd{$ftpuser}{'gecos'} =~ /- POP/;
#$quotabalken = easytecc3::quotabar($ftpquota, $ftpused, 'used');
my @domainlist = ();
if(exists $domain_home{$passwd{$ftpuser}{'home'}}){
foreach(@{$domain_home{$passwd{$ftpuser}{'home'}}}){
push @domainlist, encode('utf-8', domain_to_unicode($_));
}
$domain = join '<br />', @domainlist;
} else {
my $home = $passwd{$ftpuser}{'home'};
my $self_home = $passwd{$input{'adminuser'}}{'home'};
my $allowed = 0;
if($home ne $self_home && $home !~ m#^$self_home/#){
foreach my $dir (keys %domain_home){
if($home eq $dir || $home =~ m#^$dir/#){
$allowed = '1';
}
}
if($allowed != 1){
next;
}
}
}
$ftp_table_data->{$ftpuser}{'alert_ftpuser_quota'} = easytecc3::quota_alert($ftpquota, $ftpused, '.8');
$ftp_table_data->{$ftpuser}{'ftpuser'} = $ftpuser;
$ftp_table_data->{$ftpuser}{'domain'} = $domain;
$ftp_table_data->{$ftpuser}{'gecos'} = $passwd{$ftpuser}{'gecos'};
$ftp_table_data->{$ftpuser}{'home_tooltip'} = $passwd{$ftpuser}{'home'};
$ftp_table_data->{$ftpuser}{'home'} = easytecc3::substr_e4($passwd{$ftpuser}{'home'});
$ftp_table_data->{$ftpuser}{'ftpquota_sized'} = $ftpquota_sized;
$ftp_table_data->{$ftpuser}{'ftpquota_used_sized'} = easytecc3::getsize($ftpused);
$ftp_table_data->{$ftpuser}{'ftpquota_used_percent'} = sprintf("%.0f", ($ftpused/$ftpquota)*100) if $ftpquota > 0;
$ftp_table_data->{$ftpuser}{'show_ftp'} = '1';
$ftp_table_data->{$ftpuser}{'show_edit_ftp'} = '1';
}
#easytecc3::table(\$template,'<td>L__User__L</td><td>L__Domain__L</td><td>L__Beschreibung__L</td><td>L__Homeverzeichnis__L</td><td>L__FTP-Quota__L</td><td>L__Quotanutzung__L</td><td>L__Aktionen__L</td>', \@ftp_user, 'table_ftpuser');
easytecc3::table_e4($template, $ftp_table_data, 'table_tr_show_quota_ftpuser_template.html');
my $mail_table_data = {};
foreach my $mailuser (sort keys %mailpasswd){
next if ($mailpasswd{$mailuser}{'gecos'} !~ / - POP$/ && $mailuser ne 'admin');
#wenn kein externer mailserver muss admin nicht bei popusern auftauchen
next if( ! easytecc3::extern_mx() && $mailuser eq 'admin');
logline("debug","foreach POP mailpasswd = $mailuser");
my $domain = $mailpasswd{$mailuser}{'gecos'};
$domain =~ s/ - POP$//;
logline("debug","mailuser $mailuser domain: #$domain#");
my $admins = $domains{'www.' . $domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $input{'adminuser'} . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
delete $active_users{$mailuser};
next;
}
my $mailquota_sized = $mailquota{$mailuser}{'quota'} / 1024;
#my $quotabalken = easytecc3::quotabar($mailquota{$user}{'quota'}, $mailquota{$user}{'use'}, 'used');
my $change_mailuser = '';
if ($fb) {
$change_mailuser = qq~<a href='/cgi-bin/easytecc3/index.pl?action=change_forward&domain=www.$domain'>L__Editieren__L</a>~
}
else{
$change_mailuser = qq~<a href='/cgi-bin/easytecc3/index.pl?action=change_popuser&domain=www.$domain'>L__Editieren__L</a>~
}
my $idn_mailuser = encode('utf-8', email_to_unicode($mailuser));
logline("debug","#$mailuser#$idn_mailuser#");
my $idn_domain = encode('utf-8', domain_to_unicode($domain));
$mail_table_data->{$idn_mailuser}{'alert_mailuser_quota'} = easytecc3::quota_alert($mailquota{$mailuser}{'quota'}, $mailquota{$mailuser}{'use'}, '.8');
$mail_table_data->{$idn_mailuser}{'mailuser'} = $mailuser;
$mail_table_data->{$idn_mailuser}{'idn_mailuser'} = $idn_mailuser;
$mail_table_data->{$idn_mailuser}{'domain'} = $idn_domain;
$mail_table_data->{$idn_mailuser}{'idn_domain'} = $idn_domain;
$mail_table_data->{$idn_mailuser}{'domain_www'} = 'www.' . $domain;
$mail_table_data->{$idn_mailuser}{'gecos'} = $mailpasswd{$mailuser}{'gecos'};
$mail_table_data->{$idn_mailuser}{'mailquota_sized'} = easytecc3::getsize($mailquota{$mailuser}{'quota'});
$mail_table_data->{$idn_mailuser}{'mailquota_used_sized'} = easytecc3::getsize($mailquota{$mailuser}{'use'});
$mail_table_data->{$idn_mailuser}{'mailquota_used_percent'} = sprintf("%.0f", ($mailquota{$mailuser}{'use'}/$mailquota{$mailuser}{'quota'})*100) if $mailquota{$mailuser}{'quota'} > 0;
$mail_table_data->{$idn_mailuser}{'show_email'} = '1';
$mail_table_data->{$idn_mailuser}{'show_edit_email'} = '1';
my @keys = ('EMAILUSER',$mailuser);
my $note = note_from_hashfile(\@keys);
if($note->{title}){
$mail_table_data->{$idn_mailuser}{'note_title'} = $note->{title};
$mail_table_data->{$idn_mailuser}{'note_text'} = $note->{text};
}
#push(@user, $user.'|'.domain_to_unicode($domain).'|'.qq~$mailquota_sized MB~.'|'.qq~$quotabalken~.'|'.$change_mailuser);
}
#easytecc3::table(\$template,'<td>L__User__L</td><td>L__Domain__L</td><td>L__E-Mail-Quota__L</td><td>L__Quotanutzung__L</td><td colspan="3">L__Aktionen__L</td>', \@user, 'table_mailuser');
easytecc3::table_e4($template, $mail_table_data, 'table_tr_show_quota_mailuser_template.html');
my @special_spamfilter = ();
foreach $domain (sort keys %active_domains){
$domain = ascii_domain($domain);
$domain =~ s/^www\.//;
$domain =~ s/^\*\.//;
if(!exists $allowed_domains{$domain}){
delete $active_domains{$domain};
}
}
my $spam_table_data = {};
foreach(sort keys %active_users){
if(/^$input{'ulist'}/ || $input{'ulist'} eq 'all'){
push(@special_spamfilter, $_ . '|' . qq~<a href='/cgi-bin/easytecc3/index.pl?action=change_special_spamfilter&user=$_'>L__Editieren__L</a><br /><a href='/cgi-bin/easytecc3/index.pl?action=delete_special_spamfilter&spam_user_domain=$_'>L__Löschen__L</a>~);
my $idn_mailuser = encode('utf-8', email_to_unicode($_));
$spam_table_data->{$idn_mailuser}{'special_spam_user_domain'} = $_;
$spam_table_data->{$idn_mailuser}{'special_spam_idn_user_domain'} = $idn_mailuser;
$spam_table_data->{$idn_mailuser}{'hide_note'} = 1;
}
}
foreach(sort keys %active_domains){
if(/^$input{'dlist'}/ || $input{'dlist'} eq 'all'){
push(@special_spamfilter, $_ . '|' . qq~<a href="/cgi-bin/easytecc3/index.pl?action=change_special_spamfilter&domain=~ . ascii_domain($_) . qq~">L__Editieren__L</a><br /><a href="/cgi-bin/easytecc3/index.pl?action=delete_special_spamfilter&spam_user_domain=~ . ascii_domain($_) . qq~">L__Löschen__L</a>~);
my $idn_domain = encode('utf-8', domain_to_unicode($_));
$spam_table_data->{$idn_domain}{'special_spam_user_domain'} = encode('utf-8',ascii_domain($_));
$spam_table_data->{$idn_domain}{'special_spam_idn_user_domain'} = $idn_domain;
$spam_table_data->{$idn_domain}{'hide_note'} = 1;
}
}
#easytecc3::table(\$template,'<td>L__User/Domain__L</td><td colspan="6">L__Aktionen__L</td>', \@special_spamfilter, 'special_spamfilter');
easytecc3::table_e4($template, $spam_table_data, 'table_tr_show_special_spamfilter_template.html');
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my %logs;
my @logs = ();
if ($fb) {
@logs = `/usr/iports/bin/sudo /usr/sbin/dellogs`;
}
else{
@logs = `/usr/sbin/dellogs`;
}
#actually no maillog download for external mailservers
my $extern_mx = easytecc3::extern_mx();
my @logfiles = ();
my $all_logs_size = '';
my $quotabalken = '';
my $quota = `cat /etc/vsd/quota`;
chomp $quota;
my $domain_tmp = '';
my @syslog = ();
my %sorted_logs;
my $table_data_domainlog = {};
foreach(@logs){
last if /^Geben Sie/;
next if /^-/;
next if /^$/;
next if /^dellogs/;
next if /(Domainname|Alle|Systemlogs)/;
my ($domain, $logfile, $size) = split /\|/, $_;
$domain =~ s/\s//gc;
# in Zeile für errorlog taucht keine Domain auf, bei so einer Zeile einfach die zuletzt gespeicherte Domain nehmen
# hostnet.de | speedlog | 1.00 MB
# | error_log_hostnet.de | 8.00 kB
$domain_tmp = $domain if $domain;
$logfile =~ s/^\s+//;
$logfile =~ s/\s+$//;
$size =~ s/^\s+(.*)\s+$/$1/gc;
my $admins = $domains{'www.' . $domain_tmp}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $input{'adminuser'} . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
#use logfile name from httpd.conf instead dellogs
if ($logfile =~ /^access_log/ && length($domains{"www.$domain"}{'access_log'})) {
$logfile = $domains{"www.$domain"}{'access_log'};
$logfile =~ s/^.*\///;
$sorted_logs{$domain}{'access'} = $logfile;
$sorted_logs{$domain}{'access_size'} = $size;
}
elsif ($logfile =~ /^error_log/ && length($domains{"www.$domain_tmp"}{'error_log'})) {
$logfile = $domains{"www.$domain_tmp"}{'error_log'};
$logfile =~ s/^.*\///;
$sorted_logs{$domain_tmp}{'error'} = $logfile;
$sorted_logs{$domain_tmp}{'error_size'} = $size;
}
#else{
#$sorted_logs{$domain_tmp}{'error'} = $logfile;
# $sorted_logs{$domain_tmp}{'error_size'} = $size;
#}
if($logfile =~ /^(Access Logs|Error Logs|Messages|Maillogs)/){
$size =~ /^(.*)\s(.*)$/;
# Grösse kann in kB oder MB angegeben werden, alles auf MB umrechnen und summieren
my $size_unscaled = $1;
my $scale = $2;
$size_unscaled = $size_unscaled/1024 if $scale eq 'kB';
$all_logs_size += $size_unscaled;
}
}
foreach(sort keys %sorted_logs){
my $domain = $_;
if($sorted_logs{$_}{'access'}){
my $logfile = $sorted_logs{$_}{'access'};
$table_data_domainlog->{$domain}{'deleteable'} = '1';
$table_data_domainlog->{$domain}{'idn_domain'} = encode('utf-8', domain_to_unicode($domain));
$table_data_domainlog->{$domain}{'domain'} = $domain;
$table_data_domainlog->{$domain}{'logfile_name'} = $sorted_logs{$_}{'access'};
$table_data_domainlog->{$domain}{'logfile_size_sized'} = $sorted_logs{$_}{'access_size'};
my $logfile_encoded = encode_base64url($logfile);
$table_data_domainlog->{$domain}{'logfile_href_download'} = qq~/cgi-bin/easytecc4/index.pl?action=download_file&file=$logfile_encoded&type=logfile~;
#push(@logfiles, domain_to_unicode($_).'|'.$sorted_logs{$_}{'access'}.'|'.$sorted_logs{$_}{'access_size'}.'|'.
# qq~<a href="/cgi-bin/easytecc3/index.pl?action=download_file&file=$logfile&type=logfile">L__Download__L</a>~ .'|'.
# qq~<a href="/cgi-bin/easytecc3/index.pl?action=delete_logfiles&domain=$domain">L__Löschen__L</a>~
#);
}
if($sorted_logs{$_}{'error'}){
my $logfile = $sorted_logs{$_}{'error'};
#'z' is ugly workaround for sorted access and error log output. Nobody has seen it ;)
$table_data_domainlog->{$domain . 'z'}{'logfile_name'} = $sorted_logs{$_}{'error'};
$table_data_domainlog->{$domain . 'z'}{'logfile_size_sized'} = $sorted_logs{$_}{'error_size'};
my $logfile_encoded = encode_base64url($logfile);
$table_data_domainlog->{$domain . 'z'}{'logfile_href_download'} = qq~/cgi-bin/easytecc4/index.pl?action=download_file&file=$logfile_encoded&type=logfile~;
#push(@logfiles, ''.'|'.$sorted_logs{$_}{'error'}.'|'.$sorted_logs{$_}{'error_size'}.'|'.
# qq~<a href="/cgi-bin/easytecc3/index.pl?action=download_file&file=$logfile&type=logfile">L__Download__L</a>~ .'|'.
# ''
#);
}
}
#push(@logfiles, @syslog);
my $percentval = ($all_logs_size/$quota)*100;
##kaufm. Rundung
$percentval = sprintf("%.0f", $percentval);
my $balken_usage = $percentval;
my $balken_free = 100 - $balken_usage;
if(($quota * .8) <= $all_logs_size){
$template->param('logfile_size_alert' => 1);
# $quotabalken = qq|<img src="/easytecc3/images/red.gif" width="$balken_usage" height="15" align="bottom" alt="$balken_usage % genutzt" border="0" /><img src="/easytecc3/images/grey.gif" width="$balken_free" height="15" align="bottom" alt="$balken_free % frei" border="0" />|;
}
#else{
# $quotabalken = qq|<img src="/easytecc3/images/green.gif" width="$balken_usage" height="15" align="bottom" alt="$balken_usage % genutzt" border="0" /><img src="/easytecc3/images/grey.gif" width="$balken_free" height="15" align="bottom" alt="$balken_free % frei" border="0" />|;
#}
$template->param('in_use_MB' => sprintf "%.2f", $all_logs_size);
$template->param('percent' => ' (' . $percentval . '%)');
#$template->param('bar' => $quotabalken);
#easytecc3::table(\$template,'<td>L__Domainname__L</td><td>L__Logfile__L</td><td>L__Größe__L</td><td colspan="4">L__Aktionen__L</td>', \@logfiles, 'table1');
easytecc3::table_e4($template, $table_data_domainlog, 'table_tr_show_logfiles_domain_template.html');
my @db = ();
my $html_error = '';
my ($dbh, $mysql_connect_error) = easytecc3::mysql_connect();
# Grsse der Datenbanken ermitteln, von der Funktion wird auch datadir übermittelt. kann man vielleicht noch mal brauchen
my (%database_size, $datadir) = easytecc3::get_size_mysql();
# seems to be a dummy.
my $grant_ok = '1';
my $query = 'SHOW databases';
my @user = ();
# gather allowed dirs
my %allowed_dirs;
foreach my $domain (keys %domains){
my $admins = $domains{$domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $input{'adminuser'} . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
$allowed_dirs{$domains{$domain}{'droot'}} = '1';
my $doc_root_alias = $domains{$domain}{'droot'};
$doc_root_alias =~ s#/apache24/noexec/#/apache24/data/#;
$allowed_dirs{$doc_root_alias} = '1';
}
$allowed_dirs{$passwd{$input{'adminuser'}}{'home'}} = '1';
foreach my $user(sort keys %passwd){
# chown nicht an POP-User ermöglichen
next if $passwd{$user}{'gecos'} =~ / - POP/;
my $home = $passwd{$user}{'home'};
foreach my $dir (keys %allowed_dirs){
if($home eq $dir || $home =~ m#^$dir/#){
push(@user,$user);
}
}
}
my $userlist = '\'' . join('\',\'', @user) . '\'';
$query = "SHOW DATABASES WHERE `Database` IN (SELECT DISTINCT Db AS `Database` FROM mysql.db WHERE User IN ($userlist))";
my $sth = $dbh->prepare( $query );
$sth->execute;
my $db_table_data = {};
while ( my @row = $sth->fetchrow_array ){ # alle rows auslesen
foreach my $item (@row){
next if $item eq 'information_schema';
# Datenbanken mit . sind Sicherungen von getback auf die kein Zugriff ber mysql-Schnittstelle mglich ist
# und daher auch kein Backup gemacht werden kann.
#next if $item =~ /\./;
# wenn show databases DB mysql oder db01 anzeigt, gehen wir davon aus, da Rechte des Users der Sicherungen durchfhrt ok sind
# ansonsten Formular für mysqluser anzeigen
$grant_ok = '1' if $item eq 'mysql';
$grant_ok = '1' if $item eq 'db01';
# berprüfen ob Backup angelegt
my $backup = "Ja";
my $backup_config = "/usr/local/etc/easytecc/mysqlbackup/$item.dbb";
my $backup_dir = "$mysqlbackup_dir/$item";
my @dir_entries = ();
my $in_use_for_backup = '';
my $backup_has_error = '0';
my $backup_has_lock = '0';
my $backup_count = '0';
if (-d $backup_dir){
opendir(D,$backup_dir) || dienice("opendir $backup_dir: $!");
@dir_entries = grep !/^\.\.?$/, readdir(D); #read in dir entries to array
closedir D;
#$backup_has_lock = 1 if (grep /\.lock$/, @dir_entries);
foreach my $error_file(@dir_entries){
logline("warning","error_file1=$error_file item=$item");
$backup_has_lock = 1 if ($error_file =~ /\.lock$/);
next if $error_file !~ /^(.*)\.error$/;
my $name_of_backup = $1;
logline("warning","error_file2=$error_file");
$backup_has_error = 1;
my $error_text = `cat $backup_dir/$error_file`;
my $error_template = HTML::Template->new(filename => 'error_div.html');
$error_template->param('alert_has_close_action' => 'alert_has_close_action');
$error_template->param('alert_close_action' => "exec_delete_alert&database=$item&error=$error_file");
$error_template->param('error_text' => qq~$item Backup $name_of_backup: $error_text~);
$html_error .= $error_template->output;
}
$backup_count = scalar(@dir_entries) - $backup_has_lock - $backup_has_error;
if($backup_count > 0){
$in_use_for_backup = `du -s $backup_dir` unless $fb;
$in_use_for_backup = `/usr/iports/bin/sudo /usr/bin/du -As $backup_dir` if $fb;
$in_use_for_backup = easytecc3::getsize($in_use_for_backup);
}
}
# kein automatisches Backup und keine Dumps
if ( ! -e $backup_config && $backup_count == '0'){
$db_table_data->{$item}{'db_name'} = $item;
$db_table_data->{$item}{'db_size_sized'} = easytecc3::getsize($database_size{$item});
$db_table_data->{$item}{'edit_db'} = 1;
#$backup = "L__Nein__L";
#push(@db, $item . '|' .
#easytecc3::getsize($database_size{$item}) . '|' .
#$backup . '|' .
#$in_use_for_backup . '|' .
#qq~<a href="/cgi-bin/easytecc3/index.pl?action=show_mysqlbackup_details&database=$item">L__Backup anlegen__L</a><br />~);
}
# kein automatisches Backup aber Dumps vorhanden
elsif ( ! -e $backup_config && $backup_count > 0){
$db_table_data->{$item}{'has_dbbackup'} = 1;
$db_table_data->{$item}{'db_name'} = $item;
$db_table_data->{$item}{'db_size_sized'} = easytecc3::getsize($database_size{$item});
$db_table_data->{$item}{'dbbackup_size_sized'} = $in_use_for_backup;
$db_table_data->{$item}{'dbbackup_count'} = $backup_count;
$db_table_data->{$item}{'edit_db'} = 1;
#$backup = "L__Nein__L";
#push(@db, $item . '|' .
#easytecc3::getsize($database_size{$item}) . '|' .
#$backup . '|' .
#$in_use_for_backup . '|' .
#qq~<a href="/cgi-bin/easytecc3/index.pl?action=show_mysqlbackup_details&database=$item">L__Details__L</a><br />~);
}
# automatischs Backup ist vorhanden
else{
$db_table_data->{$item}{'db_has_auto_backup'} = 1;
$db_table_data->{$item}{'has_dbbackup'} = 1;
$db_table_data->{$item}{'db_name'} = $item;
$db_table_data->{$item}{'db_size_sized'} = easytecc3::getsize($database_size{$item});
$db_table_data->{$item}{'dbbackup_size_sized'} = $in_use_for_backup;
$db_table_data->{$item}{'dbbackup_count'} = $backup_count;
$db_table_data->{$item}{'edit_db'} = 1;
#$backup = "L__Ja__L";
#push(@db, $item . '|' .
#easytecc3::getsize($database_size{$item}) . '|' .
#$backup . '|' .
#$in_use_for_backup . '|' .
#qq~<a href="/cgi-bin/easytecc3/index.pl?action=show_mysqlbackup_details&database=$item">L__Details__L</a>~);
}
$db_table_data->{$item}{'hide_note'} = 1;
}
}
easytecc3::table_e4($template, $db_table_data, 'table_tr_show_dbbackup_template.html');
logline("debug","Creating File Object \$cronfile.");
my $cronfile = file->new({file_name => '/home/web/cronfile'});
$cronfile->read_file;
my %cronjobs = %{$cronfile->file_parsed_hash()};
my $cron_table_data = {};
foreach my $cronjob (sort keys %cronjobs){
next if $cronjobs{$cronjob}{'job'} =~ /easytecc4\/dobackup\.pl/;
next if $cronjobs{$cronjob}{'job'} =~ /tools\/awstats_updateall\.pl/;
# check dirs
my $allowed = 0;
foreach my $dir (keys %allowed_dirs){
if($cronjobs{$cronjob}{'job'} =~ m#$dir/#){
# check if other dirs are affected
my $job = $cronjobs{$cronjob}{'job'};
$job =~ s#$dir/##;
if($job !~ m#/home/# && $job !~ m#(/usr/local/www/|/home/httpd/docs/)#){
$allowed = 1;
last;
}
}
# check domains
if($allowed == 0){
foreach my $domain (keys %allowed_domains){
if($cronjobs{$cronjob}{'job'} =~ m#(ftp|http)s?://(www\.)?$domain/#){
$allowed = 1;
last;
}
}
}
}
if($allowed != 1){
next;
}
my $cronjob_string_no_dev_null = $cronjobs{$cronjob}{'job'};
$cronjob_string_no_dev_null =~ s/(1|2)>.*$//;
$cron_table_data->{$cronjob}{'cronjob'} = $cronjobs{$cronjob}{'count'};
$cron_table_data->{$cronjob}{'cron_command_tooltip'} = $cronjobs{$cronjob}{'job'};
#$table_data->{$cronjob}{'cron_command'} = easytecc3::substr_e4($cronjobs{$cronjob}{'job'});
$cron_table_data->{$cronjob}{'cron_command'} = easytecc3::substr_e4($cronjob_string_no_dev_null);
$cron_table_data->{$cronjob}{'cron_minute'} = $cronjobs{$cronjob}{'min'};
$cron_table_data->{$cronjob}{'cron_hour'} = $cronjobs{$cronjob}{'std'};
$cron_table_data->{$cronjob}{'cron_day'} = $cronjobs{$cronjob}{'mday'};
$cron_table_data->{$cronjob}{'cron_month'} = $cronjobs{$cronjob}{'mon'};
$cron_table_data->{$cronjob}{'cron_weekday'} = $cronjobs{$cronjob}{'wday'};
$cron_table_data->{$cronjob}{'edit_cron'} = 1;
$cron_table_data->{$cronjob}{'new_cron'} = 0;
#push(@cronjobs, $cronjobs{$cronjob}{'job'} . '|' .
#$cronjobs{$cronjob}{'min'} . '|' .
#$cronjobs{$cronjob}{'std'} . '|' .
#$cronjobs{$cronjob}{'mday'} . '|' .
#$cronjobs{$cronjob}{'mon'} . '|' .
#$cronjobs{$cronjob}{'wday'} . '|' .
#qq~<a href="/cgi-bin/easytecc3/index.pl?action=change_cronjob&cronjob=$cronjobs{$cronjob}{'count'}">L__Editieren__L</a> ~ .
#qq~<a href="/cgi-bin/easytecc3/index.pl?action=delete_cronjob&cronjob=$cronjobs{$cronjob}{'count'}">L__Löschen__L</a>~);
}
easytecc3::table_e4($template, $cron_table_data, 'table_tr_show_cronjobs_template.html');
}
easytecc3::table_e4($template, $table_data, 'table_tr_show_adminuser_template.html');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_quota{
if($session->param('show_quota') ne '1'){
return start();
}
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_quota.html');
my $type = $input{'type'};
my @serverquota = ();
my %mailpasswd = ();
my %mailquota = ();
my ($mailquotaref, $sum_maillimit, $sum_mailuse, $mailserverlimit);
my $zpool_size_MB;
my $zfs_disk_freespace_MB;
my $zfs_disk_usage_MB;
my $alert_diskspace = '';
my $df_used_in_KB = 0;
my $df_available_in_KB = 0;;
my $disk_freespace_MB = 0;;
my $disk_usage_MB = 0;
if($session->param('user') eq 'admin'){
if ( $fb eq '1' ) {
logline("debug","DISK SPACE ALLOCATION check: is XEN server");
my $is_xen_server = `/bin/sh -c '/sbin/sysctl kern.vm_guest 2>/dev/null'`;
chomp($is_xen_server);
logline("debug","DISK SPACE ALLOCATION check: ###$is_xen_server###");
if ( $is_xen_server =~ m/xen/ ) {
logline("debug","DISK SPACE ALLOCATION for ZFS starts now ... on XEN");
#my $zfs_available = `/sbin/zfs list -Hp -oavail vsd`;
my $zfs_available = `/bin/sh -c '/sbin/zfs list -Hp -oavail vsd 2> /dev/null'`;
logline("debug","\$zfs_available = $zfs_available eq '' ");
$zfs_disk_freespace_MB = $zfs_available / 1048576;
$disk_freespace_MB = $zfs_disk_freespace_MB;
#my $zpool_size = `/sbin/zpool list -Hp -osize vsd`;
my $zpool_size = `/bin/sh -c '/sbin/zpool list -Hp -osize vsd 2> /dev/null'`;
$zpool_size_MB = $zpool_size / 1048576;
$zfs_disk_usage_MB = $zpool_size_MB - $zfs_disk_freespace_MB;
$disk_usage_MB = $zfs_disk_usage_MB;
### Mario: bei 80% Ausnutzung soll die Zeile ROT sein! ###
#my $disk_emptyspace = ( $zfs_available * 100 ) / $zpool_size;
#my $disk_comsumption = 100 - $disk_emptyspace;
#if ( $disk_comsumption gt 80 ) {
#
# #$template->param('alert_diskspace' => easytecc3::quota_alert($ftpserverlimit, $sum_ftpuse, '.8'));
#}
$template->param('alert_diskspace' => easytecc3::quota_alert($zpool_size, $zpool_size - $zfs_available, '.8'));
logline("debug","\$disk_emptyspace = $disk_emptyspace");
logline("debug","DISK SPACE ALLOCATION for ZFS ended.");
} else {
logline("debug","DISK SPACE ALLOCATION for ZFS starts now ... on DMR");
$disk_usage_MB = `/bin/sh -c "/bin/df -cm | /usr/bin/grep total | /usr/bin/sed 's/total *//' | /usr/bin/cut -d' ' -f2"`;
$disk_freespace_MB = `/bin/sh -c "/bin/df -cm | /usr/bin/grep total | /usr/bin/sed 's/total *//' | /usr/bin/cut -d' ' -f3"`;
}
}
}
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
# zum gucken, ob es FTP-User gibt, die passwd vom Webserver auslesen, und gukcen ob es zum
# document root der Domain einen FTP-User mit passendem home-Verzeichnis gibt
logline("debug","Creating File Object \$webserver_passwd.");
my $webserver_passwd = file->new({file_name => '/etc/passwd'});
$webserver_passwd->read_file;
my %webserver_passwd = %{$webserver_passwd->file_parsed_hash()};
my %home_lookup = %{$webserver_passwd->lookup2_hash()};
my ($quotaref, $sum_ftplimit, $sum_ftpuse, $ftpserverlimit) = easytecc3::getquota_ftp();
my %quota = %$quotaref;
my $show_email = '';
my $show_edit_email = '';
my $show_ftp = '';
my $show_edit_ftp = '';
# hide webserver quota for non admin
if($session->param('user') eq 'admin'){
$template->param('show_server_quota' => '1');
$show_email = '1';
$show_edit_email = '1';
$show_ftp = '1';
$show_edit_ftp = '1';
} else {
my $gecos = $webserver_passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.email-1.ftp-2';
}
if($gecos =~ m/\.email/){
$show_email = '1';
if($gecos =~ m/\.email-[1-9]/){
$show_edit_email = '1';
}
}
if($gecos =~ m/\.ftp/){
$show_ftp = '1';
if($gecos =~ m/\.ftp-[1-9]/){
$show_edit_ftp = '1';
}
}
}
$template->param('show_email' => $show_email);
$template->param('show_ftp' => $show_ftp);
if (easytecc3::extern_mx() || $fb){
$mailpasswd = easytecc3::get_mailpasswd();
%mailpasswd = %{$mailpasswd->file_parsed_hash()};
#%mailpasswd = %{easytecc3::get_mailpasswd()};
($mailquotaref, $sum_maillimit, $sum_mailuse, $mailserverlimit) = easytecc3::getquota_mail(\%mailpasswd);
logline("debug","show_quota mailquotaref=$mailquotaref");
%mailquota = %$mailquotaref;
#my %mailquota_tmp = %mailquota;
#foreach(sort keys %mailquota_tmp){
# logline("debug","show_quota mailquota key=$_ value=" . $mailquota_tmp{$_} . "\n$sum_maillimit, $sum_mailuse, $mailserverlimit");
# my $hash_ref = $mailquota_tmp{$_};
# %mailquota = %$hash_ref;
# last;
# #warum auch immer...
# #%mailquota = %hash if $fb;
# foreach(sort keys %mailquota){
# logline("debug","1show_quota zweiter hash key=$_ value=" . $mailquota{$_});
# }
#}
#foreach(sort keys %mailquota){
# logline("debug","2show_quota zweiter hash key=$_ value=" . $mailquota{$_});
#}
}
else{
%mailpasswd = %webserver_passwd;
%mailquota = %quota;
$sum_maillimit = $sum_ftplimit;
$sum_mailuse = $sum_ftpuse;
$mailserverlimit = $ftpserverlimit;
}
my %domain_home;
foreach(keys %domains){
# filter domains
if($session->param('user') ne 'admin'){
my $admins = $domains{$_}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $session->param('user') . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
}
logline("debug","domain_home=" . $domains{$_}{'droot'});
logline("debug","domain_domains=" . $domains{$_}{'domains'});
$domain_home{$domains{$_}{'droot'}} = $domains{$_}{'domains'};
}
#nicht easytecc3::getsize nehmen, da man durch Rundung zuwenig belegten Platz angezeigt bekommt
#push @serverquota, sprintf("%.2f", $sum_ftplimit/1000) . ' GB' . '|' . sprintf("%.2f", $ftpserverlimit/1000) . ' GB' . '|' . sprintf("%.2f", $sum_ftpuse/1000) . ' GB';
#easytecc3::table(\$template,'<td>L__Summe der Limits Webserver__L</td><td>L__Maximaler Serverplatz Webserver__L</td><td colspan="5">L__Quotanutzung__L</td>', \@serverquota, 'table_webserver');
#if ($ftpserverlimit > 0){
# if(($sum_ftpuse/$ftpserverlimit)*100 >= 90){
# $template->param('alert_webserver_quota' => 1);
# }
#}
$template->param('alert_webserver_quota' => easytecc3::quota_alert($ftpserverlimit, $sum_ftpuse, '.8'));
$template->param('disk_freespace_GB' => sprintf("%.2f", $disk_freespace_MB/1024) . ' GB');
$template->param('disk_usage_GB' => sprintf("%.2f", $disk_usage_MB/1024) . ' GB');
$template->param('webserver_quota_used_percent' => sprintf("%.0f", ($sum_ftpuse/$ftpserverlimit)*100)) if $ftpserverlimit > 0;
$template->param('webserver_quota_used_GB' => sprintf("%.2f", $sum_ftpuse/1000) . ' GB');
$template->param('webserver_quota_GB' => sprintf("%.2f", $ftpserverlimit/1000) . ' GB');
$template->param('webserver_quota_sum_GB' => sprintf("%.2f", $sum_ftplimit/1000) . ' GB');
#wenn externer Mailserver, dann darber bersicht zeigen
if(easytecc3::extern_mx()){
#@serverquota = ();
#push @serverquota, sprintf("%.2f", $sum_maillimit/1000) . ' GB' . '|' . sprintf("%.2f", $mailserverlimit/1000) . ' GB' . '|' . sprintf("%.2f", $sum_mailuse/1000) . ' GB';
#easytecc3::table(\$template,'<td>L__Summe der Limits Mailserver__L</td><td>L__Maximaler Serverplatz Mailserver__L</td><td colspan="5">L__Quotanutzung__L</td>', \@serverquota, 'table_mailserver');
#if ($mailserverlimit > 0){
# if(($sum_mailuse/$mailserverlimit)*100 >= 90){
# $template->param('alert_mailserver_quota' => 1);
# }
#}
$template->param('has_extern_mailserver' => 1);
$template->param('alert_mailserver_quota' => easytecc3::quota_alert($mailserverlimit, $sum_mailuse, '.8'));
$template->param('mailserver_quota_used_percent' => sprintf("%.0f", ($sum_mailuse/$mailserverlimit)*100)) if $mailserverlimit > 0;
$template->param('mailserver_quota_used_GB' => sprintf("%.2f", $sum_mailuse/1000) . ' GB');
$template->param('mailserver_quota_GB' => sprintf("%.2f", $mailserverlimit/1000) . ' GB');
$template->param('mailserver_quota_sum_GB' => sprintf("%.2f", $sum_maillimit/1000) . ' GB');
}
#my @ftp_user = ();
my $table_data = {};
foreach my $ftpuser (sort keys %webserver_passwd){
# do NOT show system users here
next if $ftpuser eq 'ftp';
next if $ftpuser eq 'cyrus';
next if $ftpuser eq 'dovecot';
next if $ftpuser eq 'dovenull';
next if $ftpuser eq 'virtmail';
next if $ftpuser eq 'svn';
next if $ftpuser eq 'haproxy';
my $ftpquota = '';
my $ftpquota_sized = '';
my $ftpused = '';
my $quotabalken = '';
my $domain = '';
logline("debug","foreach ftpuser = $ftpuser");
$ftpquota = $quota{$ftpuser}{'quota'};
$ftpquota_sized = easytecc3::getsize($ftpquota);
$ftpused = $quota{$ftpuser}{'use'};
next unless $ftpused;
next if $webserver_passwd{$ftpuser}{'gecos'} =~ /- POP/;
#$quotabalken = easytecc3::quotabar($ftpquota, $ftpused, 'used');
my @domainlist = ();
if(exists $domain_home{$webserver_passwd{$ftpuser}{'home'}}){
foreach(@{$domain_home{$webserver_passwd{$ftpuser}{'home'}}}){
push @domainlist, encode('utf-8', domain_to_unicode($_));
}
$domain = join '<br />', @domainlist;
} else {
# filter domains
if($session->param('user') ne 'admin'){
my $home = $webserver_passwd{$ftpuser}{'home'};
my $self_home = $webserver_passwd{$session->param('user')}{'home'};
my $allowed = 0;
if($home ne $self_home && $home !~ m#^$self_home/#){
foreach my $dir (keys %domain_home){
if($home eq $dir || $home =~ m#^$dir/#){
$allowed = '1';
}
}
if($allowed != 1){
next;
}
}
}
}
$table_data->{$ftpuser}{'alert_ftpuser_quota'} = easytecc3::quota_alert($ftpquota, $ftpused, '.8');
$table_data->{$ftpuser}{'ftpuser'} = $ftpuser;
$table_data->{$ftpuser}{'domain'} = $domain;
$table_data->{$ftpuser}{'gecos'} = $webserver_passwd{$ftpuser}{'gecos'};
$table_data->{$ftpuser}{'home_tooltip'} = $webserver_passwd{$ftpuser}{'home'};
$table_data->{$ftpuser}{'home'} = easytecc3::substr_e4($webserver_passwd{$ftpuser}{'home'});
$table_data->{$ftpuser}{'ftpquota_sized'} = $ftpquota_sized;
$table_data->{$ftpuser}{'ftpquota_used_sized'} = easytecc3::getsize($ftpused);
$table_data->{$ftpuser}{'ftpquota_used_percent'} = sprintf("%.0f", ($ftpused/$ftpquota)*100) if $ftpquota > 0;
$table_data->{$ftpuser}{'show_ftp'} = $show_ftp;
$table_data->{$ftpuser}{'show_edit_ftp'} = $show_edit_ftp;
if($ftpuser eq 'admin' || $ftpuser eq 'web'){
#push(@ftp_user, $ftpuser.'|'.$domain.'|'.$webserver_passwd{$ftpuser}{'gecos'}.'|'.$webserver_passwd{$ftpuser}{'home'}.'|'.$ftpquota_sized.'|'.$quotabalken.'|'.
#qq~<a href='/cgi-bin/easytecc3/index.pl?action=change_ftpuser&ftpuser=$ftpuser'>L__Editieren__L</a>~);
}
else{
#push(@ftp_user, $ftpuser.'|'.$domain.'|'.$webserver_passwd{$ftpuser}{'gecos'}.'|'.$webserver_passwd{$ftpuser}{'home'}.'|'.$ftpquota_sized.'|'.$quotabalken.'|'.
#qq~<a href='/cgi-bin/easytecc3/index.pl?action=change_ftpuser&ftpuser=$ftpuser'>L__Editieren__L</a><br /><a href='/cgi-bin/easytecc3/index.pl?action=delete_ftpuser&ftpuser=$ftpuser'>L__Löschen__L</a>~);
}
}
#easytecc3::table(\$template,'<td>L__User__L</td><td>L__Domain__L</td><td>L__Beschreibung__L</td><td>L__Homeverzeichnis__L</td><td>L__FTP-Quota__L</td><td>L__Quotanutzung__L</td><td>L__Aktionen__L</td>', \@ftp_user, 'table_ftpuser');
easytecc3::table_e4($template, $table_data, 'table_tr_show_quota_ftpuser_template.html');
my $servername = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
chomp $servername;
$table_data = {};
foreach my $mailuser (sort keys %mailpasswd){
if($mailpasswd{$mailuser}{'gecos'} !~ / - POP$/ && $mailuser ne 'admin' && ($mailuser ne 'admin@' . $servername || $session->param('user') ne 'admin')){
next;
}
#wenn kein externer mailserver muss admin nicht bei popusern auftauchen
next if( ! easytecc3::extern_mx() && $mailuser eq 'admin');
logline("debug","foreach POP mailpasswd = $mailuser");
my $domain = $mailpasswd{$mailuser}{'gecos'};
$domain =~ s/ - POP$//;
if($mailuser eq 'admin@' . $servername){
$domain = $servername;
}
logline("debug","mailuser $mailuser domain: #$domain#");
# filter domains
if($session->param('user') ne 'admin'){
my $admins = $domains{'www.' . $domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $session->param('user') . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
}
my $mailquota_sized = $mailquota{$mailuser}{'quota'} / 1024;
#my $quotabalken = easytecc3::quotabar($mailquota{$user}{'quota'}, $mailquota{$user}{'use'}, 'used');
my $change_mailuser = '';
if ($fb) {
$change_mailuser = qq~<a href='/cgi-bin/easytecc3/index.pl?action=change_forward&domain=www.$domain'>L__Editieren__L</a>~
}
else{
$change_mailuser = qq~<a href='/cgi-bin/easytecc3/index.pl?action=change_popuser&domain=www.$domain'>L__Editieren__L</a>~
}
my $idn_mailuser = encode('utf-8', email_to_unicode($mailuser));
my $idn_domain = encode('utf-8', domain_to_unicode($domain));
my $wwwdomain = 'www.' . $domain;
if($domain eq $servername){
$wwwdomain = $servername;
}
$table_data->{$idn_mailuser}{'alert_mailuser_quota'} = easytecc3::quota_alert($mailquota{$mailuser}{'quota'}, $mailquota{$mailuser}{'use'}, '.8');
$table_data->{$idn_mailuser}{'idn_mailuser'} = $idn_mailuser;
$table_data->{$idn_mailuser}{'mailuser'} = $mailuser;
$table_data->{$idn_mailuser}{'domain'} = $idn_domain;
$table_data->{$idn_mailuser}{'idn_domain'} = $idn_domain;
$table_data->{$idn_mailuser}{'domain_www'} = $wwwdomain;
$table_data->{$idn_mailuser}{'gecos'} = $mailpasswd{$mailuser}{'gecos'};
$table_data->{$idn_mailuser}{'mailquota_sized'} = easytecc3::getsize($mailquota{$mailuser}{'quota'});
$table_data->{$idn_mailuser}{'mailquota_used_sized'} = easytecc3::getsize($mailquota{$mailuser}{'use'});
$table_data->{$idn_mailuser}{'mailquota_used_percent'} = sprintf("%.0f", ($mailquota{$mailuser}{'use'}/$mailquota{$mailuser}{'quota'})*100) if $mailquota{$mailuser}{'quota'} > 0;
$table_data->{$idn_mailuser}{'show_email'} = $show_email;
$table_data->{$idn_mailuser}{'show_edit_email'} = $show_edit_email;
#push(@user, $user.'|'.domain_to_unicode($domain).'|'.qq~$mailquota_sized MB~.'|'.qq~$quotabalken~.'|'.$change_mailuser);
}
#easytecc3::table(\$template,'<td>L__User__L</td><td>L__Domain__L</td><td>L__E-Mail-Quota__L</td><td>L__Quotanutzung__L</td><td colspan="3">L__Aktionen__L</td>', \@user, 'table_mailuser');
easytecc3::table_e4($template, $table_data, 'table_tr_show_quota_mailuser_template.html');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_special_spamfilter{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
#included by change_spamfilter tab3
my $template = shift;
my($active_user_chars_ref, $active_domain_chars_ref, $active_users_ref, $active_domains_ref) = easytecc3::get_userchars();
my %active_users = %$active_users_ref;
my %active_domains = %$active_domains_ref;
my @special_spamfilter = ();
# filter domains and users
if($session->param('user') ne 'admin' && (keys %active_users || keys %active_domains)){
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
# filter users
if (keys %active_users) {
my %mailpasswd;
if (easytecc3::extern_mx() || $fb){
my $mailpasswd = easytecc3::get_mailpasswd();
%mailpasswd = %{$mailpasswd->file_parsed_hash()};
#logline("debug"," -M A R I O- --> file_parsed_hash() " . $domain_ohne_www );
} else {
my $mailpasswd = file->new({file_name => '/etc/passwd'});
$mailpasswd->read_file;
%mailpasswd = %{$mailpasswd->file_parsed_hash()};
#logline("debug"," -M A R I O- --> else: file_parsed_hash() " . $domain_ohne_www );
}
foreach my $mailuser (sort keys %mailpasswd){
next if ($mailpasswd{$mailuser}{'gecos'} !~ / - POP$/);
my $domain = $mailpasswd{$mailuser}{'gecos'};
$domain =~ s/ - POP$//;
my $admins = $domains{'www.' . $domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $session->param('user') . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
delete $active_users{$mailuser};
}
}
}
# filter domains
if (keys %active_domains) {
my %allowed_domains;
foreach $domain (sort keys %domains){
my $admins = $domains{$domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $session->param('user') . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins =~ m/$userregex/i){
foreach my $alias_domain (@{$domains{$domain}{'domains'}}){
$alias_domain =~ s/^www\.//;
$alias_domain =~ s/^\*\.//;
$allowed_domains{$alias_domain} = 1;
logline("debug","allowed_domain:$alias_domain");
}
$domain =~ s/^www\.//;
$domain =~ s/^\*\.//;
$allowed_domains{$domain} = 1;
logline("debug","allowed_domain:$domain");
}
}
foreach $domain (sort keys %active_domains){
$domain = ascii_domain($domain);
$domain =~ s/^www\.//;
$domain =~ s/^\*\.//;
if(!exists $allowed_domains{$domain}){
delete $active_domains{$domain};
}
}
}
}
if (keys %active_users || keys %active_domains) {
$template->param('has_special_spamfilter' => '1');
}
foreach(keys %active_domains){
logline("debug","active_domains = " . $_);
}
foreach(keys %active_users){
logline("debug","active_users = " . $_);
}
my $table_data = {};
foreach(sort keys %active_users){
if(/^$input{'ulist'}/ || $input{'ulist'} eq 'all'){
push(@special_spamfilter, $_ . '|' . qq~<a href='/cgi-bin/easytecc3/index.pl?action=change_special_spamfilter&user=$_'>L__Editieren__L</a><br /><a href='/cgi-bin/easytecc3/index.pl?action=delete_special_spamfilter&spam_user_domain=$_'>L__Löschen__L</a>~);
my $idn_mailuser = encode('utf-8', email_to_unicode($_));
$table_data->{$idn_mailuser}{'special_spam_user_domain'} = $_;
$table_data->{$idn_mailuser}{'special_spam_idn_user_domain'} = $idn_mailuser;
}
}
foreach(sort keys %active_domains){
if(/^$input{'dlist'}/ || $input{'dlist'} eq 'all'){
push(@special_spamfilter, $_ . '|' . qq~<a href="/cgi-bin/easytecc3/index.pl?action=change_special_spamfilter&domain=~ . ascii_domain($_) . qq~">L__Editieren__L</a><br /><a href="/cgi-bin/easytecc3/index.pl?action=delete_special_spamfilter&spam_user_domain=~ . ascii_domain($_) . qq~">L__Löschen__L</a>~);
my $idn_domain = encode('utf-8', domain_to_unicode($_));
$table_data->{$idn_domain}{'special_spam_user_domain'} = encode('utf-8',ascii_domain($_));
$table_data->{$idn_domain}{'special_spam_idn_user_domain'} = $idn_domain;
}
}
foreach (keys %{ $table_data }){
my @keys = ('SPAMFILTER',$table_data->{$_}{'special_spam_user_domain'});
my $note = note_from_hashfile(\@keys);
if($note->{title}){
$table_data->{$_}{'note_title'} = $note->{title};
$table_data->{$_}{'note_text'} = $note->{text};
}
}
#easytecc3::table(\$template,'<td>L__User/Domain__L</td><td colspan="6">L__Aktionen__L</td>', \@special_spamfilter, 'special_spamfilter');
easytecc3::table_e4($template, $table_data, 'table_tr_show_special_spamfilter_template.html');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return($template);
}
sub show_virusfilter{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_virusfilter.html');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_scan_antivirus{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_scan_antivirus.html');
$template->param('result' => $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_dbbackup{
if($session->param('show_db') ne '1'){
return start();
}
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_dbbackup.html');
my @db = ();
my $html_error = '';
my ($dbh, $mysql_connect_error) = easytecc3::mysql_connect();
if ($mysql_connect_error == '1'){
return(add_mysql_password());
}
if (! -e "$mysqlbackup_dir") {
mkdir("$mysqlbackup_dir", 0775);
`chmod 775 $mysqlbackup_dir`;
}
if ($fb) {
my $correct_sqldumproot = `/usr/iports/bin/sudo /usr/sbin/chown.pl admin:vuser "/usr/local/etc/easytecc/mysqlbackup" d 2>&1`;
return(error("L__Fehler beim Setzen des Besitzers für__L /usr/local/etc/easytecc/mysqlbackup: $correct_sqldumproot")) if $correct_sqldumproot;
}
else {
my $correct_sqldumproot = `/home/httpd/cgi-bin/easytecc4/chmod.pl 775 "/usr/local/etc/easytecc/mysqlbackup" 2>&1`;
return(error("L__Fehler beim Setzen des Besitzers für__L /usr/local/etc/easytecc/mysqlbackup: $correct_sqldumproot")) if $correct_sqldumproot;
}
# Grsse der Datenbanken ermitteln, von der Funktion wird auch datadir übermittelt. kann man vielleicht noch mal brauchen
my (%database_size, $datadir) = easytecc3::get_size_mysql();
foreach(sort keys %database_size){
logline("debug","key=$_ value=" . $database_size{$_});
}
# vorhandene Datenbanken auslesen
# wenn Datenbank "mysql" nicht auftaucht, hat mysqluser vermutlich zuwenig Rechte,
# in diesem Fall Formular für mysql-User anzeigen
my $grant_ok = '';
my $query = 'SHOW databases';
my $new_db = '';
my $edit_db = '';
if($session->param('user') eq 'admin'){
$new_db = '1';
$edit_db = '1';
$template->param('is_admin' => 1);
} else {
my @user = ();
# gather allowed dirs
my %allowed_dirs;
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
foreach my $domain (keys %domains){
my $admins = $domains{$domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $session->param('user') . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
$allowed_dirs{$domains{$domain}{'droot'}} = '1';
}
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my $gecos = $passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.db-2';
}
if($gecos =~ m/\.db-[1-9]/){
$edit_db = '1';
}
if($gecos =~ m/\.db-2/){
$new_db = '1';
}
$allowed_dirs{$passwd{$session->param('user')}{'home'}} = '1';
foreach my $user(sort keys %passwd){
# chown nicht an POP-User ermöglichen
next if $passwd{$user}{'gecos'} =~ / - POP/;
my $home = $passwd{$user}{'home'};
foreach my $dir (keys %allowed_dirs){
if($home eq $dir || $home =~ m#^$dir/#){
push(@user,$user);
}
}
}
my $userlist = '\'' . join('\',\'', @user) . '\'';
$query = "SHOW DATABASES WHERE `Database` IN (SELECT DISTINCT Db AS `Database` FROM mysql.db WHERE User IN ($userlist))";
# a very strange mechanism...
$grant_ok = '1'
}
$template->param('new_db' => $new_db);
my $sth = $dbh->prepare( $query );
$sth->execute;
my $table_data = {};
while ( my @row = $sth->fetchrow_array ){ # alle rows auslesen
foreach my $item (@row){
next if $item eq 'information_schema';
# Datenbanken mit . sind Sicherungen von getback auf die kein Zugriff ber mysql-Schnittstelle mglich ist
# und daher auch kein Backup gemacht werden kann.
#next if $item =~ /\./;
# wenn show databases DB mysql oder db01 anzeigt, gehen wir davon aus, dass Rechte des Users der Sicherungen durchfhrt ok sind
# ansonsten Formular für mysqluser anzeigen
$grant_ok = '1' if $item eq 'mysql';
$grant_ok = '1' if $item eq 'db01';
# Überprüfen, ob Backup angelegt
my $backup = "Ja";
my $backup_config = "/usr/local/etc/easytecc/mysqlbackup/$item.dbb";
my $backup_dir = "$mysqlbackup_dir/$item";
my @dir_entries = ();
my $in_use_for_backup = '';
my $backup_has_error = '0';
my $backup_has_lock = '0';
my $backup_count = '0';
if (-d $backup_dir){
opendir(D,$backup_dir) || dienice("opendir $backup_dir: $!");
@dir_entries = grep !/^\.\.?$/, readdir(D); #read in dir entries to array
closedir D;
#$backup_has_lock = 1 if (grep /\.lock$/, @dir_entries);
foreach my $error_file(@dir_entries){
logline("info","file1=$error_file item=$item");
$backup_has_lock = 1 if ($error_file =~ /\.lock$/);
next if $error_file !~ /^(.*)\.error$/;
my $name_of_backup = $1;
logline("info","file2=$error_file");
$backup_has_error = 1;
my $error_text = `cat $backup_dir/$error_file`;
my $error_template = HTML::Template->new(filename => 'error_div.html');
$error_template->param('alert_has_close_action' => 'alert_has_close_action');
$error_template->param('alert_close_action' => "exec_delete_alert&database=$item&error=$error_file");
$error_template->param('error_text' => qq~$item Backup $name_of_backup: $error_text~);
$html_error .= $error_template->output;
}
$backup_count = scalar(@dir_entries) - $backup_has_lock - $backup_has_error;
if($backup_count > 0){
$in_use_for_backup = `du -s $backup_dir` unless $fb;
$in_use_for_backup = `/usr/iports/bin/sudo /usr/bin/du -As $backup_dir` if $fb;
$in_use_for_backup = easytecc3::getsize($in_use_for_backup);
}
}
# kein automatisches Backup und keine Dumps
if ( ! -e $backup_config && $backup_count == '0'){
$table_data->{$item}{'db_name'} = $item;
$table_data->{$item}{'db_size_sized'} = easytecc3::getsize($database_size{$item});
$table_data->{$item}{'edit_db'} = $edit_db;
#$backup = "L__Nein__L";
#push(@db, $item . '|' .
#easytecc3::getsize($database_size{$item}) . '|' .
#$backup . '|' .
#$in_use_for_backup . '|' .
#qq~<a href="/cgi-bin/easytecc3/index.pl?action=show_mysqlbackup_details&database=$item">L__Backup anlegen__L</a><br />~);
}
# kein automatisches Backup aber Dumps vorhanden
elsif ( ! -e $backup_config && $backup_count > 0){
$table_data->{$item}{'has_dbbackup'} = 1;
$table_data->{$item}{'db_name'} = $item;
$table_data->{$item}{'db_size_sized'} = easytecc3::getsize($database_size{$item});
$table_data->{$item}{'dbbackup_size_sized'} = $in_use_for_backup;
$table_data->{$item}{'dbbackup_count'} = $backup_count;
$table_data->{$item}{'edit_db'} = $edit_db;
#$backup = "L__Nein__L";
#push(@db, $item . '|' .
#easytecc3::getsize($database_size{$item}) . '|' .
#$backup . '|' .
#$in_use_for_backup . '|' .
#qq~<a href="/cgi-bin/easytecc3/index.pl?action=show_mysqlbackup_details&database=$item">L__Details__L</a><br />~);
}
# automatischs Backup ist vorhanden
else{
$table_data->{$item}{'db_has_auto_backup'} = 1;
$table_data->{$item}{'has_dbbackup'} = 1;
$table_data->{$item}{'db_name'} = $item;
$table_data->{$item}{'db_size_sized'} = easytecc3::getsize($database_size{$item});
$table_data->{$item}{'dbbackup_size_sized'} = $in_use_for_backup;
$table_data->{$item}{'dbbackup_count'} = $backup_count;
$table_data->{$item}{'edit_db'} = $edit_db;
#$backup = "L__Ja__L";
#push(@db, $item . '|' .
#easytecc3::getsize($database_size{$item}) . '|' .
#$backup . '|' .
#$in_use_for_backup . '|' .
#qq~<a href="/cgi-bin/easytecc3/index.pl?action=show_mysqlbackup_details&database=$item">L__Details__L</a>~);
}
my @keys = ('DBBACKUP',$item);
my $note = note_from_hashfile(\@keys);
if($note->{title}){
$table_data->{$item}{'note_title'} = $note->{title};
$table_data->{$item}{'note_text'} = $note->{text};
}
}
}
# alles für die Katz, mysqluser hat zuwenig Rechte
unless($grant_ok){
$dbh->disconnect;
logline("warning","Leaving show_dbbackup() grant_ok: $grant_ok");
return(add_mysql_password());
}
easytecc3::table_e4($template, $table_data, 'table_tr_show_dbbackup_template.html');
#easytecc3::table(\$template,'<td>L__Datenbank__L</td><td>L__Größe__L</td><td>L__Automatisches Backup__L</td><td>L__Backup-Speichernutzung__L</td><td colspan="3">L__Aktionen__L</td>', \@db, 'table1');
#my $mysqlbackup_space_in_use = `du -s $mysqlbackup_dir` unless $fb;
#my $mysqlbackup_space_in_use = `/usr/iports/bin/sudo /usr/bin/du -s $mysqlbackup_dir` if $fb;
#$mysqlbackup_space_in_use = easytecc3::getsize($mysqlbackup_space_in_use);
#$template->param('mysqlbackup_space_in_use' => 'L__Backup-Gesamtspeichernutzung__L: ' . $mysqlbackup_space_in_use);
$dbh->disconnect;
$template->param('error' => $html_error) if $html_error;
if($new_db eq '1'){;
if (length($input{'active_tab'})) {
$template->param('show_dbbackup_active_tab'.$input{'active_tab'} => 1);
}
else{
$template->param('show_dbbackup_active_tab1' => 1);
}
} else {
$template->param('show_dbbackup_active_tab1' => 1);
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_mysqlbackup_details{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_mysqlbackup_details.html');
my $database = $input{'database'};
my %backup = ();
my %backup_lock = ();
my %backup_error = ();
my @backup;
my $edit_db = '';
if($session->param('user') eq 'admin'){
$edit_db = '1';
} else {
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my $gecos = $passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.db-1';
}
if($gecos =~ m/\.db-[1-9]/){
$edit_db = '1';
}
}
$template->param('edit_db' => $edit_db);
if(-d "$mysqlbackup_dir/$database"){
my $command = "du -s $mysqlbackup_dir/$database/*" unless $fb;
$command = "/usr/iports/bin/sudo /usr/bin/du -As $mysqlbackup_dir/$database/*" if $fb;
logline("debug","Executing $command : ");
open (COMMAND, "$command|") || dienice("open $command|: $!");
while(my $line = <COMMAND>){
if ($fb) {
my @out = split /\n/, $line;
logline("debug","out = $out");
foreach(@out){
my @path = split /\//, $_;
my $print = $path[0] . " " . $path[-1];
$line = $print;
}
}
logline("debug","mysqlbackup = $line");
# Output in kB
# 676 mysql
# 88996 ndb_3_fs
my($size, $backup) = split /\s+/, $line;
logline("debug","size = $size, backup = $backup");
if ($line =~ /\s+(.*)\.error$/){
logline("debug","mysqlbackuperror = $1");
next;
}
if ($line =~ /\s+(.*)\.lock$/){
logline("debug","mysqlbackuplock = $1");
$backup{$1}{'reload_button'} = '1';
next;
}
# ich sag nix mehr, ich sag einfach nix mehr...
$backup =~ s/^.*\///g;
$backup{$backup}{'size'} = easytecc3::getsize($size);
my $modtime = (stat("$mysqlbackup_dir/$database/$backup"))[9];
logline("debug","modtime = $modtime");
my @formatedtime = localtime($modtime);
$backup{$backup}{'date'} = easytecc3::zeit(\@formatedtime);
}
close COMMAND;
my $table_data = {};
foreach (sort keys %backup){
my $backup = $_;
logline("notice","backup=$backup");
#für den Fall, da grösseres Backup gerade komprimiert wird, dann gibt es .lock und .gz-Datei. Es soll aber nur "Backup in Arbeit" angezeigt werden
#Darum skippen, wenn es .gz und eine .lock gibt
if($backup =~ /^(.*)\.gz$/){
#next if exists $backup_lock{$1};
next if (-e "$mysqlbackup_dir/$database/$1.lock");
}
$table_data->{$backup}{'database'} = $input{'database'};
$table_data->{$backup}{'nameofbackup'} = $backup;
$table_data->{$backup}{'dateofbackup'} = $backup{$backup}{'date'};
$table_data->{$backup}{'sizeofbackup'} = $backup{$backup}{'size'};
$table_data->{$backup}{'reload_button'} = $backup{$backup}{'reload_button'};
$table_data->{$backup}{'backup_error'} = $backup{$backup}{'backup_error'};
$table_data->{$backup}{'edit_db'} = $edit_db;
#if(exists $backup_lock{$_}){
# push(@backup, $_.'|'.$backup{$_}{'date'}.'|'.$backup{$_}{'size'}.'|'.
# qq~<img src="/easytecc3/images/data_time.gif" />L__Backup in Arbeit__L
# <a href="/cgi-bin/easytecc3/index.pl?action=show_mysqlbackup_details&database=$database">L__Aktualisieren__L</a>~);
# $table_data->{$backup}{'reload_button'} = 1;
#}
#elsif(exists $backup_error{$_}){
# push(@backup, $_.'|'.$backup{$_}{'date'}.'|'.$backup{$_}{'size'}.'|'.
# qq~<img src="/easytecc3/images/data_error.gif" />Backupfehler!
# <a href="/cgi-bin/easytecc3/index.pl?action=exec_delete_mysqlbackup&database=$database&backup=$_&has_error=1">L__Löschen__L</a>~);
# $table_data->{$backup}{'backup_error'} = 1;
#}
#else{
#push(@backup, $_.'|'.$backup{$_}{'date'}.'|'.$backup{$_}{'size'}.'|'.
#qq~<a href="/cgi-bin/easytecc3/index.pl?action=confirm_restore_mysqlbackup&database=$database&backup=$_">L__Einspielen__L</a> ~ .
#qq~<a href="/cgi-bin/easytecc3/index.pl?action=download_mysqlbackup&database=$database&backup=$_">Download</a> ~ .
#qq~<a href="/cgi-bin/easytecc3/index.pl?action=exec_delete_mysqlbackup&database=$database&backup=$_">L__Löschen__L</a>~);
#}
}
easytecc3::table_e4($template, $table_data, 'table_tr_show_mysqlbackup_details_template.html');
#easytecc3::table(\$template,'<td>Name</td><td>L__Datum__L</td><td>L__Größe__L</td><td colspan="4">L__Aktionen__L</td>', \@backup, 'backups');
}
else{
logline("notice","Kein Backup vorhanden");
$template->param('backups' => 'L__Kein Backup vorhanden__L');
}
$template->param('database' => $database);
if(-e "/usr/local/etc/easytecc/mysqlbackup/$database.dbb"){
logline("debug","mysqlbackup vorhanden:$database");
$template->param('delete_auto_backup' => '1');
}
else{
$template->param('edit_new_auto_mysqlbackup' => 'L__Anlegen__L');
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_cronjobs{
if($session->param('show_cron') ne '1'){
return start();
}
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_cronjobs.html');
my @cronjobs = ();
logline("debug","Creating File Object \$cronfile.");
my $cronfile = file->new({file_name => '/home/web/cronfile'});
$cronfile->read_file;
my %cronjobs = %{$cronfile->file_parsed_hash()};
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
# gather allowed dirs and domains
my %allowed_dirs;
my %allowed_domains;
my $edit_cron = '';
my $new_cron = '';
if($session->param('user') eq 'admin'){
$edit_cron = '1';
$new_cron = '1';
} else {
my $gecos = $passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.cron-2';
}
if($gecos =~ m/\.cron-[1-9]/){
$edit_cron = '1';
}
if($gecos =~ m/\.cron-2/){
$new_cron = '1';
}
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
foreach my $domain (keys %domains){
my $admins = $domains{$domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $session->param('user') . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
foreach my $alias_domain (@{$domains{$domain}{'domains'}}){
$alias_domain =~ s/^www\.//;
$alias_domain =~ s/^\*\.//;
$allowed_domains{$alias_domain} = 1;
}
$allowed_dirs{$domains{$domain}{'droot'}} = '1';
if($fb && $domains{$domain}{'droot'} !~ m#/apache24/data/#){
my $doc_root_alias = $domains{$domain}{'droot'};
$doc_root_alias =~ s#/apache24/noexec/#/apache24/data/#;
$allowed_dirs{$doc_root_alias} = '1';
}
$domain =~ s/^www\.//;
$domain =~ s/^\*\.//;
$allowed_domains{$domain} = 1;
}
$allowed_dirs{$passwd{$session->param('user')}{'home'}} = '1';
}
$template->param('edit_cron' => $edit_cron);
$template->param('new_cron' => $new_cron);
my $table_data = {};
foreach my $cronjob (sort keys %cronjobs){
next if $cronjobs{$cronjob}{'job'} =~ /easytecc4\/dobackup\.pl/;
next if $cronjobs{$cronjob}{'job'} =~ /tools\/awstats_updateall\.pl/;
$cronjobs{$cronjob}{'job'} = encode('utf-8',$cronjobs{$cronjob}{'job'});
if($session->param('user') ne 'admin'){
my $allowed = 0;
# check dirs
foreach my $dir (keys %allowed_dirs){
if($cronjobs{$cronjob}{'job'} =~ m#$dir/#){
# check if other dirs are affected
my $job = $cronjobs{$cronjob}{'job'};
$job =~ s#$dir/##;
if($job !~ m#/home/# && $job !~ m#(/usr/local/www/|/home/httpd/docs)#){
$allowed = 1;
last;
}
}
}
# check domains
if($allowed == 0){
foreach my $domain (keys %allowed_domains){
if($cronjobs{$cronjob}{'job'} =~ m#(ftp|http)s?://(www\.)?$domain/#){
$allowed = 1;
last;
}
}
}
if($allowed != 1){
next;
}
}
my $cronjob_string_no_dev_null = $cronjobs{$cronjob}{'job'};
$cronjob_string_no_dev_null =~ s/(1|2)*\s*>\s*\/dev\/null//;
$cronjob_string_no_dev_null =~ s/(1|2)\s*>\s*&(1|2)//;
$table_data->{$cronjob}{'cronjob'} = $cronjobs{$cronjob}{'count'};
$table_data->{$cronjob}{'cron_command_tooltip'} = $cronjobs{$cronjob}{'job'};
#$table_data->{$cronjob}{'cron_command'} = easytecc3::substr_e4($cronjobs{$cronjob}{'job'});
$table_data->{$cronjob}{'cron_command'} = easytecc3::substr_e4($cronjob_string_no_dev_null);
$table_data->{$cronjob}{'cron_minute'} = $cronjobs{$cronjob}{'min'};
$table_data->{$cronjob}{'cron_hour'} = $cronjobs{$cronjob}{'std'};
$table_data->{$cronjob}{'cron_day'} = $cronjobs{$cronjob}{'mday'};
$table_data->{$cronjob}{'cron_month'} = $cronjobs{$cronjob}{'mon'};
$table_data->{$cronjob}{'cron_weekday'} = $cronjobs{$cronjob}{'wday'};
$table_data->{$cronjob}{'edit_cron'} = $edit_cron;
$table_data->{$cronjob}{'new_cron'} = $new_cron;
my $old_cron_key = $cronjobs{$cronjob}{'job'};
$old_cron_key =~ s/[^a-z0-9]+/-/gi;
my @old_keys = ('CRONJOB',$old_cron_key);
# new key format
my $cron_key = encode_base64url($cronjobs{$cronjob}{'job'} . $cronjobs{$cronjob}{'min'} . $cronjobs{$cronjob}{'std'} . $cronjobs{$cronjob}{'mday'} . $cronjobs{$cronjob}{'mon'} . $cronjobs{$cronjob}{'wday'});
my @keys = ('CRONJOB',$cron_key);
$table_data->{$cronjob}{'cron_key'} = $cron_key;
my $note = note_from_hashfile(\@old_keys);
if($note->{title}){
note_to_hashfile(\@keys,decode('utf-8',$note->{title}),decode('utf-8',$note->{text}));
note_to_hashfile(\@old_keys,'','');
}
$note = note_from_hashfile(\@keys);
if($note->{title}){
$table_data->{$cronjob}{'note_title'} = $note->{title};
$table_data->{$cronjob}{'note_text'} = $note->{text};
}
#push(@cronjobs, $cronjobs{$cronjob}{'job'} . '|' .
#$cronjobs{$cronjob}{'min'} . '|' .
#$cronjobs{$cronjob}{'std'} . '|' .
#$cronjobs{$cronjob}{'mday'} . '|' .
#$cronjobs{$cronjob}{'mon'} . '|' .
#$cronjobs{$cronjob}{'wday'} . '|' .
#qq~<a href="/cgi-bin/easytecc3/index.pl?action=change_cronjob&cronjob=$cronjobs{$cronjob}{'count'}">L__Editieren__L</a> ~ .
#qq~<a href="/cgi-bin/easytecc3/index.pl?action=delete_cronjob&cronjob=$cronjobs{$cronjob}{'count'}">L__Löschen__L</a>~);
}
easytecc3::table_e4($template, $table_data, 'table_tr_show_cronjobs_template.html');
#easytecc3::table(\$template,'<td>L__Kommando__L</td><td>L__Minuten__L</td><td>L__Stunden__L</td><td>L__Tage__L</td><td>L__Monate__L</td><td>L__Wochentag__L</td><td>L__Aktionen__L</td>', \@cronjobs, 'table1');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_frontpage{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_frontpage.html');
my @allfiles = ();
my @frontpage_domains = ();
unless(`grep 'httpd_enable="F"' /etc/rc.conf`){
$template = HTML::Template->new(filename => 'frontpage_not_enabled.html');
}
else{
opendir(DIR, '/usr/local/frontpage') || dienice("opendir /usr/local/frontpage: $!");
@allfiles = grep !/^\.\.?$/, readdir DIR;
closedir DIR;
foreach my $file(@allfiles){
next unless $file =~ /:80\.cnf$/;
my $domain = $file;
$domain =~ s/:80\.cnf$//;
# ohne www. anzeigen
my $domain_ohne_www = $domain;
$domain_ohne_www =~ s/^www\.//;
push(@frontpage_domains, $domain_ohne_www . '|' . qq~<a href="/cgi-bin/easytecc3/index.pl?action=delete_frontpage&domain=$domain">L__Löschen__L</a>~);
}
easytecc3::table(\$template,'<td>L__Domain__L</td><td colspan="6">L__Aktionen__L</td>', \@frontpage_domains, 'table1');
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_filemanager{
if($session->param('show_fileman') ne '1'){
return start();
}
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_filemanager.html');
my ($directories_ref, $files_ref, $allowed_primary) = get_files();
if($session->param('user') eq 'admin'){
$allowed_primary = 1;
}
$input{'dir'} =~ s#^$droot_prefix/?##;
my @directories = @$directories_ref;
my @files = @$files_ref;
my @filemanager = ();
my $chdir = '';
my $dir = '';
my $pwd = $droot_prefix . '/' . $input{'dir'};
#if($input{'dir'} !~ m#/snapshots/#){
#
# $pwd = $droot_prefix . '/' . $input{'dir'};
#
#} else {
#
# $pwd = $input{'dir'};
#
#}
my $show_password_protection='0';
if(scalar @files || scalar @directories >1 || $session->param('user') eq 'admin'){
$show_password_protection='1';
}
$template->param('show_password_protection' => $show_password_protection && $allowed_primary);
$template->param('show_new_dir' => $allowed_primary);
my $result = $validation_result;
if($result){
# in diesem Fall wird show_filemanager nicht mit $input{'action'} = exec...
# aufgerufen, so daß hier abgebrochen wird
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(error($result));
}
else{
# stat() gibt uns nur die UID, in easytecc muss natürlich der Name erscheinen
# $passwd{$user}{'uid'}, key ist Username und uid die UID,
# daraus basteln wir uns einen lookup-hash
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my %username_lookup = %{$passwd->lookup_hash()};
my $table_data_dir = {};
my $table_data_file = {};
my $edit_fileman = '';
if($session->param('user') eq 'admin'){
$edit_fileman = '1';
} else {
my $gecos = $passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.fileman-1';
}
if($gecos =~ m/\.fileman-[1-9]/){
$edit_fileman = '1';
}
}
$template->param('edit_fileman' => $edit_fileman);
# my $snapshot_dir = $pwd;
# $snapshot_dir =~ s#/usr/local/www/apache24/noexec/#/usr/local/www/apache24/data/#;
# my $snapshot_list = `ls -d1 /snapshots/*/$snapshot_dir 2>&1 | sed 's/^.*bckp_// ; s/\\/.*//' 2>&1`;
# my @snapshots;
# my $snapshot;
#
# logline("debug","#####################$snapshot_dir\n$snapshot_list\n");
#
# foreach $snapshot (split(/[\r\n]+/,$snapshot_list)){
#
# my ($day,$month,$year) = $snapshot =~ m/^([0-9]{2})([0-9]{2})([0-9]{4})$/;
#
# # add to list
# push(@snapshots, { snapshot_name => "$day.$month.$year", snapshot_href => '/cgi-bin/easytecc4/index.pl?action=show_filemanager&dir=' . encode_base64url('/snapshots/bckp_' . $snapshot . $snapshot_dir)});
#
# }
#
# $template->param('snapshots' => \@snapshots);
foreach (@directories){
my $full_path = $droot_prefix;
$dir = $input{'dir'} . '/' . $_ if $input{'dir'};
$dir = $_ unless $input{'dir'};
$chdir = $full_path . '/' . $input{'dir'} . '/' . $_ if $input{'dir'};
$chdir = $full_path . '/' . $_ unless $input{'dir'};
my ($filesize, $filedate, $owner, $fileperm, $nlink) = (stat($chdir))[7,9,4,2,3];
$fileperm = sprintf "%lo", ($fileperm & 07777);
#$filesize = `du -Ask $chdir`;
#$filesize = $nlink;
logline("debug","_:$_ dir:$dir input_dir: $input{'dir'}\n");
if($_ eq '..'){
#logline("debug","..=$_");
$dir = '' unless $input{'dir'} =~ /\//;
$dir = $input{'dir'} if $dir;
# aus /home/httpd/docs/bla/fasel mach
# /home/httpd/docs/bla
$dir =~ s/\/[^\/]{0,100}$// if $dir;
$filesize = `ls -1 $full_path/$input{'dir'} | wc -l`;
#$table_data_dir->{'..'}{'topdir_href'} = qq~/cgi-bin/easytecc3/index.pl?action=show_filemanager&dir=$dir~;
#$table_data_dir->{'..'}{'topdir_mtime'} = easytecc3::getdate($filedate);
#$table_data_dir->{'..'}{'topdir_chmod'} = $fileperm;
#$table_data_dir->{'..'}{'topdir_user'} = $username_lookup{$owner};
#$table_data_dir->{'..'}{'topdir_size_sized'} = easytecc3::filesize($filesize);
my $dir_encoded = encode_base64url($dir);
$template->param('topdir_href' => qq~/cgi-bin/easytecc4/index.pl?action=show_filemanager&dir=$dir_encoded~);
$template->param('topdir_mtime' => easytecc3::getdate($filedate));
$template->param('topdir_chmod' => $fileperm);
$template->param('topdir_user' => $username_lookup{$owner});
#$template->param('topdir_size_sized' => easytecc3::filesize($filesize));
$template->param('topdir_size_sized' => $filesize);
#push(@filemanager,
# '<img src="/easytecc3/images/folder.gif" align="middle" />' . qq~<a href="/cgi-bin/easytecc3/index.pl?action=show_filemanager&dir=$dir">~ . $_ . '</a>|' .
# easytecc3::filesize($filesize) . '|' .
# easytecc3::getdate($filedate) . '|' .
# qq~$fileperm/$username_lookup{$owner}~ . '|' . ''
#);
}
else{
my $dir_encoded = encode_base64url($dir);
$filesize = `ls -1 $chdir | wc -l`;
$table_data_dir->{$_}{'dir'} = $dir;
$table_data_dir->{$_}{'dir_href'} = qq~/cgi-bin/easytecc4/index.pl?action=show_filemanager&dir=$dir_encoded~;
$table_data_dir->{$_}{'dir_name'} = $_;
$table_data_dir->{$_}{'dir_mtime'} = easytecc3::getdate($filedate);
$table_data_dir->{$_}{'dir_chmod'} = $fileperm;
$table_data_dir->{$_}{'dir_user'} = $username_lookup{$owner};
#$table_data_dir->{$_}{'dir_size_sized'} = easytecc3::filesize($filesize);
$table_data_dir->{$_}{'dir_size_sized'} = $filesize;
my $dirlink = uri_escape($dir);
$table_data_dir->{$_}{'dir_href_url'} = qq~http://$ENV{'SERVER_NAME'}/$dirlink~;
$table_data_dir->{$_}{'dir_href_chmod'} = qq~modify_dir&type=chmod&dir=$dir_encoded~;
$table_data_dir->{$_}{'dir_href_cms_fix'} = qq~modify_dir&type=cms_fix&dir=$dir_encoded~;
$table_data_dir->{$_}{'dir_href_cp'} = qq~modify_dir&type=cp&dir=$dir_encoded~;
$table_data_dir->{$_}{'dir_href_mv'} = qq~modify_dir&type=mv&dir=$dir_encoded~;
$table_data_dir->{$_}{'dir_href_rm'} = qq~modify_dir&type=rm&dir=$dir_encoded~;
$table_data_dir->{$_}{'edit_fileman'} = $edit_fileman;
my $dir_key = $chdir;
$dir_key =~ s/[^a-z0-9]+/-/gi;
$table_data_dir->{$_}{'dir_key'} = $dir_key;
my @keys = ('DIRECTORY',$dir_key);
my $note = note_from_hashfile(\@keys);
if($note->{title}){
$table_data_dir->{$_}{'note_title'} = $note->{title};
$table_data_dir->{$_}{'note_text'} = $note->{text};
}
#push(@filemanager,
# '<img src="/easytecc3/images/folder.gif" align="middle" />' . qq~<a href="/cgi-bin/easytecc3/index.pl?action=show_filemanager&dir=$dir">~ . $_ . '</a>|' .
# easytecc3::filesize($filesize) . '|' .
# easytecc3::getdate($filedate) . '|' .
# qq~<a href="/cgi-bin/easytecc3/index.pl?action=modify_dir&type=chmod&dir=$dir">~ . qq~$fileperm/$username_lookup{$owner}~ . '</a>|' .
# qq~<a href="http://$ENV{'SERVER_NAME'}/$dir" target="_blank">L__Ansehen__L</a>
# <a href="/cgi-bin/easytecc3/index.pl?action=modify_dir&type=cp&dir=$dir">L__Kopieren__L</a>
# <a href="/cgi-bin/easytecc3/index.pl?action=modify_dir&type=mv&dir=$dir">L__Umbenennen__L</a>
# <a href="/cgi-bin/easytecc3/index.pl?action=modify_dir&type=rm&dir=$dir">L__Löschen__L</a>~
#);
}
}
foreach (@files){
my $chdir = '';
my $filelink = '';
#logline("debug","file = $file");
my $full_path = $droot_prefix;
my $dir = $input{'dir'};
$chdir = $full_path . '/' . $dir . '/' . $_ if $input{'dir'};
$chdir = $full_path . '/' . $_ unless $input{'dir'};
$filelink = $dir . '/' . $_ if $input{'dir'};
$filelink = $_ unless $input{'dir'};
$filelink = uri_escape($filelink);
# hard hack the /
$filelink =~ s/%2F/\//g;
logline("debug","filelink: $filelink");
my($filesize, $filedate, $owner, $fileperm) = (stat($chdir))[7,9,4,2];
my $fileperm_o = sprintf "%lo", $fileperm;
$fileperm = sprintf "%lo", ($fileperm & 07777);
my ($dummy,$ext) = split(/\./,$_);
my $icon = "file.gif";
if ($ext eq 'htm' || $ext eq 'html' || $ext eq 'shtml') { $icon = "html.gif"; }
if ($ext eq 'txt') { $icon = "txt.gif"; }
if ($ext eq 'pl' || $ext eq 'cgi') { $icon = "cgi.gif"; }
if ($ext eq 'zip') { $icon = "zip.gif"; }
if ($ext eq 'exe') { $icon = "exe.gif"; }
if ($ext eq 'gif') { $icon = "gif.gif"; }
if ($ext eq 'jpg') { $icon = "jpg.gif"; }
my $dir_encoded = encode_base64url($dir);
my $file = $_;
my $file_encoded = encode_base64url($file);
$table_data_file->{$_}{'file_href'} = qq~/cgi-bin/easytecc4/index.pl?action=show_filemanager&dir=$dir_encoded~;
$table_data_file->{$_}{'file_name'} = $file;
$table_data_file->{$_}{'file_mtime'} = easytecc3::getdate($filedate);
$table_data_file->{$_}{'file_chmod'} = $fileperm;
$table_data_file->{$_}{'file_user'} = $username_lookup{$owner};
$table_data_file->{$_}{'file_size_sized'} = easytecc3::filesize($filesize);
$table_data_file->{$_}{'file_href_url'} = qq~http://$ENV{'SERVER_NAME'}/$filelink~;
$table_data_file->{$_}{'file_href_download'} = qq~/cgi-bin/easytecc4/index.pl?action=download_file&dir=$dir_encoded&file=$file_encoded~;
$table_data_file->{$_}{'file_href_edit'} = qq~modify_file&type=edit&dir=$dir_encoded&file=$file_encoded~;
$table_data_file->{$_}{'file_href_chmod'} = qq~modify_file&type=chmod&dir=$dir_encoded&file=$file_encoded~;
$table_data_file->{$_}{'file_href_cp'} = qq~modify_file&type=cp&dir=$dir_encoded&file=$file_encoded~;
$table_data_file->{$_}{'file_href_mv'} = qq~modify_file&type=mv&dir=$dir_encoded&file=$file_encoded~;
$table_data_file->{$_}{'file_href_rm'} = qq~modify_file&type=rm&dir=$dir_encoded&file=$file_encoded~;
$table_data_file->{$_}{'edit_fileman'} = $edit_fileman;
my $file_key = $chdir;
$file_key =~ s/[^a-z0-9]+/-/gi;
$table_data_file->{$_}{'file_key'} = $file_key;
my @keys = ('FILE',$file_key);
my $note = note_from_hashfile(\@keys);
if($note->{title}){
$table_data_file->{$_}{'note_title'} = $note->{title};
$table_data_file->{$_}{'note_text'} = $note->{text};
}
#push(@filemanager, qq~<img src="/easytecc3/images/$icon" align="middle" /><a href="/cgi-bin/easytecc3/index.pl?action=modify_file&type=edit&dir=$dir&file=$_">$_~ . '</a>|' .
# easytecc3::filesize($filesize) . '|' .
# easytecc3::getdate($filedate) . '|' .
# qq~<a href="/cgi-bin/easytecc3/index.pl?action=modify_file&type=chmod&dir=$dir&file=$_">~ . qq~$fileperm/$username_lookup{$owner}~ . '</a>|' .
# qq~<a href="http://$ENV{'SERVER_NAME'}/$filelink" target="_blank">L__Ansehen__L</a>
# <a href="/cgi-bin/easytecc3/index.pl?action=modify_file&type=cp&dir=$dir&file=$_">L__Kopieren__L</a>
# <a href="/cgi-bin/easytecc3/index.pl?action=modify_file&type=mv&dir=$dir&file=$_">L__Umbenennen__L</a>
# <a href="/cgi-bin/easytecc3/index.pl?action=modify_file&type=rm&dir=$dir&file=$_">L__Löschen__L</a>
# <a href="/cgi-bin/easytecc3/index.pl?action=download_file&dir=$dir&file=$_">Download</a>~
#);
}
#easytecc3::table(\$template,'<td>L__Dateiname__L</td><td>L__Größe__L</td><td>L__Letzte Änderung__L</td><td>L__CHMOD/user__L</td><td colspan="3">L__Aktionen__L</td>', \@filemanager, 'table1');
$template->param('pwd' => $pwd);
$template->param('pwd_encoded' => encode_base64url($pwd));
$template->param('dir_password_protection' => encode_base64url($input{'dir'}));
easytecc3::table_e4($template, $table_data_dir, 'table_tr_show_filemanager_dir_template.html');
easytecc3::table_e4($template, $table_data_file, 'table_tr_show_filemanager_file_template.html');
# Aktionsmöglichkeiten für .htaccess:
# -anlegen oder
# -editieren, löschen
# wenn es .htaccess gibt
if(-e qq~$pwd/.htaccess~){
#und darin Authentifizierung enthalten
if(`grep AuthUserFile $pwd/.htaccess`){
#dann Option für editieren und löschen von .htaccess
$template->param('has_password_protection' => 1);
# $template->param('htaccess_action' => qq~
# <a href="/cgi-bin/easytecc3/index.pl?action=change_htaccess&dir=$input{'dir'}">L__Passwortschutz editieren__L</a><br />
# <a href="/cgi-bin/easytecc3/index.pl?action=delete_htaccess&dir=$input{'dir'}&type=delete_all">L__Passwortschutz löschen__L</a>~);
}
#else{
# #oder Option zum Anlegen von Passwortschutz
# $template->param('htaccess_action' => qq~
# <a href="/cgi-bin/easytecc3/index.pl?action=new_htaccess&dir=$input{'dir'}">L__Passwortschutz anlegen__L</a>~);
#}
}
#else{
# #oder Option zum Anlegen von Passwortschutz
# $template->param('htaccess_action' => qq~
# <a href="/cgi-bin/easytecc3/index.pl?action=new_htaccess&dir=$input{'dir'}">L__Passwortschutz anlegen__L</a>~);
#}
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_htpasswd{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_htpasswd.html');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_logfiles{
if($session->param('show_logs') ne '1'){
return start();
}
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_logfiles.html');
my %logs;
my @logs = ();
if ($fb) {
@logs = `/usr/iports/bin/sudo /usr/sbin/dellogs`;
}
else{
@logs = `/usr/sbin/dellogs`;
}
#actually no maillog download for external mailservers
my $extern_mx = easytecc3::extern_mx();
my @logfiles = ();
my $all_logs_size = '';
my $quotabalken = '';
my $quota = `cat /etc/vsd/quota`;
chomp $quota;
my $domain_tmp = '';
my @syslog = ();
my %sorted_logs;
my $table_data_syslog = {};
my $table_data_domainlog = {};
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my $edit_logs = '';
if($session->param('user') eq 'admin'){
$edit_logs = '1';
$template->param('is_admin' => '1');
} else {
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my $gecos = $passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.logs-1';
}
if($gecos =~ m/\.logs-[1-9]/){
$edit_logs = '1';
}
}
foreach(@logs){
last if /^Geben Sie/;
next if /^-/;
next if /^$/;
next if /^dellogs/;
next if /(Domainname|Alle|Systemlogs)/;
my ($domain, $logfile, $size) = split /\|/, $_;
$domain =~ s/\s//gc;
# in Zeile für errorlog taucht keine Domain auf, bei so einer Zeile einfach die zuletzt gespeicherte Domain nehmen
# hostnet.de | speedlog | 1.00 MB
# | error_log_hostnet.de | 8.00 kB
$domain_tmp = $domain if $domain;
$logfile =~ s/^\s+//;
$logfile =~ s/\s+$//;
$size =~ s/^\s+(.*)\s+$/$1/gc;
# filter domains
if($session->param('user') ne 'admin'){
my $admins = $domains{'www.' . $domain_tmp}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $session->param('user') . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
}
#use logfile name from httpd.conf instead dellogs
if ($logfile =~ /^access_log/ && length($domains{"www.$domain"}{'access_log'})) {
$logfile = $domains{"www.$domain"}{'access_log'};
$logfile =~ s/^.*\///;
$sorted_logs{$domain}{'access'} = $logfile;
$sorted_logs{$domain}{'access_size'} = $size;
}
elsif ($logfile =~ /^error_log/ && length($domains{"www.$domain_tmp"}{'error_log'})) {
$logfile = $domains{"www.$domain_tmp"}{'error_log'};
$logfile =~ s/^.*\///;
$sorted_logs{$domain_tmp}{'error'} = $logfile;
$sorted_logs{$domain_tmp}{'error_size'} = $size;
}
#else{
#$sorted_logs{$domain_tmp}{'error'} = $logfile;
# $sorted_logs{$domain_tmp}{'error_size'} = $size;
#}
if($logfile =~ /^(Access Logs|Error Logs|Messages|Maillogs)/){
$size =~ /^(.*)\s(.*)$/;
# Grösse kann in kB oder MB angegeben werden, alles auf MB umrechnen und summieren
my $size_unscaled = $1;
my $scale = $2;
$size_unscaled = $size_unscaled/1024 if $scale eq 'kB';
$all_logs_size += $size_unscaled;
}
#else{
# logline("debug","Domain:$domain##### Log:$logfile#####");
# logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
#
# if ($domain ne '') {
# $sorted_logs{$domain}{'access'} = $logfile;
# $sorted_logs{$domain}{'access_size'} = $size;
# $sorted_logs{$domain}{'error'} = $logfile;
# $sorted_logs{$domain}{'error_size'} = $size;
# }
# else{
# $sorted_logs{$domain_tmp}{'error'} = $logfile;
# $sorted_logs{$domain_tmp}{'error_size'} = $size;
# }
#}
if($logfile =~ /^(Access Logs)/){
$table_data_syslog->{$logfile}{'deleteable'} = $edit_logs;
$table_data_syslog->{$logfile}{'domain'} = 'L__Alle Domains__L';
$table_data_syslog->{$logfile}{'logfile_name'} = $logfile;
$table_data_syslog->{$logfile}{'logfile_size_sized'} = $size;
$table_data_syslog->{$logfile}{'logfile_name_delete'} = 'alldomains';
}
elsif($logfile =~ /^(Error Logs)/){
$table_data_syslog->{$logfile}{'logfile_name'} = $logfile;
$table_data_syslog->{$logfile}{'logfile_size_sized'} = $size;
}
elsif($logfile =~ /^(Messages|Maillogs)/){
my $all = '';
$all = 'allsystem' unless $fb;
$all = 'all' if $fb;
my $downloadable = '1';
my $deleteable = $edit_logs;
if ( ! $fb && $extern_mx && $logfile =~ /Maillogs/) {
$downloadable = '';
$deleteable = '';
}
$table_data_syslog->{$logfile}{'downloadable'} = $downloadable;
$table_data_syslog->{$logfile}{'deleteable'} = $deleteable;
$table_data_syslog->{$logfile}{'domain'} = 'L__Systemlogs__L';
$table_data_syslog->{$logfile}{'logfile_name'} = $logfile;
$table_data_syslog->{$logfile}{'logfile_size_sized'} = $size;
my $logfile_encoded = encode_base64url($logfile);
$table_data_syslog->{$logfile}{'logfile_href_download'} = qq~/cgi-bin/easytecc4/index.pl?action=download_file&file=$logfile_encoded&type=logfile~;
$table_data_syslog->{$logfile}{'logfile_name_delete'} = 'allsystem';
}
}
foreach(sort keys %sorted_logs){
my $domain = $_;
my $idn_domain = encode('utf-8', domain_to_unicode($domain));
if($sorted_logs{$_}{'access'}){
my $logfile = $sorted_logs{$_}{'access'};
$table_data_domainlog->{$idn_domain}{'deleteable'} = $edit_logs;
$table_data_domainlog->{$idn_domain}{'idn_domain'} = encode('utf-8', domain_to_unicode($domain));
$table_data_domainlog->{$idn_domain}{'domain'} = $domain;
$table_data_domainlog->{$idn_domain}{'logfile_name'} = $sorted_logs{$_}{'access'};
$table_data_domainlog->{$idn_domain}{'logfile_size_sized'} = $sorted_logs{$_}{'access_size'};
my $logfile_encoded = encode_base64url($logfile);
$table_data_domainlog->{$idn_domain}{'logfile_href_download'} = qq~/cgi-bin/easytecc4/index.pl?action=download_file&file=$logfile_encoded&type=logfile~;
#push(@logfiles, domain_to_unicode($_).'|'.$sorted_logs{$_}{'access'}.'|'.$sorted_logs{$_}{'access_size'}.'|'.
# qq~<a href="/cgi-bin/easytecc3/index.pl?action=download_file&file=$logfile&type=logfile">L__Download__L</a>~ .'|'.
# qq~<a href="/cgi-bin/easytecc3/index.pl?action=delete_logfiles&domain=$domain">L__Löschen__L</a>~
#);
}
if($sorted_logs{$_}{'error'}){
my $logfile = $sorted_logs{$_}{'error'};
#'z' is ugly workaround for sorted access and error log output. Nobody has seen it ;)
$table_data_domainlog->{$idn_domain . 'z'}{'logfile_name'} = $sorted_logs{$_}{'error'};
$table_data_domainlog->{$idn_domain . 'z'}{'logfile_size_sized'} = $sorted_logs{$_}{'error_size'};
my $logfile_encoded = encode_base64url($logfile);
$table_data_domainlog->{$idn_domain . 'z'}{'logfile_href_download'} = qq~/cgi-bin/easytecc4/index.pl?action=download_file&file=$logfile_encoded&type=logfile~;
#push(@logfiles, ''.'|'.$sorted_logs{$_}{'error'}.'|'.$sorted_logs{$_}{'error_size'}.'|'.
# qq~<a href="/cgi-bin/easytecc3/index.pl?action=download_file&file=$logfile&type=logfile">L__Download__L</a>~ .'|'.
# ''
#);
}
}
#push(@logfiles, @syslog);
my $percentval = ($all_logs_size/$quota)*100;
##kaufm. Rundung
$percentval = sprintf("%.0f", $percentval);
my $balken_usage = $percentval;
my $balken_free = 100 - $balken_usage;
if(($quota * .8) <= $all_logs_size){
$template->param('logfile_size_alert' => 1);
# $quotabalken = qq|<img src="/easytecc3/images/red.gif" width="$balken_usage" height="15" align="bottom" alt="$balken_usage % genutzt" border="0" /><img src="/easytecc3/images/grey.gif" width="$balken_free" height="15" align="bottom" alt="$balken_free % frei" border="0" />|;
}
#else{
# $quotabalken = qq|<img src="/easytecc3/images/green.gif" width="$balken_usage" height="15" align="bottom" alt="$balken_usage % genutzt" border="0" /><img src="/easytecc3/images/grey.gif" width="$balken_free" height="15" align="bottom" alt="$balken_free % frei" border="0" />|;
#}
$template->param('in_use_MB' => sprintf "%.2f", $all_logs_size);
$template->param('percent' => ' (' . $percentval . '%)');
#$template->param('bar' => $quotabalken);
unless(`grep 'dellogs -a' /home/web/cronfile`){
if(!$fb){
$template->param('add_cron_delete_logfiles' => '1');
}
}
#easytecc3::table(\$template,'<td>L__Domainname__L</td><td>L__Logfile__L</td><td>L__Größe__L</td><td colspan="4">L__Aktionen__L</td>', \@logfiles, 'table1');
easytecc3::table_e4($template, $table_data_domainlog, 'table_tr_show_logfiles_domain_template.html');
if($session->param('user') eq 'admin'){
easytecc3::table_e4($template, $table_data_syslog, 'table_tr_show_logfiles_syslog_template.html');
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub domainsearch{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_domainsearch.html');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub change_errordocs{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'change_errordocs.html');
my $unauthorized_file = `cat $droot_prefix/error_docs/unauthorized.htm`;
my $forbidden_file = `cat $droot_prefix/error_docs/forbidden.htm`;
my $notfound_file = `cat $droot_prefix/error_docs/notfound.htm`;
my $ierror_file = `cat $droot_prefix/error_docs/ierror.htm`;
#$unauthorized_file =~ s/\n/<br />/g;
#$forbidden_file =~ s/\n/<br />/g;
#$notfound_file =~ s/\n/<br />/g;
#$ierror_file =~ s/\n/<br />/g;
$template->param('unauthorized' => $unauthorized_file);
$template->param('forbidden' => $forbidden_file);
$template->param('notfound' => $notfound_file);
$template->param('ierror' => $ierror_file);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_webmailer{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_webmailer.html');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub new_vhost{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = '';
## warum gibt es hier $input{'xxxx'} Felder? Laut grep gibt es kein Form mit action=new_vhost. Woher soll $input kommen?
## TODO: korrigieren
# fehlerhafte felder sollte man auch sehen können...
if($validation_result){
my %error_fields = %$validation_result;
if($error_fields{'special'} || $error_fields{'quota'} || $error_fields{'custom_tag'}){
$input{'extended_options'} = '1';
}
}
$template = HTML::Template->new(filename => 'new_vhost.html');
my $new_ftp = '';
my $new_db = '';
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
if($session->param('user') eq 'admin'){
$new_ftp = '1';
$new_db = '1';
my $userselect='<select id="userselect" name="userselect" class="selectpicker form-control" multiple title="L__Benutzer wählen__L">';
foreach my $ftpuser (sort keys %passwd){
next if $passwd{$ftpuser}{'gecos'} !~ /^CUST/;
$readuserregex = '#' . $ftpuser . '#';
$writeuserregex = '#' . uc $ftpuser . '#';
$userselect .= '<optgroup label="' . $ftpuser . '">';
$userselect .= '<option id="write__' . $ftpuser . '" title="' . uc($ftpuser) . '"';
if($admins =~ m/$writeuserregex/){
$userselect .= ' selected';
}
$userselect .= '>L__schreiben__L</option>';
$userselect .= '<option id="read__' . $ftpuser . '" title="' . lc($ftpuser) . '"';
if($admins =~ m/$readuserregex/){
$userselect .= ' selected';
}
$userselect .= '>L__lesen__L</option>';
$userselect .= '</optgroup>';
}
$userselect .= '</select>';
$userselect .= "
<script type='text/javascript'>
\$('#userselect').on('change', function(e){
var arr = \$('#userselect').data('selectedids') || new Array();
var admin_users = '';
\$(this).find('option').each(function(){
var id = \$(this).attr('id');
var arr_id = id.split('__',2);
var readwrite = arr_id[0];
var user = arr_id[1];
var idx = arr.indexOf(id)
if(\$(this).is(':selected')){
if(idx == -1){
var removeId;
if(readwrite === 'write'){
removeId = 'read__' + user;
} else {
removeId = 'write__' + user;
}
\$('#' + removeId).removeAttr('selected');
var removeIdx = arr.indexOf(removeId);
if(removeIdx > -1){
arr.splice(removeIdx, 1);
}
arr.push(id);
}
} else {
if(idx > -1){
arr.splice(idx, 1);
}
}
});
for (var idx = 0; idx < arr.length; idx++) {
var id = arr[idx];
var arr_id = id.split('__',2);
var readwrite = arr_id[0];
var user = arr_id[1];
if(admin_users.length > 0){
admin_users += ', ';
}
if(readwrite === 'write'){
admin_users += user.toUpperCase();
} else {
admin_users += user.toLowerCase();
}
}
\$(this).data('selectedids',arr);
\$(this).selectpicker('refresh');
\$('#admin_users').val(admin_users);
});
</script>";
$template->param('userselect' => $userselect);
} else {
my $gecos = $passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.ftp-2.db-2';
}
if($gecos =~ m/\.ftp-2/){
$new_ftp = '1';
}
if($gecos =~ m/\.db-2/){
$new_db = '1';
}
}
$template->param('new_ftp' => $new_ftp);
$template->param('new_db' => $new_db);
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my %config = %{$httpd_conf->config_hash()};
if(scalar $config{'listen_80'} > 1){
my $ip = $config{'main_ip'};
$ip = $input{'ip_select'} if exists $input{'ip_select'};
my $template_ip_select = HTML::Template->new(filename => 'ip_select.html');
easytecc3::template_loop(\%input,\$template_ip_select, $config{'listen_80'}, 'ip_select', $ip);
$template->param('ip_select' => $template_ip_select->output);
}
else{
$template->param('ip_select' => $config{'main_ip'});
}
# ich bin fassungslos ob dessen, was ich hier kopier
if(scalar $config{'php_versions'} > 1){
logline("debug","php-versions: " . join(',',@ { $config{'php_versions'} }));
my $php = $config{'server_php'};
$php = $input{'php_select'} if exists $input{'php_select'};
my $template_php_select = HTML::Template->new(filename => 'php_select.html');
easytecc3::template_loop(\%input,\$template_php_select, $config{'php_versions'}, 'php_select', $php);
$template->param('php_select' => $template_php_select->output);
}
# if(-d '/home/httpd/docs/twig' && ! -d '/home/httpd/docs/zarafa'){
# $template->param('twig_select' => 'Twig' . '<input type="checkbox" name="webmail" value="twig" checked><br />');
# }
# elsif(-d '/home/httpd/docs/twig' && -d '/home/httpd/docs/zarafa'){
# $template->param('twig_select' => 'Twig' . '<input type="checkbox" name="webmail" value="twig"><br />');
# $template->param('zarafa_select' => 'Zarafa' . '<input type="checkbox" name="webmail" value="zarafa" checked><br />');
# }
# elsif(-d '/home/httpd/docs/zarafa'){
# $template->param('zarafa_select' => 'Zarafa' . '<input type="checkbox" name="webmail" value="zarafa" checked><br />');
# }
#bei Entryserver keine Option für ftp- und mysqluser und Datenbank anlegen
unless (defined easytecc3::is_ftp_limited()) {
my $template_ftp_mysql = HTML::Template->new(filename => 'new_vhost_ftp_mysql.html');
my $display_ftp = 'none';
$display_ftp = 'block' if $input{'ftp'};
my $display_mysql_db = 'none';
$display_mysql_db = 'block' if $input{'mysql_db'};
# wenn beim Anlegen fehlerhafte Eingabe, dann ggf. ftp und mysql erneut als cheked anzeigen
$template_ftp_mysql->param('checked_ftp' => ' checked') if $input{'ftp'};
$template_ftp_mysql->param('display_ftp' => $display_ftp);
$template_ftp_mysql->param('ftpuser' => $input{'ftpuser'});
$template_ftp_mysql->param('ftppass' => $input{'ftppass'});
$template_ftp_mysql->param('ftpquota' => $input{'ftpquota'});
$template_ftp_mysql->param('ftpdescription' => $input{'ftpdescription'});
$template_ftp_mysql->param('checked_suexec' => ' checked') if $input{'suexec'};
$template_ftp_mysql->param('checked_mysql_db' => ' checked') if $input{'mysql_db'};
$template_ftp_mysql->param('display_mysql_db' => $display_mysql_db);
$template_ftp_mysql->param('db' => $input{'db'});
$template_ftp_mysql->param('dbuser' => $input{'dbuser'});
$template_ftp_mysql->param('dbpass' => $input{'dbpass'});
$template_ftp_mysql->param('new_ftp' => $new_ftp);
$template_ftp_mysql->param('new_db' => $new_db);
# Fehlerklasse für Felder setzen, wo Validierung fehlgeschlagen ist
%error_fields = %$validation_result;
foreach(keys %error_fields){
$template_ftp_mysql->param('error_class_' . $_ => qq~has-error~);
$template_ftp_mysql->param('error_text_' . $_ => qq~<span class="help-block">~ . encode_entities($error_fields{$_}, '<>&"') . qq~</span>~);
}
$template_ftp_mysql->param('has_suexec' => $config{'has_suexec'});
$template->param('new_vhost_ftp_mysql' => $template_ftp_mysql->output);
}
if(!defined($input{'quota'})){
$input{'quota'} = '100000';
}
$template->param('quota' => $input{'quota'});
# show / hide extended options
my $display_extended_options = 'none';
my $checked_extended_options = '';
if ($input{'extended_options'}){
$display_extended_options = 'block';
$checked_extended_options = ' checked';
}
$template->param('display_extended_options' => $display_extended_options);
$template->param('checked_extended_options' => $checked_extended_options);
# if($input{'stats'} eq 'awstats'){
$template->param('checked_awstats' => ' checked');
# }
# elsif($input{'stats'} eq 'webalizer'){
# $template->param('checked_webalizer' => ' checked');
# }
# if($input{'webmail'} eq 'roundcube'){
$template->param('checked_roundcube' => ' checked');
# }
# #Webmailer Zarafa
# elsif($input{'webmail'} eq 'zarafa'){
# $template->param('checked_zarafa' => ' checked');
# }
$template->param('checked_mysql' => ' checked');
$template->param('special' => encode_entities($input{'special'})) if exists $input{'special'};
#set default pop for aut to 10
if (length($input{'pop'}) == '0') {
$template->param('pop' => '10');
}
if (length($input{'for'}) == '0') {
$template->param('for' => '10');
}
if (length($input{'aut'}) == '0') {
$template->param('aut' => '10');
}
if (length($input{'custom_tag'})) {
$template->param('custom_tag' => $input{'custom_tag'});
}
my $default_docroot = '';
if($session->param('user') eq 'admin'){
if($fb){
$default_docroot = '/usr/local/www/apache24/noexec/';
} else {
$default_docroot = '/home/httpd/docs/';
}
if (length($input{'admin_users'})) {
$template->param('admin_users' => $input{'admin_users'});
}
$template->param('show_admin_users' => '1');
$template->param('show_ip_select' => '1');
} else {
$template->param('ip' => $config{'main_ip'});
$input{'admin_users'} = $session->param('user');
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
$default_docroot = $passwd{$input{'admin_users'}}{'home'} . '/';
}
$template->param('show_php_select' => scalar $config{'php_versions'} >= 1 ? '1' : '');
$template->param('default_docroot' => $default_docroot);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub change_vhost{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = '';
$template = HTML::Template->new(filename => 'change_vhost.html');
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my %config = %{$httpd_conf->config_hash()};
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my %home_lookup = %{$passwd->lookup2_hash()};
my ($quotaref, $sum_ftplimit, $sum_ftpuse, $ftpserverlimit) = easytecc3::getquota_ftp();
my %quota = %$quotaref;
my $ftpuser = '';
my $ftpquota = '';
my $ftpquota_sized = '';
my $ftpused = '';
my $quotabalken = '';
my $domain = $input{'domain'};
my $domain_ssl_icon = '';
my $domain_ip_icon = '';
my $domain_ohne_www = $domain;
$domain_ohne_www =~ s/^www\.//;
$domain = 'www.' . $domain unless($domain =~ /^www\./);
my $ftpdir = $domains{$domain}{'droot'};
while(length($ftpdir) && $ftpdir !~ /\/(data|noexec)$/){
if(exists $home_lookup{$ftpdir}){
$ftpuser = $home_lookup{$ftpdir};
$ftpquota = $quota{$ftpuser}{'quota'};
$ftpquota_sized = easytecc3::getsize($ftpquota);
$ftpused = $quota{$ftpuser}{'use'};
$quotabalken = easytecc3::quotabar($ftpquota, $ftpused, 'all');
last;
}
$ftpdir =~ s/\/[^\/]*$//;
}
#if(exists $home_lookup{$domains{$domain}{'droot'}}){
# $ftpuser = $home_lookup{$domains{$domain}{'droot'}};
# $ftpquota = $quota{$ftpuser}{'quota'};
# $ftpquota_sized = easytecc3::getsize($ftpquota);
# $ftpused = $quota{$ftpuser}{'use'};
# $quotabalken = easytecc3::quotabar($ftpquota, $ftpused, 'all');
#}
logline("debug","$domain ssl_enabled=" . $config{'ssl_enabled'} . 'ssl=' . $domains{$domain}{'ssl'} . 'droot=' . $domains{$domain}{'ssl_droot'});
# Kunde - domain specific check
if($session->param('user') ne 'admin'){
my $admins = $domains{$domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$readuserregex = '#' . $session->param('user') . '#';
$writeuserregex = '#' . uc $session->param('user') . '#';
if($admins =~ m/$writeuserregex/){
$template->param('disabled' => '');
} else {
$template->param('disabled' => 'disabled');
}
$gecos = $passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.vhost-1';
}
if($gecos !~ m/\.vhost-[1-9]/){
$template->param('no_quota' => '1');
}
} else {
$template->param('disabled' => '');
}
# wenn SSL-Domain, dann Icon
if($config{'ssl_enabled'} && $domains{$domain}{'ssl'}){
$domain_ssl_icon = qq~<img src="/easytecc3/images/ssl.gif" width="15" height="15" align="bottom" alt="SSL-Domain" border="0" />~;
my $template_ssl = HTML::Template->new(filename => 'ssl_change_vhost.html');
$template_ssl->param('ssl_ip' => $domains{$domain}{'ssl_ip'});
$template_ssl->param('ssl_port' => $domains{$domain}{'ssl_port'});
$template_ssl->param('ssl_droot' => $domains{$domain}{'ssl_droot'});
# take over value from above check
$template_ssl->param('disabled' => $template->param('disabled'));
$template_ssl->param('checked_ssl_force' => ' checked') if $domains{$domain}{'ssl_force'} == '1';
$template_ssl->param('ssl_port' => $input{'ssl_port'}) if exists $input{'ssl_port'};
$template_ssl->param('ssl_droot' => $input{'ssl_droot'}) if exists $input{'ssl_droot'};
# Fehlerklasse für Felder setzen, wo Validierung fehlgeschlagen ist
%error_fields = %$validation_result;
foreach(keys %error_fields){
$template_ssl->param('error_class_' . $_ => qq~class="form-error-label"~);
}
# evtl. haben Port80-vhost und SSL-vhost verschiedene spezielle Einstellungen.
# daher bei SSL-Domain zwei Felder für manuelle eintrge
my $html = '';
foreach(@{$domains{$domain}{'special_ssl'}}){
$html .= $_ . "\n";
}
$template_ssl->param('special_ssl' => encode_entities($html));
$template_ssl->param('special_ssl' => encode_entities($input{'special_ssl'})) if exists $input{'special_ssl'};
$template->param('ssl_change_vhost' => $template_ssl->output);
}
# wenn separate IP, dann Icon
if($config{'main_ip'} ne $domains{$domain}{'ip'}){
$domain_ip_icon = qq~<img src="/easytecc3/images/ip.gif" width="15" height="15" align="bottom" alt="SSL-Domain" border="0" />~;
}
# wenn webserver mehrere IPs hat, dann IPs zur Auswahl stellen, damit Kunde vhost auf andere IP ändern kann
# Evtl. hat er mehrere IPs gemietet und will unterschiedlich aufteilen. Nach Absenden von change_vhost kommt
# Nachfrage, ob vhost nur geändert oder Kopie von vhost mit alter IP für Propagation angelegt werden soll.
if(scalar $config{'listen_80'} > 1){
logline("debug","listen_80: " . join(',',@ { $config{'listen_80'} }));
my $ip = $domains{$domain}{'ip'};
$ip = $input{'ip_select'} if exists $input{'ip_select'};
my $template_ip_select = HTML::Template->new(filename => 'ip_select.html');
easytecc3::template_loop(\%input,\$template_ip_select, $config{'listen_80'}, 'ip_select', $ip);
$template->param('ip_select' => $template_ip_select->output);
}
# ich bin fassungslos ob dessen, was ich hier kopier
if(scalar $config{'php_versions'} > 1){
logline("debug","php-versions: " . join(',',@ { $config{'php_versions'} }));
my $php = $domains{$domain}{'php'};
$php = $input{'php_select'} if exists $input{'php_select'};
my $template_php_select = HTML::Template->new(filename => 'php_select.html');
easytecc3::template_loop(\%input,\$template_php_select, $config{'php_versions'}, 'php_select', $php);
$template->param('php_select' => $template_php_select->output);
}
$template->param('openbasedir' => $domains{$domain}{'openbasedir'});
# .user.ini link
my $dir_encoded = $domains{$domain}{'droot'};
$dir_encoded =~ s#^(/home/httpd/docs/|/usr/local/www/apache24/(noexec|data)/)##;
$dir_encoded = encode_base64url($dir_encoded);
my $file_encoded = encode_base64url('.user.ini');
$template->param('file_href_edit' => qq~modify_file&type=edit&dir=$dir_encoded&file=$file_encoded~);
# wenn mindestens ein Scriptalias diesen als änderbares Feld anzeigen, aber nur Standard-Scriptaliase /cgi-bin/ und /cgi-local/.
# Eigene landen in manuelle Eintrge
my $has_cgi_bin = '';
my $has_cgi_local = '';
#script alias cgi-local always in data instead noexec
my $droot_data = $domains{$domain}{'droot'};
$droot_data =~ s/\/noexec\//\/data\//;
if(scalar $domains{$domain}{'scriptalias'} >= 1){
foreach(@{$domains{$domain}{'scriptalias'}}){
if(/^ScriptAlias\s+\/cgi-bin(\/|\s)\s*\/home\/httpd\/cgi-bin[\/]{0,1}$/ && ! $fb){
$template->param('checked_cgi-bin' => ' checked');
$has_cgi_bin = '1';
}
elsif(/^ScriptAlias\s+\/cgi-bin(\/|\s)\s*\/usr\/local\/www\/apache24\/cgi-bin[\/]{0,1}$/ && $fb){
$template->param('checked_cgi-bin' => ' checked');
$has_cgi_bin = '1';
}
elsif(/^ScriptAlias\s+\/cgi-local(\/|\s)\s*$droot_data\/cgi-local[\/]{0,1}$/){
$template->param('checked_cgi-local' => ' checked');
$has_cgi_local = '1';
}
#kein Standard-Scriptalias, kommt in manuelle Eintrge
else{
push @{$domains{$domain}{'special'}}, $_;
}
}
}
if($domains{$domain}{'roundcube'} == '1' || $fb){
$template->param('checked_roundcube' => ' checked');
}
if($domains{$domain}{'redirect_domain'}){
$template->param('redirect_domain' => $domains{$domain}{'redirect_domain'});
}
#Alias für phpmyadmin
if($domains{$domain}{'mysql'}){
$template->param('checked_mysql' => ' checked');
}
logline("debug",qq~Log:$domains{$domain}{'access_log'}~);
#Logs
if($domains{$domain}{'access_log'}){
$template->param('stats' => qq~accesslog: <input type="text" name="access_log" value="$domains{$domain}{'access_log'}" size="45"><br />
errorlog: <input type="text" name="error_log" value="$domains{$domain}{'error_log'}" size="45"><br />~);
}
#awstats oder webalizer oder nix wenn change_vhost zum ersten mal aufgerufen wird
unless($input{'stats'}){
if(-e "$awstats_conf_prefix/awstats.$domain_ohne_www.conf"){
$template->param('checked_awstats' => ' checked');
}
elsif(`grep '/usr/local/etc/$domain_ohne_www.conf' /home/web/cronfile`){
$template->param('checked_webalizer' => ' checked');
}
else {
$template->param('checked_nostats' => ' checked');
}
}
#falls exec_change_vhost mit Fehler, dann wird change_vhost erneut aufgerufen, die Vorauswahl wieder übernehmen
else{
if($input{'stats'} eq 'awstats'){
$template->param('checked_awstats' => ' checked');
}
elsif($input{'stats'} eq 'webalizer'){
$template->param('checked_webalizer' => ' checked');
}
else {
$template->param('checked_nostats' => ' checked');
}
}
$template->param('vhost' => $domain);
$template->param('domain' => $domain_ohne_www);
$template->param('idn_domain' => encode('utf-8', domain_to_unicode($domain_ohne_www)));
$template->param('domain_ssl_icon' => $domain_ssl_icon);
$template->param('domain_ip_icon' => $domain_ip_icon);
$template->param('ip' => $domains{$domain}{'ip'});
$template->param('port' => $domains{$domain}{'port'});
$template->param('quota' => $domains{$domain}{'quota'});
$template->param('quotabar' => qq~<input type="hidden" name="ftpuser" value="$ftpuser" /><input type="hidden" name="ftpquota" value="$ftpquota" /> L__FTP-User__L $ftpuser: $quotabalken~);
$template->param('serveradmin' => $domains{$domain}{'serveradmin'});
$template->param('droot' => $domains{$domain}{'droot'});
$template->param('access_log' => $domains{$domain}{'access_log'});
$template->param('error_log' => $domains{$domain}{'error_log'});
$template->param('pop' => $domains{$domain}{'pop'});
$template->param('for' => $domains{$domain}{'for'});
$template->param('aut' => $domains{$domain}{'aut'});
$template->param('custom_tag' => $domains{$domain}{'custom_tag'});
$template->param('show_php_select' => scalar $config{'php_versions'} >= 1 ? '1' : '');
$template->param('ftp_user' => $ftpuser);
if($session->param('user') eq 'admin'){
$template->param('admin_users' => $domains{$domain}{'admin_users'});
$template->param('show_admin_users' => '1');
$template->param('show_ip_select' => '1');
$template->param('disabled' => '');
my $admins = $domains{$domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
my $userselect='<select id="userselect" name="userselect" class="selectpicker form-control" multiple title="L__Benutzer wählen__L">';
foreach my $ftpuser (sort keys %passwd){
next if $passwd{$ftpuser}{'gecos'} !~ /^CUST/;
$readuserregex = '#' . $ftpuser . '#';
$writeuserregex = '#' . uc $ftpuser . '#';
$userselect .= '<optgroup label="' . $ftpuser . '">';
$userselect .= '<option id="write__' . $ftpuser . '" title="' . uc($ftpuser) . '"';
if($admins =~ m/$writeuserregex/){
$userselect .= ' selected';
}
$userselect .= '>L__schreiben__L</option>';
$userselect .= '<option id="read__' . $ftpuser . '" title="' . lc($ftpuser) . '"';
if($admins =~ m/$readuserregex/){
$userselect .= ' selected';
}
$userselect .= '>L__lesen__L</option>';
$userselect .= '</optgroup>';
}
$userselect .= '</select>';
$userselect .= "
<script type='text/javascript'>
\$('#userselect').on('change', function(e){
var arr = \$('#userselect').data('selectedids') || new Array();
var admin_users = '';
\$(this).find('option').each(function(){
var id = \$(this).attr('id');
var arr_id = id.split('__',2);
var readwrite = arr_id[0];
var user = arr_id[1];
var idx = arr.indexOf(id)
if(\$(this).is(':selected')){
if(idx == -1){
var removeId;
if(readwrite === 'write'){
removeId = 'read__' + user;
} else {
removeId = 'write__' + user;
}
\$('#' + removeId).removeAttr('selected');
var removeIdx = arr.indexOf(removeId);
if(removeIdx > -1){
arr.splice(removeIdx, 1);
}
arr.push(id);
}
} else {
if(idx > -1){
arr.splice(idx, 1);
}
}
});
for (var idx = 0; idx < arr.length; idx++) {
var id = arr[idx];
var arr_id = id.split('__',2);
var readwrite = arr_id[0];
var user = arr_id[1];
if(admin_users.length > 0){
admin_users += ', ';
}
if(readwrite === 'write'){
admin_users += user.toUpperCase();
} else {
admin_users += user.toLowerCase();
}
}
\$(this).data('selectedids',arr);
\$(this).selectpicker('refresh');
\$('#admin_users').val(admin_users);
});
</script>";
$template->param('userselect' => $userselect);
}
#Eingabefeld für weitere Domainnamen
my $serveralias = '';
foreach(@{$domains{$domain}{'domains'}}){
logline("debug","serveralias = $_");
next if /^www\./;
next if /^$domain_ohne_www$/;
$serveralias .= encode('utf-8', domain_to_unicode($_)) . "\n";
}
$template->param('domains' => qq~$serveralias~);
my $html = '';
unless($input{'special'}){
foreach(@{$domains{$domain}{'special'}}){
$html .= $_ . "\n";
}
}
else{
$html = $input{'special'};
}
$template->param('special' => encode_entities($html));
my $suexec='';
if(!$input{'suexec'}){
if($html =~ /\s*[^#]\s*SuexecUserGroup\s+$ftpuser\s+$ftpuser/){
$suexec='1';
}
}
$template->param('suexec' => $suexec);
$template->param('has_suexec' => $config{'has_suexec'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub new_install{
if($session->param('show_inst') ne '1'){
return start();
}
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'new_install.html');
# saving allowed_domains
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my %allowed_domains = ();
foreach my $domain (keys %domains){
if($session->param('user') ne 'admin'){
my $admins = $domains{$domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $session->param('user') . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
}
foreach my $alias_domain (@{$domains{$domain}{'domains'}}){
$alias_domain =~ s/^www\.//;
$alias_domain =~ s/^\*\.//;
# deny server.han-solo.net
if ($alias_domain =~ m/^[^\.]+\.han-solo\.net$/){
next;
}
$allowed_domains{$alias_domain} = 1;
}
$domain =~ s/^www\.//;
$domain =~ s/^\*\.//;
$allowed_domains{$domain} = 1;
}
# hack: installer kann nicht mit langen listen
if($session->param('user') eq 'admin'){
%allowed_domains = ();
} else {
if(! keys %allowed_domains){
$input{'error'} = 1;
$template = HTML::Template->new(filename => 'index.html');
return error("L__Der Autonistaller kann nicht geladen werden, es sind keine Domains eingerichtet__L");
}
}
$session->param("allowed_domains", join(',', sort keys %allowed_domains));
$session->flush();
# $template->param('domain_select' => '');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub new_install_old{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'new_install.html');
#first check for database connection
my ($dbh, $mysql_connect_error) = easytecc3::mysql_connect();
if ($mysql_connect_error == '1'){
logline("error","<<< Leaving ".(caller(0))[3]."() by mysql connect error.");
return(add_mysql_password());
}
$dbh->disconnect;
my $domain = $input{'domain'};
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my @idn_domains = ();
foreach my $domain (sort keys %domains){
logline("debug","foreach = $domain");
#wildcard nicht für Weiterleitung anbieten
next if(/\*/);
#push @idn_domains, domain_to_unicode($_ . '|' . qq~value="$_"~;
#push @idn_domains, $_;
my $domain_ohne_www = $domain;
$domain_ohne_www =~ s/^www\.//;
push @idn_domains, encode('utf-8', domain_to_unicode($domain_ohne_www));
}
my $template_domain_select = HTML::Template->new(filename => 'domain_select.html');
easytecc3::template_loop_e4(\%input,\$template_domain_select, \@idn_domains, "domain_select$forcount", $input{"domain_select$forcount"} ? encode('utf-8', domain_to_unicode($input{"domain_select$forcount"})) : encode('utf-8', domain_to_unicode($domain)));
$template->param('domain_select' => $template_domain_select->output);
if (length($input{'active_tab'})) {
$template->param('new_install_active_tab'.$input{'active_tab'} => 1);
}
else{
$template->param('new_install_active_tab1' => 1);
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub confirm_new_install{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'confirm_new_install.html');
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
$template->param('install' => $input{'install'});
$template->param('domain' => $input{'domain'});
$template->param('droot' => $domains{'www.'.$input{'domain'}}{'droot'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_new_install{
}
sub change_popuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'change_popuser.html');
$template = HTML::Template->new(filename => 'change_popuser_admin_extern_mailserver.html') if $input{'domain'} eq 'www.administrator';
my $email = '';
my $popcount = 1;
my $quotabalken = '';
my $password = '';
my @user = ();
my $domain = $input{'domain'};
$domain =~ s/^www\.//;
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my %passwd = ();
my %mailquota = ();
my ($mailquotaref, $sum_maillimit, $sum_mailuse, $mailserverlimit);
### Mario: Passwörter nicht mehr anzeigen ###
logline("debug","ShowMailuserPasswords: $easytecc_custom_conf_entries{'ShowMailuserPasswords'}");
if ( "$easytecc_custom_conf_entries{'ShowMailuserPasswords'}" eq "NO" ) {
logline ("debug","ShowMailuserPasswords=NO");
$template->param('do_not_show_password' => '1');
} else {
logline ("debug","ShowMailuserPasswords=YES");
}
# zum gucken, ob es FTP-User gibt, die passwd vom Webserver auslesen, und gucken ob es zum
# document root der Domain einen FTP-User mit passendem home-Verzeichnis gibt
logline("debug","Creating File Object \$webserver_passwd.");
my $webserver_passwd = file->new({file_name => '/etc/passwd'});
$webserver_passwd->read_file;
my %webserver_passwd = %{$webserver_passwd->file_parsed_hash()};
my %home_lookup = %{$webserver_passwd->lookup2_hash()};
my ($quotaref, $sum_ftplimit, $sum_ftpuse, $ftpserverlimit) = easytecc3::getquota_ftp();
my %quota = %$quotaref;
if (easytecc3::extern_mx() || $fb) {
$mailpasswd = easytecc3::get_mailpasswd();
%passwd = %{$mailpasswd->file_parsed_hash()};
($mailquotaref, $sum_maillimit, $sum_mailuse, $mailserverlimit) = easytecc3::getquota_mail(\%passwd);
%mailquota = %$mailquotaref;
#%mailquota = %passwd;
}
#elsif (easytecc3::extern_mx()){
# $mailpasswd = easytecc3::get_mailpasswd();
# %passwd = %{$mailpasswd->file_parsed_hash()};
#
# #%passwd = %{easytecc3::get_mailpasswd()};
# ($mailquotaref, $sum_maillimit, $sum_mailuse, $mailserverlimit) = easytecc3::getquota_mail();
# %mailquota = %$mailquotaref;
#}
else{
%passwd = %webserver_passwd;
%mailquota = %quota;
$sum_maillimit = $sum_ftplimit;
$sum_mailuse = $sum_ftpuse;
$mailserverlimit = $ftpserverlimit;
}
# hide mailserver domains for non admin, show edit
my $show_vhost = '';
my $disabled = '';
my $servername = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
chomp $servername;
if($session->param('user') eq 'admin'){
$show_vhost = '1';
$disabled = '';
if($input{'domain'} eq $servername){
$domains{$servername}{'pop'} = 1;
$domains{$servername}{'for'} = 1;
$domains{$servername}{'aut'} = 0;
}
} else {
my $passwd_ftp = file->new({file_name => '/etc/passwd'});
$passwd_ftp->read_file;
my %passwd_ftp = %{$passwd_ftp->file_parsed_hash()};
my $gecos = $passwd_ftp{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.vhost-1.email-1';
}
if($gecos =~ m/\.vhost/){
$show_vhost = '1';
}
if($gecos !~ m/\.email-[1-9]/){
$disabled = 'disabled';
}
}
$template->param('show_vhost' => $show_vhost);
$template->param('disabled' => $disabled);
my $splitted_domains = join '|', @{$domains{$input{'domain'}}{'domains'}};
$splitted_domains =~ s/\*/\\*/g;
logline("debug","splitted_domains = $splitted_domains");
logline("debug","servername = $servername");
my $admin_delete_disabled = ($domain eq 'administrator' || $input{'domain'} eq $servername) ? 'DISABLED': '';
logline("debug","admin_delete_disabled = $admin_delete_disabled");
my $table_data = {};
foreach my $user(sort keys %passwd){
if(
$domain eq 'administrator' && $user ne 'admin' ||
$input{'domain'} eq $servername && $user ne 'admin@' . $servername ||
$input{'domain'} ne $servername && $passwd{$user}{'gecos'} !~ /^($splitted_domains) - POP/
){
logline("debug","skipping user $user");
next;
}
my $mailquota_sized = $mailquota{$user}{'quota'} / 1024;
my $quotabalken = easytecc3::quotabar($mailquota{$user}{'quota'}, $mailquota{$user}{'use'}, 'used');
$password = value("$passwd{$user}{'dec'}", "pass$popcount") if $input{'form_submit'};
#$password = decode("utf8", value("$passwd{$user}{'dec'}", "pass$popcount")) if not exists $input{'form_submit'};
$password = value("$passwd{$user}{'dec'}", "pass$popcount") if not exists $input{'form_submit'};
push(@user, qq~<input type="hidden" name="old_user$popcount" value="$user" />
<input type="hidden" name="old_pass$popcount" value="$passwd{$user}{'dec'}" />
<input type="hidden" name="old_quota$popcount" value="$mailquota_sized" />
<input type="checkbox" name="delete$popcount" id="delete$popcount" value="$user" $admin_delete_disabled />
<input name="user$popcount" type="text" id="user$popcount" value=~ . value("$user", "user$popcount") . qq~size="20" />~ . '|' .
qq~<input name="pass$popcount" type="text" id="pass$popcount" value=~ . $password . qq~size="20" />~ . '|' .
qq~<input name="quota$popcount" type="text" id="quota$popcount" value=~ . value("$mailquota_sized", "quota$popcount") . qq~size="6" /> MB~ . '|' .
qq~$quotabalken~
);
logline("debug","change_popuser table_data user=$user");
if($input{'domain'} eq $servername){
$table_data->{$user}{'domain'} = $domain;
} else {
$table_data->{$user}{'domain'} = 'www.'.$domain;
}
$table_data->{$user}{'popcount'} = $popcount;
$table_data->{$user}{"user"} = $user;
$table_data->{$user}{"user_idn"} = encode('utf-8', email_to_unicode($user));
$table_data->{$user}{"pass"} = $password;
$table_data->{$user}{"oldpass"} = $passwd{$user}{'dec'};
#$table_data->{$user}{"quota"} = $fb ? $mailquota{$user}{'quota'} : $mailquota_sized;
$table_data->{$user}{"quota"} = $input{"quota$popcount"} ? $input{"quota$popcount"} : $mailquota{$user}{'quota'} / 1024;
$table_data->{$user}{'mailquota_used_sized'} = easytecc3::getsize($mailquota{$user}{'use'});
$table_data->{$user}{'mailquota_used_percent'} = sprintf("%.0f", ($mailquota{$user}{'use'}/$mailquota{$user}{'quota'})*100) if $mailquota{$user}{'quota'} > 0;
$table_data->{$user}{'alert_mailuser_quota'} = easytecc3::quota_alert($mailquota{$user}{'quota'}, $mailquota{$user}{'use'}, '.8');
$table_data->{$user}{"error_class_user"} = error_class("user$popcount");
$table_data->{$user}{"error_class_pass"} = error_class("pass$popcount");
$table_data->{$user}{"error_class_quota"} = error_class("quota$popcount");
$table_data->{$user}{"error_text_user"} = qq~<span class="help-block">$error_fields{"user$popcount"}</span>~ if $error_fields{"user$popcount"};
$table_data->{$user}{"error_text_pass"} = qq~<span class="help-block">$error_fields{"pass$popcount"}</span>~ if $error_fields{"pass$popcount"};
$table_data->{$user}{"error_text_quota"} = qq~<span class="help-block">$error_fields{"quota$popcount"}</span>~ if $error_fields{"quota$popcount"};
$table_data->{$user}{"error_text_quota"} = qq~<span class="help-block">$error_fields{"quota$popcount"}</span>~ if $error_fields{"quota$popcount"};
$table_data->{$user}{'disabled'} = $disabled;
$table_data->{$user}{'delete_disabled'} = $admin_delete_disabled;
if(-x '/usr/iports/bin/imapsync' || -x '/usr/local/bin/imapsync'){
$table_data->{$user}{'HAS_IMAPSYNC'} = '1';
# imapsync running
my $pidfile = "/tmp/imapsync-$user.pid";
if(-f $pidfile){
$table_data->{$user}{'IMPORT_RUNNING'} = '1';
}
my $logfile = "/tmp/imapsync-$user.log";
if(-f $logfile){
$table_data->{$user}{'IMPORT_DONE'} = '1';
my $successfile = "/tmp/imapsync-$user.ok";
if (! -f $successfile){
$table_data->{$user}{'IMPORT_ERROR'} = '1';
}
}
}
my $easytecc_enable_file = "/usr/local/etc/easytecc/mailuser/$user";
if(-e $easytecc_enable_file){
$table_data->{$user}{'HAS_EASYTECC'} = '1';
if(-e "/usr/local/etc/easytecc/2fa/$user"){
$table_data->{$user}{'HAS_2FA'} = '1';
}
}
my @keys = ('EMAILUSER',$user);
my $note = note_from_hashfile(\@keys);
if($note->{title}){
$table_data->{$user}{'note_title'} = $note->{title};
$table_data->{$user}{'note_text'} = $note->{text};
}
# fix perms
`/usr/iports/bin/sudo /usr/sbin/chown.pl virtmail:vuser /home/$user`;
$popcount++;
}
logline("debug","pop = " . $domains{$input{'domain'}}{'pop'});
# leere Felder
#bei freebsd dmr ist Anzahl von Emailusern 'for' da Emailuser gleichzeitig Emailadressen mit Weiterleitung auf den User sind
#if ($fb) {
#damit leere Felder auch auf freebsd angezeigt werden, nicht hüpsch aber egal
# $domains{$input{'domain'}}{'pop'} = $domains{$input{'domain'}}{'for'};
#}
my $add_empty_lines = `cat /usr/local/etc/easytecc/new_mail_lines 2>/dev/null`;
chomp $add_empty_lines;
if(!defined($add_empty_lines) || $add_empty_lines !~ m/^[0-9]+$/){
$add_empty_lines = 5;
}
my $max_empty_lines = $popcount + $add_empty_lines;
while($domains{$input{'domain'}}{'pop'} >= $popcount && $popcount < $max_empty_lines){
push(@user, qq~<input type="hidden" name="old_user$popcount" value="" />
<input type="checkbox" name="delete$popcount" id="delete$popcount" value="" DISABLED />
<input name="user$popcount" type="text" id="user$popcount" value=~ . value("", "user$popcount") . qq~size="20" />~ . '|' .
qq~<input name="pass$popcount" type="text" id="pass$popcount" value=~ . value("", "pass$popcount") . qq~size="20" />~ . '|' .
qq~<input name="quota$popcount" type="text" id="quota$popcount" value=~ . value("", "quota$popcount") . qq~size="6" /> MB~
);
my $user = 'zzz'.$popcount unless $input{"user$popcount"};
$user = $input{"user$popcount"} if length($input{"user$popcount"});
$table_data->{$user}{"newuser"} = 1;
$table_data->{$user}{"user"} = encode('utf-8', $input{"user$popcount"});
$table_data->{$user}{"user_idn"} = encode('utf-8', email_to_unicode($input{"user$popcount"}));
$table_data->{$user}{"pass"} = encode('utf-8', $input{"pass$popcount"});
$table_data->{$user}{"quota"} = encode('utf-8', $input{"quota$popcount"});
$table_data->{$user}{"error_class_user"} = error_class("user$popcount");
$table_data->{$user}{"error_class_pass"} = error_class("pass$popcount");
$table_data->{$user}{"error_class_quota"} = error_class("quota$popcount");
$table_data->{$user}{"error_text_user"} = qq~<span class="help-block">$error_fields{"user$popcount"}</span>~ if $error_fields{"user$popcount"};
$table_data->{$user}{"error_text_pass"} = qq~<span class="help-block">$error_fields{"pass$popcount"}</span>~ if $error_fields{"pass$popcount"};
$table_data->{$user}{"error_text_quota"} = qq~<span class="help-block">$error_fields{"quota$popcount"}</span>~ if $error_fields{"quota$popcount"};
$table_data->{$user}{"popcount"} = $popcount;
$table_data->{$user}{"disabled"} = $disabled;
if($fb){
$table_data->{$user}{"placeholder"} = encode('utf-8',email_to_unicode("adresse$popcount\@$domain"));
} else {
$table_data->{$user}{"placeholder"} = "benutzer$popcount";
}
if($input{'domain'} eq $servername){
$table_data->{$user}{'domain'} = $domain;
} else {
$table_data->{$user}{'domain'} = 'www.'.$domain;
}
$popcount++;
}
if(
$home_lookup{$domains{$input{'domain'}}{'droot'}} ne '' ||
$input{'domain'} eq $servername
){
my $ftpuser = $home_lookup{$domains{$input{'domain'}}{'droot'}};
if($input{'domain'} eq $servername){
$ftpuser = 'admin';
}
my $ftpquota = $quota{$ftpuser}{'quota'};
my $ftpquota_sized = $ftpquota / 1024;
my $ftpused = $quota{$ftpuser}{'use'};
my $quotabalken = easytecc3::quotabar($ftpquota, $ftpused);
logline("debug","change_pop mit ftp = $ftpuser");
my @ftpuser = ($ftpuser . '|' . qq~<input type="hidden" NAME="ftpuser" value="$ftpuser" />
<input type="hidden" name="old_ftpquota" value="$ftpquota_sized" />
<input name="ftpquota" id="ftpquota" value=~ . value("$ftpquota_sized", "ftpquota") . qq~size="6" /> MB~);
#easytecc3::table(\$template,'<td>L__FTP-User dieser Domain__L</td><td colspan="6">L__FTP-Quota__L</td>', \@ftpuser, 'table2');
$template->param('ftpquota' => $ftpquota_sized);
if($input{'domain'} eq $servername){
$domains{$input{'domain'}}{'quota'} = $ftpquota_sized;
}
}
easytecc3::table_e4($template, $table_data, 'table_tr_change_popuser_template.html');
#easytecc3::table(\$template,'<td>L__Username__L</td><td>L__Passwort__L</td><td>L__E-Mail-Quota__L</td><td colspan="4">L__Quotanutzung__L</td>', \@user, 'table1');
$template->param('domain' => $input{'domain'});
$template->param('idn_domain' => encode('utf-8', domain_to_unicode($input{'domain'})));
if($domains{$input{'domain'}}{'quota'}){
my $mailquota;
if($domain eq $servername){
$mailquota = $quota{'admin'}{'quota'} / 1024;
}
else{
$mailquota = $domains{$input{'domain'}}{'quota'};
my $ftpdir = $domains{$input{'domain'}}{'droot'};
while(length($ftpdir) && $ftpdir !~ /\/(data|noexec)$/){
if(exists $home_lookup{$ftpdir}){
my $ftpuser = $home_lookup{$ftpdir};
$mailquota = (($domains{$input{'domain'}}{'quota'} * 1024 ) - $quota{$ftpuser}{'quota'}) / 1024;
last;
}
$ftpdir =~ s/\/[^\/]*$//;
}
}
$template->param('quota' => $mailquota . ' MB');
}
$template->param('delete_disabled' => $admin_delete_disabled);
logline("debug","change_pop action=$action input-action=" . $input{'action'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub show_single_edit_email{
change_forward();
}
sub new_forward_single_edit{
change_forward();
}
sub change_forward_single_edit{
change_forward();
}
sub change_forward{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
#my $ref_fb = (caller(0))[3] . '_fb';
#if(defined *$ref_fb{CODE}){return($ref_fb->(@args));}
# lhs = left hand side
# rhs = right hand side
# weiterleitungen editieren:
# in Freifeld Namen von Usern wenn mehrere Empfänger
# Autoresponder anlegen/editieren/löschen
# wenn Autoresponder, dann aus aliases Empfänger
# Autoresponder löschen:
# bein editieren von Weiterleitung
# als Formularbutton beim editieren von Autoresponder
# Autoresponderübersicht wie bisher auer anstatt Email-Copyempfänger
# selectbox mit angelegten E-Mailadressen
# beim editieren von Weiterleitungen anzeigen, ob Autoresponder angelegt + Link
# in aliases ist lokaler user oder externe E-Mailadresse
my $template = HTML::Template->new(filename => 'change_forward.html') if ($action eq 'change_forward' ||
$action eq 'change_forward_single_edit' ||
$action eq 'new_forward_single_edit');
#same output expect selectboxes and non modal and all read only
$template = HTML::Template->new(filename => 'show_single_edit_email.html') if $action eq 'show_single_edit_email';
my $do_not_show_ascii_autoresponder = 0;
if ( "$easytecc_custom_conf_entries{'ShowASCIIAutoresponder'}" eq "NO" ) {
$do_not_show_ascii_autoresponder = 1;
}
$template->param('do_not_show_ascii_autoresponder' => $do_not_show_ascii_autoresponder);
my $email = '';
my $forcount = '1';
my $autcount = '';
my @forward = ();
my @popuser = ();
my @popuser_idn = ();
# hash zum schnelleren lokalisieren existierender pop3user
my %popuser_lookup = undef;
my $domain = $input{'domain'};
$domain =~ s/^www\.//;
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
return(error('L__Der Benutzer oder die Domain existiert nicht__L')) unless exists $domains{$input{'domain'}};
#$error_fields{"non_specific"} .= "L__Der Benutzer oder die Domain existiert nicht__L" unless exists $domains{$input{'domain'}};
logline("debug","Creating File Object \$virtmaps.");
my $virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %virtmaps = %{$virtmaps->file_parsed_hash()};
logline("debug","Creating File Object \$aliases.");
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
$mailpasswd = easytecc3::get_mailpasswd();
my %passwd = %{$mailpasswd->file_parsed_hash()};
my $splitted_domains = join '|', @{$domains{$input{'domain'}}{'domains'}};
$splitted_domains =~ s/\*/\\*/g;
logline("debug","splitted_domains = $splitted_domains");
my $show_vhost = '';
my $disabled = '';
if($session->param('user') eq 'admin'){
$show_vhost = '1';
$disabled = '';
} else {
my $passwd_ftp = file->new({file_name => '/etc/passwd'});
$passwd_ftp->read_file;
my %passwd_ftp = %{$passwd_ftp->file_parsed_hash()};
my $gecos = $passwd_ftp{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.vhost-1.email-1';
}
if($gecos =~ m/\.vhost/){
$show_vhost = '1';
}
if($gecos !~ m/\.email-[1-9]/){
$disabled = 'disabled';
}
}
$template->param('show_vhost' => $show_vhost);
$template->param('disabled' => $disabled);
#%popuser_lookup enthält alle pop3user oder bei dmr emailadressen (welche gleichzeitig pop3user sind), die zu vhost gehören
if ($fb) {
foreach my $user(sort keys %passwd){
next if $user !~ /@(?:$splitted_domains)$/;
push @popuser, $user;
push @popuser_idn, encode('utf-8', email_to_unicode($user));
$popuser_lookup{$user} = '1';
# fix perms
`/usr/iports/bin/sudo /usr/sbin/chown.pl virtmail:vuser /home/$user`;
}
}
else{
foreach my $user(sort keys %passwd){
next if $passwd{$user}{'gecos'} !~ /^$domain - POP/;
push @popuser, $user;
push @popuser_idn, $user;
$popuser_lookup{$user} = '1';
}
}
my @idn_domains = ();
foreach(@{$domains{$input{'domain'}}{'domains'}}){
logline("debug","foreach = $_");
#wildcard nicht für Weiterleitung anbieten
next if(/\*/);
next if($_ eq $domain);
#push @idn_domains, domain_to_unicode($_ . '|' . qq~value="$_"~;
#push @idn_domains, $_;
push @idn_domains, encode('utf-8', domain_to_unicode($_));
}
# wegen wildcard Domains
@idn_domains = easytecc3::del_array_duplicates(@idn_domains);
# hautpdomain zuerst
unshift @idn_domains, encode('utf-8', domain_to_unicode($domain));
foreach(keys %virtmaps){
my $line = $_ . ' ' . $virtmaps{$_};
#$line = quotemeta($line);
logline("debug","line = $line");
if($line =~ /@(?:$splitted_domains)(?: |\t)+[a-zA-Z_\.\-0-9]+[^_aut](.+)$/){
logline("debug","match $1");
if ($1 eq '_aut'){
logline("debug","match aut");
$autcount++;
}
}
}
my $table_data = {};
foreach(sort keys %virtmaps){
my $emailadress = $_;
#wenn bei exec_change_forward_single_edit Fehler auftritt $input{'forward'} aus post-variablen erzeugen
#aus exec_change_forward_single_edit wird html_error aufgerufen, welches change_forward_single_edit aufruft
#bei single_edit ist es zwangsläufig Nr. 1:
#<input name="old_user1" type="hidden" id="old_user1" value="userpart">
#<input name="old_domain_select1" type="hidden" id="old_domain_select1" value="example.com">
if ($action eq 'change_forward_single_edit' && length($input{'old_domain_select1'})) {
$input{'forward'} = $input{'old_user1'} . '@' . $input{'old_domain_select1'};
}
#einzelne Emailadresse editieren
if ($action eq 'change_forward_single_edit' && $emailadress ne $input{'forward'}) {
next;
}
#einzelne Emailadresse neu anlegen auch über change_forward, wobei die vorhandenen Adressen nicht angezeigt werden sondern nur eine leere Zeile
if ($action eq 'new_forward_single_edit') {
next;
}
my $virtmaps_rhs = $virtmaps{$_};
my $line = $emailadress . ' ' . $virtmaps_rhs;
# Variable für vorausgewählten User, kann aus virtmaps oder aus aliases kommen
#my $user_select = $virtmaps_rhs;
my $user_select = '';
logline("debug","virtmaps line = $line##");
# freefield: da steht immer was drin, wenns an mehrere User geht
my $freefield = '';
#jeder Empfänger steht in eigenem Freifeld
my %freefields;
#if($line =~ /@(?:$splitted_domains)(?: |\t)+[a-zA-Z_\.\-0-9]+[^_aut|_spl](.+)$/){
# (?!.*_aut|.*_spl) = negatives lookahead, gucken ob kein autoresponder oder Weiterleitung an mehrere Empfänger
#if($line =~ /@(?:$splitted_domains)(?: |\t)+(?!.*_aut|.*_spl)([a-zA-Z_\.\-0-9]+)$/){
if($line =~ /@(?:$splitted_domains)(?: |\t)+([a-zA-Z_\.\-0-9@]+)$/){
my ($user,$domain) = split("@", $line);
$domain =~ s/\s+.*$//;
#einzelne Weiterleitung in virtmaps auf externe emailadresse oder bei dmr auf lokalen User
if(is_email($virtmaps_rhs)){
if ($fb) {
#wenn Empfängerdomain zu vhost gehört, dann Vorauswahl in selectbox, ansonsten Freifeld,
#auf diese Weise werden Emailaliase dargestellt
#if ($virtmaps_rhs =~ /@(?:$splitted_domains)$/ && exists $popuser_lookup{$virtmaps_rhs}) {
# $user_select .= "$virtmaps_rhs|";
#}
#else{
$freefield = $virtmaps_rhs . ',';
$freefields{$virtmaps_rhs} = 1;
#}
}
else{
$freefield = $virtmaps_rhs . ',';
$freefields{$virtmaps_rhs} = 1;
$user_select = '';
#wenn auf Nicht-DMR in virtmaps Weiterleitung an externe Emailadresse kann er keinen Autoresponder haben
#da dieser immer über aliases angesteuert wird.
#Icon zur Anlage von neuem Autoresponder zeigen
if($disabled eq ''){
$table_data->{$emailadress}{'new_autoreply'} = 1;
}
}
}
#wenn keine ext. emailadresse und kein lokaler POPuser, kein automreponder und keine Weiterleitung an mehrere user, dann z.B. papierkorb, dummy...
#wegen spam
elsif(! $popuser_lookup{$virtmaps_rhs} && $virtmaps_rhs !~ /(_aut|_spl)$/ && ! exists $aliases{$virtmaps_rhs}){
logline("debug","virtmaps rhs dummy = " . $virtmaps_rhs . "###");
$freefield = $virtmaps_rhs . ',';
$freefields{$virtmaps_rhs} = 1;
$user_select = '';
if($disabled eq ''){
$table_data->{$emailadress}{'new_autoreply'} = 1;
}
}
elsif( ! $fb && $popuser_lookup{$virtmaps_rhs}){
#nicht dmr, einzelne Weiterleitung auf lokalen user
logline("debug","virtmaps rhs local user = " . $virtmaps_rhs . "###");
$user_select .= "$virtmaps_rhs|";
#wenn auf Nicht-DMR in virtmaps Weiterleitung an lokalen User kann er keinen Autoresponder haben
#da dieser immer über aliases angesteuert wird.
#Icon zur Anlage von neuem Autoresponder zeigen
if($disabled eq ''){
$table_data->{$emailadress}{'new_autoreply'} = 1;
}
}
my $autoresponder_icon = '';
if ($domains{$input{'domain'}}{'aut'} >= 1 && $user && $domains{$input{'domain'}}{'aut'} > $autcount){
# Icon für Autoresponder anlegen, aber nur wenn mindestens 1 autoresponde erlaubt und keine catchall-Weiterleitung
$autoresponder_icon = qq~<a href="/cgi-bin/easytecc3/index.pl?action=new_autoreply&forward=$_&domain=$input{'domain'}">L__Neu__L</a>~;
$table_data->{$emailadress}{'has_autoreply'} = 0;
}
# Sonderfälle Autoresponder und Weiterleitungen an mehrere User oder ext. E-Mailadressen. In diesem
# Fall anstatt rhs aus virtmaps das Ziel aus aliases auslesen und anzeigen. Bei Autoresponder ein Icon, da Autoresponder angelegt
# Autoresponder?
if($virtmaps_rhs =~ /(_aut)$/){
# Wenn Autoresponder vorhanden, dann 2 Icons: editieren, löschen
$autoresponder_icon = qq~<a href="/cgi-bin/easytecc3/index.pl?action=change_autoreply&forward=$_&domain=$input{'domain'}">L__Editieren__L</a> ~;
$autoresponder_icon .= qq~<a href="/cgi-bin/easytecc3/index.pl?action=delete_autoreply&forward=$_&domain=$input{'domain'}">L__Löschen__L</a>~;
#$table_data->{$emailadress}{'has_autoreply'} = 1;
#logline("debug",qq~autoreply: virtmaps rhs=$virtmaps{$_} aliases lhs $aliases{$virtmaps{$_} . ':'~);
#rhs aus virtmaps ist lhs aus aliases
if(exists $aliases{$virtmaps_rhs}){
logline("debug","virtmaps = aliases match");
# zur besseren Lesbarkeit temp. Variable
my $aliases_target = $aliases{$virtmaps_rhs};
logline("debug","aut alias target1 = $aliases_target");
if ($aliases_target =~ /\/autoresponder/) {
$table_data->{$emailadress}{'has_autoreply'} = 1;
}
else{
if($disabled eq ''){
$table_data->{$emailadress}{'new_autoreply'} = 1;
}
}
# Ziele sind durch Kommata getrennt
my @aliases_target = split(',', $aliases_target);
# normaler Autoresponder mit lokalem pop3user, diesen in select box vorauswählen
if(exists $popuser_lookup{$aliases_target[0]} && $#aliases_target == 1){
$user_select = $aliases_target[0];
$freefield = '';
logline("debug","aut alias match popuser $aliases_target");
}
elsif($#aliases_target >= 0 && length($aliases_target) > 0){
logline("debug","aut alias aliases_target >= 1 $aliases_target");
foreach my $aliases_target(@aliases_target){
logline("debug","aut alias foreach $aliases_target");
if ($aliases_target =~ /\/autoresponder/) {
next;
}
logline("debug","spl alias target2 = $aliases_target");
#trim whitespaces
$aliases_target =~ s/^\s+//;
$aliases_target =~ s/\s+$//;
if (exists $popuser_lookup{$aliases_target}) {
$user_select .= "$aliases_target|";
}
else{
logline("debug","aut alias target2 = $aliases_target");
$freefield .= $aliases_target . ', ' ;
$freefields{$aliases_target} = 1;
}
#if (exists $popuser_lookup{$aliases_target}) {
# $user_select .= "$aliases_target|";
#}
#else{
# $freefield .= $aliases_target . ', ';
# $freefields{$aliases_target} = 1;
#}
}
# kein vorausgewählter User wenn mehrere Empfänger
#$user_select = '';
}
#else{
#bei normalem Autoresponder ist erster Eintrag der Empfänger
#$user_select = $aliases_target[0];
#$freefield = '';
#}
}
}
#Weiterleitung an mehrere User?
elsif($virtmaps_rhs =~ /_spl$/ || exists $aliases{$virtmaps_rhs}){
#rhs aus virtmaps ist lhs aus aliases
if(exists $aliases{$virtmaps_rhs}){
logline("debug","virtmaps = aliases match");
# Zeile aus aliases sieht so aus:
# mails_wichtig_hostnet_de_spl: frank, admin
# User rausziehen( können auch mehrere sein)
# zur besseren Lesbarkeit temp. Variable
my $aliases_target = $aliases{$virtmaps_rhs};
if ($aliases_target =~ /\/autoresponder/) {
$table_data->{$emailadress}{'has_autoreply'} = 1;
}
else{
if($disabled eq ''){
$table_data->{$emailadress}{'new_autoreply'} = 1;
}
}
# Ziele sind durch Kommata getrennt
my @aliases_target = split(',', $aliases_target);
foreach my $aliases_target(@aliases_target){
#wenn Zeil lokaler pop3user oder bei dmr emailadresse ist welcher als User existiert,
#dann in user select anzeigen. Mehrfachauswahl möglich. Zur Überprüfung gibt es %popuser_lookup
if ($aliases_target =~ /\/autoresponder/) {
next;
}
logline("debug","spl alias target2 = $aliases_target");
#trim whitespaces
$aliases_target =~ s/^\s+//;
$aliases_target =~ s/\s+$//;
my $alias_on_same_server = 0;
#if ($fb) {
#bei dmr sieht Zeile in aliases so aus:
#test1_easytecc4.de_spl: "|/usr/iports/bin/procmail -a test1@easytecc4.de"
#aliases_target ist "|/usr/iports/bin/procmail -a test1@easytecc4.de"
#daraus die Empfängeremailadresse extrahieren
# if ($aliases_target =~ /^"\|\/usr\/iports\/bin\/procmail -a (.*)"$/) {
# $aliases_target = $1;
# $alias_on_same_server = 1;
# logline("debug","spl fb extracted alias target = $aliases_target");
# }
#}
if ($aliases_target =~ /fwd_as_att\s([^"]*)"/){
$aliases_target = $1;
foreach $aliases_target (split(/\s+/,$aliases_target)){
if($aliases_target !~ /^\//){
$freefield .= $aliases_target . ', ';
$freefields{$aliases_target} = 1;
logline("debug","spl fb extracted alias target = $aliases_target");
}
}
}
elsif ($aliases_target =~ /^"\|\/usr\/iports\/bin\/procmail -a (.*)"$/) {
$aliases_target = $1;
if(exists $popuser_lookup{$aliases_target}){
$user_select .= "$aliases_target|";
} else {
push @popuser_idn, $aliases_target;
$freefield .= $aliases_target . ', ';
$freefields{$aliases_target} = 1;
}
}
elsif ($aliases_target !~ /\@/ && exists $popuser_lookup{$aliases_target}) {
$user_select .= "$aliases_target|";
}
else{
$freefield .= $aliases_target . ', ';
$freefields{$aliases_target} = 1;
}
}
}
}
my $template_domain_select = HTML::Template->new(filename => 'domain_select.html');
easytecc3::template_loop_e4(\%input,\$template_domain_select, \@idn_domains, "domain_select$forcount", $input{"domain_select$forcount"} ? encode('utf-8', domain_to_unicode($input{"domain_select$forcount"})) : encode('utf-8', domain_to_unicode($domain)));
$template_domain_select->param('disabled' => $disabled);
my $template_user_select = HTML::Template->new(filename => 'user_select.html');
#bei change_forward kann man in selectbox mehrere User gleichzeitig selektieren, dies sind immer lokale User, beim alten
#System pop3-user und bei dmr Emailadressen die immer gleichzeitig Emailuser sind.
#Vorausgewählte User werden | separiert übergeben
#angegebene auswahl behalten
if(exists($input{"user_select$forcount"})){
if(ord($input{"user_select$forcount"}) == '160'){
$input{"user_select$forcount"} = '';
}
$user_select = join('|',split(/\x0/,$input{"user_select$forcount"}));
}
easytecc3::template_loop_e4(\%input,\$template_user_select, \@popuser_idn, "user_select$forcount", encode('utf-8', email_to_unicode($user_select)));
$template_user_select->param('disabled' => $disabled);
my $user_select_single_edit = $user_select;
$user_select_single_edit =~ s/\|$//g;
$user_select_single_edit =~ s/\|/<br>/g;
my $freefields_single_edit = '';
my @freefields;
my $freefield_count = 1;
my $topmargin = 0;
foreach my $freefield(sort keys %freefields){
logline("debug","foreach freefields key=$freefield forcount=$forcount freefield_count=$freefield_count value=".$input{'freefield'.$forcount.'_'.$freefield_count});
my $old_freefield = $freefield;
if (length $input{'freefield'.$forcount.'_'.$freefield_count}) {
$freefield = $input{'freefield'.$forcount.'_'.$freefield_count};
}
push(@freefields,"$forcount|$freefield_count|$freefield|$topmargin|$old_freefield");
$freefield_count++;
$topmargin = 1;
$freefields_single_edit .= $freefield . '<br>' if length($freefield);
}
foreach my $freefield(sort keys %input){
next if $freefield ne 'freefield'.$forcount.'_'.$freefield_count;
my $freefield_value = $input{$freefield};
push(@freefields,"$forcount|$freefield_count|" . $input{$freefield} . "|$topmargin");
$freefield_count++;
$topmargin = 1;
}
#wenn keine Inhalte für Freifeld vorhanden ein leeres anzeigen
if(scalar @freefields == 0){
push(@freefields,"$forcount|$freefield_count|||");
}
my $template_change_forward_freefields = HTML::Template->new(filename => 'change_forward_freefields.html', global_vars => 1 );
easytecc3::template_loop_e4(\%input,\$template_change_forward_freefields, \@freefields, "freefields");
$template_change_forward_freefields->param('disabled' => $disabled);
# read sieve
$table_data->{$emailadress}{'emailuser'} = $emailadress;
my ($forward_filter, $forward_to, $autoresponder_filter, $autoresponder_subject, $autoresponder_message) = read_sieve($emailadress);
if(length($autoresponder_message)){
$table_data->{$emailadress}{'has_autoreply'} = 1;
$table_data->{$emailadress}{'new_autoreply'} = 0;
}
#if(scalar @{$forward_to}){
#
# if(length($forward_to_list)){
#
# $forward_to_list .= "\n";
#
# }
#
# $forward_to_list .= join("\n",@{$forward_to});
# $forward_to_count += scalar @{$forward_to};
#
#}
# freefield nur ausfllen, wenn Ziel kein regulrer pop3user der Domain ist. In %popuser_lookup befinden sich alle existierenden pop3user des vhosts
# doch blödsinn, dann würde da _aut und _spl drinstehen
# $freefield = $virtmaps{$_} unless exists $popuser_lookup{$user_select};
my $forward_to_list = '';
my $forward_to_count = 0;
my $freefield;
foreach $freefield (@freefields){
$freefield =~ s/^[^\|]*\|[^\|]*\|//;
$freefield =~ s/\|.*$//;
if(length($freefield)){
push(@{$forward_to}, $freefield);
#if(length($forward_to_list)){
#
# $forward_to_list .= "\n";
#
#}
#
#$forward_to_list .= $freefield;
#$forward_to_count++;
}
}
# unique
@{$forward_to} = keys %{{ map { $_ => 1 } @{$forward_to} }};
$forward_to_list = join("\n",@{$forward_to});
$forward_to_count = scalar @{$forward_to};
$table_data->{$emailadress}{'forward_to'} = $forward_to_list;
$table_data->{$emailadress}{'forward_to_count'} = $forward_to_count;
if(!$forward_to_count){
$table_data->{$emailadress}{'new_forward'} = 1;
}
$table_data->{$emailadress}{'can_delete'} = 1;
logline("debug","freefield3 = $freefield; input-freefield3 = " . $input{'freefield3'});
$table_data->{$emailadress}{'domain'} = $input{'domain'};
$table_data->{$emailadress}{'emailadress'} = $emailadress;
if(exists($input{"user$forcount"})){
$table_data->{$emailadress}{'user'} = $input{"user$forcount"}
} else {
$table_data->{$emailadress}{'user'} = $user;
}
$table_data->{$emailadress}{'old_user'} = $user;
$table_data->{$emailadress}{'old_domain_select'} = $domain;
$table_data->{$emailadress}{'old_user_select'} = $user_select;
#$table_data->{$emailadress}{'old_freefield'} = $freefield;
$table_data->{$emailadress}{'forcount'} = $forcount;
#$table_data->{$emailadress}{'freefield'} = $input{"freefield$forcount"} ? $input{"freefield$forcount"} : $freefield;
$table_data->{$emailadress}{'domain_select'} = $template_domain_select->output if ($action eq 'change_forward' || $action eq 'change_forward_single_edit');
$table_data->{$emailadress}{'domain_select'} = encode('utf-8', domain_to_unicode($domain)) if $action eq 'show_single_edit_email';
$table_data->{$emailadress}{'user_select'} = $template_user_select->output if ($action eq 'change_forward' || $action eq 'change_forward_single_edit');
$table_data->{$emailadress}{'user_select'} = $user_select_single_edit if $action eq 'show_single_edit_email';
$table_data->{$emailadress}{"error_class_domain_select"} = error_class("domain_select$forcount");
$table_data->{$emailadress}{'freefields'} = $template_change_forward_freefields->output if ($action eq 'change_forward' || $action eq 'change_forward_single_edit');
$table_data->{$emailadress}{'freefields'} = $freefields_single_edit if $action eq 'show_single_edit_email';
$table_data->{$emailadress}{'edit_email_icons'} = 1 if $action eq 'show_single_edit_email';
$table_data->{$emailadress}{'email_type'} = $input{'email_type'};
$table_data->{$emailadress}{"error_class_user"} = error_class("user$forcount");
$table_data->{$emailadress}{"error_text_user"} = qq~<span class="help-block">$error_fields{"user$forcount"}</span>~ if $error_fields{"user$forcount"};
$table_data->{$emailadress}{'disabled'} = $disabled;
$table_data->{$emailadress}{'do_not_show_ascii_autoresponder'} = $do_not_show_ascii_autoresponder;
my @keys = ('EMAILADDRESS',$emailadress);
my $note = note_from_hashfile(\@keys);
if($note->{title}){
$table_data->{$emailadress}{'note_title'} = $note->{title};
$table_data->{$emailadress}{'note_text'} = $note->{text};
}
$forcount++;
}
}
# Icon für Autoresponder anlegen gibs nicht bei leeren Zeilen
my $autoresponder_icon = '';
my $add_empty_lines = `cat /usr/local/etc/easytecc/new_mail_lines 2>/dev/null`;
chomp $add_empty_lines;
if(!defined($add_empty_lines) || $add_empty_lines !~ m/^[0-9]+$/){
$add_empty_lines = 5;
}
my $max_empty_lines = $forcount + $add_empty_lines;
# leere Felder
while($domains{$input{'domain'}}{'for'} >= $forcount && $forcount < $max_empty_lines && ($action eq 'change_forward' || $action eq 'new_forward_single_edit')){
my $template_domain_select = HTML::Template->new(filename => 'domain_select.html');
#easytecc3::template_loop(\%input,\$template_domain_select, \@idn_domains, "domain_select$forcount", domain_to_unicode($input{"domain_select$forcount"}) . '|' . qq~value="$input{"domain_select$forcount"}"~) if exists $input{"domain_select$forcount"};
#easytecc3::template_loop(\%input,\$template_domain_select, \@idn_domains, "domain_select$forcount", '') unless exists $input{"domain_select$forcount"};
$template_domain_select->param('disabled' => $disabled);
easytecc3::template_loop_e4(\%input,\$template_domain_select, \@idn_domains, "domain_select$forcount", $input{"domain_select$forcount"} ? $input{"domain_select$forcount"} : '');
my $template_user_select = HTML::Template->new(filename => 'user_select.html');
#easytecc3::template_loop(\%input,\$template_user_select, \@popuser, "user_select$forcount", $input{"user_select$forcount"}) if exists $input{"user_select$forcount"};
#easytecc3::template_loop(\%input,\$template_user_select, \@popuser, "user_select$forcount", '') unless exists $input{"user_select$forcount"};
$template_user_select->param('disabled' => $disabled);
easytecc3::template_loop_e4(\%input,\$template_user_select, \@popuser_idn, "user_select$forcount", $input{"user_select$forcount"} ? $input{"user_select$forcount"} : '');
undef @freefields;
my %new_freefields;
my $freefield_count = 1;
my $topmargin = 0;
foreach my $freefield(sort keys %input){
my $regex = '^freefield'.$forcount.'_';
next if $freefield !~ /$regex/;
my $freefield_value = $input{$freefield};
$new_freefields{$freefield} = $input{$freefield};
push(@freefields,"$forcount|$freefield_count|" . $input{$freefield} . "|$topmargin");
$freefield_count++;
$topmargin = 1;
}
#immer ein leeres feld anzeigen
if (scalar @freefields < 1) {
push(@freefields,"$forcount|$freefield_count||");
}
my $template_change_forward_freefields = HTML::Template->new(filename => 'change_forward_freefields.html', global_vars => 1);
easytecc3::template_loop_e4(\%input,\$template_change_forward_freefields, \@freefields, "freefields");
$template_change_forward_freefields->param('disabled' => $disabled);
if(length($input{"user$forcount"}) && length($input{'domain'})){
$emailadress = $input{"user$forcount"} . '@' . $input{'domain'};
# $table_data->{$emailadress}{'newrow'} = 1;
# $table_data->{$emailadress}{'new_forward'} = 1;
# $table_data->{$emailadress}{'new_autoreply'} = 1;
} else {
$emailadress = 'zzz'.$forcount unless length($input{"user$forcount"});
}
$table_data->{$emailadress}{'new_forward'} = 1;
$table_data->{$emailadress}{'new_autoreply'} = 1;
$table_data->{$emailadress}{"error_class_user"} = error_class("user$forcount");
#$table_data->{$emailadress}{"error_text_user"} = $error_fields{"user$forcount"};
$table_data->{$emailadress}{"error_text_user"} = qq~<span class="help-block">$error_fields{"user$forcount"}</span>~ if $error_fields{"user$forcount"};
$table_data->{$emailadress}{"error_class_freefield"} = error_class("freefield$forcount");
$table_data->{$emailadress}{'user'} = $input{"user$forcount"};
#$table_data->{$emailadress}{'old_domain_select'} = $domain;
#$table_data->{$emailadress}{'old_user_select'} = $user_select;
$table_data->{$emailadress}{'forcount'} = $forcount;
#$table_data->{$emailadress}{'freefield'} = $input{"freefield$forcount"};
$table_data->{$emailadress}{'freefields'} = $template_change_forward_freefields->output;
$table_data->{$emailadress}{'domain_select'} = $template_domain_select->output;
$table_data->{$emailadress}{'user_select'} = $template_user_select->output;
$table_data->{$emailadress}{"error_class_domain_select"} = error_class("domain_select$forcount");
$table_data->{$emailadress}{'domain'} = $input{'domain'};
$table_data->{$emailadress}{'email_type'} = $input{'email_type'};
#$table_data->{$user}{"error_class_user"} = error_class("user$forcount");
#$table_data->{$user}{"error_text_user"} = qq~<span class="help-block">$error_fields{"user$forcount"}</span>~ if $error_fields{"user$forcount"};
$table_data->{$emailadress}{'disabled'} = $disabled;
$table_data->{$emailadress}{'do_not_show_ascii_autoresponder'} = $do_not_show_ascii_autoresponder;
$table_data->{$emailadress}{'newrow'} = 1;
$forcount++;
if ($action eq 'new_forward_single_edit') {
$table_data->{$emailadress}{'newuser'} = 1;
last;
}
}
if($action eq 'new_forward_single_edit'){
$template->param('newuser' => 1);
}
easytecc3::table_e4($template, $table_data, 'table_tr_change_forward_template.html') if ($action eq 'change_forward' ||
$action eq 'change_forward_single_edit' ||
$action eq 'new_forward_single_edit');
easytecc3::table_e4($template, $table_data, 'table_tr_show_single_edit_email_template.html') if $action eq 'show_single_edit_email';
$template->param('action' => 'exec_' . $input{'action'});
$template->param('domain' => $input{'domain'});
$template->param('idn_domain' => encode('utf-8', domain_to_unicode($input{'domain'})));
$template->param('email_type' => $input{'email_type'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub new_autoreply{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'new_autoreply.html');
my $forward = $input{'forward'};
my $idn_forward = $input{'forward'};
#catchall, hat nix vor dem @. Domain für Anzeigein idn umwandeln
if($idn_forward =~ /^@(.*)$/){
$idn_forward = '@' . encode('utf-8', domain_to_unicode($1));
}
else{
$idn_forward = email_to_unicode($idn_forward);
}
$template->param('forward' => $forward);
$template->param('idn_forward' => $idn_forward);
$template->param('domain' => $input{'domain'});
$template->param('email_type' => $input{'email_type'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub change_autoreply{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'change_autoreply.html');
my $autoreply = '';
my $autoreply_subject = '';
my $autoreply_text = '';
my $forward = $input{'forward'};
my $forward_aliases = $forward;
$forward_aliases =~ s/(@|\.)/_/g;
my $domain = $forward;
$domain =~ s/^(.*)\@//;
my $user = $1;
# es gibt autoresponderdateien wo domainname mit _ oder mit. existiert:
# c.blubb_domainshooter.at.aut
# k.seifert_steiner_de.aut
my $domain_reverse = reverse($domain);
# umdrehen, den ersten _ gegen . ersetzen und dann einfach gucken was vorhanden ist, das lassen wir auch so, sonst muss beim ändern von autoresponder
# immder die aliases ggf. geändert werden..., viel zu kompliziert
$domain_reverse =~ s/\./_/;
$domain_reverse = reverse($domain_reverse);
my $idn_forward = $input{'forward'};
# catchall, hat nix vor dem @. Domain für Anzeigein idn umwandeln
if($idn_forward =~ /^@(.*)$/){
$idn_forward = '@' . encode('utf-8', domain_to_unicode($1));
}
else{
$idn_forward = email_to_unicode($idn_forward);
}
logline("debug","forward_aliases=$forward_aliases");
if(-e '/usr/local/etc/' . $forward_aliases . '.aut'){
$autoreply = file->new({file_name => '/usr/local/etc/' . $forward_aliases . '.aut'});
$autoreply->read_file;
}
elsif(-e '/usr/local/etc/' . $user . '_' . $domain . '.aut'){
$autoreply = file->new({file_name => '/usr/local/etc/' . $user . '_' . $domain . '.aut'});
$autoreply->read_file;
}
elsif(-e '/usr/local/etc/' . $user . '_' . $domain_reverse . '.aut'){
$autoreply = file->new({file_name => '/usr/local/etc/' . $user . '_' . $domain_reverse . '.aut'});
$autoreply->read_file;
}
elsif(-e '/usr/local/etc/easytecc/' . $forward_aliases . '.aut'){
$autoreply = file->new({file_name => '/usr/local/etc/easytecc/' . $forward_aliases . '.aut'});
$autoreply->read_file;
}
elsif(-e '/usr/local/etc/easytecc/' . $user . '_' . $domain . '.aut'){
$autoreply = file->new({file_name => '/usr/local/etc/easytecc/' . $user . '_' . $domain . '.aut'});
$autoreply->read_file;
}
elsif(-e '/usr/local/etc/easytecc/' . $user . '_' . $domain_reverse . '.aut'){
$autoreply = file->new({file_name => '/usr/local/etc/easytecc/' . $user . '_' . $domain_reverse . '.aut'});
$autoreply->read_file;
}
else{
return(html_error({'non_specific' => 'L__Kann Autoresponderdatei nicht öffnen__L',
'template' => \$template}));
}
if (defined $autoreply) {
foreach($autoreply->file_content){
if(/^Subject: /){
$autoreply_subject = $_;
$autoreply_subject =~ s/^Subject: //;
}
elsif(/^From: /){
}
else {
$autoreply_text .= $_;
}
}
}
$template->param('forward' => $forward);
$template->param('idn_forward' => $idn_forward);
$template->param('autoreply_subject' => encode("utf-8", $autoreply_subject));
$template->param('autoreply_text' => encode("utf-8", $autoreply_text));
$template->param('domain' => $input{'domain'});
$template->param('email_type' => $input{'email_type'});
$template->param('disabled' => $input{'disabled'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub delete_autoreply{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'delete_autoreply.html');
my $forward = $input{'forward'};
$template->param('forward' => $forward);
$template->param('forward_idn' => email_to_unicode($forward));
$template->param('domain' => $input{'domain'});
$template->param('email_type' => $input{'email_type'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub new_ftpuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'new_ftpuser.html');
if(defined easytecc3::is_ftp_limited()){
$template = HTML::Template->new(filename => 'option_not_available.html');
} else {
my $default_home = '';
if($session->param('user') ne 'admin'){
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
$default_home = $passwd{$session->param('user')}{'home'};
} else {
if($fb){
$default_home = '/usr/local/www/apache24/noexec';
} else {
$default_home = '/home/httpd/docs';
}
}
$default_home .= '/benutzer';
$template->param('default_home' => $default_home);
my $default_home_rows = sprintf("%.0f", length($default_home) / 35 + 0.5);
$template->param('default_home_rows' => $default_home_rows);
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub new_adminuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'new_adminuser.html');
if(defined easytecc3::is_ftp_limited() || $session->param('user') ne 'admin'){
$template = HTML::Template->new(filename => 'option_not_available.html');
} else {
my $default_home = '';
if($fb){
$default_home = '/usr/local/www/apache24/noexec';
} else {
$default_home = '/home/httpd/docs';
}
$default_home .= '/benutzer';
$template->param('default_home' => $default_home);
my $default_home_rows = sprintf("%.0f", length($default_home) / 35 + 0.5);
$template->param('default_home_rows' => $default_home_rows);
}
if(!$validation_result){
my $gecos = 'CUST.vhost.email-1.ftp.quota.spam.fileman-1.logs-1.db-1.cron-2.inst';
if($gecos =~ m/\.vhost/){
$template->param('checked_show_vhosts' => 'CHECKED');
if($gecos =~ m/\.vhost-[1-9]/){
$template->param('checked_new_vhosts' => 'CHECKED');
}
}
if($gecos =~ m/\.email/){
$template->param('checked_show_email' => 'CHECKED');
if($gecos =~ m/\.email-[1-9]/){
$template->param('checked_edit_email' => 'CHECKED');
}
}
if($gecos =~ m/\.ftp/){
$template->param('checked_show_ftp' => 'CHECKED');
if($gecos =~ m/\.ftp-[1-9]/){
$template->param('checked_edit_ftp' => 'CHECKED');
}
if($gecos =~ m/\.ftp-2/){
$template->param('checked_new_ftp' => 'CHECKED');
}
}
if($gecos =~ m/\.quota/){
$template->param('checked_show_quota' => 'CHECKED');
}
if($gecos =~ m/\.spam/){
$template->param('checked_show_spam' => 'CHECKED');
}
if($gecos =~ m/\.fileman/){
$template->param('checked_show_fileman' => 'CHECKED');
if($gecos =~ m/\.fileman-1/){
$template->param('checked_edit_fileman' => 'CHECKED');
}
}
if($gecos =~ m/\.logs/){
$template->param('checked_show_logs' => 'CHECKED');
if($gecos =~ m/\.logs-1/){
$template->param('checked_edit_logs' => 'CHECKED');
}
}
if($gecos =~ m/\.db/){
$template->param('checked_show_db' => 'CHECKED');
if($gecos =~ m/\.db-[1-9]/){
$template->param('checked_edit_db' => 'CHECKED');
}
if($gecos =~ m/\.db-2/){
$template->param('checked_new_db' => 'CHECKED');
}
}
if($gecos =~ m/\.cron/){
$template->param('checked_show_cron' => 'CHECKED');
if($gecos =~ m/\.cron-[1-9]/){
$template->param('checked_edit_cron' => 'CHECKED');
}
if($gecos =~ m/\.cron-2/){
$template->param('checked_new_cron' => 'CHECKED');
}
}
if($gecos =~ m/\.inst/){
$template->param('checked_show_inst' => 'CHECKED');
}
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub change_ftpuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'change_ftpuser.html');
my $domain = '';
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
# Domains und deren document roots in Hash und dann mit home-Verzeuchnis des FTP-Users vergleichen
my %domain_home;
foreach(keys %domains){
$domain_home{$domains{$_}{'droot'}} = $domains{$_}{'domain'};
}
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my ($quotaref, $sum_ftplimit, $sum_ftpuse, $ftpserverlimit) = easytecc3::getquota_ftp();
my %quota = %$quotaref;
my $ftpuser = $input{'ftpuser'};
my $ftpquota = $quota{$ftpuser}{'quota'};
my $ftpquota_sized = easytecc3::getsize($ftpquota);
my $ftpused = $quota{$ftpuser}{'use'};
my $quotabalken = easytecc3::quotabar($ftpquota, $ftpused, 'MB_form');
if(exists $domain_home{$passwd{$ftpuser}{'home'}}){
#$domain = @{$domain_home{$passwd{$ftpuser}{'home'}}};
$domain = join '<br />', @{$domain_home{$passwd{$ftpuser}{'home'}}};
logline("debug","exist home: $domain " . @{$domain_home{$passwd{$ftpuser}{'home'}}});
$template->param('domain' => $domain_home{$passwd{$ftpuser}{'home'}});
$template->param('idn_domain' => encode('utf-8', domain_to_unicode($domain_home{$passwd{$ftpuser}{'home'}})));
$template->param('quota' => $domains{$domain_home{$passwd{$ftpuser}{'home'}}}{'quota'} . ' MB');
}
if ($passwd{$ftpuser}{'shell'} eq '/usr/sbin/nologin' || $ftpuser =~ /^(admin|cyrus|dovecot|dovenull|mysql|pgsql|virtmail|web)$/) {
$template->param('system_user' => 1);
}
if ($passwd{$ftpuser}{'shell'} eq '/usr/sbin/nologin' ||
$passwd{$ftpuser}{'shell'} eq '/bin/false' ||
$passwd{$ftpuser}{'shell'} eq '/sbin/nologin' ||
$passwd{$ftpuser}{'shell'} eq '/nonexistent' ||
$ftpuser eq 'web') {
$template->param('no_password' => 1);
}
$template->param('ftpuser' => $ftpuser);
$template->param('gecos' => $passwd{$ftpuser}{'gecos'});
# immer in MB angeben
$template->param('ftpquota' => $ftpquota / 1024);
$template->param('home' => $passwd{$ftpuser}{'home'});
$template->param('ftpquota_used_percent' => $quota{$ftpuser}{'use'} > 0 ? sprintf("%.0f",($quota{$ftpuser}{'use'} / $quota{$ftpuser}{'quota'}) * 100) : '0');
$template->param('alert_ftpuser_quota' => easytecc3::quota_alert($quota{$ftpuser}{'quota'}, $quota{$ftpuser}{'use'}, '.8'));
if($passwd{$ftpuser}{'gecos'} =~ m/^CUST/){
$template->param('hide_gecos' => '1');
}
if($session->param('user') eq 'admin'){
$template->param('show_vhost' => '1');
$template->param('disabled' => '');
} else {
my $gecos = $passwd{$session->param('user')}{'gecos'};
my $gecos = $passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.vhost-1.ftp-1';
}
if($gecos =~ m/\.vhost/){
$template->param('show_vhost' => '1');
}
$template->param('disabled' => 'disabled');
$template->param('no_password' => 1);
$template->param('no_quota' => 1);
$template->param('no_home' => 1);
if($gecos =~ m/\.ftp/){
$template->param('disabled' => '');
}
if($gecos =~ m/\.ftp-1/){
$template->param('no_password' => '');
}
if($gecos =~ m/\.ftp-2/){
$template->param('no_password' => '');
$template->param('no_quota' => '');
}
if($session->param('user') ne $ftpuser){
$template->param('no_home' => '');
}
}
# 2fa
if($session->param('user') eq $ftpuser){
$template->param('2fa_possible' => 1);
# 2fa setup
if(-f "/usr/local/etc/easytecc/2fa/$ftpuser.setup"){
$template->param('2fa_setup' => 1);
$qrcode_url = 'data:image/png;base64,' . `cat /usr/local/etc/easytecc/2fa/$ftpuser.qr`;
$template->param('qrcode_url' => $qrcode_url);
}
}
# 2fa present
if(-f "/usr/local/etc/easytecc/2fa/$ftpuser"){
$template->param('2fa_active' => 1);
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub change_adminuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'change_adminuser.html');
my $domain = '';
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my %allowed_domains;
foreach my $domain (keys %domains){
my $admins = $domains{$domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $input{'ftpuser'} . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
foreach my $alias_domain (@{$domains{$domain}{'domains'}}){
$alias_domain =~ s/^www\.//;
$alias_domain =~ s/^\*\.//;
$alias_domain = encode('utf-8', domain_to_unicode($alias_domain));
$allowed_domains{$alias_domain} = 1;
}
}
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my $ftpuser = $input{'ftpuser'};
my $admin_domains = join(', ',(sort keys %allowed_domains));
$template->param('admin_domains' => $admin_domains);
my $gecos = $passwd{$ftpuser}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.vhost-1.email-1.ftp-2.quota.spam.fileman-1.logs-1.db-2.cron-2.inst';
$template->param('ftp_to_admin' => 1);
}
if($gecos =~ m/\.vhost/){
$template->param('checked_show_vhosts' => 'CHECKED');
if($gecos =~ m/\.vhost-[1-9]/){
$template->param('checked_new_vhosts' => 'CHECKED');
}
}
if($gecos =~ m/\.email/){
$template->param('checked_show_email' => 'CHECKED');
if($gecos =~ m/\.email-[1-9]/){
$template->param('checked_edit_email' => 'CHECKED');
}
}
if($gecos =~ m/\.ftp/){
$template->param('checked_show_ftp' => 'CHECKED');
if($gecos =~ m/\.ftp-[1-9]/){
$template->param('checked_edit_ftp' => 'CHECKED');
}
if($gecos =~ m/\.ftp-2/){
$template->param('checked_new_ftp' => 'CHECKED');
}
}
if($gecos =~ m/\.quota/){
$template->param('checked_show_quota' => 'CHECKED');
}
if($gecos =~ m/\.spam/){
$template->param('checked_show_spam' => 'CHECKED');
}
if($gecos =~ m/\.fileman/){
$template->param('checked_show_fileman' => 'CHECKED');
if($gecos =~ m/\.fileman-1/){
$template->param('checked_edit_fileman' => 'CHECKED');
}
}
if($gecos =~ m/\.logs/){
$template->param('checked_show_logs' => 'CHECKED');
if($gecos =~ m/\.logs-1/){
$template->param('checked_edit_logs' => 'CHECKED');
}
}
if($gecos =~ m/\.db/){
$template->param('checked_show_db' => 'CHECKED');
if($gecos =~ m/\.db-[1-9]/){
$template->param('checked_edit_db' => 'CHECKED');
}
if($gecos =~ m/\.db-2/){
$template->param('checked_new_db' => 'CHECKED');
}
}
if($gecos =~ m/\.cron/){
$template->param('checked_show_cron' => 'CHECKED');
if($gecos =~ m/\.cron-[1-9]/){
$template->param('checked_edit_cron' => 'CHECKED');
}
if($gecos =~ m/\.cron-2/){
$template->param('checked_new_cron' => 'CHECKED');
}
}
if($gecos =~ m/\.inst/){
$template->param('checked_show_inst' => 'CHECKED');
}
# Domains und deren document roots in Hash und dann mit home-Verzeuchnis des FTP-Users vergleichen
my %domain_home;
foreach(keys %domains){
$domain_home{$domains{$_}{'droot'}} = $domains{$_}{'domain'};
}
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my ($quotaref, $sum_ftplimit, $sum_ftpuse, $ftpserverlimit) = easytecc3::getquota_ftp();
my %quota = %$quotaref;
my $ftpuser = $input{'ftpuser'};
my $ftpquota = $quota{$ftpuser}{'quota'};
my $ftpquota_sized = easytecc3::getsize($ftpquota);
my $ftpused = $quota{$ftpuser}{'use'};
my $quotabalken = easytecc3::quotabar($ftpquota, $ftpused, 'MB_form');
if(exists $domain_home{$passwd{$ftpuser}{'home'}}){
#$domain = @{$domain_home{$passwd{$ftpuser}{'home'}}};
$domain = join '<br />', @{$domain_home{$passwd{$ftpuser}{'home'}}};
logline("debug","exist home: $domain " . @{$domain_home{$passwd{$ftpuser}{'home'}}});
$template->param('admin_domains' => $domain_home{$passwd{$ftpuser}{'home'}});
$template->param('idn_domain' => encode('utf-8', domain_to_unicode($domain_home{$passwd{$ftpuser}{'home'}})));
$template->param('quota' => $domains{$domain_home{$passwd{$ftpuser}{'home'}}}{'quota'} . ' MB');
}
if ($passwd{$ftpuser}{'shell'} eq '/usr/sbin/nologin' || $ftpuser =~ /^(admin|cyrus|dovecot|dovenull|mysql|pgsql|virtmail|web)$/) {
$template->param('system_user' => 1);
}
if ($passwd{$ftpuser}{'shell'} eq '/usr/sbin/nologin' ||
$passwd{$ftpuser}{'shell'} eq '/bin/false' ||
$passwd{$ftpuser}{'shell'} eq '/sbin/nologin' ||
$passwd{$ftpuser}{'shell'} eq '/nonexistent' ||
$ftpuser eq 'web') {
$template->param('no_password' => 1);
}
$template->param('ftpuser' => $ftpuser);
$template->param('gecos' => $passwd{$ftpuser}{'gecos'});
# immer in MB angeben
$template->param('ftpquota' => $ftpquota / 1024);
$template->param('home' => $passwd{$ftpuser}{'home'});
$template->param('ftpquota_used_percent' => $quota{$ftpuser}{'use'} > 0 ? sprintf("%.0f",($quota{$ftpuser}{'use'} / $quota{$ftpuser}{'quota'}) * 100) : '0');
$template->param('alert_ftpuser_quota' => easytecc3::quota_alert($quota{$ftpuser}{'quota'}, $quota{$ftpuser}{'use'}, '.8'));
# 2fa present
if(-f "/usr/local/etc/easytecc/2fa/$ftpuser"){
$template->param('2fa_active' => 1);
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub delete_ftpuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'delete_ftpuser.html');
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my $ftpuser = $input{'ftpuser'};
$template->param('ftpuser' => $ftpuser);
$template->param('home' => $passwd{$ftpuser}{'home'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub delete_adminuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'delete_adminuser.html');
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my $ftpuser = $input{'ftpuser'};
$template->param('ftpuser' => $ftpuser);
$template->param('home' => $passwd{$ftpuser}{'home'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub delete_sendmail_cw{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'delete_sendmail_cw.html');
my %domains_to_delete = ();
my $domains_to_delete_html = '';
my $domains_to_delete_html_list = '';
foreach(keys %input){
if (/^deletecw[0-9]{1,4}$/){
$domains_to_delete{$_} = $input{$_};
$domains_to_delete_html .= qq~<input type="hidden" name="$_" value="$input{$_}" />~;
$domains_to_delete_html_list .= encode('utf-8', domain_to_unicode($input{$_})) . qq~<br />~;
}
}
$template->param('domains_to_delete_hidden_fields' => $domains_to_delete_html);
$template->param('domains_to_delete_list' => $domains_to_delete_html_list);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_delete_sendmail_cw{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
logline("debug","Creating File Object \$sendmail_cw.");
my $sendmail_cw = file->new({file_name => '/etc/mail/sendmail.cw'});
$sendmail_cw->read_file;
my %sendmail_cw = %{$sendmail_cw->file_parsed_hash()};
my %domains_to_delete = ();
my @new_sendmail_cw = ();
foreach(keys %input){
if (/^deletecw[0-9]{1,4}$/){
logline("debug","delete sendmail.cw= $_ = $input{$_}");
$domains_to_delete{$input{$_}} = '1';
}
}
foreach(@{$sendmail_cw->file_content}){
chomp;
if(exists $domains_to_delete{$_}){
}
else{
push @new_sendmail_cw, $_;
}
}
@{$sendmail_cw->file_content} = @new_sendmail_cw;
my $got = $sendmail_cw->write_file;
return(error($got)) if $got;
$template->param('result' => 'L__Die Domains wurden aus der Mailkonfiguration gelöscht__L') if keys %domains_to_delete > 1;
$template->param('result' => 'L__Die Domain wurde aus der Mailkonfiguration gelöscht__L') if keys %domains_to_delete == 1;
$success_text = 'L__Die Domains wurden aus der Mailkonfiguration gelöscht__L' if keys %domains_to_delete > 1;
$success_text = 'L__Die Domain wurde aus der Mailkonfiguration gelöscht__L' if keys %domains_to_delete == 1;
logline("debug","<<< Leaving ".(caller(0))[3]."().");
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_email&active_tab=2&success_text=' . encode_base64url($success_text);
return(\$template);
}
sub delete_vhost{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'delete_vhost.html');
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my $droot = $domains{$input{'domain'}}{'droot'};
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my %home_lookup = %{$passwd->lookup2_hash()};
my $ftpuser = '';
if(exists $home_lookup{$domains{$input{'domain'}}{'droot'}}){
$ftpuser = $home_lookup{$domains{$input{'domain'}}{'droot'}};
}
logline("debug"," MARIO SSL L9671 : @{$domains{$input{'domain'}}{'special_ssl'}} ");
if((join ' ', @{$domains{$input{'domain'}}{'special_ssl'}}) =~ m/letsencrypt/){
logline("debug"," MARIO SSL L9673 : @{$domains{$input{'domain'}}{'special_ssl'}} ");
$template->param('is_letsencrypt' => '1');
}
$template->param('domain' => $input{'domain'});
$template->param('idn_domain' => encode('utf-8', domain_to_unicode($input{'domain'})));
$template->param('droot' => $droot);
$template->param('delete_ftpuser' => qq~<div class="checkbox"><label><input type="checkbox" name="delete_ftpuser" value="$ftpuser" /> FTP-User $ftpuser L__Löschen__L</label></div>~) if $ftpuser;
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub change_spamfilter{
if($session->param('show_spam') ne '1'){
return start();
}
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'change_spamfilter.html');
my @rbl = ();
my $whitelist_content = '';
my $blacklist_content = '';
logline("debug","Creating File Object \$procmailrc.");
my $procmailrc = file->new({file_name => '/etc/procmailrc'});
$procmailrc->read_file;
my %procmailrc = %{$procmailrc->file_parsed_hash()};
logline("debug","Creating File Object \$dnsbl.");
my $dnsbl = file->new({file_name => '/etc/mail/dnsbl.hosts'});
$dnsbl->read_file;
my %dnsbl = %{$dnsbl->file_parsed_hash()};
logline("debug","Creating File Object \$whitelist.");
my $whitelist = file->new({file_name => '/home/spamdef/.white.lst'});
$whitelist->read_file;
my %whitelist = %{$whitelist->file_parsed_hash()};
logline("debug","Creating File Object \$blacklist.");
my $blacklist = file->new({file_name => '/home/spamdef/.black.lst'});
$blacklist->read_file;
my %blacklist = %{$blacklist->file_parsed_hash()};
logline("debug","Creating File Object \$user_prefs.");
my $user_prefs = file->new({file_name => '/home/spamdef/.spamd/user_prefs'});
$user_prefs->read_file;
my %user_prefs = %{$user_prefs->file_parsed_hash()};
my @ok_languages = split /\s+/, $user_prefs{'ok_languages'};
my $deliver = "/etc/.deliver";
my $junkfolder=`sed '/^DOVECOT_JUNK=/!d ; s/^.*=//' $deliver 2>/dev/null`;
chomp $junkfolder;
$template->param('junkfolder' => $junkfolder);
my %lang = easytecc3::spam_lang();
my $checked_europe = '';
my $checked_china = '';
my $checked_russia = '';
my $checked_other = '';
if($session->param('user') eq 'admin'){
$template->param('show_global_spamfilter' => '1');
}
if($input{'form_submit'} && $input{'action'} eq 'exec_change_spamfilter'){
if($input{'action_virus'} eq 'OFF'){
$template->param('checked_virusoff' => 'checked');
}
elsif($input{'action_virus'} eq 'DEL'){
$template->param('checked_virusdel' => 'checked');
}
elsif($input{'action_virus'} eq 'MARK'){
$template->param('checked_virusmark' => 'checked');
}
if($input{'spamd'} eq 'OFF'){
$template->param('checked_spamdoff' => 'checked');
}
elsif($input{'spamd'} eq 'ON'){
$template->param('checked_spamdon' => 'checked');
}
$template->param('selected_pspam' . $input{'pspam_level'} => 'selected');
if($input{'action_pspam'} eq 'MARK'){
$template->param('checked_mark_pspam' => 'checked');
}
elsif($input{'action_pspam'} eq 'HEADER'){
$template->param('checked_header_pspam' => 'checked');
}
$template->param('selected_cspam' . $input{'cspam_level'} => 'selected');
if($input{'action_cspam'} eq 'MARK'){
$template->param('checked_cspam_mark' => 'checked');
}
elsif($input{'action_cspam'} eq 'HEADER'){
$template->param('checked_cspam_header' => 'checked');
}
elsif($input{'action_cspam'} eq 'DEL'){
$template->param('checked_cspam_delete' => 'checked');
}
if($input{'report_safe'}){
$template->param('checked_report_safe_on' => 'checked');
}
else{
$template->param('checked_report_safe_off' => 'checked');
}
foreach(keys %input){
#<input name="lang_other" type="checkbox" class="languagetype="checkbox"" value="other" <TMPL_VAR NAME=checked_spamd_lang_other>
next unless /^lang_(.*)$/;
$template->param('checked_spamd_lang_' . $1 => 'checked');
}
}
else{
foreach(@ok_languages){
$template->param('checked_spamd_lang_' . $_ => ' checked');
$checked_europe = '1' if(!$checked_europe && /^($lang{'europe'})$/);
$checked_china = '1' if(!$checked_europe && /^($lang{'china'})$/);
$checked_russia = '1' if(!$checked_europe && /^($lang{'russia'})$/);
$checked_other = '1' if(!$checked_europe && /^($lang{'other'})$/);
}
$template->param('checked_spamd_lang_europe' => ' checked') if $checked_europe;
$template->param('checked_spamd_lang_china' => ' checked') if $checked_china;
$template->param('checked_spamd_lang_russia' => ' checked') if $checked_russia;
$template->param('checked_spamd_lang_other' => ' checked') if $checked_other;
#rbl
my @loop_data = ();
foreach(sort keys %dnsbl){
logline("debug","rbl:$_ $dnsbl{$_}");
my %row_data;
$row_data{'RBL_ID'} = "rbl_$_";
$row_data{'RBL_NAME'} = $_;
$row_data{'CHECKED_RBL_ID'} = 'checked' if $dnsbl{$_} == '1';
push(@loop_data, \%row_data);
#my $checked = 'checked' if $dnsbl{$_} == '1';
#push(@rbl, qq~$_~ . '|' .
# qq~<input name="rbl_$_" type="checkbox" onClick="rbl(this)" value="1" $checked />~
#);
}
$template->param('RBL_LOOP' => \@loop_data);
#easytecc3::table(\$template,'<td>L__Realtime Blacklists__L</td><td colspan="6">L__aktiv__L</td>', \@rbl, 'rbl');
# Whiteliste
foreach(sort keys %whitelist){
$whitelist_content = $whitelist_content . $_ . "\n";
}
$template->param('whitelist' => $whitelist_content);
# Blackliste
foreach(sort keys %blacklist){
$blacklist_content = $blacklist_content . $_ . "\n";
}
$template->param('blacklist' => $blacklist_content);
# generischer Anhangsfilter
# VIRUS=MARK #OFF;DEL;MARK
if($procmailrc{'VIRUS'} eq 'OFF'){
$template->param('checked_virusoff' => 'checked');
}
elsif($procmailrc{'VIRUS'} eq 'DEL'){
$template->param('checked_virusdel' => 'checked');
}
elsif($procmailrc{'VIRUS'} eq 'MARK'){
$template->param('checked_virusmark' => 'checked');
}
$template->param('subj_virus' => $procmailrc{'SUBJ_VIRUS'});
$template->param('postfix_virus' => $procmailrc{'POSTFIX'});
# Spamassassin
if($procmailrc{'SPAMD'} eq 'OFF'){
$template->param('checked_spamdoff' => 'checked');
}
elsif($procmailrc{'SPAMD'} eq 'ON'){
$template->param('checked_spamdon' => 'checked');
}
# warscheinlicher Spam
# aus /home/spamdef/.spamd/user_prefs
# required_hits 5.0
$template->param('selected_pspam' . $user_prefs{'required_hits'} => 'selected');
# Aktion warscheinlicher Spam
# PSPAM=MARK #MARK;HEADER
if($procmailrc{'PSPAM'} eq 'MARK'){
$template->param('checked_mark_pspam' => 'checked');
}
elsif($procmailrc{'PSPAM'} eq 'HEADER'){
$template->param('checked_header_pspam' => 'checked');
}
# Subjektpräfix Spamverdacht
$template->param('subj_pspam' => $procmailrc{'SUBJ_PSPAM'});
# sicherer Spam
# aus /etc/procmailrc
# CLEVEL='\*\*\*\*\*\*\*\*\*\*'
# Wert wurde schon als Zahl beim Parsen in $procmailrc{'CLEVEL'} gespeichert
$template->param('selected_cspam' . $procmailrc{'CLEVEL'} => 'selected');
# Aktion sicherer Spam
# CSPAM=MARK #DEL;MARK;HEADER
if($procmailrc{'CSPAM'} eq 'MARK'){
$template->param('checked_cspam_mark' => 'checked');
}
elsif($procmailrc{'CSPAM'} eq 'HEADER'){
$template->param('checked_cspam_header' => 'checked');
}
elsif($procmailrc{'CSPAM'} eq 'DEL'){
$template->param('checked_cspam_delete' => 'checked');
}
# Subjektpräfix sicherer Spam
$template->param('subj_cspam' => $procmailrc{'SUBJ_CSPAM'});
# Bericht user_prefs:
# report_safe 1
if($user_prefs{'report_safe'} eq '1'){
$template->param('checked_report_safe_on' => 'checked');
}
else{
$template->param('checked_report_safe_off' => 'checked');
}
# ugly unhack from score_DNSBL 10 to DNSBL 10
my @scores = ();
foreach(keys %user_prefs){
next unless (/^score_/);
next unless ($user_prefs{$_} =~ /[0-9\.]+/);
my $rule = $_;
$rule =~ s/^score_//;
push @scores, $rule . ' ' . $user_prefs{$_};
}
$template->param('scores' => join("\n", sort @scores));
}
if($input{'action'} eq 'change_spamfilter' || $input{'action'} eq 'exec_change_spamfilter'){
#preselect defaults for new special spamfilter tab
$template->param('special_checked_virusmark' => 'checked');
$template->param('special_subj_virus' => $procmailrc{'SUBJ_VIRUS'});
$template->param('special_postfix_virus' => $procmailrc{'POSTFIX'});
$template->param('special_checked_spamdon' => 'checked');
$template->param('special_selected_pspam' . $user_prefs{'required_hits'} => 'selected');
$template->param('special_checked_mark_pspam' => 'checked');
$template->param('special_subj_pspam' => $procmailrc{'SUBJ_PSPAM'});
$template->param('special_selected_cspam' . $procmailrc{'CLEVEL'} => 'selected');
$template->param('special_checked_cspam_mark' => 'checked');
$template->param('special_subj_cspam' => $procmailrc{'SUBJ_CSPAM'});
$template->param('special_checked_report_safe_off' => 'checked');
$template->param('special_checked_spamd_lang_europe' => ' checked') if $checked_europe;
$template->param('special_checked_spamd_lang_china' => ' checked') if $checked_china;
$template->param('special_checked_spamd_lang_russia' => ' checked') if $checked_russia;
$template->param('special_checked_spamd_lang_other' => ' checked') if $checked_other;
foreach(@ok_languages){
$template->param('special_checked_spamd_lang_' . $_ => ' checked');
}
$template->param('special_scores' => join("\n", sort @scores));
}
if (length($input{'active_tab'})) {
$template->param('change_spamfilter_active_tab'.$input{'active_tab'} => 1);
}
else{
if($session->param('user') eq 'admin'){
$template->param('change_spamfilter_active_tab1' => 1);
} else {
$template->param('change_spamfilter_active_tab2' => 1);
}
}
show_special_spamfilter($template);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub new_special_spamfilter{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
#my $template = HTML::Template->new(filename => 'change_spamfilter.html');
#Formular für neuen Spezialfilter istz in change_spamfilter als eigener tab...
my $template_tmp = change_spamfilter();
my $template = $$template_tmp;
$template->param('change_spamfilter_active_tab2' => 1);
logline("debug","Creating File Object \$procmailrc.");
my $procmailrc = file->new({file_name => '/etc/procmailrc'});
$procmailrc->read_file;
my %procmailrc = %{$procmailrc->file_parsed_hash()};
logline("debug","Creating File Object \$user_prefs.");
my $user_prefs = file->new({file_name => '/home/spamdef/.spamd/user_prefs'});
$user_prefs->read_file;
my %user_prefs = %{$user_prefs->file_parsed_hash()};
my $special_spamfilter = $input{'special_spam_user_domain'} if $input{'special_spam_user_domain'};
my $deliver = "/home/$special_spamfilter/.deliver";
my $junkfolder=`sed '/^DOVECOT_JUNK=/!d ; s/^.*=//' $deliver 2>/dev/null`;
chomp $junkfolder;
$template->param('special_junkfolder' => $junkfolder);
unless($input{'form_submit'}){
# generischer Anhangsfilter
# VIRUS=MARK #OFF;DEL;MARK
if($procmailrc{'VIRUS'} eq 'OFF'){
$template->param('special_checked_virusoff' => 'checked');
}
elsif($procmailrc{'VIRUS'} eq 'DEL'){
$template->param('special_checked_virusdel' => 'checked');
}
elsif($procmailrc{'VIRUS'} eq 'MARK'){
$template->param('special_checked_virusmark' => 'checked');
}
$template->param('special_subj_virus' => $procmailrc{'SUBJ_VIRUS'});
$template->param('special_postfix_virus' => $procmailrc{'POSTFIX'});
# Spamassassin
if($procmailrc{'SPAMD'} eq 'OFF'){
$template->param('special_checked_spamdoff' => 'checked');
}
elsif($procmailrc{'SPAMD'} eq 'ON'){
$template->param('special_checked_spamdon' => 'checked');
}
# warscheinlicher Spam
# aus /home/spamdef/.spamd/user_prefs
# required_hits 5.0
$template->param('special_selected_pspam' . $user_prefs{'required_hits'} => 'selected');
# Aktion warscheinlicher Spam
# PSPAM=MARK #MARK;HEADER
if($procmailrc{'PSPAM'} eq 'MARK'){
$template->param('special_checked_mark_pspam' => 'checked');
}
elsif($procmailrc{'PSPAM'} eq 'HEADER'){
$template->param('special_checked_header_pspam' => 'checked');
}
# Subjektpräfix Spamverdacht
$template->param('special_subj_pspam' => $procmailrc{'SUBJ_PSPAM'});
# sicherer Spam
# aus /etc/procmailrc
# CLEVEL='\*\*\*\*\*\*\*\*\*\*'
# Wert wurde schon als Zahl beim Parsen in $procmailrc{'CLEVEL'} gespeichert
$template->param('special_selected_cspam' . $procmailrc{'CLEVEL'} => 'selected');
# Aktion sicherer Spam
# CSPAM=MARK #DEL;MARK;HEADER
if($procmailrc{'CSPAM'} eq 'MARK'){
$template->param('special_checked_cspam_mark' => 'checked');
}
elsif($procmailrc{'CSPAM'} eq 'HEADER'){
$template->param('special_checked_cspam_header' => 'checked');
}
elsif($procmailrc{'CSPAM'} eq 'DEL'){
$template->param('special_checked_cspam_delete' => 'checked');
}
# Subjektpräfix sicherer Spam
$template->param('special_subj_cspam' => $procmailrc{'SUBJ_CSPAM'});
# Bericht user_prefs:
# report_safe 1
if($user_prefs{'report_safe'} eq '1'){
$template->param('special_checked_report_safe_on' => 'checked');
}
else{
$template->param('special_checked_report_safe_off' => 'checked');
}
}
else{
$template->param('special_spam_user_domain' => $special_spamfilter);
if($input{'special_action_virus'} eq 'OFF'){
$template->param('special_checked_virusoff' => 'checked');
}
elsif($input{'special_action_virus'} eq 'DEL'){
$template->param('special_checked_virusdel' => 'checked');
}
elsif($input{'special_action_virus'} eq 'MARK'){
$template->param('special_checked_virusmark' => 'checked');
}
if($input{'special_spamd'} eq 'OFF'){
$template->param('special_checked_spamdoff' => 'checked');
}
elsif($input{'special_spamd'} eq 'ON'){
$template->param('special_checked_spamdon' => 'checked');
}
$template->param('special_selected_pspam' . $input{'special_pspam_level'} => 'selected');
if($input{'special_action_pspam'} eq 'MARK'){
$template->param('special_checked_mark_pspam' => 'checked');
}
elsif($input{'special_action_pspam'} eq 'HEADER'){
$template->param('special_checked_header_pspam' => 'checked');
}
$template->param('special_selected_cspam' . $input{'special_cspam_level'} => 'selected');
if($input{'special_action_cspam'} eq 'MARK'){
$template->param('special_checked_cspam_mark' => 'checked');
}
elsif($input{'special_action_cspam'} eq 'HEADER'){
$template->param('special_checked_cspam_header' => 'checked');
}
elsif($input{'special_action_cspam'} eq 'DEL'){
$template->param('special_checked_cspam_delete' => 'checked');
}
if($input{'special_report_safe'}){
$template->param('special_checked_report_safe_on' => 'checked');
}
else{
$template->param('special_checked_report_safe_off' => 'checked');
}
# ugly unhack from score_DNSBL 10 to DNSBL 10
my @scores = ();
foreach(keys %user_prefs){
next unless (/^score_/);
next unless ($user_prefs{$_} =~ /[0-9\.]+/);
my $rule = $_;
$rule =~ s/^score_//;
push @scores, $rule . ' ' . $user_prefs{$_};
}
$template->param('special_scores' => join("\n", sort @scores));
foreach(keys %input){
#<input name="lang_other" type="checkbox" class="language" value="other" <TMPL_VAR NAME=checked_spamd_lang_other>
next unless /^special_lang_(.*)$/;
$template->param('special_checked_spamd_lang_' . $1 => 'checked');
}
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub change_special_spamfilter{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'change_special_spamfilter.html');
my $whitelist_content = '';
my $blacklist_content = '';
my $special_spamfilter = $input{'domain'} if $input{'domain'};
my $special_spamfilter_idn = encode('utf-8', domain_to_unicode($input{'domain'})) if $input{'domain'};
$special_spamfilter = $input{'user'} if $input{'user'};
$special_spamfilter_idn = encode('utf-8',email_to_unicode($input{'user'})) if $input{'user'};
$special_spamfilter = $input{'special_spam_user_domain'} if $input{'special_spam_user_domain'};
$special_spamfilter_idn = encode('utf-8', domain_to_unicode($input{'special_spam_user_domain'})) if $input{'special_spam_user_domain'};
logline("debug","Creating File Object \$procmailrc.");
my $procmailrc = file->new({file_name => "/home/$special_spamfilter/.spamproc",
user => $input{'user'},
domain => $input{'domain'}}
);
$procmailrc->read_file;
my %procmailrc = %{$procmailrc->file_parsed_hash()};
logline("debug","Creating File Object \$whitelist.");
my $whitelist = file->new({file_name => "/home/$special_spamfilter/.white.lst"});
$whitelist->read_file;
my %whitelist = %{$whitelist->file_parsed_hash()};
logline("debug","Creating File Object \$blacklist.");
my $blacklist = file->new({file_name => "/home/$special_spamfilter/.black.lst"});
$blacklist->read_file;
my %blacklist = %{$blacklist->file_parsed_hash()};
logline("debug","Creating File Object \$user_prefs.");
my $user_prefs = file->new({file_name => "/home/$special_spamfilter/.spamd/user_prefs"});
$user_prefs->read_file;
my %user_prefs = %{$user_prefs->file_parsed_hash()};
my @ok_languages = split /\s+/, $user_prefs{'ok_languages'};
my $deliver = "/home/$special_spamfilter/.deliver";
my $junkfolder=`sed '/^DOVECOT_JUNK=/!d ; s/^.*=//' $deliver 2>/dev/null`;
chomp $junkfolder;
$template->param('special_junkfolder' => $junkfolder);
my %lang = easytecc3::spam_lang();
my $checked_europe = '';
my $checked_china = '';
my $checked_russia = '';
my $checked_other = '';
unless($input{'form_submit'}){
foreach(@ok_languages){
$template->param('special_checked_spamd_lang_' . $_ => ' checked');
$checked_europe = '1' if(!$checked_europe && /^($lang{'europe'})$/);
$checked_china = '1' if(!$checked_europe && /^($lang{'china'})$/);
$checked_russia = '1' if(!$checked_europe && /^($lang{'russia'})$/);
$checked_other = '1' if(!$checked_europe && /^($lang{'other'})$/);
}
$template->param('special_checked_spamd_lang_europe' => ' checked') if $checked_europe;
$template->param('special_checked_spamd_lang_china' => ' checked') if $checked_china;
$template->param('special_checked_spamd_lang_russia' => ' checked') if $checked_russia;
$template->param('special_checked_spamd_lang_other' => ' checked') if $checked_other;
# Whiteliste
foreach(sort keys %whitelist){
logline("debug","whitelist:$_");
$whitelist_content = $whitelist_content . $_ . "\n";
}
$template->param('special_whitelist' => $whitelist_content);
# Blackliste
foreach(sort keys %blacklist){
$blacklist_content = $blacklist_content . $_ . "\n";
}
$template->param('special_blacklist' => $blacklist_content);
# generischer Anhangsfilter
# VIRUS=MARK #OFF;DEL;MARK
if($procmailrc{'VIRUS'} eq 'OFF'){
$template->param('special_checked_virusoff' => 'checked');
}
elsif($procmailrc{'VIRUS'} eq 'DEL'){
$template->param('special_checked_virusdel' => 'checked');
}
elsif($procmailrc{'VIRUS'} eq 'MARK'){
$template->param('special_checked_virusmark' => 'checked');
}
$template->param('special_subj_virus' => $procmailrc{'SUBJ_VIRUS'});
$template->param('special_postfix_virus' => $procmailrc{'POSTFIX'});
# Spamassassin
if($procmailrc{'SPAMD'} eq 'OFF'){
$template->param('special_checked_spamdoff' => 'checked');
}
elsif($procmailrc{'SPAMD'} eq 'ON'){
$template->param('special_checked_spamdon' => 'checked');
}
# wahrscheinlicher Spam
# aus /home/spamdef/.spamd/user_prefs
# required_hits 5.0
$template->param('special_selected_pspam' . $user_prefs{'required_hits'} => 'selected');
# Aktion warscheinlicher Spam
# PSPAM=MARK #MARK;HEADER
if($procmailrc{'PSPAM'} eq 'MARK'){
$template->param('special_checked_mark_pspam' => 'checked');
}
elsif($procmailrc{'PSPAM'} eq 'HEADER'){
$template->param('special_checked_header_pspam' => 'checked');
}
# Subjektpräfix Spamverdacht
$template->param('special_subj_pspam' => $procmailrc{'SUBJ_PSPAM'});
# sicherer Spam
# aus /etc/procmailrc
# CLEVEL='\*\*\*\*\*\*\*\*\*\*'
# Wert wurde schon als Zahl beim Parsen in $procmailrc{'CLEVEL'} gespeichert
$template->param('special_selected_cspam' . $procmailrc{'CLEVEL'} => 'selected');
# Aktion sicherer Spam
# CSPAM=MARK #DEL;MARK;HEADER
if($procmailrc{'CSPAM'} eq 'MARK'){
$template->param('special_checked_cspam_mark' => 'checked');
}
elsif($procmailrc{'CSPAM'} eq 'HEADER'){
$template->param('special_checked_cspam_header' => 'checked');
}
elsif($procmailrc{'CSPAM'} eq 'DEL'){
$template->param('special_checked_cspam_delete' => 'checked');
}
# Subjektpräfix sicherer Spam
$template->param('special_subj_cspam' => $procmailrc{'SUBJ_CSPAM'});
# Bericht user_prefs:
# report_safe 1
if($user_prefs{'report_safe'} eq '1'){
$template->param('special_checked_report_safe_on' => 'checked');
}
else{
$template->param('special_checked_report_safe_off' => 'checked');
}
# ugly unhack from score_DNSBL 10 to DNSBL 10
my @scores = ();
foreach(keys %user_prefs){
next unless (/^score_/);
next unless ($user_prefs{$_} =~ /[0-9\.]+/);
my $rule = $_;
$rule =~ s/^score_//;
push @scores, $rule . ' ' . $user_prefs{$_};
}
$template->param('special_scores' => join("\n", sort @scores));
}
else{
if($input{'special_action_virus'} eq 'OFF'){
$template->param('special_checked_virusoff' => 'checked');
}
elsif($input{'special_action_virus'} eq 'DEL'){
$template->param('special_checked_virusdel' => 'checked');
}
elsif($input{'special_action_virus'} eq 'MARK'){
$template->param('special_checked_virusmark' => 'checked');
}
if($input{'special_spamd'} eq 'OFF'){
$template->param('special_checked_spamdoff' => 'checked');
}
elsif($input{'special_spamd'} eq 'ON'){
$template->param('special_checked_spamdon' => 'checked');
}
$template->param('special_selected_pspam' . $input{'special_pspam_level'} => 'selected');
if($input{'special_action_pspam'} eq 'MARK'){
$template->param('special_checked_mark_pspam' => 'checked');
}
elsif($input{'special_action_pspam'} eq 'HEADER'){
$template->param('special_checked_header_pspam' => 'checked');
}
$template->param('special_selected_cspam' . $input{'special_cspam_level'} => 'selected');
if($input{'special_action_cspam'} eq 'MARK'){
$template->param('special_checked_cspam_mark' => 'checked');
}
elsif($input{'special_action_cspam'} eq 'HEADER'){
$template->param('special_checked_cspam_header' => 'checked');
}
elsif($input{'special_action_cspam'} eq 'DEL'){
$template->param('special_checked_cspam_delete' => 'checked');
}
if($input{'special_report_safe'} eq 'ON'){
$template->param('special_checked_report_safe_on' => 'checked');
}
elsif($input{'special_report_safe'} eq 'OFF'){
$template->param('special_checked_report_safe_off' => 'checked');
}
foreach(keys %input){
#<input name="lang_other" type="checkbox" class="language" value="other" <TMPL_VAR NAME=checked_spamd_lang_other>
next unless /^lang_(.*)$/;
$template->param('special_checked_spamd_lang_' . $1 => 'checked');
}
}
$template->param('special_spam_user_domain' => $special_spamfilter);
$template->param('special_spam_user_domain_idn' => $special_spamfilter_idn);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub change_virusfilter{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'change_virusfilter.html');
my $whitelist_content = '';
logline("debug","Creating File Object \$clamavmilter.");
my $clamavmilter = file->new({file_name => "/etc/sysconfig/clamav-milter"});
$clamavmilter->read_file;
my %clamavmilter = %{$clamavmilter->file_parsed_hash()};
logline("debug","Creating File Object \$clamavtemplate.");
my $clamavtemplate = file->new({file_name => "/etc/sysconfig/clamav-template"});
$clamavtemplate->read_file;
my %clamavtemplate = %{$clamavtemplate->file_parsed_hash()};
logline("debug","Creating File Object \$clamavwhitelist.");
my $clamavwhitelist = file->new({file_name => "/etc/sysconfig/clamav-whitelist"});
$clamavwhitelist->read_file;
my %clamavwhitelist = %{$clamavwhitelist->file_parsed_hash()};
# Virusfilter an/aus aus /etc/sysconfig/clamav-milter ziehen
# MILTER_ON=YES
# MILTER_ON=
if($clamavmilter{'MILTER_ON'} eq 'YES'){
$template->param('checked_virusfilter_on' => 'checked');
}
else{
$template->param('checked_virusfilter_off' => 'checked');
}
# Viruswhiteliste, diese Absender laufen nicht dirch Virenfilter
foreach(sort keys %clamavwhitelist){
$whitelist_content = $whitelist_content . $_ . "\n";
}
$template->param('virus_whitelist' => $whitelist_content);
# Virenbericht an/aus aus /etc/sysconfig/clamav-milter ziehen
# Bericht an: QUIET=
# Bericht aus: QUIET=YES
if($clamavmilter{'QUIT'} eq 'YES'){
$template->param('checked_report_safe_off' => 'checked');
}
else{
$template->param('checked_report_safe_on' => 'checked');
}
# Sender des Virenberichtes
# FROM=
# FROM=rttrtrtr@erererer.de
$template->param('virus_found_sender' => $clamavmilter{'FROM'});
# Subject des Virenberichtes
# [admin@mxmxmx ~]$ cat /etc/sysconfig/clamav-template
# Subject: Virugs gelöscht! [%s]
# [%s] ist Original-Subject, kann optional in Berichtsmail eingebaut werden, in Easytecc {ORGSUB} anstatt [%s] anzeigen
$template->param('virus_found_subject' => easytecc3::string_to_utf8($clamavtemplate{'subject'}));
# und der Templateinhalt
$template->param('virus_found_text' => easytecc3::string_to_utf8($clamavtemplate{'template'}));
logline("debug","change_virus text:" . $clamavtemplate{'template'});
# Headereintrag an/aus aus /etc/sysconfig/clamav-milter ziehen
# Headereintrag an: NOXHEADER=
# Headereintrag aus: NOXHEADER=YES
if($clamavmilter{'NOXHEADER'} eq 'YES'){
$template->param('checked_virusheader_off' => 'checked');
}
else{
$template->param('checked_virusheader_on' => 'checked');
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub new_cronjob{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'new_cronjob.html');
my $template_cronjob_table = HTML::Template->new(filename => 'cronjob_table.html');
my $edit_cron = '';
if($session->param('user') eq 'admin'){
$edit_cron = '1';
} else {
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my $gecos = $passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.cron-1';
}
if($gecos =~ m/\.cron-2/){
$edit_cron = '1';
}
}
$template->param('edit_cron' => $edit_cron);
$template_cronjob_table->param('edit_cron' => $edit_cron);
# bei neuem cronjob zunchst zufllige Uhrzeit zwischen 00:00 - 02:00 auswhlen, damit die Spassvgel nicht immer mintlich machen
my %cronjob = ( 'min' => int(rand('59')),
'std' => int(rand('2')));
easytecc3::cronjob_selected_time(\$template_cronjob_table, \%cronjob);
$template->param('cronjob_table' => $template_cronjob_table->output);
$template->param('job' => $input{'command'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub change_cronjob{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'change_cronjob.html');
my $template_cronjob_table = HTML::Template->new(filename => 'cronjob_table.html');
my $cronjob = $input{'cronjob'};
logline("debug","Creating File Object \$cronfile.");
my $cronfile = file->new({file_name => '/home/web/cronfile'});
$cronfile->read_file;
my %cronjobs = %{$cronfile->file_parsed_hash()};
my $cronjob_html = '';
# cronjob suchen, $cronjob ist Zeilennummer in Datei, der hash-key ist aber Befehl rückwärts
# damit das listing von gleichen jobs mit unterschiedlichen Zeiten funktioniert
# Also suchen wir nach $cronjobs{$cronjob}{'count'} = $cronjob
# Es muss zwar der ganze hash durchgegangen werden aber egal...
foreach(keys %cronjobs){
if($cronjobs{$_}{'count'} == $cronjob){
# encode_entities damit Zeichen wie " in Fomrularfeld dargestellt werden und nicht das html zerstören
$cronjobs{$_}{'job'} = encode_entities($cronjobs{$_}{'job'});
$template->param('job' => $cronjobs{$_}{'job'});
easytecc3::cronjob_selected_time(\$template_cronjob_table, \%{$cronjobs{$_}});
}
}
# $cronjobs{$cronjob}{'job'}
# $cronjobs{$cronjob}{'min'}
# $cronjobs{$cronjob}{'std'}
# $cronjobs{$cronjob}{'mday'}
# $cronjobs{$cronjob}{'mon'}
# $cronjobs{$cronjob}{'wday'}
my $edit_cron = '';
my $new_cron = '';
if($session->param('user') eq 'admin'){
$edit_cron = '1';
$new_cron = '1';
} else {
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my $gecos = $passwd{$session->param('user')}{'gecos'};
if($gecos !~ m/^CUST/){
$gecos = 'CUST.cron-1';
}
if($gecos =~ m/\.cron-[1-9]/){
$edit_cron = '1';
}
if($gecos =~ m/\.cron-2/){
$new_cron = '1';
}
}
$template->param('edit_cron' => $edit_cron);
$template_cronjob_table->param('edit_cron' => $edit_cron);
$template->param('new_cron' => $new_cron);
$template_cronjob_table->param('new_cron' => $new_cron);
$template->param('cronjob' => $cronjob);
$template->param('cron_key' => $input{'cron_key'});
$template->param('cronjob_table' => $template_cronjob_table->output);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub delete_cronjob{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'delete_cronjob.html');
my $cronjob = $input{'cronjob'};
logline("debug","Creating File Object \$cronfile.");
my $cronfile = file->new({file_name => '/home/web/cronfile'});
$cronfile->read_file;
my %cronjobs = %{$cronfile->file_parsed_hash()};
# cronjob suchen, $cronjob ist Zeilennummer in Datei, der hash-key ist aber Befehl rückwärts
# damit das listing von gleichen jobs mit unterschiedlichen Zeiten funktioniert
# Also suchen wir nach $cronjobs{$cronjob}{'count'} = $cronjob
# Es muss zwar der ganze hash durchgegangen werden aber egal...
foreach(keys %cronjobs){
if($cronjobs{$_}{'count'} == $cronjob){
$template->param('job' => encode('utf-8',$cronjobs{$_}{'job'}));
$template->param('cron_key' => $input{'cron_key'});
}
}
$template->param('cronjob' => $cronjob);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub new_htaccess{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'new_htaccess.html');
my $dir = $input{'dir'};
my $showdir = '';
my $warning = '';
unless ($dir){
$showdir = 'L__Kein gültiges Verzeichnis ausgewählt.__L';
$warning = 1;
} else {
if ($fb) {
$showdir = '/usr/local/www/apache24/noexec/' . $dir;
}
else{
$showdir = '/home/httpd/docs/' . $dir;
}
}
$template->param('dir' => $dir);
my $dir_encoded = encode_base64url($dir);
$template->param('dir_encoded' => $dir_encoded);
$template->param('showdir' => $showdir);
$template->param('warning' => $warning);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub new_dir{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'new_dir.html');
my $dir = $input{'dir'};
$template->param('dir' => $dir);
my $dir_encoded = encode_base64url($dir);
$template->param('dir_encoded' => $dir_encoded);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_new_dir{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_new_dir result:$result###");
if($result){
}
else{
$newdir = lc($input{'dir'} . '/' . $input{'newdir'});
$newdir =~ s/\/\//\//;
logline("debug","newdir: $newdir\n");
if($fb){
system("/usr/iports/bin/sudo /usr/sbin/webmkdir -p $newdir");
system("/usr/iports/bin/sudo /usr/sbin/chown.pl " . $session->param('user') . ":vuser $newdir d");
system("/usr/iports/bin/sudo /usr/sbin/chmod.pl 775 $newdir");
}
else {
system("/usr/sbin/admmkdir -p $newdir");
}
}
$result = 'L__Fehler__L: ' . $error if $error;
return error($error) if $error;
$result = 'L__Das Verzeichnis wurde erfolgreich angelegt__L';
$success_text = 'L__Das Verzeichnis wurde erfolgreich angelegt__L';
$template->param('result' => $result);
logline("debug","result = " . $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_filemanager&dir=' . encode_base64url($newdir) . '&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub change_htaccess{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'change_htaccess.html');
my $dir = $droot_prefix . '/' . $input{'dir'};
my @htuser;
open (HTPASSWD,"$dir/.htpasswd") || return(error("L__Fehler beim Lesen von .htpasswd__L:", "$!"));
my @htpasswd = <HTPASSWD>;
close(HTPASSWD);
foreach(sort @htpasswd){
next if (! /:/);
my ($user,$pass) = split /\:/, $_;
push @htuser, $user if $user;
}
my $template_user_select = HTML::Template->new(filename => 'user_select_no_multiple.html');
easytecc3::template_loop_e4(\%input,\$template_user_select, \@htuser, 'user_select', '');
$template->param('tableuser' => $template_user_select->output);
$template->param('full_dir' => $dir);
$template->param('dir' => $input{'dir'});
my $dir_encoded = encode_base64url($input{'dir'});
$template->param('dir_encoded' => $dir_encoded);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub delete_htaccess{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'delete_htaccess_all.html');
$template = HTML::Template->new(filename => 'delete_htaccess_user.html') if $input{'type'} eq 'delete_user';
my $dir = $droot_prefix . '/' . $input{'dir'};
$template->param('full_dir' => $dir);
$template->param('dir' => $input{'dir'});
my $dir_encoded = encode_base64url($input{'dir'});
$template->param('dir_encoded' => $dir_encoded);
# gibs nur bei user löschen, nicht wenn ganzer passwortschutz weg soll
$template->param('htaccessuser' => $input{'user_select'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub new_frontpage{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'new_frontpage.html');
# wenn von exec_new_frontpage kommt und User oder Passwort falsch, dann zunchst
my $result = $validation_result;
# evtl. redirect von exec_new_frontpage, wenn alte FP-Installation gefunden.
# In deisem Fall löschen von alten FP-Dateien und Ordnern anbieten
if($input{'action'} eq 'exec_new_frontpage' && ! $result){
my $template_old_frontpage = HTML::Template->new(filename => 'old_frontpage.html');
$template_old_frontpage->param('domain_select' => $input{'domain_select'});
$template->param('domain_select' => $input{'domain_select'});
$template->param('old_frontpage' => $template_old_frontpage->output);
$template->param('frontpageuser' => $input{'frontpageuser'});
$template->param('password' => $input{'password'});
}
else{
my $template_domain_select = HTML::Template->new(filename => 'domain_select.html');
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my @domains = ();
foreach(sort keys %domains){
#keine wildcarddomains für frontplage anbieten
next if(/\*/);
# damit ohne www. in selectbox angezeigt wird
my $domain_ohne_www = $_;
$domain_ohne_www =~ s/^www\.//;
push @domains, encode('utf-8', domain_to_unicode($domain_ohne_www)) . '|' . qq~value="$_"~;
}
#wenn falsche Eingabe wird new_frontpage erneut aufgerufen. fpinstall legt grundstzlich mit führendem
#www an. Von ausgewählter Domain domain_select das führende www entfernen und erneut als vorausgewählt
#anzeigen sofern vorhanden.
my $selected_domain_ohne_www = $input{'domain_select'};
$selected_domain_ohne_www =~ s/^www\.//;
easytecc3::template_loop(\%input,\$template_domain_select, \@domains, 'domain_select', encode('utf-8', domain_to_unicode($selected_domain_ohne_www)) . '|' . qq~value="$input{'domain_select'}"~);
#logline("debug","template_domain_select:\n" . $template_domain_select->output);
#my $table = $template_domain_select->output;
#my $out = $table;
$template->param('domain_select' => $template_domain_select->output);
logline("debug","template_domain_select:\n" . $template_domain_select->output);
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub delete_special_spamfilter{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'delete_special_spamfilter.html');
$template->param('special_spam_user_domain' => $input{'special_spam_user_domain'});
$template->param('special_spam_user_domain_idn' => encode('utf-8', domain_to_unicode($input{'special_spam_user_domain'})));
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub delete_frontpage{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'delete_frontpage.html');
$template->param('domain' => $input{'domain'});
$template->param('idn_domain' => encode('utf-8', domain_to_unicode($input{'domain'})));
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub auto_cronjob{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = '';
if($input{'cronjob'} eq 'delete_all_logs'){
$template = HTML::Template->new(filename => 'add_cron_delete_logfiles.html');
}
elsif($input{'cronjob'} eq 'delete_admin_email'){
$template = HTML::Template->new(filename => 'add_cron_delete_admin_email.html');
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub delete_logfiles{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'delete_logfiles.html');
my $logfile = $input{'logfile'};
my $domain = $input{'domain'};
my $idn_domain = encode('utf-8', domain_to_unicode($domain));
# wenn in Logfilebersicht auf "alle Logs zuknftig automatisch löschen klickt
if($logfile eq 'add_cron'){
$template = HTML::Template->new(filename => 'add_cron_delete_logfiles.html');
}
else{
# Log einzelner Domain löschen
if($domain){
$template->param('log_domain' => 1);
}
# Logs aller Domains löschen
elsif($logfile eq 'alldomains'){
$template->param('log_alldomain' => 1);
}
# alle Systemlogs löschen
elsif($logfile eq 'allsystem'){
$template->param('log_allsystem' => 1);
}
elsif($logfile eq 'all'){
$template->param('log_all' => 1);
}
}
$template->param('domain' => $domain);
$template->param('idn_domain' => $idn_domain);
$template->param('logfile' => $logfile);
return(\$template);
}
sub instant_mysqlbackup{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
if ($input{'nameofbackup'} eq '' || $input{'nameofbackup'} =~ m/[^A-Za-z\.\-\_0-9]/){
# $action ist Funktion, die html an html_error ausliefert
#$action = 'show_mysqlbackup_details';
$action = 'change_mysqlbackup';
return(html_error({'nameofbackup' => 'L__Der Dateiname ist ungültig__L'}));
}
my @databases;
if($session->param('user') eq 'admin' && $input{'all_databases'}){
logline("debug","instant_mysqlbackup:1");
my ($dbh, $mysql_connect_error) = easytecc3::mysql_connect();
if ($mysql_connect_error == '1'){
return(add_mysql_password());
}
my $sth = $dbh->prepare('SHOW DATABASES');
$sth->execute;
logline("debug","instant_mysqlbackup:2");
while ( my @row = $sth->fetchrow_array ){ # alle rows auslesen
foreach my $item (@row){
next if $item eq 'information_schema';
push(@databases, $item);
logline("debug","instant_mysqlbackup:$item");
}
}
} else {
push(@databases, $input{'database'});
}
my $backup = $input{'nameofbackup'};
#my $user = 'root';
#my $db_host = $ENV{HTTP_HOST};
my $mysqldump = "$easytecc_prefix/mysqldumper.pl";
#if(-e "/usr/local/etc/easytecc/.dbconf"){
# do "/usr/local/etc/easytecc/.dbconf";
#}
my $database;
foreach $database (@databases){
if( ! -d "$mysqlbackup_dir/$database"){
mkdir("$mysqlbackup_dir/$database", 0775);
`chmod 775 $mysqlbackup_dir/$database`;
}
`touch $mysqlbackup_dir/$database/$backup.lock`;
logline("debug","instant_mysqlbackup:$mysqldump $database $backup $input{'gzip_compression'}");
$| = 1;
if(my $pid = fork){
}
else{
#child
close (STDIN);
close (STDOUT);
close (STDERR);
open STDIN, '>/dev/null';
open STDOUT, '>/dev/null';
open STDERR, '>/dev/null';
system("$mysqldump $database $backup $input{'gzip_compression'} &");
exit(0);
}
}
sleep(2);
return(show_mysqlbackup_details());
}
sub change_mysqlbackup{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'change_mysqlbackup.html');
my ($database,$backup_days,$email_backup,$admin_email_from,$admin_email_to,$has_mysqlbackup) = '';
if($input{'all_databases'}){
$template->param('all_databases' => 1);
} else {
if(-e "/usr/local/etc/easytecc/mysqlbackup/$input{'database'}.dbb"){
my $dbconf = `cat /usr/local/etc/easytecc/mysqlbackup/$input{'database'}.dbb`;
($database,$backup_days,$email_backup,$admin_email_from,$admin_email_to) = split /\n/, $dbconf;
$database =~ s/^\s*\$database='(.*)'\;/$1/;
$backup_days =~ s/^\s*\$backup_days='(.*)'\;/$1/;
$email_backup =~ s/^\s*\$email_backup='(.*)'\;/$1/;
$admin_email_from =~ s/^\s*\$admin_email_from='(.*)'\;/$1/;
$admin_email_to =~ s/^\s*\$admin_email_to='(.*)'\;/$1/;
$has_mysqlbackup = '1';
}
if(-e "/usr/local/etc/easytecc/mysqlbackup/$input{'database'}.dbb" && $database eq ''){
return(error("$input{'database'}: L__Backup-Konfigurationsdatei nicht lesbar__L"));
}
$template->param('database' => $input{'database'});
}
#wenn beim Ausfllen von Formular Fehler, dann wird es mit Fehlermeldung erneut angezeigt.
#Vorauswahl wieder übernehmen.
if(exists $input{'email_backup'}){
$email_backup = $input{'email_backup'};
}
#Backup per email schicken nur für Datenbanken bis 50 MB erlauben
my (%database_size, $datadir) = easytecc3::get_size_mysql();
foreach(sort keys %database_size){
logline("debug","database_size key=$_ value=" . $database_size{$_});
}
my $database_too_big_for_mail = '';
if($database_size{$input{'database'}} >= '50000'){
$database_too_big_for_mail = '1';
$template->param('disabled_email_backup_yes' => 'disabled');
}
if($email_backup eq 'yes' && ! $database_too_big_for_mail){
$template->param('checked_email_backup_yes' => 'checked="checked"');
}
#wenn Datenbank zu groß und es wird editiert, dann auf confirm wechseln
elsif($email_backup eq 'yes' && $database_too_big_for_mail){
$template->param('checked_email_backup_confirm' => 'checked="checked"');
}
elsif($email_backup eq 'confirm'){
$template->param('checked_email_backup_confirm' => 'checked="checked"');
}
elsif($email_backup eq ''){
$template->param('checked_email_backup_no' => 'checked="checked"');
}
$template->param('admin_email_to' => $admin_email_to);
$template->param('admin_email_from' => $admin_email_from);
$template->param('backup_days' => $backup_days);
$template->param('has_mysqlbackup' => $has_mysqlbackup);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub confirm_delete_forward{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
#if ($fb) {
# $template = HTML::Template->new(filename => 'delete_multi_forward_fb.html');
#}
#else{
$template = HTML::Template->new(filename => 'delete_multi_forward.html');
#}
my %delete_forward;
foreach(sort keys %input){
# <input type="checkbox" name="delete2" value="frank">
if(/^delete[0-9]{1,4}$/){
$delete_forward{$_} = $input{$_};
}
}
my $hidden_fields_delete_forward = '';
my $delete_forward = '';
foreach(sort keys %delete_forward){
$hidden_fields_delete_forward .= qq~<input type="hidden" name="$_" value="$delete_forward{$_}">~;
$delete_forward .= $delete_forward{$_} . '<br />';
}
$template->param('domain' => $input{'domain'});
$template->param('hidden_fields_delete_forward' => $hidden_fields_delete_forward);
$template->param('delete_forward' => $delete_forward);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub confirm_restore_mysqlbackup{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'confirm_restore_mysqlbackup.html');
$template->param('database' => $input{'database'});
$template->param('backup' => $input{'backup'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub confirm_delete_mysqlbackup{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'confirm_delete_mysqlbackup.html');
$template->param('database' => $input{'database'});
$template->param('backup' => $input{'backup'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub download_mysqlbackup{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $database = $input{'database'};
my $backup = $input{'backup'};
if(-e "$mysqlbackup_dir/$database/$backup"){
logline("debug","pushing db backup = "."$mysqlbackup_dir/$database/$backup");
binmode STDOUT;
open (IF, "$mysqlbackup_dir/$database/$backup") || dienice("open $mysqlbackup_dir/$database/$backup: $!");
print "Content-Type: application/octet-stream\n";
print "Content-Disposition: attachment;filename=\"$backup\"\n\n";
print while(<IF>);
close IF;
}
logline("debug","<<< Exiting ".(caller(0))[3]."().");
exit(0);
}
sub delete_mysql_auto_backup{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $database = $input{'database'};
# automatisches Backup löschen
my $template = HTML::Template->new(filename => 'confirm_delete_mysql_auto_backup.html');
$template->param('database' => $database);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_restore_mysqlbackup{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $database = $input{'database'};
my $backup = $input{'backup'};
my $arg = '';
my $backup_file = "$mysqlbackup_dir/$database/$backup";
my $db_host = $ENV{HTTP_HOST};
$db_host = 'localhost' if $fb;
my ($dbh, $mysql_connect_error) = easytecc3::mysql_connect();
if ($mysql_connect_error == '1'){
logline("error","<<< Leaving ".(caller(0))[3]."() by mysql connect error.");
return(add_mysql_password());
}
$dbh->disconnect;
# do anstatt require, weil .dbconf schon in easytecc3::mysql_connect() gelesen wird und zweimal require der selben Datei geht nicht
my $dbconf = `cat /usr/local/etc/easytecc/.dbconf`;
my ($user,$password) = split /\n/, $dbconf;
$user =~ s/^\$user="(.*)"\;/$1/;
$password =~ s/^\$password="(.*)"\;/$1/;
$password = quotemeta($password);
logline("debug","user=$user password=$password");
if( ! -e $backup_file){
$action = 'confirm_restore_mysqlbackup';
logline("error","Das Backup existiert nicht = ".$backup_file);
return(html_error({'Fehler' => 'L__Das Backup existiert nicht__L'}));
}
if ( ! -z $backup_file && -r $backup_file){
# T wie Text
if ( -T $backup_file){
$arg = "$mysql --host=$db_host --user=$user --password=$password $database < $backup_file 2>&1";
}
# B wie Binär, also gzip-komprimiert
elsif ( -B $backup_file){
$arg = "gunzip -c $backup_file | $mysql --host=$db_host --user=$user --password=$password $database 2>&1";
}
else{
$action = 'confirm_restore_mysqlbackup';
logline("error","Der Dateityp der Backupdatei konnte nicht erkannt werden = ".$backup_file);
return(html_error({'Fehler' => 'L__Der Dateityp der Backupdatei konnte nicht erkannt werden__L'}));
}
my $got = `$arg`;
if($got && $got !~ /Using a password on the command line interface can be insecure/){
$action = 'confirm_restore_mysqlbackup';
logline("error","Das Backup konnte nicht eingespielt werden = ".$got);
return(html_error({'Fehler' => "L__Das Backup konnte nicht eingespielt werden__L: $got"}));
}
}
else{
$action = 'confirm_restore_mysqlbackup';
logline("error","Die Backupdatei durfte nicht gelesen werden oder is 0 bytes = ".$backup_file);
return(html_error({'Fehler' => 'L__Die Backupdatei konnte nicht gelesen werden__L'}));
}
$template->param('result' => 'L__Das Backup wurde erfolgreich wieder hergestellt__L');
$success_text = 'L__Das Backup wurde erfolgreich wieder hergestellt__L';
$json_output{'success_message'} = '1';
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_delete_mysql_auto_backup{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
if($result){
logline("error","exec_delete_mysql_auto_backup result = $result###");
}
else{
`rm -f $mysqlbackup_dir/$input{'database'}.dbb` unless $fb;
`/usr/iports/bin/sudo /usr/sbin/rm.pl $mysqlbackup_dir/$input{'database'}.dbb` if $fb;
logline("debug","exec_delete_mysql_auto_backup result = $result###");
$result = 'L__Das automatische Backup wurde deaktiviert__L';
$success_text = 'L__Das automatische Backup wurde deaktiviert__L';
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
$json_output{'success_message'} = '1';
return(\$template);
}
sub new_mysqluser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'new_mysqluser.html') unless $fb;
my $template = HTML::Template->new(filename => 'new_mysqluser_fb.html') if $fb;
if(defined easytecc3::is_ftp_limited()){
$template = HTML::Template->new(filename => 'option_not_available.html');
}
else{
my ($dbh, $mysql_connect_error) = easytecc3::mysql_connect();
if ($mysql_connect_error == '1'){
return(add_mysql_password());
}
$template->param('dbhost' => $ENV{HTTP_HOST} );
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_new_vhost{
#hier gibts gehacktes!
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
if($result){
# hm. hier kommen wir nie an...
# wenn Datenbank mit vhost angelegt werden soll und mysql-Verbindung fehlgeschlagen ist
# dann Formular für mysql-Passwort anzeigen
if($results->invalid( 'dbuser' ) =~ /Datenbankverbindung/){
logline("warning","invalid dbuser = " . $result);
return(add_mysql_password());
}
}
else{
my %handle_hash = %{easytecc3::return_file_handler_store()};
my $httpd_conf = $handle_hash{'/etc/httpd/conf/httpd.conf'};
my %config = %{$httpd_conf->config_hash()};
my $ip = $input{'ip_select'} if $input{'ip_select'};
#ansonsten ist es Haupt-IP aus httpd.conf
$ip = $config{'main_ip'} unless $input{'ip_select'};
$input{'droot'} = lc($input{'droot'});
my $newphp = $input{'php'};
if($input{'php_select'}){
$newphp = $input{'php_select'};
}
if(!$newphp){
$newphp = '5.5'
}
my $newwrapper = '';
my $newsuexec = '';
my $suexec_copy_wrapper_from = '';
my $suexec_copy_wrapper_to = '';
#todo: php-version aus kopiertem wrapper parsen
if($fb){
if($newphp eq '5.5'){
$newwrapper = '/usr/iports/bin/php-cgi';
}
else{
$newwrapper = "/usr/iports/php$newphp/bin/php-cgi";
$newwrapper =~ s/\.//g;
}
logline("debug","special was " . $input{'special'});
if($input{'suexec'}){
my $exec_droot = $input{'droot'};
$exec_droot =~ s/\/noexec\//\/data\//;
$suexec_copy_wrapper_from = $newwrapper;
$newwrapper = "$exec_droot/php$newphp-cgi";
$suexec_copy_wrapper_to = $newwrapper;
$newsuexec = "SuexecUserGroup $input{'ftpuser'} $input{'ftpuser'}";
if($input{'special'} =~ /\s*SuexecUserGroup\s*/){
$input{'special'} =~ s#SuexecUserGroup\s*.*#$newsuexec#g;
} else {
$input{'special'} .= "\n<IfModule suexec_module>\n$newsuexec\n<\/IfModule>";
}
if($input{'special_ssl'} =~ /\s*SuexecUserGroup\s*/){
$input{'special_ssl'} =~ s#SuexecUserGroup\s*.*#$newsuexec#g;
} else {
$input{'special_ssl'} .= "\n<IfModule suexec_module>\n$newsuexec\n<\/IfModule>";
}
}
# alter indianer kennt kein iffile
my $apache_version = `/usr/iports/sbin/httpd -v 2>/dev/null | sed '1!d ; s/[^0-9]*//g' 2>/dev/null`;
chomp($apache_version);
if($input{'openbasedir'}){
if($apache_version > 2425){
$newwrapper = "<IfFile $newwrapper>\nFcgidWrapper \"$newwrapper -d open_basedir=$input{'openbasedir'}\"\n<\/IfFile>";
} else {
$newwrapper = "FcgidWrapper \"$newwrapper -d open_basedir=$input{'openbasedir'}\"";
}
} else {
if($apache_version > 2425){
$newwrapper = "<IfFile $newwrapper>\nFcgidWrapper $newwrapper\n<\/IfFile>";
} else {
$newwrapper = "FcgidWrapper $newwrapper";
}
}
if($input{'special'} =~ /(?<!\#)FcgidWrapper/){
$input{'special'} =~ s#(<IfFile[^\n]+\n+)?(?<!\#)FcgidWrapper[^\n]+(\n+</IfFile>)?#$newwrapper#;
} else {
$input{'special'} .= "\n<IfModule fcgid_module>\n<Location \/>\n$newwrapper\n<\/Location>\n<\/IfModule>";
}
if($input{'special_ssl'} =~ /(?<!\#)*FcgidWrapper/){
$input{'special_ssl'} =~ s#(<IfFile[^\n]+\n+)?(?<!\#)*FcgidWrapper[^\n]+(\n+</IfFile>)?#$newwrapper#;
} else {
$input{'special_ssl'} .= "\n<IfModule fcgid_module>\n<Location \/>\n$newwrapper\n<\/Location>\n<\/IfModule>";
}
}
if($input{'redirect_domain'}){
my $redirect_domain = $input{'redirect_domain'};
my $redirect_path;
if(!$redirect_domain){
$redirect_domain = '%{HTTP_HOST}';
} else {
($redirect_domain,$redirect_path) = $redirect_domain =~ m/^([^\/]+)\/*(.*)$/;
}
my $redirect_scheme = 'http';
if($input{'special'} !~ /\s*RewriteRule.*REDIRECT_DOMAIN:.*/){
$input{'special'} .= "\n<IfModule rewrite_module>\nRewriteEngine On\nRewriteRule ^\/?\\.well-known/.+ - [END]\nRewriteRule . - [E=REDIRECT_DOMAIN:$redirect_domain]\nRewriteRule . - [E=REDIRECT_SCHEME:$redirect_scheme]\nRewriteCond expr \"%{HTTP_HOST} != %{ENV:REDIRECT_DOMAIN} || 'http' != %{ENV:REDIRECT_SCHEME}\"\nRewriteRule ^\\/?(.*)\$ %{ENV:REDIRECT_SCHEME}:\/\/%{ENV:REDIRECT_DOMAIN}\/\$1 [R=301,L]\n<\/IfModule>";
}
else{
$input{'special'} =~ s/\[E=REDIRECT_DOMAIN:.*\]/[E=REDIRECT_DOMAIN:$redirect_domain]/;
$input{'special'} =~ s/\[E=REDIRECT_SCHEME:.*\]/[E=REDIRECT_SCHEME:$redirect_scheme]/;
}
if(length($redirect_path)){
$input{'special'} =~ s/%\{ENV:REDIRECT_DOMAIN\}\/[^\s]+/%{ENV:REDIRECT_DOMAIN}\/$redirect_path/;
}
}
# add letsencrypt
if($input{'special'} !~ /\.well-known\//){
$input{'special'} = "<IfModule rewrite_module>\nRewriteEngine On\nRewriteRule ^\/?\\.well-known/.+ - [END]\n<\/IfModule>" . $input{'special'};
}
# set admin_users for non admin
if($session->param('user') ne 'admin'){
$input{'admin_users'} = uc ($session->param('user'));
}
my $port = '80';
my $awstats = '';
my $webmail = '';
$webmail = qq~Alias /zarafa $droot_prefix/zarafa~ if $input{'webmail'} eq 'zarafa';
$webmail = qq~Alias /webmail $droot_prefix/roundcube~ if ($input{'webmail'} eq 'roundcube' && ! $fb);
#$webmail = qq~Redirect /webmail /roundcube~ if ($input{'webmail'} eq 'roundcube' && $fb);
my $cgi_bin = '';
$cgi_bin = qq~ScriptAlias /cgi-bin/ $cgi_prefix/~ if $input{'cgi-bin'};
my $cgi_local = '';
if ($fb && $input{'cgi-local'}) {
$cgi_local = qq~$input{'droot'}/cgi-local/~;
$cgi_local =~ s/\/noexec\//\/data\//;
$cgi_local = qq~ScriptAlias /cgi-local/ $cgi_local
<Directory "$cgi_local">
AllowOverride None
Options None
Require all granted
</Directory>
~;
}
elsif ( ! $fb && $input{'cgi-local'}) {
$cgi_local = qq~ScriptAlias /cgi-local/ $input{'droot'}/cgi-local/~;
}
my $mysql = '';
$mysql = qq~Alias /mysql $droot_prefix/phpMyAdmin~ if ($input{'mysql'} && ! $fb);
$mysql = qq~Alias /mysql /usr/local/www/phpMyAdmin~ if ($input{'mysql'} && $fb);
#pop, for, aut auf null wenn leer
$input{'pop'} = '0' unless $input{'pop'};
$input{'for'} = '0' unless $input{'for'};
$input{'aut'} = '0' unless $input{'aut'};
my $domains = $input{'domains'};
#Zeilenumbrche aus mehrzeiligem Fomrularfeld entfernen
$domains =~ s/\r\n/ /g;
#lowercase
$domains =~ tr/A-Z/a-z/;
#erstes www. wenn vorhanden entfernen
$domains =~ s/^www\.//;
#wenn andere Domains mit www. dann das auch weg
$domains =~ s/(;|:|,|\t+|\s+)www\./ /g;
my @domains_tmp = split m(;|:|,|\t+|\s+), $domains;
my @domains = ();
#seriously...
#apache2.0:
#ServerName *.test.de
#ServerAlias *.test.de www.*.test.de
#apache2.4:
#ServerName test.de
#ServerAlias *.test.de www.*.test.de
foreach(@domains_tmp){
#bei wildcarddomains schlägt domain_to_ascii fehl, daher * abschneiden, domain_to_ascii und * wieder ranhängen
if(/^\*\.(.*)$/){
my $domain = $1;
$domain = ascii_domain($domain);
$domain = '*.' . $domain;
push @domains, $domain;
}
else{
push @domains, ascii_domain($_);
}
}
#serveradmin umlautfähig
my $serveradmin = email_to_ascii($input{'serveradmin'});
my $servername = $domains[0];
if ($fb && $servername =~ /^\*\.(.*)$/) {
$servername = $1;
if (! grep $_ eq $servername, @domains) {
push @domains, ascii_domain($servername);
}
}
my $domain_ohne_www = $servername;
$servername = 'www.' . $servername if($servername !~ /^www\./);
$result .= join('#',@domains);
logline("debug","domains = " . join(' ',@domains));
unless($input{'ftp'}){
if ($fb){
system("/usr/iports/bin/sudo /usr/sbin/webmkdir -p $input{'droot'}")
}
else{
system("/usr/sbin/admmkdir -p $input{'droot'}");
system("chmod 775 $input{'droot'}");
system("$easytecc_prefix/chmod.pl 775 $input{'droot'}");
}
}
my $logfiles = '';
#logfiles schreiben, wenn Statistikauswertung erfolgen soll
if($input{'stats'} eq 'webalizer' || $input{'stats'} eq 'awstats'){
$logfiles = qq~CustomLog /home/web/log/access_log_$domain_ohne_www combined~;
}
if($input{'stats'} eq 'awstats'){
if($input{'suexec'}){
#my $servername = `grep -m1 han-solo.net /etc/hosts | awk '{print \$2}'`;
my $servername = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
chomp $servername;
$awstats = qq~Redirect /stats http://$servername/awstats/awstats.pl?config=$domain_ohne_www~;
} else {
$awstats = qq~Redirect /stats http://$servername/awstats/awstats.pl?config=$domain_ohne_www~;
}
my $got = `$easytecc_prefix/gen_awstats.pl $domain_ohne_www newlog`;
return(error("L__Fehler beim Anlegen der Statistik für Domain__L $domain_ohne_www : $got")) if $got;
#awstats-cronjob anlegen, sofern noch nicht vorhanden und webalizer-cronjob entfernen sofern vorhanden
my @new_cronfile = ();
my $has_webalizer_cron = '';
my $has_awstats_cron = '';
logline("debug","Creating File Object \$cronfile.");
my $cronfile = file->new({file_name => '/home/web/cronfile'});
$cronfile->read_file;
foreach($cronfile->file_content){
#cronjob löschen
if (/\/usr\/local\/etc\/$domain_ohne_www\.conf/){
logline("debug","cronjob löschen = $_");
$has_webalizer_cron = '1';
next;
}
if (/awstats_updateall\.pl/){
$has_awstats_cron = '1';
}
# alles andere in zu schreibendes cronfile
push @new_cronfile, $_;
}
#ggf. awstatscronjob hinzufügen
if(! $has_awstats_cron){
my $min = int(rand('59'));
push @new_cronfile, qq~$min 0 * * * $awstats_updateall now 1>/dev/null 2>/dev/null\n~;
}
$cronfile->file_content(\@new_cronfile);
my $got = $cronfile->write_file;
return(error($got)) if $got;
}
elsif($input{'stats'} eq 'webalizer'){
#ggf. vorhandene awstats-conf löschen, die Statistiken selbst löschen wir lieber nicht... cleanup kann man irgendwann immer noch abhängig von letztem Zugriff machen
if(-e "$awstats_conf_prefix/awstats.$domain_ohne_www.conf"){
my $got = `rm -f $awstats_conf_prefix/awstats.$domain_ohne_www.conf`;
return(error("L__Fehler beim Löschen der AWStats-Konfigurationsdatei für Domain__L $domain_ohne_www:$got")) if $got;
}
#neuen webalizer-cronjob und webalizerdatei anlegen
unless(`grep '/usr/local/etc/$domain_ohne_www.conf' /home/web/cronfile`){
logline("debug","Creating File Object \$cronfile.");
my $cronfile = file->new({file_name => '/home/web/cronfile'});
my $got = $cronfile->read_file;
my $min = int(rand('59'));
push @{$cronfile->file_content}, qq~$min 0 * * * /usr/local/bin/webalizer -c /usr/local/etc/$domain_ohne_www.conf 1>/dev/null 2>/dev/null\n~;
my $got = $cronfile->write_file;
return(error($got)) if $got;
easytecc3::generatewebalizer($domain_ohne_www, $input{'droot'});
}
}
#Serveraliaszeile
my $serveralias = "";
foreach(@domains){
$serveralias .= $_ . ' www.' . $_ . ' ';
}
my $new_vhost = qq~
<VirtualHost $ip:$port>
ServerAdmin $serveradmin
DocumentRoot $input{'droot'}
ServerName $servername
ServerAlias $serveralias
$logfiles
$cgi_bin
$cgi_local
$webmail
$mysql
$awstats
$input{'special'}
#POP:$input{'pop'}
#FOR:$input{'for'}
#AUT:$input{'aut'}
#QUOT:$input{'quota'}
#CUSTOM_TAG:$input{'custom_tag'}
#ADMIN_USERS:$input{'admin_users'}
</VirtualHost>
~;
push @{$httpd_conf->file_content} , split(/\n/,$new_vhost);
logline("debug","new_vhost=$new_vhost");
if($input{'ftp'}){
$input{'gecos'} = $input{'ftpdescription'};
$error = easytecc3::add_ftpuser(\%input);
return(error('L__Konnte FTP-User nicht anlegen__L')) if $error;
if($input{'suexec'}){
#todo: cp.pl anpassen?
#my $got = `/usr/iports/bin/sudo /usr/sbin/cp.pl $suexec_copy_wrapper_from $suexec_copy_wrapper_to 2>&1`;
#berechtigungen von -o wieder zurücksetzen
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl $input{'ftpuser'}:vuser $input{'droot'} d 2>&1`;
return(error("L__Fehler beim Setzen des Besitzers für__L $input{'droot'}: $got")) if $got;
$got = `/usr/iports/bin/sudo /usr/sbin/chmod.pl 775 $input{'droot'} 2>&1`;
return(error("L__Fehler beim Setzen der Berechtigungen für__L $input{'droot'}: $got")) if $got;
$got = `cp -f $suexec_copy_wrapper_from $suexec_copy_wrapper_to`;
return(error("L__Fehler beim Kopieren von__L $suexec_copy_wrapper_from L__zu__L $suexec_copy_wrapper_to: $got")) if $got;
#und wieder setzen
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl $input{'ftpuser'}:$input{'ftpuser'} $input{'droot'} d 2>&1`;
return(error("L__Fehler beim Setzen des Besitzers für__L $input{'droot'}: $got")) if $got;
$got = `/usr/iports/bin/sudo /usr/sbin/chmod.pl 755 $input{'droot'} 2>&1`;
return(error("L__Fehler beim Setzen der Berechtigungen für__L $input{'droot'}: $got")) if $got;
}
}
if($input{'mysql_db'}){
$error = easytecc3::add_mysqldb(\%input);
return(error('L__Konnte Datenbank nicht anlegen__L')) if $error;
$error = easytecc3::add_mysqluser(\%input);
return(error('L__Konnte mySQL-User nicht anlegen__L')) if $error;
}
my $got = $httpd_conf->write_file;
return(error($got)) if $got;
$result = qq~L__Der vHost wurde erfolgreich angelegt__L!~;
$result .= qq~<a href="/cgi-bin/easytecc3/index.pl?action=change_popuser&domain=$servername">L__Fortfahren mit E-Mail-User anlegen__L</a><br />~ if $input{'pop'};
$result .= qq~<a href="/phpMyAdmin" target="_blank">L__Fortfahren mit phpMyAdmin__L</a><br />~ unless $fb;
$result .= qq~<a href="/phpmyadmin" target="_blank">L__Fortfahren mit phpMyAdmin__L</a><br />~ if $fb;
$success_text = qq~L__Der vHost wurde erfolgreich angelegt__L!~;
}
$template->param('result' => $result);
logline("debug","result = " . $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_vhosts&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_delete_vhost{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
logline("debug","exec_delete_vhost result:$result###");
if($result){
}
else{
# Kunde
if($session->param('user') ne 'admin'){
my $loginuser = $session->param('user');
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
if ($passwd{$loginuser}{'gecos'} !~ /\.vhost-[1-9]/){
return(error("L__Sie können diese Domain nicht verändern.__L"));
}
}
# httpd.conf wurde bereits bei Validierung eingelesen und in globale Variable gespeichert, damit ersparen wir uns doppelte Arbeit
my %handle_hash = %{easytecc3::return_file_handler_store()};
my $httpd_conf = $handle_hash{'/etc/httpd/conf/httpd.conf'};
my %domains = %{$httpd_conf->file_parsed_hash()};
my $droot = $domains{$input{'domain'}}{'droot'};
my $vhost_to_delete = $input{'domain'};
my $vhost_to_delete_ohne_www = $vhost_to_delete;
$vhost_to_delete_ohne_www =~ s/^www\.//;
#vhost aus httpd.conf löschen
my @new_httpd_conf = ();
my $vhost = '';
my $delete_this_vhost = '';
my @tmp_vhost = ();
foreach($httpd_conf->file_content){
chomp;
$vhost = 1 if(/^\<VirtualHost\s+([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}):/i);
if($vhost){
push @tmp_vhost, $_;
my $vhost_to_delete_quoted = quotemeta("$vhost_to_delete");
$delete_this_vhost = '1' if(/^ServerName\s+$vhost_to_delete_quoted\b/);
#dieser vhost ist es nicht, also in @tmp_vhost gesammelte Zeilen unverändert übernehmen
if(/^\<\/VirtualHost/ && ! $delete_this_vhost){
push @new_httpd_conf, @tmp_vhost;
$vhost = '';
@tmp_vhost = ();
}
#oder match auf zu löschenden vhost, hier passiert nix und vhost wird nicht in new_httpd_conf gepushed, gleichbedeutend mit löschen
elsif(/^\<\/VirtualHost/ && $delete_this_vhost){
logline("debug","vhost=$vhost");
$vhost = '';
@tmp_vhost = ();
# $delete_this_vhost wieder auf null setzen, da es mehrere vhost mit gleichem Namen geben kann, z.B. wegen SSL oder
# propagationsvhost mit alter IP. Alles weghauen
$delete_this_vhost = '';
}
}
else{
push @new_httpd_conf, $_;
}
}
@{$httpd_conf->file_content} = @new_httpd_conf;
if($input{'delete_ftpuser'}){
# delete_droot = 0: Inhalt von home user admin zuordnen
# delete_droot = 1: home löschen
my $got = easytecc3::del_ftpuser($input{'delete_ftpuser'}, $input{'delete_droot'});
return(error("L__Fehler beim Löschen von FTP-User__L: $got")) if $got;
}
# wenn es FTP-User zum löschen gibt und delete_droot=1, dann wurde home schon beim löschen von
#ftpuser gelöscht
#TODO fb
if($input{'delete_droot'} && !$input{'delete_ftpuser'}){
my $got = `/usr/iports/bin/sudo /usr/sbin/rm.pl $droot d` if $fb;
my $got = `$easytecc_prefix/rm.pl $droot d` unless $fb;
return(error("L__Fehler beim Löschen von__L $droot: $got")) if ($got || -d "$droot");
}
#domainspezifische Spameinstellungen löschen
if(-e "/home/$vhost_to_delete_ohne_www/.spamd/user_prefs"){
my $tmperror = system("/usr/sbin/delspam","-n","$vhost_to_delete_ohne_www") unless $fb;
my $tmperror = `/usr/iports/bin/sudo /usr/sbin/delspam -n $vhost_to_delete_ohne_www` if $fb;
return(html_error(({'L__Die Spameinstellungen konnten nicht gelöscht werden__L' => "$tmperror"}))) if $tmperror;
my $got = easytecc3::delete_from_spamconf($vhost_to_delete_ohne_www);
return(html_error(({'L__Die Spameinstellungen konnten nicht gelöscht werden__L' => "$got"}))) if $got;
}
# E-Mailuser und Weiterleitungen löschen
if($input{'delete_email'}){
my @new_virtmaps = ();
my @new_aliases = ();
my %delete_from_aliases = ();
my $domain = $input{'domain'};
$domain =~ s/^www\.//;
$mailpasswd = easytecc3::get_mailpasswd();
my %passwd = %{$mailpasswd->file_parsed_hash()};
#my %passwd = %{easytecc3::get_mailpasswd()};
logline("debug","Creating File Object \$virtmaps.");
my $virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %virtmaps = %{$virtmaps->file_parsed_hash()};
logline("debug","Creating File Object \$aliases.");
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
my $serveralias = '';
foreach(@{$domains{$input{'domain'}}{'domains'}}){
logline("debug","serveralias=$_");
#wildcard gibs in emailadressen nicht
next if /^\*\./;
#ebenso kein www....
next if /^www\./;
next if /^$domain_ohne_www$/;
$serveralias .= $_ . '|';
}
#das letzte | weg, daruas können wir dann regex (domain1|domain2|domain3) basteln fr
#match auf lhs in virtmaps um Weiterleitungen zu löschen
$serveralias =~ s/\|$//;
my $emailadress_regex = $serveralias;
logline("debug","emailadress_regex=$emailadress_regex");
foreach my $user(sort keys %passwd){
logline("debug","E-Mailuser=$user gecos=" . $passwd{$user}{'gecos'});
next if $passwd{$user}{'gecos'} !~ /^$domain - POP/;
#userspezifische Spameinstellungen löschen
if(-e "/home/$user/.spamd/user_prefs"){
my $tmperror = system("/usr/sbin/delspam","-n","$user") unless $fb;
my $tmperror = `/usr/iports/bin/sudo /usr/sbin/delspam -n $user` if $fb;
return(html_error(({'L__Die Spameinstellungen konnten nicht gelöscht werden__L' => "$tmperror"}))) if $tmperror;
my $got = easytecc3::delete_from_spamconf($olduser);
return(html_error(({'L__Die Spameinstellungen konnten nicht gelöscht werden__L' => "$got"}))) if $got;
}
#TODO fb
if ($fb) {
my $mailpasswd = easytecc3::get_mailpasswd();
my @new_mailpasswd = $mailpasswd->file_content;
#vorhandenen Eintrag entfernen
@new_mailpasswd = grep !/^$user:/, @new_mailpasswd;
@{$mailpasswd->file_content} = @new_mailpasswd;
$got = $mailpasswd->write_file;
logline("error","mailpasswd->write_file got = $got") if $got;
return(error($got)) if $got;
}
else{
my $got = `/usr/sbin/deluser -m -r -n "$user"`;
return(error("L__Fehler beim Löschen von E-Mailuser__L: $got")) if $got;
}
# .pass datei
`rm -f "/usr/local/etc/easytecc/$user.pass"`;
}
foreach($virtmaps->file_content) {
# match auf Weiterleitung von Domain aus zu löschendem vhost
if(/^[a-zA-Z0-9_\-\.]{0,100}\@($emailadress_regex)\s+(.*)$/){
my $target_to_delete = $2;
logline("debug","match emailadress=$_ target_to_delete=$target_to_delete");
# Ziel kann Weiterleitung auf mehrere user und/oder autoresponder sein,
# diese ebenfalls aus aliases entfernen
if($target_to_delete =~ /_aut$/){
$delete_from_aliases{$target_to_delete} = $forcount;
my $autoreply_file = $target_to_delete;
$autoreply_file =~ s/_aut/\.aut/;
`rm -f /usr/local/etc/$autoreply_file`;
}
elsif($target_to_delete =~ /_spl$/){
$delete_from_aliases{$target_to_delete} = $forcount;
}
}
else{
#alle Zeilen, die nicht auf zu löschen vhost matchen wieder in neue virtmaps übernehmen
push @new_virtmaps, $_;
}
}
@{$virtmaps->file_content} = map(lc, @new_virtmaps);
my $got = $virtmaps->write_file;
if ($got) {
logline("error","virtmaps->write_file = ".$got);
return(error($got));
}
# aus hash %delete_from_aliases regex basteln, um Zeilen aus aliases zu matchen die gelöscht werden sollen
my $delete_from_aliases_regex = join('|',keys %delete_from_aliases);
logline("debug","delete_from_aliases_regex=$delete_from_aliases_regex");
foreach($aliases->file_content) {
if(/^($delete_from_aliases_regex)\s*:/){
logline("debug","match aliases=$_");
#nix, Zeile wird gelöscht
}
else{
#alles andere wieder übernehmen
push @new_aliases, $_;
}
}
if(keys %delete_from_aliases){
@{$aliases->file_content} = @new_aliases;
my $got = $aliases->write_file;
if ($got) {
logline("error","aliases->write_file = ".$got);
return(error($got));
}
}
my $sendmail_cw = file->new({file_name => '/etc/mail/sendmail.cw'});
$sendmail_cw->read_file;
my @sendmail_cw = @{$sendmail_cw->file_content()};
my @new_sendmail_cw = grep !/^$serveralias/, @sendmail_cw;
@{$sendmail_cw->file_content} = @new_sendmail_cw;
$got = $sendmail_cw->write_file;
if ($got) {
logline("error","aliases->write_file = ".$got);
return(error($got));
}
# .pass datei-reste
my $passfiles = '/usr/local/etc/easytecc/*@' . $domain . '.pass';
`rm -f $passfiles`;
}
### Mario: Sobald ein SSL-VHost gelöscht wird -jedoch nicht das SSL-Zertifikat- dann wird durch den Cronjob immer wieder versucht,
### das SSL-Zertifikat zu verlängern. Daher müssen einige Schritte durchgeführt werden ...
if($input{'delete_ssl_files'}){
#my $got = `/usr/iports/bin/sudo /usr/sbin/rm.pl $droot d` if $fb;
#my $got = `$easytecc_prefix/rm.pl $droot d` unless $fb;
logline("debug"," MARIO delete_ssl_files von $vhost_to_delete_ohne_www");
system('/bin/sh -c "/usr/iports/bin/letsencrypt revoke --cert-path ' . $domains{$input{'domain'}}{'ssl_cert'} . '"');
#return(error("L__Fehler beim Löschen von__L $droot: $got")) if ($got || -d "$droot");
}
#awstats und/oder webalizer-Statistik löschen
if ($fb) {
`rm -f /usr/local/etc/awstats/awstats.$vhost_to_delete_ohne_www.conf`;
`rm -f /usr/local/www/awstats/cgi-bin/awstats[0-9][0-9][0-9][0-9][0-9][0-9].$vhost_to_delete_ohne_www.*`;
} else {
if(-e "$awstats_conf_prefix/awstats.$vhost_to_delete_ohne_www.conf"){
logline("debug","awstats loeschen:$awstats_conf_prefix/awstats.$vhost_to_delete_ohne_www.conf");
my $got = `$easytecc_prefix/rm.pl $awstats_conf_prefix/awstats.$vhost_to_delete_ohne_www.conf`;
my $got = `$easytecc_prefix/rm.pl /var/lib/awstats/awstats[0-9][0-9][0-9][0-9][0-9][0-9].$vhost_to_delete_ohne_www.txt`;
my $got = `$easytecc_prefix/rm.pl /var/lib/awstats/awstats[0-9][0-9][0-9][0-9][0-9][0-9].$vhost_to_delete_ohne_www.bak`;
}
}
if(-e "/usr/local/etc/$vhost_to_delete_ohne_www.conf"){
logline("debug","webalizer loeschen: /usr/local/etc/$vhost_to_delete_ohne_www.conf");
my $got = `$easytecc_prefix/rm.pl /usr/local/etc/$vhost_to_delete_ohne_www.conf`;
logline("debug","Creating File Object \$cronfile.");
my $cronfile = file->new({file_name => '/home/web/cronfile'});
$cronfile->read_file;
my @new_cronfile = ();
foreach($cronfile->file_content){
#cronjob löschen
if (/webalizer -c \/usr\/local\/etc\/$vhost_to_delete_ohne_www.conf/){
logline("debug","cronjob löschen:$_");
next;
}
# alles andere in zu schreibendes cronfile
push @new_cronfile, $_;
}
$cronfile->file_content(\@new_cronfile);
my $got = $cronfile->write_file;
if ($got) {
logline("error","cronfile->write_file = ".$got);
return(error($got));
}
}
my $got = $httpd_conf->write_file;
return(error($got)) if $got;
$result = 'L__Der vHost wurde erfolgreich gelöscht!__L';
$success_text = 'L__Der vHost wurde erfolgreich gelöscht!__L';
}
$template->param('result' => $result);
logline("debug","result = " . $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_vhosts&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_change_vhost{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
logline("debug","exec_change_vhost result:$result###");
if($result){
}
else{
# httpd.conf wurde bereits bei Validierung eingelesen und in globale Variable gespeichert, damit ersparen wir uns doppelte Arbeit
my %handle_hash = %{easytecc3::return_file_handler_store()};
my $httpd_conf = $handle_hash{'/etc/httpd/conf/httpd.conf'};
my %domains = %{$httpd_conf->file_parsed_hash()};
my %config = %{$httpd_conf->config_hash()};
my $vhost = $input{'vhost'};
my $domain_ohne_www = $vhost;
$domain_ohne_www =~ s/^www\.//;
# die alte IP des zu ändernden vhosts, wichtig falls mehrere IPs vorhanden um zu ändernden vhost eindeutig zu identifizieren
my $oldip = $input{'ip'};
my $port = $input{'port'};
#optionales hiddenfeld, nur wenn vhost SSL hat
my $old_ssl_port = $input{'old_ssl_port'};
my $ssl_port = $input{'ssl_port'};
# wenn vhost SSL hat, dann ist hiddenfeld ssl_port gesetzt
my $ssl = '1' if $input{'old_ssl_port'};
# wenn Server mehrere IPs hat, dann Formularfeld ip_select auswerten
my $newip = $input{'ip_select'} if $input{'ip_select'};
#ansonsten ist es hidden-Feld ip
$newip = $input{'ip'} unless $input{'ip_select'};
my $awstats = '';
#if(!length($input{'ssl_droot'})){
$input{'ssl_droot'} = $input{'droot'};
#}
if(!length($input{'ssl_port'})){
$input{'ssl_port'} = 443;
}
if($input{'stats'} eq 'awstats'){
if($input{'suexec'}){
#my $vhost = `grep -m1 han-solo.net /etc/hosts | awk '{print \$2}'`;
my $vhost = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
chomp $vhost;
$awstats = qq~Redirect /stats http://$vhost/awstats/awstats.pl?config=$domain_ohne_www~;
} else {
$awstats = qq~Redirect /stats http://$vhost/awstats/awstats.pl?config=$domain_ohne_www~;
}
}
# preserve admin_users and ip for non admin
if($session->param('user') ne 'admin'){
$input{'admin_users'} = $domains{$vhost}{'admin_users'};
$newip = $domains{$vhost}{'ip'};
}
my $newphp = $input{'php'};
if($input{'php_select'}){
$newphp = $input{'php_select'};
}
if(!$newphp){
$newphp = '5.5'
}
my $newwrapper = '';
my $newsuexec = '';
my $suexec_copy_wrapper_from = '';
my $suexec_copy_wrapper_to = '';
if($fb){
if($newphp eq '5.5'){
$newwrapper = '/usr/iports/bin/php-cgi';
}
else{
$newwrapper = "/usr/iports/php$newphp/bin/php-cgi";
$newwrapper =~ s/\.//g; # Der Punkt in der Version wird entfernt. #
}
logline("debug","special was " . $input{'special'});
if($input{'suexec'}){
my $exec_droot = $input{'droot'};
$exec_droot =~ s/\/noexec\//\/data\//;
$suexec_copy_wrapper_from = $newwrapper;
$newwrapper = "$exec_droot/php$newphp-cgi";
$suexec_copy_wrapper_to = $newwrapper;
$newsuexec = "SuexecUserGroup $input{'ftpuser'} $input{'ftpuser'}";
if($input{'special'} =~ /\s*[^#]\s*SuexecUserGroup\s+/){
$input{'special'} =~ s#SuexecUserGroup\s*.*#$newsuexec#g;
} else {
$input{'special'} .= "\n<IfModule suexec_module>\n$newsuexec\n<\/IfModule>";
}
if($input{'special_ssl'} =~ /\s*[^#]\s*SuexecUserGroup\s+/){
$input{'special_ssl'} =~ s#SuexecUserGroup\s*.*#$newsuexec#g;
} else {
$input{'special_ssl'} .= "\n<IfModule suexec_module>\n$newsuexec\n<\/IfModule>";
}
# dann halt hier...
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my $gecos = $passwd{$input{'ftpuser'}}{'gecos'};
#i hate my life
$got = `/usr/iports/bin/sudo /usr/sbin/usermod -h '$input{'droot'}' -u '$input{'ftpuser'}' -d "'$gecos'" -o 2>&1`;
if($got && $got !~ m/group\sname.*already\sexists/){
return(error("L__Fehler beim Ändern des FTP-Benutzers__L $input{'ftpuser'}: $got")) if $got;
}
#berechtigungen von -o wieder zurücksetzen
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl $input{'ftpuser'}:vuser $input{'droot'} d 2>&1`;
return(error("L__Fehler beim Setzen des Besitzers für__L $input{'droot'}: $got")) if $got;
$got = `/usr/iports/bin/sudo /usr/sbin/chmod.pl 775 $input{'droot'} 2>&1`;
return(error("L__Fehler beim Setzen der Berechtigungen für__L $input{'droot'}: $got")) if $got;
$got = `rm -f $suexec_copy_wrapper_to 2>/dev/null`;
$got = `cp -f $suexec_copy_wrapper_from $suexec_copy_wrapper_to`;
return(error("L__Fehler beim Kopieren von__L $suexec_copy_wrapper_from L__zu__L $suexec_copy_wrapper_to: $got")) if $got;
#und wieder setzen
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl $input{'ftpuser'}:$input{'ftpuser'} $input{'droot'} d 2>&1`;
return(error("L__Fehler beim Setzen des Besitzers für__L $input{'droot'}: $got")) if $got;
$got = `/usr/iports/bin/sudo /usr/sbin/chmod.pl 755 $input{'droot'} 2>&1`;
return(error("L__Fehler beim Setzen der Berechtigungen für__L $input{'droot'}: $got")) if $got;
} elsif ($input{'special'} =~ m/<IfModule suexec_module>[^<]*<\/IfModule>/) {
logline("debug","exec_change_vhost undoing suexec: $input{'ftpuser'}\n");
$input{'special'} =~ s/<IfModule suexec_module>[^<]*<\/IfModule>//m;
$input{'special_ssl'} =~ s/<IfModule suexec_module>[^<]*<\/IfModule>//m;
#$input{'special'} =~ s/SuexecUserGroup/#SuexecUserGroup/;
#$input{'special_ssl'} =~ s/SuexecUserGroup/#SuexecUserGroup/;
#/usr/sbin/usermod kann die gruppe leider nicht entfernen, deswegen admin und cmsfix
if (length($input{'ftpuser'})){
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl $input{'ftpuser'}:vuser $input{'droot'} d 2>&1`;
return(error("L__Fehler beim Setzen des Besitzers für__L $input{'droot'}: $got")) if $got;
$got = `/usr/iports/bin/sudo /usr/sbin/cms_fix.pl $input{'ftpuser'} $input{'droot'} 2>&1`;
return(error("L__Fehler beim Setzen der Berechtigungen für__L $input{'droot'}: $got")) if $got;
}
}
# alter indianer kennt kein iffile
my $apache_version = `/usr/iports/sbin/httpd -v 2>/dev/null | sed '1!d ; s/[^0-9]*//g' 2>/dev/null`;
chomp($apache_version);
if($input{'openbasedir'}){
if($apache_version > 2425){
$newwrapper = "<IfFile $newwrapper>\nFcgidWrapper \"$newwrapper -d open_basedir=$input{'openbasedir'}\"\n<\/IfFile>";
} else {
$newwrapper = "FcgidWrapper \"$newwrapper -d open_basedir=$input{'openbasedir'}\"";
}
} else {
if($apache_version > 2425){
$newwrapper = "<IfFile $newwrapper>\nFcgidWrapper $newwrapper\n<\/IfFile>";
} else {
$newwrapper = "FcgidWrapper $newwrapper";
}
}
if($input{'special'} =~ /(?<!\#)FcgidWrapper/){
$input{'special'} =~ s#(<IfFile[^\n]+\n+)?(?<!\#)FcgidWrapper[^\n]+(\n+</IfFile>)?#$newwrapper#;
} else {
$input{'special'} .= "\n<IfModule fcgid_module>\n<Location \/>\n$newwrapper\n<\/Location>\n<\/IfModule>";
}
if($input{'special_ssl'} =~ /(?<!\#)FcgidWrapper/){
$input{'special_ssl'} =~ s#(<IfFile[^\n]+\n+)?(?<!\#)FcgidWrapper[^\n]+(\n+</IfFile>)?#$newwrapper#;
} else {
$input{'special_ssl'} .= "\n<IfModule fcgid_module>\n<Location \/>\n$newwrapper\n<\/Location>\n<\/IfModule>";
}
}
if($input{'redirect_domain'} ne $domains{$vhost}{'redirect_domain'} || $input{'ssl_force'} ne $domains{$vhost}{'ssl_force'}){
my $redirect_domain = $input{'redirect_domain'};
my $redirect_path;
if(!$redirect_domain){
$redirect_domain = '%{HTTP_HOST}';
} else {
($redirect_domain,$redirect_path) = $redirect_domain =~ m/^([^\/]+)\/*(.*)$/;
}
my $redirect_scheme = 'http';
if($input{'ssl_force'}){
$redirect_scheme = 'https';
}
if($input{'special'} !~ /\s*RewriteRule.*REDIRECT_DOMAIN:.*/){
$input{'special'} .= "\n<IfModule rewrite_module>\nRewriteEngine On\nRewriteRule ^\/?\\.well-known/.+ - [END]\nRewriteRule . - [E=REDIRECT_DOMAIN:$redirect_domain]\nRewriteRule . - [E=REDIRECT_SCHEME:$redirect_scheme]\nRewriteCond expr \"%{HTTP_HOST} != %{ENV:REDIRECT_DOMAIN} || 'http' != %{ENV:REDIRECT_SCHEME}\"\nRewriteRule ^\\/?(.*)\$ %{ENV:REDIRECT_SCHEME}:\/\/%{ENV:REDIRECT_DOMAIN}\/\$1 [R=301,L]\n<\/IfModule>";
}
else{
$input{'special'} =~ s/\[E=REDIRECT_DOMAIN:.*\]/[E=REDIRECT_DOMAIN:$redirect_domain]/;
$input{'special'} =~ s/\[E=REDIRECT_SCHEME:.*\]/[E=REDIRECT_SCHEME:$redirect_scheme]/;
}
if(length($redirect_path)){
$input{'special'} =~ s/%\{ENV:REDIRECT_DOMAIN\}\/[^\s]+/%{ENV:REDIRECT_DOMAIN}\/$redirect_path/;
}
if($input{'special_ssl'} !~ /\s*RewriteRule.*REDIRECT_DOMAIN:.*/){
$input{'special_ssl'} .= "\n<IfModule rewrite_module>\nRewriteEngine On\nRewriteRule ^\/?\\.well-known/.+ - [END]\nRewriteRule . - [E=REDIRECT_DOMAIN:$redirect_domain]\nRewriteCond expr \"%{HTTP_HOST} != %{ENV:REDIRECT_DOMAIN}\"\nRewriteRule ^\\/?(.*)\$ https:\/\/%{ENV:REDIRECT_DOMAIN}\/\$1 [R=301,L]\n<\/IfModule>";
}
else{
$input{'special_ssl'} =~ s/\[E=REDIRECT_DOMAIN:.*\]/[E=REDIRECT_DOMAIN:$redirect_domain]/;
#falls kopiert!
$input{'special_ssl'} =~ s/\[E=REDIRECT_SCHEME:.*\]/[E=REDIRECT_SCHEME:https]/;
$input{'special_ssl'} =~ s/\'http\'\s!=\s%\{ENV:REDIRECT_SCHEME\}/\'https\' != %{ENV:REDIRECT_SCHEME}/;
}
if(length($redirect_path)){
$input{'special_ssl'} =~ s/%\{ENV:REDIRECT_DOMAIN\}\/[^\s]+/%{ENV:REDIRECT_DOMAIN}\/$redirect_path/;
}
}
# add letsencrypt
if($input{'special'} !~ /\.well-known\//){
$input{'special'} = "<IfModule rewrite_module>\nRewriteEngine On\nRewriteRule ^\/?\\.well-known/.+ - [END]\n<\/IfModule>\n" . $input{'special'};
}
if($input{'special_ssl'} !~ /\.well-known\//){
$input{'special_ssl'} = "<IfModule rewrite_module>\nRewriteEngine On\nRewriteRule ^\/?\\.well-known/.+ - [END]\n<\/IfModule>\n" . $input{'special_ssl'};
}
if($ssl && length($input{'admin_users'})){
if($input{'special_ssl'} !~ m/ProxyPass\s\/easytecc/ && $fb){
# immer und immer wieder
#my $servername = `grep -m1 '^[^#]*han-solo.net' /etc/hosts | awk '{print \$2}'`;
my $servername = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
chomp $servername;
$input{'special_ssl'} .= "\nSSLProxyEngine on";
$input{'special_ssl'} .= "\nProxyPass /easytecc https://$servername/easytecc/";
$input{'special_ssl'} .= "\nProxyPassReverse /easytecc https://$servername/easytecc/";
$input{'special_ssl'} .= "\nProxyPass /cgi-bin/easytecc4/ https://$servername/cgi-bin/easytecc4/";
$input{'special_ssl'} .= "\nProxyPassReverse /cgi-bin/easytecc4/ https://$servername/cgi-bin/easytecc4/";
}
} elsif($input{'special_ssl'} =~ m/ProxyPass\s\/easytecc\// && $fb){
$input{'special_ssl'} =~ s/.*SSLProxyEngine\son.*//;
$input{'special_ssl'} =~ s/.*ProxyPass\s.*easytecc.*//g;
$input{'special_ssl'} =~ s/.*ProxyPassReverse\s.*easytecc.*//g;
}
logline("debug","special is " . $input{'special'});
# Wenn SSL-vhost geändert werden soll, gucken, ob gleiche IP + Port schon durch andere SSL-Domain besetzt ist
# weil sonst das Zertifikat des ersten vhosts in der httpd.conf genommen wird.
my %ip_port_used = '';
foreach(keys %domains){
next if $_ eq $vhost;
$ip_port_used{$domains{$_}{'ssl_ip'}}{$domains{$_}{'ssl_port'}} = '1';
}
# SNI allowed on fb machines
# nun auch auf linux ;-)
#if(exists $ip_port_used{$newip}{$ssl_port}){
# # return(html_error('L__Die angegebene IP und der Port werden bereits durch eine andere SSL-Domain verwendet__L'));
# return(html_error(({'ip_select' => 'L__Die angegebene IP und der Port werden bereits durch eine andere SSL-Domain verwendet__L'})));
#}
#Auswertung für awstats entfernen wenn checkbox nicht aktiv
if($input{'stats'} ne 'awstats' && -e "$awstats_conf_prefix/awstats.$domain_ohne_www.conf"){
`/usr/iports/bin/sudo /usr/sbin/rm.pl "$awstats_conf_prefix/awstats.$domain_ohne_www.conf"` if $fb;
`rm -f "$awstats_conf_prefix/awstats.$domain_ohne_www.conf"` unless $fb;
}
# falls von webalizer auf awstats oder umgekehrt gewechselt wird
elsif($input{'stats'} eq 'awstats' && ! -e "$awstats_conf_prefix/awstats.$domain_ohne_www.conf"){
# wenn schon log vorhanden, dann sucht es sich gen_awstats.pl selbst raus
if($domains{$vhost}{'access_log'} ne ''){
my $got = `$easytecc_prefix/gen_awstats.pl $domain_ohne_www`;
$got = `$easytecc_prefix/gen_awstats.pl $domain_ohne_www`;
return(error("L__Fehler beim Anlegen der Statistik für Domain__L $domain_ohne_www:$got")) if $got;
}
# wenn nicht standardpfad benutzen und gen_awstats.pl mit zweiltem Schalter mitteilen
else{
my $got = `$easytecc_prefix/gen_awstats.pl $domain_ohne_www newlog`;
return(error("L__Fehler beim Anlegen der Statistik für Domain__L $domain_ohne_www:$got")) if $got;
}
# awstats-cronjob anlegen, sofern noch nicht vorhanden und webalizer-cronjob entfernen sofern vorhanden
my @new_cronfile = ();
my $has_webalizer_cron = '';
my $has_awstats_cron = '';
logline("debug","Creating File Object \$cronfile.");
my $cronfile = file->new({file_name => '/home/web/cronfile'});
$cronfile->read_file;
foreach($cronfile->file_content){
# cronjob löschen
if (/\/usr\/local\/etc\/$domain_ohne_www\.conf/){
logline("debug","cronjob löschen:$_");
$has_webalizer_cron = '1';
next;
}
if (/awstats_updateall\.pl/){
$has_awstats_cron = '1';
}
# alles andere in zu schreibendes cronfile
push @new_cronfile, $_;
}
# ggf. awstatscron hinzufügen
if(! $has_awstats_cron){
my $min = int(rand('59'));
push @new_cronfile, qq~$min 0 * * * $awstats_updateall now 1>/dev/null 2>/dev/null\n~;
}
$cronfile->file_content(\@new_cronfile);
my $got = $cronfile->write_file;
return(error($got)) if $got;
}
elsif($input{'stats'} eq 'webalizer'){
# ggf. vorhandene awstats-conf löschen, die Statistiken selbst löschen wir lieber nicht... cleanup kann man irgendwann immer noch abhängig von letztem Zugriff machen
if(-e "$awstats_conf_prefix/awstats.$domain_ohne_www.conf"){
my $got = `rm -f $awstats_conf_prefix/awstats.$domain_ohne_www.conf`;
return(error("L__Fehler beim Löschen der AWStats-Konfigurationsdatei für Domain__L $domain_ohne_www: $got")) if $got;
}
#neuen webalizer-cronjob und webalizerdatei anlegen
unless(`grep '/usr/local/etc/$domain_ohne_www.conf' /home/web/cronfile`){
logline("debug","Creating File Object \$cronfile.");
my $cronfile = file->new({file_name => '/home/web/cronfile'});
my $got = $cronfile->read_file;
my $min = int(rand('59'));
push @{$cronfile->file_content}, qq~$min 0 * * * /usr/local/bin/webalizer -c /usr/local/etc/$domain_ohne_www.conf 1>/dev/null 2>/dev/null\n~;
my $got = $cronfile->write_file;
return(error($got)) if $got;
easytecc3::generatewebalizer($domain_ohne_www, $input{'droot'});
}
}
my @new_httpd_conf = ();
#my $special = $input{'special'};
#$special =~ s/\r\n/ /g;
my $logfiles = '';
#vorhandenen Pfad für Logfile immer übernehmen
if($domains{$vhost}{'access_log'} ne ''){
$logfiles = qq~CustomLog $domains{$vhost}{'access_log'} combined\n~;
# sofern vorhanden auch errorlog übernehmen
$logfiles .= qq~ErrorLog $domains{$vhost}{'error_log'}~ if $domains{$vhost}{'error_log'} ne '';
}
#noch kein Log vorhanden, aber Auswahl für Statistikprogramm, also Logfile anlegen
elsif($input{'stats'} eq 'webalizer' || $input{'stats'} eq 'awstats'){
$logfiles = qq~CustomLog /home/web/log/access_log_$domain_ohne_www combined\nErrorLog /home/web/log/error_log_$domain_ohne_www~;
}
my $webmail = '';
$webmail = qq~Alias /zarafa $droot_prefix/zarafa~ if $input{'webmail'} eq 'zarafa';
$webmail = qq~Alias /webmail $droot_prefix/roundcube~ if ($input{'webmail'} eq 'roundcube' && ! $fb);
#$webmail = qq~Redirect /webmail /roundcube~ if ($input{'webmail'} eq 'roundcube' && $fb);
my $cgi_bin = '';
$cgi_bin = qq~ScriptAlias /cgi-bin/ $cgi_prefix/~ if $input{'cgi-bin'};
my $cgi_local = '';
if ($fb && $input{'cgi-local'}) {
$cgi_local = qq~$input{'droot'}/cgi-local/~;
$cgi_local =~ s/\/noexec\//\/data\//;
$cgi_local = qq~ScriptAlias /cgi-local/ $cgi_local
<Directory "$cgi_local">
AllowOverride None
Options None
Require all granted
</Directory>
~;
}
elsif ( ! $fb && $input{'cgi-local'}) {
$cgi_local = qq~ScriptAlias /cgi-local/ $input{'droot'}/cgi-local/~;
}
my $mysql = '';
$mysql = qq~Alias /mysql $droot_prefix/phpMyAdmin~ if ($input{'mysql'} && ! $fb);
$mysql = qq~Alias /mysql /usr/local/www/phpMyAdmin~ if ($input{'mysql'} && $fb);
#der zu ändernde vhost
my $vhost_to_change = $input{'vhost'};
my $domains = $input{'domains'};
# Zeilenumbrche aus mehrzeiligem Fomrularfeld entfernen
$domains =~ s/\r\n/ /g;
# lowercase
$domains =~ tr/A-Z/a-z/;
# erstes www. wenn vorhanden entfernen
$domains =~ s/^www\.//;
# wenn andere Domains mit www. dann das auch weg
$domains =~ s/(;|:|,|\t+|\s+)www\./ /g;
my $servername = $servername_to_alias = ascii_domain($input{'domain'});
my $servername_to_alias = $servername;
$servername = 'www.' . $servername if($servername !~ /^www\./);
# Servername kommt auch in Serveralias rein
$servername_to_alias =~ s/^www\.//;
$domains = "$servername_to_alias " . $domains;
my @domains = split m(;|:|,|\t+|\s+), $domains;
logline("debug","domains=" . join(' ',@domains));
# Serveraliaszeile
my $serveralias = "";
foreach(@domains){
# bei wildcarddomains schlägt domain_to_ascii fehl, daher * abschneiden, domain_to_ascii und * wieder ranhängen
if(/^\*\.(.*)$/){
my $domain = $1;
$domain = ascii_domain($domain);
$domain = '*.' . $domain;
$serveralias .= $domain . ' www.' . $domain . ' ';
}
else{
$serveralias .= ascii_domain($_) . ' www.' . ascii_domain($_) . ' ';
}
}
$serveralias =~ s/\s+$//;
#Serveradmin E-Mailadresse umlautfähig
my $serveradmin = email_to_ascii($input{'serveradmin'});
my $change_this_vhost = '';
# bei erster Zeile eines vhosts wissen wir noch nicht welcher vhost es ist
#also erstmal zwischenspeichern
my @tmp_vhost = ();
my $vhost = '';
my $ssl_vhost = '';
my $vhost_ip = '';
# counter für array @new_httpd_conf, falls zweiter vhost aufgrund Änderung von IP eingefgt werden muss
my $line_vhost_port80 = '';
my $line_vhost_ssl = '';
# für den alten vhost wird ein neuer erstellt. Erkennung erfolgt mit /^ServerName\s+$vhost_to_change\b/
# Alles was dann an Zeilen vom alten vhost folgt wird gelöscht
my $discard_rest_of_old_vhost = '';
# wenn vhost auf andere IP geändert wurde wird zweiter vhost mit alter IP wegen Propagation
# angelegt. Wenn der vhost erneut geändert wird, wird beim ändern des ersten vhosts schon zweiter vhost mit alter
# IP erstellt. D.h. der zweite alte vhost in httpd.conf kann ignoriert werden. variable wird bei if($oldip ne $newip) gesetzt
my $vhost_done = '';
my $tmp_servername;
foreach($httpd_conf->file_content){
#wenn Server mehrere IPs hat, dann existieren ggf. 4 vhosts, je zwei für port 80 und 443 wegen Propagationszeit
# Änderungen dann an 4 vhosts durchführen
#wenn die IP von vhost geändert wird, dann den alten vhost belassenund neuen vhostz mit neuer IP vor alten anlegen
#auch wegen Propagation. Bei allen nderungen auch Änderung an vhost mit alter IP machen
#evtl. hat SSL-vhost Spezialeintrge, diese auf jeden Fall immer mitübernehmen, es sei denn eine Änderung matcht auf
#special line. Dabei <directory> und <ifconfig> bercksichtigen
$vhost = 1 if(/^\<VirtualHost\s+([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}):$port/i);
$ssl_vhost = 1 if(/^\<VirtualHost\s+([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}):(443|8444|8445|8080)/i);
$vhost_ip = $1;
if($vhost){
push @tmp_vhost, $_;
my $vhost_to_change_quoted = quotemeta("$vhost_to_change");
$change_this_vhost = '1' if(/^ServerName\s+$vhost_to_change_quoted\b/);
if(/^ServerName/){
$tmp_servername = $_;
logline("debug","tmpservername1=$tmp_servername");
}
#dieser vhost ist es nicht, also in @tmp_vhost gesammelte Zeilen unverändert übernehmen
if(/^\<\/VirtualHost/ && ! $change_this_vhost){
logline("debug","tmpservername2=$tmp_servername");
push @new_httpd_conf, @tmp_vhost;
$vhost = '';
@tmp_vhost = ();
}
# letzte Zeile von zu änderndem vhost, hier Variablen zurcksetzen, damit nachfolgende vhosts auch
#geschrieben werden können
elsif(/^\<\/VirtualHost/ && $change_this_vhost){
$change_this_vhost = '';
$vhost = '';
$discard_rest_of_old_vhost = '';
@tmp_vhost = ();
# ganz wichtig, sonst wird vhost doppelt geschrieben
next;
}
#oder match auf zu ändernden vhost. $vhost_done ist für den Fall, da noch nachfolgende vhosts mit anderen IPs folgen, diese werden
# ignoriert, da hier schon zweiter vhost mit alter IP angelegt wird, sofern die IP geändert werden soll
elsif($change_this_vhost && ! $vhost_done){
#restliche Zeilen vom zu ändernden vhost nicht übernehmen
next if $discard_rest_of_old_vhost;
logline("debug","vhost=$vhost\tssl_vhost=$ssl_vhost\tvhost_ip=$vhost_ip\told_ssl_port=$old_ssl_port\tnewip=$newip");
logline("debug","vhost 80 match");
my $vhost_changed = qq~
<VirtualHost $newip:$port>
ServerAdmin $serveradmin
DocumentRoot $input{'droot'}
ServerName $servername
ServerAlias $serveralias
$logfiles
$cgi_bin
$cgi_local
$webmail
$mysql
$awstats
$input{'special'}
#POP:$input{'pop'}
#FOR:$input{'for'}
#AUT:$input{'aut'}
#QUOT:$input{'quota'}
#CUSTOM_TAG:$input{'custom_tag'}
#ADMIN_USERS:$input{'admin_users'}
</VirtualHost>
~;
# $vhost_changed =~ s/\n\n/\n/g;
# $vhost_changed =~ s/\n\n/\n/g;
# push @new_httpd_conf, $vhost_changed;
push @new_httpd_conf, split(/\n/,$vhost_changed);
# ok, nun haben wir den geänderten vhost, es kann aber sein, da sich die IP geändert hat
# in diesem Fall den gleichen vhost mit der alten IP hinter dem neuen vhost anlegen, damit es bei
# propagation nicht zu Ausfall kommt. Domains aus vhosts hören auf beide IPs
if($oldip ne $newip){
logline("debug","$oldip ne $newip");
my $vhost_oldip = qq~
<VirtualHost $oldip:$port>
ServerAdmin $serveradmin
DocumentRoot $input{'droot'}
ServerName $servername
ServerAlias $serveralias
$logfiles
$cgi_bin
$cgi_local
$webmail
$mysql
$awstats
$input{'special'}
#POP:$input{'pop'}
#FOR:$input{'for'}
#AUT:$input{'aut'}
#QUOT:$input{'quota'}
#CUSTOM_TAG:$input{'custom_tag'}
#ADMIN_USERS:$input{'admin_users'}
</VirtualHost>
~;
# $vhost_oldip =~ s/\n\n/\n/g;
# $vhost_oldip =~ s/\n\n/\n/g;
# push @new_httpd_conf, $vhost_oldip;
push @new_httpd_conf, split(/\n/,$vhost_oldip);
}
# die restlichen Zeilen des alten vhosts ignorieren
$discard_rest_of_old_vhost = '1';
# vhost mit alter IP fertig. für den Fall, da bereits vhost mit alter IP vorhanden wird dieser ignoriert, da ja hier bereits zwei vhosts
# mit beiden IP s angelegt wurden
$vhost_done = '1';
}
}
elsif($ssl_vhost){
push @tmp_vhost, $_;
$change_this_vhost = '1' if(/^ServerName\s+$vhost_to_change\b/);
#dieser vhost ist es nicht, also in @tmp_vhost gesammelte Zeilen unverändert übernehmen
if(/^\<\/VirtualHost/ && ! $change_this_vhost){
push @new_httpd_conf, @tmp_vhost;
$ssl_vhost = '';
@tmp_vhost = ();
}
elsif(/^\<\/VirtualHost/ && $change_this_vhost){
$change_this_vhost = '';
$ssl_vhost = '';
$discard_rest_of_old_vhost = '';
@tmp_vhost = ();
# ganz wichtig, sonst wird vhost doppelt geschrieben
next;
}
# oder match auf zu ändernden vhost
elsif($change_this_vhost){
#restliche Zeilen vom zu ändernden vhost nicht übernehmen
next if $discard_rest_of_old_vhost;
logline("debug","SSLvhost=$vhost\tssl_vhost=$ssl_vhost\tvhost_ip=$vhost_ip\told_ssl_port=$old_ssl_port\tnewip=$newip\tssl_port=$ssl_port");
logline("debug","SSLvhost match");
my $vhost_changed = qq~
<VirtualHost $newip:$ssl_port>
ServerAdmin $serveradmin
DocumentRoot $input{'ssl_droot'}
ServerName $servername
ServerAlias $serveralias
$logfiles
$cgi_bin
$cgi_local
$webmail
$mysql
$awstats
$input{'special_ssl'}
</VirtualHost>
~;
# $vhost_changed =~ s/\n\n/\n/g;
# $vhost_changed =~ s/\n\n/\n/g;
# push @new_httpd_conf, $vhost_changed;
push @new_httpd_conf, split(/\n/,$vhost_changed);
logline("debug","vhost_changed=$vhost_changed");
# ok, nun haben wir den geänderten SSL-vhost, es kann aber sein, da sich die IP geändert hat
# in diesem Fall den gleichen vhost mit der alten IP hinter dem neuen vhost anlegen, damit es bei
# propagation nicht zu Ausfall kommt. Domains aus vhosts hören auf beide IPs
# Nein, doch nicht...
# Wenn Kopie von vhost mit alter IP angelegt wird und es gibt anderen SSL-vhost mit der gleichen IP dann würde das falsche Zertifikat
# und der falsch vhost beim Aufruf der zweiten SSL-domain erfolgen. Also doch Propagation, aber nur beim SSL-Aufruf. Damit kann man aber leben
# die restlichen Zeilen des alten vhosts ignorieren
$discard_rest_of_old_vhost = '1';
}
}
else{
push @new_httpd_conf, $_;
}
}
@{$httpd_conf->file_content} = @new_httpd_conf;
my $got = $httpd_conf->write_file;
return(error($got)) if $got;
if($ssl && $input{'special_ssl'} =~ m/letsencrypt/){
if(defined($session) && defined($session->param('ssl_expiry_dates'))){
%ssl_expiry_dates = %{$session->param('ssl_expiry_dates')};
delete $ssl_expiry_dates{$vhost};
}
if(
$input{'ssl_droot'} ne $domains{$servername}{'ssl_droot'} ||
$input{'droot'} ne $domains{$servername}{'droot'} ||
$input{'vhost'} ne $domains{$servername}{'domain'} ||
$serveralias ne $domains{$servername}{'serveralias'}
){
logline("debug","ssl=$ssl\ninput_special_ssl=$input{'special_ssl'}\ninput_ssl_droot=$input{'ssl_droot'}\nvhost_ssl_droot=$domains{$servername}{'ssl_droot'}\ninput_droot=$input{'droot'}\nvhost_droot=$domains{$servername}{'droot'}\n");
logline("debug","input_vhost=#$input{'vhost'}#\ninput_serveralias=#$serveralias#\nvhost_vhost=#$domains{$servername}{'domain'}#\nvhost_serveralias=#$domains{$servername}{'serveralias'}#\n");
$success_text2 = 'L__Eine Veränderung des DocumentRoot, ServerName oder ServerAlias wirkt sich auf das hinterlegte Let\'s Encrypt Zertifikat aus. Sie sollten das Zertifikat neu erstellen, falls die Änderung nicht nur temporär ist.__L';
}
}
}
my $user_context = qq~<br /><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_forward&domain=$input{'vhost'}"><b>L__gehe zu "E-Mail-Weiterleitungen anlegen"__L</b></a><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_popuser&domain=$input{'vhost'}"><b>L__gehe zu "E-Mail-User anlegen"__L</b></a>~;
$template->param('result' => 'L__Der vhost wurde erfolgreich geändert!__L' . $user_context);
$success_text = 'L__Der vhost wurde erfolgreich geändert!__L';
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_vhosts&success_text=' . encode_base64url($success_text);
if($success_text2 ne ''){
$json_output{'redirect_to'} .= '&success_text2=' . encode_base64url($success_text2);
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub delete_popuser{
$input{'action'} = 'exec_delete_popuser';
exec_change_popuser();
}
sub exec_delete_popuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
logline("debug","exec_delete_popuser result:$result###");
if($result){
}
else{
# erstmal die zu löschenden user in array sammeln
my @deluser;
foreach(sort keys %input){
# <input type="checkbox" name="delete2" value="frank">
if(/^delete[0-9]{1,4}$/){
push @deluser, $input{$_};
}
}
foreach my $olduser(@deluser) {
my $easytecc_enable_file = '/usr/local/etc/easytecc/mailuser/' . $olduser;
`test -f $easytecc_enable_file && rm $easytecc_enable_file`;
if(-e "/home/$olduser/.spamd/user_prefs"){
my $tmperror = `/usr/sbin/delspam -n $olduser` unless $fb;
my $tmperror = `/usr/iports/bin/sudo /usr/sbin/delspam -n $olduser` if $fb;
return(html_error(({'non_specific' => 'L__Die Spameinstellungen konnten nicht gelöscht werden__L'}))) if $tmperror;
my $got = easytecc3::delete_from_spamconf($olduser);
return(html_error(({'non_specific' => 'L__Die Spameinstellungen konnten nicht gelöscht werden__L'}))) if $got;
}
if ($fb) {
logline("debug","Creating File Object \$virtmaps.");
my $virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %virtmaps = %{$virtmaps->file_parsed_hash()};
logline("debug","Creating File Object \$aliases.");
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
my %delete_from_aliases;
my @new_virtmaps = ();
my @new_aliases = ();
# erstmal die zu löschenden Weiterleitungen in hash sammeln
my %old_emailadress;
foreach(sort keys %input){
# <input type="checkbox" name="delete2" value="frank">
if(/^delete[0-9]{1,4}$/){
logline("debug","key input=$_");
$old_emailadress{$input{$_}} = '1';
}
}
my $emailadress_regex = join('|',keys %old_emailadress);
foreach($virtmaps->file_content) {
# Wenn Domain aber kein Autoresponder
# Domainmituser@ und direkt am Zeilenbeginn
if(/^($emailadress_regex)\s+(.*)$/){
# aha, match auf ein der zu löschenden E-Mailadressen, value aus %old_emailadress ist die Zeile aus Fornular, wo
# neue Daten eingetragen wurden. $1 aus regex entspricht gespeichertem value
my $forcount_to_delete = $1;
my $target_to_delete = $2;
logline("debug","regex match: forcount_to_delete = $1## - target_to_delete = $2##");
# entweder einzelne Weiterleitung in virtmaps oder mehrere Ziele, d.h. auch aliases Zeile löschen
if($target_to_delete =~ /(_aut|_spl)$/){
$delete_from_aliases{$target_to_delete} = $forcount;
}
}
else{
#alles was nicht matcht unverändert übernehmen
push @new_virtmaps, $_;
}
}
my $delete_from_aliases_regex = join('|',keys %delete_from_aliases);
if(keys %delete_from_aliases){
foreach($aliases->file_content) {
if(/^($delete_from_aliases_regex)\s*:/){
# nix, Zeile wird gelöscht
}
else{
push @new_aliases, $_;
}
}
@{$aliases->file_content} = @new_aliases;
my $got = $aliases->write_file;
if ($got) {
logline("error","aliases->write_file = ".$got);
return(error($got));
}
}
@{$virtmaps->file_content} = map(lc, @new_virtmaps);
my $got = $virtmaps->write_file;
if ($got) {
logline("error","virtmaps->write_file = ".$got);
return(error($got));
}
my $mailpasswd = easytecc3::get_mailpasswd();
my @new_mailpasswd = $mailpasswd->file_content;
#vorhandenen Eintrag entfernen
@new_mailpasswd = grep !/^$olduser:/, @new_mailpasswd;
@{$mailpasswd->file_content} = @new_mailpasswd;
$got = $mailpasswd->write_file;
logline("error","mailpasswd->write_file got = $got") if $got;
return(error($got)) if $got;
if (is_email($olduser)){
$got = `/usr/iports/bin/sudo /usr/sbin/rm.pl /home/$olduser d`;
logline("error","/usr/sbin/rm.pl /home/$olduser d got = $got") if $got;
return(error($got)) if $got;
}
}
else{
##bei E-Mailuser Alles an Daten wech hauen...
my $newerror = `/usr/sbin/deluser -m -r -n "$olduser"`;
if($newerror){
chomp($newerror);
$error .= "deluser2: $newerror<br />\n";
$newerror = "";
}
last if $error;
}
# .pass datei
`rm -f "/usr/local/etc/easytecc/$olduser.pass"`;
}
if (! $error){
my $user_context = qq~<br /><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_forward&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-Weiterleitungen anlegen"__L</b></a><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_popuser&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-User anlegen"__L</b></a>~;
$result = qq~L__E-Mail-User erfolgreich gelöscht!__L<br /><br />~ . $user_context;
$success_text = 'L__E-Mail-User erfolgreich gelöscht!__L';
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_email&success_text=' . encode_base64url($success_text);
}
else{
$result = qq~L__Achtung! Die Änderungen konnten nicht vollständig übernommen werden. Bitte beachten Sie folgende Warnhinweise__L:<br />$error~;
$json_output{'error'} = $result;
}
}
$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_change_popuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $anychange = '';
my $result = $validation_result;
logline("debug","exec_change_popuser result:$result###");
if($result){
}
else{
my %delete_popuser;
my @adduser;
my @deluser;
my @editquota;
my @editpass;
my %domains;
#zuerst gucken, ob popuser gelöscht werden sollen
foreach(sort keys %input){
# <input type="checkbox" name="delete2" value="frank">
if(/^delete[0-9]{1,4}$/){
$delete_popuser{$_} = $input{$_};
}
}
my %sendmail_cw_domains;
if(keys %delete_popuser >= 1 && !$session->param('is_mailuser')){
logline("debug",'change_popuser delete');
$template = HTML::Template->new(filename => 'delete_multi_popuser.html');
my $hidden_fields_delete_popuser = '';
my $delete_popuser = '';
foreach(sort keys %delete_popuser){
$hidden_fields_delete_popuser .= qq~<input type="hidden" name="$_" value="$delete_popuser{$_}">~;
$delete_popuser .= $delete_popuser{$_} . '<br />';
logline("debug","delete: " . $delete_popuser{$_});
}
$template->param('domain' => $input{'domain'});
$template->param('hidden_fields_delete_popuser' => $hidden_fields_delete_popuser);
$template->param('delete_popuser' => $delete_popuser);
$template->param('delete_popuser_idn' => encode('utf-8', email_to_unicode($delete_popuser)));
}
# keine popuser explizit zum löschen, nur Änderung von Name, Passwort oder Quota
# Änderung von Name beinhaltet natürlich auch löschen und Neuanlage von User
else{
logline("debug",'change_popuser change');
# erstmal Daten sammeln:
# <tr><td><INPUT TYPE="HIDDEN" NAME="old_user2" VALUE="frank">
# <input type="checkbox" name="delete2" value="frank">
# <INPUT NAME="user2" TYPE="TEXT" id="user2" VALUE="frank" SIZE="20"></td>
# <td><INPUT NAME="pass2" TYPE="TEXT" id="pass2" VALUE="gugl" SIZE="20"></td>
# <td><INPUT NAME="quota2" TYPE="TEXT" id="quota2" VALUE="1000" SIZE="6"> MB</td>
# darf nicht mehr als vhost-Quota sein
my $vhost_quota_sum = '';
my $popused = '';
foreach(keys %input){
next unless /^old_user(.*)$/;
$popused++;
}
#if ($fb) {
#$domains{$input{'domain'}}{'pop'} = $domains{$input{'domain'}}{'for'};
#logline("debug",qq~fb pop=for=$domains{$input{'domain'}}{'for'}~);
#}
# mailuser hack
if($session && $session->param('is_mailuser')){
logline("debug","is_mailuser=1, setting template=mailuser_interface");
$template = ${mailuser_interface()};
$action = $input{'action'} = 'mailuser_interface';
$input{'active_tab'} = '_password';
if(length($input{"pass1"})){
push(@editpass,1);
$anychange = 1;
}
} else {
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
%domains = %{$httpd_conf->file_parsed_hash()};
my $servername = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
chomp $servername;
#$input{'domain'} ne 'www.administrator' damit admin auf externem Mailserver geändert werden kann
if($popused > $domains{$input{'domain'}}{'pop'} && $input{'domain'} ne 'www.administrator' && $input{'domain'} ne $servername){
logline("debug","popused = $popused, domain = $input{'domain'}, popmax = $domains{$input{'domain'}}{'pop'}");
return(html_error(({'non_specific' => 'L__Der vHost enthält mehr E-Mail-User als der vHost erlaubt. Bitte editieren Sie den vHost und erhöhen die Anzahl der E-Mail-Accounts um Änderungen vornehmen zu können__L'})));
}
#Damit admin auf externem Mailserver geändert werden kann, admin ist keiner domain zugeordnet
$domains{$input{'domain'}}{'pop'} = '1' if ($input{'domain'} eq 'www.administrator' || $input{'domain'} eq $servername);
my $domain = $input{'domain'};
$domain =~ s/^www\.//;
foreach my $count (0..$domains{$input{'domain'}}{'pop'}){
$input{"user$count"} = email_to_ascii($input{"user$count"});
my $easytecc_enable_file;
if($input{"easytecc$count"} && length($input{"user$count"})){
$easytecc_enable_file = '/usr/local/etc/easytecc/mailuser/' . $input{"user$count"};
`test -f $easytecc_enable_file || touch $easytecc_enable_file`;
$anychange = 1;
} elsif(length($input{"old_user$count"})) {
$easytecc_enable_file = '/usr/local/etc/easytecc/mailuser/' . $input{"old_user$count"};
`test -f $easytecc_enable_file && rm $easytecc_enable_file`;
$anychange = 1;
}
if(!$input{"2fa$count"}){
my $two_fa_enable_file = '/usr/local/etc/easytecc/2fa/' . $input{"old_user$count"};
`test -f $two_fa_enable_file && rm $two_fa_enable_file`;
$anychange = 1;
}
if($input{"old_user$count"} ne $input{"user$count"} ||
$input{"old_pass$count"} ne $input{"pass$count"} ||
$input{"old_quota$count"} ne $input{"quota$count"}){
logline("debug","###exec_change_popuser###" . $input{"old_pass$count"} . "##" . $input{"pass$count"} . "##");
# AHA :) also was geändert.....
# nur was?!?!?!? ;)
if($input{"old_user$count"} eq ""){
logline("debug",qq~popuser anlegen: $input{"user$count"}~);
#gabs nich - also neu
push(@adduser,$count);
$anychange = 1;
}
elsif($input{"user$count"} eq ""){
logline("debug",qq~popuser löschen: $input{"user$count"}~);
#gabs vorher - jetzt weg
push(@deluser,$count);
$anychange = 1;
# Quota eines zu löschenden Users aus der für E-Mailuser vergebenen Quota herausrechnen
$vhost_quota_sum -= $input{"quota$count"}
}
elsif($input{"user$count"} eq $input{"old_user$count"} &&
$input{"old_pass$count"} eq $input{"pass$count"} &&
$input{"old_quota$count"} ne $input{"quota$count"}){
logline("debug",qq~popuser quota ändern: $input{"user$count"}~);
#user gabs vorher - immernoch GLEICH
#quota geändert
push(@editquota,$count);
$anychange = 1;
}
elsif($input{"user$count"} eq $input{"old_user$count"} &&
$input{"old_pass$count"} ne $input{"pass$count"} &&
$input{"old_quota$count"} eq $input{"quota$count"}){
logline("debug",qq~popuser pass ändern: $input{"user$count"}~);
#user gabs vorher - immernoch GLEICH
#pass geändert
push(@editpass,$count);
$anychange = 1;
}
elsif($input{"user$count"} eq $input{"old_user$count"} &&
$input{"old_pass$count"} ne $input{"pass$count"} &&
$input{"old_quota$count"} ne $input{"quota$count"}){
logline("debug",qq~popuser pass und quota ändern: $input{"user$count"}~);
#user gabs vorher - immernoch GLEICH
#pass UND quota geändert
push(@editpass,$count);
push(@editquota,$count);
$anychange = 1;
}
elsif($input{"user$count"} ne $input{"old_user$count"}){
logline("debug",qq~popuser löschen und anlegen: $input{"old_user$count"} $input{"user$count"}~);
# user gabs vorher - ABER geändert (also einen gelöscht neuen in gleiche id
# pass UND/ODER quota muss uns egal sein - alles andere klappt wg. web rechten nicht - also nehmen wir neuen user an
push(@deluser,$count); ##mit altem user
push(@adduser,$count); ##mit neuem user
$anychange = 1;
}
}
$vhost_quota_sum += $input{"quota$count"};
}
if($input{'ftpquota'} ne $input{'old_ftpquota'}){
$anychange = 1;
}
if($input{'ftpquota'}){
$vhost_quota_sum += $input{'ftpquota'};
}
if($domains{$input{'domain'}}{'quota'} < $vhost_quota_sum && $input{'domain'} ne 'www.administrator' && $input{'domain'} ne $servername){
my $max_pop_quota = $domains{$input{'domain'}}{'quota'} - $input{'ftpquota'};
#return(html_error(({'quota' => 'L__Die vergebene Quota darf die Gesamtquota des vHosts nicht übersteigen__L'})));
$error_fields{"non_specific"} .= "L__Die vergebene Quota darf die Gesamtquota des vHosts nicht übersteigen__L L__Für E-Mail-Benutzer stehen zur Verfügung:__L $max_pop_quota MB";
}
}
# user zählen und wenn doppelt dann Fehlermeldung
my %popusers;
my $domainpart = '';
# Validierung der Formularfelder, bei Fehler wieder change_popuser anzeigen und css klasse setzen, damit Felder markiert sind
# In hash error_fields wird feldname und Fehlermeldung gesetzt, dadurch wei html_error welches Feld markiert werden muß.
if($anychange){
logline("debug","exec_change_popuser validation");
# die arrays
# @adduser = $input{"user$count"}
# @editquota = $input{"quota$count"}
# @editpass = $input{"pass$count"}
# enthalten die Änderungen, wenn z.B. in @adduser eine "2" steht, dann muss $input{"user2"} überprft werden.
foreach my $count(@adduser){
undef $domain_part;
# hash of arrays um Usernamen dem Formularfeld user$count zuordnen zu können und fehlerhaftes Feld CSS-Klasse setzen zu können
# In anonymen array landen nummern von $count. Wenn mehr als eine, dann wurde Username doppelt angegeben.
push @{$popusers{$input{"user$count"}}}, $count;
$domain_part = $input{"user$count"};
$domain_part =~ s/^.*@//;
$domain_part = ascii_domain($domain_part);
logline("debug","domainpart=$domain_part");
my %password_chars;
my @password_chars = split //, $input{"pass$count"};
foreach(@password_chars){
$password_chars{$_} = '1';
}
logline("debug","user = $count; "."pass = " . $input{"pass$count"});
if(easytecc3::mailuser_exists($input{"user$count"})){
$error_fields{"user$count"} = "L__Der Benutzer existiert bereits__L";
}
if($input{"user$count"} =~ /^(mail|kontakt|support|info|webmaster|administrator|office|admin|httpd)$/){
$error_fields{"user$count"} = "L__Dieser Name kann nicht als E-Mail-User verwendet werden. Bitte wählen Sie einen anderen Namen.__L";
}
if(! $input{"user$count"}){
$error_fields{"user$count"} = "L__Bitte geben Sie einen Benutzernamen an__L";
}
if($input{"user$count"} =~ /[^a-zA-Z0-9\-\_]/ && ! $fb){
$error_fields{"user$count"} = "L__Der Benutzername enthält ungültige Zeichen__L";
}
if(is_domain($domain_part) && ! is_email(email_to_ascii($input{"user$count"})) && $fb){
$error_fields{"user$count"} = "L__Die E-Mail-Adresse hat ein falsches Format__L";
}
elsif(! is_domain($domain_part) && $fb){
$error_fields{"user$count"} = "$domain_part: L__Ungültiger Domainname__L";
logline("debug","domainpart=$domain_part Ungültiger Domainname");
}
elsif( (! grep $_ eq $domain_part, @{$domains{$input{'domain'}}{'domains'}}) && $fb){
$error_fields{"user$count"} = "$domain_part L__gehört nicht zur Domain__L $input{'domain'}";
logline("debug","domainpart=$domain_part falsche Domain");
}
if(length $input{"user$count"} < 2){
$error_fields{"user$count"} = "L__Der Benutzername ist zu kurz__L";
}
if(length $input{"user$count"} > 16 && ! $fb){
$error_fields{"user$count"} = "L__Der Benutzername ist zu lang. Bitte geben Sie höchstens 16 Zeichen an.__L";
}
if(length $input{"user$count"} > 250 && $fb){
$error_fields{"user$count"} = "L__Der Benutzername ist zu lang. Bitte geben Sie höchstens 250 Zeichen an.__L";
}
if(! $input{"quota$count"}){
$error_fields{"quota$count"} = "L__Bitte geben Sie eine Speicherbegrenzung an__L";
}
if($input{"quota$count"} =~ /\D/){
logline("warning","quota ungültig");
$error_fields{"quota$count"} = "L__Die Mengenangabe für die Speicherbegrenzung darf nur aus Zahlen bestehen__L";
}
if(! $input{"pass$count"}){
$error_fields{"pass$count"} = "L__Bitte geben Sie ein Passwort an__L";
}
elsif($input{"pass$count"} =~ /^[0-9]{1,}$/){
$error_fields{"pass$count"} = "L__Das Passwort darf nicht ausschliesslich aus Zahlen bestehen__L";
}
elsif($input{"pass$count"} =~ /[äöüÄÖÜß]/){
$error_fields{"pass$count"} = "L__Das Passwort enthält ungültige Zeichen__L";
}
elsif($input{"pass$count"} !~ /[A-Za-z0-9\%\+\*\~\-\_\@\#\$\&\=\?\!]/){
$error_fields{"pass$count"} = "L__Das Passwort enthält ungültige Zeichen__L";
}
elsif($input{"user$count"} eq $input{"pass$count"}){
$error_fields{"pass$count"} = ('L__Das Passwort darf nicht gleich dem Benutzernamen sein__L');
}
elsif(length($input{"pass$count"}) < 10){
$error_fields{"pass$count"} = ('L__Das Passwort ist zu kurz__L');
}
elsif(keys(%password_chars) < 2){
logline("debug","change popuser chars:" . $input{"pass$count"} . '=' . keys(%password_chars));
$error_fields{"pass$count"} = ('L__Das Passwort muss mindestens zwei verschiedene Zeichen enthalten__L');
} else {
$sendmail_cw_domains{$domain_part} = 1;
}
}
foreach(@editquota){
logline("debug",qq~quota=$_ $input{"quota$_"}~);
if(! $input{"quota$_"}){
$error_fields{"quota$_"} = "L__Bitte geben Sie eine Speicherbegrenzung an__L";
}
elsif($input{"quota$_"} =~ /\D/){
logline("warning","quota ungültig");
$error_fields{"quota$_"} = "L__Die Mengenangabe für die Speicherbegrenzung darf nur aus Zahlen bestehen__L";
} else {
undef $domain_part;
$domain_part = $input{"user$_"};
$domain_part =~ s/^.*@//;
$domain_part = ascii_domain($domain_part);
$sendmail_cw_domains{$domain_part} = 1;
}
}
foreach(@editpass){
my %password_chars;
my @password_chars = split //, $input{"pass$_"};
foreach(@password_chars){
logline("debug","char=$_ ord=" . ord($_));
$password_chars{$_} = '1';
}
logline("debug",$input{"pass$_"}." = editpass = $_\nchars = ".keys(%password_chars));
if(! $input{"pass$_"}){
$error_fields{"pass$_"} = "L__Bitte geben Sie ein Passwort an__L";
}
elsif($input{"pass$_"} =~ /^[0-9]{1,}$/){
$error_fields{"pass$_"} = "L__Das Passwort darf nicht ausschliesslich aus Zahlen bestehen__L";
}
elsif($input{"pass$_"} =~ /[äöüÄÖÜß]/){
$error_fields{"pass$_"} = "L__Das Passwort enthält ungültige Zeichen__L";
}
elsif($input{"pass$_"} !~ /[A-Za-z0-9\%\+\*\~\-\_\@\#\$\&\=\?\!]/){
$error_fields{"pass$_"} = "L__Das Passwort enthält ungültige Zeichen__L";
}
elsif($input{"user$_"} eq $input{"pass$_"}){
$error_fields{"pass$_"} = ('L__Das Passwort darf nicht gleich dem Benutzernamen sein__L');
}
elsif(length($input{"pass$_"}) < 10){
$error_fields{"pass$_"} = ('L__Das Passwort ist zu kurz__L');
}
elsif(keys(%password_chars) < 2){
$error_fields{"pass$_"} = ('L__Das Passwort muss mindestens zwei verschiedene Zeichen enthalten__L');
}
elsif(exists ($input{"rep_pass$_"}) && !length($input{"rep_pass$_"})){
$error_fields{"rep_pass$_"} = "L__Bitte wiederholen Sie das Passwort__L";
}
elsif(exists ($input{"rep_pass$_"}) && $input{"rep_pass$_"} ne $input{"pass$_"}){
$error_fields{"rep_pass$_"} = "L__Die Passwörter stimmen nicht überein__L";
}
else {
undef $domain_part;
$domain_part = $input{"user$_"};
$domain_part =~ s/^.*@//;
$domain_part = ascii_domain($domain_part);
$sendmail_cw_domains{$domain_part} = 1;
}
}
# doppelte Usernamen?
foreach(sort keys %popusers){
# $popusers{$_} enthält anonymes array von user$count. Wenn mehr als einer, dann wurde user doppelt angegeben.
# Mit Hilfe von user$count CSS-Klasse setzen
if(scalar @{$popusers{$_}} > 1){
foreach(@{$popusers{$_}}){
$error_fields{"user$_"} = $input{"user$_"} . ": L__Der Benutzername wurde doppelt angegeben__L";
}
}
}
}
if(keys(%error_fields)){
return(html_error(\%error_fields))
}
my $newerror = '';
#um Code übersichtlicher zu halten kann mailpasswd ggf. mehrmals geschrieben werden,
#macht in der Praxis aber nur ein paar Millisekunden aus
my $virtmaps = '';
my $aliases = '';
my $mailpasswd = '';
my @new_mailpasswd;
my @new_virtmaps;
my @new_aliases;
if($anychange){
#In easytecc4 können bei change_popuser keine Emailuser mehr gelöscht werden, indem der Name des Users geändert wird.
#easytecc3:
#-Kd ändert Namen von Benutzer
#-exec_change_popuser löscht alten User und legt neuen an. Dadurch werden auch alle Emails des alten Users gelöscht
#und einige Kunden dachten diese werden mit übernommen.
#
#easytecc4:
#-zu löschende User werden mit checkbox marktiert und es gibt separaten Löschungsdialog
#dadurch entstehen keine Missverständnisse
#das Feld des Emailbenutzers ist auch readonly und kann nicht geändert werden
#
#den Code lassen wir erstmal drin und setzen @deluser zurück, vielleicht kann man es für andere Zwecke nochmal gebrauchen
undef @deluser;
## @deluser - single - Wird nicht mehr verwendet
foreach my $count (@deluser) {
# old_ Namen holen von id
my $olduser = $input{"old_user$count"};
if(-e "/home/$olduser/.spamd/user_prefs"){
my $tmperror = system("/usr/sbin/delspam","-n","$olduser");
return(html_error(({'L__Die Spameinstellungen konnten nicht gelöscht werden__L' => "$tmperror"}))) if $tmperror;
my $got = easytecc3::delete_from_spamconf($olduser);
return(html_error(({'L__Die Spameinstellungen konnten nicht gelöscht werden__L' => "$got"}))) if $got;
}
##bei E-Mailuser Alles an Daten wech hauen...
$newerror = `/usr/sbin/deluser -m -r -n "$olduser"` unless $error;
if($newerror){
chomp($newerror);
$error .= "deluser2: $newerror<br />\n";
$newerror = "";
}
last if $error;
}
## @adduser - single
my $domain = $input{'domain'};
$domain =~ s/^www\.//;
unless($error){
if ($fb && scalar @adduser > 0) {
logline("debug","Creating File Object \$mailpasswd.");
$mailpasswd = easytecc3::get_mailpasswd();
@new_mailpasswd = $mailpasswd->file_content;
logline("debug","Creating File Object \$virtmaps.");
$virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %virtmaps = %{$virtmaps->file_parsed_hash()};
@new_virtmaps = $virtmaps->file_content;
logline("debug","Creating File Object \$aliases.");
$aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
@new_aliases = $aliases->file_content;
}
##Neue Daten anhängen
foreach my $count (@adduser) {
##user prüfen und schreiben
#auf altem System wird nur ein Systemuser angelegt, sonst nix
if($input{"user$count"} && ! $fb) {
logline("debug",qq~vor adduser pop3: $input{"user$count"}~);
# usernamen immer klein
$input{"user$count"} = lc($input{"user$count"});
##Nur Mail da kein -f(tp) Schalter
$newerror = `/usr/sbin/adduser -h '/home/$input{"user$count"}' -d '$domain - POP' -q $input{"quota$count"}M -p '$input{"pass$count"}' -n '$input{"user$count"}'`;
$error .= qq~adduser $input{"user$count"},$input{"quota$count"}M: $newerror<br />\n~ if $newerror;
logline("debug",qq~nach adduser pop3: $newerror /usr/sbin/adduser -h /home/$input{"user$count"} -d '$domain - POP' -q $input{"quota$count"}M -p $input{"pass$count"} -n $input{"user$count"}~);
easytecc3::encrypt("/usr/local/etc/easytecc/" . $input{"user$count"} . ".pass", $input{"pass$count"});
}
elsif($input{"user$count"} && $fb) {
#auf freebsd dmr ist Emailuser=Emailadresse und es wird User in /etc/mail/mailuser
#und auch auch eine Weiterleitung angelegt.
#virtmaps: blubb@example.com blubb_example.com_spl
#aliases: blubb_example.com_spl: "|/usr/iports/bin/procmail -a blubb@example.com"
my $email_address = email_to_ascii($input{"user$count"});
my $virtmaps_rhs = $email_address . '_spl';
$virtmaps_rhs =~ s/@/_/;
my $aliases_lhs = $virtmaps_rhs;
my $aliases_rhs = qq~"|/usr/iports/bin/procmail -a $email_address"~;
push @new_virtmaps, qq~$email_address\t\t$virtmaps_rhs~;
push @new_aliases, qq~$aliases_lhs:\t$aliases_rhs~;
my $password = $input{"pass$count"};
$password = encode('iso-8859-1', "$password");
$password = `/usr/iports/bin/sudo /usr/sbin/doveadm pw -s SHA512-CRYPT -p '$password' | sed s/\{SHA512-CRYPT\}//`;
chomp $password;
#TODO: get real 'virtmail' UID from passwd
push @new_mailpasswd, qq~$email_address:$password:1008:1005:$domain - POP:/home/~ . $email_address . '::userdb_quota_rule=*:storage=' . $input{"quota$count"} . 'M';
my $got = `/usr/iports/bin/sudo /usr/sbin/webmkmhome -u $email_address` if ($email_address && ! -d "/home/$email_address");
logline("debug","webmkmhome got = $got\nemail_address = $email_address");
logline("error","webmkmhome got = $got") if $got;
return(error($got)) if $got;
easytecc3::encrypt("/usr/local/etc/easytecc/$email_address.pass", $input{"pass$count"});
}
last if $error;
}
if ($fb && scalar @adduser > 0) {
@{$virtmaps->file_content} = map(lc, @new_virtmaps);
my $got = $virtmaps->write_file;
logline("error","virtmaps->write_file got = $got") if $got;
undef @new_virtmaps;
return(error($got)) if $got;
@{$aliases->file_content} = map(lc, @new_aliases);
$got = $aliases->write_file;
logline("error","aliases->write_file got = $got") if $got;
undef @new_aliases;
return(error($got)) if $got;
@{$mailpasswd->file_content} = @new_mailpasswd;
$got = $mailpasswd->write_file;
logline("error","mailpasswd->write_file got = $got") if $got;
undef @new_mailpasswd;
return(error($got)) if $got;
}
}
## @editpass - multi
unless($error){
if ($fb && scalar @editpass > 0) {
logline("debug","Creating File Object \$mailpasswd.");
$mailpasswd = easytecc3::get_mailpasswd();
@new_mailpasswd = $mailpasswd->file_content;
}
foreach my $count (@editpass) {
##user prüfen und pass ändern
if($input{"user$count"} && ! $fb) {
$newerror = `/usr/sbin/chps -p '$input{"pass$count"}' -n '$input{"user$count"}' -m`;
$error .= qq~<B>$input{"user$count"}</B>: $newerror<br />~ if $newerror;
easytecc3::encrypt("/usr/local/etc/easytecc/" . $input{"user$count"} . ".pass", $input{"pass$count"});
}
elsif($input{"user$count"} && $fb) {
my $password = $input{"pass$count"};
logline("debug","doveadm password1=$password");
$password = encode('iso-8859-1', "$password");
logline("debug","doveadm password2=$password");
$password = `/usr/iports/bin/sudo /usr/sbin/doveadm pw -s SHA512-CRYPT -p '$password' | sed s/\{SHA512-CRYPT\}//`;
chomp $password;
my $emailadress = $input{"user$count"};
@new_mailpasswd = grep !/^$emailadress:/, @new_mailpasswd;
#TODO: get real 'virtmail' UID from passwd
push @new_mailpasswd, qq~$emailadress:$password:1008:1005:$domain - POP:/home/~ . $emailadress . '::userdb_quota_rule=*:storage=' . $input{"quota$count"} . 'M';
easytecc3::encrypt("/usr/local/etc/easytecc/$emailadress.pass", $input{"pass$count"});
}
last if $error;
}
if ($fb && scalar @editpass > 0) {
@{$mailpasswd->file_content} = @new_mailpasswd;
$got = $mailpasswd->write_file;
logline("error","mailpasswd->write_file got = $got") if $got;
undef @new_mailpasswd;
return(error($got)) if $got;
}
}
# @editquota - multi
unless($error){
if ($fb && scalar @editquota > 0) {
logline("debug","Creating File Object \$mailpasswd.");
$mailpasswd = easytecc3::get_mailpasswd();
@new_mailpasswd = $mailpasswd->file_content;
}
foreach my $count (@editquota) {
# User prüfen und quota ändern, gibs auf freebsd nicht wegen virtuell
if($input{"user$count"} && ! $fb) {
$newerror = `/usr/sbin/quotuser -q $input{"quota$count"}M -n $input{"user$count"} -m 2>&1`;
logline("debug",qq~editquota:/usr/sbin/quotuser -q $input{"quota$count"}M -n $input{"user$count"}~);
$error .= qq~<B>$input{"user$count"}</B>: $newerror<br />~ if $newerror;
}
elsif($input{"user$count"} && $fb) {
my $emailadress = $input{"user$count"};
logline("debug","changing quota for $emailadress");
my $password = $input{"pass$count"};
# resuse existing pwd
if(!length($password) || $password eq $input{"old_pass$count"}){
($password) = grep /^$emailadress:/, @new_mailpasswd;
$password =~ s/^[^:]+://;
$password =~ s/:.*$//;
logline("debug","editquota reusing pwdhash $password");
} else {
$password = encode('iso-8859-1', "$password");
$password = `/usr/iports/bin/sudo /usr/sbin/doveadm pw -s SHA512-CRYPT -p '$password' | sed s/\{SHA512-CRYPT\}//`;
}
chomp $password;
@new_mailpasswd = grep !/^$emailadress:/, @new_mailpasswd;
#TODO: get real 'virtmail' UID from passwd
if($input{'domain'} ne $servername){
push @new_mailpasswd, qq~$emailadress:$password:1008:1005:$domain - POP:/home/~ . $emailadress . '::userdb_quota_rule=*:storage=' . $input{"quota$count"} . 'M';
} else {
push @new_mailpasswd, qq~$emailadress:$password:1008:1005::/home/~ . $emailadress . '::userdb_quota_rule=*:storage=' . $input{"quota$count"} . 'M';
}
}
last if $error;
}
if ($fb && scalar @editquota > 0) {
@{$mailpasswd->file_content} = @new_mailpasswd;
$got = $mailpasswd->write_file;
logline("error","mailpasswd->write_file got = $got") if $got;
undef @new_mailpasswd;
return(error($got)) if $got;
}
}
unless($error){
# ftp quota neu setzen, nicht freebsd
if($input{'old_ftpquota'} != $input{'ftpquota'}){
logline("debug",qq~vor ftpquota ändern: $input{"ftpuser"}~);
# M hinter $input{'quotaftp'}steht für MB
$newerror = `/usr/sbin/quotuser -q $input{'ftpquota'}M -n '$input{'ftpuser'}' 2>&1`;
$error .= qq~<B>$input{'ftpuser'}</B>: ".$newerror."<br />~ if $newerror;
logline("debug",qq~nach ftpquota ändern: /usr/sbin/quotuser -q $input{'ftpquota'}M -n $input{'ftpuser'}~);
}
}
}
}
logline("debug","error = $error");
logline("debug","anychange = $anychange");
#wenn checkboxen für zu löschende User ausgewählt anderes Template anzeigen und kein redirect,
#ist ganz am Anfang dieser Funktion.
if (! $error && keys(%delete_popuser) == 0 && $anychange){
my $user_context = qq~<br /><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_forward&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-Weiterleitungen anlegen"__L</b></a><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_popuser&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-User anlegen"__L</b></a>~;
#<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
$result = qq~L__Die Änderung wurde erfolgreich durchgeführt__L!<br /><br />~ . $user_context;
$success_text = 'L__Die Änderung wurde erfolgreich durchgeführt__L!';
my $domainlist = '';
my $sendmail_cw = file->new({file_name => '/etc/mail/sendmail.cw'});
$sendmail_cw->read_file;
my %domains = %{$sendmail_cw->file_parsed_hash()};
if($fb && keys %sendmail_cw_domains){
my $domain;
foreach $domain (keys %sendmail_cw_domains){
if(!exists $domains{$domain}){
if($domainlist ne ''){
$domainlist .= ', ';
}
$domainlist .= $domain;
}
}
} else {
my $domainlist = $input{'domain'};
$domainlist =~ s/^www\.//;
}
if($domainlist ne ''){
$success_text .= '<br><br><span style="color: #a94442;">Die Domain';
if($domainlist =~ m/,/){
$success_text .= "s $domainlist sind";
} else {
$success_text .= " $domainlist ist";
}
$success_text .= ' noch nicht als Mailserver-Domain eingetragen und für den Mailempfang nicht aktiv!</span>';
}
#$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_email&success_text=' . encode_base64url($success_text);
$json_output{'redirect_to'} = '&success_text=' . encode_base64url($success_text);
}
elsif($error){
$result = qq~L__Achtung! Die Änderungen konnten nicht vollständig übernommen werden. Bitte beachten Sie folgende Warnhinweise__L:<br />$error~;
$json_output{'error'} = $result;
}
}
$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_delete_forward{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
logline("debug","exec_delete_forward result = $result###");
if($result){
logline("error","exec_delete_forward result = $result###");
$result .= 'error';
}
else{
logline("debug","Creating File Object \$virtmaps.");
my $virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %virtmaps = %{$virtmaps->file_parsed_hash()};
logline("debug","Creating File Object \$aliases.");
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
my %delete_from_aliases;
my @new_virtmaps = ();
my @new_aliases = ();
# erstmal die zu löschenden Weiterleitungen in hash sammeln
my %old_emailadress;
foreach(sort keys %input){
# <input type="checkbox" name="delete2" value="frank">
if(/^delete[0-9]{1,4}$/){
logline("debug","key input=$_");
$old_emailadress{$input{$_}} = '1';
}
}
my $emailadress_regex = join('|',keys %old_emailadress);
foreach($virtmaps->file_content) {
# Wenn Domain aber kein Autoresponder
# Domainmituser@ und direkt am Zeilenbeginn
if(/^($emailadress_regex)\s+(.*)$/){
# aha, match auf ein der zu löschenden E-Mailadressen, value aus %old_emailadress ist die Zeile aus Fornular, wo
# neue Daten eingetragen wurden. $1 aus regex entspricht gespeichertem value
my $forcount_to_delete = $1;
my $target_to_delete = $2;
logline("debug","regex match: forcount_to_delete = $1## - target_to_delete = $2##");
# entweder einzelne Weiterleitung in virtmaps oder mehrere Ziele, d.h. auch aliases Zeile löschen
if($target_to_delete =~ /(_aut|_spl)$/){
$delete_from_aliases{$target_to_delete} = $forcount;
}
}
else{
#alles was nicht matcht unverändert übernehmen
push @new_virtmaps, $_;
}
}
my $delete_from_aliases_regex = join('|',keys %delete_from_aliases);
if(keys %delete_from_aliases){
foreach($aliases->file_content) {
if(/^($delete_from_aliases_regex)\s*:/){
# nix, Zeile wird gelöscht
}
else{
push @new_aliases, $_;
}
}
@{$aliases->file_content} = @new_aliases;
my $got = $aliases->write_file;
if ($got) {
logline("error","aliases->write_file = ".$got);
return(error($got));
}
}
@{$virtmaps->file_content} = map(lc, @new_virtmaps);
my $got = $virtmaps->write_file;
if ($got) {
logline("error","virtmaps->write_file = ".$got);
return(error($got));
}
}
my $user_context = '';
if ($fb) {
$user_context = qq~<br /><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_forward&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-Adressen anlegen"__L</b></a><br />~;
$template->param('result' => 'L__Die E-Mail-Adressen wurden erfolgreich geändert__L' . $user_context);
$success_text = 'L__Die E-Mail-Adressen wurden erfolgreich geändert__L';
if ($input{'email_type'} eq 'single_edit') {
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_single_edit_email&domain=' . $input{'domain'} . '&success_text=' . encode_base64url($success_text);
}
else{
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_email&success_text=' . encode_base64url($success_text);
}
}
else{
$user_context = qq~<br /><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_forward&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-Weiterleitungen anlegen"__L</b></a><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_popuser&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-User anlegen"__L</b></a>~;
$template->param('result' => 'L__Die Weiterleitungen wurden erfolgreich geändert__L' . $user_context);
$success_text = 'L__Die Weiterleitungen wurden erfolgreich geändert__L';
if ($input{'email_type'} eq 'single_edit') {
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_single_edit_email&domain=' . $input{'domain'} . '&success_text=' . encode_base64url($success_text);
}
else{
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_email&success_text=' . encode_base64url($success_text);
}
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_new_forward_single_edit{
exec_change_forward();
}
sub exec_change_forward_single_edit{
exec_change_forward();
}
sub exec_change_forward{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
my %delete_forward;
my %sendmail_cw_domains;
logline("debug","exec_change_forward result:$result###");
if($result){
}
else{
#zuerst gucken, ob Weiterleitungen gelöscht werden sollen
foreach(sort keys %input){
# <input type="checkbox" name="delete2" value="frank">
if(/^delete[0-9]{1,4}$/){
$delete_forward{$_} = $input{$_};
}
}
if(keys %delete_forward >= 1){
$template = HTML::Template->new(filename => 'delete_multi_forward.html');
my $hidden_fields_delete_forward = '';
my $delete_forward = '';
foreach(sort keys %delete_forward){
$hidden_fields_delete_forward .= qq~<input type="hidden" name="$_" value="$delete_forward{$_}">~;
$delete_forward .= $delete_forward{$_} . '<br />';
logline("debug","exec_change_forward delete_forward=$_");
}
$template->param('domain' => $input{'domain'});
$template->param('hidden_fields_delete_forward' => $hidden_fields_delete_forward);
$template->param('delete_forward' => $delete_forward);
$template->param('email_type' => $input{'email_type'});
}
else{
my $forcount = '1';
my @forcount_change=();
# wenn bei Weiterleitung Änderung an aliases notwendig, dann ist $aliases_forcount{$forcount} gesetzt und enthlt Array mit Zielen
my %aliases_forcount;
# Hash um zu berprüfen, ob E-Mailadressen doppelt angegeben wurden
my %emailadress;
# wird bentigt, um in vorhandener virtmaps die zu ändernde E-Mailadresse zu finden
my %old_emailadress;
my $domain = $input{'domain'};
$domain =~ s/^www\.//;
my %freefields;
my %user_select;
my %handle_hash = %{easytecc3::return_file_handler_store()};
# httpd_conf wurde schon von Validator geöffnet, also nicht nochmal öffnen, sondern vorhandene Datenstruktur nehmen
my $httpd_conf = $handle_hash{'/etc/httpd/conf/httpd.conf'};
my %domains = %{$httpd_conf->file_parsed_hash()};
logline("debug","Creating File Object \$virtmaps.");
my $virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %virtmaps = %{$virtmaps->file_parsed_hash()};
logline("debug","Creating File Object \$aliases.");
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
$mailpasswd = easytecc3::get_mailpasswd();
%passwd = %{$mailpasswd->file_parsed_hash()};
my $splitted_domains = join '|', @{$domains{$input{'domain'}}{'domains'}};
$splitted_domains =~ s/\*/\\*/g;
logline("debug","splitted_domains=$splitted_domains");
#my %error_fields = ();
# es gibt pro Weiterleitung acht Felder, 4 für die vorhandenen und 4 für die neuen Eintrge:
# old_user1
# old_domain_select1
# old_user_select1
# old_freefield1
# user1
# domain_select1
# user_select1
# freefield1
#
# user1 + domain_select1 = E-Mailadresse
while($domains{$input{'domain'}}{'for'} >= $forcount){
$input{"domain_select$forcount"} = ascii_domain($input{"domain_select$forcount"});
$input{"user_select$forcount"} = email_to_ascii($input{"user_select$forcount"});
my %user_select_compare;
my %old_user_select;
# user- und domainselect haben wenn keine Domain ausgewählt, wird an Script als Sonderzeichen ord(194) übertragen
# das muss in "nix" umgewandelt werden, damit Stringvergleich mit vorhandenen Weiterleitungen funktioniert
# und erkannt werden kann ob sich was geändert hat.
if(ord($input{"domain_select$forcount"}) == '160'){
$input{"domain_select$forcount"} = '';
}
if(ord($input{"user_select$forcount"}) == '160'){
$input{"user_select$forcount"} = '';
}
logline("debug","user_select$forcount=".$input{"user_select$forcount"});
##split multiple user_select ord($char== 0)
my @arr = split /\x0/, $input{"user_select$forcount"};
@{$user_select{$forcount}} = @arr;
foreach(@arr){
logline("debug","arr###$_###\n");
$user_select_compare{$_} = 1;
}
# E-Mailadressen in Hash inkrementieren
## wenn mehr als 1 rauskommt wurde E-Mailadresse doppelt angegeben
# aber nur wenn mindestens ein Formularfeld ausgefüllt wurde, sonst würde @ als doppelte E-Mailadresse erkannt werden
if ($input{"domain_select$forcount"} && ($input{"user$forcount"} || $input{"user_select$forcount"} || $input{"freefield$forcount"."_1"} )){
my $email_tmp = $input{"user$forcount"} . '@' . $input{"domain_select$forcount"};
$emailadress{$email_tmp}++;
}
## bei oldfreefield muss letzes Komma weggetrimmt werden, da dies bei freefield auch gemacht wird.
##ansonsten wird fälschlicherweise erkannt, daß sich etwas geändert hat
##wenn autoresponder mit weiterleitung an User, dann gibt es am Ende Leerzeichen, in dem Fall Leerzeichen und Komma am Ende weg
#$input{"old_freefield$forcount"} =~ s/\s+$//;
#$input{"old_freefield$forcount"} =~ s/,$//;
#$input{"freefield$forcount"} =~ s/[(\;|\,|\:|\s+)]{2,}/,/gc;
#$input{"freefield$forcount"} =~ s/^[(\s*\;\s*|\s*\,\s*|\s*\:\s*|\s+)]{0,}//;
#$input{"freefield$forcount"} =~ s/[(\s*\;\s*|\s*\,\s*|\s*\:\s*|\s+)]{0,}$//;
#my @targetsarray = split /\s*\;\s*|\s*\,\s*|\s*\:\s*|\s+/, $input{"freefield$forcount"};
## im Freifeld sind z.B. pupupu und blubber als Weiterleitung auf 2 user drin und user_select ist leer
## kd ändert user_select auf pupupu, da user schon in freefield drin ergibt sich keine nderung
#if(grep (/^$input{"user_select$forcount"}$/, @targetsarray)){
# my $target_string = join(',', @targetsarray);
# logline("debug",qq~clear $input{"user_select$forcount"} from #$target_string#~);
# $input{"user_select$forcount"} = '';
#}
my $freefield_changed = '';
#foreach(grep {/^freefield$forcount_/} sort keys %input){
foreach(sort keys %input){
my $freefield = $_;
my $regex = '^freefield'.$forcount.'_';
next if $freefield !~ /$regex/;
my $freefield_value = $input{$freefield};
my $freefield_count = 1;
logline("debug","forcount=$forcount freefield=$freefield value=".$input{$freefield});
if ($input{"old_$freefield"} ne $input{"$freefield"}) {
push @forcount_change, $forcount;
$freefields{$forcount}{$freefield} = $freefield_value;
$freefield_changed = 1;
logline("debug","$forcount old_freefield != freefield freefield=$freefield ".$input{"old_$freefield"}.'!='.$input{"$freefield"});
}
elsif(length($freefield_value) > 0){
#vorhandene Freifelder übernehmen
$freefields{$forcount}{$freefield} = $freefield_value;
}
}
# hack to throw error
if(exists($input{"user$forcount"}) && exists($input{"domain_select$forcount"})){
if(
$input{"old_user$forcount"} ne '' ||
$input{"old_domain_select$forcount"} ne '' ||
$input{"old_user_select$forcount"} ne '' ||
$input{"old_freefield_select$forcount"} ne ''
) {
if(! $input{"user_select$forcount"} && keys %{$freefields{$forcount}} < 1 && !length($input{"forward_to_text$forcount"})){
push @forcount_change, $forcount;
}
}
}
#irgendeine nderung?
#multiple user select is stored as | separated hidden field, compare with user_select hash
#<input name="old_user_select1" type="hidden" id="old_user_select1" value="test1@test2.de|test2@test1.de">
my $user_select_changed = '';
my @old_user_select = split /\|/, $input{"old_user_select$forcount"};
foreach(@old_user_select){
$old_user_select{$_} = 1;
}
if (%old_user_select != %user_select_compare) {
foreach(sort keys %old_user_select){
logline("debug","$forcount old_user_select $_=" . $old_user_select{$_} . "##");
}
foreach(sort keys %user_select_compare){
logline("debug","$forcount user_select_compare $_=" . $user_select_compare{$_} . "##");
}
$user_select_changed = 1;
logline("debug","$forcount old_user_select != user_select_compare");
}
else {
my %cmp = map { $_ => 1 } keys %old_user_select;
for my $key (keys %user_select_compare) {
last unless exists $cmp{$key};
last unless $old_user_select{$key} eq $user_select_compare{$key};
delete $cmp{$key};
}
if (%cmp) {
$user_select_changed = 1;
logline("debug","$forcount cmp old_user_select != user_select_compare");
}
else{
#print "they have the same keys or values\n";
}
}
if($input{"old_user$forcount"} ne $input{"user$forcount"} ||
$user_select_changed ||
$freefield_changed)
{
logline("debug","Weiterleitung ändern1:$forcount user_select_changed=$user_select_changed freefield_changed=$freefield_changed");
logline("debug",qq~$forcount, neu:$input{"user$forcount"}\@$input{"domain_select$forcount"} alt:$input{"old_user$forcount"}\@$input{"old_domain_select$forcount"}~);
push @forcount_change, $forcount unless (grep $_ eq $forcount, @forcount_change);
$old_emailadress{qq~$input{"old_user$forcount"}\@$input{"old_domain_select$forcount"}~} = $forcount;
}
if($input{"old_domain_select$forcount"} ne '' &&
$input{"old_domain_select$forcount"} ne $input{"domain_select$forcount"}
)
{
logline("debug","Weiterleitung ändern2 domain_select:$forcount user_select_changed=$user_select_changed freefield_changed=$freefield_changed");
logline("debug",qq~$forcount, neu:$input{"user$forcount"}\@$input{"domain_select$forcount"} alt:$input{"old_user$forcount"}\@$input{"old_domain_select$forcount"}~);
push @forcount_change, $forcount unless (grep $_ eq $forcount, @forcount_change);
$old_emailadress{qq~$input{"old_user$forcount"}\@$input{"old_domain_select$forcount"}~} = $forcount;
}
$forcount++;
}
#keine Änderung, hat nur aus Spass geklickt
if(scalar @forcount_change == '0'){
#$template->param('result' => 'L__Es wurde keine Änderung durchgeführt__L');
$success_text = 'L__Es wurde keine Änderung durchgeführt__L';
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_email&success_text=' . encode_base64url($success_text);
return(\$template);
}
# doppelte E-Mailadressen?
foreach(sort keys %emailadress){
if($emailadress{$_} > 1){
$error_fields{"Emailfehler"} = "$_: L__Die E-Mail-Adresse wurde doppelt angegeben__L";
}
}
# weitere Überprüfungen der Eingabefelder nur durchführen, wenn überhaupt eine Änderung und nix doppelt
if(scalar @forcount_change >= 1 && ! $error){
foreach my $forcount(@forcount_change){
# hier stehen ein oder mehrere lokale User und/oder externe E-Mailadressen drin
#my @targetsarray = split /\s*\;\s*|\s*\,\s*|\s*\:\s*|\s+/, $input{"freefield$forcount"};
my @targetsarray = ();
my %freefield_hash = %{$freefields{$forcount}};
logline("debug",qq~vor foreach freefield hash~);
#gon on here add aliases
foreach(sort keys %freefield_hash){
push @targetsarray, $freefield_hash{$_};
logline("debug",qq~foreach freefield hash=$_ value=~.$freefield_hash{$_});
}
foreach(@{$user_select{$forcount}}){
if ($fb) {
push @targetsarray, qq~"|/usr/iports/bin/procmail -a $_"~;
}
else{
push @targetsarray, $_;
}
}
my $mailuser = $input{"user$forcount"} . '@' . $input{"domain_select$forcount"};
my $forward_filter;
# external
my $sendmail_target = $mailuser;
# add random local part to catch all
if($mailuser =~ m/^@/){
$sendmail_target = 'catchall' . $$ . $sendmail_target;
}
my $sendmail_forward = `/usr/sbin/sendmail -d27 -bv $sendmail_target 2>/dev/null | grep -m 1 'aliased to' 2>/dev/null | sed 's/^.*aliased to // ; s/"//g' 2>/dev/null`;
chomp($sendmail_forward);
# single virtmaps line
if(!length($sendmail_forward)){
$sendmail_forward = `/usr/sbin/sendmail -d60 -bv $sendmail_target 2>/dev/null | grep -m 1 'map_lookup(virtuser' 2>/dev/null | sed 's/.*> // ; s/ .*//' 2>/dev/null`;
}
$sendmail_forward = get_sendmail_forward($mailuser);
my $forward_target;
foreach $forward_target (split(/,\s*/,$sendmail_forward)){
# email
if($forward_target =~ m/^([^\@\s]+\@[^\@]+)$/){
push(@{$forward_to}, $1);
if($forward_filter ne 'att'){
$forward_filter = 'off';
}
}
# fwd_as_att
elsif($forward_target =~ m/fwd_as_att\s([^"]*)"/){
$forward_target = $1;
foreach $forward_target (split(/\s+/,$forward_target)){
if($forward_target !~ /^\//){
push(@{$forward_to}, $forward_target);
}
}
$forward_filter = 'att';
}
}
#all targets from form submit
$aliases_forcount{$forcount} = \@targetsarray;
if($input{"user$forcount"} ne '' && $input{"user$forcount"} !~ /[a-zA-Z0-9_\-\.]/ ){
$error_fields{"user$forcount"} = $input{"user$forcount"} . '@' . $input{"domain_select$forcount"} . ": L__Die E-Mail-Adresse enthält ungültige Zeichen__L";
}
#E-Mailadresse berprüfen, aber nur wenn $input{"user$forcount"} existiert. Wenn leer dann ist es catchallweiterleitung
elsif($input{"user$forcount"} ne '' && ! is_email($input{"user$forcount"} . '@' . $input{"domain_select$forcount"})){
$error_fields{"user$forcount"} = $input{"user$forcount"} . '@' . $input{"domain_select$forcount"} . ": L__Keine gültige E-Mail-Adresse__L";
}
if(! is_domain($input{"domain_select$forcount"})){
$error_fields{"domain_select$forcount"} = $input{"domain_select$forcount"} . " L__Bitte wählen Sie einen Domainnamen__L";
}
elsif($input{"domain_select$forcount"} !~ /^($splitted_domains)$/){
$error_fields{"domain_select$forcount"} = $input{"domain_select$forcount"} . ": L__Der Domainname ist für diesen vHost nicht erlaubt__L";
}
# Wenn neue Weiterleitung angelegt wird, dann mu auch Ziel angegeben sein
logline("debug",qq~userforcount=$input{"user$forcount"} input_domain_select=$input{"domain_select$forcount"} user_select_forcount=$input{"user_select$forcount"} keys freefields=~ . keys %{$freefields{$forcount}});
if(exists($input{"user$forcount"}) && exists($input{"domain_select$forcount"})){
if(! $input{"user_select$forcount"} && keys %{$freefields{$forcount}} < 1 && !length($input{"forward_to_text$forcount"})){
$error_fields{"user_select$forcount"} = $input{"user$forcount"} . '@' . $input{"domain_select$forcount"} . ": L__Bitte geben Sie einen Benutzer oder eine Weiterleitung an__L";
}
}
# ausgewählten E-Mailuser berprüfen, wenn keiner ausgewählt, dann freefield prüfen
foreach my $user_select(@{$user_select{$forcount}}){
# User wurde ausgewählt, gucken ob es den gibt
if(not exists $passwd{$user_select}){
$error_fields{"user_select$forcount"} = $user_select . ": L__Der E-Mail-User existiert nicht__L";
}
# ist ausgewählter User der Domain zugeordnet?
# hmpf, wenn er einmal drin ist, laesst es sich so nicht mehr speichern
#elsif($passwd{$user_select}{'gecos'} !~ /^$domain - POP$/){
# $error_fields{"user_select$forcount"} = $user_select . ": L__Der E-Mail-User ist einem anderen vHost zugeordnet__L";
#}
}
# freefield prüfen
#my %freefield_hash = $freefields{$forcount};
logline("debug",qq~old_freefield $input{"old_freefield$forcount"} new_freefield $input{"freefield$forcount"}~);
my $freefieldcount = '1';
foreach my $targetaddress_fieldname (sort keys %freefield_hash){
my $targetaddress = $freefield_hash{$targetaddress_fieldname};
logline("debug","targetaddress:$targetaddress targetaddress_fieldname=$targetaddress_fieldname");
# wenn Ziel ein @ beinhaltet gehen wir davon aus, da eine E-Mailadresse gemeint ist
# Usernamen nicht berprüfen, da es Weiterleitungen nach muell, papierkorb o.. gibt
# damit Mails schon auf SMTP-Ebene abgelehnt werden
if($targetaddress =~ /@/ && $targetaddress =~ /^.*[^a-zA-Z0-9_\-\.]{1,100}.*\@.*/ ){
$error_fields{"$targetaddress_fieldname"} = $input{"freefield$forcount"} . ": L__Ungültige Zeichen__L";
}
elsif( $targetaddress =~ /@/ && !is_email($targetaddress)){
$error_fields{"$targetaddress_fieldname"} = $targetaddress . ": L__Keine korrekte E-Mail-Adresse__L";
}
elsif( is_domain($targetaddress)){
$error_fields{"$targetaddress_fieldname"} = "L__Eine Domain kann kein Ziel sein__L";
logline("debug","error_fields freefield=$targetaddress_fieldname");
}
elsif( $targetaddress !~ /@/ && $targetaddress =~ /[^a-zA-Z0-9_\-\.\/]/){
$error_fields{"$targetaddress_fieldname"} = $targetaddress . ": L__Ungültige Zeichen__L";
}
elsif( $fb && ( length($targetaddress) > 4 && $targetaddress !~ /@/ && $targetaddress ne '/dev/null')){
$error_fields{"$targetaddress_fieldname"} = $targetaddress . ": L__Keine korrekte E-Mail-Adresse__L";
}
$freefieldcount++;
}
}
}
logline("debug","forcount_change:" . scalar @forcount_change);
if(scalar @forcount_change >= 1 && keys %error_fields >= 1){
return(html_error(\%error_fields));
}
if(scalar @forcount_change >= 1 && ! $error){
my @new_virtmaps;
my @new_aliases;
# wenn eine Weiterleitung von zwei oder meheren Usern auf einen User geändert wird
# kann die _spl-Zeile aus aliases gelöscht werden
my %delete_from_aliases;
my %add_to_aliases;
my %modify_aliases;
my $emailadress_regex = join('|',keys %old_emailadress);
foreach($virtmaps->file_content) {
# Wenn Domain aber kein Autoresponder
# Domainmituser@ und direkt am Zeilenbeginn
if(/^($emailadress_regex)\s+(.*)$/){
# aha, match auf ein der zu ändernden E-Mailadressen, value aus %old_emailadress ist die Zeile aus Fornular, wo
# neue Daten eingetragen wurden. $1 aus regex entspricht gespeichertem value
my $virtmaps_lhs = $1;
my $virtmaps_rhs = $2;
#$forcount_to_change ist lhs in virtmaps, was in hash %old_emailadress als key gespeichert ist
# der entsprechende value ist die zu ändernde Weiterleitung aus den Formularfeldern, $forcount=Formularfeldnummer
my $forcount = $old_emailadress{$virtmaps_lhs};
my @aliases_forcount = @{$aliases_forcount{$forcount}};
logline("debug","regex match:virtmaps_lhs=$1##virtmaps_rhs=$2##forcount=$forcount##aliases_forcount=$aliases_forcount{$forcount}");
# entweder einzelne Weiterleitung in virtmaps oder mehrere Ziele, d.h. auch aliases ändern
if($virtmaps_rhs =~ /_(spl|aut)$/){
# nur ein Ziel auf externe E-Mailadresse was vorher Weiterleitung auf mindstens 2 mit _spl war, ist in %aliases_forcount weil externe E-Mailadresse
# in freefield angegeben wurde. ext. emailadresse landet in virtmaps und _spl aus aliases löschen
if(scalar @aliases_forcount == '1' && ! $input{"user_select$forcount"} && ! $input{"has_autoreply$forcount"}){
logline("debug",qq~auf extern aliases_forcount=$aliases_forcount{$forcount}~);
push @new_virtmaps, qq~$input{"user$forcount"}\@$input{"domain_select$forcount"}\t\t$aliases_forcount[0]~;
$delete_from_aliases{$virtmaps_rhs} = '1';
}
#alles andere über _spl mit aliases
else{
push @new_virtmaps, qq~$input{"user$forcount"}\@$input{"domain_select$forcount"}\t\t$input{"user$forcount"}_$input{"domain_select$forcount"}_spl~;
# aliases modifizieren, Verknpfung von aliaszeile lhs zur zu ändernden Zeile aus Formular herstellen
$modify_aliases{$virtmaps_rhs} = $forcount;
# todo: in $modify_aliases das array von $aliases_forcount{$forcount} rein
}
}
else{
# nur ein Ziel auf externe E-Mailadresse, ist in %aliases_forcount weil externe E-Mailadresse
# in freefield angegeben wurde
if(scalar @aliases_forcount == '1' && ! $input{"user_select$forcount"} && $aliases_forcount[0] ne '/dev/null'){
logline("debug",qq~auf extern aliases_forcount=$aliases_forcount{$forcount}~);
push @new_virtmaps, qq~$input{"user$forcount"}\@$input{"domain_select$forcount"}\t\t$aliases_forcount[0]~;
}
else{
logline("debug",qq~aliases_forcount=$aliases_forcount{$forcount}~);
push @new_virtmaps, qq~$input{"user$forcount"}\@$input{"domain_select$forcount"}\t\t$input{"user$forcount"}_$input{"domain_select$forcount"}_spl~;
$add_to_aliases{$forcount} = qq~$input{"user$forcount"}_$input{"domain_select$forcount"}_spl~;
}
}
}
else{
push @new_virtmaps, $_;
}
}
#Neue Weiterleitung anhängen
foreach my $forcount(@forcount_change){
my @aliases_forcount = @{$aliases_forcount{$forcount}};
logline("debug","new forward: aliases_forcount=" . join(',', @aliases_forcount));
if( $input{"old_user$forcount"} eq '' &&
$input{"old_domain_select$forcount"} eq '' &&
$input{"old_user_select$forcount"} eq '' &&
$input{"old_freefield_select$forcount"} eq '')
{
if(scalar @aliases_forcount == '1' && ! $input{"user_select$forcount"} && $aliases_forcount[0] ne '/dev/null'){
#einzelne externe emailadresse
push @new_virtmaps, qq~$input{"user$forcount"}\@$input{"domain_select$forcount"}\t\t$aliases_forcount[0]~;
}
else {
#alles andere über _spl mit aliases
push @new_virtmaps, qq~$input{"user$forcount"}\@$input{"domain_select$forcount"}\t\t$input{"user$forcount"}_$input{"domain_select$forcount"}_spl~;
$add_to_aliases{$forcount} = qq~$input{"user$forcount"}_$input{"domain_select$forcount"}_spl~;
}
$sendmail_cw_domains{$input{"domain_select$forcount"}} = 1;
}
}
my $modify_aliases_regex = join('|',keys %modify_aliases);
my $delete_from_aliases_regex = join('|',keys %delete_from_aliases);
logline("debug","modify_aliases_regex: #$modify_aliases_regex#");
logline("debug","delete_from_aliases_regex: #$delete_from_aliases_regex#");
# modifizieren und alte löschen
foreach($aliases->file_content) {
my $line = $_;
#der erste matcht auf alle ziele + autoresponder oder Programm, der zweite auf Ziele ohne Programm, z.B. externe Emailadresse und/oder lokaler User
#if(/^($modify_aliases_regex)\s*:\s*(.*),\s*("{0,}.*)$/ || /^($modify_aliases_regex)\s*:\s*(.*)$/){
if( /^($modify_aliases_regex)\s*:\s*(.*)$/ ){
logline("debug","match auf modify_aliases_regex:1=$1 2=$2");
# Zeile modifizieren
my $aliases_lhs = $1;
my $aliases_rhs_targets = $2;
my $forcount = $modify_aliases{$aliases_lhs};
$input{"user$forcount"} = lc($input{"user$forcount"});
my @targetsarray = @{$aliases_forcount{$forcount}};
@targetsarray = easytecc3::del_array_duplicates(@targetsarray);
my $target_string = join(',', @targetsarray);
logline("debug","#####################target_string = $target_string");
#in $aliases_forcount{$forcount} sind nur Ziele aus Formular, Autoresponder hinzufügen wenn vorhanden
#und Dateinamen ändern wenn sich Emailadresse geändert hat
if ($input{"has_autoreply$forcount"}) {
$target_string .= qq~, "|$autoresponder /usr/local/etc/easytecc/$input{"user$forcount"}_$input{"domain_select$forcount"}.aut"~;
}
#spezielle Einträge übernehmen, alles was in Anführungszeichen und kein Autoresponder ist können
#pipes an kundeneigene Programme sein
my @aliases_rhs_targets_array = split /,\s*/, $aliases_rhs_targets;
foreach my $string(@aliases_rhs_targets_array){
logline("debug","#####################string = $string");
if ($string =~ /"/ && $string !~ /\/autoresponder/ && $string !~ /\|\/usr\/iports\/bin\/procmail -a/) {
$target_string .= qq~, $string~;
}
elsif($string =~ /^[^\|\/\s\"]+$/ && !exists($passwd{$string})){
logline("debug","#####################string is no user");
$target_string .= qq~, $string~;
}
}
$target_string =~ s/^,//;
$target_string =~ s/,$//;
$target_string =~ s/,,/,/g;
if($aliases_lhs =~ /_(aut|spl)$/){
# wenn sich die E-Mailadresse einer Weiterleitung mit Auroresponder ändert, muss sich auch der Name der
# Autoresponderdatei ändern, der immer eine bestimmte Syntax hat, z.B.
# auto@krusator.de = auto_krusator.de.aut
# Wenn auto@krusator.de auf doofauto@krusator.de geändert wird muss sie doofauto_krusator.de.aut heissen, also vorhandene Datei umbenennen
# vorhandene Autoresponderdatei:
if ($input{"has_autoreply$forcount"}) {
my $autoreply_file = $aliases_rhs_targets;
$autoreply_file =~ m/\/(.*\.aut)/;
$autoreply_file = $1;
my $new_autoreply_file = qq~$input{"user$forcount"}_$input{"domain_select$forcount"}.aut~;
logline("debug","has_autoreply=1 autoreply_file=$autoreply_file");
my $got = `$easytecc_prefix/mv.pl /usr/local/etc/$autoreply_file /usr/local/etc/$new_autoreply_file 2>&1` unless $fb;
my $got = `/usr/iports/bin/sudo /usr/sbin/mv.pl /usr/local/etc/easytecc/$autoreply_file /usr/local/etc/easytecc/$new_autoreply_file 2>&1` if $fb;
# autoresponderdatei nochmal einlesen und schreiben, damit ggf. auf externen Mailserver übertragen wird
logline("debug","Creating File Object /usr/local/etc/easytecc/$new_autoreply_file.");
my $file = file->new({file_name => "/usr/local/etc/easytecc/$new_autoreply_file"});
$file->read_file;
$got = $file->write_file;
if ($got) {
logline("error","/usr/local/etc/$new_autoreply_file ->write_file = ".$got);
return(error($got));
}
}
push @new_aliases, qq~$input{"user$forcount"}_$input{"domain_select$forcount"}_spl:\t$target_string~;
}
else{
push @new_aliases, qq~$aliases_lhs:\t$target_string~;
}
}
elsif(/^($delete_from_aliases_regex)\s*:\s*(.*)$/){
# nix, Zeile wird gelöscht
}
else{
push @new_aliases, $_;
}
}
foreach my $forcount(sort keys %add_to_aliases){
my @targetsarray = @{$aliases_forcount{$forcount}};
@targetsarray = easytecc3::del_array_duplicates(@targetsarray);
my $target_string = join(',', @targetsarray);
$target_string =~ s/^,//;
$target_string =~ s/,$//;
push @new_aliases, qq~$input{"user$forcount"}_$input{"domain_select$forcount"}_spl:\t$target_string~;
}
@{$virtmaps->file_content} = map(lc, @new_virtmaps);
my $got = $virtmaps->write_file;
if ($got) {
logline("error","virtmaps->write_file = ".$got);
return(error($got));
}
if(keys %modify_aliases || keys %delete_from_aliases || keys %add_to_aliases){
@{$aliases->file_content} = map(lc, @new_aliases);
my $got = $aliases->write_file;
if ($got) {
logline("error","aliases->write_file = ".$got);
return(error($got));
}
}
}
}
}
if (! $error && keys %delete_forward == 0){
logline("debug","exec_change_forward error=0 delete_forward=0");
my $user_context = qq~<br /><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_forward&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-Weiterleitungen anlegen"__L</b></a><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_popuser&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-User anlegen"__L</b></a>~;
$template->param('result' => 'L__Die E-Mail-Weiterleitungen wurden erfolgreich geändert__L' . $user_context);
$success_text = 'L__Die E-Mail-Weiterleitungen wurden erfolgreich geändert__L';
my $domainlist = '';
my $sendmail_cw = file->new({file_name => '/etc/mail/sendmail.cw'});
$sendmail_cw->read_file;
my %domains = %{$sendmail_cw->file_parsed_hash()};
if(keys %sendmail_cw_domains){
my $domain;
foreach $domain (keys %sendmail_cw_domains){
if(!exists $domains{$domain}){
if($domainlist ne ''){
$domainlist .= ', ';
}
$domainlist .= $domain;
}
}
}
if($domainlist ne ''){
$success_text .= '<br><br><span style="color: #a94442;">Die Domain';
if($domainlist =~ m/,/){
$success_text .= "s $domainlist sind";
} else {
$success_text .= " $domainlist ist";
}
$success_text .= ' noch nicht als Mailserver-Domain eingetragen und für den Mailempfang nicht aktiv!</span>';
}
if ($input{'email_type'} eq 'single_edit') {
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_single_edit_email&domain=' . $input{'domain'} . '&success_text=' . encode_base64url($success_text);
}
else{
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_email&success_text=' . encode_base64url($success_text);
}
}
elsif($error){
$json_output{'error'} = 'L__Ein Fehler ist aufgetreten__L';
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_new_autoreply{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
logline("debug","exec_new_autoreply result:$result###");
if($result){
}
else{
my $forward = $input{'forward'};
logline("debug","Creating File Object \$virtmaps.");
my $virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %virtmaps = %{$virtmaps->file_parsed_hash()};
logline("debug","Creating File Object \$aliases.");
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
my @new_virtmaps = ();
my @new_aliases = ();
my $aliases_lhs = '';
# $domain und $user um autoreplydateinamen zu erstellen
my $domain = $forward;
$domain =~ s/^(.*)\@//;
my $user = $1;
# Wenn einzelner Empfänger in virtmaps, dann muss er in aliases bernommen werden
my $virtmaps_to_aliases_target = '';
# wenn mehrere Empfänger, dann rhs aus virtmaps sichern, diese entspricht lhs aus aliases die modifiziert werden muss
my $old_virtmaps_rhs = '';
#Die Weiterleitung kann auf einen Empfänger in virtmaps oder schon auf mehrere Empfänger mit "_spl"
#in aliases angelegt sein
foreach($virtmaps->file_content){
# die zu ändernde E-Mailadresse, entweder ist es normale Weiterleitung oder es gibt _spl-Verweis auf aliases.
# wenn _spl dann existiert bereits Weiterleitung an mehrere User
if(/^$forward\s+(.*)$/){
my $virtmaps_rhs = $1;
if($virtmaps_rhs =~ /_(spl|aut)$/){
# virtmaps_rhs sichern, weil diese Zeile in aliases geändert werden muss
$old_virtmaps_rhs = $virtmaps_rhs;
#obsolet, kein Nutzen
#$virtmaps_rhs =~ s/_spl$/_aut/;
push @new_virtmaps, qq~$forward\t$virtmaps_rhs~;
$aliases_lhs = $virtmaps_rhs;
}
else{
# Weiterleitungsziel sichern, der kommt mit in aliases als Empfänger
$virtmaps_to_aliases_target = $virtmaps_rhs;
# anschliessend rhs von virtmaps auf _aut ändern
$virtmaps_rhs = $user . '_' . $domain . '_aut';
push @new_virtmaps, qq~$forward\t$virtmaps_rhs~;
# virtmaps_rhs z.B. blubber_hostnet.de_aut
$aliases_lhs = $virtmaps_rhs;
}
}
else{
push @new_virtmaps, $_;
}
}
# wenn $virtmaps_to_aliases_target gesetzt, dann wissen wir, da es vorher noch keinen eintrag in aliases gab.
# D.h. neue Zeile in aliases anhängen
if($virtmaps_to_aliases_target){
push @{$aliases->file_content}, $aliases_lhs . ":\t" . $virtmaps_to_aliases_target . ',' . qq~"|$autoresponder /usr/local/etc/easytecc/$user~ . '_' . qq~$domain.aut"~;
@new_aliases = @{$aliases->file_content};
}
#ansonmsten Zeile suchen und modifizieren
else{
foreach($aliases->file_content){
# vorhandene Weiterleitung in aliases an mehrere User gefunden
if(/^$old_virtmaps_rhs\s*:\s*(.*)$/){
push @new_aliases, $aliases_lhs . ":\t" . $1 . ',' . qq~"|$autoresponder /usr/local/etc/easytecc/$user~ . '_' . qq~$domain.aut"~;
}
else{
push @new_aliases, $_;
}
}
}
$aliases->file_content(\@new_aliases);
my $got = $aliases->write_file;
if ($got) {
logline("error","aliases->write_file = ".$got);
return(error($got));
}
@new_virtmaps = map(lc, @new_virtmaps);
$virtmaps->file_content(\@new_virtmaps);
my $got = $virtmaps->write_file;
if ($got) {
logline("error","virtmaps->write_file = ".$got);
return(error($got));
}
logline("debug","Creating File Object /usr/local/etc/easytecc/" . $user . '_' . $domain . '.aut');
my $autoreply = file->new({ file_name => '/usr/local/etc/easytecc/' . $user . '_' . $domain . '.aut',
user => $user,
domain => $domain});
my @autoreply_content = ("From: $forward", "Subject: $input{'autoreply_subject'}\n", "$input{'autoreply_text'}");
$autoreply->file_content(\@autoreply_content);
my $got = $autoreply->write_file;
if ($got) {
logline("error","autoreply->write_file = ".$got);
return(error($got));
}
}
my $user_context = qq~<br /><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_forward&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-Weiterleitungen anlegen"__L</b></a><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_popuser&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-User anlegen"__L</b></a>~;
$template->param('result' => 'L__Der Autoresponder wurde erfolgreich angelegt!__L' . $user_context);
$success_text = 'L__Der Autoresponder wurde erfolgreich angelegt!__L';
if ($input{'email_type'} eq 'single_edit') {
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_single_edit_email&domain=' . $input{'domain'} . '&success_text=' . encode_base64url($success_text);
}
else{
$json_output{'modal_action'} = 'change_forward';
$json_output{'modal_action_args'} = '&domain=' . $input{'domain'};
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_change_autoreply{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
logline("debug","exec_change_autoreply result: $result###");
if($result){
}
else{
my $domain = $input{'forward'};
my $forward = $input{'forward'};
my $forward_aliases = $forward;
$forward_aliases =~ s/(@|\.)/_/g;
$domain =~ s/^(.*)\@//;
my $user = $1;
my $autoreply_file = '';
# es gibt autoresponderdateien wo domainname mit _ oder mit. existiert:
# c.blubb_domainshooter.at.aut
# k.seifert_steiner_de.aut
my $domain_reverse = reverse($domain);
# umdrehen, den ersten _ gegen . ersetzen und dann einfach gucken was vorhanden ist, das lassen wir auch so, sonst muss beim Ändern von autoresponder
# immder die aliases ggf. geändert werden..., viel zu kompliziert
$domain_reverse =~ s/\./_/;
$domain_reverse = reverse($domain_reverse);
if(-e '/usr/local/etc/' . $forward_aliases . '.aut'){
$autoreply_file = '/usr/local/etc/' . $forward_aliases . '.aut';
}
elsif(-e '/usr/local/etc/' . $user . '_' . $domain . '.aut'){
$autoreply_file = '/usr/local/etc/' . $user . '_' . $domain . '.aut';
}
elsif(-e '/usr/local/etc/' . $user . '_' . $domain_reverse . '.aut'){
$autoreply_file = '/usr/local/etc/' . $user . '_' . $domain_reverse . '.aut';
}
elsif(-e '/usr/local/etc/easytecc/' . $forward_aliases . '.aut'){
$autoreply_file = '/usr/local/etc/easytecc/' . $forward_aliases . '.aut';
}
elsif(-e '/usr/local/etc/easytecc/' . $user . '_' . $domain . '.aut'){
$autoreply_file = '/usr/local/etc/easytecc/' . $user . '_' . $domain . '.aut';
}
elsif(-e '/usr/local/etc/easytecc/' . $user . '_' . $domain_reverse . '.aut'){
$autoreply_file = '/usr/local/etc/easytecc/' . $user . '_' . $domain_reverse . '.aut';
}
else{
return(html_error({'non_specific' => 'L__Kann Autoresponderdatei nicht öffnen__L'}));
}
logline("debug","Creating File Object \$autoreply_file.");
my $autoreply = file->new({ file_name => $autoreply_file,
user => $user,
domain => $domain});
my @autoreply_content = ("From: $input{'forward'}", "Subject: $input{'autoreply_subject'}\n", "$input{'autoreply_text'}");
$autoreply->file_content(\@autoreply_content);
my $got = $autoreply->write_file;
return(error($got)) if $got;
}
my $user_context = qq~<br /><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_forward&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-Weiterleitungen anlegen"__L</b></a><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_popuser&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-User anlegen"__L</b></a>~;
$template->param('result' => 'L__Der Autoresponder wurde erfolgreich geändert!__L' . $user_context);
$success_text = 'L__Der Autoresponder wurde erfolgreich geändert!__L';
if ($input{'email_type'} eq 'single_edit') {
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_single_edit_email&domain=' . $input{'domain'} . '&success_text=' . encode_base64url($success_text);
}
else{
$json_output{'modal_action'} = 'change_forward';
$json_output{'modal_action_args'} = '&domain=' . $input{'domain'} . '&success_text=' . encode_base64url($success_text);
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_delete_alert{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
if(length($input{'database'}) && length($input{'error'}) && -e "$mysqlbackup_dir/" . $input{'database'} . "/" . $input{'error'}){
my $to_remove = "$mysqlbackup_dir/" . $input{'database'} . "/" . $input{'error'};
logline("debug","to_remove=$to_remove");
my $got = `rm -f $to_remove`;
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
exit(0);
}
sub exec_delete_autoreply{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
logline("debug","exec_delete_autoreply result:$result###");
if($result){
}
else{
my $forward = $input{'forward'};
logline("debug","Creating File Object \$virtmaps.");
my $virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %virtmaps = %{$virtmaps->file_parsed_hash()};
logline("debug","Creating File Object \$aliases.");
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
my @new_virtmaps = ();
my @new_aliases = ();
my $aliases_lhs = '';
# $domain und $user um autoreplydateinamen zu erstellen
my $domain = $forward;
$domain =~ s/^(.*)\@//;
my $user = $1;
# Wenn einzelner Empfänger in virtmaps, dann muss er in aliases bernommen werden
my $virtmaps_to_aliases_target = '';
# wenn mehrere Empfänger, dann rhs aus virtmaps sichern, diese entspricht lhs aus aliases die modifiziert werden muss
my $old_virtmaps_rhs = '';
#Die Weiterleitung kann auf einen Empfänger in virtmaps oder schon auf mehrere Empfänger mit "_spl"
#in aliases angelegt sein
foreach($virtmaps->file_content){
# die zu ändernde E-Mailadresse, entweder ist es normale Weiterleitung oder es gibt _spl-Verweis auf aliases.
# wenn _spl dann existiert bereits Weiterleitung an mehrere User
if(/^$forward\s+(.*)$/){
# virtmaps_rhs sichern, weil diese Zeile in aliases geändert werden muss
# wenn es Autoreply mit nur einem Weiterleitungszeil war, dann alten Eintrag aus aliases raus und Ziel als normale
# Weiterleitung in virtmaps rein, nachdem aliases ausgelesen wurde wissen wir was in virtmaps reinmuss
$old_virtmaps_rhs = $1;
}
else{
push @new_virtmaps, $_;
}
}
foreach($aliases->file_content){
if(/^$old_virtmaps_rhs\s*:\s*(.*),\s*(".*)$/){
logline("debug","match auf modify_aliases_regex:$1 $2");
my $aliases_targets = $1;
my @targetsarray = split /,/, $aliases_targets;
# wenn mehr als ein Empfänger wird alaises-Eintrag weiterhin gebraucht und virtmapseintrag wird von aut in spl geändert
#if(scalar @targetsarray > 1){
my $aliases_lhs = $old_virtmaps_rhs;
#obsolet, kein Nutzen
#$aliases_lhs =~ s/_aut$/_spl/;
push @new_aliases, $aliases_lhs . ":\t" . $aliases_targets;
# nun wissen wir auch was in virtmaps rein muss: Weiterleitung an mehrere User
push @new_virtmaps, "$forward\t$aliases_lhs";
#}
#else{
# oder Weiterleitung an nur einen Empfänger
# zeile nicht übernehmen und Empfänger wandert in virtmaps. Da nur ein Empfänger ist es erstes Feld in targetsarray
# push @new_virtmaps, "$forward\t$targetsarray[0]";
#}
}
else{
push @new_aliases, $_;
}
}
$aliases->file_content(\@new_aliases);
my $got = $aliases->write_file;
return(error($got)) if $got;
@new_virtmaps = map(lc, @new_virtmaps);
$virtmaps->file_content(\@new_virtmaps);
my $got = $virtmaps->write_file;
return(error($got)) if $got;
my $file = '/usr/local/etc/easytecc/' . $user . '_' . $domain . '.aut';
easytecc3::del_autoreply_file($file);
}
my $user_context = qq~<br /><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_forward&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-Weiterleitungen anlegen"__L</b></a><br />
<a href="/cgi-bin/easytecc3/index.pl?action=change_popuser&domain=$input{'domain'}"><b>L__gehe zu "E-Mail-User anlegen"__L</b></a>~;
$template->param('result' => 'L__Der Autoresponder wurde erfolgreich gelöscht__L' . $user_context);
$success_text = 'L__Der Autoresponder wurde erfolgreich gelöscht__L';
if ($input{'email_type'} eq 'single_edit') {
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_single_edit_email&domain=' . $input{'domain'} . '&success_text=' . encode_base64url($success_text);
}
else{
$json_output{'modal_action'} = 'change_forward';
$json_output{'modal_action_args'} = '&domain=' . $input{'domain'};
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_new_ftpuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
logline("debug","exec_new_ftpuser result:$result###");
if($result){
}
else{
$error .= easytecc3::add_ftpuser(\%input);
}
$result = 'L__Fehler__L: ' . $error if $error;
return(html_error({'non_specific' => "$error"})) if $error;
$result = 'L__Der FTP-User wurde erfolgreich angelegt__L';
$success_text = 'L__Der FTP-User wurde erfolgreich angelegt__L';
$template->param('result' => $result);
logline("debug","result = " . $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_ftpuser&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_new_adminuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
logline("debug","exec_new_adminuser result:$result###");
my $gecos = 'CUST';
if($input{'new_vhosts'} ne ''){
$gecos .= '.vhost-1';
} elsif($input{'show_vhosts'} ne ''){
$gecos .= '.vhost';
}
if($input{'edit_email'} ne ''){
$gecos .= '.email-1';
} elsif($input{'show_email'} ne ''){
$gecos .= '.email';
}
if($input{'new_ftp'} ne ''){
$gecos .= '.ftp-2';
} elsif($input{'edit_ftp'} ne ''){
$gecos .= '.ftp-1';
} elsif($input{'show_ftp'} ne ''){
$gecos .= '.ftp';
}
if($input{'show_quota'} ne ''){
$gecos .= '.quota';
}
if($input{'show_spam'} ne ''){
$gecos .= '.spam';
}
if($input{'edit_fileman'} ne ''){
$gecos .= '.fileman-1';
} elsif($input{'show_fileman'} ne ''){
$gecos .= '.fileman';
}
if($input{'edit_logs'} ne ''){
$gecos .= '.logs-1';
} elsif($input{'show_logs'} ne ''){
$gecos .= '.logs';
}
if($input{'new_db'} ne ''){
$gecos .= '.db-2';
} elsif($input{'edit_db'} ne ''){
$gecos .= '.db-1';
} elsif($input{'show_db'} ne ''){
$gecos .= '.db';
}
if($input{'new_cron'} ne ''){
$gecos .= '.cron-2';
} elsif($input{'edit_cron'} ne ''){
$gecos .= '.cron-1';
} elsif($input{'show_cron'} ne ''){
$gecos .= '.cron';
}
if($input{'show_inst'} ne ''){
$gecos .= '.inst';
}
if($result){
}
else{
$input{'gecos'} = $gecos;
$error .= easytecc3::add_ftpuser(\%input);
}
$result = 'L__Fehler__L: ' . $error if $error;
return(html_error({'non_specific' => "$error"})) if $error;
$result = 'L__Der Kunde wurde erfolgreich angelegt__L';
$success_text = 'L__Der Kunde wurde erfolgreich angelegt__L';
$template->param('result' => $result);
logline("debug","result = " . $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_adminuser&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_delete_ftpuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
if($result){
}
elsif($input{'ftpuser'} eq 'admin' || $input{'ftpuser'} eq 'web' || $input{'ftpuser'} eq 'ftp' || $input{'ftpuser'} eq 'mail'){
$error = "$input{'ftpuser'}: L__User darf NICHT gelöscht werden__L";
}
else{
$error .= easytecc3::del_ftpuser($input{'ftpuser'}, $input{'delete_home'});
return(error(qq~L__Fehler beim Löschen von__L $input{'ftpuser'}: $error~)) if $error;
}
$result = 'L__Der FTP-User wurde erfolgreich gelöscht__L';
$success_text = 'L__Der FTP-User wurde erfolgreich gelöscht__L';
$template->param('result' => $result);
logline("debug","result = " . $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_ftpuser&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_delete_adminuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
if($result){
}
elsif($input{'ftpuser'} eq 'admin' || $input{'ftpuser'} eq 'web' || $input{'ftpuser'} eq 'ftp' || $input{'ftpuser'} eq 'mail'){
$error = "$input{'ftpuser'}: L__User darf NICHT gelöscht werden__L";
}
else{
$error .= easytecc3::del_ftpuser($input{'ftpuser'}, $input{'delete_home'});
return(error(qq~L__Fehler beim Löschen von__L $input{'ftpuser'}: $error~)) if $error;
}
$result = 'L__Der Kunde wurde erfolgreich gelöscht__L';
$success_text = 'L__Der Kunde wurde erfolgreich gelöscht__L';
$template->param('result' => $result);
logline("debug","result = " . $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_adminuser&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_change_adminuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
logline("debug","exec_change_adminuser result:$result###");
if($result){
}
else{
my $ftpuser = $input{'ftpuser'};
if(defined($input{'2fa'}) && $input{'2fa'} eq 'del'){
`rm -f /usr/local/etc/easytecc/2fa/$ftpuser`;
$result = 'L__Die Zwei-Faktor-Authentifizierung wurde deaktiviert__L!';
$success_text = 'L__Die Zwei-Faktor-Authentifizierung wurde deaktiviert__L!';
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_adminuser&success_text=' . encode_base64url($success_text);
return(\$template);
}
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my $ftpuser = $input{'ftpuser'};
my $gecos = 'CUST';
if($input{'new_vhosts'} ne ''){
$gecos .= '.vhost-1';
} elsif($input{'show_vhosts'} ne ''){
$gecos .= '.vhost';
}
if($input{'edit_email'} ne ''){
$gecos .= '.email-1';
} elsif($input{'show_email'} ne ''){
$gecos .= '.email';
}
if($input{'new_ftp'} ne ''){
$gecos .= '.ftp-2';
} elsif($input{'edit_ftp'} ne ''){
$gecos .= '.ftp-1';
} elsif($input{'show_ftp'} ne ''){
$gecos .= '.ftp';
}
if($input{'show_quota'} ne ''){
$gecos .= '.quota';
}
if($input{'show_spam'} ne ''){
$gecos .= '.spam';
}
if($input{'edit_fileman'} ne ''){
$gecos .= '.fileman-1';
} elsif($input{'show_fileman'} ne ''){
$gecos .= '.fileman';
}
if($input{'edit_logs'} ne ''){
$gecos .= '.logs-1';
} elsif($input{'show_logs'} ne ''){
$gecos .= '.logs';
}
if($input{'new_db'} ne ''){
$gecos .= '.db-2';
} elsif($input{'edit_db'} ne ''){
$gecos .= '.db-1';
} elsif($input{'show_db'} ne ''){
$gecos .= '.db';
}
if($input{'new_cron'} ne ''){
$gecos .= '.cron-2';
} elsif($input{'edit_cron'} ne ''){
$gecos .= '.cron-1';
} elsif($input{'show_cron'} ne ''){
$gecos .= '.cron';
}
if($input{'show_inst'} ne ''){
$gecos .= '.inst';
}
# wenn home geändert werden soll, nachfragen was mit Dateien im alten home passieren soll
# Optionen:
# -alten home-Ordner löschen
# -alten home-Ordner beibehalten und user admin zuordnen
# -Inhalt von alten nach neuen home-Ordner kopieren
# -Inhalt von alten nach neuen home verschieben
if($input{'home'} ne $passwd{$ftpuser}{'home'} && not exists $input{'home_action'}){
$template = HTML::Template->new(filename => 'change_ftpuser_home_options.html');
$template->param('ftpuser' => $ftpuser);
$template->param('ftpquota' => $input{'ftpquota'});
$template->param('gecos' => $gecos);
$template->param('home' => $input{'home'});
$template->param('old_home' => $passwd{$ftpuser}{'home'});
$template->param('change_adminuser' => '1');
logline("debug","Leaving (changed home path) ".(caller(0))[3]."().");
return(\$template);
}
if($input{'gecos'}){
$gecos = $input{'gecos'};
}
if($gecos ne $passwd{$ftpuser}{'gecos'} || $input{'home'} ne $passwd{$ftpuser}{'home'}){
my $got = '';
if ($fb) {
$got= `/usr/iports/bin/sudo /usr/sbin/usermod -h '$input{'home'}' -u '$ftpuser' -d '$gecos' 2>&1`;
if ($got =~ /WARNING: home/) {
$got = '';
}
}
else{
$got= `/usr/sbin/moduser -h '$input{'home'}' -u '$ftpuser' -d '$gecos' 2>&1`;
}
return(error("L__Fehler beim Ändern von__L $ftpuser: $got")) if $got;
}
# Quota ändern falls notwendig
my ($quotaref, $sum_ftplimit, $sum_ftpuse, $ftpserverlimit) = easytecc3::getquota_ftp();
my %quota = %$quotaref;
my $ftpquota = $quota{$ftpuser}{'quota'} / 1024;
if($input{'ftpquota'} ne $ftpquota){
my $got = '';
if ($fb) {
$got = `/usr/iports/bin/sudo /usr/sbin/setquota $ftpuser $input{"ftpquota"}M`;
}
else{
$got = `/usr/sbin/quotuser -q $input{'ftpquota'}M -n '$ftpuser' 2>&1`;
}
return(error("L__Fehler beim Ändern der Quota von__L $ftpuser: $got")) if $got;
}
$input{'ftppass'} =~ s/\s//g;
# Paswort ändern, wenn Formularfeld für Passwort ausgefüllt
if($input{'ftppass'}){
logline("debug","change ftp pass=" . $input{'ftppass'} . "###");
my $got = '';
if ($fb) {
$got = `/usr/iports/bin/sudo /usr/sbin/chps -p '$input{'ftppass'}' -n '$ftpuser' 2>&1`;
$got = '' if $got =~ /user information updated/;
}
else{
$got = `/usr/sbin/chps -p '$input{'ftppass'}' -n '$ftpuser' 2>&1`;
}
return(error("L__Fehler beim Ändern des Passwortes von__L $ftpuser: $got")) if $got;
}
# entweder soll home geändert werden und es wurde angegeben was passieren soll oder keine Änderung von home
if($input{'home'} ne $passwd{$ftpuser}{'home'}){
# wenn neus home, dann wurde home-Verzeichnis vorher mit moduser geändert
# das neue home auf chmod 775 setzen, weil moduser das nicht macht
my $got = `$easytecc_prefix/chmod.pl 775 $input{'home'} 2>&1` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/chmod.pl 775 $input{'home'} 2>&1` if $fb;
return(error("L__Fehler beim CHMOD von__L $input{'home'}: $got")) if $got;
if($input{'home_action'} eq 'delete'){
my $got = `$easytecc_prefix/rm.pl $passwd{$ftpuser}{'home'} d 2>&1` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/rm.pl $passwd{$ftpuser}{'home'} d 2>&1` if $fb;
return(error("L__Fehler beim Löschen von__L $passwd{$ftpuser}{'home'}: $got")) if $got;
$result = "L__Das Verzeichnis wurde erfolgreich gelöscht__L!";
}
elsif($input{'home_action'} eq 'keep'){
my $got = `$easytecc_prefix/chown.pl admin $passwd{$ftpuser}{'home'} d 2>&1` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl admin $passwd{$ftpuser}{'home'} d 2>&1` if $fb;
return(error("L__Fehler bei CHOWN von__L $passwd{$ftpuser}{'home'}: $got")) if $got;
$result = 'L__Das home-Verzeichnis des FTP-Users wurde erfolgreich geändert und das alte home-Verzeichnis wurde beibehalten__L!';
}
elsif($input{'home_action'} eq 'cp'){
# Dateien in neues home kopieren
my $got = `$easytecc_prefix/cp.pl $passwd{$ftpuser}{'home'} $input{'home'} d 2>&1` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/cp.pl $passwd{$ftpuser}{'home'} $input{'home'} d 2>&1` if $fb;
return(error("L__Fehler beim Kopieren von__L $passwd{$ftpuser}{'home'} L__zu__L $input{'home'}: $got")) if $got;
# Dateien im alten home admin zuordnen
$got = `$easytecc_prefix/chown.pl admin $passwd{$ftpuser}{'home'} d 2>&1` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl admin $passwd{$ftpuser}{'home'} d 2>&1` if $fb;
return(error("L__Fehler bei CHOWN von__L $passwd{$ftpuser}{'home'}: $got")) if $got;
$result = 'L__Das Verzeichnis wurde erfolgreich kopiert__L!';
}
elsif($input{'home_action'} eq 'mv'){
my $got = `$easytecc_prefix/mv.pl $passwd{$ftpuser}{'home'} $input{'home'} d 2>&1` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/mv.pl $passwd{$ftpuser}{'home'} $input{'home'} d 2>&1` if $fb;
return(error("L__Fehler beim Umbenennen von__L $passwd{$ftpuser}{'home'} L__zu__L $input{'home'}: $got")) if $got;
$result = 'L__Das Verzeichnis wurde erfolgreich umbenannt__L!';
}
}
if($input{'ftp_to_admin'}){
$result = 'L__Der Kunde wurde erfolgreich angelegt__L!';
$success_text = 'L__Der Kunde wurde erfolgreich angelegt__L!';
} else {
$result = 'L__Der Kunde wurde erfolgreich geändert__L!';
$success_text = 'L__Der Kunde wurde erfolgreich geändert__L!';
}
}
$template->param('result' => $result);
logline("debug","result = " . $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_adminuser&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_change_ftpuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
logline("debug","exec_change_ftpuser result:$result###");
if($result){
}
else{
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my $ftpuser = $input{'ftpuser'};
# force reading from passwd if gecos is not given at all
# could be an admin user edited by an admin
$input{'gecos'} = $passwd{$ftpuser}{'gecos'} unless $input{'gecos'};
# 2fa
if(defined($input{'2fa'}) && $input{'2fa'} ne 'noop'){
if($input{'2fa'} eq 'new'){
my $label = $ftpuser;
if($ftpuser eq 'admin'){
my $servername = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
chomp $servername;
$label .= '@' . $servername;
}
my $qrcode_url = `/usr/local/bin/google-authenticator -C -t -d -f -l $label -i easyTECC -Q UTF8 -r 3 -R 30 -s /usr/local/etc/easytecc/2fa/$ftpuser.setup -S 30 -w 3`;
($qrcode_url) = $qrcode_url =~ m/(https:\/\/www\.google\.com\/chart[^\s]+)/;
#$qrcode_url =~ s/https:\/\/www\.google\.com/https:\/\/chart.googleapis.com/;
`wget -q -O - '$qrcode_url' | openssl base64 | tr -d '\n' > /usr/local/etc/easytecc/2fa/$ftpuser.qr`;
$template = ${ change_ftpuser() };
return(\$template);
}
elsif($input{'2fa'} eq 'ok'){
`mv /usr/local/etc/easytecc/2fa/$ftpuser.setup /usr/local/etc/easytecc/2fa/$ftpuser`;
`rm /usr/local/etc/easytecc/2fa/$ftpuser.qr`;
$result = 'L__Die Zwei-Faktor-Authentifizierung wurde aktiviert__L!';
$success_text = 'L__Die Zwei-Faktor-Authentifizierung wurde aktiviert__L!';
}
elsif($input{'2fa'} eq 'del'){
`rm -f /usr/local/etc/easytecc/2fa/$ftpuser*`;
$result = 'L__Die Zwei-Faktor-Authentifizierung wurde deaktiviert__L!';
$success_text = 'L__Die Zwei-Faktor-Authentifizierung wurde deaktiviert__L!';
}
}
# wenn home geändert werden soll, nachfragen was mit Dateien im alten home passieren soll
# Optionen:
# -alten home-Ordner löschen
# -alten home-Ordner beibehalten und user admin zuordnen
# -Inhalt von alten nach neuen home-Ordner kopieren
# -Inhalt von alten nach neuen home verschieben
elsif($input{'home'} ne $passwd{$ftpuser}{'home'} && not exists $input{'home_action'}){
$template = HTML::Template->new(filename => 'change_ftpuser_home_options.html');
$template->param('ftpuser' => $ftpuser);
$template->param('ftpquota' => $input{'ftpquota'});
$template->param('gecos' => $input{'gecos'});
$template->param('home' => $input{'home'});
$template->param('old_home' => $passwd{$ftpuser}{'home'});
logline("debug","Leaving (changed home path) ".(caller(0))[3]."().");
return(\$template);
}
else{
logline("error","exec_change_ftpuser \$input{'home'}: " . $input{'home'});
logline("error","exec_change_ftpuser \$passwd{$ftpuser}{'home'}: " . $passwd{$ftpuser}{'home'});
logline("error","exec_change_ftpuser \$input{'gecos'}: " . $input{'gecos'});
logline("error","exec_change_ftpuser \$passwd{$ftpuser}{'gecos'}: " . $passwd{$ftpuser}{'gecos'});
# moduser nur, wenn description oder home geändert werden soll
if($input{'home'} ne $passwd{$ftpuser}{'home'} || $input{'gecos'} ne $passwd{$ftpuser}{'gecos'}){
my $got = '';
if ($fb) {
$got= `/usr/iports/bin/sudo /usr/sbin/usermod -h '$input{'home'}' -u '$ftpuser' -d "'$input{'gecos'}'" 2>&1`;
if ($got =~ /WARNING: home/) {
$got = '';
}
}
else{
$got= `/usr/sbin/moduser -h '$input{'home'}' -u '$ftpuser' -d '$input{'gecos'}' 2>&1`;
}
return(error("L__Fehler beim Ändern von__L $ftpuser: $got")) if $got;
}
# Quota ändern falls notwendig
my ($quotaref, $sum_ftplimit, $sum_ftpuse, $ftpserverlimit) = easytecc3::getquota_ftp();
my %quota = %$quotaref;
my $ftpquota = $quota{$ftpuser}{'quota'} / 1024;
if($input{'ftpquota'} ne $ftpquota){
my $got = '';
if ($fb) {
$got = `/usr/iports/bin/sudo /usr/sbin/setquota $ftpuser $input{"ftpquota"}M`;
}
else{
$got = `/usr/sbin/quotuser -q $input{'ftpquota'}M -n '$ftpuser' 2>&1`;
}
return(error("L__Fehler beim Ändern der Quota von__L $ftpuser: $got")) if $got;
}
$input{'ftppass'} =~ s/\s//g;
# Paswort ändern, wenn Formularfeld für Passwort ausgefüllt
if($input{'ftppass'}){
logline("debug","change ftp pass=" . $input{'ftppass'} . "###");
my $got = '';
if ($fb) {
$got = `/usr/iports/bin/sudo /usr/sbin/chps -p '$input{'ftppass'}' -n '$ftpuser' 2>&1`;
$got = '' if $got =~ /user information updated/;
}
else{
$got = `/usr/sbin/chps -p '$input{'ftppass'}' -n '$ftpuser' 2>&1`;
}
return(error("L__Fehler beim Ändern des Passwortes von__L $ftpuser: $got")) if $got;
}
#TODO fb
# entweder soll home geändert werden und es wurde angegeben was passieren soll oder keine Änderung von home
if($input{'home'} ne $passwd{$ftpuser}{'home'}){
# wenn neus home, dann wurde home-Verzeichnis vorher mit moduser geändert
# das neue home auf chmod 775 setzen, weil moduser das nicht macht
my $got = `$easytecc_prefix/chmod.pl 775 $input{'home'} 2>&1` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/chmod.pl 775 $input{'home'} 2>&1` if $fb;
return(error("L__Fehler beim CHMOD von__L $input{'home'}: $got")) if $got;
if($input{'home_action'} eq 'delete'){
my $got = `$easytecc_prefix/rm.pl $passwd{$ftpuser}{'home'} d 2>&1` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/rm.pl $passwd{$ftpuser}{'home'} d 2>&1` if $fb;
return(error("L__Fehler beim Löschen von__L $passwd{$ftpuser}{'home'}: $got")) if $got;
$result = "L__Das Verzeichnis wurde erfolgreich gelöscht__L!";
}
elsif($input{'home_action'} eq 'keep'){
my $got = `$easytecc_prefix/chown.pl admin $passwd{$ftpuser}{'home'} d 2>&1` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl admin $passwd{$ftpuser}{'home'} d 2>&1` if $fb;
return(error("L__Fehler bei CHOWN von__L $passwd{$ftpuser}{'home'}: $got")) if $got;
$result = 'L__Das home-Verzeichnis des FTP-Users wurde erfolgreich geändert und das alte home-Verzeichnis wurde beibehalten__L!';
}
elsif($input{'home_action'} eq 'cp'){
# Dateien in neues home kopieren
my $got = `$easytecc_prefix/cp.pl $passwd{$ftpuser}{'home'} $input{'home'} d 2>&1` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/cp.pl $passwd{$ftpuser}{'home'} $input{'home'} d 2>&1` if $fb;
return(error("L__Fehler beim Kopieren von__L $passwd{$ftpuser}{'home'} L__zu__L $input{'home'}: $got")) if $got;
# Dateien im alten home admin zuordnen
$got = `$easytecc_prefix/chown.pl admin $passwd{$ftpuser}{'home'} d 2>&1` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl admin $passwd{$ftpuser}{'home'} d 2>&1` if $fb;
return(error("L__Fehler bei CHOWN von__L $passwd{$ftpuser}{'home'}: $got")) if $got;
$result = 'L__Das Verzeichnis wurde erfolgreich kopiert__L!';
}
elsif($input{'home_action'} eq 'mv'){
my $got = `$easytecc_prefix/mv.pl $passwd{$ftpuser}{'home'} $input{'home'} d 2>&1` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/mv.pl $passwd{$ftpuser}{'home'} $input{'home'} d 2>&1` if $fb;
return(error("L__Fehler beim Umbenennen von__L $passwd{$ftpuser}{'home'} L__zu__L $input{'home'}: $got")) if $got;
$result = 'L__Das Verzeichnis wurde erfolgreich umbenannt__L!';
}
}
else{
if ($passwd{$ftpuser}{'shell'} eq '/usr/sbin/nologin' || $ftpuser =~ /^(admin|cyrus|dovecot|dovenull|mysql|pgsql|virtmail|web)$/) {
$result = 'L__Der System-User wurde erfolgreich geändert__L!';
$success_text = 'L__Der System-User wurde erfolgreich geändert__L!';
} else {
$result = 'L__Der FTP-User wurde erfolgreich geändert__L!';
$success_text = 'L__Der FTP-User wurde erfolgreich geändert__L!';
}
}
}
}
if( -f "/usr/local/etc/easytecc/2fa/$ftpuser"){
$template->param('2fa' => 1);
}
$template->param('result' => $result);
logline("debug","result = " . $result);
$json_output{'redirect_to'} = '&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_change_spamfilter{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_change_spamfilter result: $result###");
if($result){
}
else{
my %new_dnsbl;
my $whitelist_content = '';
my $blacklist_content = '';
logline("debug","Creating File Object \$procmailrc.");
my $procmailrc = file->new({file_name => '/etc/procmailrc'});
$procmailrc->read_file;
logline("debug","Creating File Object \$dnsbl.");
my $dnsbl = file->new({file_name => '/etc/mail/dnsbl.hosts'});
$dnsbl->read_file;
my %dnsbl = %{$dnsbl->file_parsed_hash()};
logline("debug","Creating File Object \$whitelist.");
my $whitelist = file->new({file_name => '/home/spamdef/.white.lst'});
$whitelist->read_file;
logline("debug","Creating File Object \$blacklist.");
my $blacklist = file->new({file_name => '/home/spamdef/.black.lst'});
$blacklist->read_file;
logline("debug","Creating File Object \$user_prefs.");
my $user_prefs = file->new({file_name => '/home/spamdef/.spamd/user_prefs'});
$user_prefs->read_file;
# rbl schreiben, zuerst die vorhandenen Listen auslesen, und mit $input{'rbl_...'} vergleichen und dann schreiben
my $line_yes = "YES\t";
my $line_no = "NO\t";
foreach(sort keys %dnsbl){
$line_yes .= "$_ " if($input{"rbl_$_"} == 1);
$line_no .= "$_ " if($input{"rbl_$_"} != 1);
}
my @rbl_file_content = ("$line_yes", "$line_no");
$dnsbl->file_content(\@rbl_file_content);
my $got = $dnsbl->write_file;
if ($got) {
logline("error","dnsbl->write_file = ".$got);
return(error($got));
}
# whitelist schreiben
my @whitelist_content = split m(\r\n|;|:|,|\t+|\s+), $input{'whitelist'};
$whitelist->file_content(\@whitelist_content);
$got = $whitelist->write_file;
if ($got) {
logline("error","whitelist->write_file = ".$got);
return(error($got));
}
# blacklist schreiben
my @blacklist_content = split m(\r\n|;|:|,|\t+|\s+), $input{'blacklist'};
$blacklist->file_content(\@blacklist_content);
$got = $blacklist->write_file;
if ($got) {
logline("error","blacklist->write_file = ".$got);
return(error($got));
}
# /etc/procmailrc schreiben
# VIRUS=MARK
# SPAMD=ON
# PSPAM=MARK
# CSPAM=MARK
# SUBJ_VIRUS='*VIRUSVERDACHTT*:'
# SUBJ_PSPAM='*SPAMVERDACHT*:'
# SUBJ_CSPAM='*SPAM ERKANNT*:'
# CLEVEL='\*\*\*\*\*\*'
# POSTFIX='bat|com|dll|exe|pif|scr|vbs|zip'
my @new_procmailrc;
my $clevel = '\*' x $input{'cspam_level'};
my @postfix = split(/\s+|\;|\,|\n/,$input{"postfix_virus"});
my ($line,$name,$val);
foreach(@{$procmailrc->file_content}){
if(/^VIRUS=/){
push @new_procmailrc, "VIRUS=$input{'action_virus'}";
}
elsif(/^SPAMD=/){
push @new_procmailrc, "SPAMD=$input{'spamd'}";
}
elsif(/^PSPAM=/){
push @new_procmailrc, "PSPAM=$input{'action_pspam'}";
}
elsif(/^CSPAM=/){
push @new_procmailrc, "CSPAM=$input{'action_cspam'}";
}
elsif(/^CLEVEL=/){
push @new_procmailrc, "CLEVEL='$clevel'";
}
# veränderbare
elsif(/^POSTFIX=/){
my $postfix = "";
foreach my $item (sort @postfix){
next unless($item);
next if($item eq $lastitem);
$postfix .= "$item|";
$lastitem = $item;
}
chop $postfix;
push @new_procmailrc, "POSTFIX='$postfix'";
}
elsif(/^SUBJ_CSPAM\s*=/){
push @new_procmailrc, "SUBJ_CSPAM='$input{'subj_cspam'}'";
}
elsif(/^SUBJ_PSPAM\s*=/){
push @new_procmailrc, "SUBJ_PSPAM='$input{'subj_pspam'}'";
}
elsif(/^SUBJ_VIRUS\s*=/){
push @new_procmailrc, "SUBJ_VIRUS='$input{'subj_virus'}'";
}
else {
push @new_procmailrc, $_;
}
}
$procmailrc->file_content(\@new_procmailrc);
$got = $procmailrc->write_file;
logline("debug","write procmail:$got");
if ($got) {
logline("error","procmailrc->write_file = ".$got);
return(error($got));
}
# user_prefs schreiben
my $new_user_prefs_ref = easytecc3::prepare_user_prefs($user_prefs, \%input);
my @new_user_prefs = @$new_user_prefs_ref;
$user_prefs->file_content(\@new_user_prefs);
$got = $user_prefs->write_file;
if ($got) {
logline("error","user_prefs->write_file = ".$got);
return(error($got));
}
# .deliver - sed -i hat unter bsd leider einen bug und legt immer temp-dateien im selben dir an, deswegen das gecatte
my $deliver = "/etc/.deliver";
my $junkfolder = $input{'junkfolder'};
$got = `[ -s $deliver ] || echo 'DOVECOT_JUNK=' > $deliver 2>/dev/null; sed 's/^DOVECOT_JUNK=.*/DOVECOT_JUNK=\'$junkfolder\'/' $deliver > /tmp/.deliver.$$ && cat /tmp/.deliver.$$ > $deliver && rm /tmp/.deliver.$$`;
if ($got) {
logline("error",".deliver->write_file = ".$got);
return(error($got));
}
}
$template->param('result' => 'L__Die globalen Spameinstellungen wurden erfolgreich geändert__L!');
$success_text = 'L__Die globalen Spameinstellungen wurden erfolgreich geändert__L!';
logline("debug","<<< Leaving ".(caller(0))[3]."().");
undef %input;
$input{'action'} = 'change_spamfilter';
change_spamfilter();
#return(\$template);
}
sub exec_new_special_spamfilter{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_new_special_spamfilter result: $result###");
if($result){
}
else{
$special_spamfilter = ascii_domain($input{'special_spam_user_domain'});
logline("debug","exec_new_special_spamfilter vor genspam: $special_spamfilter");
system("/usr/sbin/genspam","-n",$special_spamfilter) unless $fb;
my $got = `/usr/iports/bin/sudo /usr/sbin/genspam -n $special_spamfilter` if $fb;
logline("debug","genspam got: $got");
my $whitelist_content = '';
my $blacklist_content = '';
logline("debug","Creating File Object \$procmailrc.");
my $procmailrc = file->new({file_name => "/home/$special_spamfilter/.spamproc",
user => "$special_spamfilter"});
$procmailrc->read_file;
logline("debug","Creating File Object \$whitelist.");
my $whitelist = file->new({file_name => "/home/$special_spamfilter/.white.lst",
user => "$special_spamfilter"});
#$whitelist->read_file;
logline("debug","Creating File Object \$blacklist.");
my $blacklist = file->new({file_name => "/home/$special_spamfilter/.black.lst",
user => "$special_spamfilter"});
#$blacklist->read_file;
logline("debug","Creating File Object \$user_prefs.");
my $user_prefs = file->new({file_name => "/home/$special_spamfilter/.spamd/user_prefs",
user => "$special_spamfilter"});
$user_prefs->read_file;
# whitelist schreiben
my @whitelist_content_tmp = split m(\r\n|;|:|,|\t+|\s+), $input{'special_whitelist'};
my @whitelist_content = ();
foreach(@whitelist_content_tmp){
if(/@/){
push @whitelist_content, email_to_ascii($_);
}
else{
push @whitelist_content, ascii_domain($_);
}
}
$whitelist->file_content(\@whitelist_content);
$got = $whitelist->write_file;
if ($got) {
logline("error","whitelist->write_file = ".$got);
return(error($got));
}
# blacklist schreiben
my @blacklist_content_tmp = split m(\r\n|;|:|,|\t+|\s+), $input{'special_blacklist'};
my @blacklist_content = ();
foreach(@blacklist_content_tmp){
if(/@/){
push @blacklist_content, email_to_ascii($_);
}
else{
push @blacklist_content, ascii_domain($_);
}
}
$blacklist->file_content(\@blacklist_content);
$got = $blacklist->write_file;
if ($got) {
logline("error","blacklist->write_file = ".$got);
return(error($got));
}
# /etc/procmailrc schreiben
# VIRUS=MARK
# SPAMD=ON
# PSPAM=MARK
# CSPAM=MARK
# SUBJ_VIRUS='*VIRUSVERDACHTT*:'
# SUBJ_PSPAM='*SPAMVERDACHT*:'
# SUBJ_CSPAM='*SPAM ERKANNT*:'
# CLEVEL='\*\*\*\*\*\*'
# POSTFIX='bat|com|dll|exe|pif|scr|vbs|zip'
my @new_procmailrc;
my $clevel = '\*' x $input{'special_cspam_level'};
my @postfix = split(/\s+|\;|\,|\n/,$input{"special_postfix_virus"});
my ($line,$name,$val);
foreach(@{$procmailrc->file_content}){
if(/^VIRUS=/){
push @new_procmailrc, "VIRUS=$input{'special_action_virus'}";
}
elsif(/^SPAMD=/){
push @new_procmailrc, "SPAMD=$input{'special_spamd'}";
}
elsif(/^PSPAM=/){
push @new_procmailrc, "PSPAM=$input{'special_action_pspam'}";
}
elsif(/^CSPAM=/){
push @new_procmailrc, "CSPAM=$input{'special_action_cspam'}";
}
elsif(/^CLEVEL=/){
push @new_procmailrc, "CLEVEL='$clevel'";
}
# veränderbare
elsif(/^POSTFIX=/){
my $postfix = "";
foreach my $item (sort @postfix){
next unless($item);
next if($item eq $lastitem);
$postfix .= "$item|";
$lastitem = $item;
}
chop $postfix;
push @new_procmailrc, "POSTFIX='$postfix'";
}
elsif(/^SUBJ_CSPAM\s*=/){
push @new_procmailrc, "SUBJ_CSPAM='$input{'special_subj_cspam'}'";
}
elsif(/^SUBJ_PSPAM\s*=/){
push @new_procmailrc, "SUBJ_PSPAM='$input{'special_subj_pspam'}'";
}
elsif(/^SUBJ_VIRUS\s*=/){
push @new_procmailrc, "SUBJ_VIRUS='$input{'special_subj_virus'}'";
}
else {
push @new_procmailrc, $_;
}
}
$procmailrc->file_content(\@new_procmailrc);
$got = $procmailrc->write_file;
if ($got) {
logline("error","procmailrc->write_file = ".$got);
return(error($got));
}
# user_prefs schreiben
my $new_user_prefs_ref = easytecc3::prepare_user_prefs($user_prefs, \%input);
my @new_user_prefs = @$new_user_prefs_ref;
$user_prefs->file_content(\@new_user_prefs);
$got = $user_prefs->write_file;
if ($got) {
logline("error","user_prefs->write_file = ".$got);
return(error($got));
}
$mailpasswd = easytecc3::get_mailpasswd();
my %mailpasswd = %{$mailpasswd->file_parsed_hash()};
#my %mailpasswd = %{easytecc3::get_mailpasswd()};
my $domain = $mailpasswd{$special_spamfilter}{'gecos'};
$domain =~ s/ - POP$//;
# wenn Domain in mailpasswd nicht gefunden wird, dann ist es eine Domain
$domain = $special_spamfilter unless $domain;
#spamconf ändern
logline("debug","Creating File Object /usr/local/etc/easytecc/spamuser.conf.");
my $file = file->new({file_name => '/usr/local/etc/easytecc/spamuser.conf', append => '1', file_content => [qq~$special_spamfilter=$domain~]});
$got = $file->write_file;
if ($got) {
logline("error","/usr/local/etc/easytecc/spamuser.conf->write_file = ".$got);
return(error($got));
}
# .deliver - sed -i hat unter bsd leider einen bug und legt immer temp-dateien im selben dir an, deswegen das gecatte
my $deliver = "/home/$special_spamfilter/.deliver";
my $junkfolder = $input{'special_junkfolder'};
$got = `[ -s $deliver ] || echo 'DOVECOT_JUNK=' > $deliver 2>/dev/null; sed 's/^DOVECOT_JUNK=.*/DOVECOT_JUNK=\'$junkfolder\'/' $deliver > /tmp/.deliver.$$ && cat /tmp/.deliver.$$ > $deliver && rm /tmp/.deliver.$$`;
if ($got) {
logline("error",".deliver->write_file = ".$got);
return(error($got));
}
}
$template->param('result' => 'L__Die speziellen Spameinstellungen wurden erfolgreich angelegt__L!');
$success_text = 'L__Die speziellen Spameinstellungen wurden erfolgreich angelegt__L!';
logline("debug","<<< Leaving ".(caller(0))[3]."().");
# mailuser hack
if($session && $session->param('is_mailuser')){
logline("debug","is_mailuser=1, setting template=mailuser_interface");
$template = ${mailuser_interface()};
$action = $input{'action'} = 'mailuser_interface';
$input{'active_tab'} = '_spamfilter';
} else {
#direct call to change_spamfilter with active tab 3
undef %input;
$input{'active_tab'} = '3';
$template = ${change_spamfilter()};
}
return(\$template);
}
sub exec_change_special_spamfilter{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_change_special_spamfilter result:$result###");
if($result){
}
else{
$special_spamfilter = ascii_domain($input{'special_spam_user_domain'});
my $whitelist_content = '';
my $blacklist_content = '';
logline("debug","Creating File Object \$procmailrc.");
my $procmailrc = file->new({file_name => "/home/$special_spamfilter/.spamproc",
user => "$special_spamfilter"});
$procmailrc->read_file;
logline("debug","Creating File Object \$whitelist.");
my $whitelist = file->new({file_name => "/home/$special_spamfilter/.white.lst",
user => "$special_spamfilter"});
#$whitelist->read_file;
logline("debug","Creating File Object \$blacklist.");
my $blacklist = file->new({file_name => "/home/$special_spamfilter/.black.lst",
user => "$special_spamfilter"});
#$blacklist->read_file;
logline("debug","Creating File Object \$user_prefs.");
my $user_prefs = file->new({file_name => "/home/$special_spamfilter/.spamd/user_prefs",
user => "$special_spamfilter"});
$user_prefs->read_file;
# whitelist schreiben
my @whitelist_content_tmp = split m(\r\n|;|:|,|\t+|\s+), $input{'special_whitelist'};
my @whitelist_content = ();
foreach(@whitelist_content_tmp){
if(/@/){
push @whitelist_content, email_to_ascii($_);
}
else{
push @whitelist_content, ascii_domain($_);
}
}
$whitelist->file_content(\@whitelist_content);
my $got = $whitelist->write_file;
return(error($got)) if $got;
# blacklist schreiben
my @blacklist_content_tmp = split m(\r\n|;|:|,|\t+|\s+), $input{'special_blacklist'};
my @blacklist_content = ();
foreach(@blacklist_content_tmp){
if(/@/){
push @blacklist_content, email_to_ascii($_);
}
else{
push @blacklist_content, ascii_domain($_);
}
}
$blacklist->file_content(\@blacklist_content);
$got = $blacklist->write_file;
return(error($got)) if $got;
# /etc/procmailrc schreiben
# VIRUS=MARK
# SPAMD=ON
# PSPAM=MARK
# CSPAM=MARK
# SUBJ_VIRUS='*VIRUSVERDACHTT*:'
# SUBJ_PSPAM='*SPAMVERDACHT*:'
# SUBJ_CSPAM='*SPAM ERKANNT*:'
# CLEVEL='\*\*\*\*\*\*'
# POSTFIX='bat|com|dll|exe|pif|scr|vbs|zip'
my @new_procmailrc;
my $clevel = '\*' x $input{'special_cspam_level'};
my @postfix = split(/\s+|\;|\,|\n/,$input{"special_postfix_virus"});
my ($line,$name,$val);
foreach(@{$procmailrc->file_content}){
if(/^VIRUS=/){
push @new_procmailrc, "VIRUS=$input{'special_action_virus'}";
}
elsif(/^SPAMD=/){
push @new_procmailrc, "SPAMD=$input{'special_spamd'}";
}
elsif(/^PSPAM=/){
push @new_procmailrc, "PSPAM=$input{'special_action_pspam'}";
}
elsif(/^CSPAM=/){
push @new_procmailrc, "CSPAM=$input{'special_action_cspam'}";
}
elsif(/^CLEVEL=/){
push @new_procmailrc, "CLEVEL='$clevel'";
}
# veränderbare
elsif(/^POSTFIX=/){
my $postfix = "";
foreach my $item (sort @postfix){
next unless($item);
next if($item eq $lastitem);
$postfix .= "$item|";
$lastitem = $item;
}
chop $postfix;
push @new_procmailrc, "POSTFIX='$postfix'";
}
elsif(/^SUBJ_CSPAM\s*=/){
push @new_procmailrc, "SUBJ_CSPAM='$input{'special_subj_cspam'}'";
}
elsif(/^SUBJ_PSPAM\s*=/){
push @new_procmailrc, "SUBJ_PSPAM='$input{'special_subj_pspam'}'";
}
elsif(/^SUBJ_VIRUS\s*=/){
push @new_procmailrc, "SUBJ_VIRUS='$input{'special_subj_virus'}'";
}
else {
push @new_procmailrc, $_;
}
}
$procmailrc->file_content(\@new_procmailrc);
$got = $procmailrc->write_file;
if ($got) {
logline("error","procmailrc->write_file = ".$got);
return(error($got));
}
# user_prefs schreiben
my $new_user_prefs_ref = easytecc3::prepare_user_prefs($user_prefs, \%input);
my @new_user_prefs = @$new_user_prefs_ref;
$user_prefs->file_content(\@new_user_prefs);
$got = $user_prefs->write_file;
if ($got) {
logline("error","user_prefs->write_file = ".$got);
return(error($got));
}
# .deliver - sed -i hat unter bsd leider einen bug und legt immer temp-dateien im selben dir an, deswegen das gecatte
my $deliver = "/home/$special_spamfilter/.deliver";
my $junkfolder = $input{'special_junkfolder'};
$got = `[ -s $deliver ] || echo 'DOVECOT_JUNK=' > $deliver 2>/dev/null; sed 's/^DOVECOT_JUNK=.*/DOVECOT_JUNK=\'$junkfolder\'/' $deliver > /tmp/.deliver.$$ && cat /tmp/.deliver.$$ > $deliver && rm /tmp/.deliver.$$`;
if ($got) {
logline("error",".deliver->write_file = ".$got);
return(error($got));
}
}
$success_text = 'L__Die speziellen Spameinstellungen wurden erfolgreich geändert__L!';
# mailuser hack
if($session && $session->param('is_mailuser')){
logline("debug","is_mailuser=1, setting template=mailuser_interface");
$template = ${mailuser_interface()};
$action = $input{'action'} = 'mailuser_interface';
$input{'active_tab'} = '_spamfilter';
} else {
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=change_spamfilter&active_tab=3&success_text=' . encode_base64url($success_text);
}
$template->param('result' => 'L__Die speziellen Spameinstellungen wurden erfolgreich geändert__L!');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_delete_special_spamfilter{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
my $success_text = '';
if($result){
}
else{
my $special_spamfilter = $input{'special_spam_user_domain'};
my $tmperror = system("/usr/sbin/delspam","-n","$special_spamfilter") unless $fb;
my $tmperror = `/usr/iports/bin/sudo /usr/sbin/delspam -n $special_spamfilter` if $fb;
return(html_error(({'L__Die Spameinstellungen konnten nicht gelöscht werden__L' => "$tmperror"}))) if $tmperror;
if(-e "/etc/cshost"){
$tmperror = `/usr/sbin/spamconf -d $special_spamfilter 2>&1` unless $fb;
$tmperror = `/usr/sbin/spamconf -d $special_spamfilter 2>&1` if $fb;
return(html_error(({'L__Die Spameinstellungen konnten nicht gelöscht werden__L' => "can't delete spamconfs for user $special_spamfilter at spamd: $tmperror"}))) if $tmperror;
}
my $got = easytecc3::delete_from_spamconf($special_spamfilter);
if ($got) {
logline("error","delete_from_spamconf($special_spamfilter) = ".$got);
return(error($got));
}
$result = "L__Die Spameinstellungen für__L $special_spamfilter L__wurden erfolgreich gelöscht__L";
$success_text = "L__Die Spameinstellungen für__L $special_spamfilter L__wurden erfolgreich gelöscht__L";
}
$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=change_spamfilter&active_tab=3&success_text=' . encode_base64url($success_text);
return(\$template);
}
sub exec_change_virusfilter{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_change_virusfilter result: $result###");
if($result){
}
else{
my $whitelist_content = '';
logline("debug","Creating File Object \$clamavmilter.");
my $clamavmilter = file->new({file_name => "/etc/sysconfig/clamav-milter"});
$clamavmilter->read_file;
logline("debug","Creating File Object \$clamavtemplate.");
my $clamavtemplate = file->new({file_name => "/etc/sysconfig/clamav-template"});
$clamavtemplate->read_file;
logline("debug","Creating File Object \$clamavwhitelist.");
my $clamavwhitelist = file->new({file_name => "/etc/sysconfig/clamav-whitelist"});
$clamavwhitelist->read_file;
my $quit = '';
my $noxheader = '';
my $from = '';
my $milter_on = '';
unless($input{'report_safe'}){
$quit = 'YES';
}
unless($input{'virusheader'}){
$noxheader = 'YES';
}
if($input{'virus_found_sender'}){
$from = $input{'virus_found_sender'};
}
if($input{'virusfilter'}){
$milter_on = 'YES';
}
my @clamav_milter = qq~QUIET=$quit
NOXHEADER=$noxheader
TEMPLATE=YES
WHITELIST=YES
FROM=$from
MILTER_ON=$milter_on~;
$clamavmilter->file_content(\@clamav_milter);
my $got = $clamavmilter->write_file;
if ($got) {
logline("error","clamavmilter->write_file = ".$got);
return(error($got));
}
logline("debug","virus_whitelist:\n$input{'virus_whitelist'}\n");
#my @virus_whitelist = split/(\s+|;|:|,|\t)/, $input{'virus_whitelist'};
my @virus_whitelist = split m(\r\n|;|:|,|\t+|\s+), $input{'virus_whitelist'};
foreach(@virus_whitelist){
logline("debug","wl:$_##");
}
$clamavwhitelist->file_content(\@virus_whitelist);
my $got = $clamavwhitelist->write_file;
if ($got) {
logline("error","clamavwhitelist->write_file = ".$got);
return(error($got));
}
my @clamav_template = ("Subject: $input{'virus_found_subject'}\n\n", "$input{'virus_found_text'}");
$clamavtemplate->file_content(\@clamav_template);
my $got = $clamavtemplate->write_file;
if ($got) {
logline("error","clamavtemplate->write_file = ".$got);
return(error($got));
};
}
$template->param('result' => 'L__Die Virenfilter-Voreinstellungen wurden erfolgreich geändert__L!');
$success_text = 'L__Die Virenfilter-Voreinstellungen wurden erfolgreich geändert__L!';
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_scan_antivirus{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
if($result){
}
else{
open DAT,">/tmp/scan.$$" or dienice( 'Error processing file: '.$!);
my $cgi = new CGI;
my $file = $cgi->upload("filename");
binmode $file;
binmode DAT;
my $data;
while(read $file,$data,1024) {
print DAT $data;
}
close DAT;
my $answer = `/usr/sbin/clamdscan --config-file=/etc/clamd.conf --stdout --verbose - < /tmp/scan.$$`;
my @answer = split(/\n/,$answer);
`rm -f /tmp/scan.$$`;
foreach my $item (@answer) {
$item =~ s/stream/\<STRONG\>$input{'filename'}\<\/STRONG\>/;
$item =~ s/\sOK$/\<SPAN class\=\"green\"> OK\<\/SPAN\>/;
$item =~ s/\sFOUND$/\<SPAN class\=\"red\"> FOUND\<\/SPAN\>/;
if($item =~ /^Infected files/){
$dummy = $item;
$dummy =~ s/^.*\:\s+//;
if($dummy > 0){
$item =~ s/^(.*)$/\<SPAN class\=\"red\">$1\<\/SPAN\>/;
}
else {
$item =~ s/^(.*)$/\<SPAN class\=\"green\">$1\<\/SPAN\>/;
}
}
$result .= "$item<br />";
}
}
$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_new_cronjob{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_new_cronjob result:$result###");
if($result){
}
else{
my %handle_hash = %{easytecc3::return_file_handler_store()};
my $cronfile = $handle_hash{'/home/web/cronfile'};
my $new_cronjob = '';
my %form_to_cron = %{easytecc3::form_to_cron()};
$input{'min'} = $form_to_cron{$input{'min'}} unless $input{'min'} =~ /^\d+$/;
$input{'std'} = $form_to_cron{$input{'std'}} unless $input{'std'} =~ /^\d+$/;
$input{'mday'} = $form_to_cron{$input{'mday'}} unless $input{'mday'} =~ /^\d+$/;
$input{'mon'} = $form_to_cron{$input{'mon'}} unless $input{'mon'} =~ /^\d+$/;
$input{'wday'} = $form_to_cron{$input{'wday'}} unless $input{'wday'} =~ /^\d+$/;
if($fb){
$input{'command'} =~ s#/apache24/noexec/#/apache24/data/#;
}
push @{$cronfile->file_content}, qq~$input{'min'} $input{'std'} $input{'mday'} $input{'mon'} $input{'wday'} $input{'command'}\n~;
logline("debug",qq~cronjob modifiziert:$input{'min'} $input{'std'} $input{'mday'} $input{'mon'} $input{'wday'} $input{'command'}~);
$new_cronjob = qq~$input{'min'} $input{'std'} $input{'mday'} $input{'mon'} $input{'wday'} $input{'command'}\n~;
my $got = $cronfile->write_file;
if ($got) {
logline("error","cronfile->write_file = ".$got);
return(error($got));
}
$result = qq~L__Der cronjob wurde erfolgreich angelegt__L~;
$success_text = qq~L__Der cronjob wurde erfolgreich angelegt__L~;
}
$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_cronjobs&success_text=' . encode_base64url($success_text);
return(\$template);
}
sub exec_auto_cronjob{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
my $cronjob = '';
logline("debug","exec_auto_cronjob result:$result###");
if($result){
$template->param('result' => $result);
}
else{
my %handle_hash = %{easytecc3::return_file_handler_store()};
my $cronfile = $handle_hash{'/home/web/cronfile'};
if($input{'type'} eq 'delete_all_logs'){
$cronjob = qq~05 01 * * * /usr/sbin/dellogs -a~ unless $fb;
$cronjob = qq~05 01 * * * /usr/iports/bin/sudo /usr/sbin/dellogs -a~ if $fb;
}
elsif($input{'type'} eq 'delete_admin_email'){
if(easytecc3::extern_mx()){
my $socket = easytecc3::make_socket();
logline("debug","nach make_socket() = $socket");
print $socket "cron_delete_admin_email=\n";
}
if ($fb) {
#my $servername = `grep -m1 han-solo.net /etc/hosts | awk '{print \$2}'`;
my $servername = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
chomp $servername;
my $dir = '/home/admin@' . $servername . '/mail/*';
$cronjob = qq~05 01 * * * rm -rf $dir~;
logline("debug","dir=$dir");
}
else{
$cronjob = qq~05 01 * * * rm -rf /root/mail/*~;
}
}
push @{$cronfile->file_content}, qq~$cronjob\n~;
my $got = $cronfile->write_file;
return(error($got)) if $got;
$result = qq~L__Der cronjob wurde erfolgreich angelegt__L~;
$success_text = qq~L__Der cronjob wurde erfolgreich angelegt__L~;
}
$template->param('result' => $result);
logline("debug","result = " . $result);
#if($input{'type'} eq 'delete_all_logs'){
#$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_logfiles&success_text=' . encode_base64url($success_text);
#}
#else{
#$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=start&success_text=' . encode_base64url($success_text);
#}
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_cronjobs&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_delete_cronjob{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
my $deleted_cronjob = '';
logline("debug","exec_delete_cronjob result:$result###");
if($result){
}
else{
my %handle_hash = %{easytecc3::return_file_handler_store()};
my $cronfile = $handle_hash{'/home/web/cronfile'};
my $count = '';
my @new_cronfile = ();
foreach($cronfile->file_content){
$count++ unless /^#/ || /^$/;
logline("debug","content cronfile $count:$_");
s/\s+$//;
#cronjob löschen
if ($input{'cronjob'} == $count && ! /^#/ || /^$/){
$deleted_cronjob = $_;
logline("debug","cronjob löschen:$_");
next;
}
# alles andere in zu schreibendes cronfile
push @new_cronfile, $_;
}
$cronfile->file_content(\@new_cronfile);
my $got = $cronfile->write_file;
if ($got) {
logline("error","cronfile->write_file = ".$got);
return(error($got));
}
# change note key
my $old_cron_key = $input{'cron_key'};
my @old_keys = ('CRONJOB',$old_cron_key);
my $note = note_from_hashfile(\@old_keys);
if($note->{title}){
note_to_hashfile(\@old_keys,'','');
}
my $cronjob_string_no_dev_null = encode('utf-8',$deleted_cronjob);
$cronjob_string_no_dev_null =~ s/(1|2)*\s*>\s*\/dev\/null//;
$cronjob_string_no_dev_null =~ s/(1|2)\s*>\s*&(1|2)//;
$result = qq~cronjob $cronjob_string_no_dev_null L__wurde erfolgreich gelöscht__L~;
$success_text = qq~cronjob $cronjob_string_no_dev_null L__wurde erfolgreich gelöscht__L~;
}
$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_cronjobs&success_text=' . encode_base64url($success_text);
return(\$template);
}
sub exec_change_cronjob{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_delete_cronjob result:$result###");
if($result){
}
else{
my %handle_hash = %{easytecc3::return_file_handler_store()};
my $cronfile = $handle_hash{'/home/web/cronfile'};
my $count = '';
my @new_cronfile = ();
my $modified_cronjob = '';
my %form_to_cron = %{easytecc3::form_to_cron()};
foreach($cronfile->file_content){
$count++ unless /^#/ || /^$/;
logline("debug","content cronfile $count:$_");
s/\s+$//;
#cronjob modifizieren
if ($input{'cronjob'} == $count && ! /^#/ || /^$/){
$input{'min'} = $form_to_cron{$input{'min'}} unless $input{'min'} =~ /^\d+$/;
$input{'std'} = $form_to_cron{$input{'std'}} unless $input{'std'} =~ /^\d+$/;
$input{'mday'} = $form_to_cron{$input{'mday'}} unless $input{'mday'} =~ /^\d+$/;
$input{'mon'} = $form_to_cron{$input{'mon'}} unless $input{'mon'} =~ /^\d+$/;
$input{'wday'} = $form_to_cron{$input{'wday'}} unless $input{'wday'} =~ /^\d+$/;
# change note key
my $old_cron_key = $input{'cron_key'};
my @old_keys = ('CRONJOB',$old_cron_key);
# new key
my $cron_key = encode_base64url(encode('utf-8',$input{'command'}) . $input{'min'} . $input{'std'} . $input{'mday'} . $input{'mon'} . $input{'wday'});
my @keys = ('CRONJOB',$cron_key);
my $note = note_from_hashfile(\@old_keys);
if($note->{title}){
note_to_hashfile(\@keys,decode('utf-8',$note->{title}),decode('utf-8',$note->{text}));
note_to_hashfile(\@old_keys,'','');
}
push @new_cronfile, qq~$input{'min'} $input{'std'} $input{'mday'} $input{'mon'} $input{'wday'} $input{'command'}\n~;
logline("debug",qq~cronjob modifiziert:$input{'min'} $input{'std'} $input{'mday'} $input{'mon'} $input{'wday'} $input{'command'}~);
$modified_cronjob = qq~$input{'min'} $input{'std'} $input{'mday'} $input{'mon'} $input{'wday'} $input{'command'}\n~;
next;
}
# alles andere in zu schreibendes cronfile
push @new_cronfile, $_;
}
$cronfile->file_content(\@new_cronfile);
my $got = $cronfile->write_file;
if ($got) {
logline("error","cronfile->write_file = ".$got);
return(error($got));
}
$result = qq~L__Der cronjob wurde erfolgreich modifiziert__L~;
$success_text = qq~L__Der cronjob wurde erfolgreich modifiziert__L~;
}
$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_cronjobs&success_text=' . encode_base64url($success_text);
return(\$template);
}
sub exec_change_errordocs{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_change_errordocs result:$result###");
if($result){
}
else{
if (! -e "$droot_prefix/error_docs" ) {
`mkdir $droot_prefix/error_docs`;
}
logline("debug","Creating File Object $droot_prefix/error_docs/unauthorized.htm.");
my $errordoc = file->new({file_name => "$droot_prefix/error_docs/unauthorized.htm"});
my @new_errordoc = qq~$input{'unauthorized'}~;
$errordoc->file_content(\@new_errordoc);
my $got = $errordoc->write_file;
if ($got) {
logline("error","$droot_prefix/error_docs/unauthorized.htm->write_file = ".$got);
return(error($got));
}
logline("debug","Creating File Object $droot_prefix/error_docs/forbidden.htm.");
$errordoc = file->new({file_name => "$droot_prefix/error_docs/forbidden.htm"});
@new_errordoc = qq~$input{'forbidden'}~;
$errordoc->file_content(\@new_errordoc);
$got = $errordoc->write_file;
if ($got) {
logline("error","$droot_prefix/error_docs/forbidden.htm->write_file = ".$got);
return(error($got));
}
logline("debug","Creating File Object $droot_prefix/error_docs/notfound.htm.");
$errordoc = file->new({file_name => "$droot_prefix/error_docs/notfound.htm"});
@new_errordoc = qq~$input{'notfound'}~;
$errordoc->file_content(\@new_errordoc);
$got = $errordoc->write_file;
if ($got) {
logline("error","$droot_prefix/error_docs/notfound.htm->write_file = ".$got);
return(error($got));
}
logline("debug","Creating File Object $droot_prefix/error_docs/ierror.htm.");
$errordoc = file->new({file_name => "$droot_prefix/error_docs/ierror.htm"});
@new_errordoc = qq~$input{'ierror'}~;
$errordoc->file_content(\@new_errordoc);
$got = $errordoc->write_file;
if ($got) {
logline("error","$droot_prefix/error_docs/ierror.htm->write_file = ".$got);
return(error($got));
}
}
#$template->param('result' => 'L__Die error-docs wurden erfolgreich geändert__L!');
$success_text = 'L__Die error-docs wurden erfolgreich geändert__L!';
undef %input;
$input{'action'} = 'change_errordocs';
logline("debug","<<< Leaving ".(caller(0))[3]."().");
change_errordocs();
#return(\$template);
}
sub exec_new_htaccess{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_new_htaccess result: $result###");
if($result){
}
else{
my $directory = $input{'dir'};
$directory = $droot_prefix . '/' . $directory;
# if($fb){
# $directory = $droot_prefix . '/' . $directory if $directory !~ /\/usr\/local\/www\/apache24\/noexec/;
# } else {
# $directory = $droot_prefix . '/' . $directory if $directory !~ /\/home\/httpd\/docs/;
# }
my $username = $input{'htaccessuser'};
my $password = $input{'htaccesspass'};
my ($fileperm, $fileuid, $filegid) = (stat($directory))[2,4,5];
$fileperm = sprintf "%lo", ($fileperm & 07777);
# evtl. ist da schon eine .htaccess mit rewrite-Regeln o..
# Passwortschutz anhängen um vorhandene Inhalte nicht zu löschen
my $new_file_content = qq~#####EASYTECC GENERATED, DO NOT EDIT#####
AuthUserFile $directory/.htpasswd
AuthGroupFile $directory/.htgroup
AuthName \"login\"
AuthType Basic
<Limit POST GET>
require group $username
</Limit>
#####END EASYTECC GENERATED#####~;
if ( ! -f "$directory/.htaccess" || ! -f "$directory/.htgroup" || ! -f "$directory/.htpasswd" ){
# open dir
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl $fileuid:vuser $directory 2>&1`;
return(error("L__Fehler beim Setzen des Besitzers für__L $directory: $got")) if $got;
$got = `/usr/iports/bin/sudo /usr/sbin/chmod.pl 775 $directory 2>&1`;
return(error("L__Fehler beim Setzen der Berechtigungen für__L $directory: $got")) if $got;
if ( ! -f "$directory/.htaccess" ){
system "touch","$directory/.htaccess";
}
if ( ! -f "$directory/.htgroup" ){
system "touch","$directory/.htgroup";
}
if ( ! -f "$directory/.htpasswd" ){
system "touch","$directory/.htpasswd";
}
# close dir
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl $fileuid:$filegid $directory 2>&1`;
return(error("L__Fehler beim Setzen des Besitzers für__L $directory: $got")) if $got;
$got = `/usr/iports/bin/sudo /usr/sbin/chmod.pl $fileperm $directory 2>&1`;
return(error("L__Fehler beim Setzen der Berechtigungen für__L $directory: $got")) if $got;
}
logline("debug","Creating File Object $directory/.htaccess.");
my $file = file->new({file_name => "$directory/.htaccess", append => '1', file_content => [$new_file_content]});
my $got = $file->write_file;
if ($got) {
logline("error","$directory/.htaccess->write_file = ".$got);
return(error($got));
}
##jetzt auf den richtigen User und richtige chmod
#system "/usr/bin/chown", "$fileuid"."."."$filegid", "$directory/.htaccess";
#system "chmod", "664", "$directory/.htaccess";
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl $fileuid:$filegid $directory/.htaccess 2>&1`;
$got = `/usr/iports/bin/sudo /usr/sbin/chmod.pl 664 $directory/.htaccess 2>&1`;
logline("debug","Creating File Object $directory/.htgroup.");
$file = file->new({file_name => "$directory/.htgroup", file_content => ["$username: $username"]});
my $got = $file->write_file;
if ($got) {
logline("error","$directory/.htgroup->write_file = ".$got);
return(error($got));
}
##jetzt auf den richtigen User und richtige chmod
#system "/usr/bin/chown", "$fileuid"."."."$filegid", "$directory/.htgroup";
#system "chmod", "664", "$directory/.htgroup";
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl $fileuid:$filegid $directory/.htgroup 2>&1`;
$got = `/usr/iports/bin/sudo /usr/sbin/chmod.pl 664 $directory/.htgroup 2>&1`;
my $content = '';
if($fb){
$content = `/usr/iports/bin/htpasswd -nb "$username" "$password" 2>/dev/null`;
}
# fallback
if(!length($content)){
$content = $username . ':' . easytecc3::encrypt_htpasswd($password);
}
logline("debug","Creating File Object $directory/.htpasswd.");
$file = file->new({file_name => "$directory/.htpasswd", file_content => ["$content"]});
my $got = $file->write_file;
if ($got) {
logline("error","$directory/.htpasswd->write_file = ".$got);
return(error($got));
}
# jetzt auf den richtigen User und richtige chmod
#system "/usr/bin/chown", "$fileuid"."."."$filegid", "$directory/.htpasswd";
#system "chmod", "664", "$directory/.htpasswd";
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl $fileuid:$filegid $directory/.htpasswd 2>&1`;
$got = `/usr/iports/bin/sudo /usr/sbin/chmod.pl 664 $directory/.htpasswd 2>&1`;
}
$success_text = 'L__Die .htaccess-Einstellungen wurden erfolgreich angelegt__L!';
my $dir_encoded = encode_base64url($input{'dir'});
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_filemanager&dir=' . $dir_encoded . '&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_delete_htaccess{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_delete_htaccess result:$result###");
if($result){
}
else{
my $directory = $droot_prefix . '/' . $input{'dir'};
my $custom_htaccess = '';
# user kann entweder durch Eingabefeld oder selectbox übermittelt werden
my $username = $input{'htaccessuser'};
# in .htaccess gucken, ob eigene Eintrge vorhanden und Passwortschutz ggf. nur ausschneiden:
# #####EASYTECC GENERATED, DO NOT EDIT#####
# AuthUserFile /home/httpd/docs/dav/.htpasswd
# AuthGroupFile /home/httpd/docs/dav/.htgroup
# AuthName "/home/httpd/docs/dav"
# AuthType Basic
# <Limit POST GET>
# require group rrr
# </Limit>
# #####END EASYTECC GENERATED#####
open(HTACCESS,"$directory/.htaccess") || return(error("L__Fehler beim Lesen von__L $directory/.htaccess:", "$!"));
my @htaccess = ();
while(<HTACCESS>){
push @htaccess, $_;
}
close(HTPASSWD);
$custom_htaccess = '1' if $#htaccess > '10';
if($input{'type'} eq 'delete_user'){
open(HTPASSWD,"$directory/.htpasswd") || return(error("L__Fehler beim Lesen von__L $directory/.htpasswd:", "$!"));
my @data = ();
while(<HTPASSWD>){
next if (/^$/);
push @data, $_;
}
close(HTPASSWD);
#wenn nur ein User vorhanden dann ganzen Passwortschutz weghauen
if(scalar @data <= 1){
my $got = `$easytecc_prefix/rm.pl "$directory/.htpasswd"` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/rm.pl "$directory/.htpasswd"` if $fb;
return(error("L__Fehler beim Entfernen von__L $htpasswd: $got")) if $got;
#system "rm", "-f", "$directory/.htpasswd" || return(error("L__Fehler beim Entfernen von__L $htpasswd:", "$!"));
$got = `$easytecc_prefix/rm.pl "$directory/.htgroup"` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/rm.pl "$directory/.htgroup"` if $fb;
return(error("L__Fehler beim Entfernen von__L $htgroup: $got")) if $got;
#system "rm", "-f", "$directory/.htgroup" || return(error("L__Fehler beim Entfernen von__L $htgroup:", "$!"));
if($custom_htaccess){
my @new_file_content;
logline("debug","Creating File Object $directory/.htaccess.");
my $file = file->new({file_name => "$directory/.htaccess", file_content => \@new_file_content});
my $remove = '';
foreach(@htaccess){
$remove = '1' if(/#####EASYTECC GENERATED/);
push @new_file_content, $_ unless $remove;
$remove = '' if(/#####END EASYTECC GENERATED/);
}
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 666 $directory/.htaccess 2>&1`;
my $got = $file->write_file;
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 664 $directory/.htaccess 2>&1`;
if ($got) {
logline("error","$directory/.htaccess->write_file = ".$got);
return(error($got));
}
}
else{
my $got = `$easytecc_prefix/rm.pl "$directory/.htaccess"` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/rm.pl "$directory/.htaccess"` if $fb;
return(error("L__Fehler beim Entfernen von__L $htaccess: $got")) if $got;
#system "rm", "-f", "$directory/.htaccess" || return(error("L__Fehler beim Entfernen von__L $htaccess:", "$!"));
}
}
else{
my @new_file_content;
logline("debug","Creating File Object $directory/.htpasswd.");
my $file = file->new({file_name => "$directory/.htpasswd", file_content => \@new_file_content});
foreach(@data){
next if (/^$username:/);
push @new_file_content, $_;
}
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 666 $directory/.htpasswd 2>&1`;
my $got = $file->write_file;
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 664 $directory/.htpasswd 2>&1`;
if ($got) {
logline("error","$directory/.htpasswd->write_file = ".$got);
return(error($got));
}
open(HTGROUP,"$directory/.htgroup") || return(error("L__Fehler beim Lesen von__L $directory/.htgroup:", "$!"));
@data = <HTGROUP>;
close(HTGROUP);
if ($data[0] =~ /$username/) { $data[0] =~ s/$username //g || $data[0] =~ s/ $username//g; }
logline("debug","Creating File Object $directory/.htgroup.");
$file = file->new({file_name => "$directory/.htgroup", file_content => [$data[0]]});
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 666 $directory/.htgroup 2>&1`;
my $got = $file->write_file;
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 664 $directory/.htgroup 2>&1`;
if ($got) {
logline("error","$directory/.htgroup->write_file = ".$got);
return(error($got));
}
}
}
elsif($input{'type'} eq 'delete_all'){
my $got = `$easytecc_prefix/rm.pl "$directory/.htpasswd"` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/rm.pl "$directory/.htpasswd"` if $fb;
return(error("L__Fehler beim Entfernen von__L $htpasswd: $got")) if $got;
#system "rm", "-f", "$directory/.htpasswd" || return(error("L__Fehler beim Entfernen von__L $htpasswd:", "$!"));
$got = `$easytecc_prefix/rm.pl "$directory/.htgroup"` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/rm.pl "$directory/.htgroup"` if $fb;
return(error("L__Fehler beim Entfernen von__L $htgroup: $got")) if $got;
#system "rm", "-f", "$directory/.htgroup" || return(error("L__Fehler beim Entfernen von__L $htgroup:", "$!"));
if($custom_htaccess){
my @new_file_content;
logline("debug","Creating File Object $directory/.htaccess.");
my $file = file->new({file_name => "$directory/.htaccess", file_content => \@new_file_content});
my $remove = '';
foreach(@htaccess){
$remove = '1' if(/#####EASYTECC GENERATED/);
push @new_file_content, $_ unless $remove;
$remove = '' if(/#####END EASYTECC GENERATED/);
}
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 666 $directory/.htaccess 2>&1`;
my $got = $file->write_file;
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 664 $directory/.htaccess 2>&1`;
if ($got) {
logline("error","$directory/.htaccess->write_file = ".$got);
return(error($got));
}
}
else{
my $got = `$easytecc_prefix/rm.pl "$directory/.htaccess"` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/rm.pl "$directory/.htaccess"` if $fb;
return(error("L__Fehler beim Entfernen von__L $htaccess: $got")) if $got;
#system "rm", "-f", "$directory/.htaccess" || return(error("L__Fehler beim Entfernen von__L $htaccess:", "$!"));
}
}
}
$success_text = 'L__Die .htaccess-Einstellungen wurden erfolgreich gelöscht__L!';
my $dir_encoded = encode_base64url($input{'dir'});
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_filemanager&dir=' . $dir_encoded . '&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_change_htaccess{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_change_htaccess result:$result###");
if($result){
}
else{
my $directory = $droot_prefix . '/' . $input{'dir'};
if($input{'type'} eq 'newuser'){
my $username = $input{'htaccessuser_newuser'};
my $password = $input{'htaccesspass_newuser'};
logline("debug","Creating File Object $directory/.htgroup");
my $file = file->new({file_name => "$directory/.htgroup"});
$file->read_file;
#chomp ist gaaanz wichtig, da die user nebeneinander stehen. Der neue User landet am Ende der Zeile
#ohne chomp würde er in neue Zeile eingefügt werden
chomp ${$file->file_content}[0];
${$file->file_content}[0] .= qq~ $username~;
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 666 $directory/.htgroup 2>&1`;
my $got = $file->write_file;
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 664 $directory/.htgroup 2>&1`;
if ($got) {
logline("error","$directory/.htgroup->write_file = ".$got);
return(error($got));
}
my $encrypted = easytecc3::encrypt_htpasswd($password);
logline("debug","Creating File Object $directory/.htpasswd");
$file = file->new({file_name => "$directory/.htpasswd", append => '1', file_content => [qq~$username:$encrypted~]});
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 666 $directory/.htpasswd 2>&1`;
my $got = $file->write_file;
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 664 $directory/.htpasswd 2>&1`;
if ($got) {
logline("error","$directory/.htpasswd->write_file = ".$got);
return(error($got));
}
}
elsif($input{'type'} eq 'changepass'){
my $username = $input{'user_select'};
my $password = $input{'htaccesspass_changepass'};
open(HTPASSWD,"$directory/.htpasswd") || return(error("L__Fehler beim Lesen von__L $directory/.htpasswd:", "$!"));
my @data = <HTPASSWD>;
close(HTPASSWD);
my $encrypted = easytecc3::encrypt_htpasswd($password);
for (my $i=0; $i<=$#data; $i++) { if ($data[$i] =~ /^$username:/) { $data[$i] = "$username:$encrypted"; } }
logline("debug","Creating File Object $directory/.htpasswd");
$file = file->new({file_name => "$directory/.htpasswd", file_content => \@data});
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 666 $directory/.htpasswd 2>&1`;
my $got = $file->write_file;
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 664 $directory/.htpasswd 2>&1`;
if ($got) {
logline("error","$directory/.htpasswd->write_file = ".$got);
return(error($got));
}
}
}
$success_text = 'L__Die .htaccess-Einstellungen wurden erfolgreich geändert__L!';
my $dir_encoded = encode_base64url($input{'dir'});
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_filemanager&dir=' . $dir_encoded . '&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_new_frontpage{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_new_frontpage result:$result###");
if($result){
}
else{
# neues Frontpageweb anlegen
if($input{'with_old_frontpage_form'}){
# ggf. altes FP-Web löschen und dann erst neues anlegen
if($input{'delete_old_frontpage'}){
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my $document_root = $domains{$input{'domain_select'}}{'droot'};
my $out = `$easytecc_prefix/delete_frontpage.pl $document_root`;
return(error("L__Das Frontpage-Web konnte nicht gelöscht werden__L: $out")) if $out;
}
# fpinstall -u eee -p eee -d easytecc.at
# das www. vom Domainnamen weg, weil FP sonst für www.www angelegt wird
# $input{'domain_select'} ist immer Servername des vhosts in httpd.conf um eindeutige Zuordnung zu haben
my $domain_ohne_www = $input{'domain_select'};
$domain_ohne_www =~ s/^www\.//;
my $got = `/usr/sbin/fpinstall -u $input{'frontpageuser'} -p $input{'password'} -d $domain_ohne_www`;
if($got =~ /Install completed/){
$result = qq~$domain_ohne_www: L__Das Frontpageweb wurde erfolgreich angelegt__L~;
}
else{
my @got = split /\n/, $got;
my $fp_error = '';
foreach(@got){
$fp_error .= $_ . '<br />';
}
return(error($fp_error));
}
}
else{
# erstmaliger Aufruf von exec_new_frontpage
# erstmal gucken ob noch Reste von alter Installation, wenn ja dann wieder zu new_frontpage mit Option
# die Reste zu löschen
# aus httpd.conf das Document root ziehen und da gucken, ob was da
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my $document_root = $domains{$input{'domain_select'}}{'droot'};
logline("debug","exec_new_frontpage droot:$document_root");
if( -d "$document_root/_private/" ||
-d "$document_root/_vti_bin/" ||
-d "$document_root/_vti_cnf/" ||
-d "$document_root/_vti_log/" ||
-d "$document_root/_vti_pvt/" ||
-d "$document_root/_vti_txt/" )
{
return(new_frontpage());
}
else{
# neues Frontpageweb anlegen
# fpinstall -u eee -p eee -d easytecc.at
# das www. vom Domainnamen weg, weil FP sonst für www.www angelegt wird
# $input{'domain_select'} ist immer Servername des vhosts in httpd.conf um eindeutige Zuordnung zu haben
my $domain_ohne_www = $input{'domain_select'};
$domain_ohne_www =~ s/^www\.//;
my $got = `/usr/sbin/fpinstall -u $input{'frontpageuser'} -p $input{'password'} -d $domain_ohne_www`;
if($got =~ /Install completed/){
$result = qq~$domain_ohne_www: L__Das Frontpageweb wurde erfolgreich angelegt__L~;
}
else{
my @got = split /\n/, $got;
my $fp_error = '';
foreach(@got){
$fp_error .= $_ . '<br />';
}
return(error($fp_error));
}
}
}
}
$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_delete_frontpage{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_new_frontpage result:$result###");
if($result){
}
else{
# fpuninstall -d easytecc.at
# das www. vom Domainnamen weg
# $input{'domain_select'} ist immer Servername des vhosts in httpd.conf um eindeutige Zuordnung zu haben
my $domain_ohne_www = $input{'domain'};
$domain_ohne_www =~ s/^www\.//;
my $got = `/usr/sbin/fpuninstall -d $domain_ohne_www`;
if($got =~ /Uninstall completed/){
$result = qq~$domain_ohne_www: L__Das Frontpageweb wurde erfolgreich gelöscht__L~;
}
else{
my @got = split /\n/, $got;
my $fp_error = '';
foreach(@got){
$fp_error .= $_ . '<br />';
}
return(error($fp_error));
}
if($input{'delete_old_frontpage'}){
logline("debug","exec_delete_frontpage altes web löschen");
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my $document_root = $domains{$input{'domain'}}{'droot'};
my $out = `$easytecc_prefix/delete_frontpage.pl $document_root`;
return(error("L__Das Frontpage-Web konnte nicht gelöscht werden__L: $out")) if $out;
}
}
$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_delete_logfiles{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $logfile = $input{'logfile'};
my $domain = $input{'domain'};
# Log einzelner Domain löschen
if($domain){
`/usr/sbin/dellogs -d $domain` unless $fb;
`/usr/iports/bin/sudo /usr/sbin/dellogs -d $domain` if $fb;
}
# Logs aller Domains löschen
elsif($logfile eq 'alldomains'){
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
foreach(keys %domains){
if($domains{$_}{'access_log'}){
`cat /dev/null > $domains{$_}{'access_log'}`;
}
if($domains{$_}{'error_log'}){
`cat /dev/null > $domains{$_}{'error_log'}`;
}
}
}
# alle Systemlogs löschen
elsif($logfile eq 'allsystem'){
`/usr/sbin/admlogs` unless $fb;
`/usr/iports/bin/sudo /usr/sbin/dellogs -a` if $fb;
}
# alle Logs löschen
elsif($logfile eq 'all'){
`/usr/sbin/dellogs -a` unless $fb;
`/usr/iports/bin/sudo /usr/sbin/dellogs -a` if $fb;
}
$result = 'L__Die Logs wurden gelöscht__L';
$success_text = 'L__Die Logs wurden gelöscht__L';
$template->param('result' => $result);
logline("debug","result = " . $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_logfiles&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_delete_mysqlbackup{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
#my $template = HTML::Template->new(filename => 'result.html');
my $database = $input{'database'};
my $backup = $input{'backup'};
my $result = $validation_result;
logline("debug","exec_delete_mysqlbackup result: $result###");
if($result){
#$template->param('result' => $result);
}
else{
if ($fb) {
`/usr/iports/bin/sudo /usr/sbin/rm.pl $mysqlbackup_dir/$database/$backup`;
`/usr/iports/bin/sudo /usr/sbin/rm.pl $mysqlbackup_dir/$database/$backup.error` if ($input{'has_error'});
}
else{
`rm -f $mysqlbackup_dir/$database/$backup`;
`rm -f $mysqlbackup_dir/$database/$backup.error` if ($input{'has_error'});
}
$success_text = "$backup: L__Das Datenbankbackup wurde erfolgreich gelöscht__L";
}
my $html_tmp = $success_text;
my $template = HTML::Template->new(scalarref => \$html_tmp);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
#return(show_mysqlbackup_details());
#$json_output{'ajax_html'} = 'success';
$json_output{'success_message'} = '1';
return(\$template);
}
sub exec_change_mysqlbackup{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_change_mysqlbackup result:$result###");
if($result){
}
# neue mysql-Backup-Konfigurationsdatei schreiben:
# $database='ajaxfb';
# $backup_days='5';
# $email_backup='yes';
# $admin_email_to='frank@krusator.de';
# $admin_email_from='dbadmin@krusator.de';
else{
if ($input{'backup_days'} eq '0' || ! length($input{'backup_days'})) {
return(exec_delete_mysql_auto_backup());
}
my @databases;
if($session->param('user') eq 'admin' && $input{'all_databases'}){
logline("debug","instant_mysqlbackup:1");
my ($dbh, $mysql_connect_error) = easytecc3::mysql_connect();
if ($mysql_connect_error == '1'){
return(add_mysql_password());
}
my $sth = $dbh->prepare('SHOW DATABASES');
$sth->execute;
logline("debug","instant_mysqlbackup:2");
while ( my @row = $sth->fetchrow_array ){ # alle rows auslesen
foreach my $item (@row){
next if $item eq 'information_schema';
push(@databases, $item);
logline("debug","instant_mysqlbackup:$item");
}
}
} else {
push(@databases, $input{'database'});
}
foreach $database(@databases){
my $conf = qq~\$database='$database';
\$backup_days='$input{'backup_days'}';
\$email_backup='$input{'email_backup'}';
\$admin_email_from='$input{'admin_email_from'}';
\$admin_email_to='$input{'admin_email_to'}';\n~;
logline("debug","Creating File Object /usr/local/etc/easytecc/mysqlbackup/$database.dbb");
my $file = file->new({file_name => "/usr/local/etc/easytecc/mysqlbackup/$database.dbb", file_content => [qq~$conf~]});
my $got = $file->write_file;
if ($got) {
logline("error","/usr/local/etc/easytecc/mysqlbackup/$database.dbb->write_file = ".$got);
return(error($got));
}
#
#unless(`grep dobackup.pl /home/web/cronfile`){
# logline("debug","Creating File Object \$cronfile.");
# my $cronfile = file->new({file_name => '/home/web/cronfile'});
# $cronfile->read_file;
# my $min = int(rand('59'));
# my $std = int(rand('1'));
# push @{$cronfile->file_content}, qq~$min $std * * * $easytecc_prefix/dobackup.pl -a 1>/dev/null 2>/dev/null\n~;
# my $got = $cronfile->write_file;
# if ($got) {
# logline("error","cronfile->write_file = ".$got);
# return(error($got));
# }
#}
add_dobackup_cron();
}
$result = 'L__Das automatische Backup wurde erfolgreich angelegt__L<br />' .
qq~<a href="/cgi-bin/easytecc3/index.pl?action=show_mysqlbackup_details&database=$input{'database'}">L__Zurück zu Datenbankbackupdetails__L</a>~;
$success_text = 'L__Das automatische Backup wurde erfolgreich angelegt__L';
}
#$template->param('result' => $result);
logline("debug","result = " . $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_dbbackup' . '&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub add_dobackup_cron{
unless(`grep dobackup.pl /home/web/cronfile`){
logline("debug","Creating File Object \$cronfile.");
my $cronfile = file->new({file_name => '/home/web/cronfile'});
$cronfile->read_file;
my $min = int(rand('59'));
my $std = int(rand('1'));
push @{$cronfile->file_content}, qq~$min $std * * * $easytecc_prefix/dobackup.pl -a 1>/dev/null 2>/dev/null\n~;
my $got = $cronfile->write_file;
if ($got) {
logline("error","cronfile->write_file = ".$got);
return(error($got));
}
}
}
sub exec_new_mysqluser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
#my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_new_mysqluser result: $result###");
if($result){
}
else{
if($input{'db'}){
$error = easytecc3::add_mysqldb(\%input);
return(error("L__Konnte Datenbank nicht anlegen__L: $error")) if $error;
$result .= "<br />L__Die Datenbank wurde erfolgreich angelegt__L";
$success_text = "L__Die Datenbank wurde erfolgreich angelegt__L";
}
$error = easytecc3::add_mysqluser(\%input);
return(error("L__Konnte mySQL-User nicht anlegen__L: $error")) if $error;
$result .= '<br />L__Der mysqluser wurde erfolgreich angelegt__L';
$success_text2 = 'L__Der mysqluser wurde erfolgreich angelegt__L';
}
#$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
undef %input;
$input{'active_tab'} = '2';
show_dbbackup();
#return(\$template);
}
sub exec_domainsearch{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'whois_result.html');
my $result = $validation_result;
logline("debug","exec_domainsearch result: $result###");
if($result){
}
else{
my $cgi = new CGI;
my $ua = LWP::UserAgent->new();
my $anf = HTTP::Request->new();
my ($names,$i);
my (@names) = $cgi->param;
$anf->method('POST');
$anf->uri('http://83.138.67.7/cgi-bin/library/iwhois/elookup_easytecc3.pl');
foreach $names(@names){
$anf->header($names[$i] => $cgi->param($names[$i]));
$i++;
}
my $response = $ua->request($anf);
if($response->is_success){
$result = $response->content;
}
else{
$result = 'L__Die Domainabfrage ist z.Z. nicht erreichbar__L';
}
$template->param('whois_result' => decode(utf8, $result));
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub get_files {
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $dir = $input{'dir'};
$dir =~ s#^$droot_prefix/?##;
#if($dir eq $droot_prefix){
# $dir = '';
#}
my @allfiles = ();
my @directories = ();
my @files = ();
my $allowed_primary = 1;
my $allowed_expanded = 1;
# gather allowed dirs
my %allowed_dirs;
my %allowed_dirs_expanded;
if($session->param('user') ne 'admin'){
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
foreach my $domain (keys %domains){
my $admins = $domains{$domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $session->param('user') . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
$allowed_dirs{$domains{$domain}{'droot'}} = '1';
logline("debug","allowed dir: $domains{$domain}{'droot'}");
}
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
$allowed_dirs{$passwd{$session->param('user')}{'home'}} = '1';
logline("debug","allowed dir: $passwd{$session->param('user')}{'home'}");
foreach my $allowed_dir (keys %allowed_dirs){
$allowed_dir =~ s/\/data\//\/noexec\//;
if($allowed_dir =~ m#^$droot_prefix/?#){
$allowed_dirs_expanded{$allowed_dir} = 1;
$allowed_dir =~ s#^$droot_prefix/?##;
my @subdirs = split(/\//,$allowed_dir);
$allowed_dir = $droot_prefix;
foreach my $subdir (@subdirs){
$allowed_dir .= '/' . $subdir;
$allowed_dirs_expanded{$allowed_dir} = 1;
}
}
}
logline("debug","allowed dirs:" . Data::Dumper->Dump([\%allowed_dirs]));
logline("debug","allowed dirs:" . Data::Dumper->Dump([\%allowed_dirs_expanded]));
if(length($dir)){
my $path = $droot_prefix . '/' . $dir;
$allowed_primary = exists($allowed_dirs{$path});
if(!$allowed_primary){
foreach my $allowed_dir (keys %allowed_dirs){
if($path =~ m#^$allowed_dir/.+#){
$allowed_primary = 1;
last;
}
}
}
$allowed_expanded = exists($allowed_dirs_expanded{$path}) || $allowed_primary;
} else {
$allowed_primary = 0;
}
}
my $chdir = $droot_prefix . '/' . $dir;
#if($input{'dir'} !~ m#/snapshots/#){
#
# $chdir = $droot_prefix . '/' . $dir;
#
#} else {
#
# $chdir = $dir;
#
#}
if($allowed_expanded){
opendir (DIR, $chdir) || dienice("opendir $chdir: $!");
@allfiles = readdir(DIR);
closedir (DIR);
}
foreach (@allfiles) {
if(-d "$chdir/$_"){
next if /^\.$/;
logline("debug","directory=$_");
if($session->param('user') ne 'admin' && $_ ne '..'){
my $path = $droot_prefix;
if(length($dir)){
$path .= '/' . $dir;
}
$path .= '/' . $_;
if(
exists($allowed_dirs{$path}) ||
exists($allowed_dirs_expanded{$path})
){
push(@directories, $_);
logline("debug","path=$path dir=$dir\n");
} else {
foreach my $allowed_dir (keys %allowed_dirs){
if($path =~ m#^$allowed_dir/.+#){
push(@directories, $_);
logline("debug","path=$path dir=$dir\n");
last;
}
}
}
} else {
push(@directories, $_);
}
}
else{
logline("debug","file=$_");
if($session->param('user') eq 'admin' || $allowed_primary){
push(@files,$_);
}
}
}
@directories = sort { lc($a) cmp lc($b) } @directories;
@files = sort { lc($a) cmp lc($b) } @files;
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\@directories, \@files, $allowed_primary);
}
sub add_mysql_password{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'add_mysql_password.html');
# Entryserver hat admin als Hauptuser, den vorausgewählt zeigen
if(defined easytecc3::is_ftp_limited()){
$template->param('dbuser' => 'admin');
}
else{
$template->param('dbuser' => 'root');
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_add_mysql_password{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $dbuser = $input{'dbuser'};
my $dbpass = $input{'dbpass'};
logline("debug","Creating File Object /usr/local/etc/easytecc/.dbconf");
my $file = file->new({file_name => '/usr/local/etc/easytecc/.dbconf', file_content => [qq~\$user=\"$dbuser\";\n\$password=\"$dbpass\";\n~]});
my $got = $file->write_file;
if ($got) {
logline("error","/usr/local/etc/easytecc/.dbconf->write_file = ".$got);
#second try, quick and dirty
my $got2 = `$easytecc_prefix/chmod.pl 666 /usr/local/etc/easytecc/.dbconf` unless $fb;
$got2 = `/usr/iports/bin/sudo /usr/sbin/chmod.pl 666 /usr/local/etc/easytecc/.dbconf` if $fb;
$got = '';
$got = $file->write_file;
return(error($got)) if $got;
}
$template->param('result' => 'L__Der mySQL-User wurde erfolgreich gespeichert__L');
$success_text = 'L__Der mySQL-User wurde erfolgreich gespeichert__L';
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(show_dbbackup());
#return(\$template);
}
sub modify_dir{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
# Verzeichnis chown, chmod, löschen, umbenennen
my $type = $input{'type'};
my $dir = $input{'dir'};
my $chdir = $droot_prefix . '/' . $dir;
my $dir_without_path = $dir;
$dir_without_path =~ s/^.*\///;
my $template = '';
unless(-d "$droot_prefix/$dir"){
error("$dir: L__Das Verzeichnis existiert nicht__L");
}
# für Österreicher, Apple-User und Frauen:
# Jimmy: tztztz, wer kommentiert sich denn hier so weit aus dem Fenster??? ;)
elsif($dir =~ /^easytecc/){
error('L__Am easyTECC-Tool sollten Sie keine Änderungen vornehmen__L');
}
# User für select-Box für chown und cms-fix auslesen
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my %username_lookup = %{$passwd->lookup_hash()};
my @user = ();
my @groups = ();
# gather allowed dirs
my %allowed_dirs;
if($session->param('user') ne 'admin'){
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
foreach my $domain (keys %domains){
my $admins = $domains{$domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $session->param('user') . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
$allowed_dirs{$domains{$domain}{'droot'}} = '1';
}
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
$allowed_dirs{$passwd{$session->param('user')}{'home'}} = '1';
}
foreach my $user (sort keys %passwd){
# chown nicht an POP-User ermöglichen
next if $passwd{$user}{'gecos'} =~ / - POP/;
if($session->param('user') ne 'admin'){
my $allowed = 0;
if($user eq 'web'){
### Mario: Auf Wunsch von einem Kunden bei Matthias am Telefon, habe ich $allowed = 1; auf = 0; gesetzt, damit sich Enkunden nicht Ihrer Quota mit beliebigen FTP-Benutzern entziehen können. Man kann nun als Kunde eingeloggt nicht mehr die Dateien dem Benutzer web zuweisen. ###
$allowed = 0;
} else {
my $home = $passwd{$user}{'home'};
foreach my $dir (keys %allowed_dirs){
if($home eq $dir || $home =~ m#^$dir/#){
$allowed = 1;
}
}
}
if($allowed == 1){
push(@user,$user);
push(@groups, @{$passwd{$user}{'groups'}});
}
} else {
push(@user,$user);
push(@groups, @{$passwd{$user}{'groups'}});
}
}
@groups = keys %{{ map { $_ => 1 } @groups }};
### Mario: [04.05.2020] Seit einigen Wochen werden beim CMS-Fix Systemgruppen angezeigt.
### Diese werden mit den folgenden Zeilen entfernt. ###
my @groups_temp = ();
foreach ( @groups ) {
my $tempgroup = $_;
my $gid = `getent group $tempgroup | cut -d: -f3`;
chomp ($gid);
if ( $gid >= 1000 ) {
push (@groups_temp, $tempgroup);
}
}
@groups = @groups_temp;
logline("debug","groups: @groups");
if($type eq 'chmod'){
$template = HTML::Template->new(filename => 'chmod_dir.html');
my ($owner, $group, $fileperm) = (stat($chdir))[4,5,2];
my $chmod = sprintf "%lo", ($fileperm & 07777);
my $groupname = `/usr/bin/grep ':$group:' /etc/group | sed 's/:.*//'`;
chomp($groupname);
my $template_user_select = HTML::Template->new(filename => 'user_select_no_multiple.html');
easytecc3::template_loop_e4(\%input,\$template_user_select, \@user, 'user_select', $username_lookup{$owner});
$template->param('user_select' => $template_user_select->output);
my $template_group_select = HTML::Template->new(filename => 'group_select_no_multiple.html');
easytecc3::template_loop_e4(\%input,\$template_group_select, \@groups, 'group_select', $groupname);
$template->param('group_select' => $template_group_select->output);
$template->param('dir_chmod' => $chmod);
}
elsif($type eq 'cms_fix'){
$template = HTML::Template->new(filename => 'cms_fix.html');
my ($owner, $group, $fileperm) = (stat($chdir))[4,5,2];
my $groupname = `/usr/bin/grep ':$group:' /etc/group | sed 's/:.*//'`;
chomp($groupname);
my $template_user_select = HTML::Template->new(filename => 'user_select_no_multiple.html');
easytecc3::template_loop_e4(\%input,\$template_user_select, \@user, 'user_select', $username_lookup{$owner});
$template->param('user_select' => $template_user_select->output);
my $template_group_select = HTML::Template->new(filename => 'group_select_no_multiple.html');
easytecc3::template_loop_e4(\%input,\$template_group_select, \@groups, 'group_select', $groupname);
$template->param('group_select' => $template_group_select->output);
}
elsif($type eq 'mv'){
$template = HTML::Template->new(filename => 'mv_dir.html');
}
elsif($type eq 'cp'){
$template = HTML::Template->new(filename => 'cp_dir.html');
}
elsif($type eq 'rm'){
$template = HTML::Template->new(filename => 'rm_dir.html') ;
}
$template->param('chdir' => $chdir);
$template->param('dir' => $dir);
my $dir_encoded = encode_base64url($dir);
$template->param('dir_encoded' => $dir_encoded);
$template->param('dir_without_path' => $dir_without_path);
#falls formular mit ungültigen Pfadangaben abgeschickt, diese wieder einfügen
$template->param('dir_without_path' => $input{'dir_cp'}) if exists $input{'dir_cp'};
$template->param('dir_without_path' => $input{'dir_mv'}) if exists $input{'dir_mv'};
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_modify_dir{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $type = $input{'type'};
# $dir wird relativ von /home/httpd/docs übergeben
my $dir = $droot_prefix . '/' . $input{'dir'};
my $parent_dir = $dir;
$parent_dir =~ s/\/[^\/]{1,}$//;
my $dir_mv = "$parent_dir/" . $input{'dir_mv'};
my $dir_cp = "$parent_dir/" . $input{'dir_cp'};
my $result = $validation_result;
logline("debug","exec_modify_dir result:$result###");
if($result){
}
else{
# wenn neuer Dateiname bereits vorhanden nachfragen ob überschrieben werden soll
if($type eq 'cp' && -d "$dir_cp" && ! $input{'overwrite'}){
$template = HTML::Template->new(filename => 'overwrite_dir.html');
$template->param('dir' => $input{'dir'});
my $dir_encoded = encode_base64url($input{'dir'});
$template->param('dir_encoded' => $dir_encoded);
# alles im arsch hier
$template->param('dir_cp' => $input{'dir_cp'});
$template->param('dir_mv' => $input{'dir_cp'});
return(\$template);
}
# Änderungen durchführen: mv, rm, edit
if($type eq 'mv'){
my $got = `$easytecc_prefix/mv.pl $dir $dir_mv d` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/mv.pl $dir $dir_mv d` if $fb;
return(error("L__Fehler beim Umbenennen von__L $dir L__zu__L $dir_mv: $got")) if $got;
$success_text = "L__Das Verzeichnis wurde erfolgreich umbenannt__L";
}
if($type eq 'cp'){
my $got = `$easytecc_prefix/cp.pl $dir $dir_cp` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/cp.pl $dir $dir_cp` if $fb;
return(error("L__Fehler beim Kopieren von__L $dir L__zu__L $dir_cp: $got")) if $got;
$success_text = "L__Das Verzeichnis wurde erfolgreich kopiert__L";
}
elsif($type eq 'rm'){
my $got = `$easytecc_prefix/rm.pl $dir d` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/rm.pl $dir d` if $fb;
return(error("L__Fehler beim Löschen von__L $dir: $got")) if $got;
$success_text = "L__Das Verzeichnis wurde erfolgreich gelöscht__L";
}
elsif($type eq 'chmod'){
logline("debug",qq~newowner:$input{'user_select'} newchmod:$input{'dir_chmod'}~);
my $got = `$easytecc_prefix/chown.pl $input{'user_select'}:$input{'group_select'} $dir` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl $input{'user_select'}:$input{'group_select'} $dir` if $fb;
return(error("L__Fehler bei CHOWN von__L $dir: $got")) if $got;
my $got = `$easytecc_prefix/chmod.pl $input{'dir_chmod'} $dir` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/chmod.pl $input{'dir_chmod'} $dir` if $fb;
return(error("L__Fehler bei CHMOD von__L $dir: $got")) if $got;
$success_text = "L__Das Verzeichnis wurde erfolgreich geändert.__L";
}
elsif($type eq 'cms_fix'){
logline("debug",qq~cms_fix:$input{'user_select'}~);
my $got = `$easytecc_prefix/cms_fix.pl $input{'user_select'}:$input{'group_select'} $dir` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/cms_fix.pl $input{'user_select'}:$input{'group_select'} $dir` if $fb;
return(error("L__Fehler bei cms_fix von__L $dir: $got")) if $got;
$success_text = 'L__Das Verzeichnis wurde erfolgreich geändert__L';
}
}
# mv
# rm
# cms fix:
# find melanie/ -not -user admin|xargs du -sc
#7256 melanie
#4 melanie/stats/.htaccess
#.
#.
#.
#12 melanie/logo.gif
#7616 insgesamt
#7616 - 7256 = Quotabedarf + ~256kB für Verzeichnis-Inodes
my $dir_back = $input{'dir'};
$dir_back = '' if($dir_back !~ /\//);
$dir_back =~ s/\/[^\/]{0,100}$// if $dir_back;
#$result = $result . qq~<br /><br /><a href="/cgi-bin/easytecc3/index.pl?action=show_filemanager&dir=~ . $dir_back . qq~">L__Zurück zum Filemanager__L</a>~;
#$template->param('result' => $result);
#logline("debug","result = " . $result);
my $dir_encoded = encode_base64url($dir_back);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_filemanager&dir=' . $dir_encoded . '&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub modify_file{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $type = $input{'type'};
my $dir = $input{'dir'};
my $chdir = '';
# wenn kein $dir, dann kein /, weil sonst bei full_file 2 slashes da wären
$chdir = $droot_prefix . '/' . $dir if $dir;
$chdir = $droot_prefix unless $dir;
my $file = $input{'file'};
my $template = '';
logline("debug","chdir=$chdir\ndir=$dir\nfile=$file");
if($type eq 'edit' && $file eq '.user.ini' && !-e "$droot_prefix/$dir/$file"){
`touch $droot_prefix/$dir/$file`;
if(!-e "$droot_prefix/$dir/$file"){
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 777 $droot_prefix/$dir`;
`touch $droot_prefix/$dir/$file`;
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 755 $droot_prefix/$dir`;
}
if(!-e "$droot_prefix/$dir/$file"){
return(modal_error('L__Die Datei konnte nicht angelegt werden.__L'));
} else {
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 644 $droot_prefix/$dir/$file`;
my($fileuid, $filegid) = (stat("$droot_prefix/$dir"))[4,5];
`/usr/iports/bin/sudo /usr/sbin/chown.pl $fileuid:$filegid $droot_prefix/$dir/$file 2>&1`;
}
}
unless(-e "$droot_prefix/$dir/$file"){
return(modal_error('L__Die Datei existiert nicht__L'));
}
# für Österrreicher, Apple-User und Frauen:
elsif($dir =~ /^easytecc/){
return(modal_error('L__Am easyTECC-Tool sollten Sie keine Änderungen vornehmen__L'));
}
if($type eq 'chmod'){
$template = HTML::Template->new(filename => 'chmod_file.html');
# User für select-Box für chown auslesen
logline("debug","Creating File Object \$passwd.");
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my %username_lookup = %{$passwd->lookup_hash()};
my @user = ();
my @groups = ();
# gather allowed dirs
my %allowed_dirs;
if($session->param('user') ne 'admin'){
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
foreach my $domain (keys %domains){
my $admins = $domains{$domain}{'admin_users'};
$admins =~ s/[\s,]+/#/g;
$admins = '#' . $admins . '#';
$userregex = '#' . $session->param('user') . '#';
logline("debug","admins:$admins\nuserregex:$userregex");
if($admins !~ m/$userregex/i){
next;
}
$allowed_dirs{$domains{$domain}{'droot'}} = '1';
}
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
$allowed_dirs{$passwd{$session->param('user')}{'home'}} = '1';
}
foreach my $user(sort keys %passwd){
# chown nicht an POP-User ermöglichen
next if $passwd{$user}{'gecos'} =~ / - POP/;
if($session->param('user') ne 'admin'){
my $allowed = 0;
if($user eq 'web'){
### Mario: $allowed = 0; gesetzt, damit eingeloggte Kunden nicht mehr die Möglichkeit haben, die Quota zu umgehen, indem Sie Dateien dem Benutzer web zuordnen. ###
$allowed = 0;
} else {
my $home = $passwd{$user}{'home'};
foreach my $dir (keys %allowed_dirs){
if($home eq $dir || $home =~ m#^$dir/#){
$allowed = 1;
}
}
}
if($allowed == 1){
push(@user,$user);
push(@groups, @{$passwd{$user}{'groups'}});
}
} else {
push(@user,$user);
push(@groups, @{$passwd{$user}{'groups'}});
}
}
@groups = keys %{{ map { $_ => 1 } @groups }};
my ($owner, $group, $fileperm) = (stat("$chdir/$file"))[4,5,2];
my $chmod = sprintf "%lo", ($fileperm & 07777);
my $groupname = `/usr/bin/grep ':$group:' /etc/group | sed 's/:.*//'`;
chomp($groupname);
logline("debug","owner=$owner\nchmod=$chmod");
# foreach my $user(sort keys %passwd){
# # chown nicht an POP-User ermöglichen
# next if $passwd{$user}{'gecos'} =~ / - POP/;
# push(@user,$user);
# }
my $template_user_select = HTML::Template->new(filename => 'user_select_no_multiple.html');
easytecc3::template_loop_e4(\%input,\$template_user_select, \@user, 'user_select', $username_lookup{$owner});
$template->param('user_select' => $template_user_select->output);
my $template_group_select = HTML::Template->new(filename => 'group_select_no_multiple.html');
easytecc3::template_loop_e4(\%input,\$template_group_select, \@groups, 'group_select', $groupname);
$template->param('group_select' => $template_group_select->output);
$template->param('file_chmod' => $chmod);
$template->param('old_owner' => $username_lookup{$owner});
}
elsif($type eq 'mv'){
$template = HTML::Template->new(filename => 'mv_file.html');
}
elsif($type eq 'cp'){
$template = HTML::Template->new(filename => 'cp_file.html');
}
elsif($type eq 'rm'){
$template = HTML::Template->new(filename => 'rm_file.html') ;
}
elsif($type eq 'edit'){
$template = HTML::Template->new(filename => 'edit_file.html') ;
if(-s "$chdir/$file" && -B "$chdir/$file"){
logline("warning","bin $chdir/$file");
return(modal_error('L__Binärdateien können nicht editiert werden__L.'));
}
my $file_content = `cat $chdir/$file`;
my $decoder = Encode::Guess->guess($file_content, qw/ascii utf8 latin1/);
# die $decoder unless ref($decoder);
my $utf8 = $file_content;
if(ref($decoder) && $decoder->name =~ /utf8/){
#nix, ist schon utf8
}
else{
$utf8 = $decoder->decode($file_content) if ref($decoder);
}
logline("debug","decoder = " . $decoder->name) if $debug && ref($decoder);
$utf8 =~ s/&/\&/g;
$utf8 =~ s/\</\</g;
$utf8 =~ s/\>/\>/g;
$template->param('file_content' => $utf8);
}
$template->param('chdir' => $chdir);
$template->param('dir' => $dir);
my $dir_encoded = encode_base64url($dir);
$template->param('dir_encoded' => $dir_encoded);
$template->param('file' => $file);
my $file_encoded = encode_base64url($file);
$template->param('file_encoded' => $file_encoded);
$template->param('file_mv' => $file);
$template->param('file_cp' => $file);
$template->param('full_file' => $chdir . '/'. $file);
my $full_file_encoded = encode_base64url($chdir . '/'. $file);
$template->param('full_file_encoded' => $full_file_encoded);
$template->param('encoding' => $decoder->name) if ref($decoder);
#falls formular mit ungültigen Pfadangaben abgeschickt, diese wieder einfügen
$template->param('file_cp' => $input{'file_cp'}) if exists $input{'file_cp'};
$template->param('file_mv' => $input{'file_mv'}) if exists $input{'file_mv'};
if($input{'parent'}){
$template->param('parent' => $input{'parent'});
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_modify_file{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $type = $input{'type'};
my $file = $input{'file'};
my $dir = $droot_prefix;
$dir .= '/' . $input{'dir'} if $input{'dir'};
my $fullfile = $input{'full_file'};
if(!$fullfile){
$fullfile = $dir ."/" . $file;
}
my $file_mv = $input{'file_mv'};
my $file_cp = $input{'file_cp'};
# $dir wird relativ von /home/httpd/docs übergeben
my $result = $validation_result;
logline("debug","exec_modify_file result:$result###");
if($result){
}
else{
# wenn neuer Dateiname bereits vorhanden nachfragen ob überschrieben werden soll
if($type eq 'mv' && -f "$dir/$file_mv" && ! $input{'overwrite'}){
$template = HTML::Template->new(filename => 'overwrite_file_mv.html');
$template->param('file' => $file);
my $file_encoded = encode_base64url($file);
$template->param('file_encoded' => $file_encoded);
$template->param('file_mv' => $file_mv);
$template->param('dir' => $input{'dir'});
my $dir_encoded = encode_base64url($input{'dir'});
$template->param('dir_encoded' => $dir_encoded);
return(\$template);
}
elsif($type eq 'cp' && -f "$dir/$file_cp" && ! $input{'overwrite'}){
$template = HTML::Template->new(filename => 'overwrite_file_cp.html');
$template->param('file' => $file);
my $file_encoded = encode_base64url($file);
$template->param('file_encoded' => $file_encoded);
$template->param('file_cp' => $file_cp);
$template->param('dir' => $input{'dir'});
my $dir_encoded = encode_base64url($input{'dir'});
$template->param('dir_encoded' => $dir_encoded);
return(\$template);
}
# Änderungen durchführen: mv, rm, edit
if($type eq 'mv'){
my $got = `$easytecc_prefix/mv.pl $dir/$file $dir/$file_mv` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/mv.pl $dir/$file $dir/$file_mv` if $fb;
return(error("L__Fehler beim Umbenennen von__L $dir/$file zu $dir/$file_mv: $got")) if $got;
$success_text = 'L__Die Datei wurde erfolgreich umbenannt__L';
}
if($type eq 'cp'){
my $got = `$easytecc_prefix/cp.pl $dir/$file $dir/$file_cp` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/cp.pl $dir/$file $dir/$file_cp` if $fb;
return(error("L__Fehler beim Kopieren von__L $dir/$file zu $dir/$file_cp: $got")) if $got;
$success_text = 'L__Die Datei wurde erfolgreich kopiert__L';
}
elsif($type eq 'rm'){
my $got = `$easytecc_prefix/rm.pl $fullfile` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/rm.pl $fullfile` if $fb;
return(error("L__Fehler beim Löschen von__L $fullfile: $got")) if $got;
$success_text = 'L__Die Datei wurde erfolgreich gelöscht__L';
}
elsif($type eq 'edit'){
my $file_content = $input{'file_content'};
my $encoding = $input{'encoding'};
# etwas herumcodieren und dann speichern
# Content kommt als utf8, wenn vorher ascii oder latin1, dann umkodieren
$file_content =~ s/\&/&/g;
$file_content =~ s/\</\</g;
$file_content =~ s/\>/\>/g;
$file_content = encode("ascii", $file_content) if ($encoding eq 'ascii');
$file_content = encode("iso-8859-1", $file_content) if ($encoding eq 'latin1');
logline("debug","Creating File Object $fullfile");
my $file = file->new({file_name => "$fullfile", file_content => [qq~$file_content\n~]});
my $got = $file->write_file;
if($got){
`/usr/iports/bin/sudo /usr/sbin/chown.pl admin:vuser $fullfile 2>&1`;
my $got = $file->write_file;
my($fileuid, $filegid) = (stat("$dir"))[4,5];
`/usr/iports/bin/sudo /usr/sbin/chown.pl $fileuid:$filegid $fullfile 2>&1`;
if ($got) {
logline("error","$fullfile->write_file = ".$got);
return(error($got));
}
}
$success_text = 'L__Die Datei wurde erfolgreich geändert__L';
}
elsif($type eq 'chmod'){
logline("debug",qq~newowner:$input{'user_select'} newchmod:$input{'file_chmod'}~);
#if($input{'old_owner'} ne $input{'user_select'}){
my $got = `$easytecc_prefix/chown.pl $input{'user_select'}:$input{'group_select'} $fullfile` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/chown.pl $input{'user_select'}:$input{'group_select'} $fullfile` if $fb;
return(error("L__Fehler bei CHOWN von__L $fullfile: $got")) if $got;
#}
#if($input{'old_chmod'} != $input{'file_chmod'}){
my $got = `$easytecc_prefix/chmod.pl $input{'file_chmod'} $fullfile` unless $fb;
$got = `/usr/iports/bin/sudo /usr/sbin/chmod.pl $input{'file_chmod'} $fullfile` if $fb;
return(error("L__Fehler bei CHMOD von__L $fullfile: $got")) if $got;
#}
$success_text = 'L__Die Datei wurde erfolgreich geändert__L';
}
}
my $dir_encoded = encode_base64url($input{'dir'});
if(!$input{'parent'}){
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_filemanager&dir=' . $dir_encoded . '&success_text=' . encode_base64url($success_text);
}
#$result = $result . qq~<br /><br /><a href="/cgi-bin/easytecc3/index.pl?action=show_filemanager&dir=~ . $input{'dir'} . qq~">L__Zurück zum Filemanager__L</a>~;
#$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub download_file{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $dir = $input{'dir'};
my $file = $input{'file'};
logline("debug","download file [$input{'type'}]: ".$dir."/".$file);
if(exists $input{'type'} && $input{'type'} eq 'logfile'){
binmode STDOUT;
if($file eq 'Messages'){
open (IF, "/var/log/messages") || dienice("open /var/log/messages: $!");
$file = 'messages';
}
elsif($file eq 'Maillogs'){
open (IF, "/var/log/maillog") || dienice("open /var/log/maillog: $!");
$file = 'maillog';
}
else{
open (IF, "/home/web/log/$file") || dienice("open /home/web/log/$file: $!");
}
print "Content-Type: application/octet-stream\n";
print "Content-Disposition: attachment;filename=\"$file.txt\"\n\n";
print while(<IF>);
close IF;
}
elsif(-e "$droot_prefix/$dir/$file"){
binmode STDOUT;
open (IF, "$droot_prefix/$dir/$file") || dienice("open $droot_prefix/$dir/$file: $!");
print "Content-Type: application/octet-stream\n";
print "Content-Disposition: attachment;filename=\"$file\"\n\n";
print while(<IF>);
close IF;
}
logline("debug","<<< Exiting ".(caller(0))[3]."().");
exit(0);
}
sub new_sendmail_cw{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
#included by show_email() second tab
my $template = shift;
my @sendmail_cw = ();
logline("debug","Creating File Object \$sendmail_cw.");
my $sendmail_cw = file->new({file_name => '/etc/mail/sendmail.cw'});
$sendmail_cw->read_file;
my %sendmail_cw = %{$sendmail_cw->file_parsed_hash()};
foreach(keys %sendmail_cw){
delete ($sendmail_cw{$_}) if /\.han-solo\.net/;
}
my @sendmail_cw_entries = sort keys %sendmail_cw;
#dkim
my $dkim_available = 0;
if(-f '/etc/opendkim.conf'){
$dkim_available = 1;
}
my $table_data = {};
for(my $count = 0; $count <= $#sendmail_cw_entries; $count++){
push @sendmail_cw, qq~<input type="checkbox" name="delete$count" id="delete$domaincount" value="$sendmail_cw_entries[$count]" />~ . encode('utf-8', domain_to_unicode($sendmail_cw_entries[$count]));
$table_data->{$sendmail_cw_entries[$count]}{'idn_domain'} = encode('utf-8', domain_to_unicode($sendmail_cw_entries[$count]));
$table_data->{$sendmail_cw_entries[$count]}{'domain'} = $sendmail_cw_entries[$count];
$table_data->{$sendmail_cw_entries[$count]}{'count'} = $count+1;
#dkim
if( -e "/etc/dkim/keys/$sendmail_cw_entries[$count]"){
$table_data->{$sendmail_cw_entries[$count]}{'dkim'} = '1';
}
$table_data->{$sendmail_cw_entries[$count]}{'dkim_available'} = $dkim_available;
}
my $table_data_sorted = {};
foreach $domain (keys %{$table_data}){
$table_data_sorted->{$table_data->{$domain}{'idn_domain'}} = $table_data->{$domain};
}
easytecc3::table_e4($template, $table_data_sorted, 'table_tr_sendmail_cw_domains_template.html');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_new_sendmail_cw{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_new_sendmail_cw result:$result###");
if($result){
}
else{
my %handle_hash = %{easytecc3::return_file_handler_store()};
my $sendmail_cw = $handle_hash{'/etc/mail/sendmail.cw'};
push @{$sendmail_cw->file_content} , $input{'domain'};
my $got = $sendmail_cw->write_file;
if ($got) {
logline("error","sendmail_cw->write_file = ".$got);
return(error($got));
}
$result .= encode('utf-8', domain_to_unicode($input{'domain'})) . ": L__Erfolgreich in Mailkonfiguration eingetragen__L";
$success_text = $result;
#$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_email&active_tab=2&success_text=' . encode_base64url($success_text);
}
$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
#direct call to show_email with active tab 2
undef %input;
$input{'active_tab'} = '2';
$action = 'show_email';
return(show_email());
#return(\$template);
}
sub exec_new_quotamessage{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_new_quotamessage result:$result###");
if($result){
#todo:validieren!
}
else{
my $file_content = "From: " . $input{'quotasender'} . "\nSubject: " . $input{'quotasubject'} . "\n\n" . $input{'quotamessage'};
$file_content = encode('utf8', $file_content);
my $file = file->new({file_name => '/etc/mail/quotamessage', file_content => [qq~$file_content\n~]});
my $got = $file->write_file;
if ($got) {
logline("error","/etc/mail/quotamessage->write_file = ".$got);
return(error($got));
}
$file = file->new({file_name => '/etc/mail/quotafrom', file_content => [qq~$input{'quotasender'}~]});
$got = $file->write_file;
if ($got) {
logline("error","/etc/mail/quotafrom->write_file = ".$got);
return(error($got));
}
$result = 'L__Die Emailquota-Warnung wurde erfolgreich geändert.__L';
$success_text = $result;
#$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_email&active_tab=3&success_text=' . encode_base64url($success_text);
}
$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
#direct call to show_email with active tab 3
undef %input;
$input{'active_tab'} = '3';
$action = 'show_email';
return(show_email());
#return(\$template);
}
sub exec_new_mailserver_cert{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_new_mailserver_cert result:$result###");
if($result){
#todo:validieren!
}
else{
my $mailserver_cert = $input{'mailserver_cert_select'};
$result = `/usr/iports/bin/sudo /usr/sbin/setmailcert $mailserver_cert 2>&1 1>/dev/null`;
if(length($result)){
#$result = encode_entities($result);
return(error("L__Beim Setzen des Mailserver-Zertifikates ist ein Fehler aufgetreten:__L <pre>$result</pre>"));
}
$result = 'L__Das Mailserver-Zertifikat wurde erfolgreich geändert.__L';
$success_text = $result;
#$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_email&active_tab=3&success_text=' . encode_base64url($success_text);
}
$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
#direct call to show_email with active tab 3
undef %input;
$input{'active_tab'} = '4';
$action = 'show_email';
return(show_email());
#return(\$template);
}
sub add_ssl_vhost{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'add_ssl_vhost.html');
my $domain = $input{'domain'};
$template->param('domain' => $domain);
$template->param('action' => 'exec_add_ssl_vhost');
$template->param('newcert' => '1');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub change_ssl_vhost{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'add_ssl_vhost.html');
my $domain = $input{'domain'};
$template->param('domain' => $domain);
$template->param('action' => 'exec_change_ssl_vhost');
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
$template->param('cert' => $domains{$domain}{'ssl_cert'});
$template->param('key' => $domains{$domain}{'ssl_key'});
$template->param('chain' => $domains{$domain}{'ssl_chain'});
if($domains{$domain}{'ssl_cert'} =~ m/letsencrypt/){
$template->param('is_letsencrypt' => '1');
}
if($domains{$domain}{'ssl_force'} == '1'){
$template->param('has_ssl_redirect' => '1');
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_add_ssl_vhost{
my $template = HTML::Template->new(filename => 'result.html');
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $result = $validation_result;
my $success_text = '';
if($result){
}
else{
my $domain = $input{'domain'};
if($domain !~ m/^www\./){
$domain = 'www.' . $domain;
}
my $install_apache_cert = '';
if($fb){
$install_apache_cert = '/usr/iports/bin/sudo /usr/sbin/install_apache_cert.pl';
} else {
$install_apache_cert = '/home/httpd/cgi-bin/easytecc4/install_apache_cert.pl';
}
if($input{'letsencrypt'}){
if(!$fb){
return(error("L__Let's Encrypt steht auf diesem Servertyp nicht zur Verfügung__L"));
}
$result = `/bin/sh -c '$install_apache_cert $domain LETSENCRYPT 2>&1'`;
if($result =~ m/^ok/){
$result = "L__Das Let's Encrypt Zertifikat wurde erfolgreich erstellt.__L";
} else {
$result = encode_entities($result);
return(error("L__Beim Erstellen des Let's Encrypt Zertifikates ist ein Fehler aufgetreten:__L <pre>$result</pre><br>L__Eventuell verweist eine der Domains nicht auf Ihren Server oder der Zugriff auf /.well-known/acme-challenge wurde durch eine Rewrite-Regel verhindert.__L"));
}
}
elsif($input{'csr'}){
my $openssl_create_csr = 'openssl req -nodes -newkey rsa:2048 -sha256 -keyout ' . $input{'key_file'} . ' -out ' . $input{'csr_file'} . ' -subj "/C=' . $input{'csr_country'} . '/ST=' . $input{'csr_state'} . '/L=' . $input{'csr_city'} . '/O=' . $input{'csr_company'} . '/OU=' . $input{'csr_section'} . '/CN=' . $input{'domain'} . '/emailAddress=' . $input{'csr_email'} . '" && cat ' . $input{'csr_file'};
if(-e '/usr/local/bin/openssl'){
$openssl_create_csr = '/usr/local/bin/' . $openssl_create_csr;
}
$result = `$openssl_create_csr 2>&1`;
if($result =~ m/problems/){
return(error("L__Beim Erstellen des CSR ist ein Fehler aufgetreten:__L $result"));
}
else {
return(modal_message('L__Zertifikatsanfrage (CSR)__L','L__Bitte geben Sie diesen Textblock bei der Bestellung des Zertifikates an:__L<br><br><pre>' . $result . '</pre>'));
}
}
else {
logline("debug","running $install_apache_cert $domain $input{'cert'} $input{'key'} $input{'chain'} 2>&1");
$result = `$install_apache_cert $domain $input{'cert'} $input{'key'} $input{'chain'} 2>&1`;
if($result =~ m/^ok/){
$result = "L__Das Zertifikat wurde erfolgreich eingerichtet.__L";
}
else {
return(error("L__Beim Einrichten des Zertifikates ist ein Fehler aufgetreten:__L $result"));
}
}
$success_text = $result;
}
$template->param('result' => $result);
logline("debug","result = " . $result);
if($session && $session->param('ssl_expiry_dates')){
$session->clear('ssl_expiry_dates');
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_vhosts&success_text=' . encode_base64url($success_text);
return(\$template);
}
sub exec_change_ssl_vhost{
my $template = HTML::Template->new(filename => 'result.html');
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $result = $validation_result;
my $success_text = '';
if($result){
}
else{
my $domain = $input{'domain'};
if($domain !~ m/^www\./){
$domain = 'www.' . $domain;
}
my $install_apache_cert = '';
if($fb){
$install_apache_cert = '/usr/iports/bin/sudo /usr/sbin/install_apache_cert.pl';
} else {
$install_apache_cert = '/home/httpd/cgi-bin/easytecc4/install_apache_cert.pl';
}
if($input{'letsencrypt'}){
if(!$fb){
return(error("L__Let's Encrypt steht auf diesem Servertyp nicht zur Verfügung__L"));
}
$result = `/bin/sh -c '$install_apache_cert $domain 443 LETSENCRYPT 2>&1'`;
if($result =~ m/^ok/){
$result = "L__Das Let's Encrypt Zertifikat wurde erfolgreich erstellt.__L";
} else {
$result = encode_entities($result);
return(error("L__Beim Erstellen des Let's Encrypt Zertifikates ist ein Fehler aufgetreten:__L <pre>$result</pre><br>L__Eventuell verweist eine der Domains nicht auf Ihren Server oder der Zugriff auf /.well-known/acme-challenge wurde durch eine Rewrite-Regel verhindert.__L"));
}
}
elsif($input{'delete'}){
logline("debug","Creating File Object \$httpd_conf.");
my $httpd_conf = file->new({file_name => '/etc/httpd/conf/httpd.conf'});
$httpd_conf->read_file;
my %domains = %{$httpd_conf->file_parsed_hash()};
my $vhost_to_delete = $domain;
my $vhost_to_delete_ohne_www = $vhost_to_delete;
$vhost_to_delete_ohne_www =~ s/^www\.//;
#vhost aus httpd.conf löschen
my @new_httpd_conf = ();
my $vhost = '';
my $delete_this_vhost = '';
my @tmp_vhost = ();
my $ssl = '';
foreach($httpd_conf->file_content){
chomp;
$vhost = 1 if(/^\<VirtualHost\s+([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}):/i);
$ssl = 1 if(/^\<VirtualHost\s+([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}):443/i);
if($vhost){
if(/^ServerName\s+$vhost_to_delete_quoted\b/){
s/E=REDIRECT_SCHEME:https/E=REDIRECT_SCHEME:http/g;
}
push @tmp_vhost, $_;
my $vhost_to_delete_quoted = quotemeta("$vhost_to_delete");
if(/^ServerName\s+$vhost_to_delete_quoted\b/ && $ssl){
$delete_this_vhost = '1'
}
#dieser vhost ist es nicht, also in @tmp_vhost gesammelte Zeilen unverändert übernehmen
if(/^\<\/VirtualHost/ && ! $delete_this_vhost){
push @new_httpd_conf, @tmp_vhost;
$vhost = '';
$ssl = '';
@tmp_vhost = ();
}
#oder match auf zu löschenden vhost, hier passiert nix und vhost wird nicht in new_httpd_conf gepushed, gleichbedeutend mit löschen
elsif(/^\<\/VirtualHost/ && $delete_this_vhost){
logline("debug","vhost=$vhost");
$vhost = '';
$ssl = '';
@tmp_vhost = ();
# $delete_this_vhost wieder auf null setzen, da es mehrere vhost mit gleichem Namen geben kann, z.B. wegen SSL oder
# propagationsvhost mit alter IP. Alles weghauen
$delete_this_vhost = '';
}
}
else{
push @new_httpd_conf, $_;
}
}
@{$httpd_conf->file_content} = @new_httpd_conf;
my $got = $httpd_conf->write_file;
return(error($got)) if $got;
### Mario: Sobald ein SSL-VHost gelöscht wird -jedoch nicht das SSL-Zertifikat- dann wird durch den Cronjob immer wieder versucht,
### das SSL-Zertifikat zu verlängern. Daher müssen einige Schritte durchgeführt werden ...
if($domains{$domain}{'ssl_cert'} =~ m/letsencrypt/){
#my $got = `/usr/iports/bin/sudo /usr/sbin/rm.pl $droot d` if $fb;
#my $got = `$easytecc_prefix/rm.pl $droot d` unless $fb;
logline("debug"," MARIO delete_ssl_files von $vhost_to_delete_ohne_www");
system('/bin/sh -c "/usr/iports/bin/letsencrypt revoke --cert-path ' . $domains{$domain}{'ssl_cert'} . '"');
#return(error("L__Fehler beim Löschen von__L $droot: $got")) if ($got || -d "$droot");
}
$result = "L__Der SSL-Vhost wurde erfolgreich gelöscht__L";
}
else {
logline("debug","running $install_apache_cert $domain $input{'cert'} $input{'key'} $input{'chain'} 2>&1");
$result = `$install_apache_cert $domain 443 $input{'cert'} $input{'key'} $input{'chain'} 2>&1`;
if($result =~ m/^ok/){
$result = "L__Das Zertifikat wurde erfolgreich eingerichtet.__L";
}
else {
return(error("L__Beim Einrichten des Zertifikates ist ein Fehler aufgetreten:__L $result"));
}
}
}
$success_text = $result;
$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_vhosts&success_text=' . encode_base64url($success_text);
return(\$template);
}
sub hash_to_file{
my ($file, $hashref) = @_;
if(!open(HASHFILE,'>:encoding(UTF-8)',$file)){
return 0;
}
use Data::Dumper;
print HASHFILE Data::Dumper->Dump([$hashref],['$hashref']);
close HASHFILE;
return 1;
}
sub hash_from_file{
my ($file) = @_;
if(!open(HASHFILE,'<:encoding(UTF-8)',$file)){
return 0;
}
local($/) = '';
my $hashref = {};
my $hashdef = <HASHFILE>;
eval $hashdef;
close HASHFILE;
return $hashref;
}
sub note_to_hashfile{
my ($keys, $title, $text) = @_;
my $user_hash_file = '/usr/local/etc/easytecc/note/' . $session->param('user') . '.data';
my $user_hashref = hash_from_file($user_hash_file);
if(ref($user_hashref) ne 'HASH'){
$user_hashref = {};
}
my $target_hashref = $user_hashref;
foreach (@{$keys}){
if(!exists($target_hashref->{$_})){
$target_hashref->{$_} = {};
}
$target_hashref = $target_hashref->{$_};
}
$target_hashref->{note}->{title} = $title;
$target_hashref->{note}->{text} = $text;
return hash_to_file($user_hash_file,$user_hashref );
}
sub note_from_hashfile{
my ($keys) = @_;
my $user_hash_file = '/usr/local/etc/easytecc/note/' . $session->param('user') . '.data';
my $user_hashref = hash_from_file($user_hash_file);
my $target_hashref = $user_hashref;
foreach (@{$keys}){
if(!exists($target_hashref->{$_})){
last;
}
$target_hashref = $target_hashref->{$_};
}
my $result = {};
$result->{title} = encode('utf-8',$target_hashref->{note}->{title});
$result->{text} = encode('utf-8',$target_hashref->{note}->{text});
return $result;
}
sub show_save_note{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'show_note.html');
my @keys = split(/\//, $input{'note_key'});
my $note = note_from_hashfile(\@keys);
$template->param('title' => $input{'title'});
$template->param('note_key' => $input{'note_key'});
$template->param('note_title' => $note->{title});
$template->param('note_text' => $note->{text});
if(! $note->{title} && $input{'note_title'}){
$template->param('note_title' => $input{'note_title'});
}
if($input{'parent'}){
$template->param('parent' => $input{'parent'});
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_show_save_note{
my $template = HTML::Template->new(filename => 'show_note.html');
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $result = $validation_result;
my $success_text = '';
if($result){
}
else{
my @keys = split(/\//, $input{'note_key'});
my $title = $input{'note_title'};
my $text = $input{'note_text'};
if(!note_to_hashfile(\@keys,$title,$text)){
return(error("L__Beim Speichern der Notiz ist ein Fehler aufgetreten.__L"));
} else {
$result = "L__Die Notiz wurde gespeichert.__L";
}
$success_text = $result;
}
$template->param('result' => $result);
logline("debug","result = " . $result);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
if(!$input{'parent'}){
$json_output{'redirect_to'} = '&success_text=' . encode_base64url($success_text);
}
return(\$template);
}
sub change_firewall{
my $error = '';
if($session->param('show_firewall') ne '1'){
return start();
}
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
if(! -d '/usr/local/etc/easytecc/shell2ban'){
system("mkdir -p /usr/local/etc/easytecc/shell2ban");
system("touch /usr/local/etc/easytecc/shell2ban/.disabled");
}
my $template = HTML::Template->new(filename => 'change_firewall.html');
# enable
if($input{'enable'}){
$input{'active_tab'} = 1;
system("rm -f /usr/local/etc/easytecc/shell2ban/.disabled");
system("touch /usr/local/etc/easytecc/shell2ban/WHITELIST");
system("touch /usr/local/etc/easytecc/shell2ban/BLACKLIST");
$result = 'L__Die Firewall wurde aktiviert.__L';
}
elsif($input{'disable'}){
$input{'active_tab'} = 1;
system("touch /usr/local/etc/easytecc/shell2ban/.disabled");
$result = 'L__Die Firewall wurde deaktiviert.__L';
}
elsif($input{'enable_web2ban'}){
$input{'active_tab'} = 2;
system("rm -f /usr/local/etc/easytecc/shell2ban/.web2ban.disabled");
$result = 'L__Das Webserver-Plugin wurde aktiviert.__L';
}
elsif($input{'disable_web2ban'}){
$input{'active_tab'} = 2;
system("touch /usr/local/etc/easytecc/shell2ban/.web2ban.disabled");
$result = 'L__Das Webserver-Plugin wurde deaktiviert.__L';
}
elsif($input{'enable_scan2ban'}){
$input{'active_tab'} = 3;
system("rm -f /usr/local/etc/easytecc/shell2ban/.scan2ban.disabled");
$result = 'L__Das Portscan-Plugin wurde aktiviert.__L';
}
elsif($input{'disable_scan2ban'}){
$input{'active_tab'} = 1;
system("touch /usr/local/etc/easytecc/shell2ban/.scan2ban.disabled");
$result = 'L__Das Portscan-Plugin wurde deaktiviert.__L';
}
elsif($input{'enable_share2ban'}){
$input{'active_tab'} = 1;
system("rm -f /usr/local/etc/easytecc/shell2ban/.share2ban.disabled");
$result = 'L__Das Community-Plugin wurde aktiviert.__L';
}
elsif($input{'disable_share2ban'}){
$input{'active_tab'} = 1;
system("touch /usr/local/etc/easytecc/shell2ban/.share2ban.disabled");
$result = 'L__Das Community-Plugin wurde deaktiviert.__L';
}
elsif($input{'whitelist_remove'}){
$input{'active_tab'} = 1;
my @keys = split(/\//, 'FIREWALL/WHITELIST/' . $input{'whitelist_remove'});
note_to_hashfile(\@keys,'','');
$input{'whitelist_remove'} =~ s/\//\\\//;
system("sed -i '.bak' '/^" . $input{'whitelist_remove'} . "/d' /usr/local/etc/easytecc/shell2ban/WHITELIST");
$result = 'L__Die IP / das Netzwerk wurde entfernt.__L';
}
elsif($input{'blacklist_remove'}){
$input{'active_tab'} = 1;
my @keys = split(/\//, 'FIREWALL/BLACKLIST/' . $input{'blacklist_remove'});
note_to_hashfile(\@keys,'','');
$input{'blacklist_remove'} =~ s/\//\\\//;
system("sed -i '.bak' '/^" . $input{'blacklist_remove'} . "/d' /usr/local/etc/easytecc/shell2ban/BLACKLIST");
$result = 'L__Die IP / das Netzwerk wurde entfernt.__L';
}
elsif($input{'web2ban_delete_rule'}){
$input{'active_tab'} = 2;
$error = web2ban_add_edit_delete_rule('delete');
if(!$error){
$result = 'L__Die Regel wurde entfernt.__L';
}
}
elsif($input{'scan2ban_remove_port'}){
$input{'active_tab'} = 3;
$input{'port'} =~ s/\s+//g;
system("sed -i '.bak' '/^" . $input{'port'} . "/d' /usr/local/etc/easytecc/shell2ban/SCAN2BAN_WHITELIST");
$input{'port'} =~ s/[^0-9]//g;
my @keys = split(/\//, 'FIREWALL/SCAN2BAN_WHITELIST/' . $input{'port'});
note_to_hashfile(\@keys,'','');
$result = 'L__Ports wurden entfernt.__L';
} elsif(length($input{'scan2ban_block_not_whitelisted'})){
$input{'active_tab'} = 3;
if($input{'scan2ban_block_not_whitelisted'}){
system("touch /usr/local/etc/easytecc/shell2ban/.scan2ban.block.not.whitelisted");
} else {
system("rm -f /usr/local/etc/easytecc/shell2ban/.scan2ban.block.not.whitelisted");
}
$result = 'L__Portscan-Einstellungen geändert.__L';
} else {
$template->param('change_firewall_active_tab2' => '0');
$template->param('change_firewall_active_tab3' => '0');
}
if(!length($input{'active_tab'})){
$input{'active_tab'} = 1;
}
$template->param('change_firewall_active_tab' . $input{'active_tab'} => '1');
if(-e '/usr/local/etc/easytecc/shell2ban/.disabled'){
$template->param('disabled' => '1');
} else {
my @whitelist;
if(-s '/usr/local/etc/easytecc/shell2ban/WHITELIST'){
open WHITELIST, '</usr/local/etc/easytecc/shell2ban/WHITELIST';
while (<WHITELIST>){
my ($ip,$ttl,$note) = $_ =~ m/^([^\s]+)\s+([0-9]+)\s*#*(.*)$/;
if(defined($ip)){
logline("debug","###ip: $ip ### ttl: $ttl ### note: $note ###");
if(!defined($ttl)){
$ttl = 0;
}
elsif($ttl > 0){
#$ttl = `/bin/sh -c "date -j -f '%s' '$ttl' '+%d.%m.%Y %H:%M:%S'"`;
#chomp $ttl;
$ttl = $strftime{"%d.%m.%Y %H:%M", $ttl};
}
my @keys = split(/\//, 'FIREWALL/WHITELIST/' . $ip);
if(defined($note) && length($note)){
note_to_hashfile(\@keys,'WHITELIST',$note);
} else {
$note = note_from_hashfile(\@keys);
$note = $note->{text};
}
push @whitelist, { ip => $ip, ttl => $ttl, note => $note };
}
}
close WHITELIST;
}
$template->param('whitelist' => \@whitelist);
my @blacklist;
if(-s '/usr/local/etc/easytecc/shell2ban/BLACKLIST'){
open BLACKLIST, '</usr/local/etc/easytecc/shell2ban/BLACKLIST';
while (<BLACKLIST>){
my ($ip,$ttl,$note) = $_ =~ m/^([^\s]+)\s+([0-9]+)\s*#*(.*)$/;
if(defined($ip)){
logline("debug","###ip: $ip ### ttl: $ttl ### note: $note ###");
if(!defined($ttl)){
$ttl = 0;
}
elsif($ttl > 0){
#$ttl = `/bin/sh -c "date -j -f '%s' '$ttl' '+%d.%m.%Y %H:%M:%S'"`;
#chomp $ttl;
$ttl = $strftime{"%d.%m.%Y %H:%M", $ttl};
}
my @keys = split(/\//, 'FIREWALL/BLACKLIST/' . $ip);
if(defined($note) && length($note)){
note_to_hashfile(\@keys,'WHITELIST',$note);
} else {
$note = note_from_hashfile(\@keys);
$note = $note->{text};
}
push @blacklist, { ip => $ip, ttl => $ttl, note => $note };
}
}
close BLACKLIST;
}
$template->param('blacklist' => \@blacklist);
my @dyn_whitelist;
if(-s '/usr/local/etc/easytecc/shell2ban/DYN_WHITELIST'){
open DYN_WHITELIST, '</usr/local/etc/easytecc/shell2ban/DYN_WHITELIST';
while (<DYN_WHITELIST>){
my ($ip,$ttl,$hits) = $_ =~ m/^([^\/]+)\/32\s+([0-9]+)([0-9])$/;
if(defined($ip)){
if(!defined($ttl)){
$ttl = 0;
}
elsif($ttl > 0){
$ttl *= 10;
#$ttl = `/bin/sh -c "date -j -f '%s' '$ttl' '+%d.%m.%Y %H:%M:%S'"`;
#chomp $ttl;
$ttl = $strftime{"%d.%m.%Y %H:%M", $ttl};
}
push @dyn_whitelist, { ip => $ip, ttl => $ttl, hits => $hits };
}
}
close DYN_WHITELIST;
}
@dyn_whitelist = sort { inet_aton($a->{'ip'}) cmp inet_aton($b->{'ip'}) } @dyn_whitelist;
$template->param('dyn_whitelist' => \@dyn_whitelist);
my @dyn_blacklist;
if(-s '/usr/local/etc/easytecc/shell2ban/DYN_BLACKLIST'){
open DYN_BLACKLIST, '</usr/local/etc/easytecc/shell2ban/DYN_BLACKLIST';
while (<DYN_BLACKLIST>){
my ($ip,$ttl,$hits) = $_ =~ m/^([^\/]+)\/32\s+([0-9]+)([0-9])$/;
if(defined($ip)){
if(!defined($ttl)){
$ttl = 0;
}
elsif($ttl > 0){
$ttl *= 10;
#$ttl = `/bin/sh -c "date -j -f '%s' '$ttl' '+%d.%m.%Y %H:%M:%S'"`;
#chomp $ttl;
$ttl = $strftime{"%d.%m.%Y %H:%M", $ttl};
}
push @dyn_blacklist, { ip => $ip, ttl => $ttl, hits => $hits };
}
}
close DYN_BLACKLIST;
}
@dyn_blacklist = sort { inet_aton($a->{'ip'}) cmp inet_aton($b->{'ip'}) } @dyn_blacklist;
$template->param('dyn_blacklist' => \@dyn_blacklist);
if(-e '/usr/local/etc/easytecc/shell2ban/.web2ban.disabled'){
$template->param('web2ban_disabled' => '1');
} else {
my @web2ban_whitelist;
if(-s '/usr/local/etc/easytecc/shell2ban/WEB2BAN_WHITELIST'){
open WEB2BAN_WHITELIST, '</usr/local/etc/easytecc/shell2ban/WEB2BAN_WHITELIST';
my $index = 1;
my ($name,$note,$list,$key,$rule);
while (<WEB2BAN_WHITELIST>){
# name or note
if($_ =~ m/^#\s*(.*)$/){
if(!defined($name)){
$name = $1;
} elsif(!defined($note)){
$note = $1;
} else {
$note .= $1;
}
}
# LogMessage line
elsif($_ =~ m/^LogMessage\s\"#shell2ban\.web2ban#(5|6|8|9)#([^#]+)#[^#]+#\"\s\"expr=\s\\$/){
($list,$key) = ($1,$2);
}
# rule
elsif($_ =~ m/^(.+)\\$/){
if(!defined($rule)){
$rule = $1;
} else {
$rule .= '<br>' . $1;
}
}
# end
elsif($_ =~ m/^\"$/){
if(defined($name) && defined($note) && defined($list) && defined($key) && defined($rule)){
push @web2ban_whitelist, { index => $index, name => $name, note => $note, key => $key, rule => $rule, testmode => $list > 7 ? 1 : 0 };
$name = undef;
$note = undef;
$rule = undef;
$index++;
}
}
}
close WEB2BAN_WHITELIST;
}
$template->param('web2ban_whitelist' => \@web2ban_whitelist);
my @web2ban_blacklist;
if(-s '/usr/local/etc/easytecc/shell2ban/WEB2BAN_BLACKLIST'){
open WEB2BAN_BLACKLIST, '</usr/local/etc/easytecc/shell2ban/WEB2BAN_BLACKLIST';
my $index = 1;
my ($name,$note,$key,$rule);
while (<WEB2BAN_BLACKLIST>){
# name or note
if($_ =~ m/^#\s*(.*)$/){
if(!defined($name)){
$name = $1;
} elsif(!defined($note)){
$note = $1;
} else {
$note .= $1;
}
}
# LogMessage line
elsif($_ =~ m/^LogMessage\s\"#shell2ban\.web2ban#(5|6|8|9)#([^#]+)#[^#]+#\"\s\"expr=\s\\$/){
($list,$key) = ($1,$2);
}
# rule
elsif($_ =~ m/^(.+)\\$/){
if(!defined($rule)){
$rule = $1;
} else {
$rule .= '<br>' . $1;
}
}
# end
elsif($_ =~ m/^\"$/){
if(defined($name) && defined($note) && defined($key) && defined($rule)){
#$key =~ s/(.{16})/$1<span style="display:block;"><\/span>/g;
push @web2ban_blacklist, { index => $index, name => $name, note => $note, key => $key, rule => $rule, testmode => $list > 7 ? 1 : 0 };
$name = undef;
$note = undef;
$rule = undef;
$index++;
}
}
}
close WEB2BAN_BLACKLIST;
}
$template->param('web2ban_blacklist' => \@web2ban_blacklist);
my @web2ban_test_whitelist;
if(-s '/usr/local/etc/easytecc/shell2ban/WEB2BAN_TEST_WHITELIST'){
open WEB2BAN_TEST_WHITELIST, '</usr/local/etc/easytecc/shell2ban/WEB2BAN_TEST_WHITELIST';
while (<WEB2BAN_TEST_WHITELIST>){
my ($ip,$ttl,$hits) = $_ =~ m/^([^\/]+)\/32\s+([0-9]+)([0-9])$/;
if(defined($ip)){
if(!defined($ttl)){
$ttl = 0;
}
elsif($ttl > 0){
$ttl *= 10;
#$ttl = `/bin/sh -c "date -j -f '%s' '$ttl' '+%d.%m.%Y %H:%M:%S'"`;
#chomp $ttl;
$ttl = $strftime{"%d.%m.%Y %H:%M", $ttl};
}
push @web2ban_test_whitelist, { ip => $ip, ttl => $ttl, hits => $hits };
}
}
close WEB2BAN_TEST_WHITELIST;
}
@web2ban_test_whitelist = sort { inet_aton($a->{'ip'}) cmp inet_aton($b->{'ip'}) } @web2ban_test_whitelist;
$template->param('web2ban_test_whitelist' => \@web2ban_test_whitelist);
my @web2ban_test_blacklist;
if(-s '/usr/local/etc/easytecc/shell2ban/WEB2BAN_TEST_BLACKLIST'){
open WEB2BAN_TEST_BLACKLIST, '</usr/local/etc/easytecc/shell2ban/WEB2BAN_TEST_BLACKLIST';
while (<WEB2BAN_TEST_BLACKLIST>){
my ($ip,$ttl,$hits) = $_ =~ m/^([^\/]+)\/32\s+([0-9]+)([0-9])$/;
if(defined($ip)){
if(!defined($ttl)){
$ttl = 0;
}
elsif($ttl > 0){
$ttl *= 10;
#$ttl = `/bin/sh -c "date -j -f '%s' '$ttl' '+%d.%m.%Y %H:%M:%S'"`;
#chomp $ttl;
$ttl = $strftime{"%d.%m.%Y %H:%M", $ttl};
}
push @web2ban_test_blacklist, { ip => $ip, ttl => $ttl, hits => $hits };
}
}
close WEB2BAN_TEST_BLACKLIST;
}
@web2ban_test_blacklist = sort { inet_aton($a->{'ip'}) cmp inet_aton($b->{'ip'}) } @web2ban_test_blacklist;
$template->param('web2ban_test_blacklist' => \@web2ban_test_blacklist);
}
if(-e '/usr/local/etc/easytecc/shell2ban/.scan2ban.disabled'){
$template->param('scan2ban_disabled' => '1');
} else {
my @scan2ban_whitelist;
if(-s '/usr/local/etc/easytecc/shell2ban/SCAN2BAN_WHITELIST'){
open SCAN2BAN_WHITELIST, '</usr/local/etc/easytecc/shell2ban/SCAN2BAN_WHITELIST';
while (<SCAN2BAN_WHITELIST>){
my ($port,$note) = split(/#/,$_,2);
if(defined($port)){
$port =~ s/,/, /g;
push @scan2ban_whitelist, { port => $port, note => $note };
}
}
close SCAN2BAN_WHITELIST;
}
$template->param('scan2ban_whitelist' => \@scan2ban_whitelist);
if(-e '/usr/local/etc/easytecc/shell2ban/.scan2ban.block.not.whitelisted'){
$template->param('scan2ban_block_not_whitelisted' => '1');
} else {
$template->param('scan2ban_block_not_whitelisted' => '0');
}
}
if(-e '/usr/local/etc/easytecc/shell2ban/.share2ban.disabled'){
$template->param('share2ban_disabled' => '1');
} else {
$template->param('share2ban_disabled' => '0');
}
}
if($error){
my $subtemplate = error($error);
my $errorhtml = $$subtemplate->output;
if($input{'active_tab'} eq 2){
$template->param('error_tab2' => $errorhtml);
} else {
$template->param('error' => $errorhtml);
}
}
$template->param('result' => $result);
logline("debug","result = " . $result);
$success_text = $result;
#$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=change_firewall&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub list_add_ip{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'list_add_ip.html');
$template->param('whitelist' => $input{'whitelist'});
$template->param('blacklist' => $input{'blacklist'});
$template->param('ip' => $input{'ip'});
$template->param('ttl' => $input{'ttl'});
$template->param('ttl' => $input{'note'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_list_add_ip{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_list_add_ip result:$result###");
if($result){
}
else{
#$input{'ip'} =~ s/\//\\\//;
if(defined($input{'ttl'}) && $input{'ttl'} > 0){
my $timestamp = `/bin/sh -c "date -j '+%s'"`;
chomp $timestamp;
$input{'ttl'} = $timestamp + ($input{'ttl'}*60*60);
} else {
$input{'ttl'} = 0;
}
my $list = $input{'whitelist'} ? 'WHITELIST' : 'BLACKLIST';
my $listfile = '/usr/local/etc/easytecc/shell2ban/' . $list;
#system("echo '" . $input{'ip'} . " " . $input{'ttl'} . " 1' >> " . $listfile);
system("echo '" . $input{'ip'} . " " . $input{'ttl'} . " #" . $input{'note'} . "' >> " . $listfile);
my @keys = split(/\//, 'FIREWALL/' . $list . '/' . $input{'ip'});
my $title = $list;
my $text = $input{'note'};
if(!note_to_hashfile(\@keys,$title,$text)){
$error = "L__Beim Speichern der Notiz ist ein Fehler aufgetreten.__L";
}
}
$result = 'L__Fehler__L: ' . $error if $error;
return error($error) if $error;
$result = 'L__Die IP / das Netzwerk wurde hinzugefügt.__L';
$success_text = $result;
$template->param('result' => $result);
logline("debug","result = " . $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=change_firewall&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub scan2ban_add_port{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'scan2ban_add_port.html');
$template->param('whitelist' => $input{'whitelist'});
$template->param('blacklist' => $input{'blacklist'});
$template->param('port' => $input{'port'});
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_scan2ban_add_port{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
logline("debug","exec_scan2ban_add_port result:$result###");
if($result){
}
else{
my $list = $input{'whitelist'} ? 'WHITELIST' : 'BLACKLIST';
my $listfile = '/usr/local/etc/easytecc/shell2ban/SCAN2BAN_' . $list;
#my $port;
#foreach $port (split(/[,\s]+/,$input{'port'})){
# system("echo '" . $port . " #" . $input{'note'} . "' >> " . $listfile);
#}
$input{'port'} =~ s/\s+//g;
system("echo '" . $input{'port'} . " #" . $input{'note'} . "' >> " . $listfile);
my $portstring = $input{'port'};
$portstring =~ s/[^0-9]//g;
my @keys = split(/\//, 'FIREWALL/SCAN2BAN_' . $list . '/' . $portstring);
my $title = $list;
my $text = $input{'note'};
if(!note_to_hashfile(\@keys,$title,$text)){
$error = "L__Beim Speichern der Notiz ist ein Fehler aufgetreten.__L";
}
}
$result = 'L__Fehler__L: ' . $error if $error;
return error($error) if $error;
$result = 'L__Ports wurden hinzugefügt.__L';
$success_text = $result;
$template->param('result' => $result);
logline("debug","result = " . $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=change_firewall&active_tab=3&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub web2ban_add_edit_delete_rule{
my $action = shift;
my $listname = $input{'whitelist'} ? 'WHITELIST' : 'BLACKLIST';
my $listfile = '/usr/local/etc/easytecc/shell2ban/WEB2BAN_' . $listname;
my $listfile_new = '/tmp/WEB2BAN_' . $listname . '.' . $$;
my $logextra = '[%{SERVER_NAME}] %{REQUEST_SCHEME}://%{HTTP_HOST} %{THE_REQUEST} %{REQUEST_STATUS} \"%{HTTP_REFERER}\" \"%{HTTP_USER_AGENT}\"';
my $error = '';
my $errortext;
if($action eq 'add'){
$errortext = "L__Beim Hinzufügen der Regel ist ein Fehler aufgetreten.__L";
} elsif($action eq 'edit'){
$errortext = "L__Beim Editieren der Regel ist ein Fehler aufgetreten.__L";
if(! -s $listfile){
return $errortext;
}
} elsif($action eq 'delete'){
$errortext = "L__Beim Löschen der Regel ist ein Fehler aufgetreten.__L";
if(! -s $listfile){
return $errortext;
}
}
open WEB2BAN_LIST, "<$listfile";
open WEB2BAN_LIST_NEW, ">$listfile_new";
my $index = 1;
my ($name,$note,$list,$ttl,$rule,$rule_rows);
while (<WEB2BAN_LIST>){
chomp;
if($action eq 'add'){
print WEB2BAN_LIST_NEW $_ . "\n";
next;
} else {
if($index ne $input{'index'}){
print WEB2BAN_LIST_NEW $_ . "\n";
if($index gt $input{'index'}){
next;
}
}
}
# name or note
if($_ =~ m/^#\s*(.*)$/){
if(!defined($name)){
$name = $1;
} elsif(!defined($note)){
$note = $1;
} else {
$note .= $1;
}
}
# LogMessage line
elsif($_ =~ m/^LogMessage\s\"#shell2ban\.web2ban#(5|6|8|9)#([^#]+)#[^#]+#\"\s\"expr=\s\\$/){
($list,$key) = ($1,$2);
}
# rule
elsif($_ =~ m/^(.+)\\$/){
if(!defined($rule)){
$rule = $1;
$rule_rows = 1;
} else {
$rule .= "\n" . $1;
$rule_rows++;
}
}
# end
elsif($_ =~ m/^\"$/){
if($index eq $input{'index'}){
if($action eq 'edit'){
$name=$input{'name'};
$note=encode('utf-8',$input{'note'});
$note =~ s/^#//mg;
$note =~ s/^/# /mg;
$list = $input{'whitelist'} ? 5 : 6;
if($input{'testmode'}){
$list += 3;
}
$rule=$input{'rule'};
$rule =~ s/[\\\s]+$//mg;
$rule =~ s/$/ \\/mg;
$key=md5_hex($rule);
print WEB2BAN_LIST_NEW "# $name\n$note\n";
print WEB2BAN_LIST_NEW "LogMessage \"#shell2ban\.web2ban#$list#$key#$logextra#\" \"expr= \\\n";
print WEB2BAN_LIST_NEW "$rule\n\"\n";
}
}
$name = undef;
$note = undef;
$rule = undef;
$index++;
}
}
close WEB2BAN_LIST;
if($action eq 'add'){
$name=$input{'name'};
$note=encode('utf-8',$input{'note'});
$note =~ s/^#//mg;
$note =~ s/^/# /mg;
$list = $input{'whitelist'} ? 5 : 6;
if($input{'testmode'}){
$list += 3;
}
$rule=$input{'rule'};
$rule =~ s/[\\\s]+$//mg;
$rule =~ s/$/ \\/mg;
$key=md5_hex($rule);
print WEB2BAN_LIST_NEW "# $name\n$note\n";
print WEB2BAN_LIST_NEW "LogMessage \"#shell2ban\.web2ban#$list#$key#$logextra#\" \"expr= \\\n";
print WEB2BAN_LIST_NEW "$rule\n\"\n";
}
close WEB2BAN_LIST_NEW;
my $got = `/usr/iports/bin/sudo /usr/iports/sbin/httpd -C "LoadModule mpm_prefork_module libexec/apache24/mod_mpm_prefork.so" -C "LoadModule log_debug_module libexec/apache24/mod_log_debug.so" -t -f $listfile_new 2>&1`;
chomp $got;
if($got !~ m/^Syntax OK$/s){
$error = $got;
$error =~ s/^AH[0-9]+:[^:]+:/$errortext\n /;
} else {
# bsd cat is buggy as it does not throw all errors to stderr
$got = `cp $listfile_new $listfile 2>&1 && rm -f $listfile_new && /usr/iports/bin/sudo /usr/sbin/reload_apache 2>&1`;
chomp $got;
if(length($got)){
$error = "$errortext\n$got";
} else {
system("cd /usr/local/etc/easytecc/shell2ban && rm -f WEB2BAN_HTTPDERRORLOG.regex && /usr/bin/grep '#shell2ban.web2ban#' WEB2BAN_*LIST | sed 's/^.*#shell2ban.web2ban#[5689]#// ; s/#.*//' | while read UID ; do NAME=`grep -h -B 2 \"\$UID\" WEB2BAN_*LIST | sed '1!d; s/^# *//'` ; echo \"s/\$UID/\$NAME/\" >> WEB2BAN_HTTPDERRORLOG.regex; done;");
}
}
return $error;
}
sub web2ban_edit_rule{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'web2ban_add_edit_rule.html');
$template->param('whitelist' => $input{'whitelist'});
$template->param('blacklist' => $input{'blacklist'});
$template->param('edit' => 1);
$template->param('add' => 0);
my $listname = $input{'whitelist'} ? 'WEB2BAN_WHITELIST' : 'WEB2BAN_BLACKLIST';
my $listfile = '/usr/local/etc/easytecc/shell2ban/' . $listname;
if(! -s $listfile){
return modal_error("L__Beim Lesen der Regel ist ein Fehler aufgetreten.__L");
}
open WEB2BAN_LIST, "<$listfile";
my $index = 1;
my ($name,$note,$list,$key,$rule,$rule_rows);
while (<WEB2BAN_LIST>){
chomp;
# name or note
if($_ =~ m/^#\s*(.*)$/){
if(!defined($name)){
$name = $1;
} elsif(!defined($note)){
$note = $1;
} else {
$note .= $1;
}
}
# LogMessage line
elsif($_ =~ m/^LogMessage\s\"#shell2ban\.web2ban#(5|6|8|9)#([^#]+)#[^#]+#\"\s\"expr=\s\\$/){
($list,$key) = ($1,$2);
}
# rule
elsif($_ =~ m/^(.+)\\$/){
if(!defined($rule)){
$rule = $1;
$rule_rows = 1;
} else {
$rule .= "\n" . $1;
$rule_rows++;
}
}
# end
elsif($_ =~ m/^\"$/){
if(defined($name) && defined($note) && defined($list) && defined($key) && defined($rule)){
push @web2ban_blacklist, { index => $index, name => $name, note => $note, key => $key, rule => $rule, rule_rows => $rule_rows < 3 ? 3 : $rule_rows, testmode => $list > 7 ? 1 : 0 };
if($index eq $input{'index'}){
last;
} else {
$name = undef;
$note = undef;
$rule = undef;
$index++;
}
}
}
}
close WEB2BAN_LIST;
if($index ne $input{'index'}){
return modal_error("L__Beim Lesen der Regel ist ein Fehler aufgetreten.__L");
}
$template->param('index' => $index);
$template->param('name' => $name);
$template->param('note' => $note);
$template->param('key' => $key);
$template->param('rule' => $rule);
$template->param('rule_rows' => $rule_rows < 3 ? 3 : $rule_rows);
$template->param('testmode' => $list > 7 ? 1 : 0);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_web2ban_edit_rule{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
my $error = '';
logline("debug","exec_web2ban_edit_rule result:$result###");
if($result){
}
else{
$error = web2ban_add_edit_delete_rule('edit');
}
$result = 'L__Fehler__L: ' . $error if $error;
return error($error) if $error;
$result = 'L__Die Regel wurde geändert.__L';
$success_text = $result;
$template->param('result' => $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=change_firewall&active_tab=2&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub web2ban_add_rule{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'web2ban_add_edit_rule.html');
$template->param('whitelist' => $input{'whitelist'});
$template->param('blacklist' => $input{'blacklist'});
$template->param('edit' => 0);
$template->param('add' => 1);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_web2ban_add_rule{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
my $error = '';
logline("debug","exec_web2ban_add_rule result:$result###");
if($result){
}
else{
$error = web2ban_add_edit_delete_rule('add');
}
$result = 'L__Fehler__L: ' . $error if $error;
return error($error) if $error;
$result = 'L__Die Regel wurde hinzugefügt.__L';
$success_text = $result;
$template->param('result' => $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=change_firewall&active_tab=2&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub logrotate{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'change_logrotate.html');
my $count=0;
my $when='';
if(-s '/usr/local/etc/newsyslog.conf.d/apache_mysql_mail.conf'){
my $count_when = `awk '/^\\// { print \$4"\\n"\$6; exit 0; }' /usr/local/etc/newsyslog.conf.d/apache_mysql_mail.conf`;
chomp($count_when);
($count,$when) = split(/[\r\n]+/,$count_when);
}
#logrotate_when_never
if($when eq '$D'){
$template->param('logrotate_when_daily' => 1);
}
elsif($when eq '$W1'){
$template->param('logrotate_when_weekly' => 1);
}
elsif($when eq '$M1'){
$template->param('logrotate_when_monthly' => 1);
} else {
$template->param('logrotate_when_never' => 1);
}
$template->param('logrotate_count' => $count);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_logrotate{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $result = $validation_result;
my $error = '';
logline("debug","exec_logrotate result:$result###");
if($result){
}
else{
if($input{'logrotate_when'} eq 'never'){
`rm -f /usr/local/etc/newsyslog.conf.d/apache_mysql_mail.conf`;
if(-f '/usr/local/etc/newsyslog.conf.d/apache_mysql_mail.conf'){
$error = "L__Fehler beim Löschen der newsyslog-Datei__L /usr/local/etc/newsyslog.conf.d/apache_mysql_mail.conf";
}
} else {
if(! -f '/usr/local/etc/newsyslog.conf.d/apache_mysql_mail.conf'){
if(! -f '/usr/local/etc/newsyslog.conf.d/'){
`/usr/iports/bin/sudo /usr/sbin/webmkdir -p /usr/local/etc/newsyslog.conf.d 2>&1`;
`/usr/iports/bin/sudo /usr/sbin/chown.pl admin:vuser /usr/local/etc/newsyslog.conf.d d 2>&1`;
}
`cat /usr/local/etc/easytecc/newsyslog_apache_mysql_mail.conf > /usr/local/etc/newsyslog.conf.d/apache_mysql_mail.conf`;
if(! -f '/usr/local/etc/newsyslog.conf.d/apache_mysql_mail.conf'){
return(error("L__Fehler beim Anlegen der newsyslog-Datei__L /usr/local/etc/newsyslog.conf.d/apache_mysql_mail.conf"));
}
#change awstats cron
`sed -i '' 's/^[0-9]*[^0-9]*00*\\(.*awstats_updateall.pl.*\\)\$/55 23\\1/' /home/web/cronfile && /usr/iports/bin/sudo /usr/sbin/webcron`
}
# remove lars' logrotate
if(-f '/etc/newsyslog.conf.d/default_logrotate.conf'){
`cp /etc/newsyslog.conf.d/default_logrotate.conf /usr/local/etc/easytecc/backup_files/ 2>/dev/null`;
`cat /dev/null > /etc/newsyslog.conf.d/default_logrotate.conf`;
}
my $when = '';
if($input{'logrotate_when'} eq 'daily'){
$when = '\$D';
}
elsif($input{'logrotate_when'} eq 'weekly'){
$when = '\$W1';
}
elsif($input{'logrotate_when'} eq 'monthly'){
$when = '\$M1';
}
my $count = $input{'logrotate_count'};
$error = `sed -i '' "s/^\\(\\/[^:]*:[^0-9]*[0-9]*[^0-9]*\\)[0-9]*\\([^\\*]*\\*[^\\\$]*\\)\\\$[DWM]1*\\(.*\\)\$/\\1$count\\2$when\\3/" /usr/local/etc/newsyslog.conf.d/apache_mysql_mail.conf 2>&1`;
if($error){
$error = "L__Fehler beim Ändern der newsyslog-Datei__L /usr/local/etc/newsyslog.conf.d/apache_mysql_mail.conf: $error";
}
}
}
$result = 'L__Fehler__L: ' . $error if $error;
return error($error) if $error;
$result = 'L__Die Einstellungen wurden gespeichert.__L';
$success_text = $result;
$template->param('result' => $result);
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_logfiles&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub search_logs{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $ip = $input{'ip'};
my $hostname = `/usr/bin/host -W 1 -t PTR $ip 2>/dev/null || echo 'NXDOMAIN' | /usr/bin/tail -n 1 2>/dev/null | /usr/bin/sed '/NXDOMAIN/d ; s/^.*LOCALHOST.*\$//i ; /^\$/d ; s/^.* // ; s/\.\$//' 2>/dev/null`;
chomp($hostname);
my $search_host_or_ip = length($hostname) ? "($ip|$hostname)" : $ip;
$search_host_or_ip =~ s/\./\\\./g;
# my $result = `/usr/iports/bin/sudo /usr/bin/bzgrep -E '$search' /var/log/auth.log /var/log/auth.log.0.bz2 /var/log/auth.log.1.bz2 /var/log/messages /var/log/messages.0.bz2 /var/log/messages.1.bz2 /var/log/maillog /var/log/maillog.0.bz2 /var/log/maillog.1.bz2 /var/log/apache/httpd-error.log /var/log/apache/httpd-error.log.0.bz2 /var/log/apache/httpd-error.log.1.bz2 2>/dev/null`;
my $servername = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
chomp $servername;
my $result='';
my %logfiles = ( 'TCPDUMP' => '/var/log/tcpdump.log', 'AUTHLOG' => '/var/log/auth.log', 'MESSAGES' => '/var/log/messages', 'MAILLOG' => '/var/log/maillog', 'HTTPDERRORLOG' => '/var/log/apache/httpd-error.log', 'MYSQLLOG' => '/var/db/mysql/' . $servername . '.err' );
my $logname;
my $prefix = $input{'whitelist'} ? 'WHITELIST' : 'BLACKLIST';
# sort explicit
#foreach $logname (keys %logfiles){
foreach $logname ('TCPDUMP','AUTHLOG','MAILLOG','MESSAGES','HTTPDERRORLOG','MYSQLLOG'){
my $regexfile = '/usr/local/etc/easytecc/shell2ban/' . $prefix . '_' . $logname . '.regex';
my $base_logfile = $logfiles{$logname};
my $groupresult='';
my $index;
foreach $index (-1 .. 6){
my $logfile = $base_logfile . ($index >= 0 ? ".$index.bz2" : '');
if(-e $logfile){
#logline("debug","/usr/iports/bin/sudo /usr/bin/bzgrep -E '$search' $logfile 2>/dev/null | /usr/bin/sed -E -f $regexfile 2>/dev/null");
my $search = $search_host_or_ip;
my $logresult = '';
if($logname eq 'HTTPDERRORLOG'){
$search = "\\[[a-z]* $search";
}
if($logname eq 'HTTPDERRORLOG' && -e '/usr/local/etc/easytecc/shell2ban/WEB2BAN_HTTPDERRORLOG.regex'){
$logresult = `/usr/iports/bin/sudo /usr/sbin/bzgrep -E '$search' $logfile 2>/dev/null | /usr/bin/sed -E -f $regexfile 2>/dev/null | /usr/bin/tail -r -n 100 2>/dev/null | /usr/bin/sed -f '/usr/local/etc/easytecc/shell2ban/WEB2BAN_HTTPDERRORLOG.regex' 2>/dev/null`;
} else {
$logresult = `/usr/iports/bin/sudo /usr/sbin/bzgrep -E '$search' $logfile 2>/dev/null | /usr/bin/sed -E -f $regexfile 2>/dev/null | /usr/bin/tail -r -n 100 2>/dev/null`;
}
logline("debug","/usr/iports/bin/sudo /usr/sbin/bzgrep -E '$search' $logfile 2>/dev/null");
chomp($logresult);
if(length($logresult)){
$groupresult .= "$logresult\n";
}
logline("debug","##$search##$logfile##$logresult##$groupresult##");
}
}
if(length($groupresult)){
logline("debug","##$search##$base_logfile##$groupresult##$result##");
if(length($result)){
$result .= "\n";
}
$result .= "[$base_logfile*]\n$groupresult";
}
}
if(!length($result)){
$result = 'L__keine Logeinträge__L';
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(modal_message('L__Logeinträge für__L ' . $ip . (length($hostname) ? " ($hostname)" : ''),'<pre>' . $result . '</pre>'));
}
sub whois{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $ip = $input{'ip'};
my $hostname = `/usr/bin/host -W 1 -t PTR $ip 2>/dev/null | /usr/bin/tail -n 1 2>/dev/null | /usr/bin/sed '/NXDOMAIN/d ; s/^.*LOCALHOST.*\$//i ; /^\$/d ; s/^.* // ; s/\.\$//' 2>/dev/null`;
chomp($hostname);
my $result=`wget -q -O - http://info.api.2014.de/api/info/ip/$ip/whois 2>/dev/null | sed '/^#/d ; s/^\\(.*abuse.*\@.*\\)\$/<strong>\\1<\\/strong>/i ; s/^\\(.*[0-9][0-9]*\\.[0-9][0-9]*\\.[0-9][0-9]*\\.[0-9][0-9]*\\/[0-9][0-9]*.*\\)\$/<strong>\\1<\\/strong>/' 2>/dev/null | cat -s`;
# my $result=`whois $ip 2>/dev/null | sed '/^#/d ; s/^\\(.*abuse.*\\)\$/<strong>\\1<\\/strong>/i' 2>/dev/null | cat -s`;
# if($result !~ m/CIDR:/){
# $result=`whois '= n + $ip' 2>/dev/null | sed '/^#/d ; s/^\\(.*abuse.*\\)\$/<strong>\\1<\\/strong>/i' 2>/dev/null | cat -s`;
# }
##my $result=`whois $ip 2>/dev/null`;
#my $whois_server = `whois -I $ip 2>/dev/null | sed '/^whois:/!d ; s/^whois: *//' 2>/dev/null`;
#chomp($whois_server);
#
#if(!length($whois_server)){
#
# $whois_server = 'whois.arin.net';
#
#}
#
#my $whois_param;
#if($whois_server eq 'whois.arin.net'){
#
# $whois_param = " \"= n + $ip\"";
#
#} else {
#
# $whois_param .= " $ip";
#
#}
#
#my $result=`whois -h $whois_server $whois_param 2>/dev/null | sed '/^#/d ; s/^\\(.*abuse.*\\)\$/<strong>\\1<\\/strong>/i' 2>/dev/null | cat -s`;
chomp($result);
if(!length($result)){
$result = 'L__keine Whois-Daten__L';
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(modal_message('L__Whois-Daten für__L ' . $ip . (length($hostname) ? " ($hostname)" : ''),'<pre>' . $result . '</pre>'));
}
sub show_create_dkim{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $domain = $input{'domain'};
if(! -s "/etc/dkim/txt/$domain"){
`/usr/sbin/opendkim-add-domain.sh $domain`;
}
if(! -s "/etc/dkim/txt/$domain"){
$result = 'L__Es ist ein Fehler aufgetreten__L.';
} else {
$result = `cat "/etc/dkim/txt/$domain"`;
chomp($result);
my ($key,$type,$value) = split(/\s/,$result,3);
$value =~ s/\"//g;
$result = "L__Bitte setzen Sie in der__L <a href=\"https://www.hostnet.de/konto.html#dns:$domain\" target=\"blank\">L__DNS-Verwaltung für__L $domain</a> L__folgenden Eintrag__L:<br><br>
L__Hostname__L<br><br>
<pre><strong>$key</strong></pre><br>
L__Typ__L<br><br>
<pre><strong>$type</strong></pre><br>
L__Ziel__L<br><br>
<pre style=\"white-space: normal;\"><strong>$value</strong></pre><br>
L__um DKIM für die Domain zu konfigurieren__L.";
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(modal_message('L__DKIM für__L ' . $domain,$result));
}
sub info_mailuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'info_mailuser.html');
my $mailuser = $input{'mailuser'};
my $idn_mailuser = encode('utf-8', email_to_unicode($mailuser));
my $domain = $input{'domain'};
$template->param('mailuser' => $mailuser);
$template->param('idn_mailuser' => $idn_mailuser);
$template->param('domain' => $domain);
#if($session && $session->param('is_mailuser')){
#
# $template->param('is_mailuser' => 1);
#
#}
my $mailstats=`$easytecc_prefix/mailstats.pl $mailuser 2>/dev/null`;
chomp $mailstats;
my @mailstats=split(/[\r\n]+/,$mailstats);
if(!scalar @mailstats){
return(error("L__Beim Abrufen der Details ist ein Fehler aufgetreten.__L"));
}
my $table_data = {};
my $table_data_sum = {};
foreach my $boxstats (@mailstats){
my ($box,$guid,$messages,$unseen,$spam,$vsize) = $boxstats =~ m/^[^\/]*\/([^\(]+)\(?([a-f0-9]+)?\)?\smessages=([0-9]+)\sunseen=([0-9]+)\sspam=([0-9]+)\svsize=([0-9]+)$/;
if($box ne '*'){
my $box_html = $box;
$box_html =~ s/\./ \/ /g;
$table_data->{$box}{'box'} = $box_html;
$table_data->{$box}{'box_encoded'} = encode_base64url($box_html);
$table_data->{$box}{'guid'} = $guid;
$table_data->{$box}{'messages'} = $messages;
$table_data->{$box}{'unseen'} = $unseen;
$table_data->{$box}{'spam'} = $spam;
$table_data->{$box}{'size'} = easytecc3::getsize($vsize / 1024);
$table_data->{$box}{'mailuser'} = $mailuser;
$table_data->{$box}{'domain'} = $domain;
} else {
$table_data_sum->{$box}{'box'} = "L__Summe__L";
$table_data_sum->{$box}{'messages'} = $messages;
$table_data_sum->{$box}{'unseen'} = $unseen;
$table_data_sum->{$box}{'spam'} = $spam;
$table_data_sum->{$box}{'size'} = easytecc3::getsize($vsize / 1024);
$table_data_sum->{$box}{'mailuser'} = $mailuser;
$table_data_sum->{$box}{'domain'} = $domain;
}
}
#$template->param('table_tr_info_mailuser_template' => $mailstats);
easytecc3::table_e4($template, $table_data, 'table_tr_info_mailuser_template.html');
easytecc3::table_e4($template, $table_data_sum, 'table_tr_info_mailuser_template_sum.html');
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub import_mailuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'import_mailuser.html');
my $mailuser = $input{'mailuser'};
my $idn_mailuser = encode('utf-8', email_to_unicode($mailuser));
my $domain = $input{'domain'};
$template->param('mailuser' => $mailuser);
$template->param('idn_mailuser' => $idn_mailuser);
$template->param('domain' => $domain);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_import_mailuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $error = '';
my $result = $validation_result;
logline("debug","exec_import_mailuser result:$result###");
if($result){
}
else{
my $host2 = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
chomp $host2;
my $user2 = $input{'mailuser'};
my $password2 = easytecc3::decrypt("/usr/local/etc/easytecc/$user2.pass");
my $host1 = $input{'host'};
my $user1 = $input{'user'};
my $password1 = $input{'pass'};
my $pidfile = "/tmp/imapsync-$user2.pid";
if(-f $pidfile){
$error .= 'L__Es wird bereits ein Import für dieses Postfach ausgeführt__L';
} else {
my $imapsync = "/usr/iports/bin/imapsync";
if(! -x $imapsync){
$imapsync = "/usr/local/bin/imapsync";
}
if(! -x $imapsync){
$error .= 'L__Imapsync ist auf diesem Server nicht installiert__L';
} else {
$imapsync .= ' --maxbytespersecond 256';
my $logfile = "/tmp/imapsync-$user2.log";
my $successfile = "/tmp/imapsync-$user2.ok";
if (-f $successfile){
unlink $successfile;
}
$| = 1;
#child
unless(my $pid = fork){
close (STDIN);
close (STDOUT);
close (STDERR);
open STDIN, '>/dev/null';
open STDOUT, '>/dev/null';
open STDERR, '>/dev/null';
#`. /etc/apache24/envvars.d/perl.env; $imapsync --host1 $host1 --user1 $user1 --password1 '$password1' --host2 $host2 --user2 $user2 --password2 '$password2' --pidfile $pidfile > $logfile 2>&1 &`;
my $cmd = '';
# suexec clears env
$cmd .= '. /etc/apache24/envvars.d/perl.env;';
# imapsync detects cgo otherwise
$cmd .= 'SERVER_SOFTWARE=;';
$cmd .= "$imapsync --host1 $host1 --user1 $user1 --password1 '$password1' --host2 $host2 --user2 $user2 --password2 '$password2' --pidfile $pidfile --logfile $logfile";
$cmd .= ">$logfile 2>&1 ";
$cmd .= "&& touch $successfile";
system "$cmd &";
# some time to write a pidfile
#sleep(1);
logline("debug","exec_import_mailuser cmd:$cmd###");
#`echo ". /etc/apache24/envvars.d/perl.env" > $cmdfile`;
#`echo SERVER_SOFTWARE= >> $cmdfile`;
#`echo "$imapsync --host1 $host1 --user1 $user1 --password1 '$password1' --host2 $host2 --user2 $user2 --password2 '$password2' --pidfile $pidfile --logfile $logfile > $logfile 2>&1" >> $cmdfile`;
#`. $cmdfile &`;
#system "/bin/sh -c"," . /etc/apache24/envvars.d/perl.env; $imapsync","--host1",$host1," --user1 $user1 --password1 $password1 --host2 $host2 --user2 $user2 --password2 $password2 --pidfile $pidfile > $logfile 2>&1' &";
#system ". /etc/apache24/envvars.d/perl.env; $imapsync","--host1",$host1,"--user1",$user1,"--password1","\'$password1\'","--host2",$host2,"--user2",$user2,"--password2","\'$password2\'","--pidfile",$pidfile,"> $alogfile 2>&1 &";
#`/bin/sh -c '. /etc/apache24/envvars.d/perl.env; echo "\$PERL5LIB" > $logfile 2>&1' &`;
exit(0);
}
}
}
}
$result = 'L__Fehler__L: ' . $error if $error;
return(html_error({'non_specific' => "$error"})) if $error;
$result = 'L__Der Import wurde gestartet__L';
$success_text = 'L__Der Import wurde gestartet__L';
$template->param('result' => $result);
logline("debug","result = " . $result);
sleep(1);
return change_popuser();
$json_output{'success_message'} = '1';
#$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?action=show_email&success_text=' . encode_base64url($success_text);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub stop_import_mailuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $user = $input{'mailuser'};
my $pidfile = "/tmp/imapsync-$user.pid";
my $pid = `cat $pidfile`;
chomp $pid;
`kill $pid`;
`rm -f $pidfile`;
$result = 'L__Fehler__L: ' . $error if $error;
return(html_error({'non_specific' => "$error"})) if $error;
$result = 'L__Der Import wurde abgebrochen__L';
$success_text = 'L__Der Import wurde abgebrochen__L';
$template->param('result' => $result);
logline("debug","result = " . $result);
#$json_output{'modal_action'} = 'change_popuser';
#$json_output{'modal_action_args'} = '&domain=' . $input{'domain'};
#return show_email();
#return(\$template);
return change_popuser();
}
sub showlog_import_mailuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $user = $input{'mailuser'};
my $logfile = "/tmp/imapsync-$user.log";
my $result=`cat $logfile`;
if(!length($result)){
$result = 'L__keine Logeinträge__L';
} else {
unlink $logfile;
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(modal_message('L__Logeinträge für E-Mail-Import__L ' . $user,'<pre>' . $result . '</pre>'));
}
sub confirm_expunge_mailbox{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $guid = $input{'guid'};
my $box = decode_base64url($input{box});
my $mailuser = $input{'mailuser'};
my $idn_mailuser = encode('utf-8', email_to_unicode($mailuser));
my $template = HTML::Template->new(filename => 'confirm_expunge_mailbox.html');
$template->param('guid' => $guid);
$template->param('box' => $box);
$template->param('mailuser' => $mailuser);
$template->param('idn_mailuser' => $idn_mailuser);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_expunge_mailbox{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'result.html');
my $guid = $input{'guid'};
my $mailuser = $input{'mailuser'};
my $doveadm='/usr/sbin/doveadm';
if(!defined($doveadm) || ! -f $doveadm){
return(error("L__Fehler beim Leeren des Postfachs.__L"));
}
$doveadm = "/usr/iports/bin/sudo $doveadm -Dv expunge -u $mailuser";
if(defined($guid)){
$doveadm .= " mailbox-guid $guid all";
} else {
$doveadm .= " mailbox '*' all";
}
my $expunged = `$doveadm 2>&1 | grep -c 'expunge:' 2>/dev/null`;
chomp $expunged;
my $success_text = $expunged . ' L__E-Mails gelöscht.__L';
$template->param('result' => $success_text);
# mailuser hack
if($session && $session->param('is_mailuser')){
$json_output{'redirect_to'} = '/cgi-bin/easytecc4/index.pl?active_tab=_mailbox&success_text=' . encode_base64url($success_text);
} else {
$json_output{'success_message'} = '1';
}
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub exec_change_autoresponder_sieve{
return change_autoresponder_sieve();
}
sub change_autoresponder_sieve{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'change_autoresponder_sieve.html');
$template->param('disabled' => $input{'disabled'});
my $mailuser = $input{'mailuser'};
$template->param('mailuser' => $mailuser);
# copy from change_special_spamfilter / new_special_spamfilter output
$input{'special_spam_user_domain'} = $mailuser;
# keep parent modal stuff
if($input{'parent'}){
$template->param('parent' => $input{'parent'});
}
my $spamfilter_template;
if(-f "/home/$mailuser/.spamproc"){
$spamfilter_template = ${change_special_spamfilter()};
} else {
$spamfilter_template = ${new_special_spamfilter()};
}
foreach my $param ('special_subj_virus','special_subj_pspam','special_subj_cspam'){
$template->param($param => $spamfilter_template->param($param));
}
# read sieve
my ($forward_filter, $forward_to, $autoresponder_filter, $autoresponder_subject, $autoresponder_message) = read_sieve($mailuser);
# easytecc autoresponder
my $autoresponder_file = $mailuser;
$autoresponder_file =~ s/\@/_/;
$autoresponder_file .= '.aut';
my $autoresponder_subject_easytecc = `sed '/^Subject: /!d ; s/^Subject: //' /usr/local/etc/$autoresponder_file /usr/local/etc/easytecc/$autoresponder_file 2>/dev/null`;
chomp($autoresponder_subject_easytecc);
my $autoresponder_message_easytecc = `sed -r '/^(Subject|From): /d' /usr/local/etc/$autoresponder_file /usr/local/etc/easytecc/$autoresponder_file 2>/dev/null`;
chomp($autoresponder_message_easytecc);
if(!length($autoresponder_subject_easytecc) && !length($autoresponder_message_easytecc)){
$autoresponder_filter = 1;
} elsif(!length($autoresponder_message)){
$autoresponder_subject = encode('utf-8',$autoresponder_subject_easytecc);
$autoresponder_message = encode('utf-8',$autoresponder_message_easytecc);
$autoresponder_filter = 0;
} else {
$autoresponder_filter = 1;
}
# mailuser
if(-d "/home/$mailuser/mail"){
$template->param('can_filter' => 1);
}
if($input{'write_sieve'}){
$autoresponder_filter = $input{'autoresponder_filter'};
$autoresponder_subject = $input{'autoresponder_subject'};
$autoresponder_message = $input{'autoresponder_message'};
if(length($autoresponder_message)){
$success_text = "L__Die Abwesenheitsbenachrichtigung wurde erfolgreich angelegt.__L";
if($autoresponder_filter){
remove_sendmail_autoresponder($mailuser);
write_sieve($mailuser, $forward_sieve, $autoresponder_subject, $autoresponder_message, $input{'subj_virus'}, $input{'subj_pspam'}, $input{'subj_cspam'});
} else {
add_sendmail_autoresponder($mailuser, $autoresponder_subject, $autoresponder_message);
write_sieve($mailuser, $forward_sieve, '', '', $input{'subj_virus'}, $input{'subj_pspam'}, $input{'subj_cspam'});
}
} else {
$success_text = "L__Die Abwesenheitsbenachrichtigung wurde gelöscht.__L";
remove_sendmail_autoresponder($mailuser);
write_sieve($mailuser, $forward_sieve, '', '', $input{'subj_virus'}, $input{'subj_pspam'}, $input{'subj_cspam'});
$autoresponder_filter = 1;
$autoresponder_subject = '';
}
}
if($autoresponder_filter){
$template->param('autoresponder_filter_on' => 'checked');
} else {
$template->param('autoresponder_filter_off' => 'checked');
}
$template->param('autoresponder_subject' => $autoresponder_subject);
$template->param('autoresponder_message' => $autoresponder_message);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
if(!$input{'parent'}){
$json_output{'redirect_to'} = '&success_text=' . encode_base64url($success_text);
} else {
$success_text = '';
}
return(\$template);
}
sub exec_change_forward_sieve{
return change_forward_sieve();
}
sub change_forward_sieve{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'change_forward_sieve.html');
$template->param('disabled' => $input{'disabled'});
my $mailuser = $input{'mailuser'};
$template->param('mailuser' => $mailuser);
# copy from change_special_spamfilter / new_special_spamfilter output
$input{'special_spam_user_domain'} = $mailuser;
# keep parent modal stuff
if($input{'parent'}){
$template->param('parent' => $input{'parent'});
}
my $spamfilter_template;
if(-f "/home/$mailuser/.spamproc"){
$spamfilter_template = ${change_special_spamfilter()};
} else {
$spamfilter_template = ${new_special_spamfilter()};
}
foreach my $param ('special_subj_virus','special_subj_pspam','special_subj_cspam'){
$template->param($param => $spamfilter_template->param($param));
}
# read sieve
my ($forward_filter, $forward_to, $autoresponder_filter, $autoresponder_subject, $autoresponder_message) = read_sieve($mailuser);
if(scalar @{$forward_to}){
$forward_filter = 'sieve';
}
# external
my $sendmail_target = $mailuser;
# add random local part to catch all
if($mailuser =~ m/^@/){
$sendmail_target = 'catchall' . $$ . $sendmail_target;
}
my $sendmail_forward = `/usr/sbin/sendmail -d27 -bv $sendmail_target 2>/dev/null | grep -m 1 'aliased to' 2>/dev/null | sed 's/^.*aliased to // ; s/"//g' 2>/dev/null`;
chomp($sendmail_forward);
# single virtmaps line
if(!length($sendmail_forward)){
$sendmail_forward = `/usr/sbin/sendmail -d60 -bv $sendmail_target 2>/dev/null | grep -m 1 'map_lookup(virtuser' 2>/dev/null | sed 's/.*> // ; s/ .*//' 2>/dev/null`;
}
$sendmail_forward = get_sendmail_forward($mailuser);
my %mailpasswd = %{easytecc3::get_mailpasswd()->file_parsed_hash()};
my $forward_target;
foreach $forward_target (split(/,\s*/,$sendmail_forward)){
# fwd_as_att
if($forward_target =~ m/fwd_as_att\s([^"]*)"/){
$forward_target = $1;
foreach $forward_target (split(/\s+/,$forward_target)){
if($forward_target !~ /^\//){
push(@{$forward_to}, $forward_target);
}
}
$forward_filter = 'att';
}
# email / user
elsif($forward_target =~ m/^([^\|\/\s\"]+)$/ && !exists($mailpasswd{$1})){
push(@{$forward_to}, $1);
if($forward_filter ne 'att'){
$forward_filter = 'off';
}
}
}
my $forward_as_att_file = "/usr/local/etc/easytecc/$mailuser.fwdmsg";
my $fh;
my $fwd_as_att_message;
my $fwd_as_att_from;
my $fwd_as_att_subject;
if(-f $forward_as_att_file && open($fh, '<', $forward_as_att_file)){
$fwd_as_att_text = '';
while($line = <$fh>){
chomp($line);
# from
if($line =~ m/^From:\s*(.+)$/ && !length($fwd_as_att_from)){
$fwd_as_att_from = $1;
}
# subject
elsif($line =~ m/^Subject:\s*(.+)$/ && !length($fwd_as_att_subject)){
$fwd_as_att_subject = $1;
}
# ignore leading blank lines
elsif(length($fwd_as_att_text) || length($line)){
$fwd_as_att_text .= $line . "\n";
}
}
close $fh;
if($fwd_as_att_text =~ m/^\s*$/s){
$fwd_as_att_text = undef;
}
$template->param('forward_from' => $fwd_as_att_from);
$template->param('forward_subject' => $fwd_as_att_subject);
$template->param('forward_text' => $fwd_as_att_text);
}
my $forward_text_count = scalar split(/\n/,$fwd_as_att_text) + 1;
if($forward_text_count < 6){
$forward_text_count = 6;
}
$template->param('forward_text_count' => $forward_text_count);
# unique
@{$forward_to} = keys %{{ map { $_ => 1 } @{$forward_to} }};
my $forward_sieve = $forward_to;
my $forward_to_count = scalar @{$forward_to} + 1;
if($forward_to_count < 3){
if($forward_to_count == 1){
$forward_filter = 'att';
}
$forward_to_count = 3;
}
$template->param('forward_to_count' => $forward_to_count);
# mailuser
if(-d "/home/$mailuser/mail"){
$template->param('can_filter' => 1);
}
if($input{'write_sieve'}){
$forward_filter = $input{'forward_filter'};
$forward_from = $input{'forward_from'};
$forward_subject = $input{'forward_subject'};
$forward_text = $input{'forward_text'};
$template->param('forward_from' => encode('utf-8',$forward_from));
$template->param('forward_subject' => encode('utf-8',$forward_subject));
$template->param('forward_text' => encode('utf-8',$forward_text));
# no mailuser
if(! -d "/home/$mailuser/mail" && $forward_filter eq 'sieve'){
$forward_filter = 'att';
}
my @forward_to;
if(length($input{'forward_to'})){
chomp($input{'forward_to'});
@forward_to = split(/[\r\n,; ]+/,$input{'forward_to'});
}
$forward_to = \@forward_to;
$forward_sieve = [];
my $forward_sendmail = [];
if(@forward_to){
if($forward_filter eq 'sieve'){
$forward_sieve = $forward_to;
} else {
$forward_sendmail = $forward_to;
}
$success_text = "L__Die Weiterletungen wurden erfolgreich angelegt.__L";
} else {
$success_text = "L__Die Weiterletungen wurden gelöscht.__L";
$forward_filter = 'att';
}
if(@{$forward_sendmail}){
if($forward_filter eq 'att'){
add_sendmail_forward_as_att($mailuser,$forward_from,$forward_subject,$forward_text,$forward_sendmail);
} else {
add_sendmail_forward($mailuser,$forward_sendmail);
}
} else {
remove_sendmail_forward($mailuser);
}
write_sieve($mailuser, $forward_sieve, $autoresponder_subject, $autoresponder_message, $input{'subj_virus'}, $input{'subj_pspam'}, $input{'subj_cspam'});
}
if($forward_filter eq 'att'){
$template->param('forward_filter_att' => 'checked');
} elsif($forward_filter eq 'sieve'){
$template->param('forward_filter_sieve' => 'checked');
} else {
$template->param('forward_filter_off' => 'checked');
}
$template->param('forward_to' => join("\n",@{$forward_to}));
logline("debug","<<< Leaving ".(caller(0))[3]."().");
if(!$input{'parent'}){
$json_output{'redirect_to'} = '&success_text=' . encode_base64url($success_text);
} else {
$success_text = '';
}
return(\$template);
}
sub mailuser_interface{
if(!$session || !$session->param('is_mailuser')){
return start();
}
my $mailuser = $session->param('user');
my $mailaddress = $session->param('mailaddress');
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $template = HTML::Template->new(filename => 'mailuser_interface.html');
# user + address
$template->param('mailuser' => $mailuser);
$template->param('mailaddress' => $mailaddress);
# password
$template->param('show_password' => 1);
$template->param('active_tab_password' => 1);
# 2fa
if($fb){
$template->param('show_2fa' => 1);
} else {
$template->param('show_2fa' => 0);
}
if(defined($input{'2fa'}) && $input{'2fa'} ne 'noop'){
if($input{'2fa'} eq 'new'){
my $qrcode_url = `/usr/local/bin/google-authenticator -C -t -d -f -l $mailuser -i easyTECC -Q UTF8 -r 3 -R 30 -s /usr/local/etc/easytecc/2fa/$mailuser.setup -S 30 -w 3`;
($qrcode_url) = $qrcode_url =~ m/(https:\/\/www\.google\.com\/chart[^\s]+)/;
#$qrcode_url =~ s/https:\/\/www\.google\.com/https:\/\/chart.googleapis.com/;
`wget -q -O - '$qrcode_url' | openssl base64 | tr -d '\n' > /usr/local/etc/easytecc/2fa/$mailuser.qr`;
}
elsif($input{'2fa'} eq 'ok'){
`mv /usr/local/etc/easytecc/2fa/$mailuser.setup /usr/local/etc/easytecc/2fa/$mailuser`;
`rm /usr/local/etc/easytecc/2fa/$mailuser.qr`;
}
elsif($input{'2fa'} eq 'del'){
`rm -f /usr/local/etc/easytecc/2fa/$mailuser*`;
}
}
# 2fa setup
if(-f "/usr/local/etc/easytecc/2fa/$mailuser.setup"){
$template->param('2fa_setup' => 1);
$qrcode_url = 'data:image/png;base64,' . `cat /usr/local/etc/easytecc/2fa/$mailuser.qr`;
$template->param('qrcode_url' => $qrcode_url);
}
# 2fa present
if( -f "/usr/local/etc/easytecc/2fa/$mailuser"){
$template->param('2fa_active' => 1);
}
# mailbox
$template->param('show_mailbox' => 1);
# quota
my $mailquota = {};
if (easytecc3::extern_mx() || $fb) {
$mailpasswd = easytecc3::get_mailpasswd();
my %passwd = %{$mailpasswd->file_parsed_hash()};
($mailquota, undef, undef, undef) = easytecc3::getquota_mail(\%passwd);
}
else{
($mailquota, undef, undef, undef) = easytecc3::getquota_ftp();
}
$template->param('quota_max' => easytecc3::getsize($mailquota->{$mailuser}{'quota'}));
$template->param('quota_use' => easytecc3::getsize($mailquota->{$mailuser}{'use'}));
if($mailquota->{$mailuser}{'quota'} > 0){
$template->param('quota_percent' => sprintf("%.0f", ($mailquota->{$mailuser}{'use'}/$mailquota->{$mailuser}{'quota'})*100));
} elsif($mailquota->{$mailuser}{'use'} > 0) {
$template->param('quota_percent' => 100);
} else {
$template->param('quota_percent' => 0);
}
# mailboxes
if($fb){
$template->param('show_mailboxes' => 1);
my $mailstats=`$easytecc_prefix/mailstats.pl $mailuser 2>/dev/null`;
chomp $mailstats;
my @mailstats=split(/[\r\n]+/,$mailstats);
if(!scalar @mailstats){
my $error_tab_mailbox = error("L__Beim Abrufen der Ordner ist ein Fehler aufgetreten.__L");
$template->param('error_tab_mailbox' => $$error_tab_mailbox->output());
}
my @mailboxes = {};
foreach my $boxstats (@mailstats){
my ($box,$guid,$messages,$unseen,$spam,$vsize) = $boxstats =~ m/^[^\/]*\/([^\(]+)\(?([a-f0-9]+)?\)?\smessages=([0-9]+)\sunseen=([0-9]+)\sspam=([0-9]+)\svsize=([0-9]+)$/;
if($box ne '*'){
my $box_html = $box;
$box_html =~ s/\./ \/ /g;
push @mailboxes, {
box => $box_html,
ttl => $ttl,
box_encoded => encode_base64url($box_html),
guid => $guid,
messages => $messages,
unseeen => $unseen,
spam => $spam,
size => easytecc3::getsize($vsize / 1024),
};
} else {
$template->param('sum_messages' => $messages);
$template->param('sum_unseen' => $unseen);
$template->param('sum_spam' => $spam);
$template->param('sum_size' => easytecc3::getsize($vsize / 1024));
}
}
$template->param('mailboxes' => \@mailboxes);
} else {
$template->param('show_mailboxes' => 0);
}
# spamfilter
$template->param('show_spamfilter' => 1);
# copy from change_special_spamfilter / new_special_spamfilter output
$input{'special_spam_user_domain'} = $mailuser;
my $spamfilter_template;
if(-f "/home/$mailuser/.spamproc"){
$spamfilter_template = ${change_special_spamfilter()};
} else {
$spamfilter_template = ${new_special_spamfilter()};
}
foreach my $param ($spamfilter_template->param()){
$template->param($param => $spamfilter_template->param($param));
}
# forward + autoresponder
if($mailaddress){
$template->param('show_forward' => 1);
$template->param('show_autoresponder' => 1);
} else {
$template->param('show_forward' => 0);
$template->param('show_autoresponder' => 0);
}
if($fb && $mailuser eq $mailaddress){
$template->param('can_filter' => 1);
} else {
$template->param('can_filter' => 0);
}
# read sieve
my ($forward_filter, $forward_to, $autoresponder_filter, $autoresponder_subject, $autoresponder_message) = read_sieve($mailuser);
if($fb && scalar @{$forward_to}){
$forward_filter = 'sieve';
}
my $sendmail_target = $mailaddress;
# add random local part to catch all
if($sendmail_target =~ m/^@/){
$sendmail_target = 'catchall' . $$ . $sendmail_target;
}
my $sendmail_forward = `/usr/sbin/sendmail -d27 -bv $sendmail_target 2>/dev/null | grep -m 1 'aliased to' 2>/dev/null | sed 's/^.*aliased to // ; s/"//g' 2>/dev/null`;
chomp($sendmail_forward);
# single virtmaps line
if(!length($sendmail_forward)){
$sendmail_forward = `/usr/sbin/sendmail -d60 -bv $sendmail_target 2>/dev/null | grep -m 1 'map_lookup(virtuser' 2>/dev/null | sed 's/.*> // ; s/ .*//' 2>/dev/null`;
}
$sendmail_forward = get_sendmail_forward($mailaddress);
my $forward_internal = '';
my $forward_internal_count = 0;
my $forward_target;
foreach $forward_target (split(/,\s*/,$sendmail_forward)){
# local
if(
$fb && $forward_target =~ m/^.*procmail\s-a\s([^\@\s]+\@[^\@]+)/ ||
!$fb && $forward_target =~ m/^([^\@\|]+)$/
){
$forward_internal .= "$1\n";
$forward_internal_count++;
}
# email
elsif($forward_target =~ m/^([^\@\s]+\@[^\@]+)$/){
push(@{$forward_to}, $1);
if($forward_filter ne 'att'){
$forward_filter = 'off';
}
}
# fwd_as_att
elsif($forward_target =~ m/^\|\/usr\/sbin\/fwd_as_att\s(.*\.fwdmsg\s)*(.*)$/){
push(@{$forward_to}, split(/\s/, $2));
$forward_filter = 'att';
}
}
$template->param('forward_internal' => $forward_internal);
$template->param('forward_internal_count' => $forward_internal_count);
my $forward_as_att_file = "/usr/local/etc/easytecc/$mailaddress.fwdmsg";
my $fh;
my $fwd_as_att_message;
my $fwd_as_att_subject;
my $fwd_as_att_from;
my $fwd_as_att_subject;
if(-f $forward_as_att_file && open($fh, '<', $forward_as_att_file)){
$fwd_as_att_text = '';
while($line = <$fh>){
chomp($line);
# from
if($line =~ m/^From:\s*(.+)$/ && !length($fwd_as_att_from)){
$fwd_as_att_from = $1;
}
# subject
elsif($line =~ m/^Subject:\s*(.+)$/ && !length($fwd_as_att_subject)){
$fwd_as_att_subject = $1;
}
# ignore leading blank lines
elsif(length($fwd_as_att_text) || length($line)){
$fwd_as_att_text .= $line . "\n";
}
}
close $fh;
if($fwd_as_att_text =~ m/^\s*$/s){
$fwd_as_att_text = undef;
}
$template->param('forward_from' => $fwd_as_att_from);
$template->param('forward_subject' => $fwd_as_att_subject);
$template->param('forward_text' => $fwd_as_att_text);
}
my $forward_text_count = scalar split(/\n/,$fwd_as_att_text) + 1;
if($forward_text_count < 6){
$forward_text_count = 6;
}
$template->param('forward_text_count' => $forward_text_count);
# unique
@{$forward_to} = keys %{{ map { $_ => 1 } @{$forward_to} }};
my $forward_sieve = $forward_to;
my $forward_to_count = scalar @{$forward_to} + 1;
if($forward_to_count < 3){
if($forward_to_count == 1){
$forward_filter = 'att';
}
$forward_to_count = 3;
}
$template->param('forward_to_count' => $forward_to_count);
# easytecc autoresponder
my $autoresponder_file = $mailaddress;
$autoresponder_file =~ s/\@/_/;
$autoresponder_file .= '.aut';
my $autoresponder_subject_easytecc = `sed '/^Subject: /!d ; s/^Subject: //' /usr/local/etc/$autoresponder_file /usr/local/etc/easytecc/$autoresponder_file 2>/dev/null`;
chomp($autoresponder_subject_easytecc);
my $autoresponder_message_easytecc = `sed -r '/^(Subject|From): /d' /usr/local/etc/$autoresponder_file /usr/local/etc/easytecc/$autoresponder_file 2>/dev/null`;
chomp($autoresponder_message_easytecc);
if(!length($autoresponder_subject_easytecc) && !length($autoresponder_message_easytecc)){
if($fb){
$autoresponder_filter = 1;
}
} elsif(!length($autoresponder_message)){
$autoresponder_subject = encode('utf-8',$autoresponder_subject_easytecc);
$autoresponder_message = encode('utf-8',$autoresponder_message_easytecc);
$autoresponder_filter = 0;
} else {
if($fb){
$autoresponder_filter = 1;
}
}
if($input{'write_sieve'}){
if($input{'active_tab'} eq '_forward'){
$forward_filter = $input{'forward_filter'};
$forward_from = $input{'forward_from'};
$forward_subject = $input{'forward_subject'};
$forward_text = $input{'forward_text'};
$template->param('forward_from' => encode('utf-8',$forward_from));
$template->param('forward_subject' => encode('utf-8',$forward_subject));
$template->param('forward_text' => encode('utf-8',$forward_text));
my @forward_to;
if(length($input{'forward_to'})){
chomp($input{'forward_to'});
@forward_to = split(/[\r\n,; ]+/,$input{'forward_to'});
}
$forward_to = \@forward_to;
$forward_sieve = [];
my $forward_sendmail = [];
if(@forward_to){
if($forward_filter eq 'sieve'){
$forward_sieve = $forward_to;
} else {
$forward_sendmail = $forward_to;
}
$success_text = "L__Die Weiterletungen wurden erfolgreich angelegt.__L";
} else {
$success_text = "L__Die Weiterletungen wurden gelöscht.__L";
$forward_filter = 'att';
}
if(@{$forward_sendmail}){
if($forward_filter eq 'att'){
add_sendmail_forward_as_att($mailaddress,$forward_from,$forward_subject,$forward_text,$forward_sendmail);
} else {
add_sendmail_forward($mailaddress,$forward_sendmail);
}
} else {
remove_sendmail_forward($mailaddress);
}
write_sieve($mailuser, $forward_sieve, $autoresponder_subject, $autoresponder_message, $input{'subj_virus'}, $input{'subj_pspam'}, $input{'subj_cspam'});
}
elsif($input{'active_tab'} eq '_autoresponder'){
$autoresponder_filter = $input{'autoresponder_filter'};
$autoresponder_subject = $input{'autoresponder_subject'};
$autoresponder_message = $input{'autoresponder_message'};
if(length($autoresponder_message)){
$success_text = "L__Die Abwesenheitsbenachrichtigung wurde erfolgreich angelegt.__L";
if($autoresponder_filter){
remove_sendmail_autoresponder($mailaddress);
write_sieve($mailuser, $forward_sieve, $autoresponder_subject, $autoresponder_message, $input{'subj_virus'}, $input{'subj_pspam'}, $input{'subj_cspam'});
} else {
add_sendmail_autoresponder($mailaddress, $autoresponder_subject, $autoresponder_message);
write_sieve($mailuser, $forward_sieve, '', '', $input{'subj_virus'}, $input{'subj_pspam'}, $input{'subj_cspam'});
}
$autoresponder_subject = encode('utf-8',$autoresponder_subject);
$autoresponder_message = encode('utf-8',$autoresponder_message);
} else {
$success_text = "L__Die Abwesenheitsbenachrichtigung wurde gelöscht.__L";
remove_sendmail_autoresponder($mailaddress);
write_sieve($mailuser, $forward_sieve, '', '', $input{'subj_virus'}, $input{'subj_pspam'}, $input{'subj_cspam'});
$autoresponder_filter = 1;
$autoresponder_subject = '';
}
}
}
if($forward_filter eq 'att'){
$template->param('forward_filter_att' => 'checked');
} elsif($forward_filter eq 'sieve'){
$template->param('forward_filter_sieve' => 'checked');
} else {
$template->param('forward_filter_off' => 'checked');
}
$template->param('forward_to' => join("\n",@{$forward_to}));
if($autoresponder_filter){
$template->param('autoresponder_filter_on' => 'checked');
} else {
$template->param('autoresponder_filter_off' => 'checked');
}
$template->param('autoresponder_subject' => $autoresponder_subject);
$template->param('autoresponder_message' => $autoresponder_message);
if($input{'active_tab'}){
$template->param('active_tab_password' => 0);
$template->param('active_tab_mailbox' => 0);
$template->param('active_tab_spamfilter' => 0);
$template->param('active_tab_forward' => 0);
$template->param('active_tab_autoresponder' => 0);
$template->param('active_tab' . $input{'active_tab'} => 1);
}
$template->param('show_webmail' => 1);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(\$template);
}
sub read_sieve{
my $mailuser = shift;
# forward
my $forward_filter = 1;
my @forward_to;
# autoresponder
my $autoresponder_filter = 1;
my $autoresponder_subject;
my $autoresponder_message;
my $autoresponder_message_multiline = 0;
# maybe dos
my @sieverules = split(/\r?\n/,`cat /home/$mailuser/.dovecot.sieve 2>/dev/null`);
my $forward = 0;
my $autoresponder = 0;
foreach my $line (@sieverules){
chomp($line);
if($line eq '# rule:[Weiterleitung [easyTECC]]'){
$forward = 1;
}
elsif($line eq '# rule:[Abwesenheit [easyTECC]]'){
$autoresponder = 1;
}
elsif($line eq '}'){
$forward = $autoresponder = $autoresponder_message_multiline = 0;
}
elsif($forward){
if($line eq 'if anyof (true)'){
$forward_filter = 0;
}
elsif($line =~ m/^\s*redirect\s+\"([^\"]+)\";?$/){
push(@forward_to,$1);
}
}
elsif($autoresponder){
if($line eq 'if anyof (true)'){
$autoresponder_filter = 0;
}
elsif($line =~ m/^\s*:subject\s+\"(.*)\";?$/){
$autoresponder_subject = $1;
}
elsif($line =~ m/^\s*(:mime )?text:\s*$/ && !$autoresponder_message_multiline){
$autoresponder_message_multiline = 1;
}
elsif($autoresponder_message_multiline){
$autoresponder_message .= $line . "\n";
}
elsif($line =~/^\s*\"(.*)\";?$/){
$autoresponder_message = $1;
}
}
}
$autoresponder_message =~ s/\n\.\n;$//s;
chomp($autoresponder_message);
if(!$forward){
$forward_filter = 0;
}
if(!$autoresponder){
$autoresponder_filter = 0;
}
return ($forward_filter, \@forward_to, $autoresponder_filter, $autoresponder_subject, $autoresponder_message);
}
sub write_sieve{
my ($mailuser, $forward_to, $autoresponder_subject, $autoresponder_message, $subj_virus, $subj_pspam, $subj_cspam) = @_;
$autoresponder_subject = encode('utf-8',$autoresponder_subject);
$autoresponder_message = encode('utf-8',$autoresponder_message);
my $forward_filter = 1;
my $autoresponder_filter = 1;
my $autoresponder_message_multiline = 0;
my $foreign_sieverules = '';
my $sieve_file = `/usr/bin/grep managesieve /usr/local/www/roundcube/config/config.inc.php && echo managesieve.sieve || echo roundcube.sieve`;
chomp($sieve_file);
# fix perms and links
if(! -d "/home/$mailuser/sieve"){
`mkdir -p /home/$mailuser/sieve`;
`/usr/iports/bin/sudo /usr/sbin/chown.pl virtmail:vuser /home/$mailuser/sieve`;
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 770 /home/$mailuser/sieve 2>/dev/null`;
`touch /home/$mailuser/sieve/$sieve_file 2>/dev/null`;
`/usr/iports/bin/sudo /usr/sbin/chown.pl virtmail:vuser /home/$mailuser/sieve/$sieve_file`;
`/usr/iports/bin/sudo /usr/sbin/chmod.pl 660 /home/$mailuser/sieve/$sieve_file 2>/dev/null`;
}
if(! -e "/home/$mailuser/.dovecot.sieve"){
`ln -s /home/$mailuser/sieve/$sieve_file /home/$mailuser/.dovecot.sieve 2>/dev/null`;
`/usr/iports/bin/sudo /usr/sbin/chown.pl virtmail:vuser /home/$mailuser/.dovecot.sieve`;
}
# maybe dos
my @sieverules = split(/\r?\n/,`cat /home/$mailuser/.dovecot.sieve 2>/dev/null`);
my $easytecc_rule = 0;
foreach my $line (@sieverules){
chomp($line);
if($line =~ m/^# rule:\[(Weiterleitung|Abwesenheit) \[easyTECC\]\]/){
$easytecc_rule = 1;
}
elsif($easytecc_rule){
if($line eq '}'){
$easytecc_rule = 0;
}
}
else {
$foreign_sieverules .= $line . "\n";
}
}
$foreign_sieverules =~ s/\n+$//s;
my $filter = '';
if(length($subj_virus)){
$filter .= "not header :contains \"Subject\" \"$subj_virus\",\n";
}
if(length($subj_pspam)){
$filter .= "not header :contains \"Subject\" \"$subj_pspam\",\n";
$filter .= "not header :contains \"X-Spam-Info\" \"$subj_pspam\",\n";
}
if(length($subj_cspam)){
$filter .= "not header :contains \"Subject\" \"$subj_cspam\",\n";
$filter .= "not header :contains \"X-Spam-Info\" \"$subj_cspam\",\n";
}
$filter =~ s/,\n$//s;
if(!length($filter)){
$forward_filter = $autoresponder_filter = 0;
}
my $easytecc_sieverules = '';
if(@{$forward_to}){
$easytecc_sieverules .= "# rule:[Weiterleitung [easyTECC]]\n";
if($forward_filter){
$easytecc_sieverules .= "if allof ($filter)\n";
} else {
$easytecc_sieverules .= "if anyof (true)\n";
}
$easytecc_sieverules .= "{\n";
my $to_address;
foreach $to_address (@{$forward_to}){
$easytecc_sieverules .= "\tredirect \"$to_address\";\n";
}
$easytecc_sieverules .= "}\n";
}
if(length($autoresponder_subject) && length($autoresponder_message)){
$easytecc_sieverules .= "# rule:[Abwesenheit [easyTECC]]\n";
if($foreign_sieverules !~ m/^\s*require \["vacation"\];/sm){
$foreign_sieverules = "require [\"vacation\"];\n$foreign_sieverules"
}
if($forward_filter){
$easytecc_sieverules .= "if allof ($filter)\n";
} else {
$easytecc_sieverules .= "if anyof (true)\n";
}
$easytecc_sieverules .= "{\n";
$easytecc_sieverules .= "\tvacation\n";
$easytecc_sieverules .= "\t\t:subject \"$autoresponder_subject\"\n";
$easytecc_sieverules .= "\t\t";
if($autoresponder_message =~ m/^MIME-Version:/){
$easytecc_sieverules .= ":mime ";
}
$easytecc_sieverules .= "text:\n$autoresponder_message\n";
$easytecc_sieverules .= ".\n;\n}\n";
}
open(SIEVE, '>', "/home/$mailuser/.dovecot.sieve");
binmode(SIEVE);
print SIEVE $foreign_sieverules . "\n" . $easytecc_sieverules;
close(SIEVE);
#/usr/iports/bin/sievec -D /home/$mailuser/sieve/roundcube.sieve
# `echo '$foreign_sieverules' > /home/$mailuser/sieve/roundcube.sieve`;
# `echo '$easytecc_sieverules' >> /home/$mailuser/sieve/roundcube.sieve`;
logline("debug","sieve $foreign_sieverules");
logline("debug","sieve $easytecc_sieverules");
}
sub remove_sendmail_autoresponder{
my $mailuser = shift;
my $autoresponder_file = $mailuser;
$autoresponder_file =~ s/\@/_/;
$autoresponder_file .= '.aut';
if(-f "/usr/local/etc/easytecc/$autoresponder_file"){
`rm -f /usr/local/etc/easytecc/$autoresponder_file`;
} else {
return;
}
my $virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %virtmaps = %{$virtmaps->file_parsed_hash()};
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
my @new_virtmaps = ();
my @new_aliases = ();
my $virtmaps_rhs = '';
foreach($virtmaps->file_content){
if(/^$mailuser\s+(.*)$/){
$virtmaps_rhs = $1;
}
push(@new_virtmaps, $_);
}
foreach($aliases->file_content){
if(/^$virtmaps_rhs\s*:\s*(.*)$/){
my $aliases = '';
my @aliases = split(/,\s*/,$1);
foreach(@aliases){
if(! /\/autoresponder/){
if(length($aliases)){
$aliases .= ',';
}
$aliases .= $_;
}
}
push @new_aliases, "$virtmaps_rhs: $aliases";
} else {
push @new_aliases, $_;
}
}
$aliases->file_content(\@new_aliases);
$aliases->write_file;
@new_virtmaps = map(lc, @new_virtmaps);
$virtmaps->file_content(\@new_virtmaps);
$virtmaps->write_file;
}
sub add_sendmail_autoresponder{
my $mailuser = shift;
my $subject = shift;
my $text = shift;
my ($user,$domain) = split(/@/,$mailuser);
my $autoreply = file->new({ file_name => '/usr/local/etc/easytecc/' . $user . '_' . $domain . '.aut', user => $user, domain => $domain});
my @autoreply_content = ("From: $mailuser", "Subject: $subject\n", "$text");
$autoreply->file_content(\@autoreply_content);
$autoreply->write_file;
my $virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %virtmaps = %{$virtmaps->file_parsed_hash()};
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
my @new_virtmaps = ();
my @new_aliases = ();
my $virtmaps_rhs = $mailuser;
$virtmaps_rhs =~ s/@/_/;
$virtmaps_rhs .= '_spl';
my $found = 0;
foreach($virtmaps->file_content){
if(/^$mailuser\s+(.*)$/){
push(@new_virtmaps, "$mailuser\t$virtmaps_rhs");
$found = 1;
} else {
push(@new_virtmaps, $_);
}
}
if(!$found){
push(@new_virtmaps, "$mailuser\t$virtmaps_rhs");
}
$found = 0;
foreach($aliases->file_content){
if(/^$virtmaps_rhs\s*:\s*(.*)$/){
foreach my $alias (split(/,\s*/,$1)){
if($alias !~ /\/autoresponder/){
push @aliases, $alias;
}
}
push @aliases, "\"|$autoresponder /usr/local/etc/easytecc/" . $user . '_' . $domain . '.aut' . "\"";
# unique
@aliases = keys %{{ map { $_ => 1 } @aliases }};
my $aliases = join(',',@aliases);
push @new_aliases, "$virtmaps_rhs: $aliases";
$found = 1;
} else {
push @new_aliases, $_;
}
}
if(!$found){
push @new_aliases, "$virtmaps_rhs: \"|$autoresponder /usr/local/etc/easytecc/" . $user . '_' . $domain . '.aut' . "\"";
}
$aliases->file_content(\@new_aliases);
$aliases->write_file;
@new_virtmaps = map(lc, @new_virtmaps);
$virtmaps->file_content(\@new_virtmaps);
$virtmaps->write_file;
}
sub remove_sendmail_forward{
my $mailuser = shift;
my $virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %virtmaps = %{$virtmaps->file_parsed_hash()};
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
my @new_virtmaps = ();
my @new_aliases = ();
my $virtmaps_rhs = '';
foreach($virtmaps->file_content){
if(/^$mailuser\s+(.*)$/){
$virtmaps_rhs = $1;
}
push(@new_virtmaps, $_);
}
foreach($aliases->file_content){
if(/^$virtmaps_rhs\s*:\s*(.*)$/){
my $aliases = '';
my @aliases = split(/,\s*/,$1);
foreach(@aliases){
if(! /^[^"@]+@.*/ && ! /fwd_as_att/){
if(length($aliases)){
$aliases .= ',';
}
$aliases .= $_;
}
}
push @new_aliases, "$virtmaps_rhs: $aliases";
} else {
push @new_aliases, $_;
}
}
`rm -f /usr/local/etc/easytecc/$mailuser.fwdmsg`;
$aliases->file_content(\@new_aliases);
$aliases->write_file;
@new_virtmaps = map(lc, @new_virtmaps);
$virtmaps->file_content(\@new_virtmaps);
$virtmaps->write_file;
}
sub add_sendmail_forward{
my $mailuser = shift;
my $forward_external = shift;
my $virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %virtmaps = %{$virtmaps->file_parsed_hash()};
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
my @new_virtmaps = ();
my @new_aliases = ();
my $virtmaps_rhs = $mailuser;
$virtmaps_rhs =~ s/@/_/;
$virtmaps_rhs .= '_spl';
my $found = 0;
foreach($virtmaps->file_content){
if(/^$mailuser\s+(.*)$/){
push(@new_virtmaps, "$mailuser\t$virtmaps_rhs");
$found = 1;
} else {
push(@new_virtmaps, $_);
}
}
if(!$found){
push(@new_virtmaps, "$mailuser\t$virtmaps_rhs");
}
my %mailpasswd = %{easytecc3::get_mailpasswd()->file_parsed_hash()};
$found = 0;
foreach($aliases->file_content){
if(/^$virtmaps_rhs\s*:\s*(.*)$/){
my @aliases = split(/,\s*/,$1);
my @all_aliases = ();
my $alias;
foreach $alias (@aliases){
if($alias =~ /(procmail|autoresponder)/ || exists($mailpasswd{$alias})){
push @all_aliases, $alias;
}
}
push @all_aliases, @{$forward_external};
# unique
@all_aliases = keys %{{ map { $_ => 1 } @all_aliases }};
my $aliases = join(',',@all_aliases);
push @new_aliases, "$virtmaps_rhs: $aliases";
$found = 1;
} else {
push @new_aliases, $_;
}
}
if(!$found){
# unique
@{$forward_external} = keys %{{ map { $_ => 1 } @{$forward_external} }};
push @new_aliases, "$virtmaps_rhs: " . join(',',@{$forward_external});
}
$aliases->file_content(\@new_aliases);
$aliases->write_file;
@new_virtmaps = map(lc, @new_virtmaps);
$virtmaps->file_content(\@new_virtmaps);
$virtmaps->write_file;
}
sub get_sendmail_forward{
my $mailaddress = shift;
logline("debug","#######################mailaddress is $mailaddress ");
my $virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %virtmaps = %{$virtmaps->file_parsed_hash()};
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
my $virtmaps_rhs;
my @forward_to;
foreach($virtmaps->file_content){
if(/^$mailaddress\s+(.*)$/){
my $match = $1;
if($match =~ /_spl$/){
$virtmaps_rhs = $match;
} else {
push(@forward_to, $match);
}
}
}
foreach($aliases->file_content){
if(/^$virtmaps_rhs\s*:\s*(.*)$/){
my @aliases = split(/,\s*/,$1);
my $alias;
foreach $alias (@aliases){
push(@forward_to, $alias);
}
}
}
@forward_to = keys %{{ map { $_ => 1 } @forward_to }};
return join(',',@forward_to);
}
sub add_sendmail_forward_as_att{
my $mailuser = shift;
my $forward_from = shift;
my $forward_subject = shift;
my $forward_text = shift;
my $forward_to = shift;
my $forward_as_att_file = "/usr/local/etc/easytecc/$mailuser.fwdmsg";
my $forward_as_att_cmd = '|/usr/sbin/fwd_as_att';
my $forward_header = '';
if(length($forward_from)){
$forward_header .= "From: $forward_from\n";
}
if(length($forward_subject)){
$forward_header .= "Subject: $forward_subject\n";
}
if(length($forward_subject) || length($forward_text)){
my $fh;
open($fh, '>', $forward_as_att_file);
binmode($fh);
if(length($forward_header)){
print $fh encode('utf-8',"$forward_header\n");
}
if(length($forward_text)){
print $fh encode('utf-8',$forward_text);
}
close($fh);
$forward_as_att_cmd .= " $forward_as_att_file";
} else {
`rm -f $forward_as_att_file 2>/dev/null`;
}
if(easytecc3::extern_mx()){
my $socket = easytecc3::make_socket();
if(-f $forward_as_att_file){
print $socket "autoreply=$forward_as_att_file\n";
} else {
print $socket "del_autoreply_file=$forward_as_att_file\n";
}
easytecc3::close_socket($socket);
}
my $virtmaps = file->new({file_name => '/etc/mail/virtmaps'});
$virtmaps->read_file;
my %virtmaps = %{$virtmaps->file_parsed_hash()};
my $aliases = file->new({file_name => '/etc/mail/aliases'});
$aliases->read_file;
my %aliases = %{$aliases->file_parsed_hash()};
my @new_virtmaps = ();
my @new_aliases = ();
my $virtmaps_rhs = $mailuser;
$virtmaps_rhs =~ s/@/_/;
$virtmaps_rhs .= '_spl';
my $found = 0;
foreach($virtmaps->file_content){
if(/^$mailuser\s+(.*)$/){
push(@new_virtmaps, "$mailuser\t$virtmaps_rhs");
$found = 1;
} else {
push(@new_virtmaps, $_);
}
}
if(!$found){
push(@new_virtmaps, "$mailuser\t$virtmaps_rhs");
}
my %mailpasswd = %{easytecc3::get_mailpasswd()->file_parsed_hash()};
$found = 0;
foreach($aliases->file_content){
if(/^$virtmaps_rhs\s*:\s*(.*)$/){
my @aliases = split(/,\s*/,$1);
my @all_aliases = ();
my $alias;
foreach $alias (@aliases){
if($alias =~ /(procmail|autoresponder)/ || exists($mailpasswd{$alias})){
push @all_aliases, $alias;
}
}
push @all_aliases, "\"$forward_as_att_cmd " . join(' ',@{$forward_to}) . "\"";
my $aliases = join(',',@all_aliases);
push @new_aliases, "$virtmaps_rhs: $aliases";
$found = 1;
} else {
push @new_aliases, $_;
}
}
if(!$found){
push @new_aliases, "$virtmaps_rhs: " . "\"$forward_as_att_cmd " . join(' ',@{$forward_to}) . "\"";
}
$aliases->file_content(\@new_aliases);
$aliases->write_file;
@new_virtmaps = map(lc, @new_virtmaps);
$virtmaps->file_content(\@new_virtmaps);
$virtmaps->write_file;
}
sub value{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $value = shift;
my $form_input = shift;
logline("debug",qq~#############value action=$input{'action'} input = $form_input~);
if(exists $error_fields{$form_input}){
logline("debug","$form_input value=error_fields");
return(qq~"$input{$form_input}" class="has-error" ~);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
}
elsif(exists $input{$form_input} && $input{'action'} =~ /^exec_/){
logline("debug","elsif input=" . $input{$form_input} . " value=$value und exec_");
return(qq~"$input{$form_input}" <TMPL_VAR NAME=error_class_$form_input> ~);
logline("debug","<<< Leaving ".(caller(0))[3]."().");
}
else{
logline("debug","else input=$form_input value=$value");
logline("debug","<<< Leaving ".(caller(0))[3]."().");
return(qq~"$value"~);
}
}
sub error_class{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]);
my $form_input = shift;
logline("debug",qq~error_class input = $form_input~);
if(exists $error_fields{$form_input}){
logline("debug","error_class $form_input ".$error_fields{$form_input});
return("has-error");
logline("debug","<<< Leaving ".(caller(0))[3]."().");
}
}
sub https_cert_expire{
my $cert_file=shift;
### Mario: Hash-Variable, um die SSL-Ablaufdaten nicht andauernd neu zu überprüfen ###
my %ssl_expiry_dates;
if(defined($session) && defined($session->param('ssl_expiry_dates'))){
%ssl_expiry_dates = %{$session->param('ssl_expiry_dates')};
if (exists($ssl_expiry_dates{$cert_file})){
### Mario: Falls der %hash-Wert für die Domain bereits existiert, soll dieser gelesen werden ###
return ($ssl_expiry_dates{$cert_file}{'cert_expire_date'}, $ssl_expiry_dates{$cert_file}{'cert_expire_days'});
logline("debug"," -M A R I O- Rueckgabe der Hashwerte von \$ssl_expiry_dates " . $cert_file );
}
}
my $openssl = 'openssl';
if(-e '/usr/local/bin/openssl'){
$openssl = '/usr/local/bin/openssl';
}
my $cert_expire_date;
if($fb){
$cert_expire_date = `/bin/sh -c "/usr/iports/bin/sudo /usr/sbin/bzgrep . $cert_file | $openssl x509 -noout -enddate 2>/dev/null"`;
} else {
$cert_expire_date = `/bin/sh -c "cat $cert_file | $openssl x509 -noout -enddate 2>/dev/null"`;
}
logline("debug","cert_expire_date:$cert_expire_date\n");
logline("debug","/bin/sh -c \"/usr/iports/bin/sudo /usr/sbin/bzgrep . $cert_file | $openssl x509 -noout -enddate 2>/dev/null\"\n");
if(length($cert_expire_date)){
chomp($cert_expire_date);
$cert_expire_date = `/bin/sh -c "echo $cert_expire_date | sed 's#^.*=##;s# *# #'"`;
chomp($cert_expire_date);
my $cert_expire_secs;
my $now_secs;
my $cert_expire_days;
if ($fb){
$cert_expire_secs = `/bin/sh -c "LC_ALL=C; date -j -f '%b %d %H:%M:%S %Y %Z' '$cert_expire_date' '+%s'"`;
chomp($cert_expire_secs);
$now_secs = `/bin/sh -c "date -j '+%s'"`;
chomp($now_secs);
$cert_expire_days = int(($cert_expire_secs - $now_secs) / 86400);
$cert_expire_date = `/bin/sh -c "date -j -f '%s' '$cert_expire_secs' '+%d.%m.%Y'"`;
chomp($cert_expire_date);
} else {
$cert_expire_secs = `/bin/sh -c "LC_ALL=C; date -d '$cert_expire_date' '+%s'"`;
chomp($cert_expire_secs);
$now_secs = `/bin/sh -c "date '+%s'"`;
chomp($now_secs);
$cert_expire_days = int(($cert_expire_secs - $now_secs) / 86400);
$cert_expire_date = `/bin/sh -c "date -d '1970-01-01 $cert_expire_secs sec GMT' '+%d.%m.%Y'"`;
chomp($cert_expire_date);
}
$ssl_expiry_dates{$cert_file}{'cert_expire_date'} = $cert_expire_date;
$ssl_expiry_dates{$cert_file}{'cert_expire_days'} = $cert_expire_days;
$session->param('ssl_expiry_dates', \%ssl_expiry_dates);
$session->flush();
return ($cert_expire_date, $cert_expire_days);
}
}
sub logline($$) {
my $level = shift;
my $message = shift;
if($debug){
chomp $message;
my ($package, $filename, $line) = caller;
my $logline = sprintf '(%5.5d)', $line;
$log->log( level => $level, message => $logline." ".$message);
}
}
sub dienice ($) {
# write die messages to the log before die'ing
my ($package, $filename, $line) = caller;
logline("alert","$_[0] at line $line in $filename");
die $_[0];
}
# from http://cpansearch.perl.org/src/KAZUHO/MIME-Base64-URLSafe-0.01/lib/MIME/Base64/URLSafe.pm to avoid dependencies
sub encode_base64url ($) {
my $data = encode_base64($_[0], '');
$data =~ tr|+/=|\-_|d;
$data;
}
# from https://github.com/ptarjan/base64url/blob/master/perl.pl
sub decode_base64url {
(my $s = shift) =~ tr{-_}{+/};
$s .= '=' x (4 - length($s));
return decode_base64($s);
}