Marius Cramer
2015-08-06 37b29231e47a0c4458dc1c15d98588f16f07e1e2
commit | author | age
0b0dc9 1 <?php
M 2
3 /*
4 Copyright (c) 2007 - 2009, Till Brehm, projektfarm Gmbh
5 Modified 2009, Marius Cramer, pixcept KG
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
10
11     * Redistributions of source code must retain the above copyright notice,
12       this list of conditions and the following disclaimer.
13     * Redistributions in binary form must reproduce the above copyright notice,
14       this list of conditions and the following disclaimer in the documentation
15       and/or other materials provided with the distribution.
16     * Neither the name of ISPConfig nor the names of its contributors
17       may be used to endorse or promote products derived from this software without
18       specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
27 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 class cron_plugin {
b1a6a5 33
0b0dc9 34     var $plugin_name = 'cron_plugin';
M 35     var $class_name = 'cron_plugin';
b1a6a5 36
0b0dc9 37     // private variables
M 38     var $action = '';
b1a6a5 39
0b0dc9 40     //* This function is called during ispconfig installation to determine
M 41     //  if a symlink shall be created for this plugin.
42     function onInstall() {
43         global $conf;
b1a6a5 44
0b0dc9 45         if($conf['services']['web'] == true) {
M 46             return true;
47         } else {
48             return false;
49         }
b1a6a5 50
0b0dc9 51     }
b1a6a5 52
MC 53
0b0dc9 54     /*
M 55          This function is called when the plugin is loaded
56     */
b1a6a5 57
0b0dc9 58     function onLoad() {
M 59         global $app;
b1a6a5 60
0b0dc9 61         /*
M 62         Register for the events
63         */
b1a6a5 64
MC 65         $app->plugins->registerEvent('cron_insert', $this->plugin_name, 'insert');
66         $app->plugins->registerEvent('cron_update', $this->plugin_name, 'update');
67         $app->plugins->registerEvent('cron_delete', $this->plugin_name, 'delete');
68
0b0dc9 69     }
b1a6a5 70
MC 71     function insert($event_name, $data) {
0b0dc9 72         global $app, $conf;
b1a6a5 73
0b0dc9 74         $this->action = 'insert';
M 75         // just run the update function
b1a6a5 76         $this->update($event_name, $data);
MC 77
0b0dc9 78     }
b1a6a5 79
MC 80
81     function update($event_name, $data) {
0b0dc9 82         global $app, $conf;
b1a6a5 83
0b0dc9 84         if($this->action != 'insert') $this->action = 'update';
b1a6a5 85
0b0dc9 86         // load the server configuration options
M 87         $app->uses("getconf");
b1a6a5 88
0b0dc9 89         if($data["new"]["parent_domain_id"] == '') {
b1a6a5 90             $app->log("Parent domain not set", LOGLEVEL_WARN);
0b0dc9 91             return 0;
M 92         }
b1a6a5 93
MC 94         //* get data from web
cc7a82 95         $parent_domain = $app->db->queryOneRecord("SELECT `domain_id`, `system_user`, `system_group`, `document_root`, `hd_quota` FROM `web_domain` WHERE `domain_id` = ?", $data["new"]["parent_domain_id"]);
b1a6a5 96         if(!$parent_domain["domain_id"]) {
MC 97             $app->log("Parent domain not found", LOGLEVEL_WARN);
98             return 0;
0b0dc9 99         }
b1a6a5 100
64ea56 101         if(!$app->system->is_allowed_user($parent_domain['system_user'], true, true)
MC 102             || !$app->system->is_allowed_group($parent_domain['system_group'], true, true)) {
103             $app->log("Websites (and Crons) cannot be owned by the root user or group.", LOGLEVEL_WARN);
104             return false;
105         }
106         
0b0dc9 107         // Get the client ID
cc7a82 108         $client = $app->dbmaster->queryOneRecord("SELECT client_id FROM sys_group WHERE sys_group.groupid = ?", $data["new"]["sys_groupid"]);
0b0dc9 109         $client_id = intval($client["client_id"]);
M 110         unset($client);
b1a6a5 111
0b0dc9 112         // Create group and user, if not exist
M 113         $app->uses("system");
b1a6a5 114
0b0dc9 115         $groupname = escapeshellcmd($parent_domain["system_group"]);
M 116         if($parent_domain["system_group"] != '' && !$app->system->is_group($parent_domain["system_group"])) {
117             exec("groupadd $groupname");
b1a6a5 118             $app->log("Adding the group: $groupname", LOGLEVEL_DEBUG);
0b0dc9 119         }
b1a6a5 120
0b0dc9 121         $username = escapeshellcmd($parent_domain["system_user"]);
M 122         if($parent_domain["system_user"] != '' && !$app->system->is_user($parent_domain["system_user"])) {
123             exec("useradd -d ".escapeshellcmd($parent_domain["document_root"])." -g $groupname $username -s /bin/false");
b1a6a5 124             $app->log("Adding the user: $username", LOGLEVEL_DEBUG);
0b0dc9 125         }
b1a6a5 126
0b0dc9 127         // Set the quota for the user
M 128         if($username != '' && $app->system->is_user($username)) {
129             if($parent_domain["hd_quota"] > 0){
b1a6a5 130                 $blocks_soft = $parent_domain["hd_quota"] * 1024;
MC 131                 $blocks_hard = $blocks_soft + 1024;
132             } else {
133                 $blocks_soft = $blocks_hard = 0;
134             }
0b0dc9 135             exec("setquota -u $username $blocks_soft $blocks_hard 0 0 -a &> /dev/null");
M 136             exec("setquota -T -u $username 604800 604800 -a &> /dev/null");
137         }
b1a6a5 138
4b88c2 139         //TODO : change this when distribution information has been integrated into server record
b1a6a5 140         //* Gentoo requires a user to be part of the crontab group.
MC 141         if (file_exists('/etc/gentoo-release')) {
142             if (strpos($app->system->get_user_groups($username), 'crontab') === false) {
143                 $app->system->add_user_to_group('crontab', $username);
144             }
145         }
146
4a6aed 147         // make temp directory writable for the apache and website users
4bd960 148         $app->system->chmod(escapeshellcmd($parent_domain["document_root"].'/tmp'), 0777);
b1a6a5 149
MC 150         /** TODO READ CRON MASTER **/
151
152
153         $this->parent_domain = $parent_domain;
0b0dc9 154         $this->_write_crontab();
b1a6a5 155
da1a7c 156         $this->action = '';
b1a6a5 157
0b0dc9 158     }
b1a6a5 159
MC 160     function delete($event_name, $data) {
0b0dc9 161         global $app, $conf;
b1a6a5 162
MC 163         //* get data from web
cc7a82 164         $parent_domain = $app->db->queryOneRecord("SELECT `domain_id`, `system_user`, `system_group`, `document_root`, `hd_quota` FROM `web_domain` WHERE `domain_id` = ?", $data["old"]["parent_domain_id"]);
b1a6a5 165         if(!$parent_domain["domain_id"]) {
MC 166             $app->log("Parent domain not found", LOGLEVEL_WARN);
167             return 0;
168         }
169
170         // Get the client ID
cc7a82 171         $client = $app->dbmaster->queryOneRecord("SELECT client_id FROM sys_group WHERE sys_group.groupid = ?", $data["old"]["sys_groupid"]);
b1a6a5 172         $client_id = intval($client["client_id"]);
MC 173         unset($client);
174
175         $this->parent_domain = $parent_domain;
176         $this->_write_crontab();
0b0dc9 177     }
b1a6a5 178
MC 179     function _write_crontab() {
180         global $app, $conf;
181
182         //* load the server configuration options
183         $app->uses("getconf");
184
185         $cron_config = $app->getconf->get_server_config($conf["server_id"], 'cron');
186
187         //* try to find customer's mail address
188
189         /** TODO: add possibility for client to choose mail notification! **/
190         $cron_content = "MAILTO=''\n";
b67344 191         $cron_content .= "SHELL='/bin/sh'\n\n";
b1a6a5 192         $chr_cron_content = "MAILTO=''\n";
MC 193         $chr_cron_content .= "SHELL='/usr/sbin/jk_chrootsh'\n\n";
194
195         $cmd_count = 0;
196         $chr_cmd_count = 0;
197
198         //* read all active cron jobs from database and write them to file
cc7a82 199         $cron_jobs = $app->db->queryAllRecords("SELECT c.`run_min`, c.`run_hour`, c.`run_mday`, c.`run_month`, c.`run_wday`, c.`command`, c.`type`, c.`log`, `web_domain`.`domain` as `domain` FROM `cron` as c INNER JOIN `web_domain` ON `web_domain`.`domain_id` = c.`parent_domain_id` WHERE c.`parent_domain_id` = ? AND c.`active` = 'y'", $this->parent_domain["domain_id"]);
b1a6a5 200         if($cron_jobs && count($cron_jobs) > 0) {
MC 201             foreach($cron_jobs as $job) {
d3687a 202                 if($job['run_month'] == '@reboot') {
T 203                     $command = "@reboot";
204                 } else {
13bfc7 205                     $command = str_replace(" ", "", $job['run_min']) . "\t" . str_replace(" ", "", $job['run_hour']) . "\t" . str_replace(" ", "", $job['run_mday']) . "\t" . str_replace(" ", "", $job['run_month']) . "\t" . str_replace(" ", "", $job['run_wday']);
b1a6a5 206                 }
46236c 207                 
MC 208                 $log_target = ">/dev/null 2>&1";
b26653 209                 $log_wget_target = '/dev/null';
MC 210                 $log_root = '';
46236c 211                 if($job['log'] == 'y') {
b26653 212                     if($job['type'] != 'chrooted') $log_root = $this->parent_domain['document_root'];
8b49ff 213                     $log_root .= '/private';
46236c 214                     
b26653 215                     $log_target = '>>' . $log_root . '/cron.log 2>>' . $log_root . '/cron_error.log';
MC 216                     $log_wget_target = $log_root . '/cron_wget.log';
46236c 217                 }
MC 218                 
d3687a 219                 $command .= "\t{$this->parent_domain['system_user']}"; //* running as user
b1a6a5 220                 if($job['type'] == 'url') {
b26653 221                     $command .= "\t{$cron_config['wget']} -q -t 1 -T 7200 -O " . $log_wget_target . " " . escapeshellarg($job['command']) . " " . $log_target;
b1a6a5 222                 } else {
0a02ee 223                     $web_root = '';
b1a6a5 224                     if($job['type'] == 'chrooted') {
MC 225                         if(substr($job['command'], 0, strlen($this->parent_domain['document_root'])) == $this->parent_domain['document_root']) {
226                             //* delete the unneeded path part
227                             $job['command'] = substr($job['command'], strlen($this->parent_domain['document_root']));
228                         }
0a02ee 229                     } else {
MC 230                         $web_root = $this->parent_domain['document_root'];
b1a6a5 231                     }
46236c 232                     
0a02ee 233                     $web_root .= '/web';
MC 234                     $job['command'] = str_replace('[web_root]', $web_root, $job['command']);
b1a6a5 235
MC 236                     $command .= "\t";
558b54 237                     //if($job['type'] != 'chrooted' && substr($job['command'], 0, 1) != "/") $command .= $this->parent_domain['document_root'].'/';
46236c 238                     $command .= $job['command'] . " " . $log_target;
b1a6a5 239                 }
MC 240
241                 if($job['type'] == 'chrooted') {
242                     $chr_cron_content .= $command . " #{$job['domain']}\n";
243                     $chr_cmd_count++;
244                 } else {
245                     $cron_content .= $command . " #{$job['domain']}\n";
246                     $cmd_count++;
247                 }
248             }
249         }
250
251         $cron_file = escapeshellcmd($cron_config["crontab_dir"].'/ispc_'.$this->parent_domain["system_user"]);
252         //TODO : change this when distribution information has been integrated into server record
253         //* Gentoo vixie-cron requires files to end with .cron in the cron.d directory
254         if (file_exists('/etc/gentoo-release')) {
255             $cron_file .= '.cron';
256         }
257
258         if($cmd_count > 0) {
259             $app->system->file_put_contents($cron_file, $cron_content);
260             $app->log("Wrote Cron file $cron_file with content:\n$cron_content", LOGLEVEL_DEBUG);
261         } else {
262             $app->system->unlink($cron_file);
263             $app->log("Deleted Cron file $cron_file", LOGLEVEL_DEBUG);
264         }
265
266         $cron_file = escapeshellcmd($cron_config["crontab_dir"].'/ispc_chrooted_'.$this->parent_domain["system_user"]);
267         if($chr_cmd_count > 0) {
268             $app->system->file_put_contents($cron_file, $chr_cron_content);
269             $app->log("Wrote Cron file $cron_file with content:\n$chr_cron_content", LOGLEVEL_DEBUG);
270         } else {
271             $app->system->unlink($cron_file);
272             $app->log("Deleted Cron file $cron_file", LOGLEVEL_DEBUG);
273         }
274
275         return 0;
276     }
0b0dc9 277
M 278 } // end class
279
4a6aed 280 ?>