package SrvMngr::Controller::Webhosting; #---------------------------------------------------------------------- # heading : Network # description : Webhosting # navigation : 6000 150 # # name : webhosting, method : get, url : /webhosting, ctlact : webhosting#main # name : webhostingu, method : post, url : /webhosting, ctlact : webhosting#do_action # name : webhostingr, method : get, url : /webhosting2, ctlact : webhosting#do_display # # routes : end #---------------------------------------------------------------------- use strict; use warnings; use Mojo::Base 'Mojolicious::Controller'; use Locale::gettext; use SrvMngr::I18N; use SrvMngr qw( theme_list init_session is_normal_password ); use esmith::AccountsDB; use esmith::ConfigDB; use esmith::DomainsDB; use esmith::php; our $adb = esmith::AccountsDB->open() || die "Couldn't open accounts db"; our $cdb = esmith::ConfigDB->open() || die "Couldn't open config db"; #TODO those 3 variables should be exported from esmith::php our $defaultdisabledfunc='system,show_source,' . 'symlink,exec,dl,shell_exec,' . 'passthru,phpinfo,' . 'escapeshellarg,escapeshellcmd'; our $BASEPHP = 54; our %defaultproperties = ( MemoryLimit => '128M', MaxExecutionTime => '30', MaxInputTime => '60', AllowUrlFopen => 'disabled', PostMaxSize => '20M', UploadMaxFilesize => '10M', FileUpload => 'enabled', PHPBaseDir => '/home/e-smith/files/ibays/$key:/var/lib/php/$key', DisabledFunctions => $defaultdisabledfunc, MailForceSender => "admin@".$cdb->get_value('DomainName'), AllowPHTML => 'disabled', ModDav => "disabled", AllowOverride => "None", FollowSymLinks => "disabled", Indexes => "enabled", ); # those are ok to be defined here and not in core. our %sizehash = ('20M' => 'S0020MB', '30M' => 'S0030MB', '40M' => 'S0040MB', '50M' => 'S0050MB', '75M' => 'S0075MB', '100M' => 'S0100MB', '125M' => 'S0125MB', '150M' => 'S0150MB', '175M' => 'S0175MB', '200M' => 'S0200MB', '300M' => 'S0300MB','400M' => 'S0400MB', '500M' => 'S0500MB', '600M' => 'S0600MB', '700M' => 'S0700MB', '800M' => 'S0800MB', '900M' => 'S0900MB', '1000M' => 'S1000MB', '1250M' => 'S1250MB', '1500M' => 'S1500MB', '1750M' => 'S1750MB', '1999M' => 'S2000MB'); our %binary = ('disabled' => 'DISABLED', 'enabled' => 'ENABLED'); our %timehash = ( '60' => 'T001m', '120' => 'T002m', '180' => 'T003m', '240' => 'T004m', '300' => 'T005m', '360' => 'T006m', '420' => 'T007m', '480' => 'T008m', '540' => 'T009m', '600' => 'T010m', '900' => 'T015m', '1800' => 'T030m', '2700' => 'T045m', '3600' => 'T060m', '7200' => 'T120m', '0' => 'UNLIMITED'); our %optionsproperties =( MemoryLimit => {'64M' => 'M0064MB', '128M' => 'M0128MB', '256M' => 'M0256MB', '512M' => 'M0512MB', '768M' => 'M0768MB','1024M' => 'M1024MB' ,'2048M' => 'M2048MB','3072M' => 'M3072MB','4096M' => 'M4096MB','61444M' => 'M6144MB','8192M' => 'M8192MB'}, MaxExecutionTime => {%timehash}, MaxInputTime => {%timehash}, AllowUrlFopen => {%binary}, PostMaxSize => {%sizehash}, UploadMaxFilesize => {%sizehash}, FileUpload => {%binary}, DisabledFunctions => $defaultdisabledfunc, AllowPHTML => {%binary}, ModDav => {%binary}, AllowOverride => { None =>'None' , All => 'All', AuthConfig => 'AuthConfig', FileInfo => 'FileInfo', Indexes => 'Indexes', Limit => 'Limit', 'FileInfo Indexes' => 'FileInfo Indexes', }, FollowSymLinks => {%binary}, Indexes => {%binary}, ); sub main { my $c = shift; $c->app->log->info($c->log_req); my %wh_datas = (); my $title = $c->l('wh_FORM_TITLE'); $wh_datas{'trt'} = 'LIST'; my @ibays = $adb->ibays(); $c->stash( title => $title, wh_datas => \%wh_datas, ibays => \@ibays ); $c->render(template => 'webhosting'); }; sub do_display { my $c = shift; $c->app->log->info($c->log_req); my $rt = $c->current_route; my $trt = ($c->param('trt') || ''); my $ibay = $c->param('ibay') || ''; my %wh_datas = (); my $title = $c->l('wh_FORM_TITLE'); my $modul = ''; $wh_datas{'trt'} = $trt; if ( $trt eq 'UPD' ) { my $rec = $adb->get($ibay); if ($rec and $rec->prop('type') eq 'ibay') { $wh_datas{ibay} = $ibay; $wh_datas{description} = $rec->prop('Name'); $wh_datas{indexes} = get_current_value($c, $ibay, 'Indexes'); $wh_datas{followsymLinks} = get_current_value($c, $ibay, 'FollowSymLinks'); $wh_datas{allowoverride} = get_current_value($c, $ibay, 'AllowOverride'); $wh_datas{allowurlfopen} = get_current_value($c, $ibay, 'AllowUrlFopen'); $wh_datas{memorylimit} = get_current_value($c, $ibay, 'MemoryLimit'); $wh_datas{uploadmaxfilesize} = get_current_value($c, $ibay, 'UploadMaxFilesize'); $wh_datas{postmaxsize} = get_current_value($c, $ibay, 'PostMaxSize'); $wh_datas{maxexecutiontime} = get_current_value($c, $ibay, 'MaxExecutionTime'); $wh_datas{maxinputtime} = get_current_value($c, $ibay, 'MaxInputTime'); $wh_datas{fileupload} = get_current_value($c, $ibay, 'FileUpload'); $wh_datas{allowphtml} = get_current_value($c, $ibay, 'AllowPHTML'); $wh_datas{mailforcesender} = $rec->prop('MailForceSender'); my $df = ($rec->prop('DisabledFunctions'))? $rec->prop('DisabledFunctions') : $defaultdisabledfunc; $wh_datas{disabledfunctions} = $df; # yes we want todo this one this way. $wh_datas{phpbasedir} = $rec->prop('PHPBaseDir'); # yes we keep this one simple $wh_datas{moddav} = get_current_value($c, $ibay, 'ModDav'); $wh_datas{phpversion} = get_current_php_value($c, $ibay, 'PHPVersion'); # we set phpversion using function called by cgi file } } if ( $trt eq 'LIST' ) { my @ibays = $adb->ibays(); $c->stash( ibays => \@ibays ); } $c->stash( title => $title, modul => $modul, wh_datas => \%wh_datas ); $c->render( template => 'webhosting' ); }; sub do_action { my $c = shift; $c->app->log->info($c->log_req); my $rt = $c->current_route; my $trt = ($c->param('trt') || ''); my %wh_datas = (); my $title = $c->l('wh_FORM_TITLE'); $wh_datas{'trt'} = $trt; my $result = ''; my $res; if ( $trt eq 'UPD' ) { my $name = ($c->param('ibay') || ''); # controls $res = validate_up_post( $c ); $result .= $res unless $res eq 'OK'; if ( ! $result ) { $res = modify_ibay( $c, $name ); $result .= $res unless $res eq 'OK'; if ( ! $result ) { $result = $c->l('wh_SUCCESSFULLY_MODIFIED_IBAY') . ' ' . $name; $wh_datas{trt} = 'LST'; } } } # common parts if ($res ne 'OK') { $c->stash( error => $result ); $c->stash( title => $title, wh_datas => \%wh_datas ); return $c->render('webhosting'); } my $message = "'Ibays' updates ($trt) DONE"; $c->app->log->info($message); $c->flash( success => $result ); $c->redirect_to('/webhosting'); }; sub modify_ibay { my ($c, $name) = @_; my $msg; my $acct = $adb->get($name); if ( ! $acct or $acct->prop('type') ne 'ibay') { return $c->l('wh_CANT_FIND_IBAY') if $msg ne 'OK'; } # real & current ibay my %doing=( Indexes => 'indexes', FollowSymLinks => 'followSymLinks', AllowOverride => 'allowOverride', ModDav => 'modDav', PHPVersion => 'phpVersion', AllowUrlFopen => 'allowUrlFopen', MemoryLimit => 'memorylimit', FileUpload => 'fileupload', UploadMaxFilesize => 'uploadmaxfilesize', PostMaxSize => 'postmaxsize', MaxExecutionTime => 'maxexecutiontime', MaxInputTime => 'maxinputtime', AllowPHTML => 'allowphtml', MailForceSender => 'mailforcesender', DisabledFunctions => 'disabledfunctions', PHPBaseDir => 'phpbasedir', ); foreach my $prop (keys %doing) { my $value = $c->param($doing{$prop}); $value = "" if ( $value eq "$BASEPHP" && $prop eq 'PHPVersion'); my $default = $defaultproperties{$prop} || ""; # exceptions to handle # DisabledFunctions if equal def delprop if ($prop eq 'DisabledFunctions' && $value eq $default) { $acct->delete_prop($prop) ; next; } # MailForceSender if empty delprop if ($prop eq 'MailForceSender' && $value eq "" ) { $acct->delete_prop($prop) ; next } # PHPBaseDir if empty delprop if ($prop eq 'PHPBaseDir' && $value eq "" ) { $acct->delete_prop($prop) ; next } # others if == default delprop if ($value eq "default") { $acct->delete_prop($prop) ; next; } $acct->merge_props($prop => $value); #TODO store them in a hash and call merge_props once } # Untaint $name before use in system() $name =~ /(.+)/; $name = $1; if (system ("/sbin/e-smith/signal-event", "webhosting-modify", $name) == 0) { $msg = 'OK'; } else { $msg = $c->l('wh_ERROR_WHILE_MODIFYING_IBAY'); } return $msg; } sub get_current_value{ my ($c, $name, $property) = @_; my $ibay = $adb->get($name); my $key = $ibay->key; my $default = $defaultproperties{$property} || ""; $default =~ s/\$key/$key/g if $property eq "PHPBaseDir"; my $value = ($ibay->prop($property))? $ibay->prop($property) : "default" ; return $value; } =head2 validate_up_post verify that the upload_max_filesize value is not greater than the post_max_size value. If yes then display an error message. =cut sub validate_up_post{ my $c = shift; my $upmaxfilesize = $c->param('uploadmaxfilesize'); my $postmaxsizeform = $c->param('postmaxsize'); ##set value to "0M" if disabled in order to compare uploadmaxfilesize and postmaxsize $upmaxfilesize = "0M" if $upmaxfilesize eq 'disabled'; $upmaxfilesize = $defaultproperties{'UploadMaxFilesize'} if $upmaxfilesize eq 'default'; $postmaxsizeform = "0M" if $postmaxsizeform eq 'disabled'; $postmaxsizeform =$defaultproperties{'PostMaxSize'} if $postmaxsizeform eq 'default'; ##remove the 'M' unit my $upmaxfilesizechop = chop($upmaxfilesize); my $postmaxsizeformchop = chop($postmaxsizeform); ##test the condition if ( $upmaxfilesize > $postmaxsizeform ) { return $c->l('wh_UPLOADMAXFILESIZE_IS_GREATER_THAN_POSTMAXSIZE'); } else { return "OK"; } } sub get_current_php_value { my ($c, $name) = @_; my $ibay= $adb->get($name); return "default" unless defined $ibay->prop('PHPVersion'); return VersionToUse($adb->get($name)); } sub get_php_options { my ($c) = @_; my $translate = $c->l('wh_DEFAULT'); my %opts= listPHPVersionHash(); # transform options list my @opts = [ "$translate: ".PHPdefault(), 'default' ]; foreach my $key ( sort keys %opts ) { push @opts, [ $opts{$key}, $key ]; } # push @opts, [ "$translate: ".PHPdefault(), 'default' ]; return \@opts; } sub print_options { my ($c, $property) = @_; my $translate = $c->l('wh_DEFAULT'); my $name = $c->param('ibay'); my $ibay = $adb->get($name); my $key = $ibay->key; my $default = $defaultproperties{$property} || ""; $default =~ s/\$key/$key/g if $property eq "PHPBaseDir"; $default=$c->l(uc("$default")) unless ($property eq 'AllowOverride'); # transform options list my @opts; foreach my $key ( sort keys %{$optionsproperties{$property}} ) { push @opts, [ $c->l($optionsproperties{$property}{$key}), $key ]; } push @opts, ["$translate: ".$default => 'default']; return \@opts } sub print_disabledfunctions { my ($c) = @_; my $translate = $c->l('wh_DESC_DISABLEDFUNCTIONS'); my $name = $c->param('ibay'); my $ibay= $adb->get($name); # ?? return "$translate : ". $defaultdisabledfunc ; } sub print_phpbasedir { my ($c) = @_; my $translate = $c->l('wh_DESC_PHPBASEDIR'); my $name = $c->param('ibay'); my $ibay= $adb->get($name); my $key = $ibay->key; my $default = $defaultproperties{'PHPBaseDir'} ||''; $default =~ s/\$key/$key/g; my $basedir = ($ibay->prop('PHPBaseDir')) ? $ibay->prop('PHPBaseDir') : $defaultproperties{'PHPBaseDir'}; return "$translate : ". $default ; } 1