From 0b0dc90a467c21513010d62af74a03c952652769 Mon Sep 17 00:00:00 2001 From: mcramer Date: Tue, 23 Jun 2009 14:46:18 +0000 Subject: [PATCH] Added: Cron Jobs for clients (url, chrooted, full) Fixed: Missing server.ini config entries for vlogger and jailkit Added: Admin interface server_config for vlogger and cron --- install/dist/conf/centos52.conf.php | 6 + install/dist/conf/centos53.conf.php | 6 + install/dist/conf/debian40.conf.php | 6 + install/dist/conf/fedora9.conf.php | 6 + install/dist/conf/gentoo.conf.php | 6 + install/dist/conf/opensuse110.conf.php | 5 + install/lib/installer_base.lib.php | 3 +- install/sql/ispconfig3.sql | 33 +++ install/tpl/server.ini.master | 9 + interface/lib/classes/validate_cron.inc.php | 191 ++++++++++++ .../web/admin/form/server_config.tform.php | 82 +++++- .../web/admin/lib/lang/de_server_config.lng | 5 + .../web/admin/lib/lang/en_server_config.lng | 5 + .../templates/server_config_cron_edit.htm | 30 ++ .../templates/server_config_jailkit_edit.htm | 4 + .../templates/server_config_vlogger_edit.htm | 22 ++ interface/web/client/form/client.tform.php | 34 +++ .../web/client/form/client_template.tform.php | 34 +++ interface/web/client/lib/lang/de_client.lng | 5 + .../client/lib/lang/de_client_template.lng | 5 + interface/web/client/lib/lang/en_client.lng | 5 + .../client/lib/lang/en_client_template.lng | 5 + .../client/templates/client_edit_limits.htm | 14 + .../templates/client_template_edit_limits.htm | 14 + interface/web/sites/cron_del.php | 64 +++++ interface/web/sites/cron_edit.php | 226 +++++++++++++++ interface/web/sites/cron_list.php | 23 ++ interface/web/sites/form/cron.tform.php | 189 ++++++++++++ interface/web/sites/lib/lang/de_cron.lng | 21 ++ interface/web/sites/lib/lang/de_cron_list.lng | 12 + interface/web/sites/lib/lang/en_cron.lng | 21 ++ interface/web/sites/lib/lang/en_cron_list.lng | 12 + interface/web/sites/lib/module.conf.php | 15 + interface/web/sites/list/cron.list.php | 152 ++++++++++ interface/web/sites/templates/cron_edit.htm | 68 +++++ interface/web/sites/templates/cron_list.htm | 71 +++++ interface/web/sites/web_domain_del.php | 6 + server/mods-available/cron_module.inc.php | 97 +++++++ .../cron_jailkit_plugin.inc.php | 272 ++++++++++++++++++ server/plugins-available/cron_plugin.inc.php | 212 ++++++++++++++ 40 files changed, 1994 insertions(+), 2 deletions(-) create mode 100644 interface/lib/classes/validate_cron.inc.php create mode 100644 interface/web/admin/templates/server_config_cron_edit.htm create mode 100644 interface/web/admin/templates/server_config_vlogger_edit.htm create mode 100644 interface/web/sites/cron_del.php create mode 100644 interface/web/sites/cron_edit.php create mode 100644 interface/web/sites/cron_list.php create mode 100644 interface/web/sites/form/cron.tform.php create mode 100644 interface/web/sites/lib/lang/de_cron.lng create mode 100644 interface/web/sites/lib/lang/de_cron_list.lng create mode 100644 interface/web/sites/lib/lang/en_cron.lng create mode 100644 interface/web/sites/lib/lang/en_cron_list.lng create mode 100644 interface/web/sites/list/cron.list.php create mode 100644 interface/web/sites/templates/cron_edit.htm create mode 100644 interface/web/sites/templates/cron_list.htm create mode 100644 server/mods-available/cron_module.inc.php create mode 100644 server/plugins-available/cron_jailkit_plugin.inc.php create mode 100644 server/plugins-available/cron_plugin.inc.php diff --git a/install/dist/conf/centos52.conf.php b/install/dist/conf/centos52.conf.php index 0f7cac079..e1ee4be44 100644 --- a/install/dist/conf/centos52.conf.php +++ b/install/dist/conf/centos52.conf.php @@ -147,8 +147,14 @@ $conf['jailkit']['config_dir'] = '/etc/jailkit'; $conf['jailkit']['jk_init'] = 'jk_init.ini'; $conf['jailkit']['jk_chrootsh'] = 'jk_chrootsh.ini'; $conf['jailkit']['jailkit_chroot_app_programs'] = '/usr/bin/groups /usr/bin/id /usr/bin/dircolors /bin/basename /usr/bin/dirname /usr/bin/nano'; +$conf['jailkit']['jailkit_chroot_cron_programs'] = '/usr/bin/php /usr/bin/perl /usr/share/perl /usr/share/php'; //* vlogger $conf['vlogger']['config_dir'] = '/etc'; +//* cron +$conf['cron']['init_script'] = 'crond'; +$conf['cron']['crontab_dir'] = '/etc/cron.d'; +$conf['cron']['wget'] = '/usr/bin/wget'; + ?> \ No newline at end of file diff --git a/install/dist/conf/centos53.conf.php b/install/dist/conf/centos53.conf.php index 51a5ba448..260eedb61 100644 --- a/install/dist/conf/centos53.conf.php +++ b/install/dist/conf/centos53.conf.php @@ -147,8 +147,14 @@ $conf['jailkit']['config_dir'] = '/etc/jailkit'; $conf['jailkit']['jk_init'] = 'jk_init.ini'; $conf['jailkit']['jk_chrootsh'] = 'jk_chrootsh.ini'; $conf['jailkit']['jailkit_chroot_app_programs'] = '/usr/bin/groups /usr/bin/id /usr/bin/dircolors /bin/basename /usr/bin/dirname /usr/bin/nano'; +$conf['jailkit']['jailkit_chroot_cron_programs'] = '/usr/bin/php /usr/bin/perl /usr/share/perl /usr/share/php'; //* vlogger $conf['vlogger']['config_dir'] = '/etc'; +//* cron +$conf['cron']['init_script'] = 'crond'; +$conf['cron']['crontab_dir'] = '/etc/cron.d'; +$conf['cron']['wget'] = '/usr/bin/wget'; + ?> \ No newline at end of file diff --git a/install/dist/conf/debian40.conf.php b/install/dist/conf/debian40.conf.php index 92fd4289b..6d107113c 100644 --- a/install/dist/conf/debian40.conf.php +++ b/install/dist/conf/debian40.conf.php @@ -147,8 +147,14 @@ $conf['jailkit']['config_dir'] = '/etc/jailkit'; $conf['jailkit']['jk_init'] = 'jk_init.ini'; $conf['jailkit']['jk_chrootsh'] = 'jk_chrootsh.ini'; $conf['jailkit']['jailkit_chroot_app_programs'] = '/usr/bin/groups /usr/bin/id /usr/bin/dircolors /usr/bin/lesspipe /usr/bin/basename /usr/bin/dirname /usr/bin/nano /usr/bin/pico'; +$conf['jailkit']['jailkit_chroot_cron_programs'] = '/usr/bin/php /usr/bin/perl /usr/share/perl /usr/share/php'; //* vlogger $conf['vlogger']['config_dir'] = '/etc'; +//* cron +$conf['cron']['init_script'] = 'cron'; +$conf['cron']['crontab_dir'] = '/etc/cron.d'; +$conf['cron']['wget'] = '/usr/bin/wget'; + ?> \ No newline at end of file diff --git a/install/dist/conf/fedora9.conf.php b/install/dist/conf/fedora9.conf.php index fd4169035..c49f133b3 100644 --- a/install/dist/conf/fedora9.conf.php +++ b/install/dist/conf/fedora9.conf.php @@ -147,8 +147,14 @@ $conf['jailkit']['config_dir'] = '/etc/jailkit'; $conf['jailkit']['jk_init'] = 'jk_init.ini'; $conf['jailkit']['jk_chrootsh'] = 'jk_chrootsh.ini'; $conf['jailkit']['jailkit_chroot_app_programs'] = '/usr/bin/groups /usr/bin/id /usr/bin/dircolors /bin/basename /usr/bin/dirname /usr/bin/nano'; +$conf['jailkit']['jailkit_chroot_cron_programs'] = '/usr/bin/php /usr/bin/perl /usr/share/perl /usr/share/php'; //* vlogger $conf['vlogger']['config_dir'] = '/etc'; +//* cron +$conf['cron']['init_script'] = 'crond'; +$conf['cron']['crontab_dir'] = '/etc/cron.d'; +$conf['cron']['wget'] = '/usr/bin/wget'; + ?> \ No newline at end of file diff --git a/install/dist/conf/gentoo.conf.php b/install/dist/conf/gentoo.conf.php index 4d9a7308b..9003aebdf 100644 --- a/install/dist/conf/gentoo.conf.php +++ b/install/dist/conf/gentoo.conf.php @@ -96,8 +96,14 @@ $conf['jailkit']['config_dir'] = '/etc/jailkit'; $conf['jailkit']['jk_init'] = 'jk_init.ini'; $conf['jailkit']['jk_chrootsh'] = 'jk_chrootsh.ini'; $conf['jailkit']['jailkit_chroot_app_programs'] = '/usr/bin/groups /usr/bin/id /usr/bin/dircolors /usr/bin/lesspipe /usr/bin/basename /usr/bin/dirname /usr/bin/nano /usr/bin/pico'; +$conf['jailkit']['jailkit_chroot_cron_programs'] = '/usr/bin/php /usr/bin/perl /usr/share/perl /usr/share/php'; //* vlogger $conf['vlogger']['config_dir'] = '/etc'; +//* cron +$conf['cron']['init_script'] = 'cron'; +$conf['cron']['crontab_dir'] = '/etc/cron.d'; +$conf['cron']['wget'] = '/usr/bin/wget'; + ?> \ No newline at end of file diff --git a/install/dist/conf/opensuse110.conf.php b/install/dist/conf/opensuse110.conf.php index e46d77ece..58b9d3801 100644 --- a/install/dist/conf/opensuse110.conf.php +++ b/install/dist/conf/opensuse110.conf.php @@ -147,9 +147,14 @@ $conf['jailkit']['config_dir'] = '/etc/jailkit'; $conf['jailkit']['jk_init'] = 'jk_init.ini'; $conf['jailkit']['jk_chrootsh'] = 'jk_chrootsh.ini'; $conf['jailkit']['jailkit_chroot_app_programs'] = '/usr/bin/groups /usr/bin/id /usr/bin/dircolors /usr/bin/basename /usr/bin/dirname /usr/bin/nano /usr/bin/pico'; +$conf['jailkit']['jailkit_chroot_cron_programs'] = '/usr/bin/php /usr/bin/perl /usr/share/perl /usr/share/php'; //* vlogger $conf['vlogger']['config_dir'] = '/etc'; +//* cron +$conf['cron']['init_script'] = 'cron'; +$conf['cron']['crontab_dir'] = '/etc/cron.d'; +$conf['cron']['wget'] = '/usr/bin/wget'; ?> \ No newline at end of file diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php index 8d92e2b4c..82b5b170e 100644 --- a/install/lib/installer_base.lib.php +++ b/install/lib/installer_base.lib.php @@ -210,7 +210,8 @@ class installer_base { $tpl_ini_array['web']['website_basedir'] = $conf['web']['website_basedir']; $tpl_ini_array['web']['website_path'] = $conf['web']['website_path']; $tpl_ini_array['web']['website_symlinks'] = $conf['web']['website_symlinks']; - + $tpl_ini_array['cron']['crontab_dir'] = $conf['cron']['crontab_dir']; + $server_ini_content = array_to_ini($tpl_ini_array); $server_ini_content = mysql_real_escape_string($server_ini_content); diff --git a/install/sql/ispconfig3.sql b/install/sql/ispconfig3.sql index 376ff6688..1e1e8e4b3 100644 --- a/install/sql/ispconfig3.sql +++ b/install/sql/ispconfig3.sql @@ -92,6 +92,9 @@ CREATE TABLE `client` ( `limit_dns_record` int(11) NOT NULL default '-1', `default_dbserver` int(11) NOT NULL default '1', `limit_database` int(11) NOT NULL default '-1', + `limit_cron` int(11) NOT NULL default '0', + `limit_cron_type` enum('url','chrooted','full') NOT NULL default 'url', + `limit_cron_frequency` int(11) NOT NULL default '5', `limit_client` int(11) NOT NULL default '0', `parent_client_id` int(11) unsigned NOT NULL default '0', `username` varchar(64) default NULL, @@ -140,10 +143,40 @@ CREATE TABLE `client_template` ( `limit_dns_zone` int(11) NOT NULL default '-1', `limit_dns_record` int(11) NOT NULL default '-1', `limit_database` int(11) NOT NULL default '-1', + `limit_cron` int(11) NOT NULL default '0', + `limit_cron_type` enum('url','chrooted','full') NOT NULL default 'url', + `limit_cron_frequency` int(11) NOT NULL default '5', `limit_client` int(11) NOT NULL default '0', PRIMARY KEY (`template_id`) ) ENGINE=MyISAM AUTO_INCREMENT=1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `dns_rr` +-- +CREATE TABLE `cron` ( + `id` int(11) unsigned NOT NULL auto_increment, + `sys_userid` int(11) unsigned NOT NULL default '0', + `sys_groupid` int(11) unsigned NOT NULL default '0', + `sys_perm_user` varchar(5) NULL default NULL, + `sys_perm_group` varchar(5) NULL default NULL, + `sys_perm_other` varchar(5) NULL default NULL, + `server_id` int(11) unsigned NOT NULL default '0', + `parent_domain_id` int(11) unsigned NOT NULL default '0', + `type` enum('url','chrooted','full') NOT NULL default 'url', + `command` varchar(255) NOT NULL, + `run_min` varchar(100) NULL, + `run_hour` varchar(100) NULL, + `run_mday` varchar(100) NULL, + `run_month` varchar(100) NULL, + `run_wday` varchar(100) NULL, + `active` enum('n','y') NOT NULL default 'y', + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=1; + + -- -------------------------------------------------------- -- diff --git a/install/tpl/server.ini.master b/install/tpl/server.ini.master index 463397e6b..d33afc7d3 100644 --- a/install/tpl/server.ini.master +++ b/install/tpl/server.ini.master @@ -48,3 +48,12 @@ fastcgi_bin=/usr/bin/php-cgi jailkit_chroot_home=/home/[username] jailkit_chroot_app_sections=basicshell editors extendedshell netutils ssh sftp scp groups jk_lsh jailkit_chroot_app_programs=/usr/bin/groups /usr/bin/id /usr/bin/dircolors /usr/bin/lesspipe /usr/bin/basename /usr/bin/dirname /usr/bin/nano /usr/bin/pico +jailkit_chroot_cron_programs=/usr/bin/php /usr/bin/perl /usr/share/perl /usr/share/php + +[vlogger] +config_dir=/etc + +[cron] +init_script=cron +crontab_dir=/etc/cron.d +wget=/usr/bin/wget diff --git a/interface/lib/classes/validate_cron.inc.php b/interface/lib/classes/validate_cron.inc.php new file mode 100644 index 000000000..42d9eb67f --- /dev/null +++ b/interface/lib/classes/validate_cron.inc.php @@ -0,0 +1,191 @@ +tform->wordbook[$errmsg])) { + return $app->tform->wordbook[$errmsg]."
\r\n"; + } else { + return $errmsg."
\r\n"; + } + } + + /* + Validator function to check if a given cron command is in correct form (url only). + */ + function command_format($field_name, $field_value, $validator) { + if(preg_match("'^(\w+):\/\/'", $field_value, $matches)) { + + $parsed = parse_url($field_value); + if($parsed === false) return $this->get_error($validator['errmsg']); + + if($parsed["scheme"] != "http" && $parsed["scheme"] != "https") return $this->get_error($validator['errmsg']); + + if(preg_match("'^([a-z0-9][a-z0-9-]{0,62}\.)+([a-z]{2,4})$'i", $parsed["host"]) == false) return $this->get_error($validator['errmsg']); + } + } + + /* + Validator function to check if a given cron time is in correct form. + */ + function run_time_format($field_name, $field_value, $validator) { + global $app; + + //* check general form + $is_ok = true; + $field_value = str_replace(" ", "", $field_value); // spaces are not needed + $used_times = array(); + + if(preg_match("'^[0-9\-\,\/\*]+$'", $field_value) == false) return $this->get_error($validator['errmsg']); // allowed characters are 0-9, comma, *, -, / + elseif(preg_match("'[\-\,\/][\-\,\/]'", $field_value) == true) return $this->get_error($validator['errmsg']); // comma, - and / never stand together + //* now split list and check each entry. store used values in array for later limit-check + $time_list = split(",", $field_value); + if(count($time_list) < 1) return $this->get_error($validator['errmsg']); + + $max_entry = 0; + $min_entry = 0; + $in_minutes = 1; + //* get maximum value of entry for each field type (name) + switch($field_name) { + case "run_min": + $max_entry = 59; + break; + case "run_hour": + $max_entry = 23; + $in_minutes = 60; + break; + case "run_mday": + $max_entry = 31; + $min_entry = 1; + $in_minutes = 1440; + break; + case "run_month": + $max_entry = 12; + $min_entry = 1; + $in_minutes = 1440 * 28; // not exactly but enough + break; + case "run_wday": + $max_entry = 7; + $in_minutes = 1440; + break; + } + + if($max_entry == 0) return $this->get_error('unknown_fieldtype_error'); + + foreach($time_list as $entry) { + //* possible value combinations: + //* x => ^(\d+)$ + //* x-y => ^(\d+)\-(\d+)$ + //* x/y => ^(\d+)\/([1-9]\d*)$ + //* x-y/z => ^(\d+)\-(\d+)\/([1-9]\d*)$ + //* */x => ^\*\/([1-9]\d*)$ + //* combined regex => ^(\d+|\*)(\-(\d+))?(\/([1-9]\d*))?$ + + if(preg_match("'^(((\d+)(\-(\d+))?)|\*)(\/([1-9]\d*))?$'", $entry, $matches) == false) { + return $this->get_error($validator['errmsg']); + } + + //* matches contains: + //* 1 => * or value or x-y range + //* 2 => unused + //* 3 => value if [1] != * + //* 4 => empty if no range was used + //* 5 => 2nd value of range if [1] != * and range was used + //* 6 => empty if step was not used + //* 7 => step + + $loop_step = 1; + $loop_from = $min_entry; + $loop_to = $max_entry; + + //* calculate used values + if($matches[1] == "*") { + //* not to check + } else { + if($matches[3] < $min_entry || $matches[3] > $max_entry) { + //* check if value is in allowed range + return $this->get_error($validator['errmsg']); + } elseif($matches[4] && ($matches[5] < $min_entry || $matches[5] > $max_entry || $matches[5] <= $matches[3])) { + //* check if value is in allowed range and not less or equal to first value + return $this->get_error($validator['errmsg']); + } + + $loop_from = $matches[3]; + $loop_to = $matches[3]; + if($matches[4]) $loop_to = $matches[5]; + } + if($matches[6] && ($matches[7] < 2 || $matches[7] > $max_entry - 1)) { + //* check if step value is valid + return $this->get_error($validator['errmsg']); + } + if($matches[7]) $loop_step = $matches[7]; + + //* loop through values to set used times + for($t = $loop_from; $t <= $loop_to; $t = $t + $loop_step) { + $used_times[] = $t; + } + } //* end foreach entry loop + + //* sort used times and erase doubles + sort($used_times); + $used_times = array_unique($used_times); + + //* get minimum frequency and store it in $app->tform->cron_min_freq for usage in onUpdateSave and onInsertSave! + $min_freq = -1; + $prev_time = -1; + foreach($used_times as $curtime) { + if($prev_time != -1) { + $freq = $curtime - $prev_time; + if($min_freq == -1 || $freq < $min_freq) $min_freq = $freq; + } + $prev_time = $curtime; + } + + //* check last against first (needed because e.g. wday 1,4,7 has diff 1 not 3 + $prev_time = $used_times[0]; + $freq = ($prev_time - $min_entry) + ($max_entry - $curtime) + 1; + if($min_freq == -1 || $freq < $min_freq) $min_freq = $freq; + + if($min_freq > 0 && $min_freq <= $max_entry) { //* only store if > 1 && < $max_entry! + $min_freq = $min_freq * $in_minutes; // we have to overwrite $app->tform->cron_min_freq if this is higher value + if(!$app->tform->cron_min_freq || $app->tform->cron_min_freq > $min_freq) $app->tform->cron_min_freq = $min_freq; + } + + //return "DEBUG: " . $app->tform->cron_min_freq . " ($min_freq) --- " . var_export($used_times, true) . "
"; + } + + + + +} \ No newline at end of file diff --git a/interface/web/admin/form/server_config.tform.php b/interface/web/admin/form/server_config.tform.php index 754000b8d..3e081b40d 100644 --- a/interface/web/admin/form/server_config.tform.php +++ b/interface/web/admin/form/server_config.tform.php @@ -478,6 +478,17 @@ $form["tabs"]['jailkit'] = array ( 'width' => '40', 'maxlength' => '1000' ), + 'jailkit_chroot_cron_programs' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'default' => '', + 'validators' => array ( 0 => array ( 'type' => 'NOTEMPTY', + 'errmsg'=> 'jailkit_chroot_cron_programs_error_empty'), + ), + 'value' => '', + 'width' => '40', + 'maxlength' => '1000' + ), ################################## # ENDE Datatable fields ################################## @@ -485,10 +496,79 @@ $form["tabs"]['jailkit'] = array ( ); +$form["tabs"]['vlogger'] = array ( + 'title' => "vlogger", + 'width' => 80, + 'template' => "templates/server_config_vlogger_edit.htm", + 'fields' => array ( + ################################## + # Begin Datatable fields + ################################## + 'config_dir' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'default' => '', + 'validators' => array ( 0 => array ( 'type' => 'NOTEMPTY', + 'errmsg'=> 'vlogger_config_dir_error_empty'), + ), + 'value' => '', + 'width' => '40', + 'maxlength' => '255' + ), + ################################## + # ENDE Datatable fields + ################################## + ) +); - +$form["tabs"]['cron'] = array ( + 'title' => "Cron", + 'width' => 80, + 'template' => "templates/server_config_cron_edit.htm", + 'fields' => array ( + ################################## + # Begin Datatable fields + ################################## + 'init_script' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'default' => '', + 'validators' => array ( 0 => array ( 'type' => 'NOTEMPTY', + 'errmsg'=> 'cron_init_script_error_empty'), + ), + 'value' => '', + 'width' => '40', + 'maxlength' => '255' + ), + 'crontab_dir' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'default' => '', + 'validators' => array ( 0 => array ( 'type' => 'NOTEMPTY', + 'errmsg'=> 'crontab_dir_error_empty'), + ), + 'value' => '', + 'width' => '40', + 'maxlength' => '255' + ), + 'wget' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'default' => '', + 'validators' => array ( 0 => array ( 'type' => 'NOTEMPTY', + 'errmsg'=> 'cron_wget_error_empty'), + ), + 'value' => '', + 'width' => '40', + 'maxlength' => '255' + ), + ################################## + # ENDE Datatable fields + ################################## + ) +); diff --git a/interface/web/admin/lib/lang/de_server_config.lng b/interface/web/admin/lib/lang/de_server_config.lng index 97f3e7ff0..8c24857e4 100644 --- a/interface/web/admin/lib/lang/de_server_config.lng +++ b/interface/web/admin/lib/lang/de_server_config.lng @@ -2,6 +2,7 @@ $wb['jailkit_chroot_home_txt'] = 'Jailkit chroot home'; $wb['jailkit_chroot_app_sections_txt'] = 'Jailkit chroot app sections'; $wb['jailkit_chroot_app_programs_txt'] = 'Jailkit chrooted applications'; +$wb['jailkit_chroot_cron_programs_txt'] = 'Jailkit cron chrooted applications'; $wb['website_path_txt'] = 'Website path'; $wb['website_symlinks_txt'] = 'Website symlinks'; $wb['vhost_conf_dir_txt'] = 'Vhost config dir'; @@ -38,4 +39,8 @@ $wb['netmask_error_wrong'] = 'Invalid Netmask format.'; $wb['gateway_error_wrong'] = 'Invalid Gateway format.'; $wb['hostname_error_empty'] = 'Hostname is empty.'; $wb['nameservers_error_empty'] = 'Nameserver is empty.'; +$wb["config_dir_txt"] = 'Config directory'; +$wb["init_script_txt"] = 'Cron init script name'; +$wb["crontab_dir_txt"] = 'Path for individual crontabs'; +$wb["wget_txt"] = 'Path to wget program'; ?> diff --git a/interface/web/admin/lib/lang/en_server_config.lng b/interface/web/admin/lib/lang/en_server_config.lng index 447ae3aff..ef736cc42 100644 --- a/interface/web/admin/lib/lang/en_server_config.lng +++ b/interface/web/admin/lib/lang/en_server_config.lng @@ -2,6 +2,7 @@ $wb["jailkit_chroot_home_txt"] = 'Jailkit chroot home'; $wb["jailkit_chroot_app_sections_txt"] = 'Jailkit chroot app sections'; $wb["jailkit_chroot_app_programs_txt"] = 'Jailkit chrooted applications'; +$wb['jailkit_chroot_cron_programs_txt'] = 'Jailkit cron chrooted applications'; $wb["website_path_txt"] = 'Website path'; $wb["website_symlinks_txt"] = 'Website symlinks'; $wb["website_basedir_txt"] = 'Website basedir'; @@ -38,4 +39,8 @@ $wb["netmask_error_wrong"] = 'Invalid Netmask format.'; $wb["gateway_error_wrong"] = 'Invalid Gateway format.'; $wb["hostname_error_empty"] = 'Hostname is empty.'; $wb["nameservers_error_empty"] = 'Nameserver is empty.'; +$wb["config_dir_txt"] = 'Config directory'; +$wb["init_script_txt"] = 'Cron init script name'; +$wb["crontab_dir_txt"] = 'Path for individual crontabs'; +$wb["wget_txt"] = 'Path to wget program'; ?> \ No newline at end of file diff --git a/interface/web/admin/templates/server_config_cron_edit.htm b/interface/web/admin/templates/server_config_cron_edit.htm new file mode 100644 index 000000000..066693ed8 --- /dev/null +++ b/interface/web/admin/templates/server_config_cron_edit.htm @@ -0,0 +1,30 @@ +

