File: /usr/local/www/apache24/cgi-bin/easytecc4/easytecc3.pm
package easytecc3;
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';
}
}
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(ascii_domain is_domain is_email is_tld);
use easytecc_class;
use Encode;
use Encode::Guess;
use IO::Socket::INET;
use Data::FormValidator;
use CGI::Session;
use Net::IDN::Encode ':all';
use HTML::Template;
use DBI;
use DBD::mysql;
#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
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
#
my ($easytecc_prefix, $droot_prefix, $droot_regex);
my $fb = "";
if (-e '/etc/sudoers') {
$fb = '1';
}
if ($fb) {
$easytecc_prefix = '/usr/local/www/apache24/cgi-bin/easytecc4';
$droot_prefix = '/usr/local/www/apache24/noexec';
$droot_regex = '\/usr\/local\/www\/apache24\/noexec\/';
}
else{
$easytecc_prefix = '/home/httpd/cgi-bin/easytecc4';
$droot_prefix = '/home/httpd/docs';
$droot_regex = '\/home\/httpd\/docs\/';
}
our %file_handler_store;
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.");
}
#fbsd
sub domain_alias_select{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $count = shift;
my $domain_alias_select = qq~<SELECT id=<TMPL_VAR NAME=select_name> NAME=<TMPL_VAR NAME=select_name>>
<TMPL_LOOP NAME=domain_alias_select$count>
<OPTION <TMPL_VAR NAME=2> <TMPL_VAR NAME=option_selected>><TMPL_VAR NAME=1></OPTION>
</TMPL_LOOP>
</select><br />
~;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return(\$domain_alias_select);
}
sub get_mail_ftp_quota_vhost{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $session = shift;
my $vhost = $session->param('vhost_no_www');
my $ftpuser = $session->param('user');
my($mail_quota_sum, $ftp_quota, $mailpasswd) = '';
my %passwd = ();
my %mailquota = ();
my ($quotaref, $sum_ftplimit, $sum_ftpuse, $ftpserverlimit) = easytecc3::getquota_ftp();
my %quota = %$quotaref;
logline("debug","vhost=$vhost ftpuser=$ftpuser fb=$fb") if $debug;
if ($fb) {
$mailpasswd = easytecc3::get_mailpasswd();
%passwd = %{$mailpasswd->file_parsed_hash()};
%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;
}
foreach my $user(sort keys %passwd){
#logline("debug","mail_quota_sum=$mail_quota_sum user=$user gecos=" . $passwd{$user}{'gecos'} . " mailquota user=" . $mailquota{$user}{'quota'}) if $debug;
next if $passwd{$user}{'gecos'} !~ /^$vhost - POP/;
$mail_quota_sum += $mailquota{$user}{'quota'};
}
$ftp_quota = $quota{$ftpuser}{'quota'} / 1024;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return($mail_quota_sum, $ftp_quota);
}
sub get_mailpasswd{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my @passwd = ();
my $passwd = '';
if(extern_mx()){
my $socket = make_socket();
logline("debug","nach make_socket()") if $debug;
print $socket "getpasswd=\n";
@passwd = <$socket>;
# um die parsing-Funktion von file benutzen zu knnne ein neues file-Objekt erzeugen und @passwd reintun
# anschlieend parsen und es kommt ein Hash raus
$passwd = file->new({file_name => '/usr/local/etc/mailpasswd'});
$passwd->file_content(\@passwd);
$passwd->write_file;
$passwd->parse_file;
}
elsif($fb){
$passwd = file->new({file_name => '/etc/mail/mailuser'});
$passwd->read_file;
#my @new_mailpasswd = $passwd->file_content;
#foreach(@new_mailpasswd){
# logline("debug","$passwd get_mailpasswd: $_ ########################################") if $debug;
#my %passwd = %{$passwd->file_parsed_hash()};
#return($passwd);
#}
#return($passwd);
}
else{
$passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
}
#my %passwd = %{$passwd->file_parsed_hash()};
#foreach(sort keys %passwd){
# logline("debug","key=$_ value=" . $passwd{$_} . "") if $debug;
#}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return($passwd);
}
sub getquota_mail{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $mailpasswd = shift;
my %mailpasswd;
if ($fb && $mailpasswd) {
%mailpasswd = %$mailpasswd;
}
my @qtst = ();
my %qtst;
my $sum_limit = '';
my $sum_use = '';
my $serverlimit = '';
if(extern_mx()){
my $socket = make_socket();
print $socket "getquota=\n";
@qtst = <$socket>;
}
elsif($fb){
$serverlimit = `cat /etc/vsd/quota`;
chomp $serverlimit;
my $mailquotas_raw = `/usr/iports/bin/sudo /usr/sbin/doveadm -f flow quota get -A`;
my $mailquota_line;
foreach $mailquota_line (split(/[\r\n]+/,$mailquotas_raw)){
if($mailquota_line =~ m/Type=MESSAGE/){
next;
}
my ($user,$quota) = $mailquota_line =~ m/^([^\s]+).+Value=([0-9]+)/;
$mailpasswd{$user}{'quota_used'} = $quota;
}
foreach my $user(sort keys %mailpasswd){
$sum_limit += $mailpasswd{$user}{'quota'};
$qtst{$user}{'quota'} = $mailpasswd{$user}{'quota'} * 1024;
my $quota = $mailpasswd{$user}{'quota'};
my $home = $mailpasswd{$user}{'home'};
#TODO: JIMMY: timeout setzen? Hatte schon verkackte logins weil er sich hier totgesucht hat
#my $use = `/usr/iports/bin/sudo /usr/bin/du -Ask $home`;
#my $use_kb = `/usr/iports/bin/doveadm -f tab mailbox status -t -u '$user' vsize '*' | tail -n1`;
#chomp $use_kb /= 1024;
# viele shellbefehle sind einfach zu lahm...
#my $use_kb = `/usr/iports/bin/sudo /usr/iports/bin/doveadm -f flow quota get -u $user | sed '/Type=MESSAGE/d ; s/^.*Type=STORAGE Value=// ; s/ Limit=.*//'`;
#chomp $use_kb;
my $use_kb = $mailpasswd{$user}{'quota_used'};
#my($use_kb, $dummy) = split /\s+/, $use;
#logline("debug","get_mailpasswd fb user=$user quota=$quota du -sk $home=" . $use_kb . "") if $debug;
$qtst{$user}{'use'} = $use_kb;
$sum_use += $qtst{$user}{'use'};
}
#return(\%qtst, $sum_limit, $sum_use, $serverlimit);
}
else{
open(QUOTASTATS,"/usr/sbin/sqt|");
while(<QUOTASTATS>){
chomp;
push @qtst, "$_";
}
close(QUOTASTATS);
}
if (! $fb) {
foreach (@qtst){
next if /^(=|User name)/;
if(/^Allocated/){
($sum_limit,$sum_use) = (split(/\|\s+/,$_))[2,3];
$sum_limit =~ s/K//;
$sum_use =~ s/K//;
$sum_limit /= 1024;
$sum_use /= 1024;
}
elsif (/^Max\/available/) {
($serverlimit) = (split(/\|\s+/,$_))[2];
$serverlimit =~ s/K//;
$serverlimit /= 1024;
}
else{
my ($mailuser,$mailquota,$mailuse) = (split(/\|\s+/,$_))[0,2,3];
$mailuser =~ s/^\s+//;
$mailquota =~ s/K//;
$mailuse =~ s/K//;
#prevent division by zero
$mailquota = '1024' if ($mailquota eq '0');
$qtst{$mailuser}{'quota'} = $mailquota;
$qtst{$mailuser}{'use'} = $mailuse;
}
}
}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return(\%qtst, $sum_limit, $sum_use, $serverlimit);
}
sub getquota_ftp{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my %quota;
my $sum_limit = '';
my $sum_use = '';
my $serverlimit = '';
open(QUOTASTATS,"/usr/sbin/quotastats|") if $fb;
open(QUOTASTATS,"/usr/sbin/sqt|") unless $fb;
while(<QUOTASTATS>){
next if /^(=|User name)/;
#Allocated/used | | 14588928K| 2950752K
#Max/available | | 10240000K| 7289248K
if (/^Allocated/) {
($sum_limit,$sum_use) = (split(/\|\s+/,$_))[2,3];
$sum_limit =~ s/K//;
$sum_use =~ s/K//;
$sum_limit /= 1024;
$sum_use /= 1024;
}
elsif (/^Max\/available/) {
($serverlimit) = (split(/\|\s+/,$_))[2];
$serverlimit =~ s/K//;
$serverlimit /= 1024;
}
else{
my ($username,$quota,$use) = (split(/\|\s+/,$_))[0,2,3];
$username =~ s/\s+//g;
$quota =~ s/K//;
$use =~ s/K//;
#prevent division by zero
$quota = '1024' if ($quota eq '0');
$quota{$username}{"quota"} = $quota;
$quota{$username}{"use"} = $use;
#logline("debug","getquota_ftp username=$username quota=$quota use=$use") if $debug;
}
}
close(QUOTASTATS);
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return(\%quota, $sum_limit, $sum_use, $serverlimit);
}
sub extern_mx{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $mxhost = `cat /etc/mxhost 2>/dev/null`;
chomp $mxhost;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return ($mxhost);
}
sub make_socket{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $localhost = `resolveip -s localhost`;
chomp $localhost;
my $mxhost = extern_mx();
unless ($localhost =~ m#^(.*)$#) {
dienice "'$localhost' has invalid characters.\n";
}
$localhost = $1;
unless ($mxhost =~ m#^(.*)$#) {
dienice "'$mxhost' has invalid characters.\n";
}
$mxhost = $1;
my $socket=IO::Socket::INET->new( PeerAddr => $mxhost,
PeerPort => 6996,
LocalAddr => $localhost,
Proto => 'tcp',
Type => SOCK_STREAM,
Timeout => 60
)
or dienice "couldn't open port\n";
$socket->autoflush(1);
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return($socket);
}
sub close_socket{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $socket = shift;
close($socket);
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub get_userchars {
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my (@allfiles, $userdirname, $user, $uid, $realname, @userlist, $domain, $unique_domain, %active_user_chars, %active_users, %active_domains, %active_domain_chars, %userarray, %domainarray);
#kein oder leeres Userlisting?
unless (-s "/usr/local/etc/easytecc/spamuser.conf"){
logline("debug","no /usr/local/etc/easytecc/spamuser.conf") if $debug;
opendir DIR, "/home" or die "You have no /home dir! Contact the support immediately!: $!";
@allfiles = grep !/^\.\.?$/, readdir DIR;
closedir DIR;
while (@allfiles) {
$userdirname = pop @allfiles;
if (-s "/home/$userdirname/.spamproc"){
push @userlist, $userdirname;
}
}
logline("debug","userlist: @userlist") if $debug;
if(extern_mx()){
my $socket = make_socket();
logline("debug","nach make_socket()") if $debug;
print $socket "getpasswd=\n";
while(<$socket>){
($user,$uid,$realname) = (split(/:/,$_))[0,2,4];
if($uid < 1000 ){
#keine Systemuser
}
else {
logline("debug","passwd:user=$user;uid=$uid;realname=$realname") if $debug;
$userarray{$user}{'name'} = $user;
$userarray{$user}{'realname'} = $realname;
}
}
}
elsif($fb){
my $passwd = easytecc3::get_mailpasswd();
my %passwd = %{$passwd->file_parsed_hash()};
foreach(sort keys %passwd){
logline("debug","fb passwd:user=$_") if $debug;
$userarray{$user}{'name'} = $_;
$userarray{$user}{'realname'} = $passwd{$_}{'gecos'};
}
}
else{
open(PASSWD,"/etc/passwd");
while(<PASSWD>){
($user,$uid,$realname) = (split(/:/,$_))[0,2,4];
if($uid < 1000 ){
#keine Systemuser
}
else {
logline("debug","passwd:user=$user;uid=$uid;realname=$realname") if $debug;
$userarray{$user}{'name'} = $user;
$userarray{$user}{'realname'} = $realname;
}
}
close(PASSWD);
}
#spamconf schreiben
open(USERL,">/usr/local/etc/easytecc/spamuser.conf");
foreach $user (@userlist){
$domain = $userarray{$user}{'realname'};
$domain =~ s/^\s+//;
$domain =~ s/\s+.*//;
print USERL "$user=$domain\n" if $domain;
unless($domain){
print USERL "$user=$user\n" if ($user =~ /\./);
}
}
close(USERL);
undef %userarray;
}
open(USERL,"/usr/local/etc/easytecc/spamuser.conf");
while(<USERL>){
my ($user,$domain) = split(/=/,$_);
chomp($domain);
logline("debug","user=$user domain=$domain") if $debug;
next unless(-e "/home/$user/.spamd/user_prefs");
if($user){
##array fr user sortierung
$userarray{$user}{'name'} = $user;
$userarray{$user}{'domain'} = $domain;
#userspezifische Einstellungen, gehört zu keiner Domain, z.B. FTPuser
if(! is_domain($domain)){
logline("debug","#$user# ne #$domain#") if $debug;
$active_user_chars{substr(lc $user,0,1)} = 1;
$active_users{$user} = 1;
}
#userspezifische Einstellungen, user ist regulärer emailuser
elsif($user ne $domain && is_domain($domain)){
$active_user_chars{substr(lc $user,0,1)} = 1;
$active_users{$user} = 1;
}
#domainspezifische Einstellungen
elsif($user eq $domain && is_domain($domain)){
$domain = domain_to_unicode($domain);
##array fr domain sortierung
$unique_domain = "$domain$user";
$domainarray{$unique_domain}{'name'} = $user;
$domainarray{$unique_domain}{'domain'} = $domain;
$active_domain_chars{substr(lc $domain,0,1)} = 1;
$active_domains{$domain} = 1;
}
}
}
close(USERL);
#my @user_charlist = keys %active_user_chars;
#my @domain_charlist = keys %active_domain_chars;
foreach(keys %active_domain_chars){
logline("debug",'active_domain_chars=' . $_ . "") if $debug;
}
foreach(keys %active_user_chars){
logline("debug",'active_user_chars=' . $_ . "") if $debug;
}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return(\%active_user_chars, \%active_domain_chars, \%active_users, \%active_domains);
}
sub decrypt {
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $passwordfile = shift;
my @salt = ("43","112","120","36","96","94","68","43","62","15","89","12");
my $plaintext = "";
my $cyphertext = "";
if($easytecc_custom_conf_entries{'ShowMailuserPasswords'} eq "NO"){
return '';
}
if(-f $passwordfile){
open (CRYPT , "$passwordfile");
while(<CRYPT>) {
$cyphertext .= $_;
}
close(CRYPT);
} else {
# keep it ugly
$cyphertext = $passwordfile;
}
my $salt = 0;
my @cypher = unpack('C*',$cyphertext);
foreach my $number (@cypher){
$number -= $salt[$salt];
$plaintext .= pack('C*',$number);
$salt++;
if(! -f $passwordfile && $salt == scalar @salt){
$salt = 0;
}
}
$plaintext =~ s/\s+$//;
#logline("debug","file=$passwordfile pass=$plaintext") if $debug;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return $plaintext;
}
sub mysql_connect{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
# User und Pass wird von anderer Funktion übergeben, wenn nicht ist es root und bei Entryservern admin
my $dbuser = shift;
my $dbpass = shift;
$dbuser = 'root' if not defined $dbuser;
# wenn Rückgabewert = 0, dann _warscheinlich entryserver und dbuser ist admin anstatt root
# kann ggf. aber durch /usr/local/etc/easytecc/.dbconf überschrieben werden.
$dbuser = 'admin' if(defined is_ftp_limited());
# Achtung, da $password über require gesetzt wird, darf es hier nicht mit my definiert werden, da ansonsten leer
#my $password = '';
my $db_host = $ENV{HTTP_HOST};
if(! $db_host){
#open(GET_HOST, "</etc/hosts");
# my $hosts = (<GET_HOST>);
#close (GET_HOST);
#my ($tmp, $host, $tmp2) = split (/\s+/, $hosts);
#$db_host = $host;
$db_host = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
}
if ($fb) {
$db_host = 'localhost';
}
my $database = "mysql:$db_host:3306";
$database = "db01:$db_host:3306" if(defined is_ftp_limited());
my $dbh = '';
my $mysql_connect_error = '';
# kommt von Formular, um mysqluser anzugeben, der Datenbanken und Backups anlegen kann
if($dbpass){
$dbh = DBI->connect('DBI:mysql:database=mysql;mysql_socket=/tmp/mysql.sock', "$dbuser", "$dbpass" ) or $mysql_connect_error = '1';
logline("debug","mysql socket connect mysql_connect_error=$mysql_connect_error") if $debug;
if ($mysql_connect_error) {
$mysql_connect_error = '';
$dbh = DBI->connect('DBI:mysql:'.$database, "$dbuser", "$dbpass" ) or $mysql_connect_error = '1';
logline("debug", "add_mysql_password mysql_connect_error=$mysql_connect_error user=$dbuser pass=$dbpass host=$db_host") if $debug;
}
}
elsif(-e "/usr/local/etc/easytecc/.dbconf"){
my $dbconf = `cat /usr/local/etc/easytecc/.dbconf`;
my ($user,$password) = split /\n/, $dbconf;
$user =~ s/^\$user=[\"\'](.*)[\"\']\;/$1/;
$password =~ s/^\$password=[\"\'](.*)[\"\']\;/$1/;
$user = $dbuser if $user eq '';
$dbh = DBI->connect('DBI:mysql:database=mysql;mysql_socket=/tmp/mysql.sock', "$user", "$password" ) or $mysql_connect_error = '1';
logline("debug","mysql socket connect mysql_connect_error=$mysql_connect_error") if $debug;
if ($mysql_connect_error) {
$mysql_connect_error = '';
$dbh = DBI->connect('DBI:mysql:'.$database, "$user", "$password" ) or $mysql_connect_error = '1';
}
logline("debug", "mit .dbconf mysql_connect_error=$mysql_connect_error user=$user pass=$password host=$db_host") if $debug;
}
else{
if (-e "/home/httpd/docs/twig/config/dbconfig.inc.php3"){
open (GETPASSWORD,"</home/httpd/docs/twig/config/dbconfig.inc.php3");
($dbh, $mysql_connect_error) = get_mysql_password();
close (GETPASSWORD);
}
elsif (-e "/home/httpd/docs/twig/config/dbconfig.inc.php"){
open (GETPASSWORD,"</home/httpd/docs/twig/config/dbconfig.inc.php");
($dbh, $mysql_connect_error) = get_mysql_password();
close (GETPASSWORD);
}
elsif (-e "/home/httpd/docs/twig/config/dbconfig.inc.php4"){
open (GETPASSWORD,"</home/httpd/docs/twig/config/dbconfig.inc.php4");
($dbh, $mysql_connect_error) = get_mysql_password();
close (GETPASSWORD);
}
else{
$mysql_connect_error = '1';
}
}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return($dbh, $mysql_connect_error);
}
sub get_mysql_password{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $db_host = $ENV{HTTP_HOST};
$db_host = 'localhost' if $fb;
my $database = "mysql:$db_host:3306";
my $user = 'root';
$user = 'admin' if(defined is_ftp_limited());
my $password = '';
my $mysql_connect_error = '';
while(<GETPASSWORD>){
if (/sqlpassword/){
$_ =~ s/\s+//g;
$_ =~ s/.*=\"//g;
$_ =~ s/\".*//g;
$password = $_;
}
}
my $dbh = DBI->connect('DBI:mysql:database=mysql;mysql_socket=/tmp/mysql.sock', "$user", "$password" ) or $mysql_connect_error = '1';
logline("debug","mysql socket connect mysql_connect_error=$mysql_connect_error") if $debug;
if ($mysql_connect_error) {
$mysql_connect_error = '';
$dbh = DBI->connect('DBI:mysql:'.$database, $user, $password ) or $mysql_connect_error = '1';
}
if ( ! $mysql_connect_error){
open (WRITEPASSWORD, "> /usr/local/etc/easytecc/.dbconf");
print WRITEPASSWORD qq~\$user=\"$user\";\n\$password=\"$password\";\n~;
close WRITEPASSWORD;
}
# wenn Passwort nicht funktioniert, dann Fehler zurckgeben
logline("debug","<<< Leaving ".(caller(0))[3]."() = $mysql_connect_error") if $debug;
return($dbh, $mysql_connect_error);
}
sub zeit {
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $formatedtime_ref = shift;
my @formatedtime = @$formatedtime_ref;
#my $wtag = ("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa")[(localtime)[6]];
my $wtag = ("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa")[(@formatedtime)[6]];
my $mtag = sprintf("%02d", (@formatedtime)[3]);
my $monat = ("Jan"," Feb", "Mär", "Apr"," Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez")[(@formatedtime)[4]];
my $jahr = (@formatedtime)[5] + 1900;
my $stunde = sprintf("%02d", (@formatedtime)[2]);
my $min = sprintf("%02d", (@formatedtime)[1]);
my $zeit = "$wtag, $mtag\. $monat $jahr $stunde\:$min Uhr";
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return $zeit;
}
sub cronjob_selected_time{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $template_ref = shift;
my $cronjob_ref = shift;
my $template = $$template_ref;
my %cronjob = %$cronjob_ref;
# $cronjob{'job'}
# $cronjob{'min'}
# $cronjob{'std'}
# $cronjob{'mday'}
# $cronjob{'mon'}
# $cronjob{'wday'}
# Null vorweg wenn nur eine Ziffer
foreach(keys %cronjob){
logline("debug",qq~key=$_ value=$cronjob{$_}\n~) if $debug;
# wday kann direkt bernommen werden
next if $_ eq 'wday';
$cronjob{$_} = '0' . $cronjob{$_} if length($cronjob{$_}) == '1';
}
# in cronjob-Template Zeiten als "selected" ausgeben:
#<SELECT NAME="min">
#<OPTION <TMPL_VAR NAME=option_selected_all_min>>Minütlich</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_all2_min>>Alle 2</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_all5_min>>Alle 5</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_all10_min>>Alle 10</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_all15_min>>Alle 15</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_all30_min>>Alle 30</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_00_min>>00</OPTION>
#.
#.
#<OPTION <TMPL_VAR NAME=option_selected_59_min>>59</OPTION>
my %time_conversion_min = (
'*' => 'all',
'*/2' => 'all2',
'*/5' => 'all5',
'*/10' => 'all10',
'*/15' => 'all15',
'*/30' => 'all30'
);
if(not exists $time_conversion_min{$cronjob{'min'}}){
$time_conversion_min{$cronjob{'min'}} = $cronjob{'min'};
}
logline("debug",qq~cronjob{'min'}=$cronjob{'min'} conversion=$time_conversion_min{$cronjob{'min'}}\n~) if $debug;
$template->param('option_selected_' . $time_conversion_min{$cronjob{'min'}} . '_min' => 'selected');
#<SELECT NAME="std">
#<OPTION <TMPL_VAR NAME=option_selected_all_std>>Stündlich</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_all2_std>>Alle 2</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_all4_std>>Alle 4</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_all6_std>>Alle 6</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_all8_std>>Alle 8</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_all12_std>>Alle 12</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_00_std>>00</OPTION>
#.
#.
#<OPTION <TMPL_VAR NAME=option_selected_23_std>>23</OPTION>
my %time_conversion_std = (
'*' => 'all',
'*/2' => 'all2',
'*/4' => 'all4',
'*/6' => 'all6',
'*/8' => 'all8',
'*/12' => 'all12'
);
if(not exists $time_conversion_std{$cronjob{'std'}}){
$time_conversion_std{$cronjob{'std'}} = $cronjob{'std'};
}
$template->param('option_selected_' . $time_conversion_std{$cronjob{'std'}} . '_std' => 'selected');
#<SELECT NAME="mday">
#<OPTION <TMPL_VAR NAME=option_selected_all_mday>>Jeden</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_all2_mday>>Alle 2</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_first_half_mday>>1.+15.</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_01_mday>>01</OPTION>
#.
#.
#<OPTION <TMPL_VAR NAME=option_selected_31_mday>>31</OPTION>
my %time_conversion_mday = (
'*' => 'all',
'*/2' => 'all2',
'1,15' => 'first_half'
);
if(not exists $time_conversion_mday{$cronjob{'mday'}}){
$time_conversion_mday{$cronjob{'mday'}} = $cronjob{'mday'};
}
$template->param('option_selected_' . $time_conversion_mday{$cronjob{'mday'}} . '_mday' => 'selected');
#<SELECT NAME="mon">
#<OPTION <TMPL_VAR NAME=option_selected_all_mon>>Jeden</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_even_mon>>Feb.,Apr.,Jun.,Aug.,Okt.,Dez.</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_quarter_mon>>Mar.,Jun.,Sep.,Dez.</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_6_12_mon>>Jun.,Dez.</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_1_mon>>Januar</OPTION>
#.
#.
#<OPTION <TMPL_VAR NAME=option_selected_12_mon>>Dezember</OPTION>
my %time_conversion_mon = (
'*' => 'all',
'2,4,6,8,10,12' => 'even',
'3,6,9,12' => 'quarter',
'6,12' => '6_12'
);
if(not exists $time_conversion_mon{$cronjob{'mon'}}){
$time_conversion_mon{$cronjob{'mon'}} = $cronjob{'mon'};
}
$template->param('option_selected_' . $time_conversion_mon{$cronjob{'mon'}} . '_mon' => 'selected');
#<SELECT NAME="wday">
#<OPTION <TMPL_VAR NAME=option_selected_all_wday>>Jeden</OPTION>
#<OPTION <TMPL_VAR NAME=option_selected_1_wday>>Montag</OPTION>
#.
#.
#<OPTION <TMPL_VAR NAME=option_selected_0_wday>>Sonntag</OPTION>
my %time_conversion_wday = (
$cronjob{'wday'} => $cronjob{'wday'}
);
$template->param('option_selected_' . $time_conversion_wday{$cronjob{'wday'}} . '_wday' => 'selected');
$template->param('job' => $cronjob{'job'});
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub store_file_handle{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $handle = shift;
$file_handler_store{$handle->file_name} = $handle;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub return_file_handler_store{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return(\%file_handler_store);
}
sub form_to_cron{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my %form_to_cron = (
'all' => '*',
'all2' => '*/2',
'all5' => '*/5',
'all4' => '*/4',
'all6' => '*/6',
'all8' => '*/8',
'all10' => '*/10',
'all12' => '*/12',
'all15' => '*/15',
'all30' => '*/30',
'first_half' => '1,15',
'even' => '2,4,6,8,10,12',
'quarter' => '3,6,9,12',
'6_12' => '6,12'
);
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return(\%form_to_cron);
}
sub string_to_utf8{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $string = shift;
my $decoder = Encode::Guess->guess($string, qw/ascii utf8 latin1/);
logline("debug", "decoder=" . $decoder->name . "string = $string") if ref($decoder);
if(ref($decoder) && $decoder->name =~ /utf8/){
logline("debug","nix") if $debug;
#nix, ist schon utf8
}
else{
logline("debug","nach utf8 codieren") if $debug;
$string = $decoder->decode($string) if ref($decoder);
}
$string =~ s/ä/ä/g;
$string =~ s/ö/ö/g;
$string =~ s/ü/ü/g;
$string =~ s/Ä/Ä/g;
$string =~ s/Ö/Ö/g;
$string =~ s/Ü/Ü/g;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return($string);
}
sub prepare_user_prefs {
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my ($self, $input_ref) = @_;
my %input_tmp = %$input_ref;
my %input;
foreach my $key(keys %input_tmp){
if ($key =~ /^special_/) {
$key =~ s/^special_//;
$input{$key} = $input_tmp{'special_'.$key};
}
else{
$input{$key} = $input_tmp{$key};
}
}
my @new_user_prefs;
my @ok_languages = ();
my @ok_locales = ();
my $ok_locales_all = '';
my %lang = spam_lang();
my %locale = spam_locale();
foreach(keys %input){
next unless (/^lang_/);
next if (/^lang_(europe|china|russia|other)$/);
logline("debug","input=$_ lang=".$input{$_}) if $debug;
push @ok_languages, $input{$_};
push @ok_locales, 'en' if $_ eq 'en';
push @ok_locales, 'ru' if $_ eq 'ru';
push @ok_locales, 'ja' if $_ eq 'ja';
push @ok_locales, 'ko' if $_ eq 'ko';
push @ok_locales, 'th' if $_ eq 'th';
push @ok_locales, 'zh' if $_ eq 'zh';
$ok_locales_all = '1' if (/^$locale{'all'}$/);
}
foreach(@{$self->file_content}){
if(/^required_hits\s+/){
push @new_user_prefs, "required_hits\t\t$input{'pspam_level'}";
}
elsif(/^report_safe\s+/){
push @new_user_prefs, "report_safe\t\t$input{'report_safe'}";
}
elsif(/^ok_languages\s+/){
push @new_user_prefs, "ok_languages\t\t" . join(' ', @ok_languages);
}
elsif(/^ok_locales\s+/){
push @new_user_prefs, "ok_locales\t\t" . join(' ', @ok_locales) unless $ok_locales_all;
push @new_user_prefs, "ok_locales\t\tall" if $ok_locales_all;
}
elsif(! /^\s*score\s+/i) {
push @new_user_prefs, $_;
}
}
# gather scores
my %scores;
my @scores_content = split m(\r\n|\r|\n), $input{'scores'};
foreach(@scores_content){
next unless(/\s+\-?[0-9\.\-]+\s*$/);
s/^\s*score\s*//i;
my ($rule,$score) = split m(\s+), $_, 2;
if(!defined($rule) || !defined($score)){
next;
}
$scores{$rule} = $score;
logline("debug",'score ' . $rule . ' ' . $score) if $debug;
}
foreach my $rule (sort keys %scores){
push @new_user_prefs, 'score ' . $rule . ' ' . $scores{$rule};
# no more shortcircuit, schwanzus longus
#if($scores{$rule} >= $input{'cspam_level'}){
# push @new_user_prefs, 'shortcircuit ' . $rule . ' spam';
#}
}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return(\@new_user_prefs);
}
sub del_array_duplicates{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my %all=();
@all{@_}=1;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return (keys %all);
}
sub is_ftp_limited{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $ftpcount = '';
if(-e "/etc/vsd/ftp"){
logline("debug","/etc/vsd/ftp existiert") if $debug;
#also entry server
open(FTP,"/etc/vsd/ftp");
while(<FTP>){
$ftpcount = $_;
chomp $ftpcount;
}
close(FTP);
$ftpcount = '0' if !$ftpcount;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return($ftpcount);
}
else{
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return(undef);
}
}
sub add_mysqldb{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $input_ref = shift;
my %input = %$input_ref;
my($dbh, $mysql_connection_error) = mysql_connect();
my $db_host = $ENV{HTTP_HOST};
$db_host = 'localhost' if $fb;
my $db = $input{'db'};
#achtung,achtung: $db müssen in Backtickets, ' und " funktionieren nicht, ebenso prepared statements. Fehler in DBD::mysql
my $query = qq~CREATE DATABASE IF NOT EXISTS `$db`~;
my $sth = $dbh->prepare($query);
if (!$sth) {
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return("Error:" . $dbh->errstr . "\n");
}
if(!$sth->execute){
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return("Error:" . $dbh->errstr . "\n");
}
$dbh->disconnect if $dbh;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return();
}
sub add_mysqluser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $input_ref = shift;
my %input = %$input_ref;
my($dbh, $mysql_connection_error) = mysql_connect();
#my $db_host = `grep -m1 han-solo.net /etc/hosts | awk '{print \$2}'`;
my $db_host = `sed 's/^.* // ; s/\$/.han-solo.net/' /etc/FQDN 2>/dev/null`;
chomp $db_host;
#my $db_host = $ENV{HTTP_HOST};
#$db_host = 'localhost' if $fb;
my $db = $input{'db'};
my $dbuser = $input{'dbuser'};
my $dbpass = $input{'dbpass'};
#aus unerklärlichen Gründen darf das Passwort nicht in Backtickets sondern muss in einfachen Anführungszeichen
# mysql8
my $query = qq~CREATE USER `$dbuser`\@`$db_host` IDENTIFIED BY '$dbpass'~;
my $sth = $dbh->prepare($query);
if (!$sth) {
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return("Error:" . $dbh->errstr . "\n");
}
if(!$sth->execute){
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return("Error:" . $dbh->errstr . "\n");
}
$query = qq~GRANT ALL PRIVILEGES ON `$db`.* TO `$dbuser`\@`$db_host`~;
my $sth = $dbh->prepare($query);
if (!$sth) {
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return("Error:" . $dbh->errstr . "\n");
}
if(!$sth->execute){
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return("Error:" . $dbh->errstr . "\n");
}
#additional user@localhost for use via socket or localhost
$query = qq~CREATE USER `$dbuser`\@`localhost` IDENTIFIED BY '$dbpass'~;
$sth = $dbh->prepare($query);
if (!$sth) {
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return("Error:" . $dbh->errstr . "\n");
}
if(!$sth->execute){
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return("Error:" . $dbh->errstr . "\n");
}
$query = qq~GRANT ALL PRIVILEGES ON `$db`.* TO `$dbuser`\@`localhost`~;
$sth = $dbh->prepare($query);
if (!$sth) {
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return("Error:" . $dbh->errstr . "\n");
}
if(!$sth->execute){
logline("debug","<<< Leaving ".(caller(0))[3]."() by error.") if $debug;
return("Error:" . $dbh->errstr . "\n");
}
$dbh->disconnect if $dbh;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return();
}
sub add_ftpuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $input_ref = shift;
my %input = %$input_ref;
#foreach(keys %input){
#logline("debug",qq~$_=$input{$_}\n~) if $debug;
#}
my $path = $input{'home'};
my $ftpcount = '';
my $error = '';
# user immer klein
$input{'ftpuser'} = lc($input{'ftpuser'});
if(!length($input{'gecos'})){
$input{'gecos'} = $input{'ftpuser'};
}
# wenn in Formular kein Pfad angegeben, dann Standardpfad /home/httpd/docs/username
if ($fb) {
$path = '/usr/local/www/apache24/noexec/' . $input{'ftpuser'} unless $input{'home'};
}
else{
$path = '/home/httpd/docs/' . $input{'ftpuser'} unless $input{'home'};
}
# wenn neuer vhost mit FTP-User angelegt wird, dann homeverzeichnis auf documentroot legen
$path = $input{'droot'} if $input{'droot'};
#checken ob Anzahl ftp user begrenzt (entry server)
if(-e "/etc/vsd/ftp"){
logline("debug","/etc/vsd/ftp existiert") if $debug;
#also entry server
open(FTP,"/etc/vsd/ftp");
while(<FTP>){
$ftpcount = $_;
chomp $ftpcount;
}
close(FTP);
logline("debug","/etc/vsd/ftp -> $ftpcount") if $debug;
if($ftpcount > 0 && $path =~ /^\/home\/httpd\//){
#ok - ftp User vorhanden und Pfad des Users im Apache Bereich
$ftpcount--;
#-f für FTP Fähigkeiten
$error = `/usr/sbin/adduser -f -h '$path' -d '$input{'gecos'}' -q $input{'ftpquota'}M -p '$input{'ftppass'}' -n '$input{'ftpuser'}' 2>&1`;
open(FTP,">/etc/vsd/ftp");
print FTP $ftpcount;
close(FTP);
logline("debug","/etc/vsd/ftp -> $ftpcount # neu geschrieben") if $debug;
}
else {
# wenn /etc/vsd/ftp leer oder null, dann können keine weiteren FTP- user angelegt werden.
$error = "Auf diesem Servertyp können keine weiteren FTP-Benutzer angelegt werden";
}
}
else {
# wenn /etc/vsd/ftp nicht existiert, dann gibt es keine ftp-Begrenzung, z.Z. alle Reseller- und ded. Server
logline("debug","/etc/vsd/ftp existiert nicht") if $debug;
##User anlegen
#-f für FTP Fähigkeiten
if($fb){
logline("debug",qq~/usr/iports/bin/sudo /usr/sbin/useradd -f -h \'$path\' -d \'$input{'gecos'}\' -q $input{'ftpquota'}M -p \'$input{'ftppass'}\' -n \'$input{'ftpuser'}\'\n~) if $debug;
$error = `/usr/iports/bin/sudo /usr/sbin/useradd -f -h '$path' -d '$input{'gecos'}' -q $input{'ftpquota'}M -p '$input{'ftppass'}' -n '$input{'ftpuser'}' 2>&1`;
#chpass ist ne tratschtante.
$error =~ s/chpass: user information updated\n//;
}
else{
logline("debug",qq~/usr/sbin/adduser -f -h \'$path\' -d \'$input{'gecos'}\' -q $input{'ftpquota'}M -p \'$input{'ftppass'}\' -n \'$input{'ftpuser'}\'\n~) if $debug;
$error = `/usr/sbin/adduser -f -h '$path' -d '$input{'gecos'}' -q $input{'ftpquota'}M -p '$input{'ftppass'}' -n '$input{'ftpuser'}' 2>&1`;
}
}
#solange es geht nehmen wir mal usermod
if($fb && $input{'suexec'}){
$error= `/usr/iports/bin/sudo /usr/sbin/usermod -h '$path' -u '$input{'ftpuser'}' -d "'$input{'gecos'}'" -o 2>&1`;
}
logline("error",$error) if $error;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return($error);
}
sub del_ftpuser{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $ftpuser = shift;
my $delete_home = shift;
my $ftpcount = '';
my $result = '';
unless ($fb){
my $rights = `listrights $ftpuser`;
chomp $rights;
$rights =~ s/^[^:]*: ?//;
my @rights = split(/\, /,$rights);
logline("debug","privs [@rights] von $ftpuser") if $debug;
foreach my $right (@rights){
# wenn es Datei /etc/vsd/ftp gibt, dann ist Anzahl an FTP-Usern begrenzt.
# Anzahl der FTP-User, die noch angelegt werden dürfen um einen erhöhen.
if($right eq 'ftp' && -e "/etc/vsd/ftp"){
logline("debug","/etc/vsd/ftp existiert") if $debug;
#also entry server
open(FTP,"/etc/vsd/ftp");
while(<FTP>){
$ftpcount = $_;
chomp $ftpcount;
}
close(FTP);
$ftpcount++;
open(FTP,">/etc/vsd/ftp");
print FTP $ftpcount;
close(FTP);
}
}
}
logline("debug","delete_home=$delete_home") if $debug;
# entweder soll home-Verzeichnis gelöscht werden
if($delete_home eq '1'){
$result = `/usr/iports/bin/sudo /usr/sbin/userdel -r -n '$ftpuser'` if $fb;
$result = `/usr/sbin/deluser -r -n '$ftpuser'` unless $fb;
}
# oder home-Ordner des gelöschten Users dem User admin zugeordnet werden
elsif($delete_home eq '0'){
$result = `/usr/iports/bin/sudo /usr/sbin/userdel -a -n '$ftpuser'` if $fb;
$result = `/usr/sbin/deluser -a -n '$ftpuser'` unless $fb;
}
# oder user löschen und nichts mit home-Ordner machen, k wie keep
elsif($delete_home eq '2'){
# zuerst gucken, ob es Dateien gibt, die dem User zugeordnet sind. Wenn ja dann Fehlermeldung
# da nach Löschen von User sonst Dateien ohne User entstehen und vuserquota nicht mehr der summierten userquota entspricht
my $passwd = file->new({file_name => '/etc/passwd'});
$passwd->read_file;
my %passwd = %{$passwd->file_parsed_hash()};
my $home = $passwd{$ftpuser}{'home'};
logline("debug","<<< Leaving ".(caller(0))[3]."().") if ($debug && !$home);
return('L__Das Verzeichnis existiert nicht__L') unless $home;
$result = `find $home -user $ftpuser 2>/dev/null`;
if($result){
$result =~ s/\n/<br \/>/g;
logline("debug","<<< Leaving ".(caller(0))[3]."() - existing files.") if $debug;
return("L__Es existieren noch Dateien oder Verzeichnisse die dem zu löschenden FTP-User gehören:__L <br />$result<br />L__Wählen Sie eine andere Löschoption oder ordnen die Dateien einem anderen FTP-User zu.__L");
}
$result = `/usr/iports/bin/sudo /usr/sbin/userdel -k -n '$ftpuser'` if $fb;
$result = `/usr/sbin/deluser -k -n '$ftpuser'` unless $fb;
}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return($result);
}
sub encrypt_htpasswd{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $password = shift;
my @salt_chars = ('A' .. 'Z', 0 .. 9, 'a' .. 'z', '.', '/');
my $salt = join '', @salt_chars[rand 64, rand 64];
my $encrypted = crypt($password, $salt);
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return($encrypted);
}
sub encrypt {
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my ($passwordfile,$encpass) = @_;
$encpass = encode('utf-8', "$encpass");
my $cyphertext = "";
my $number = '';
my $salt = 0;
my @cypher = unpack('C*',$encpass);
my @salt = ("43","112","120","36","96","94","68","43","62","15","89","12");
foreach $number (@cypher){
$number += $salt[$salt];
$cyphertext .= pack('C*',$number);
$salt++;
if(! length($passwordfile) && $salt == scalar @salt){
$salt = 0;
}
}
if(length($passwordfile) && $easytecc_custom_conf_entries{'ShowMailuserPasswords'} ne "NO" ){
system("rm -f $passwordfile") if -e $passwordfile;
open (CRYPT , ">>$passwordfile");
print CRYPT $cyphertext;
close(CRYPT);
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
} else {
return $cyphertext;
}
}
sub spam_lang{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my %lang = (
europe => 'eu|ca|da|nl|fi|fr|fy|el|hu|is|ga|it|no|pl|pt|sco|gd|sr|sk|sl|es|sv|cy',
china => 'zh|id|ja|ko|ms|ne|tl|th|vi|hi',
russia => 'sq|ar|hy|bs|bg|be|hr|cs|et|ka|lv|lt|mr|fa|ro|ru|sa|ta|tr|uk',
other => 'af|am|eo|he|la|qu|rm|sw|yi'
);
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return(%lang);
}
sub spam_locale{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my %locale = (
en => 'en',
zh => 'zh',
ja => 'ja',
ko => 'ko',
th => 'th',
ru => 'ru',
all => 'eu|ca|da|nl|fi|fr|fy|el|hu|is|ga|it|no|pl|pt|sco|gd|sr|sk|sl|es|sv|cy|af|am|eo|he|la|qu|rm|sw|yi|id|ms|ne|tl|vi|hi|sq|ar|hy|bs|bg|be|hr|cs|et|ka|lv|lt|mr|fa|ro|sa|ta|tr|uk'
);
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return(%locale);
}
sub system_quota_reached{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $sum_limit = '';
my $sum_use = '';
my $serverlimit = '';
if ($fb) {
open(QUOTASTATS,"/usr/sbin/quotastats|");
}
else{
open(QUOTASTATS,"/usr/sbin/sqt|");
}
while(<QUOTASTATS>){
next if /^(=|User name)/;
#Allocated/used | | 14588928K| 2950752K
#Max/available | | 10240000K| 7289248K
if (/^Allocated/) {
($sum_limit,$sum_use) = (split(/\|\s+/,$_))[2,3];
$sum_limit =~ s/K//;
$sum_use =~ s/K//;
$sum_limit /= 1024;
$sum_use /= 1024;
}
elsif (/^Max\/available/) {
($serverlimit) = (split(/\|\s+/,$_))[2];
$serverlimit =~ s/K//;
$serverlimit /= 1024;
}
}
close(QUOTASTATS);
if($serverlimit - $sum_use -10 < 0){
logline("debug","<<< Leaving ".(caller(0))[3]."() - Quotagrenze erreicht.") if $debug;
return('Quotagrenze erreicht');
}
else{
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return();
}
}
sub result_debug{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $results = shift;
my %error_fields = ();
if( $results->success ){
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return();
}
# Print the name of missing fields
if ( $results->has_missing ) {
for my $f ( $results->missing ) {
logline("debug","$f is missing") if $debug;
$error_fields{$f} = 'L__Fehlende Eingabe.__L';
}
}
# Print the name of invalid fields
if ( $results->has_invalid ) {
for my $f ( $results->invalid ) {
logline("debug","$f is invalid: ".${$results->invalid($f)}[0]) if $debug;
$error_fields{$f} = ${$results->invalid( $f )}[0];
#$error_fields{$f} = "L__Ungültige Eingabe__L: " . ${$results->invalid( $f )}[0];
# meta können wir nicht nehmen:
# http://search.cpan.org/~markstos/Data-FormValidator-4.63/lib/Data/FormValidator/Results.pm#meta%28%29
# This function does not currently support multi-valued fields. If it does in the future, the above syntax will still work.
#
#Darum mißbrauchern wir inm validator set_current_constraint_name() zur Übergabe von Fehlermeldung aus Validator um Fehler dem
#Formularfeld zuzuordnen. Z.B.
# $dfv->set_current_constraint_name('gibs nich');
#
#foreach(@{$results->invalid( $f )}){
#logline("debug",$_ . "") if $debug;
#$html_result .= $_ . '<br />';
#$html_result .= $results->meta($f)->{'error'} . '<br />';
#}
}
}
# Print unknown fields to debug log
if ( $results->has_unknown ) {
for my $f ( $results->unknown ) {
logline("debug","$f is unknown") if $debug;
}
}
# Print valid fields to debug log
for my $f ( $results->valid() ) {
logline("debug",'valid ' . $f. " = ". $results->valid( $f )) if $debug;
}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return(\%error_fields);
}
sub filesize{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $filesize = shift;
my $filesize_text = '';
if ($filesize > 1023999){
#MB
$filesize /= 1024000;
$filesize *= 100;
$filesize = int($filesize);
$filesize /= 100;
$filesize =~ s/\./\,/;
$filesize .= ",00" unless ($filesize =~ /\,/);
$filesize .= "0" if ($filesize =~ /\,\d{1}$/);
$filesize_text = "MB";
}
elsif ($filesize > 10){
#KB
$filesize /= 1024;
$filesize *= 100;
$filesize = int($filesize);
$filesize /= 100;
$filesize =~ s/\./\,/;
$filesize .= ",00" unless ($filesize =~ /\,/);
$filesize .= "0" if ($filesize =~ /\,\d{1}$/);
$filesize_text = "kB";
}
elsif ($filesize > 0){
#bytes
$filesize = "0,01";
$filesize_text = "kB";
}
else {
#bytes
$filesize = "0,00";
$filesize_text = "kB";
}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return($filesize . ' ' . $filesize_text);
}
sub getsize{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $filesize = shift;
my $filesize_text = '';
if ($filesize >= 1024000){
#GB
$filesize /= 1024000;
$filesize *= 100;
$filesize = int($filesize);
$filesize /= 100;
#$filesize .= ".00" unless ($filesize =~ /\./);
#$filesize .= "0" if ($filesize =~ /\.\d{1}$/);
$filesize_text = "GB";
}
elsif ($filesize > 1023){
#MB
$filesize /= 1024;
$filesize *= 100;
$filesize = int($filesize);
$filesize /= 100;
#$filesize .= ".00" unless ($filesize =~ /\./);
#$filesize .= "0" if ($filesize =~ /\.\d{1}$/);
$filesize_text = "MB";
}
elsif ($filesize > 0){
#KB
$filesize *= 100;
$filesize = int($filesize);
$filesize /= 100;
$filesize .= ".00" unless ($filesize =~ /\./);
$filesize .= "0" if ($filesize =~ /\.\d{1}$/);
$filesize_text = "kB";
}
else {
#bytes
$filesize = "0.00";
$filesize_text = "kB";
}
$filesize .= " $filesize_text";
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return ($filesize);
}
sub getdate {
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $filedate = shift;
my @months = ('Jan','Feb','Mar','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez');
my ($min, $hr, $day, $mon, $yr) = (localtime($filedate))[1,2,3,4,5];
if ($min < 10) { $min = "0$min"; }
if ($hr < 10) { $hr = "0$hr"; }
if ($day < 10) { $day = "0$day"; }
if ($yr > 99) {
$yr-=100;
if ($yr < 10) { $yr = "200$yr"; }
elsif ($yr >= 10 && $yr < 100) { $yr = "20$yr"; }
else { $yr = "2$yr"; }
}
else {
if ($yr < 10) { $yr = "190$yr"; }
else { $yr = "19$yr"; }
}
$filedate = "$day-$months[$mon]-$yr ($hr\:$min)";
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return($filedate);
}
sub quotabar{
#obsolete, no longer used
return();
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my($quota, $used, $quotainfo) = @_;
# wegen Illegal division by zero
my $percentval = ($used/$quota)*100 if $quota > 0;
$percentval = 0 if $quota == 0;
$percentval = sprintf("%.0f", $percentval);
my $bar_usage = $percentval;
my $bar_free = 100 - $bar_usage;
my $bar_template = '';
if(($quota * .8) <= $used){
$bar_template = HTML::Template->new(filename => 'bar_red.html') unless $quotainfo eq 'MB_form';
$bar_template = HTML::Template->new(filename => 'bar_red_MB_form.html') if $quotainfo eq 'MB_form';
}
else{
$bar_template = HTML::Template->new(filename => 'bar_green.html') unless $quotainfo eq 'MB_form';
$bar_template = HTML::Template->new(filename => 'bar_green_MB_form.html') if $quotainfo eq 'MB_form';
}
# wenn Quota überschritten würde für Balken ungültiger Wert rauskommen, so daß Balken zu lang
if($bar_usage > 100){
$bar_usage = '100';
$bar_free = '0';
}
$bar_template->param('bar_usage' => $bar_usage);
$bar_template->param('bar_free' => $bar_free);
if($quotainfo eq 'all'){
$bar_template->param('quotainfo' => easytecc3::getsize($quota) . ' L__Quota__L');
$bar_template->param('quotaused' => $percentval . 'L__% in Benutzung__L');
}
elsif($quotainfo eq 'used'){
$bar_template->param('quotaused' => easytecc3::getsize($used) . ' / ' . $percentval . '%');
}
elsif($quotainfo eq 'MB_form'){
$bar_template->param('quotainfo' => 'MB' . ' L__Quota__L');
$bar_template->param('quotaused' => $percentval . 'L__% in Benutzung__L');
}
elsif($quotainfo eq 'table'){
# aktuell nix, nur Balken anzeigen
}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return($bar_template->output);
}
sub quota_alert{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my($quota, $used, $alert_factor) = @_;
if(($quota * $alert_factor) <= $used){
return(1);
}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub table{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $template_ref = shift;
my $table_header = shift;
my $table_content_ref = shift;
my $table_id = shift;
my @table_content = @$table_content_ref;
my $template = $$template_ref;
my @loop_data = ();
my $table_template = HTML::Template->new(filename => 'table-template.html');
my $odd = '1';
my $odd_class = ' class="odd"';
foreach(@table_content){
my %row_data = ();
my($field1, $field2, $field3, $field4, $field5, $field6, $field7) = split/\|/, $_;
$row_data{'1'} = '<tr' . $odd_class . '><td>' . $field1 . '</td>' unless $odd % 2;
$row_data{'1'} = '<tr><td>' . $field1 . '</td>' if $odd % 2;
$row_data{'2'} = '<td>' . $field2 . '</td>';
$row_data{'3'} = '<td>' . $field3 . '</td>';
$row_data{'4'} = '<td>' . $field4 . '</td>';
$row_data{'5'} = '<td>' . $field5 . '</td>';
$row_data{'6'} = '<td>' . $field6 . '</td>';
$row_data{'7'} = '<td>' . $field7 . '</td></tr>';
#logline("debug","table fields=$field1, $field2, $field3, $field4, $field5, $field6, $field7") if $debug;
push(@loop_data, \%row_data);
$odd++;
}
$table_template->param('table_header' => $table_header);
$table_template->param('table_content' => \@loop_data);
$template->param($table_id => $table_template->output);
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub substr_e4{
my $string = shift;
$string =~ s#^/usr/local/www/apache24/(noexec|data)/#.../#;
if (length($string) > 100) {
return('...' . substr($string, -100));
}
else{
return($string);
}
}
sub table_e4{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $template = shift;
my $table_data = shift;
my $table_template = shift;
logline("debug","template=$template table_data=$table_data table_template=$table_template") if $debug;
my $table_var = $table_template;
$table_var =~ s/\.html//;
my $tr_html = '';
my $odd = '1';
foreach my $hash_domain( sort keys %{$table_data}){
my %tr_hash = %{$table_data->{$hash_domain}};
#logline("debug","table tr hash_domain=$hash_domain") if $debug;
my $tr = HTML::Template->new(filename => "html-templates/$table_template");
foreach my $td_entry(sort keys %tr_hash){
$tr->param($td_entry => $tr_hash{$td_entry});
#obsolete, now done by jquery table plugin
#$tr->param('odd_even' => ' odd ') unless $odd % 2;
#$tr->param('odd_even' => ' even ') if $odd % 2;
#logline("debug","table tr key=$td_entry") if $debug;
}
if($fb){
$tr->param(FB => '1');
}
$tr_html .= $tr->output;
$odd++;
}
#logline("debug","table tr_html=$tr_html") if $debug;
$template->param($table_var => $tr_html);
#logline("debug","table_e4=$tr_html") if $debug;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub template_loop{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $input_ref = shift;
my %input = %$input_ref;
my $template_ref = shift;
my $loop_content_ref = shift;
my $loop = shift;
my $selected = shift;
my @loop_content = @$loop_content_ref;
my $template = $$template_ref;
my @loop_data = ();
my $count = '1';
# leeres Feld an den Anfang einfügen, damit de-selektieren mglich, damit html validiert
# aber nicht bei IP auswählen
unshift @loop_content, ' ' unless $loop eq 'ip_select' or $loop eq 'php_select' or $loop eq 'mailserver_cert_select';
foreach(@loop_content){
logline("debug","template_loop=$_ selected=$selected") if $debug;
my %row_data = ();
$row_data{'option_selected'} = 'SELECTED' if $selected eq $_;
#logline("debug","loop:$selected\tloopcon:$_") if $debug;
my($field1, $field2, $field3, $field4, $field5, $field6, $field7) = split/\|/, $_;
$row_data{'1'} = $field1;
$row_data{'2'} = $field2;
$row_data{'3'} = $field3;
$row_data{'4'} = $field4;
$row_data{'5'} = $field5;
$row_data{'6'} = $field6;
$row_data{'7'} = $field7;
$row_data{'count'} = $count;
push(@loop_data, \%row_data);
$count++;
}
#error_class wird nur nach absenden von Formular angezeigt
if($input{'action'} =~ /^exec_/ || $input{'form_submit'}){
$template->param('select_name' => qq~"$loop"~ . qq~ <TMPL_VAR NAME=error_class_$loop> ~);
}
else{
$template->param('select_name' => qq~"$loop"~);
}
# in Template für loop kann der Name der loop nicht als Templatevariable einefügt werden, da Verschachtelung von Templatevariablen nicht möglich
# $loop hat am Ende Ziffer, die weg ergibt Template-loop-namen
my $loopname = $loop;
#$loopname =~ s/[0-9]{1,5}$//g;
$template->param($loopname => \@loop_data);
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub template_loop_e4{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $input_ref = shift;
my $template_ref = shift;
my $loop_content_ref = shift;
my $loop = shift;
my $selected = shift;
#bei change_forward können mehrere vorselektiert sein, was | separiert übergeben wird
#splitten, in Hash rein und wenn ich foreach hashkey vorhanden, dann vorselektieren
my @selected = split /\|/, $selected;
my %selected_hash = map { $_ => 1 } @selected;
my %input = %$input_ref;
my @loop_content = @$loop_content_ref;
my $template = $$template_ref;
my @loop_data = ();
my $count = '1';
# leeres Feld an den Anfang einfügen, damit de-selektieren mglich, damit html validiert
# aber nicht bei IP auswählen
#unshift @loop_content, ' ' unless ($loop eq 'ip_select'||
# $loop eq 'freefields');
my $loop_content_count = scalar @loop_content;
foreach(@loop_content){
#logline("debug","template_loop_e4 loop=$loop loop_content=$_ selected=$selected") if $debug;
my %row_data = ();
#$row_data{'option_selected'} = 'SELECTED' if $selected eq $_;
$row_data{'option_selected'} = 'SELECTED' if exists $selected_hash{$_};
#logline("debug","loop:$selected\tloopcon:$_") if $debug;
my($field1, $field2, $field3, $field4, $field5, $field6, $field7) = split/\|/, $_;
#logline("debug","foreach loop_content:field1=$field1 field2=$field2 field3=$field3 field4=$field4 field5=$field5 field6=$field6 field7=$field7") if $debug;
$row_data{'1'} = $field1;
$row_data{'2'} = $field2;
$row_data{'3'} = $field3;
$row_data{'4'} = $field4;
$row_data{'5'} = $field5;
$row_data{'6'} = $field6;
$row_data{'7'} = $field7;
$row_data{'count'} = $count;
if ($loop eq 'freefields') {
my $form_field = 'freefield' . $field1 . '_' . $field2;
#logline("debug","loop freefields form_field=$form_field main error_fields=" . $main::error_fields{$form_field}) if $debug;
if (length $main::error_fields{$form_field}) {
$row_data{'error_text'} = qq~<span class="help-block">$main::error_fields{$form_field}</span>~;
}
if (length $input{$form_field}) {
$row_data{'3'} = $input{$form_field};
}
}
if ($count == $loop_content_count) {
$row_data{'last_count'} = $count;
}
push(@loop_data, \%row_data);
$count++;
}
#logline("debug","foreach loop_content: error_field user_select1=" . $main::error_fields{"user_select1"}) if $debug;
if (length $main::error_fields{$loop}) {
$template->param('error_text' => qq~<span class="help-block">$main::error_fields{$loop}</span>~);
}
#error_class wird nur nach absenden von Formular verwendet und damit html_error() HTML-Templatevariablen nach Ausgabe von Untertemplate
#benutzen kann ist Trick notwendig. Z.B. in Untertemplate user_select.html, welches in table_tr_change_forward.html inkludiert wird befindet sich Variable
#<TMPL_VAR NAME=error_class>
#Nun füllen wir diese Variable mit dem Text
#<TMPL_VAR NAME=error_class_$loop>
#so dass im html-Quelltext z.B.
#<TMPL_VAR NAME=error_class_user_select2>
#steht. Dies landet bei Fehler so bei html_error(), wo ein foreach alle %error_fields durchgeht und die CSS-Klasse has-error setzt
#ist Zeile
#$html_tmp2->param('error_class_' . $_ => "has-error");
if($input{'action'} =~ /^exec_/ || $input{'form_submit'}){
#$template->param('select_name' => qq~"$loop"~ . qq~ <TMPL_VAR NAME=error_class_$loop> ~);
$template->param('select_name' => $loop);
$template->param('error_class' => qq~<TMPL_VAR NAME=error_class_$loop>~);
}
else{
$template->param('select_name' => $loop);
}
# in Template für loop kann der Name der loop nicht als Templatevariable einefügt werden, da Verschachtelung von Templatevariablen nicht möglich
# $loop hat am Ende Ziffer, die weg ergibt Template-loop-namen
my $loopname = $loop;
$loopname =~ s/[0-9]{1,5}$//g;
$template->param($loopname => \@loop_data);
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub generatewebalizer{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
#($domainnames[0],$input{'documentroot'})
my($domain,$home) = @_;
$home = lc($home);
##/stats Verzeichnis
#`mkdir $home/stats`;
#`chmod 777 $home/stats`;
my $got = `/usr/sbin/admmkdir -p $home` if (! -d "$home");
$got = `/usr/sbin/admmkdir -p $home/stats` if (! -d "$home/stats");
##conf Datei für diesen Host
open (OF,">/usr/local/etc/$domain.conf");
open (IF,"/usr/local/etc/webalizer.conf.sample");
while (<IF>) {
s/^LogFile.*$/LogFile \/home\/web\/log\/access_log_$domain/g;
s/^OutputDir.*$/OutputDir $home\/stats/g;
s/^#?HistoryName.*$/HistoryName $domain.hist/g;
s/^#?HostName.*$/HostName www.$domain/g;
s/^#Incremental\s.*$/Incremental yes/g;
s/^#IncrementalName.*$/IncrementalName webalizer.current/g;
print OF $_;
}
close(IF);
close(OF);
protect("$home/stats");
#Zeit/Datum
my($sek,$min,$std,$mday,$mon,$year) = (localtime(time))[0,1,2,3,4,5];
$mon++;
if ($mon < 10) { $mon = "0".$mon; }
if ($mday< 10) { $mday= "0".$mday; }
if ($year< 10) { $year= "0".$year; }
if ($std< 10) { $std= "0".$std; }
if ($min< 10) { $min= "0".$min; }
if ($sek< 10) { $sek= "0".$sek; }
$year += 1900;
my %monlist = '';
$monlist{'01'} = "Jan";
$monlist{'02'} = "Feb";
$monlist{'03'} = "Mar";
$monlist{'04'} = "Apr";
$monlist{'05'} = "May";
$monlist{'06'} = "Jun";
$monlist{'07'} = "Jul";
$monlist{'08'} = "Aug";
$monlist{'09'} = "Sep";
$monlist{'10'} = "Oct";
$monlist{'11'} = "Nov";
$monlist{'12'} = "Dec";
$mon = $monlist{$mon};
open (OF,">/home/web/log/access_log_$domain");
print OF "217.80.124.83 - admin [$mday/$mon/$year:$std:$min:$sek +0000] \"GET / HTTP/1.1\" 200 155 \"http://$domain/stats\" \"Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)\"";
close(OF);
system("/usr/local/bin/webalizer -c /usr/local/etc/$domain.conf >> /home/web/log/error_log_$domain");
#alle Dateien auf den Besitzer der Domain setzen:
my($fileuid, $filegid) = (stat("$home/stats"))[4,5];
system("/usr/sbin/admchown -u $fileuid -g $filegid -d $home/stats");
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub protect {
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my($statsdir) = @_;
my($homedir);
$homedir = $statsdir;
$homedir =~ s/\/stats$//;
my $username = getuserofhome($homedir);
open (HTACCESS,">$statsdir/.htaccess") || dienice ("Fehler beim erstellen von $statsdir/.htaccess: $!");
print HTACCESS "AuthUserFile /etc/passwd\n";
print HTACCESS "AuthName \"Statistikbereich\"\n";
print HTACCESS "AuthType Basic\n\n";
print HTACCESS "<Limit POST GET>\n";
##admin ist immer Berechtigt
print HTACCESS "require user $username admin\n";
print HTACCESS "</Limit>\n";
close(HTACCESS);
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub getuserofhome {
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my ($homedir) = @_;
my $user = '';
##/etc/passwd durchlesen
open(PASS,"/etc/passwd");
while(<PASS>){
chomp;
push @passwd, "$_";
}
close(PASS);
foreach $line (@passwd){
if($line =~ /\:$homedir\:/){
$user = $line;
}
}
($user) = (split(":",$user))[0];
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return $user;
}
sub clean_session{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $session = shift;
return unless $session;
my $params_hashref = $session->dataref();
my %params = %$params_hashref;
foreach(keys %params){
#Sessionkeys die mit _ anfangen sind Systemkeys, diese nicht löschen
next if /^_/;
$session->clear($_);
}
$session->flush();
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return();
}
sub mailuser_exists{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $user = email_to_ascii(shift);
my $mailpasswd = easytecc3::get_mailpasswd();
my %mailpasswd = %{$mailpasswd->file_parsed_hash()};
#my %mailpasswd = %{get_mailpasswd()};
logline("debug","checking user $user") if $debug;
logline("debug","result: $mailpasswd{$user}") if $debug;
if(not exists $mailpasswd{$user}){
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return();
}
else{
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return('1');
}
}
sub ascii_domain{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $domain = shift;
# Domain kann dddd.de oder auch wildcarddomain *.ddd.de sein
#wenn wildcard, dann *vor Umwandlung abschneiden, domain umwandlen und * wieder ran, ansonsten schlägt domain_to_ascii fehl
#domains mit _ nicht erlaubt, direkt zurückgeben
logline("debug","Testing \$domain = ".$domain) if $debug;
if($domain =~ /_/){
logline("debug","<<< Leaving ".(caller(0))[3]."() by _.") if $debug;
return($domain);
}
elsif($domain =~ /^\*\.(.*)$/){
my $domain = $1;
$domain = domain_to_ascii($domain);
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return('*.' . $domain);
}
#nur wenn ein . vorkommt kann es Domain sein
elsif($domain =~ /.+\..+/){
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return(domain_to_ascii($domain));
}
#ohne . nicht umwandeln, würde mit
#Invalid domain name (toASCII, step 3)
#fehlschlagen
else{
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return($domain);
}
}
sub is_tld{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $tld = shift;
if($tld =~ /^\.[a-z]{2,}$/){
logline("debug","<<< Leaving ".(caller(0))[3]."() by _.") if $debug;
return(1);
}
else{
return(undef);
}
}
sub is_domain{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
#ersetzt is_domain aus Data::Validate::Domain, da es nicht mit den neuen TLDs klarkommt
my $domain = shift;
if($domain =~ /^([a-z0-9]+(-[a-z0-9\-]+)*\.)+[a-z]{2,}$/){
logline("debug","<<< Leaving ".(caller(0))[3]."() by _.") if $debug;
return(1);
}
else{
return(undef);
}
}
sub is_email{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
#ersetzt is_email aus Data::Validate::Email, da es nicht mit den neuen TLDs klarkommt
my $email = shift;
if($email !~ /^[A-Za-z\.\-\_0-9]{1,}\@[A-Za-z\-\.0-9]{2,}\.[A-Za-z0-9]{2,25}$/){
logline("debug","<<< Leaving ".(caller(0))[3]."() by _.") if $debug;
return(undef);
}
else{
return(1);
}
}
sub get_size_mysql{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
# Grösse der Datenbanken ermitteln
my $datadir = '';
my %database_size;
my $command = '';
my $mysql = `grep mysql_enable /etc/rc.conf`;
# > 3
if($mysql =~ /NO/){
$datadir = '/var/lib/mysql/data';
}
else{
$datadir = '/var/lib/mysql';
}
if ($fb) {
$datadir = '/var/db/mysql';
}
my ($dbh, $mysql_connect_error) = easytecc3::mysql_connect();
logline("debug","######################dbh=$dbh error=$mysql_connect_error");
my $query = "SELECT SUM(data_length + index_length) / 1024 AS total_size, table_schema FROM information_schema.TABLES GROUP BY table_schema";
my $sth = $dbh->prepare( $query );
$sth->execute;
while ( my @row = $sth->fetchrow_array ){ # alle rows auslesen
my($size, $database) = @row;
print DEBUG "size=$size, database=$database\n";
#$database_size{$database} = easytecc3::getsize($size);
$database_size{$database} = $size;
}
#$command = "$easytecc_prefix/get_size_mysql.pl " . $datadir;
#open(COMMAND, "$command|");
#while(<COMMAND>){
# logline("debug","com = $_") if $debug;
# # Output in kB
# #676 mysql
# #88996 ndb_3_fs
# my($size, $database) = split /\s+/, $_;
# print DEBUG "size=$size, database=$database\n";
# #$database_size{$database} = easytecc3::getsize($size);
# $database_size{$database} = $size;
#}
#close COMMAND;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return(%database_size, $datadir);
}
sub del_autoreply_file{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $file = shift;
if(extern_mx()){
my $socket = make_socket();
logline("debug","nach make_socket()") if $debug;
print $socket "del_autoreply_file=$file\n" if $file;
}
if ($file =~ /^\/usr\/local\/etc/){
`/usr/iports/bin/sudo /usr/sbin/rm.pl $file` if $fb;
`rm -f $file` unless $fb;
}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub backup_file{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $file = shift;
return("backup_file: missing argument") unless $file;
my $backup_dir = '/usr/local/etc/easytecc/backup_files';
if (! -e "$backup_dir") {
`mkdir $backup_dir`;
`chmod 775 $backup_dir`;
}
my $dir = $file;
$dir =~ s/\/[^\/]*$//g;
my @pieces = split (/\//,$file);
$file = pop(@pieces);
opendir DIR, "$dir" or dienice "Kann Verzeichnis $dir nicht öffnen: $!";
my @allfiles = grep /$file\./, readdir DIR;
closedir DIR;
logline("debug","dir=$dir file=$file") if $debug;
@allfiles = sort @allfiles;
#hat das mal jemand gelesen?
#if(scalar(@allfiles) > 9){
# logline("debug","#### will delete $dir/$allfiles[9] using $easytecc_prefix/rm.pl") if $debug;
# my $got = `$easytecc_prefix/rm.pl $dir/$allfiles[9]`;
# logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
# return("L__Fehler beim Löschen von__L $dir/$allfiles[9]: $got") if $got;
#}
#Zeit/Datum
my ($sek,$min,$std,$mday,$mon,$year) = (localtime(time))[0,1,2,3,4,5];
$mon++;
$year += 1900;
if ($mon < 10) { $mon = "0".$mon; }
if ($mday< 10) { $mday= "0".$mday; }
if ($std < 10) { $std = "0".$std; }
if ($min< 10) { $min= "0".$min; }
if ($sek< 10) { $sek= "0".$sek; }
# Kopie mit Zeit setzen
# bei httpd.conf|virtmaps|aliases in Verzeichnis der Dateien sichern, ansonsten easytecc-backup-Verzeichnis, weil
# z.B. in /etc aufgrund fehlender Schreibrechte keine Dateien angelegt werden können.
#$backup_dir = $dir if($file =~ /^(httpd.conf|virtmaps|aliases)$/ && !$fb);
# nur Backup wenn Datei existiert, weil z.B. bei Neuanlage von spamregeln noch keine Dateien zum sichern vorhanden sind
if(-e "$dir/$file"){
logline("debug","$easytecc_prefix/cp.pl $dir/$file $backup_dir/$file.$year$mon$mday$std$min$sek") if $debug;
my $got = `$easytecc_prefix/cp.pl $dir/$file $backup_dir/$file.$year$mon$mday$std$min$sek` unless $fb;
my $got = `/usr/iports/bin/sudo /usr/sbin/cp.pl $dir/$file $backup_dir/$file.$year$mon$mday$std$min$sek` if $fb;
#`chmod 664 $dir/$file $backup_dir/$file.$year$mon$mday$std$min$sek`;
`chmod 664 $backup_dir/$file.$year$mon$mday$std$min$sek`;
logline("error","<<< Leaving ".(caller(0))[3]."() by error.") if $got;
return("L__Fehler beim Backup von__L $dir/$file: $got") if $got;
}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub delete_from_spamconf{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my $special_spamfilter = shift;
return unless $special_spamfilter;
my $tmperror = system("cp -f /usr/local/etc/easytecc/spamuser.conf /tmp/spamuser.conf.$$");
return("can't copy /usr/local/etc/easytecc/spamuser.conf to /tmp/spamuser.conf.$$: $! $tmperror") if $tmperror;
my @new_file_content;
open (ORIGF, "/tmp/spamuser.conf.$$") or die "can't open /tmp/spamuser.conf.$$: $!";
while (<ORIGF>){
my ($user,$domain) = split(/=/,$_);
if($user ne $special_spamfilter){
push @new_file_content, $_;
}
}
close(ORIGF);
my $file = file->new({file_name => '/usr/local/etc/easytecc/spamuser.conf', file_content => \@new_file_content});
my $got = $file->write_file;
logline("error","<<< Leaving ".(caller(0))[3]."().") if $got;
return($got) if $got;
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
sub has_twig{
logline("debug",">>> Entering ".(caller(0))[3]."() from ".(caller(1))[3]."() Line: ".(caller(0))[2]) if $debug;
my ($filesize, $filedate, $owner, $fileperm) = (stat('/home/httpd/docs/twig'))[7,9,4,2];
$fileperm = sprintf "%lo", ($fileperm & 07777);
#twig-roundcube-migration: Button nur anzeigen, wenn /home/httpd/docs/twig existiert und nicht Rechte 700 hat
if(-d '/home/httpd/docs/twig' && $fileperm != '0700'){
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
return(1);
}
logline("debug","<<< Leaving ".(caller(0))[3]."().") if $debug;
}
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];
}
1;