+

+ +
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + + +
+ + +
+
+ +
diff --git a/interface/web/admin/templates/server_config_jailkit_edit.htm b/interface/web/admin/templates/server_config_jailkit_edit.htm index ec2081de6..320fb8754 100644 --- a/interface/web/admin/templates/server_config_jailkit_edit.htm +++ b/interface/web/admin/templates/server_config_jailkit_edit.htm @@ -17,6 +17,10 @@ +
+ + +
diff --git a/interface/web/admin/templates/server_config_vlogger_edit.htm b/interface/web/admin/templates/server_config_vlogger_edit.htm new file mode 100644 index 000000000..bf6a82ab3 --- /dev/null +++ b/interface/web/admin/templates/server_config_vlogger_edit.htm @@ -0,0 +1,22 @@ +

+

+ +
+ +
+
+
+ + +
+
+ + + +
+ + +
+
+ +
diff --git a/interface/web/client/form/client.tform.php b/interface/web/client/form/client.tform.php index 288e8939a..4cc9dd57e 100644 --- a/interface/web/client/form/client.tform.php +++ b/interface/web/client/form/client.tform.php @@ -663,6 +663,40 @@ $form["tabs"]['limits'] = array ( 'rows' => '', 'cols' => '' ), + 'limit_cron' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'ISINT', + 'errmsg'=> 'limit_cron_error_notint'), + ), + 'default' => '0', + 'value' => '', + 'separator' => '', + 'width' => '10', + 'maxlength' => '10', + 'rows' => '', + 'cols' => '' + ), + 'limit_cron_type' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'SELECT', + 'default' => '', + 'value' => array('full' => 'Full Cron','chrooted' => 'Chrooted Cron','url' => 'URL Cron') + ), + 'limit_cron_frequency' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'ISINT', + 'errmsg'=> 'limit_cron_error_frequency'), + ), + 'default' => '-1', + 'value' => '', + 'separator' => '', + 'width' => '10', + 'maxlength' => '10', + 'rows' => '', + 'cols' => '' + ), ################################## # END Datatable fields ################################## diff --git a/interface/web/client/form/client_template.tform.php b/interface/web/client/form/client_template.tform.php index f732faf57..e1dd51dcd 100644 --- a/interface/web/client/form/client_template.tform.php +++ b/interface/web/client/form/client_template.tform.php @@ -395,6 +395,40 @@ $form["tabs"]['limits'] = array ( 'rows' => '', 'cols' => '' ), + 'limit_cron' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'ISINT', + 'errmsg'=> 'limit_cron_error_notint'), + ), + 'default' => '0', + 'value' => '', + 'separator' => '', + 'width' => '10', + 'maxlength' => '10', + 'rows' => '', + 'cols' => '' + ), + 'limit_cron_type' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'SELECT', + 'default' => '', + 'value' => array('full' => 'Full Cron','chrooted' => 'Chrooted Cron','url' => 'URL Cron') + ), + 'limit_cron_frequency' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'ISINT', + 'errmsg'=> 'limit_cron_error_frequency'), + ), + 'default' => '-1', + 'value' => '', + 'separator' => '', + 'width' => '10', + 'maxlength' => '10', + 'rows' => '', + 'cols' => '' + ), ################################## # END Datatable fields ################################## diff --git a/interface/web/client/lib/lang/de_client.lng b/interface/web/client/lib/lang/de_client.lng index 05fad56a6..d126fa846 100644 --- a/interface/web/client/lib/lang/de_client.lng +++ b/interface/web/client/lib/lang/de_client.lng @@ -39,6 +39,9 @@ $wb['limit_domain_txt'] = 'Max. Anzahl an Domains'; $wb['limit_subdomain_txt'] = 'Max. Anzahl an Subdomains'; $wb['limit_webquota_txt'] = 'Max. Webquota'; $wb['limit_database_txt'] = 'Max. Anzahl an Datenbanken'; +$wb["limit_cron_txt"] = 'Max. Anzahl Cron Jobs'; +$wb["limit_cron_type_txt"] = 'Max. erlaubter Typ von Cron Jobs (chrooted und full erlauben auch url)'; +$wb["limit_cron_frequency_txt"] = 'Min. Abstand zwischen Ausführungen'; $wb['ip_address_txt'] = 'IP Adresse'; $wb['limit_client_error_notint'] = 'The sub client limit must be a number.'; $wb['firstname_error_empty'] = 'Vorname ist leer.'; @@ -74,6 +77,8 @@ $wb['limit_shell_user_error_notint'] = 'Das Shell Benutzer Limit muss eine Numme $wb['limit_dns_zone_error_notint'] = 'Das DNS Einträge Limit muss eine Nummer sein.'; $wb['default_dbserver_txt'] = 'Standarddatenbankserver'; $wb['limit_database_error_notint'] = 'Das Datenbank Limit muss eine Nummer sein.'; +$wb["limit_cron_error_notint"] = 'Das Cron Job Limit muss eine Zahl sein.'; +$wb["limit_cron_error_frequency"] = 'Das Cron Job Intervall-Limit muss eine Zahl sein.'; $wb['username_error_regex'] = 'Der Benutzername enthält ungültige Zeichen.'; $wb['password_strength_txt'] = 'Passwortkomplexität'; $wb['template_master_txt'] = 'Master'; diff --git a/interface/web/client/lib/lang/de_client_template.lng b/interface/web/client/lib/lang/de_client_template.lng index 8a29d471f..cdcce8d5a 100644 --- a/interface/web/client/lib/lang/de_client_template.lng +++ b/interface/web/client/lib/lang/de_client_template.lng @@ -17,6 +17,9 @@ $wb['limit_domain_txt'] = 'Max. Anzahl an Domains'; $wb['limit_subdomain_txt'] = 'Max. Anzahl an Subdomains'; $wb['limit_webquota_txt'] = 'Max. Webquota'; $wb['limit_database_txt'] = 'Max. Anzahl an Datenbanken'; +$wb["limit_cron_txt"] = 'Max. Anzahl Cron Jobs'; +$wb["limit_cron_type_txt"] = 'Max. erlaubter Typ von Cron Jobs (chrooted und full erlauben auch url)'; +$wb["limit_cron_frequency_txt"] = 'Min. Abstand zwischen Ausführungen'; $wb['limit_web_domain_txt'] = 'Max. Anzahl an Web Domains'; $wb['limit_web_aliasdomain_txt'] = 'Max. Anzahl an Web Aliasdomains'; $wb['limit_web_subdomain_txt'] = 'Max. Anzahl an Web Subdomains'; @@ -43,5 +46,7 @@ $wb['limit_ftp_user_error_notint'] = 'Das FTP Benutzer Limit muss eine Nummer s $wb['limit_shell_user_error_notint'] = 'Das Shell Benutzer Limit muss eine Nummer sein.'; $wb['limit_dns_zone_error_notint'] = 'Das DNS Einträge Limit muss eine Nummer sein.'; $wb['limit_database_error_notint'] = 'Das Datenbanken Limit muss eine Nummer sein.'; +$wb["limit_cron_error_notint"] = 'Das Cron Job Limit muss eine Zahl sein.'; +$wb["limit_cron_error_frequency"] = 'Das Cron Job Intervall-Limit muss eine Zahl sein.'; $wb['error_template_name_empty'] = 'Bitte geben sie einen Vorlagenamen ein'; ?> diff --git a/interface/web/client/lib/lang/en_client.lng b/interface/web/client/lib/lang/en_client.lng index 74c166fe8..03cec3fee 100644 --- a/interface/web/client/lib/lang/en_client.lng +++ b/interface/web/client/lib/lang/en_client.lng @@ -39,6 +39,9 @@ $wb["limit_domain_txt"] = 'limit_domain'; $wb["limit_subdomain_txt"] = 'limit_subdomain'; $wb["limit_webquota_txt"] = 'limit_webquota'; $wb["limit_database_txt"] = 'limit_database'; +$wb["limit_cron_txt"] = 'Max. number of cron jobs'; +$wb["limit_cron_type_txt"] = 'Max. type of cron jobs (chrooted and full implies url)'; +$wb["limit_cron_frequency_txt"] = 'Min. delay between executions'; $wb["ip_address_txt"] = 'ip_address'; $wb["limit_client_error_notint"] = 'Client Limit is not a number.'; $wb["firstname_error_empty"] = 'Firstname is empty.'; @@ -78,6 +81,8 @@ $wb["limit_client_error_notint"] = 'The sub client limit must be a number.'; $wb["default_dbserver_txt"] = 'Default Database Server'; $wb["limit_database_txt"] = 'Max. number of Databases'; $wb["limit_database_error_notint"] = 'The database limit must be a number.'; +$wb["limit_cron_error_notint"] = 'The cron limit must be a number.'; +$wb["limit_cron_error_frequency"] = 'The cron frequency limit must be a number.'; $wb["username_error_regex"] = 'The Username contains invalid chracaters.'; $wb["template_master_txt"] = 'Master template'; $wb["template_additional_txt"] = 'Addon template'; diff --git a/interface/web/client/lib/lang/en_client_template.lng b/interface/web/client/lib/lang/en_client_template.lng index c3453a8b5..6d9ee1115 100644 --- a/interface/web/client/lib/lang/en_client_template.lng +++ b/interface/web/client/lib/lang/en_client_template.lng @@ -17,6 +17,9 @@ $wb["limit_domain_txt"] = 'limit_domain'; $wb["limit_subdomain_txt"] = 'limit_subdomain'; $wb["limit_webquota_txt"] = 'limit_webquota'; $wb["limit_database_txt"] = 'limit_database'; +$wb["limit_cron_txt"] = 'Max. number of cron jobs'; +$wb["limit_cron_type_txt"] = 'Max. type of cron jobs (chrooted and full implies url)'; +$wb["limit_cron_frequency_txt"] = 'Min. delay between executions'; $wb["limit_web_domain_txt"] = 'Max. number of web domains'; $wb["limit_web_aliasdomain_txt"] = 'Max. number of web aliasdomains'; $wb["limit_web_subdomain_txt"] = 'Max. number of web subdomains'; @@ -46,5 +49,7 @@ $wb["limit_dns_zone_error_notint"] = 'The dns zone limit must be a number.'; $wb["limit_dns_zone_error_notint"] = 'The dns record limit must be a number.'; $wb["limit_database_txt"] = 'Max. number of Databases'; $wb["limit_database_error_notint"] = 'The database limit must be a number.'; +$wb["limit_cron_error_notint"] = 'The cron limit must be a number.'; +$wb["limit_cron_error_frequency"] = 'The cron frequency limit must be a number.'; $wb["error_template_name_empty"] = 'Please enter a Template name'; ?> \ No newline at end of file diff --git a/interface/web/client/templates/client_edit_limits.htm b/interface/web/client/templates/client_edit_limits.htm index e12abe94d..208514164 100644 --- a/interface/web/client/templates/client_edit_limits.htm +++ b/interface/web/client/templates/client_edit_limits.htm @@ -155,6 +155,20 @@ +
+ + +
+
+ + +
+
+ + +
diff --git a/interface/web/client/templates/client_template_edit_limits.htm b/interface/web/client/templates/client_template_edit_limits.htm index bd01dcec0..2a4374cbf 100644 --- a/interface/web/client/templates/client_template_edit_limits.htm +++ b/interface/web/client/templates/client_template_edit_limits.htm @@ -89,6 +89,20 @@ +
+ + +
+
+ + +
+
+ + +
diff --git a/interface/web/sites/cron_del.php b/interface/web/sites/cron_del.php new file mode 100644 index 000000000..516b4473b --- /dev/null +++ b/interface/web/sites/cron_del.php @@ -0,0 +1,64 @@ +auth->check_module_permissions('sites'); + +$app->uses('tpl,tform,tform_actions'); +$app->load('tform_actions'); + +class page_action extends tform_actions { + + function onBeforeDelete() { + global $app; $conf; + + if($app->tform->checkPerm($this->id,'d') == false) $app->error($app->lng('error_no_delete_permission')); + } +} + +$page = new page_action; +$page->onDelete(); + +?> \ No newline at end of file diff --git a/interface/web/sites/cron_edit.php b/interface/web/sites/cron_edit.php new file mode 100644 index 000000000..1f0a025b5 --- /dev/null +++ b/interface/web/sites/cron_edit.php @@ -0,0 +1,226 @@ +auth->check_module_permissions('sites'); + +// Loading classes +$app->uses('tpl,tform,tform_actions,validate_cron'); +$app->load('tform_actions'); + +class page_action extends tform_actions { + + function onShowNew() { + global $app, $conf; + + // we will check only users, not admins + if($_SESSION["s"]["user"]["typ"] == 'user') { + + // Get the limits of the client + $client_group_id = $_SESSION["s"]["user"]["default_group"]; + $client = $app->db->queryOneRecord("SELECT limit_cron FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id"); + + // Check if the user may add another cron job. + if($client["limit_cron"] >= 0) { + $tmp = $app->db->queryOneRecord("SELECT count(id) as number FROM cron WHERE sys_groupid = $client_group_id"); + if($tmp["number"] >= $client["limit_cron"]) { + $app->error($app->tform->wordbook["limit_cron_txt"]); + } + } + } + + parent::onShowNew(); + } + + function onShowEnd() { + global $app, $conf; + + if($this->id > 0) { + //* we are editing a existing record + $app->tpl->setVar("edit_disabled", 1); + $app->tpl->setVar("parent_domain_id_value", $this->dataRecord["parent_domain_id"]); + } else { + $app->tpl->setVar("edit_disabled", 0); + } + + parent::onShowEnd(); + } + + function onSubmit() { + global $app, $conf; + + if($_SESSION["s"]["user"]["typ"] != 'admin') { + // Get the limits of the client + $client_group_id = $_SESSION["s"]["user"]["default_group"]; + $client = $app->db->queryOneRecord("SELECT limit_cron, limit_cron_type FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id"); + + // When the record is updated + if($this->id > 0) { + // When the record is inserted + } else { + // Check if the user may add another cron job. + if($client["limit_cron"] >= 0) { + $tmp = $app->db->queryOneRecord("SELECT count(id) as number FROM cron WHERE sys_groupid = $client_group_id"); + if($tmp["number"] >= $client["limit_cron"]) { + $app->error($app->tform->wordbook["limit_cron_txt"]); + } + } + } + } + + // Get the record of the parent domain + $parent_domain = $app->db->queryOneRecord("select * FROM web_domain WHERE domain_id = ".intval(@$this->dataRecord["parent_domain_id"])); + + // Set fixed values + $this->dataRecord["server_id"] = $parent_domain["server_id"]; + + //* get type of command + $command = $this->dataRecord["command"]; + if(preg_match("'^http(s)?:\/\/'i", $command)) { + $this->dataRecord["type"] = 'url'; + } else { + $domain_owner = $app->db->queryOneRecord("SELECT limit_cron_type FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ".intval($parent_domain["sys_groupid"])); + if($domain_owner["limit_cron_type"] == 'full') $this->dataRecord["type"] = 'full'; + else $this->dataRecord["type"] = 'chrooted'; + } + + parent::onSubmit(); + } + + function onUpdateSave($sql) { + global $app; + + $has_error = false; + //* last chance to stop this, so check frequency limit! + if($_SESSION["s"]["user"]["typ"] != 'admin') { + // Get the limits of the client + $client_group_id = $_SESSION["s"]["user"]["default_group"]; + $client = $app->db->queryOneRecord("SELECT limit_cron_frequency FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id"); + + if($client["limit_cron_frequency"] > 1) { + if($app->tform->cron_min_freq < $client["limit_cron_frequency"]) { + $app->error($app->tform->wordbook["limit_cron_frequency_txt"]); + $has_error = true; + } + } + } + + if($has_error == true) { + parent::onError(); + exit; + } + else parent::onUpdateSave($sql); + } + + function onInsertSave($sql) { + global $app; + + $has_error = false; + //* last chance to stop this, so check frequency limit! + if($_SESSION["s"]["user"]["typ"] != 'admin') { + // Get the limits of the client + $client_group_id = $_SESSION["s"]["user"]["default_group"]; + $client = $app->db->queryOneRecord("SELECT limit_cron_frequency FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id"); + + if($client["limit_cron_frequency"] > 1) { + if($app->tform->cron_min_freq < $client["limit_cron_frequency"]) { + $app->error($app->tform->wordbook["limit_cron_frequency_txt"]); + $has_error = true; + } + } + } + + if($has_error == true) { + parent::onError(); + exit; + } + else parent::onInsertSave($sql); + } + + function onAfterInsert() { + global $app, $conf; + + $web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".intval($this->dataRecord["parent_domain_id"])); + $server_id = $web["server_id"]; + + // The cron shall be owned by the same group then the website + $sys_groupid = $web['sys_groupid']; + + $sql = "UPDATE shell_user SET server_id = $server_id, sys_groupid = '$sys_groupid' WHERE id = ".$this->id; + $app->db->query($sql); + } + + function onAfterUpdate() { + global $app, $conf; + + + } + + function getClientName() { + global $app, $conf; + + if($_SESSION["s"]["user"]["typ"] != 'admin') { + // Get the group-id of the user + $client_group_id = $_SESSION["s"]["user"]["default_group"]; + } else { + // Get the group-id from the data itself + $web = $app->db->queryOneRecord("SELECT sys_groupid FROM web_domain WHERE domain_id = ".intval($this->dataRecord['parent_domain_id'])); + $client_group_id = $web['sys_groupid']; + } + /* get the name of the client */ + $tmp = $app->db->queryOneRecord("SELECT name FROM sys_group WHERE groupid = " . $client_group_id); + $clientName = $tmp['name']; + if ($clientName == "") $clientName = 'default'; + $clientName = convertClientName($clientName); + + return $clientName; + + } + +} + +$page = new page_action; +$page->onLoad(); + +?> \ No newline at end of file diff --git a/interface/web/sites/cron_list.php b/interface/web/sites/cron_list.php new file mode 100644 index 000000000..68e23163f --- /dev/null +++ b/interface/web/sites/cron_list.php @@ -0,0 +1,23 @@ +auth->check_module_permissions('sites'); + +$app->uses('listform_actions'); + +$app->listform_actions->onLoad(); + + +?> \ No newline at end of file diff --git a/interface/web/sites/form/cron.tform.php b/interface/web/sites/form/cron.tform.php new file mode 100644 index 000000000..4f9f8dd5b --- /dev/null +++ b/interface/web/sites/form/cron.tform.php @@ -0,0 +1,189 @@ + 0 id must match with id of current user +$form["auth_preset"]["groupid"] = 0; // 0 = default groupid of the user, > 0 id must match with groupid of current user +$form["auth_preset"]["perm_user"] = 'riud'; //r = read, i = insert, u = update, d = delete +$form["auth_preset"]["perm_group"] = 'riud'; //r = read, i = insert, u = update, d = delete +$form["auth_preset"]["perm_other"] = ''; //r = read, i = insert, u = update, d = delete + +$form["tabs"]['cron'] = array ( + 'title' => "Cron Job", + 'width' => 100, + 'template' => "templates/cron_edit.htm", + 'fields' => array ( + ################################## + # Begin Datatable fields + ################################## + 'server_id' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'SELECT', + 'datasource' => array ( 'type' => 'SQL', + 'querystring' => 'SELECT server_id,server_name FROM server WHERE web_server = 1 AND {AUTHSQL} ORDER BY server_name', + 'keyfield'=> 'server_id', + 'valuefield'=> 'server_name' + ), + 'validators' => array ( 0 => array ( 'type' => 'NOTEMPTY', + 'errmsg'=> 'server_id_error_empty'), + ), + 'default' => '', + 'value' => '', + 'width' => '30', + 'maxlength' => '255' + ), + 'parent_domain_id' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'SELECT', + 'default' => '', + 'datasource' => array ( 'type' => 'SQL', + 'querystring' => "SELECT domain_id,domain FROM web_domain WHERE type = 'vhost' AND {AUTHSQL} ORDER BY domain", + 'keyfield'=> 'domain_id', + 'valuefield'=> 'domain' + ), + 'value' => '' + ), + 'run_min' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'CUSTOM', + 'class' => 'validate_cron', + 'function' => 'run_time_format', + 'errmsg'=> 'run_min_error_format'), + ), + 'default' => '', + 'value' => '', + 'width' => '30', + 'maxlength' => '255' + ), + 'run_hour' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'CUSTOM', + 'class' => 'validate_cron', + 'function' => 'run_time_format', + 'errmsg'=> 'run_hour_error_format'), + ), + 'default' => '', + 'value' => '', + 'width' => '30', + 'maxlength' => '255' + ), + 'run_mday' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'CUSTOM', + 'class' => 'validate_cron', + 'function' => 'run_time_format', + 'errmsg'=> 'run_mday_error_format'), + ), + 'default' => '', + 'value' => '', + 'width' => '30', + 'maxlength' => '255' + ), + 'run_month' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'CUSTOM', + 'class' => 'validate_cron', + 'function' => 'run_time_format', + 'errmsg'=> 'run_month_error_format'), + ), + 'default' => '', + 'value' => '', + 'width' => '30', + 'maxlength' => '255' + ), + 'run_wday' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'CUSTOM', + 'class' => 'validate_cron', + 'function' => 'run_time_format', + 'errmsg'=> 'run_wday_error_format'), + ), + 'default' => '', + 'value' => '', + 'width' => '30', + 'maxlength' => '255' + ), + 'command' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'NOTEMPTY', + 'errmsg'=> 'command_error_empty'), + 1 => array ( 'type' => 'CUSTOM', + 'class' => 'validate_cron', + 'function' => 'command_format', + 'errmsg'=> 'command_error_format'), + ), + 'default' => '', + 'value' => '', + 'width' => '30', + 'maxlength' => '255' + ), + 'type' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'SELECT', + 'default' => 'url', + 'valuelimit' => 'list:url,full,chrooted', + 'value' => array('url' => 'Url', 'full' => 'Full', 'chrooted' => 'Chrooted') + ), + 'active' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'CHECKBOX', + 'default' => 'y', + 'value' => array(0 => 'n',1 => 'y') + ), + ################################## + # ENDE Datatable fields + ################################## + ) +); + + + +?> \ No newline at end of file diff --git a/interface/web/sites/lib/lang/de_cron.lng b/interface/web/sites/lib/lang/de_cron.lng new file mode 100644 index 000000000..c65bf38be --- /dev/null +++ b/interface/web/sites/lib/lang/de_cron.lng @@ -0,0 +1,21 @@ + diff --git a/interface/web/sites/lib/lang/de_cron_list.lng b/interface/web/sites/lib/lang/de_cron_list.lng new file mode 100644 index 000000000..4f20d8d83 --- /dev/null +++ b/interface/web/sites/lib/lang/de_cron_list.lng @@ -0,0 +1,12 @@ + diff --git a/interface/web/sites/lib/lang/en_cron.lng b/interface/web/sites/lib/lang/en_cron.lng new file mode 100644 index 000000000..8cb7f08e6 --- /dev/null +++ b/interface/web/sites/lib/lang/en_cron.lng @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/interface/web/sites/lib/lang/en_cron_list.lng b/interface/web/sites/lib/lang/en_cron_list.lng new file mode 100644 index 000000000..b5c8d1566 --- /dev/null +++ b/interface/web/sites/lib/lang/en_cron_list.lng @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/interface/web/sites/lib/module.conf.php b/interface/web/sites/lib/module.conf.php index 6a437e827..3207cafdc 100644 --- a/interface/web/sites/lib/module.conf.php +++ b/interface/web/sites/lib/module.conf.php @@ -77,6 +77,21 @@ $module["nav"][] = array( 'title' => 'Database', 'items' => $items); +/* + Cron menu +*/ +$items = array(); + +$items[] = array( 'title' => "Cron Jobs", + 'target' => 'content', + 'link' => 'sites/cron_list.php'); + + +$module["nav"][] = array( 'title' => 'Cron', + 'open' => 1, + 'items' => $items); + + //**** Statistics menu $items = array(); diff --git a/interface/web/sites/list/cron.list.php b/interface/web/sites/list/cron.list.php new file mode 100644 index 000000000..dfa2d4b35 --- /dev/null +++ b/interface/web/sites/list/cron.list.php @@ -0,0 +1,152 @@ + "active", + 'datatype' => "VARCHAR", + 'formtype' => "SELECT", + 'op' => "=", + 'prefix' => "", + 'suffix' => "", + 'width' => "", + 'value' => array('y' => "
Yes
",'n' => "
No
")); + + +$liste["item"][] = array( 'field' => "server_id", + 'datatype' => "VARCHAR", + 'formtype' => "SELECT", + 'op' => "like", + 'prefix' => "%", + 'suffix' => "%", + 'datasource' => array ( 'type' => 'SQL', + 'querystring' => 'SELECT server_id,server_name FROM server WHERE {AUTHSQL} ORDER BY server_name', + 'keyfield'=> 'server_id', + 'valuefield'=> 'server_name' + ), + 'width' => "", + 'value' => ""); + +$liste["item"][] = array( 'field' => "parent_domain_id", + 'datatype' => "VARCHAR", + 'formtype' => "SELECT", + 'op' => "like", + 'prefix' => "%", + 'suffix' => "%", + 'datasource' => array ( 'type' => 'SQL', + 'querystring' => "SELECT domain_id,domain FROM web_domain WHERE type = 'vhost' AND {AUTHSQL} ORDER BY domain", + 'keyfield'=> 'domain_id', + 'valuefield'=> 'domain' + ), + 'width' => "", + 'value' => ""); + +$liste["item"][] = array( 'field' => "run_min", + 'datatype' => "VARCHAR", + 'formtype' => "TEXT", + 'op' => "=", + 'prefix' => "", + 'suffix' => "", + 'width' => "", + 'value' => ""); + +$liste["item"][] = array( 'field' => "run_hour", + 'datatype' => "VARCHAR", + 'formtype' => "TEXT", + 'op' => "=", + 'prefix' => "", + 'suffix' => "", + 'width' => "", + 'value' => ""); + +$liste["item"][] = array( 'field' => "run_mday", + 'datatype' => "VARCHAR", + 'formtype' => "TEXT", + 'op' => "=", + 'prefix' => "", + 'suffix' => "", + 'width' => "", + 'value' => ""); + +$liste["item"][] = array( 'field' => "run_month", + 'datatype' => "VARCHAR", + 'formtype' => "TEXT", + 'op' => "=", + 'prefix' => "", + 'suffix' => "", + 'width' => "", + 'value' => ""); + +$liste["item"][] = array( 'field' => "run_wday", + 'datatype' => "VARCHAR", + 'formtype' => "TEXT", + 'op' => "=", + 'prefix' => "", + 'suffix' => "", + 'width' => "", + 'value' => ""); + + +$liste["item"][] = array( 'field' => "command", + 'datatype' => "VARCHAR", + 'formtype' => "TEXT", + 'op' => "like", + 'prefix' => "%", + 'suffix' => "%", + 'width' => "", + 'value' => ""); + + + + + + + + + +?> \ No newline at end of file diff --git a/interface/web/sites/templates/cron_edit.htm b/interface/web/sites/templates/cron_edit.htm new file mode 100644 index 000000000..39f9bc646 --- /dev/null +++ b/interface/web/sites/templates/cron_edit.htm @@ -0,0 +1,68 @@ +

+

+ +
+ +
+
Cron Job +
+ + + + + + + + +
+
+ + +

e.g. *, */3, 10-20

+
+
+ + +

e.g. *, */2, 0, 10-12

+
+
+ + +

e.g. *, */4, 1-5

+
+
+ + +

e.g. *, 1-6

+
+
+ + +

e.g. *, 0, 1-5

+
+
+ + +

e.g. /var/www/clients/client1/myscript.sh or http://www.mydomain.com/path/script.php

+
+
+

{tmpl_var name='active_txt'}

+
+ {tmpl_var name='active'} +
+
+
+ + + +
+ + +
+
+ +
diff --git a/interface/web/sites/templates/cron_list.htm b/interface/web/sites/templates/cron_list.htm new file mode 100644 index 000000000..e2e8ca9d5 --- /dev/null +++ b/interface/web/sites/templates/cron_list.htm @@ -0,0 +1,71 @@ +

+

+ +
+ +
+
Tools +
+ +
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
{tmpl_var name="server_id"}{tmpl_var name="run_min"}{tmpl_var name="run_hour"}{tmpl_var name="run_mday"}{tmpl_var name="run_month"}{tmpl_var name="run_wday"}{tmpl_var name="command"} + +
+
+
+ +
diff --git a/interface/web/sites/web_domain_del.php b/interface/web/sites/web_domain_del.php index 867d1f40e..e5614cf27 100644 --- a/interface/web/sites/web_domain_del.php +++ b/interface/web/sites/web_domain_del.php @@ -72,6 +72,12 @@ class page_action extends tform_actions { foreach($records as $rec) { $app->db->datalogDelete('shell_user','shell_user_id',$rec['shell_user_id']); } + + // Delete all records that belog to this zone. + $records = $app->db->queryAllRecords("SELECT id FROM cron WHERE parent_domain_id = '".intval($this->id)."'"); + foreach($records as $rec) { + $app->db->datalogDelete('cron','id',$rec['id']); + } } } diff --git a/server/mods-available/cron_module.inc.php b/server/mods-available/cron_module.inc.php new file mode 100644 index 000000000..778585cb4 --- /dev/null +++ b/server/mods-available/cron_module.inc.php @@ -0,0 +1,97 @@ +plugins->announceEvents($this->module_name,$this->actions_available); + + /* + As we want to get notified of any changes on several database tables, + we register for them. + + The following function registers the function "functionname" + to be executed when a record for the table "dbtable" is + processed in the sys_datalog. "classname" is the name of the + class that contains the function functionname. + */ + + $app->modules->registerTableHook('cron',$this->module_name,'process'); + + } + + /* + This function is called when a change in one of the registered tables is detected. + The function then raises the events for the plugins. + */ + + function process($tablename,$action,$data) { + global $app; + + switch ($tablename) { + case 'cron': + if($action == 'i') $app->plugins->raiseEvent('cron_insert',$data); + if($action == 'u') $app->plugins->raiseEvent('cron_update',$data); + if($action == 'd') $app->plugins->raiseEvent('cron_delete',$data); + break; + } // end switch + } // end function + + +} // end class + +?> \ No newline at end of file diff --git a/server/plugins-available/cron_jailkit_plugin.inc.php b/server/plugins-available/cron_jailkit_plugin.inc.php new file mode 100644 index 000000000..fc19db6cf --- /dev/null +++ b/server/plugins-available/cron_jailkit_plugin.inc.php @@ -0,0 +1,272 @@ +plugins->registerEvent('cron_insert', $this->plugin_name, 'insert'); + $app->plugins->registerEvent('cron_update', $this->plugin_name, 'update'); + $app->plugins->registerEvent('cron_delete', $this->plugin_name, 'delete'); + + } + + //* This function is called, when a cron job is inserted in the database + function insert($event_name,$data) { + global $app, $conf; + + if($data["new"]["parent_domain_id"] == '') { + $app->log("Parent domain not set",LOGLEVEL_WARN); + return 0; + } + + //* get data from web + $parent_domain = $app->db->queryOneRecord("SELECT `domain_id`, `system_user`, `system_group`, `document_root`, `domain` FROM `web_domain` WHERE `domain_id` = ".intval($data["new"]["parent_domain_id"])); + if(!$parent_domain["domain_id"]) { + $app->log("Parent domain not found",LOGLEVEL_WARN); + return 0; + } elseif($parent_domain["system_user"] == 'root' or $parent_domain["system_group"] == 'root') { + $app->log("Websites (and Crons) can not be owned by the root user or group.",LOGLEVEL_WARN); + return 0; + } + + $app->uses('system'); + + if($app->system->is_user($parent_domain['system_user'])) { + + /** + * Setup Jailkit Chroot System If Enabled + */ + if ($data['new']['type'] == "chrooted") + { + // load the server configuration options + $app->uses("getconf"); + $this->data = $data; + $this->app = $app; + $this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit'); + $this->parent_domain = $parent_domain; + + $this->_setup_jailkit_chroot(); + + //$command .= 'usermod -U '.escapeshellcmd($parent_domain['system_user']); + //exec($command); + + $this->_add_jailkit_user(); + } + + $app->log("Jailkit Plugin (Cron) -> insert username:".$parent_domain['system_user'],LOGLEVEL_DEBUG); + + } else { + $app->log("Jailkit Plugin (Cron) -> insert username:".$parent_domain['system_user']." skipped, the user does not exist.",LOGLEVEL_WARN); + } + + } + + //* This function is called, when a cron job is updated in the database + function update($event_name,$data) { + global $app, $conf; + + if($data["new"]["parent_domain_id"] == '') { + $app->log("Parent domain not set",LOGLEVEL_WARN); + return 0; + } + //* get data from web + $parent_domain = $app->db->queryOneRecord("SELECT `domain_id`, `system_user`, `system_group`, `document_root`, `domain` FROM `web_domain` WHERE `domain_id` = ".intval($data["new"]["parent_domain_id"])); + + if(!$parent_domain["domain_id"]) { + $app->log("Parent domain not found",LOGLEVEL_WARN); + return 0; + } elseif($parent_domain["system_user"] == 'root' or $parent_domain["system_group"] == 'root') { + $app->log("Websites (and Crons) can not be owned by the root user or group.",LOGLEVEL_WARN); + return 0; + } + + $app->uses('system'); + + if($app->system->is_user($parent_domain['system_user'])) { + + /** + * Setup Jailkit Chroot System If Enabled + */ + if ($data['new']['type'] == "chrooted") + { + $app->log("Jailkit Plugin (Cron) -> setting up jail", LOGLEVEL_DEBUG); + // load the server configuration options + $app->uses("getconf"); + $this->data = $data; + $this->app = $app; + $this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit'); + $this->parent_domain = $parent_domain; + + $this->_setup_jailkit_chroot(); + $this->_add_jailkit_user(); + } + + $app->log("Jailkit Plugin (Cron) -> update username:".$parent_domain['system_user'],LOGLEVEL_DEBUG); + + } else { + $app->log("Jailkit Plugin (Cron) -> update username:".$parent_domain['system_user']." skipped, the user does not exist.",LOGLEVEL_WARN); + } + + } + + //* This function is called, when a cron job is deleted in the database + function delete($event_name,$data) { + global $app, $conf; + + //* nothing to do here! + + } + + function _setup_jailkit_chroot() + { + //check if the chroot environment is created yet if not create it with a list of program sections from the config + if (!is_dir($this->parent_domain['document_root'].'/etc/jailkit')) + { + $command = '/usr/local/ispconfig/server/scripts/create_jailkit_chroot.sh'; + $command .= ' '.escapeshellcmd($this->parent_domain['document_root']); + $command .= ' \''.$this->jailkit_config['jailkit_chroot_app_sections'].'\''; + exec($command); + + $this->app->log("Added jailkit chroot with command: ".$command,LOGLEVEL_DEBUG); + + //$this->_add_jailkit_programs(); // done later on + + $this->app->load('tpl'); + + $tpl = new tpl(); + $tpl->newTemplate("bash.bashrc.master"); + + $tpl->setVar('jailkit_chroot',true); + $tpl->setVar('domain',$this->parent_domain['domain']); + $tpl->setVar('home_dir',$this->_get_home_dir("")); + + $bashrc = escapeshellcmd($this->parent_domain['document_root']).'/etc/bash.bashrc'; + if(@is_file($bashrc)) exec('rm '.$bashrc); + + file_put_contents($bashrc,$tpl->grab()); + unset($tpl); + + $this->app->log("Added bashrc scrpt : ".$bashrc,LOGLEVEL_DEBUG); + + $tpl = new tpl(); + $tpl->newTemplate("motd.master"); + + $tpl->setVar('domain',$this->parent_domain['domain']); + + $motd = escapeshellcmd($this->parent_domain['document_root']).'/var/run/motd'; + if(@is_file($motd)) exec('rm '.$motd); + + file_put_contents($motd,$tpl->grab()); + + } + $this->_add_jailkit_programs(); + } + + function _add_jailkit_programs() + { + //copy over further programs and its libraries + $command = '/usr/local/ispconfig/server/scripts/create_jailkit_programs.sh'; + $command .= ' '.escapeshellcmd($this->parent_domain['document_root']); + $command .= ' \''.$this->jailkit_config['jailkit_chroot_app_programs'].'\''; + exec($command); + + $this->app->log("Added programs to jailkit chroot with command: ".$command,LOGLEVEL_DEBUG); + + $command = '/usr/local/ispconfig/server/scripts/create_jailkit_programs.sh'; + $command .= ' '.escapeshellcmd($this->parent_domain['document_root']); + $command .= ' \''.$this->jailkit_config['jailkit_chroot_cron_programs'].'\''; + exec($command); + + $this->app->log("Added cron programs to jailkit chroot with command: ".$command,LOGLEVEL_DEBUG); + } + + function _add_jailkit_user() + { + //add the user to the chroot + $jailkit_chroot_userhome = $this->_get_home_dir($this->parent_domain['system_user']); + + if(!is_dir($this->parent_domain['document_root'].'/etc')) mkdir($this->parent_domain['document_root'].'/etc'); + if(!is_file($this->parent_domain['document_root'].'/etc/passwd')) exec('touch '.$this->parent_domain['document_root'].'/etc/passwd'); + + // IMPORTANT! + // ALWAYS create the user. Even if the user was created before + // if we check if the user exists, then a update (no shell -> jailkit) will not work + // and the user has FULL ACCESS to the root of the server! + $command = '/usr/local/ispconfig/server/scripts/create_jailkit_user.sh'; + $command .= ' '.escapeshellcmd($this->parent_domain['system_user']); + $command .= ' '.escapeshellcmd($this->parent_domain['document_root']); + $command .= ' '.$jailkit_chroot_userhome; + $command .= ' '.escapeshellcmd("/bin/bash"); + exec($command); + + $this->app->log("Added jailkit user to chroot with command: ".$command,LOGLEVEL_DEBUG); + + exec("mkdir -p ".escapeshellcmd($this->parent_domain['document_root'].$jailkit_chroot_userhome)); + } + + function _get_home_dir($username) + { + return str_replace("[username]",escapeshellcmd($username),$this->jailkit_config["jailkit_chroot_home"]); + } + + + +} // end class + +?> \ No newline at end of file diff --git a/server/plugins-available/cron_plugin.inc.php b/server/plugins-available/cron_plugin.inc.php new file mode 100644 index 000000000..d923d1b76 --- /dev/null +++ b/server/plugins-available/cron_plugin.inc.php @@ -0,0 +1,212 @@ +plugins->registerEvent('cron_insert',$this->plugin_name,'insert'); + $app->plugins->registerEvent('cron_update',$this->plugin_name,'update'); + $app->plugins->registerEvent('cron_delete',$this->plugin_name,'delete'); + + } + + function insert($event_name,$data) { + global $app, $conf; + + $this->action = 'insert'; + // just run the update function + $this->update($event_name,$data); + + } + + + function update($event_name,$data) { + global $app, $conf; + + if($this->action != 'insert') $this->action = 'update'; + + // load the server configuration options + $app->uses("getconf"); + + if($data["new"]["parent_domain_id"] == '') { + $app->log("Parent domain not set",LOGLEVEL_WARN); + return 0; + } + + //* get data from web + $parent_domain = $app->db->queryOneRecord("SELECT `domain_id`, `system_user`, `system_group`, `document_root`, `hd_quota` FROM `web_domain` WHERE `domain_id` = ".intval($data["new"]["parent_domain_id"])); + if(!$parent_domain["domain_id"]) { + $app->log("Parent domain not found",LOGLEVEL_WARN); + return 0; + } elseif($parent_domain["system_user"] == 'root' or $parent_domain["system_group"] == 'root') { + $app->log("Websites (and Crons) can not be owned by the root user or group.",LOGLEVEL_WARN); + return 0; + } + + // Get the client ID + $client = $app->dbmaster->queryOneRecord("SELECT client_id FROM sys_group WHERE sys_group.groupid = ".intval($data["new"]["sys_groupid"])); + $client_id = intval($client["client_id"]); + unset($client); + + // Create group and user, if not exist + $app->uses("system"); + + $groupname = escapeshellcmd($parent_domain["system_group"]); + if($parent_domain["system_group"] != '' && !$app->system->is_group($parent_domain["system_group"])) { + exec("groupadd $groupname"); + $app->log("Adding the group: $groupname",LOGLEVEL_DEBUG); + } + + $username = escapeshellcmd($parent_domain["system_user"]); + if($parent_domain["system_user"] != '' && !$app->system->is_user($parent_domain["system_user"])) { + exec("useradd -d ".escapeshellcmd($parent_domain["document_root"])." -g $groupname $username -s /bin/false"); + $app->log("Adding the user: $username",LOGLEVEL_DEBUG); + } + + // Set the quota for the user + if($username != '' && $app->system->is_user($username)) { + if($parent_domain["hd_quota"] > 0){ + $blocks_soft = $parent_domain["hd_quota"] * 1024; + $blocks_hard = $blocks_soft + 1024; + } else { + $blocks_soft = $blocks_hard = 0; + } + exec("setquota -u $username $blocks_soft $blocks_hard 0 0 -a &> /dev/null"); + exec("setquota -T -u $username 604800 604800 -a &> /dev/null"); + } + + // make temp direcory writable for the apache user and the website user + exec("chmod 777 ".escapeshellcmd($parent_domain["document_root"]."/tmp")); + + /** TODO READ CRON MASTER **/ + + $this->parent_domain = $parent_domain; + $this->_write_crontab(); + + + } + + function delete($event_name,$data) { + global $app, $conf; + + //* get data from web + $parent_domain = $app->db->queryOneRecord("SELECT `domain_id`, `system_user`, `system_group`, `document_root`, `hd_quota` FROM `web_domain` WHERE `domain_id` = ".intval($data["old"]["parent_domain_id"])); + if(!$parent_domain["domain_id"]) { + $app->log("Parent domain not found",LOGLEVEL_WARN); + return 0; + } + + // Get the client ID + $client = $app->dbmaster->queryOneRecord("SELECT client_id FROM sys_group WHERE sys_group.groupid = ".intval($data["old"]["sys_groupid"])); + $client_id = intval($client["client_id"]); + unset($client); + + /** TODO remove deleted record **/ + $this->parent_domain = $parent_domain; + $this->_write_crontab(); + } + + function _write_crontab() { + global $app, $conf; + + //* load the server configuration options + $app->uses("getconf"); + + $cron_config = $app->getconf->get_server_config($conf["server_id"], 'cron'); + + //* try to find customer's mail address + + $cron_content = "MAILTO=''\n\n"; + + //* read all active cron jobs from database and write them to file + $cron_jobs = $app->db->queryAllRecords("SELECT `run_min`, `run_hour`, `run_mday`, `run_month`, `run_wday`, `command`, `type` FROM `cron` WHERE `parent_domain_id` = ".intval($this->parent_domain["domain_id"]) . " AND `active` = 'y'"); + if($cron_jobs && count($cron_jobs) > 0) { + foreach($cron_jobs as $job) { + $command = "{$job['run_min']}\t{$job['run_hour']}\t{$job['run_mday']}\t{$job['run_month']}\t{$job['run_wday']}"; + $command .= "\t{$this->parent_domain['system_user']}"; //* running as user + if($job['type'] == 'url') { + $command .= "\t{$cron_config['wget']} -q -O /dev/null " . escapeshellarg($job['command']) . " >/dev/null 2>&1"; + } else { + if($job['type'] == 'chrooted') { + if(substr($job['command'], 0, strlen($this->parent_domain['document_root'])) == $this->parent_domain['document_root']) { + //* delete the unneeded path part + $job['command'] = substr($job['command'], strlen($this->parent_domain['document_root'])); + } + } + + $command .= "\t"; + if(substr($job['command'], 0, 1) != "/") $command .= $this->parent_domain['document_root']; + $command .= $job['command']; + } + $cron_content .= $command . "\n"; + } + } + + $cron_file = escapeshellcmd($cron_config["crontab_dir"].'/ispc_'.$this->parent_domain["system_user"]); + file_put_contents($cron_file, $cron_content); + + $app->log("Wrote Cron file $cron_file with content:\n$cron_content",LOGLEVEL_DEBUG); + return 0; + } + +} // end class + +?> \ No newline at end of file -- GitLab