Marius Cramer
2015-08-06 37b29231e47a0c4458dc1c15d98588f16f07e1e2
commit | author | age
46c683 1 <?php
T 2
3 /*
cea1e5 4 Copyright (c) 2007 - 2012, Till Brehm, projektfarm Gmbh
46c683 5 All rights reserved.
T 6
7 Redistribution and use in source and binary forms, with or without modification,
8 are permitted provided that the following conditions are met:
9
10     * Redistributions of source code must retain the above copyright notice,
11       this list of conditions and the following disclaimer.
12     * Redistributions in binary form must reproduce the above copyright notice,
13       this list of conditions and the following disclaimer in the documentation
14       and/or other materials provided with the distribution.
15     * Neither the name of ISPConfig nor the names of its contributors
16       may be used to endorse or promote products derived from this software without
17       specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 class apache2_plugin {
ac933e 32
46c683 33     var $plugin_name = 'apache2_plugin';
T 34     var $class_name = 'apache2_plugin';
ac933e 35
46c683 36     // private variables
T 37     var $action = '';
481c00 38     var $ssl_certificate_changed = false;
ac933e 39
46c683 40     //* This function is called during ispconfig installation to determine
T 41     //  if a symlink shall be created for this plugin.
42     function onInstall() {
43         global $conf;
ac933e 44
46c683 45         if($conf['services']['web'] == true) {
T 46             return true;
47         } else {
48             return false;
49         }
ac933e 50
46c683 51     }
ac933e 52
V 53
46c683 54     /*
T 55          This function is called when the plugin is loaded
56     */
ac933e 57
46c683 58     function onLoad() {
T 59         global $app;
ac933e 60
46c683 61         /*
T 62         Register for the events
63         */
b1a6a5 64         $app->plugins->registerEvent('web_domain_insert', $this->plugin_name, 'ssl');
MC 65         $app->plugins->registerEvent('web_domain_update', $this->plugin_name, 'ssl');
66         $app->plugins->registerEvent('web_domain_delete', $this->plugin_name, 'ssl');
ac933e 67
b1a6a5 68         $app->plugins->registerEvent('web_domain_insert', $this->plugin_name, 'insert');
MC 69         $app->plugins->registerEvent('web_domain_update', $this->plugin_name, 'update');
70         $app->plugins->registerEvent('web_domain_delete', $this->plugin_name, 'delete');
ac933e 71
b1a6a5 72         $app->plugins->registerEvent('server_ip_insert', $this->plugin_name, 'server_ip');
MC 73         $app->plugins->registerEvent('server_ip_update', $this->plugin_name, 'server_ip');
74         $app->plugins->registerEvent('server_ip_delete', $this->plugin_name, 'server_ip');
ac933e 75
b1a6a5 76         $app->plugins->registerEvent('webdav_user_insert', $this->plugin_name, 'webdav');
MC 77         $app->plugins->registerEvent('webdav_user_update', $this->plugin_name, 'webdav');
78         $app->plugins->registerEvent('webdav_user_delete', $this->plugin_name, 'webdav');
79
80         $app->plugins->registerEvent('client_delete', $this->plugin_name, 'client_delete');
81
82         $app->plugins->registerEvent('web_folder_user_insert', $this->plugin_name, 'web_folder_user');
83         $app->plugins->registerEvent('web_folder_user_update', $this->plugin_name, 'web_folder_user');
84         $app->plugins->registerEvent('web_folder_user_delete', $this->plugin_name, 'web_folder_user');
85
86         $app->plugins->registerEvent('web_folder_update', $this->plugin_name, 'web_folder_update');
87         $app->plugins->registerEvent('web_folder_delete', $this->plugin_name, 'web_folder_delete');
88
89         $app->plugins->registerEvent('ftp_user_delete', $this->plugin_name, 'ftp_user_delete');
90
91         $app->plugins->registerAction('php_ini_changed', $this->plugin_name, 'php_ini_changed');
46c683 92     }
b1a6a5 93
MC 94     // check for php.ini changes
95
96
97     // Handle php.ini changes
98     function php_ini_changed($event_name, $data) {
99         global $app, $conf;
100
101         $app->uses('getconf');
bd68aa 102         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
MC 103         $fastcgi_config = $app->getconf->get_server_config($conf['server_id'], 'fastcgi');
b1a6a5 104
MC 105         /* $data contains an array with these keys:
bd68aa 106          * file -> full path of changed php_ini
c59632 107          * mode -> web_domain php modes to change (mod, fast-cgi, php-fpm, hhvm or '' for all except 'mod')
bd68aa 108          * php_version -> php ini path that changed (additional php versions)
MC 109          */
b1a6a5 110
2af58c 111         $param = '';
b1a6a5 112         $qrystr = "SELECT * FROM web_domain WHERE custom_php_ini != ''";
MC 113         if($data['mode'] == 'mod') {
114             $qrystr .= " AND php = 'mod'";
115         } elseif($data['mode'] == 'fast-cgi') {
116             $qrystr .= " AND php = 'fast-cgi'";
117             if($data['php_version']) {
2af58c 118                 $qrystr .= " AND fastcgi_php_version LIKE ?";
MC 119                 $param = '%:' . $data['php_version'];
b1a6a5 120             }
MC 121         } elseif($data['mode'] == 'php-fpm') {
122             $qrystr .= " AND php = 'php-fpm'";
c59632 123             if($data['php_version']) {
2af58c 124                 $qrystr .= " AND fastcgi_php_version LIKE ?";
MC 125                 $param = '%:' . $data['php_version'] . ':%';
c59632 126             }
MC 127         } elseif($data['mode'] == 'hhvm') {
128             $qrystr .= " AND php = 'hhvm'";
b1a6a5 129             if($data['php_version']) {
2af58c 130                 $qrystr .= " AND fastcgi_php_version LIKE ?";
MC 131                 $param = '%:' . $data['php_version'] . ':%';
b1a6a5 132             }
MC 133         } else {
134             $qrystr .= " AND php != 'mod' AND php != 'fast-cgi'";
135         }
ac933e 136
bd68aa 137
b1a6a5 138         //** Get all the webs
2af58c 139         $web_domains = $app->db->queryAllRecords($qrystr, $param);
b1a6a5 140         foreach($web_domains as $web_data) {
MC 141             $custom_php_ini_dir = $web_config['website_basedir'].'/conf/'.$web_data['system_user'];
142             $web_folder = 'web';
511ba5 143             if($web_data['type'] == 'vhostsubdomain' || $web_data['type'] == 'vhostalias') {
b1a6a5 144                 $web_folder = $web_data['web_folder'];
MC 145                 $custom_php_ini_dir .= '_' . $web_folder;
146             }
147             if(!is_dir($web_config['website_basedir'].'/conf')) $app->system->mkdir($web_config['website_basedir'].'/conf');
148
149
150             if(!is_dir($custom_php_ini_dir)) $app->system->mkdir($custom_php_ini_dir);
151             $php_ini_content = '';
152             if($web_data['php'] == 'mod') {
153                 $master_php_ini_path = $web_config['php_ini_path_apache'];
154             } else {
155                 if($web_data['php'] == 'fast-cgi' && file_exists($fastcgi_config["fastcgi_phpini_path"])) {
156                     $master_php_ini_path = $fastcgi_config["fastcgi_phpini_path"];
157                 } else {
158                     $master_php_ini_path = $web_config['php_ini_path_cgi'];
159                 }
160             }
161             if($master_php_ini_path != '' && substr($master_php_ini_path, -7) == 'php.ini' && is_file($master_php_ini_path)) {
162                 $php_ini_content .= $app->system->file_get_contents($master_php_ini_path)."\n";
163             }
b41803 164             
MC 165             if(intval($web_data['directive_snippets_id']) > 0){
166                 $snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'nginx' AND active = 'y' AND customer_viewable = 'y'", intval($web_data['directive_snippets_id']));
167                 if(isset($snippet['required_php_snippets']) && trim($snippet['required_php_snippets']) != ''){
168                     $required_php_snippets = explode(',', trim($snippet['required_php_snippets']));
169                     if(is_array($required_php_snippets) && !empty($required_php_snippets)){
170                         foreach($required_php_snippets as $required_php_snippet){
171                             $required_php_snippet = intval($required_php_snippet);
172                             if($required_php_snippet > 0){
173                                 $php_snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'php' AND active = 'y'", $required_php_snippet);
174                                 $php_snippet['snippet'] = trim($php_snippet['snippet']);
175                                 if($php_snippet['snippet'] != ''){
176                                     $web_data['custom_php_ini'] .= "\n".$php_snippet['snippet'];
177                                 }
178                             }
179                         }
180                     }
181                 }
182             }
183         
b1a6a5 184             $php_ini_content .= str_replace("\r", '', trim($web_data['custom_php_ini']));
MC 185             $app->system->file_put_contents($custom_php_ini_dir.'/php.ini', $php_ini_content);
186             $app->log('Info: rewrote custom php.ini for web ' . $web_data['domain_id'] . ' (' . $web_data['domain'] . ').', LOGLEVEL_DEBUG);
187         }
188
189         if(count($web_domains) > 0) {
190             //* We do not check the apache config here - we only changed the php.ini
191             //* Check if this is a chrooted setup
192             if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
193                 $apache_chrooted = true;
194                 $app->log('Info: Apache is chrooted.', LOGLEVEL_DEBUG);
195             } else {
196                 $apache_chrooted = false;
197             }
198
199             $app->log('Info: rewrote all php.ini and reloading apache now.', LOGLEVEL_DEBUG);
200             if($apache_chrooted) {
201                 $app->services->restartServiceDelayed('httpd', 'restart');
202             } else {
203                 // request a httpd reload when all records have been processed
204                 $app->services->restartServiceDelayed('httpd', 'reload');
205             }
206         } else {
207             $app->log('Info: No webs affected by php.ini change.', LOGLEVEL_DEBUG);
208         }
209     }
210
46c683 211     // Handle the creation of SSL certificates
b1a6a5 212     function ssl($event_name, $data) {
46c683 213         global $app, $conf;
b1a6a5 214
c77103 215         $app->uses('system');
1a2310 216
L 217         // load the server configuration options
218         $app->uses('getconf');
219         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
220         if ($web_config['CA_path']!='' && !file_exists($web_config['CA_path'].'/openssl.cnf'))
b1a6a5 221             $app->log("CA path error, file does not exist:".$web_config['CA_path'].'/openssl.cnf', LOGLEVEL_ERROR);
MC 222
1ca823 223         //* Only vhosts can have a ssl cert
511ba5 224         if($data["new"]["type"] != "vhost" && $data["new"]["type"] != "vhostsubdomain" && $data["new"]["type"] != "vhostalias") return;
ac933e 225
c77103 226         // if(!is_dir($data['new']['document_root'].'/ssl')) exec('mkdir -p '.$data['new']['document_root'].'/ssl');
T 227         if(!is_dir($data['new']['document_root'].'/ssl')) $app->system->mkdirpath($data['new']['document_root'].'/ssl');
b1a6a5 228
fb3339 229         $ssl_dir = $data['new']['document_root'].'/ssl';
J 230         $domain = $data['new']['ssl_domain'];
231         $key_file = $ssl_dir.'/'.$domain.'.key.org';
232         $key_file2 = $ssl_dir.'/'.$domain.'.key';
233         $csr_file = $ssl_dir.'/'.$domain.'.csr';
234         $crt_file = $ssl_dir.'/'.$domain.'.crt';
ac933e 235
4bd960 236         //* Create a SSL Certificate, but only if this is not a mirror server.
T 237         if($data['new']['ssl_action'] == 'create' && $conf['mirror_server_id'] == 0) {
b1a6a5 238
481c00 239             $this->ssl_certificate_changed = true;
b1a6a5 240
e94a9f 241             //* Rename files if they exist
43b345 242             if(file_exists($key_file)){
b1a6a5 243                 $app->system->rename($key_file, $key_file.'.bak');
MC 244                 $app->system->chmod($key_file.'.bak', 0400);
43b345 245             }
T 246             if(file_exists($key_file2)){
b1a6a5 247                 $app->system->rename($key_file2, $key_file2.'.bak');
MC 248                 $app->system->chmod($key_file2.'.bak', 0400);
43b345 249             }
b1a6a5 250             if(file_exists($csr_file)) $app->system->rename($csr_file, $csr_file.'.bak');
MC 251             if(file_exists($crt_file)) $app->system->rename($crt_file, $crt_file.'.bak');
252
fb3339 253             $rand_file = $ssl_dir.'/random_file';
b1a6a5 254             $rand_data = md5(uniqid(microtime(), 1));
ac933e 255             for($i=0; $i<1000; $i++) {
b1a6a5 256                 $rand_data .= md5(uniqid(microtime(), 1));
MC 257                 $rand_data .= md5(uniqid(microtime(), 1));
258                 $rand_data .= md5(uniqid(microtime(), 1));
259                 $rand_data .= md5(uniqid(microtime(), 1));
ac933e 260             }
c77103 261             $app->system->file_put_contents($rand_file, $rand_data);
46c683 262
b1a6a5 263             $ssl_password = substr(md5(uniqid(microtime(), 1)), 0, 15);
ac933e 264
46c683 265             $ssl_cnf = "        RANDFILE               = $rand_file
T 266
267         [ req ]
6d80f5 268         default_bits           = 2048
6068b7 269         default_md             = sha256
46c683 270         default_keyfile        = keyfile.pem
T 271         distinguished_name     = req_distinguished_name
272         attributes             = req_attributes
273         prompt                 = no
274         output_password        = $ssl_password
275
276         [ req_distinguished_name ]
e94a9f 277         C                      = ".trim($data['new']['ssl_country'])."
T 278         ST                     = ".trim($data['new']['ssl_state'])."
279         L                      = ".trim($data['new']['ssl_locality'])."
280         O                      = ".trim($data['new']['ssl_organisation'])."
281         OU                     = ".trim($data['new']['ssl_organisation_unit'])."
46c683 282         CN                     = $domain
T 283         emailAddress           = webmaster@".$data['new']['domain']."
284
285         [ req_attributes ]
5a4285 286         ";//challengePassword              = A challenge password";
ac933e 287
fb3339 288             $ssl_cnf_file = $ssl_dir.'/openssl.conf';
b1a6a5 289             $app->system->file_put_contents($ssl_cnf_file, $ssl_cnf);
ac933e 290
46c683 291             $rand_file = escapeshellcmd($rand_file);
T 292             $key_file = escapeshellcmd($key_file);
8c82ef 293             $openssl_cmd_key_file = $key_file;
992797 294             if(substr($domain, 0, 2) == '*.' && strpos($key_file, '/ssl/\*.') !== false) $key_file = str_replace('/ssl/\*.', '/ssl/*.', $key_file); // wildcard certificate
46c683 295             $key_file2 = escapeshellcmd($key_file2);
8c82ef 296             $openssl_cmd_key_file2 = $key_file2;
992797 297             if(substr($domain, 0, 2) == '*.' && strpos($key_file2, '/ssl/\*.') !== false) $key_file2 = str_replace('/ssl/\*.', '/ssl/*.', $key_file2); // wildcard certificate
46c683 298             $ssl_days = 3650;
T 299             $csr_file = escapeshellcmd($csr_file);
8c82ef 300             $openssl_cmd_csr_file = $csr_file;
992797 301             if(substr($domain, 0, 2) == '*.' && strpos($csr_file, '/ssl/\*.') !== false) $csr_file = str_replace('/ssl/\*.', '/ssl/*.', $csr_file); // wildcard certificate
46c683 302             $config_file = escapeshellcmd($ssl_cnf_file);
T 303             $crt_file = escapeshellcmd($crt_file);
8c82ef 304             $openssl_cmd_crt_file = $crt_file;
992797 305             if(substr($domain, 0, 2) == '*.' && strpos($crt_file, '/ssl/\*.') !== false) $crt_file = str_replace('/ssl/\*.', '/ssl/*.', $crt_file); // wildcard certificate
46c683 306
c77103 307             if(is_file($ssl_cnf_file) && !is_link($ssl_cnf_file)) {
b1a6a5 308
8c82ef 309                 exec("openssl genrsa -des3 -rand $rand_file -passout pass:$ssl_password -out $openssl_cmd_key_file 2048");
6068b7 310                 exec("openssl req -new -sha256 -passin pass:$ssl_password -passout pass:$ssl_password -key $openssl_cmd_key_file -out $openssl_cmd_csr_file -days $ssl_days -config $config_file");
8c82ef 311                 exec("openssl rsa -passin pass:$ssl_password -in $openssl_cmd_key_file -out $openssl_cmd_key_file2");
1a2310 312
L 313                 if(file_exists($web_config['CA_path'].'/openssl.cnf'))
5c4d55 314                 {
8c82ef 315                     exec("openssl ca -batch -out $openssl_cmd_crt_file -config ".$web_config['CA_path']."/openssl.cnf -passin pass:".$web_config['CA_pass']." -in $openssl_cmd_csr_file");
b1a6a5 316                     $app->log("Creating CA-signed SSL Cert for: $domain", LOGLEVEL_DEBUG);
8c82ef 317                     if (filesize($crt_file)==0 || !file_exists($crt_file)) $app->log("CA-Certificate signing failed.  openssl ca -out $openssl_cmd_crt_file -config ".$web_config['CA_path']."/openssl.cnf -passin pass:".$web_config['CA_pass']." -in $openssl_cmd_csr_file", LOGLEVEL_ERROR);
1a2310 318                 };
723662 319                 if (@filesize($crt_file)==0 || !file_exists($crt_file)){
8c82ef 320                     exec("openssl req -x509 -passin pass:$ssl_password -passout pass:$ssl_password -key $openssl_cmd_key_file -in $openssl_cmd_csr_file -out $openssl_cmd_crt_file -days $ssl_days -config $config_file ");
b1a6a5 321                     $app->log("Creating self-signed SSL Cert for: $domain", LOGLEVEL_DEBUG);
5c4d55 322                 };
b1a6a5 323
ac933e 324             }
46c683 325
b1a6a5 326             $app->system->chmod($key_file, 0400);
MC 327             $app->system->chmod($key_file2, 0400);
c77103 328             @$app->system->unlink($config_file);
T 329             @$app->system->unlink($rand_file);
2af58c 330             $ssl_request = $app->system->file_get_contents($csr_file);
MC 331             $ssl_cert = $app->system->file_get_contents($crt_file);
332             $ssl_key2 = $app->system->file_get_contents($key_file2);
d1086f 333             /* Update the DB of the (local) Server */
2af58c 334             $app->db->query("UPDATE web_domain SET ssl_request = ?, ssl_cert = ?, ssl_key = ? WHERE domain = ?", $ssl_request, $ssl_cert, $ssl_key2, $data['new']['domain']);
MC 335             $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
d1086f 336             /* Update also the master-DB of the Server-Farm */
2af58c 337             $app->dbmaster->query("UPDATE web_domain SET ssl_request = ?, ssl_cert = ?, ssl_key = ? WHERE domain = ?", $ssl_request, $ssl_cert, $ssl_key2, $data['new']['domain']);
MC 338             $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
46c683 339         }
ac933e 340
46c683 341         //* Save a SSL certificate to disk
9f56bd 342         if($data["new"]["ssl_action"] == 'save') {
481c00 343             $this->ssl_certificate_changed = true;
9f56bd 344             $ssl_dir = $data["new"]["document_root"]."/ssl";
edf806 345             $domain = ($data["new"]["ssl_domain"] != '')?$data["new"]["ssl_domain"]:$data["new"]["domain"];
481c00 346             $key_file = $ssl_dir.'/'.$domain.'.key.org';
0d20af 347             $key_file2 = $ssl_dir.'/'.$domain.'.key';
9f56bd 348             $csr_file = $ssl_dir.'/'.$domain.".csr";
T 349             $crt_file = $ssl_dir.'/'.$domain.".crt";
350             $bundle_file = $ssl_dir.'/'.$domain.".bundle";
b1a6a5 351
481c00 352             //* Backup files
43b345 353             if(file_exists($key_file)){
b1a6a5 354                 $app->system->copy($key_file, $key_file.'~');
MC 355                 $app->system->chmod($key_file.'~', 0400);
43b345 356             }
T 357             if(file_exists($key_file2)){
b1a6a5 358                 $app->system->copy($key_file2, $key_file2.'~');
MC 359                 $app->system->chmod($key_file2.'~', 0400);
43b345 360             }
b1a6a5 361             if(file_exists($csr_file)) $app->system->copy($csr_file, $csr_file.'~');
MC 362             if(file_exists($crt_file)) $app->system->copy($crt_file, $crt_file.'~');
363             if(file_exists($bundle_file)) $app->system->copy($bundle_file, $bundle_file.'~');
364
481c00 365             //* Write new ssl files
b1a6a5 366             if(trim($data["new"]["ssl_request"]) != '') $app->system->file_put_contents($csr_file, $data["new"]["ssl_request"]);
f78f1e 367             if(version_compare($app->system->getapacheversion(true), '2.4.8', '>=')) {
MC 368                 $tmp_data = '';
369                 if(trim($data["new"]["ssl_cert"]) != '') $tmp_data .= $data["new"]["ssl_cert"] . "\n";
370                 if(trim($data["new"]["ssl_bundle"]) != '') $tmp_data .= $data["new"]["ssl_bundle"];
371                 if(trim($tmp_data) != '') $app->system->file_put_contents($crt_file, $tmp_data);
372             } else {
373                 if(trim($data["new"]["ssl_cert"]) != '') $app->system->file_put_contents($crt_file, $data["new"]["ssl_cert"]);
374                 if(trim($data["new"]["ssl_bundle"]) != '') $app->system->file_put_contents($bundle_file, $data["new"]["ssl_bundle"]);
375             }
b1a6a5 376
72695f 377             //* Write the key file, if field is empty then import the key into the db
T 378             if(trim($data["new"]["ssl_key"]) != '') {
b1a6a5 379                 $app->system->file_put_contents($key_file2, $data["new"]["ssl_key"]);
MC 380                 $app->system->chmod($key_file2, 0400);
72695f 381             } else {
2af58c 382                 $ssl_key2 = $app->system->file_get_contents($key_file2);
72695f 383                 /* Update the DB of the (local) Server */
2af58c 384                 $app->db->query("UPDATE web_domain SET ssl_key = ? WHERE domain = ?", $ssl_key2, $data['new']['domain']);
72695f 385                 /* Update also the master-DB of the Server-Farm */
2af58c 386                 $app->dbmaster->query("UPDATE web_domain SET ssl_key = ? WHERE domain = ?", $ssl_key2, $data['new']['domain']);
72695f 387             }
b1a6a5 388
d1086f 389             /* Update the DB of the (local) Server */
2af58c 390             $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
b1a6a5 391
d1086f 392             /* Update also the master-DB of the Server-Farm */
2af58c 393             $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
b1a6a5 394             $app->log('Saving SSL Cert for: '.$domain, LOGLEVEL_DEBUG);
46c683 395         }
ac933e 396
46c683 397         //* Delete a SSL certificate
fb3339 398         if($data['new']['ssl_action'] == 'del') {
J 399             $ssl_dir = $data['new']['document_root'].'/ssl';
edf806 400             $domain = ($data["new"]["ssl_domain"] != '')?$data["new"]["ssl_domain"]:$data["new"]["domain"];
fb3339 401             $csr_file = $ssl_dir.'/'.$domain.'.csr';
J 402             $crt_file = $ssl_dir.'/'.$domain.'.crt';
403             $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
c77103 404             if(file_exists($web_config['CA_path'].'/openssl.cnf') && !is_link($web_config['CA_path'].'/openssl.cnf'))
b1a6a5 405             {
8c82ef 406                 exec("openssl ca -batch -config ".$web_config['CA_path']."/openssl.cnf -passin pass:".$web_config['CA_pass']." -revoke ".escapeshellcmd($crt_file));
b1a6a5 407                 $app->log("Revoking CA-signed SSL Cert for: $domain", LOGLEVEL_DEBUG);
MC 408             };
c77103 409             $app->system->unlink($csr_file);
T 410             $app->system->unlink($crt_file);
411             $app->system->unlink($bundle_file);
d1086f 412             /* Update the DB of the (local) Server */
2af58c 413             $app->db->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '' WHERE domain = ?", $data['new']['domain']);
MC 414             $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
d1086f 415             /* Update also the master-DB of the Server-Farm */
2af58c 416             $app->dbmaster->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '' WHERE domain = ?", $data['new']['domain']);
MC 417             $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
b1a6a5 418             $app->log('Deleting SSL Cert for: '.$domain, LOGLEVEL_DEBUG);
46c683 419         }
ac933e 420
46c683 421     }
ac933e 422
V 423
b1a6a5 424     function insert($event_name, $data) {
46c683 425         global $app, $conf;
ac933e 426
46c683 427         $this->action = 'insert';
T 428         // just run the update function
b1a6a5 429         $this->update($event_name, $data);
ac933e 430
V 431
46c683 432     }
ac933e 433
V 434
b1a6a5 435     function update($event_name, $data) {
46c683 436         global $app, $conf;
ac933e 437
46c683 438         if($this->action != 'insert') $this->action = 'update';
ac933e 439
511ba5 440         if($data['new']['type'] != 'vhost' && $data['new']['type'] != 'vhostsubdomain' && $data['new']['type'] != 'vhostalias' && $data['new']['parent_domain_id'] > 0) {
ac933e 441
fb3339 442             $old_parent_domain_id = intval($data['old']['parent_domain_id']);
J 443             $new_parent_domain_id = intval($data['new']['parent_domain_id']);
ac933e 444
1ca823 445             // If the parent_domain_id has been changed, we will have to update the old site as well.
fb3339 446             if($this->action == 'update' && $data['new']['parent_domain_id'] != $data['old']['parent_domain_id']) {
2af58c 447                 $tmp = $app->db->queryOneRecord('SELECT * FROM web_domain WHERE domain_id = ? AND active = ?', $old_parent_domain_id, 'y');
fb3339 448                 $data['new'] = $tmp;
J 449                 $data['old'] = $tmp;
46c683 450                 $this->action = 'update';
b1a6a5 451                 $this->update($event_name, $data);
46c683 452             }
ac933e 453
46c683 454             // This is not a vhost, so we need to update the parent record instead.
5d0363 455             $tmp = $app->db->queryOneRecord('SELECT * FROM web_domain WHERE domain_id = ? AND active = ?', $new_parent_domain_id, 'y');
fb3339 456             $data['new'] = $tmp;
J 457             $data['old'] = $tmp;
46c683 458             $this->action = 'update';
T 459         }
ac933e 460
46c683 461         // load the server configuration options
fb3339 462         $app->uses('getconf');
J 463         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
ac933e 464
2bbc4c 465         //* Check if this is a chrooted setup
155cc0 466         if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
2bbc4c 467             $apache_chrooted = true;
b1a6a5 468             $app->log('Info: Apache is chrooted.', LOGLEVEL_DEBUG);
2bbc4c 469         } else {
T 470             $apache_chrooted = false;
471         }
ac933e 472
fb3339 473         if($data['new']['document_root'] == '') {
511ba5 474             if($data['new']['type'] == 'vhost' || $data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') $app->log('document_root not set', LOGLEVEL_WARN);
46c683 475             return 0;
T 476         }
15687e 477         if($app->system->is_allowed_user($data['new']['system_user'], $app->system->is_user($data['new']['system_user']), true) == false
TB 478             || $app->system->is_allowed_group($data['new']['system_group'], $app->system->is_group($data['new']['system_group']), true) == false) {
479             $app->log('Websites cannot be owned by the root user or group. User: '.$data['new']['system_user'].' Group: '.$data['new']['system_group'], LOGLEVEL_WARN);
46c683 480             return 0;
T 481         }
e94a9f 482         if(trim($data['new']['domain']) == '') {
b1a6a5 483             $app->log('domain is empty', LOGLEVEL_WARN);
e94a9f 484             return 0;
T 485         }
b1a6a5 486
MC 487         $web_folder = 'web';
488         $log_folder = 'log';
79d955 489         $old_web_folder = 'web';
MC 490         $old_log_folder = 'log';
511ba5 491         if($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') {
79d955 492             // new one
2af58c 493             $tmp = $app->db->queryOneRecord('SELECT `domain` FROM web_domain WHERE domain_id = ?', $data['new']['parent_domain_id']);
b1a6a5 494             $subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $data['new']['domain']);
MC 495             if($subdomain_host == '') $subdomain_host = 'web'.$data['new']['domain_id'];
496             $web_folder = $data['new']['web_folder'];
497             $log_folder .= '/' . $subdomain_host;
498             unset($tmp);
79d955 499             
MC 500             if(isset($data['old']['parent_domain_id'])) {
501                 // old one
2af58c 502                 $tmp = $app->db->queryOneRecord('SELECT `domain` FROM web_domain WHERE domain_id = ?', $data['old']['parent_domain_id']);
79d955 503                 $subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $data['old']['domain']);
MC 504                 if($subdomain_host == '') $subdomain_host = 'web'.$data['old']['domain_id'];
505                 $old_web_folder = $data['old']['web_folder'];
506                 $old_log_folder .= '/' . $subdomain_host;
507                 unset($tmp);
508             }
b1a6a5 509         }
6fb93d 510
dba68f 511         // Create group and user, if not exist
T 512         $app->uses('system');
b1a6a5 513
8cf78b 514         if($web_config['connect_userid_to_webid'] == 'y') {
T 515             //* Calculate the uid and gid
516             $connect_userid_to_webid_start = ($web_config['connect_userid_to_webid_start'] < 1000)?1000:intval($web_config['connect_userid_to_webid_start']);
517             $fixed_uid_gid = intval($connect_userid_to_webid_start + $data['new']['domain_id']);
518             $fixed_uid_param = '--uid '.$fixed_uid_gid;
519             $fixed_gid_param = '--gid '.$fixed_uid_gid;
b1a6a5 520
8cf78b 521             //* Check if a ispconfigend user and group exists and create them
T 522             if(!$app->system->is_group('ispconfigend')) {
523                 exec('groupadd --gid '.($connect_userid_to_webid_start + 10000).' ispconfigend');
524             }
525             if(!$app->system->is_user('ispconfigend')) {
526                 exec('useradd -g ispconfigend -d /usr/local/ispconfig --uid '.($connect_userid_to_webid_start + 10000).' ispconfigend');
527             }
528         } else {
529             $fixed_uid_param = '';
530             $fixed_gid_param = '';
531         }
dba68f 532
T 533         $groupname = escapeshellcmd($data['new']['system_group']);
534         if($data['new']['system_group'] != '' && !$app->system->is_group($data['new']['system_group'])) {
8cf78b 535             exec('groupadd '.$fixed_gid_param.' '.$groupname);
dba68f 536             if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' groupadd '.$groupname);
b1a6a5 537             $app->log('Adding the group: '.$groupname, LOGLEVEL_DEBUG);
dba68f 538         }
T 539
540         $username = escapeshellcmd($data['new']['system_user']);
541         if($data['new']['system_user'] != '' && !$app->system->is_user($data['new']['system_user'])) {
8cf78b 542             if($web_config['add_web_users_to_sshusers_group'] == 'y') {
T 543                 exec('useradd -d '.escapeshellcmd($data['new']['document_root'])." -g $groupname $fixed_uid_param -G sshusers $username -s /bin/false");
544                 if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' useradd -d '.escapeshellcmd($data['new']['document_root'])." -g $groupname $fixed_uid_param -G sshusers $username -s /bin/false");
545             } else {
546                 exec('useradd -d '.escapeshellcmd($data['new']['document_root'])." -g $groupname $fixed_uid_param $username -s /bin/false");
547                 if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' useradd -d '.escapeshellcmd($data['new']['document_root'])." -g $groupname $fixed_uid_param $username -s /bin/false");
548             }
b1a6a5 549             $app->log('Adding the user: '.$username, LOGLEVEL_DEBUG);
dba68f 550         }
ac933e 551
46c683 552         //* If the client of the site has been changed, we have a change of the document root
fb3339 553         if($this->action == 'update' && $data['new']['document_root'] != $data['old']['document_root']) {
ac933e 554
46c683 555             //* Get the old client ID
2af58c 556             $old_client = $app->dbmaster->queryOneRecord('SELECT client_id FROM sys_group WHERE sys_group.groupid = ?', $data['old']['sys_groupid']);
fb3339 557             $old_client_id = intval($old_client['client_id']);
46c683 558             unset($old_client);
ac933e 559
46c683 560             //* Remove the old symlinks
b1a6a5 561             $tmp_symlinks_array = explode(':', $web_config['website_symlinks']);
46c683 562             if(is_array($tmp_symlinks_array)) {
T 563                 foreach($tmp_symlinks_array as $tmp_symlink) {
b1a6a5 564                     $tmp_symlink = str_replace('[client_id]', $old_client_id, $tmp_symlink);
MC 565                     $tmp_symlink = str_replace('[website_domain]', $data['old']['domain'], $tmp_symlink);
46c683 566                     // Remove trailing slash
T 567                     if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
568                     // create the symlinks, if not exist
436975 569                     if(is_link($tmp_symlink)) {
fb3339 570                         exec('rm -f '.escapeshellcmd($tmp_symlink));
b1a6a5 571                         $app->log('Removed symlink: rm -f '.$tmp_symlink, LOGLEVEL_DEBUG);
46c683 572                     }
T 573                 }
574             }
b1a6a5 575
4b9329 576             //* Remove protection of old folders
b1a6a5 577             $app->system->web_folder_protection($data['old']['document_root'], false);
ac933e 578
511ba5 579             if($data["new"]["type"] != "vhostsubdomain" && $data["new"]["type"] != "vhostalias") {
b1a6a5 580                 //* Move the site data
MC 581                 $tmp_docroot = explode('/', $data['new']['document_root']);
582                 unset($tmp_docroot[count($tmp_docroot)-1]);
583                 $new_dir = implode('/', $tmp_docroot);
ac933e 584
b1a6a5 585                 $tmp_docroot = explode('/', $data['old']['document_root']);
MC 586                 unset($tmp_docroot[count($tmp_docroot)-1]);
587                 $old_dir = implode('/', $tmp_docroot);
ac933e 588
b1a6a5 589                 //* Check if there is already some data in the new docroot and rename it as we need a clean path to move the existing site to the new path
MC 590                 if(@is_dir($data['new']['document_root'])) {
591                     $app->system->web_folder_protection($data['new']['document_root'], false);
592                     $app->system->rename($data['new']['document_root'], $data['new']['document_root'].'_bak_'.date('Y_m_d_H_i_s'));
593                     $app->log('Renaming existing directory in new docroot location. mv '.$data['new']['document_root'].' '.$data['new']['document_root'].'_bak_'.date('Y_m_d_H_i_s'), LOGLEVEL_DEBUG);
594                 }
3fb802 595                 
TB 596                 //* Unmount the old log directory bfore we move the log dir
a9b325 597                 //exec('fuser -km '.escapeshellcmd($old_dir.'/log'));
3fb802 598                 exec('umount '.escapeshellcmd($old_dir.'/log'));
ac933e 599
b1a6a5 600                 //* Create new base directory, if it does not exist yet
MC 601                 if(!is_dir($new_dir)) $app->system->mkdirpath($new_dir);
602                 $app->system->web_folder_protection($data['old']['document_root'], false);
603                 exec('mv '.escapeshellarg($data['old']['document_root']).' '.escapeshellarg($new_dir));
604                 //$app->system->rename($data['old']['document_root'],$new_dir);
605                 $app->log('Moving site to new document root: mv '.$data['old']['document_root'].' '.$new_dir, LOGLEVEL_DEBUG);
0930f5 606
b1a6a5 607                 // Handle the change in php_open_basedir
MC 608                 $data['new']['php_open_basedir'] = str_replace($data['old']['document_root'], $data['new']['document_root'], $data['old']['php_open_basedir']);
609
610                 //* Change the owner of the website files to the new website owner
611                 exec('chown --recursive --from='.escapeshellcmd($data['old']['system_user']).':'.escapeshellcmd($data['old']['system_group']).' '.escapeshellcmd($data['new']['system_user']).':'.escapeshellcmd($data['new']['system_group']).' '.$new_dir);
612
613                 //* Change the home directory and group of the website user
614                 $command = 'killall -u '.escapeshellcmd($data['new']['system_user']).' ; usermod';
615                 $command .= ' --home '.escapeshellcmd($data['new']['document_root']);
616                 $command .= ' --gid '.escapeshellcmd($data['new']['system_group']);
617                 $command .= ' '.escapeshellcmd($data['new']['system_user']).' 2>/dev/null';
618                 exec($command);
619             }
620
fb3339 621             if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' '.$command);
b1a6a5 622
10b4c8 623             //* Change the log mount
074a57 624             /*
79d955 625             $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$old_log_folder.'    none    bind';
b1a6a5 626             $app->system->removeLine('/etc/fstab', $fstab_line);
79d955 627             $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$old_log_folder.'    none    bind,nobootwait';
ff5b86 628             $app->system->removeLine('/etc/fstab', $fstab_line);
074a57 629             $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$old_log_folder.'    none    bind,nobootwait';
TB 630             $app->system->removeLine('/etc/fstab', $fstab_line);
631             */
632             
633             $fstab_line_old = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$old_log_folder.'    none    bind';
634             
635             if($web_config['network_filesystem'] == 'y') {
636                 $fstab_line = '/var/log/ispconfig/httpd/'.$data['new']['domain'].' '.$data['new']['document_root'].'/'.$log_folder.'    none    bind,nobootwait,_netdev    0 0';
637                 $app->system->replaceLine('/etc/fstab', $fstab_line_old, $fstab_line, 0, 1);
638             } else {
639                 $fstab_line = '/var/log/ispconfig/httpd/'.$data['new']['domain'].' '.$data['new']['document_root'].'/'.$log_folder.'    none    bind,nobootwait    0 0';
640                 $app->system->replaceLine('/etc/fstab', $fstab_line_old, $fstab_line, 0, 1);
641             }
3fb802 642             
TB 643             exec('mount --bind '.escapeshellarg('/var/log/ispconfig/httpd/'.$data['new']['domain']).' '.escapeshellarg($data['new']['document_root'].'/'.$log_folder));
074a57 644             
46c683 645         }
ac933e 646
46c683 647         //print_r($data);
ac933e 648
fb3339 649         // Check if the directories are there and create them if necessary.
b1a6a5 650         $app->system->web_folder_protection($data['new']['document_root'], false);
MC 651
6fb93d 652         if(!is_dir($data['new']['document_root'].'/' . $web_folder)) $app->system->mkdirpath($data['new']['document_root'].'/' . $web_folder);
M 653         if(!is_dir($data['new']['document_root'].'/' . $web_folder . '/error') and $data['new']['errordocs']) $app->system->mkdirpath($data['new']['document_root'].'/' . $web_folder . '/error');
f0dfa9 654         if(!is_dir($data['new']['document_root'].'/' . $web_folder . '/stats')) $app->system->mkdirpath($data['new']['document_root'].'/' . $web_folder . '/stats');
6fb93d 655         //if(!is_dir($data['new']['document_root'].'/'.$log_folder)) exec('mkdir -p '.$data['new']['document_root'].'/'.$log_folder);
c77103 656         if(!is_dir($data['new']['document_root'].'/ssl')) $app->system->mkdirpath($data['new']['document_root'].'/ssl');
T 657         if(!is_dir($data['new']['document_root'].'/cgi-bin')) $app->system->mkdirpath($data['new']['document_root'].'/cgi-bin');
658         if(!is_dir($data['new']['document_root'].'/tmp')) $app->system->mkdirpath($data['new']['document_root'].'/tmp');
659         if(!is_dir($data['new']['document_root'].'/webdav')) $app->system->mkdirpath($data['new']['document_root'].'/webdav');
b1a6a5 660
d87f76 661         //* Create the new private directory
T 662         if(!is_dir($data['new']['document_root'].'/private')) {
663             $app->system->mkdirpath($data['new']['document_root'].'/private');
b1a6a5 664             $app->system->chmod($data['new']['document_root'].'/private', 0710);
MC 665             $app->system->chown($data['new']['document_root'].'/private', $username);
666             $app->system->chgrp($data['new']['document_root'].'/private', $groupname);
d87f76 667         }
b1a6a5 668
MC 669
46c683 670         // Remove the symlink for the site, if site is renamed
fb3339 671         if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
J 672             if(is_dir('/var/log/ispconfig/httpd/'.$data['old']['domain'])) exec('rm -rf /var/log/ispconfig/httpd/'.$data['old']['domain']);
79d955 673             if(is_link($data['old']['document_root'].'/'.$old_log_folder)) $app->system->unlink($data['old']['document_root'].'/'.$old_log_folder);
b1a6a5 674
10b4c8 675             //* remove old log mount
79d955 676             $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$old_log_folder.'    none    bind';
b1a6a5 677             $app->system->removeLine('/etc/fstab', $fstab_line);
MC 678
10b4c8 679             //* Unmount log directory
a9b325 680             //exec('fuser -km '.escapeshellarg($data['old']['document_root'].'/'.$old_log_folder));
79d955 681             exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$old_log_folder));
46c683 682         }
b1a6a5 683
d5a517 684         //* Create the log dir if nescessary and mount it
10b4c8 685         if(!is_dir($data['new']['document_root'].'/'.$log_folder) || !is_dir('/var/log/ispconfig/httpd/'.$data['new']['domain']) || is_link($data['new']['document_root'].'/'.$log_folder)) {
6fb93d 686             if(is_link($data['new']['document_root'].'/'.$log_folder)) unlink($data['new']['document_root'].'/'.$log_folder);
10b4c8 687             if(!is_dir('/var/log/ispconfig/httpd/'.$data['new']['domain'])) exec('mkdir -p /var/log/ispconfig/httpd/'.$data['new']['domain']);
c3bf39 688             $app->system->mkdirpath($data['new']['document_root'].'/'.$log_folder);
b1a6a5 689             $app->system->chown($data['new']['document_root'].'/'.$log_folder, 'root');
MC 690             $app->system->chgrp($data['new']['document_root'].'/'.$log_folder, 'root');
691             $app->system->chmod($data['new']['document_root'].'/'.$log_folder, 0755);
6fb93d 692             exec('mount --bind '.escapeshellarg('/var/log/ispconfig/httpd/'.$data['new']['domain']).' '.escapeshellarg($data['new']['document_root'].'/'.$log_folder));
d5a517 693             //* add mountpoint to fstab
ff5b86 694             $fstab_line = '/var/log/ispconfig/httpd/'.$data['new']['domain'].' '.$data['new']['document_root'].'/'.$log_folder.'    none    bind,nobootwait,_netdev    0 0';
b1a6a5 695             $app->system->replaceLine('/etc/fstab', $fstab_line, $fstab_line, 1, 1);
d5a517 696         }
b1a6a5 697
MC 698         $app->system->web_folder_protection($data['new']['document_root'], true);
ac933e 699
46c683 700         // Get the client ID
2af58c 701         $client = $app->dbmaster->queryOneRecord('SELECT client_id FROM sys_group WHERE sys_group.groupid = ?', $data['new']['sys_groupid']);
fb3339 702         $client_id = intval($client['client_id']);
46c683 703         unset($client);
ac933e 704
46c683 705         // Remove old symlinks, if site is renamed
fb3339 706         if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
b1a6a5 707             $tmp_symlinks_array = explode(':', $web_config['website_symlinks']);
46c683 708             if(is_array($tmp_symlinks_array)) {
T 709                 foreach($tmp_symlinks_array as $tmp_symlink) {
b1a6a5 710                     $tmp_symlink = str_replace('[client_id]', $client_id, $tmp_symlink);
MC 711                     $tmp_symlink = str_replace('[website_domain]', $data['old']['domain'], $tmp_symlink);
46c683 712                     // Remove trailing slash
T 713                     if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
714                     // remove the symlinks, if not exist
715                     if(is_link($tmp_symlink)) {
fb3339 716                         exec('rm -f '.escapeshellcmd($tmp_symlink));
b1a6a5 717                         $app->log('Removed symlink: rm -f '.$tmp_symlink, LOGLEVEL_DEBUG);
46c683 718                     }
T 719                 }
720             }
721         }
ac933e 722
46c683 723         // Create the symlinks for the sites
b1a6a5 724         $tmp_symlinks_array = explode(':', $web_config['website_symlinks']);
46c683 725         if(is_array($tmp_symlinks_array)) {
T 726             foreach($tmp_symlinks_array as $tmp_symlink) {
b1a6a5 727                 $tmp_symlink = str_replace('[client_id]', $client_id, $tmp_symlink);
MC 728                 $tmp_symlink = str_replace('[website_domain]', $data['new']['domain'], $tmp_symlink);
46c683 729                 // Remove trailing slash
T 730                 if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
731                 //* Remove symlink if target folder has been changed.
fb3339 732                 if($data['old']['document_root'] != '' && $data['old']['document_root'] != $data['new']['document_root'] && is_link($tmp_symlink)) {
c77103 733                     $app->system->unlink($tmp_symlink);
46c683 734                 }
T 735                 // create the symlinks, if not exist
736                 if(!is_link($tmp_symlink)) {
b1a6a5 737                     //     exec("ln -s ".escapeshellcmd($data["new"]["document_root"])."/ ".escapeshellcmd($tmp_symlink));
552178 738                     if ($web_config["website_symlinks_rel"] == 'y') {
M 739                         $this->create_relative_link(escapeshellcmd($data["new"]["document_root"]), escapeshellcmd($tmp_symlink));
740                     } else {
741                         exec("ln -s ".escapeshellcmd($data["new"]["document_root"])."/ ".escapeshellcmd($tmp_symlink));
742                     }
743
b1a6a5 744                     $app->log('Creating symlink: ln -s '.$data['new']['document_root'].'/ '.$tmp_symlink, LOGLEVEL_DEBUG);
46c683 745                 }
T 746             }
747         }
ac933e 748
V 749
3e41e8 750
b1a6a5 751         // Install the Standard or Custom Error, Index and other related files
MC 752         // /usr/local/ispconfig/server/conf is for the standard files
753         // /usr/local/ispconfig/server/conf-custom is for the custom files
754         // setting a local var here
755
756         // normally $conf['templates'] = "/usr/local/ispconfig/server/conf";
511ba5 757         if($this->action == 'insert' && ($data['new']['type'] == 'vhost' || $data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias')) {
b1a6a5 758
MC 759             // Copy the error pages
fb3339 760             if($data['new']['errordocs']) {
6fb93d 761                 $error_page_path = escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/error/';
b1a6a5 762                 if (file_exists($conf['rootpath'] . '/conf-custom/error/'.substr(escapeshellcmd($conf['language']), 0, 2))) {
MC 763                     exec('cp ' . $conf['rootpath'] . '/conf-custom/error/'.substr(escapeshellcmd($conf['language']), 0, 2).'/* '.$error_page_path);
46c683 764                 }
T 765                 else {
4ffb51 766                     if (file_exists($conf['rootpath'] . '/conf-custom/error/400.html')) {
F 767                         exec('cp '. $conf['rootpath'] . '/conf-custom/error/*.html '.$error_page_path);
46c683 768                     }
T 769                     else {
b1a6a5 770                         exec('cp ' . $conf['rootpath'] . '/conf/error/'.substr(escapeshellcmd($conf['language']), 0, 2).'/* '.$error_page_path);
46c683 771                     }
T 772                 }
fb3339 773                 exec('chmod -R a+r '.$error_page_path);
46c683 774             }
T 775
b1a6a5 776             if (file_exists($conf['rootpath'] . '/conf-custom/index/standard_index.html_'.substr(escapeshellcmd($conf['language']), 0, 2))) {
f0dfa9 777                 if(!file_exists(escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/index.html')) exec('cp ' . $conf['rootpath'] . '/conf-custom/index/standard_index.html_'.substr(escapeshellcmd($conf['language']), 0, 2).' '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/index.html');
b1a6a5 778
MC 779                 if(is_file($conf['rootpath'] . '/conf-custom/index/favicon.ico')) {
f0dfa9 780                     if(!file_exists(escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/favicon.ico')) exec('cp ' . $conf['rootpath'] . '/conf-custom/index/favicon.ico '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/');
b1a6a5 781                 }
MC 782                 if(is_file($conf['rootpath'] . '/conf-custom/index/robots.txt')) {
f0dfa9 783                     if(!file_exists(escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/robots.txt')) exec('cp ' . $conf['rootpath'] . '/conf-custom/index/robots.txt '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/');
b1a6a5 784                 }
MC 785                 if(is_file($conf['rootpath'] . '/conf-custom/index/.htaccess')) {
f0dfa9 786                     if(!file_exists(escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/.htaccess')) exec('cp ' . $conf['rootpath'] . '/conf-custom/index/.htaccess '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/');
b1a6a5 787                 }
f0dfa9 788             } else {
4ffb51 789                 if (file_exists($conf['rootpath'] . '/conf-custom/index/standard_index.html')) {
f0dfa9 790                     if(!file_exists(escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/index.html')) exec('cp ' . $conf['rootpath'] . '/conf-custom/index/standard_index.html '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/index.html');
MC 791                 } else {
792                     if(!file_exists(escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/index.html')) exec('cp ' . $conf['rootpath'] . '/conf/index/standard_index.html_'.substr(escapeshellcmd($conf['language']), 0, 2).' '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/index.html');
793                     if(is_file($conf['rootpath'] . '/conf/index/favicon.ico')){
794                         if(!file_exists(escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/favicon.ico')) exec('cp ' . $conf['rootpath'] . '/conf/index/favicon.ico '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/');
795                     }
796                     if(is_file($conf['rootpath'] . '/conf/index/robots.txt')){
797                         if(!file_exists(escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/robots.txt')) exec('cp ' . $conf['rootpath'] . '/conf/index/robots.txt '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/');
798                     }
799                     if(is_file($conf['rootpath'] . '/conf/index/.htaccess')){
800                         if(!file_exists(escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/.htaccess')) exec('cp ' . $conf['rootpath'] . '/conf/index/.htaccess '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/');
801                     }
46c683 802                 }
T 803             }
6fb93d 804             exec('chmod -R a+r '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/');
ac933e 805
V 806             //** Copy the error documents on update when the error document checkbox has been activated and was deactivated before
511ba5 807         } elseif ($this->action == 'update' && ($data['new']['type'] == 'vhost' || $data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') && $data['old']['errordocs'] == 0 && $data['new']['errordocs'] == 1) {
b1a6a5 808
6fb93d 809             $error_page_path = escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/error/';
b1a6a5 810             if (file_exists($conf['rootpath'] . '/conf-custom/error/'.substr(escapeshellcmd($conf['language']), 0, 2))) {
MC 811                 exec('cp ' . $conf['rootpath'] . '/conf-custom/error/'.substr(escapeshellcmd($conf['language']), 0, 2).'/* '.$error_page_path);
46c683 812             }
T 813             else {
4ffb51 814                 if (file_exists($conf['rootpath'] . '/conf-custom/error/400.html')) {
F 815                     exec('cp ' . $conf['rootpath'] . '/conf-custom/error/*.html '.$error_page_path);
46c683 816                 }
T 817                 else {
b1a6a5 818                     exec('cp ' . $conf['rootpath'] . '/conf/error/'.substr(escapeshellcmd($conf['language']), 0, 2).'/* '.$error_page_path);
46c683 819                 }
T 820             }
fb3339 821             exec('chmod -R a+r '.$error_page_path);
5d5d88 822             exec('chown -R '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.$error_page_path);
46c683 823         }  // end copy error docs
ac933e 824
511ba5 825         // Set the quota for the user, but only for vhosts, not vhostsubdomains or vhostalias
cc6568 826         if($username != '' && $app->system->is_user($username) && $data['new']['type'] == 'vhost') {
fb3339 827             if($data['new']['hd_quota'] > 0) {
J 828                 $blocks_soft = $data['new']['hd_quota'] * 1024;
ac933e 829                 $blocks_hard = $blocks_soft + 1024;
V 830             } else {
831                 $blocks_soft = $blocks_hard = 0;
832             }
46c683 833             exec("setquota -u $username $blocks_soft $blocks_hard 0 0 -a &> /dev/null");
fb3339 834             exec('setquota -T -u '.$username.' 604800 604800 -a &> /dev/null');
46c683 835         }
ac933e 836
1ca823 837         if($this->action == 'insert' || $data["new"]["system_user"] != $data["old"]["system_user"]) {
46c683 838             // Chown and chmod the directories below the document root
6fb93d 839             $this->_exec('chown -R '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder);
8db8f3 840             // The document root itself has to be owned by root in normal level and by the web owner in security level 20
T 841             if($web_config['security_level'] == 20) {
6fb93d 842                 $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder);
8db8f3 843             } else {
6fb93d 844                 $this->_exec('chown root:root '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder);
8db8f3 845             }
46c683 846         }
b1a6a5 847
615a0a 848         //* add the Apache user to the client group if this is a vhost and security level is set to high, no matter if this is an insert or update and regardless of set_folder_permissions_on_update
T 849         if($data['new']['type'] == 'vhost' && $web_config['security_level'] == 20) $app->system->add_user_to_group($groupname, escapeshellcmd($web_config['user']));
ac933e 850
8db8f3 851         //* If the security level is set to high
8cf78b 852         if(($this->action == 'insert' && $data['new']['type'] == 'vhost') or ($web_config['set_folder_permissions_on_update'] == 'y' && $data['new']['type'] == 'vhost')) {
b1a6a5 853
MC 854             $app->system->web_folder_protection($data['new']['document_root'], false);
855
d87f76 856             //* Check if we have the new private folder and create it if nescessary
T 857             if(!is_dir($data['new']['document_root'].'/private')) $app->system->mkdir($data['new']['document_root'].'/private');
b1a6a5 858
edf806 859             if($web_config['security_level'] == 20) {
b1a6a5 860
MC 861                 $app->system->chmod($data['new']['document_root'], 0755);
7c37ed 862                 $app->system->chmod($data['new']['document_root'].'/web', 0711);
b1a6a5 863                 $app->system->chmod($data['new']['document_root'].'/webdav', 0710);
MC 864                 $app->system->chmod($data['new']['document_root'].'/private', 0710);
865                 $app->system->chmod($data['new']['document_root'].'/ssl', 0755);
ac933e 866
edf806 867                 // make tmp directory writable for Apache and the website users
5aedfd 868                 $app->system->chmod($data['new']['document_root'].'/tmp', 0770);
b1a6a5 869
cea1e5 870                 // Set Log directory to 755 to make the logs accessible by the FTP user
418b41 871                 if(realpath($data['new']['document_root'].'/'.$log_folder . '/error.log') == '/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log') {
b1a6a5 872                     $app->system->chmod($data['new']['document_root'].'/'.$log_folder, 0755);
c77103 873                 }
b1a6a5 874
8cf78b 875                 if($web_config['add_web_users_to_sshusers_group'] == 'y') {
T 876                     $command = 'usermod';
877                     $command .= ' --groups sshusers';
526b99 878                     $command .= ' '.escapeshellcmd($data['new']['system_user']).' 2>/dev/null';
8cf78b 879                     $this->_exec($command);
T 880                 }
ac933e 881
edf806 882                 //* if we have a chrooted Apache environment
T 883                 if($apache_chrooted) {
884                     $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' '.$command);
ac933e 885
edf806 886                     //* add the apache user to the client group in the chroot environment
T 887                     $tmp_groupfile = $app->system->server_conf['group_datei'];
888                     $app->system->server_conf['group_datei'] = $web_config['website_basedir'].'/etc/group';
889                     $app->system->add_user_to_group($groupname, escapeshellcmd($web_config['user']));
890                     $app->system->server_conf['group_datei'] = $tmp_groupfile;
891                     unset($tmp_groupfile);
892                 }
b1a6a5 893
8cf78b 894                 //* Chown all default directories
b1a6a5 895                 $app->system->chown($data['new']['document_root'], 'root');
MC 896                 $app->system->chgrp($data['new']['document_root'], 'root');
897                 $app->system->chown($data['new']['document_root'].'/cgi-bin', $username);
898                 $app->system->chgrp($data['new']['document_root'].'/cgi-bin', $groupname);
418b41 899                 if(realpath($data['new']['document_root'].'/'.$log_folder . '/error.log') == '/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log') {
b1a6a5 900                     $app->system->chown($data['new']['document_root'].'/'.$log_folder, 'root', false);
MC 901                     $app->system->chgrp($data['new']['document_root'].'/'.$log_folder, $groupname, false);
c77103 902                 }
b1a6a5 903                 $app->system->chown($data['new']['document_root'].'/ssl', 'root');
MC 904                 $app->system->chgrp($data['new']['document_root'].'/ssl', 'root');
905                 $app->system->chown($data['new']['document_root'].'/tmp', $username);
906                 $app->system->chgrp($data['new']['document_root'].'/tmp', $groupname);
907                 $app->system->chown($data['new']['document_root'].'/web', $username);
908                 $app->system->chgrp($data['new']['document_root'].'/web', $groupname);
909                 $app->system->chown($data['new']['document_root'].'/web/error', $username);
910                 $app->system->chgrp($data['new']['document_root'].'/web/error', $groupname);
911                 $app->system->chown($data['new']['document_root'].'/web/stats', $username);
912                 $app->system->chgrp($data['new']['document_root'].'/web/stats', $groupname);
913                 $app->system->chown($data['new']['document_root'].'/webdav', $username);
914                 $app->system->chgrp($data['new']['document_root'].'/webdav', $groupname);
915                 $app->system->chown($data['new']['document_root'].'/private', $username);
916                 $app->system->chgrp($data['new']['document_root'].'/private', $groupname);
ac933e 917
edf806 918                 // If the security Level is set to medium
T 919             } else {
920
b1a6a5 921                 $app->system->chmod($data['new']['document_root'], 0755);
MC 922                 $app->system->chmod($data['new']['document_root'].'/web', 0755);
923                 $app->system->chmod($data['new']['document_root'].'/webdav', 0755);
924                 $app->system->chmod($data['new']['document_root'].'/ssl', 0755);
925                 $app->system->chmod($data['new']['document_root'].'/cgi-bin', 0755);
926
edf806 927                 // make temp directory writable for Apache and the website users
5aedfd 928                 $app->system->chmod($data['new']['document_root'].'/tmp', 0770);
b1a6a5 929
6fb93d 930                 // Set Log directory to 755 to make the logs accessible by the FTP user
418b41 931                 if(realpath($data['new']['document_root'].'/'.$log_folder . '/error.log') == '/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log') {
b1a6a5 932                     $app->system->chmod($data['new']['document_root'].'/'.$log_folder, 0755);
6fb93d 933                 }
b1a6a5 934
MC 935                 $app->system->chown($data['new']['document_root'], 'root');
936                 $app->system->chgrp($data['new']['document_root'], 'root');
937                 $app->system->chown($data['new']['document_root'].'/cgi-bin', $username);
938                 $app->system->chgrp($data['new']['document_root'].'/cgi-bin', $groupname);
418b41 939                 if(realpath($data['new']['document_root'].'/'.$log_folder . '/error.log') == '/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log') {
b1a6a5 940                     $app->system->chown($data['new']['document_root'].'/'.$log_folder, 'root', false);
MC 941                     $app->system->chgrp($data['new']['document_root'].'/'.$log_folder, $groupname, false);
c77103 942                 }
b1a6a5 943
MC 944                 $app->system->chown($data['new']['document_root'].'/ssl', 'root');
945                 $app->system->chgrp($data['new']['document_root'].'/ssl', 'root');
946                 $app->system->chown($data['new']['document_root'].'/tmp', $username);
947                 $app->system->chgrp($data['new']['document_root'].'/tmp', $groupname);
948                 $app->system->chown($data['new']['document_root'].'/web', $username);
949                 $app->system->chgrp($data['new']['document_root'].'/web', $groupname);
950                 $app->system->chown($data['new']['document_root'].'/web/error', $username);
951                 $app->system->chgrp($data['new']['document_root'].'/web/error', $groupname);
952                 $app->system->chown($data['new']['document_root'].'/web/stats', $username);
953                 $app->system->chgrp($data['new']['document_root'].'/web/stats', $groupname);
954                 $app->system->chown($data['new']['document_root'].'/webdav', $username);
955                 $app->system->chgrp($data['new']['document_root'].'/webdav', $groupname);
8db8f3 956             }
511ba5 957         } elseif((($data['new']['type'] == 'vhostsubdomain') || ($data['new']['type'] == 'vhostalias')) &&
DM 958                  (($this->action == 'insert') || ($web_config['set_folder_permissions_on_update'] == 'y'))) {
959
6fb93d 960             if($web_config['security_level'] == 20) {
b1a6a5 961                 $app->system->chmod($data['new']['document_root'].'/' . $web_folder, 0710);
MC 962                 $app->system->chown($data['new']['document_root'].'/' . $web_folder, $username);
963                 $app->system->chgrp($data['new']['document_root'].'/' . $web_folder, $groupname);
964                 $app->system->chown($data['new']['document_root'].'/' . $web_folder . '/error', $username);
965                 $app->system->chgrp($data['new']['document_root'].'/' . $web_folder . '/error', $groupname);
966                 $app->system->chown($data['new']['document_root'].'/' . $web_folder . '/stats', $username);
967                 $app->system->chgrp($data['new']['document_root'].'/' . $web_folder . '/stats', $groupname);
968             } else {
969                 $app->system->chmod($data['new']['document_root'].'/' . $web_folder, 0755);
970                 $app->system->chown($data['new']['document_root'].'/' . $web_folder, $username);
971                 $app->system->chgrp($data['new']['document_root'].'/' . $web_folder, $groupname);
972                 $app->system->chown($data['new']['document_root'].'/' . $web_folder . '/error', $username);
973                 $app->system->chgrp($data['new']['document_root'].'/' . $web_folder . '/error', $groupname);
974                 $app->system->chown($data['new']['document_root'].'/' . $web_folder . '/stats', $username);
975                 $app->system->chgrp($data['new']['document_root'].'/' . $web_folder . '/stats', $groupname);
976             }
977         }
978
4b9329 979         //* Protect web folders
b1a6a5 980         $app->system->web_folder_protection($data['new']['document_root'], true);
ac933e 981
6fb93d 982         if($data['new']['type'] == 'vhost') {
b1a6a5 983             // Change the ownership of the error log to the root user
MC 984             if(!@is_file('/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log')) exec('touch '.escapeshellcmd('/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log'));
985             $app->system->chown('/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log', 'root');
986             $app->system->chgrp('/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log', 'root');
987         }
ac933e 988
26c0fc 989         //* Write the custom php.ini file, if custom_php_ini fieled is not empty
fb3339 990         $custom_php_ini_dir = $web_config['website_basedir'].'/conf/'.$data['new']['system_user'];
511ba5 991         if($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') $custom_php_ini_dir .= '_' . $web_folder;
c77103 992         if(!is_dir($web_config['website_basedir'].'/conf')) $app->system->mkdir($web_config['website_basedir'].'/conf');
b1a6a5 993
26c0fc 994         //* add open_basedir restriction to custom php.ini content, required for suphp only
b1a6a5 995         if(!stristr($data['new']['custom_php_ini'], 'open_basedir') && $data['new']['php'] == 'suphp') {
26c0fc 996             $data['new']['custom_php_ini'] .= "\nopen_basedir = '".$data['new']['php_open_basedir']."'\n";
T 997         }
b1a6a5 998
cc6568 999         $fastcgi_config = $app->getconf->get_server_config($conf['server_id'], 'fastcgi');
b1a6a5 1000
cc6568 1001         if(trim($data['new']['fastcgi_php_version']) != ''){
H 1002             list($custom_fastcgi_php_name, $custom_fastcgi_php_executable, $custom_fastcgi_php_ini_dir) = explode(':', trim($data['new']['fastcgi_php_version']));
1003             if(is_file($custom_fastcgi_php_ini_dir)) $custom_fastcgi_php_ini_dir = dirname($custom_fastcgi_php_ini_dir);
b1a6a5 1004             if(substr($custom_fastcgi_php_ini_dir, -1) == '/') $custom_fastcgi_php_ini_dir = substr($custom_fastcgi_php_ini_dir, 0, -1);
cc6568 1005         }
H 1006
26c0fc 1007         //* Create custom php.ini
fb3339 1008         if(trim($data['new']['custom_php_ini']) != '') {
7fddfe 1009             $has_custom_php_ini = true;
3f478f 1010             if(!is_dir($custom_php_ini_dir)) $app->system->mkdirpath($custom_php_ini_dir);
7fddfe 1011             $php_ini_content = '';
fb3339 1012             if($data['new']['php'] == 'mod') {
7fddfe 1013                 $master_php_ini_path = $web_config['php_ini_path_apache'];
T 1014             } else {
cc6568 1015                 if($data["new"]['php'] == 'fast-cgi') {
H 1016                     if(trim($data['new']['fastcgi_php_version']) != '' && file_exists($custom_fastcgi_php_ini_dir)){
1017                         $master_php_ini_path = $custom_fastcgi_php_ini_dir;
1018                     } elseif(file_exists($fastcgi_config["fastcgi_phpini_path"])){
1019                         $master_php_ini_path = $fastcgi_config["fastcgi_phpini_path"];
1020                     } else {
1021                         $master_php_ini_path = $web_config['php_ini_path_cgi'];
1022                     }
9f56bd 1023                 } else {
T 1024                     $master_php_ini_path = $web_config['php_ini_path_cgi'];
1025                 }
7fddfe 1026             }
b1a6a5 1027
72695f 1028             //* Add php.ini to the path in case that the master_php_ini_path is a directory
T 1029             if($master_php_ini_path != '' && is_dir($master_php_ini_path) && is_file($master_php_ini_path.'/php.ini')) {
b1a6a5 1030                 if(substr($master_php_ini_path, -1) == '/') $master_php_ini_path = substr($master_php_ini_path, 0, -1);
72695f 1031                 $master_php_ini_path .= '/php.ini';
T 1032             }
b1a6a5 1033
MC 1034             if($master_php_ini_path != '' && substr($master_php_ini_path, -7) == 'php.ini' && is_file($master_php_ini_path)) {
c77103 1035                 $php_ini_content .= $app->system->file_get_contents($master_php_ini_path)."\n";
7fddfe 1036             }
b1a6a5 1037             $php_ini_content .= str_replace("\r", '', trim($data['new']['custom_php_ini']));
b41803 1038             
MC 1039             if(intval($data['new']['directive_snippets_id']) > 0){
1040                 $snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'nginx' AND active = 'y' AND customer_viewable = 'y'", intval($data['new']['directive_snippets_id']));
1041                 if(isset($snippet['required_php_snippets']) && trim($snippet['required_php_snippets']) != ''){
1042                     $required_php_snippets = explode(',', trim($snippet['required_php_snippets']));
1043                     if(is_array($required_php_snippets) && !empty($required_php_snippets)){
1044                         foreach($required_php_snippets as $required_php_snippet){
1045                             $required_php_snippet = intval($required_php_snippet);
1046                             if($required_php_snippet > 0){
1047                                 $php_snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'php' AND active = 'y'", $required_php_snippet);
1048                                 $php_snippet['snippet'] = trim($php_snippet['snippet']);
1049                                 if($php_snippet['snippet'] != ''){
1050                                     $php_ini_content .= "\n".$php_snippet['snippet'];
1051                                 }
1052                             }
1053                         }
1054                     }
1055                 }
1056             }
1057         
b1a6a5 1058             $app->system->file_put_contents($custom_php_ini_dir.'/php.ini', $php_ini_content);
7fddfe 1059         } else {
T 1060             $has_custom_php_ini = false;
c77103 1061             if(is_file($custom_php_ini_dir.'/php.ini')) $app->system->unlink($custom_php_ini_dir.'/php.ini');
7fddfe 1062         }
T 1063
1064
1065         //* Create the vhost config file
46c683 1066         $app->load('tpl');
ac933e 1067
46c683 1068         $tpl = new tpl();
fb3339 1069         $tpl->newTemplate('vhost.conf.master');
ac933e 1070
fb3339 1071         $vhost_data = $data['new'];
a7bdf8 1072         //unset($vhost_data['ip_address']);
6fb93d 1073         $vhost_data['web_document_root'] = $data['new']['document_root'].'/' . $web_folder;
M 1074         $vhost_data['web_document_root_www'] = $web_config['website_basedir'].'/'.$data['new']['domain'].'/' . $web_folder;
fb3339 1075         $vhost_data['web_basedir'] = $web_config['website_basedir'];
J 1076         $vhost_data['security_level'] = $web_config['security_level'];
1077         $vhost_data['allow_override'] = ($data['new']['allow_override'] == '')?'All':$data['new']['allow_override'];
1078         $vhost_data['php_open_basedir'] = ($data['new']['php_open_basedir'] == '')?$data['new']['document_root']:$data['new']['php_open_basedir'];
1079         $vhost_data['ssl_domain'] = $data['new']['ssl_domain'];
1080         $vhost_data['has_custom_php_ini'] = $has_custom_php_ini;
1081         $vhost_data['custom_php_ini_dir'] = escapeshellcmd($custom_php_ini_dir);
b1a6a5 1082
02bf99 1083         // Custom Apache directives
1fa8f4 1084         if(intval($data['new']['directive_snippets_id']) > 0){
2af58c 1085             $snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'apache' AND active = 'y' AND customer_viewable = 'y'", $data['new']['directive_snippets_id']);
1fa8f4 1086             if(isset($snippet['snippet'])){
FT 1087                 $vhost_data['apache_directives'] = $snippet['snippet'];
1088             }
1089         }
02bf99 1090         // Make sure we only have Unix linebreaks
T 1091         $vhost_data['apache_directives'] = str_replace("\r\n", "\n", $vhost_data['apache_directives']);
1092         $vhost_data['apache_directives'] = str_replace("\r", "\n", $vhost_data['apache_directives']);
018955 1093         $trans = array('{DOCROOT}' => $vhost_data['web_document_root_www']);
FT 1094         $vhost_data['apache_directives'] = strtr($vhost_data['apache_directives'], $trans);
ac933e 1095
46c683 1096         // Check if a SSL cert exists
fb3339 1097         $ssl_dir = $data['new']['document_root'].'/ssl';
J 1098         $domain = $data['new']['ssl_domain'];
1099         $key_file = $ssl_dir.'/'.$domain.'.key';
1100         $crt_file = $ssl_dir.'/'.$domain.'.crt';
1101         $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
ac933e 1102
a7bdf8 1103         /*
1a2310 1104         if($domain!='' && $data['new']['ssl'] == 'y' && @is_file($crt_file) && @is_file($key_file) && (@filesize($crt_file)>0)  && (@filesize($key_file)>0)) {
fb3339 1105             $vhost_data['ssl_enabled'] = 1;
J 1106             $app->log('Enable SSL for: '.$domain,LOGLEVEL_DEBUG);
46c683 1107         } else {
fb3339 1108             $vhost_data['ssl_enabled'] = 0;
1a2310 1109             $app->log('SSL Disabled. '.$domain,LOGLEVEL_DEBUG);
46c683 1110         }
a7bdf8 1111         */
ac933e 1112
46c683 1113         if(@is_file($bundle_file)) $vhost_data['has_bundle_cert'] = 1;
ac933e 1114
6fb93d 1115         //$vhost_data['document_root'] = $data['new']['document_root'].'/' . $web_folder;
b1a6a5 1116
e64fbb 1117         // Set SEO Redirect
bfcdef 1118         if($data['new']['seo_redirect'] != ''){
e64fbb 1119             $vhost_data['seo_redirect_enabled'] = 1;
bfcdef 1120             $tmp_seo_redirects = $this->get_seo_redirects($data['new']);
T 1121             if(is_array($tmp_seo_redirects) && !empty($tmp_seo_redirects)){
1122                 foreach($tmp_seo_redirects as $key => $val){
1123                     $vhost_data[$key] = $val;
1124                 }
1125             } else {
1126                 $vhost_data['seo_redirect_enabled'] = 0;
e64fbb 1127             }
F 1128         } else {
1129             $vhost_data['seo_redirect_enabled'] = 0;
1130         }
b1a6a5 1131
46c683 1132         $tpl->setVar($vhost_data);
8133de 1133         $tpl->setVar('apache_version', $app->system->getapacheversion());
ac933e 1134
46c683 1135         // Rewrite rules
T 1136         $rewrite_rules = array();
02bf99 1137         if($data['new']['redirect_type'] != '' && $data['new']['redirect_path'] != '') {
b1a6a5 1138             if(substr($data['new']['redirect_path'], -1) != '/' && !preg_match('/^(https?|\[scheme\]):\/\//', $data['new']['redirect_path'])) $data['new']['redirect_path'] .= '/';
MC 1139             if(substr($data['new']['redirect_path'], 0, 8) == '[scheme]'){
1140                 $rewrite_target = 'http'.substr($data['new']['redirect_path'], 8);
1141                 $rewrite_target_ssl = 'https'.substr($data['new']['redirect_path'], 8);
45ee67 1142             } else {
F 1143                 $rewrite_target = $data['new']['redirect_path'];
1144                 $rewrite_target_ssl = $data['new']['redirect_path'];
1145             }
bc2c3e 1146             /* Disabled path extension
fb3339 1147             if($data['new']['redirect_type'] == 'no' && substr($data['new']['redirect_path'],0,4) != 'http') {
J 1148                 $data['new']['redirect_path'] = $data['new']['document_root'].'/web'.realpath($data['new']['redirect_path']).'/';
8388ae 1149             }
bc2c3e 1150             */
ac933e 1151
fb3339 1152             switch($data['new']['subdomain']) {
b1a6a5 1153             case 'www':
MC 1154                 $rewrite_rules[] = array( 'rewrite_domain'  => '^'.$this->_rewrite_quote($data['new']['domain']),
1155                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
1156                     'rewrite_target'  => $rewrite_target,
1157                     'rewrite_target_ssl' => $rewrite_target_ssl,
1158                     'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1159                     'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1160                 $rewrite_rules[] = array( 'rewrite_domain'  => '^' . $this->_rewrite_quote('www.'.$data['new']['domain']),
1161                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
1162                     'rewrite_target'  => $rewrite_target,
1163                     'rewrite_target_ssl' => $rewrite_target_ssl,
1164                     'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1165                     'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1166                 break;
1167             case '*':
1168                 $rewrite_rules[] = array( 'rewrite_domain'  => '(^|\.)'.$this->_rewrite_quote($data['new']['domain']),
1169                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
1170                     'rewrite_target'  => $rewrite_target,
1171                     'rewrite_target_ssl' => $rewrite_target_ssl,
1172                     'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1173                     'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1174                 break;
1175             default:
1176                 $rewrite_rules[] = array( 'rewrite_domain'  => '^'.$this->_rewrite_quote($data['new']['domain']),
1177                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
1178                     'rewrite_target'  => $rewrite_target,
1179                     'rewrite_target_ssl' => $rewrite_target_ssl,
1180                     'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1181                     'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
ac933e 1182             }
46c683 1183         }
b1a6a5 1184
3501f9 1185         $server_alias = array();
b1a6a5 1186
3501f9 1187         // get autoalias
M 1188         $auto_alias = $web_config['website_autoalias'];
1189         if($auto_alias != '') {
1190             // get the client username
2af58c 1191             $client = $app->db->queryOneRecord("SELECT `username` FROM `client` WHERE `client_id` = ?", $client_id);
3501f9 1192             $aa_search = array('[client_id]', '[website_id]', '[client_username]', '[website_domain]');
M 1193             $aa_replace = array($client_id, $data['new']['domain_id'], $client['username'], $data['new']['domain']);
1194             $auto_alias = str_replace($aa_search, $aa_replace, $auto_alias);
1195             unset($client);
1196             unset($aa_search);
1197             unset($aa_replace);
cece69 1198             $server_alias[] .= $auto_alias.' ';
3501f9 1199         }
b1a6a5 1200
46c683 1201         // get alias domains (co-domains and subdomains)
2af58c 1202         $aliases = $app->db->queryAllRecords("SELECT * FROM web_domain WHERE parent_domain_id = ? AND active = 'y' AND (type != 'vhostsubdomain' AND type != 'vhostalias')", $data['new']['domain_id']);
bfcdef 1203         $alias_seo_redirects = array();
fb3339 1204         switch($data['new']['subdomain']) {
b1a6a5 1205         case 'www':
MC 1206             $server_alias[] .= 'www.'.$data['new']['domain'].' ';
1207             break;
1208         case '*':
1209             $server_alias[] .= '*.'.$data['new']['domain'].' ';
1210             break;
ac933e 1211         }
46c683 1212         if(is_array($aliases)) {
T 1213             foreach($aliases as $alias) {
fb3339 1214                 switch($alias['subdomain']) {
b1a6a5 1215                 case 'www':
MC 1216                     $server_alias[] .= 'www.'.$alias['domain'].' '.$alias['domain'].' ';
1217                     break;
1218                 case '*':
1219                     $server_alias[] .= '*.'.$alias['domain'].' '.$alias['domain'].' ';
1220                     break;
1221                 default:
1222                     $server_alias[] .= $alias['domain'].' ';
1223                     break;
ac933e 1224                 }
b1a6a5 1225                 $app->log('Add server alias: '.$alias['domain'], LOGLEVEL_DEBUG);
MC 1226
bfcdef 1227                 // Add SEO redirects for alias domains
T 1228                 if($alias['seo_redirect'] != '' && $data['new']['seo_redirect'] != '*_to_www_domain_tld' && $data['new']['seo_redirect'] != '*_to_domain_tld' && ($alias['type'] == 'alias' || ($alias['type'] == 'subdomain' && $data['new']['seo_redirect'] != '*_domain_tld_to_www_domain_tld' && $data['new']['seo_redirect'] != '*_domain_tld_to_domain_tld'))){
1229                     $tmp_seo_redirects = $this->get_seo_redirects($alias, 'alias_');
1230                     if(is_array($tmp_seo_redirects) && !empty($tmp_seo_redirects)){
1231                         $alias_seo_redirects[] = $tmp_seo_redirects;
1232                     }
1233                 }
b1a6a5 1234
46c683 1235                 // Rewriting
02bf99 1236                 if($alias['redirect_type'] != '' && $alias['redirect_path'] != '') {
b1a6a5 1237                     if(substr($alias['redirect_path'], -1) != '/' && !preg_match('/^(https?|\[scheme\]):\/\//', $alias['redirect_path'])) $alias['redirect_path'] .= '/';
MC 1238                     if(substr($alias['redirect_path'], 0, 8) == '[scheme]'){
1239                         $rewrite_target = 'http'.substr($alias['redirect_path'], 8);
1240                         $rewrite_target_ssl = 'https'.substr($alias['redirect_path'], 8);
e64fbb 1241                     } else {
F 1242                         $rewrite_target = $alias['redirect_path'];
1243                         $rewrite_target_ssl = $alias['redirect_path'];
1244                     }
bc2c3e 1245                     /* Disabled the path extension
fb3339 1246                     if($data['new']['redirect_type'] == 'no' && substr($data['new']['redirect_path'],0,4) != 'http') {
J 1247                         $data['new']['redirect_path'] = $data['new']['document_root'].'/web'.realpath($data['new']['redirect_path']).'/';
8388ae 1248                     }
bc2c3e 1249                     */
b1a6a5 1250
fb3339 1251                     switch($alias['subdomain']) {
b1a6a5 1252                     case 'www':
MC 1253                         $rewrite_rules[] = array( 'rewrite_domain'  => '^'.$this->_rewrite_quote($alias['domain']),
1254                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
1255                             'rewrite_target'  => $rewrite_target,
1256                             'rewrite_target_ssl' => $rewrite_target_ssl,
1257                             'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1258                             'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1259                         $rewrite_rules[] = array( 'rewrite_domain'  => '^' . $this->_rewrite_quote('www.'.$alias['domain']),
1260                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
1261                             'rewrite_target'  => $rewrite_target,
1262                             'rewrite_target_ssl' => $rewrite_target_ssl,
1263                             'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1264                             'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1265                         break;
1266                     case '*':
1267                         $rewrite_rules[] = array( 'rewrite_domain'  => '(^|\.)'.$this->_rewrite_quote($alias['domain']),
1268                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
1269                             'rewrite_target'  => $rewrite_target,
1270                             'rewrite_target_ssl' => $rewrite_target_ssl,
1271                             'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1272                             'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1273                         break;
1274                     default:
1275                         if(substr($alias['domain'], 0, 2) === '*.') $domain_rule = '(^|\.)'.$this->_rewrite_quote(substr($alias['domain'], 2));
1276                         else $domain_rule = '^'.$this->_rewrite_quote($alias['domain']);
1277                         $rewrite_rules[] = array( 'rewrite_domain'  => $domain_rule,
1278                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
1279                             'rewrite_target'  => $rewrite_target,
1280                             'rewrite_target_ssl' => $rewrite_target_ssl,
1281                             'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1282                             'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
ac933e 1283                     }
46c683 1284                 }
T 1285             }
1286         }
ac933e 1287
47cca9 1288         //* If we have some alias records
T 1289         if(count($server_alias) > 0) {
1290             $server_alias_str = '';
1291             $n = 0;
ac933e 1292
47cca9 1293             // begin a new ServerAlias line after 30 alias domains
T 1294             foreach($server_alias as $tmp_alias) {
1295                 if($n % 30 == 0) $server_alias_str .= "\n    ServerAlias ";
1296                 $server_alias_str .= $tmp_alias;
1297             }
1298             unset($tmp_alias);
ac933e 1299
b1a6a5 1300             $tpl->setVar('alias', trim($server_alias_str));
47cca9 1301         } else {
b1a6a5 1302             $tpl->setVar('alias', '');
47cca9 1303         }
ac933e 1304
bfcdef 1305         if(count($rewrite_rules) > 0 || $vhost_data['seo_redirect_enabled'] > 0 || count($alias_seo_redirects) > 0) {
b1a6a5 1306             $tpl->setVar('rewrite_enabled', 1);
46c683 1307         } else {
b1a6a5 1308             $tpl->setVar('rewrite_enabled', 0);
bfcdef 1309         }
8ab3cd 1310
T 1311         //$tpl->setLoop('redirects',$rewrite_rules);
ac933e 1312
V 1313         /**
1314          * install fast-cgi starter script and add script aliasd config
46c683 1315          * first we create the script directory if not already created, then copy over the starter script
T 1316          * settings are copied over from the server ini config for now
1317          * TODO: Create form for fastcgi configs per site.
1318          */
ac933e 1319
b1a6a5 1320
fb3339 1321         if ($data['new']['php'] == 'fast-cgi') {
ac933e 1322
b1a6a5 1323             $fastcgi_starter_path = str_replace('[system_user]', $data['new']['system_user'], $fastcgi_config['fastcgi_starter_path']);
MC 1324             $fastcgi_starter_path = str_replace('[client_id]', $client_id, $fastcgi_starter_path);
ac933e 1325
V 1326             if (!is_dir($fastcgi_starter_path)) {
c77103 1327                 $app->system->mkdirpath($fastcgi_starter_path);
fb3339 1328                 //exec('chown '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.escapeshellcmd($fastcgi_starter_path));
ac933e 1329
V 1330
b1a6a5 1331                 $app->log('Creating fastcgi starter script directory: '.$fastcgi_starter_path, LOGLEVEL_DEBUG);
46c683 1332             }
ac933e 1333
c77103 1334             //exec('chown -R '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.escapeshellcmd($fastcgi_starter_path));
b1a6a5 1335             $app->system->chown($fastcgi_starter_path, $data['new']['system_user']);
MC 1336             $app->system->chgrp($fastcgi_starter_path, $data['new']['system_group']);
1337
46c683 1338             $fcgi_tpl = new tpl();
fb3339 1339             $fcgi_tpl->newTemplate('php-fcgi-starter.master');
8133de 1340             $fcgi_tpl->setVar('apache_version', $app->system->getapacheversion());
b1a6a5 1341
62b385 1342             // Support for multiple PHP versions (FastCGI)
F 1343             if(trim($data['new']['fastcgi_php_version']) != ''){
1344                 $default_fastcgi_php = false;
b1a6a5 1345                 if(substr($custom_fastcgi_php_ini_dir, -1) != '/') $custom_fastcgi_php_ini_dir .= '/';
62b385 1346             } else {
F 1347                 $default_fastcgi_php = true;
1348             }
b1a6a5 1349
7fddfe 1350             if($has_custom_php_ini) {
b1a6a5 1351                 $fcgi_tpl->setVar('php_ini_path', escapeshellcmd($custom_php_ini_dir));
7fddfe 1352             } else {
62b385 1353                 if($default_fastcgi_php){
b1a6a5 1354                     $fcgi_tpl->setVar('php_ini_path', escapeshellcmd($fastcgi_config['fastcgi_phpini_path']));
62b385 1355                 } else {
b1a6a5 1356                     $fcgi_tpl->setVar('php_ini_path', escapeshellcmd($custom_fastcgi_php_ini_dir));
62b385 1357                 }
7fddfe 1358             }
b1a6a5 1359             $fcgi_tpl->setVar('document_root', escapeshellcmd($data['new']['document_root']));
MC 1360             $fcgi_tpl->setVar('php_fcgi_children', escapeshellcmd($fastcgi_config['fastcgi_children']));
1361             $fcgi_tpl->setVar('php_fcgi_max_requests', escapeshellcmd($fastcgi_config['fastcgi_max_requests']));
62b385 1362             if($default_fastcgi_php){
b1a6a5 1363                 $fcgi_tpl->setVar('php_fcgi_bin', escapeshellcmd($fastcgi_config['fastcgi_bin']));
62b385 1364             } else {
b1a6a5 1365                 $fcgi_tpl->setVar('php_fcgi_bin', escapeshellcmd($custom_fastcgi_php_executable));
62b385 1366             }
b1a6a5 1367             $fcgi_tpl->setVar('security_level', intval($web_config['security_level']));
f63910 1368             $fcgi_tpl->setVar('domain', escapeshellcmd($data['new']['domain']));
ac933e 1369
fb3339 1370             $php_open_basedir = ($data['new']['php_open_basedir'] == '')?$data['new']['document_root']:$data['new']['php_open_basedir'];
ff7075 1371             $fcgi_tpl->setVar('open_basedir', escapeshellcmd($php_open_basedir));
ac933e 1372
511ba5 1373             $fcgi_starter_script = escapeshellcmd($fastcgi_starter_path.$fastcgi_config['fastcgi_starter_script'].(($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') ? '_web' . $data['new']['domain_id'] : ''));
b1a6a5 1374             $app->system->file_put_contents($fcgi_starter_script, $fcgi_tpl->grab());
46c683 1375             unset($fcgi_tpl);
ac933e 1376
b1a6a5 1377             $app->log('Creating fastcgi starter script: '.$fcgi_starter_script, LOGLEVEL_DEBUG);
ac933e 1378
b1a6a5 1379             $app->system->chmod($fcgi_starter_script, 0755);
MC 1380             $app->system->chown($fcgi_starter_script, $data['new']['system_user']);
1381             $app->system->chgrp($fcgi_starter_script, $data['new']['system_group']);
1382
1383             $tpl->setVar('fastcgi_alias', $fastcgi_config['fastcgi_alias']);
1384             $tpl->setVar('fastcgi_starter_path', $fastcgi_starter_path);
511ba5 1385             $tpl->setVar('fastcgi_starter_script', $fastcgi_config['fastcgi_starter_script'].(($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') ? '_web' . $data['new']['domain_id'] : ''));
b1a6a5 1386             $tpl->setVar('fastcgi_config_syntax', $fastcgi_config['fastcgi_config_syntax']);
MC 1387             $tpl->setVar('fastcgi_max_requests', $fastcgi_config['fastcgi_max_requests']);
ac933e 1388
62e4b3 1389         } else {
F 1390             //remove the php fastgi starter script if available
b5b862 1391             $fastcgi_starter_script = $fastcgi_config['fastcgi_starter_script'].($data['old']['type'] == 'vhostsubdomain' ? '_web' . $data['old']['domain_id'] : '');
62e4b3 1392             if ($data['old']['php'] == 'fast-cgi') {
b1a6a5 1393                 $fastcgi_starter_path = str_replace('[system_user]', $data['old']['system_user'], $fastcgi_config['fastcgi_starter_path']);
MC 1394                 $fastcgi_starter_path = str_replace('[client_id]', $client_id, $fastcgi_starter_path);
1395                 if($data['old']['type'] == 'vhost') {
b5b862 1396                     if(is_file($fastcgi_starter_script)) @unlink($fastcgi_starter_script);
TB 1397                     if (is_dir($fastcgi_starter_path)) @rmdir($fastcgi_starter_path);
b1a6a5 1398                 } else {
b5b862 1399                     if(is_file($fastcgi_starter_script)) @unlink($fastcgi_starter_script);
b1a6a5 1400                 }
62e4b3 1401             }
46c683 1402         }
b1a6a5 1403
MC 1404
1405
274362 1406         /**
b1a6a5 1407          * PHP-FPM
MC 1408          */
274362 1409         // Support for multiple PHP versions
02e7ea 1410         if($data['new']['php'] == 'php-fpm'){
62e4b3 1411             if(trim($data['new']['fastcgi_php_version']) != ''){
F 1412                 $default_php_fpm = false;
1413                 list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['new']['fastcgi_php_version']));
b1a6a5 1414                 if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
62e4b3 1415             } else {
F 1416                 $default_php_fpm = true;
1417             }
274362 1418         } else {
c59632 1419             if(trim($data['old']['fastcgi_php_version']) != '' && ($data['old']['php'] == 'php-fpm' || $data['old']['php'] == 'hhvm')){
62e4b3 1420                 $default_php_fpm = false;
F 1421                 list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['old']['fastcgi_php_version']));
b1a6a5 1422                 if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
62e4b3 1423             } else {
F 1424                 $default_php_fpm = true;
1425             }
274362 1426         }
b1a6a5 1427
274362 1428         if($default_php_fpm){
F 1429             $pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
1430         } else {
1431             $pool_dir = $custom_php_fpm_pool_dir;
1432         }
ab79c2 1433         $pool_dir = trim($pool_dir);
b1a6a5 1434         if(substr($pool_dir, -1) != '/') $pool_dir .= '/';
274362 1435         $pool_name = 'web'.$data['new']['domain_id'];
F 1436         $socket_dir = escapeshellcmd($web_config['php_fpm_socket_dir']);
b1a6a5 1437         if(substr($socket_dir, -1) != '/') $socket_dir .= '/';
9b021b 1438         
1e67c1 1439         $apache_modules = $app->system->getapachemodules();
TB 1440         
1441         // Use sockets, but not with apache 2.4 on centos (mod_proxy_fcgi) as socket support is buggy in that version
1442         if($data['new']['php_fpm_use_socket'] == 'y' && in_array('fastcgi_module',$apache_modules)){
274362 1443             $use_tcp = 0;
F 1444             $use_socket = 1;
1445         } else {
1446             $use_tcp = 1;
1447             $use_socket = 0;
1448         }
1449         $tpl->setVar('use_tcp', $use_tcp);
1450         $tpl->setVar('use_socket', $use_socket);
1451         $fpm_socket = $socket_dir.$pool_name.'.sock';
1452         $tpl->setVar('fpm_socket', $fpm_socket);
1453         $tpl->setVar('fpm_port', $web_config['php_fpm_start_port'] + $data['new']['domain_id'] - 1);
ac933e 1454
46c683 1455         /**
T 1456          * install cgi starter script and add script alias to config.
1457          * This is needed to allow cgi with suexec (to do so, we need a bin in the document-path!)
1458          * first we create the script directory if not already created, then copy over the starter script.
1459          * TODO: we have to fetch the data from the server-settings.
1460          */
fb3339 1461         if ($data['new']['php'] == 'cgi') {
J 1462             //$cgi_config = $app->getconf->get_server_config($conf['server_id'], 'cgi');
46c683 1463
fb3339 1464             $cgi_config['cgi_starter_path'] = $web_config['website_basedir'].'/php-cgi-scripts/[system_user]/';
511ba5 1465             $cgi_config['cgi_starter_script'] = 'php-cgi-starter'.(($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') ? '_web' . $data['new']['domain_id'] : '');
fb3339 1466             $cgi_config['cgi_bin'] = '/usr/bin/php-cgi';
46c683 1467
b1a6a5 1468             $cgi_starter_path = str_replace('[system_user]', $data['new']['system_user'], $cgi_config['cgi_starter_path']);
MC 1469             $cgi_starter_path = str_replace('[client_id]', $client_id, $cgi_starter_path);
46c683 1470
ac933e 1471             if (!is_dir($cgi_starter_path)) {
c77103 1472                 $app->system->mkdirpath($cgi_starter_path);
b1a6a5 1473                 $app->system->chown($cgi_starter_path, $data['new']['system_user']);
MC 1474                 $app->system->chgrp($cgi_starter_path, $data['new']['system_group']);
1475                 $app->system->chmod($cgi_starter_path, 0755);
46c683 1476
b1a6a5 1477                 $app->log('Creating cgi starter script directory: '.$cgi_starter_path, LOGLEVEL_DEBUG);
46c683 1478             }
T 1479
1480             $cgi_tpl = new tpl();
fb3339 1481             $cgi_tpl->newTemplate('php-cgi-starter.master');
8133de 1482             $cgi_tpl->setVar('apache_version', $app->system->getapacheversion());
46c683 1483
fb3339 1484             // This works because PHP "rewrites" a symlink to the physical path
J 1485             $php_open_basedir = ($data['new']['php_open_basedir'] == '')?$data['new']['document_root']:$data['new']['php_open_basedir'];
ac933e 1486             $cgi_tpl->setVar('open_basedir', escapeshellcmd($php_open_basedir));
fb3339 1487             $cgi_tpl->setVar('document_root', escapeshellcmd($data['new']['document_root']));
ac933e 1488
46c683 1489             // This will NOT work!
fb3339 1490             //$cgi_tpl->setVar('open_basedir', '/var/www/' . $data['new']['domain']);
b1a6a5 1491             $cgi_tpl->setVar('php_cgi_bin', $cgi_config['cgi_bin']);
MC 1492             $cgi_tpl->setVar('security_level', $web_config['security_level']);
1493
1494             $cgi_tpl->setVar('has_custom_php_ini', $has_custom_php_ini);
7fddfe 1495             if($has_custom_php_ini) {
b1a6a5 1496                 $cgi_tpl->setVar('php_ini_path', escapeshellcmd($custom_php_ini_dir));
7fddfe 1497             } else {
b1a6a5 1498                 $cgi_tpl->setVar('php_ini_path', escapeshellcmd($fastcgi_config['fastcgi_phpini_path']));
7fddfe 1499             }
46c683 1500
511ba5 1501             $cgi_starter_script = escapeshellcmd($cgi_starter_path.$cgi_config['cgi_starter_script'].(($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') ? '_web' . $data['new']['domain_id'] : ''));
b1a6a5 1502             $app->system->file_put_contents($cgi_starter_script, $cgi_tpl->grab());
46c683 1503             unset($cgi_tpl);
T 1504
b1a6a5 1505             $app->log('Creating cgi starter script: '.$cgi_starter_script, LOGLEVEL_DEBUG);
46c683 1506
T 1507
b1a6a5 1508             $app->system->chmod($cgi_starter_script, 0755);
MC 1509             $app->system->chown($cgi_starter_script, $data['new']['system_user']);
1510             $app->system->chgrp($cgi_starter_script, $data['new']['system_group']);
46c683 1511
b1a6a5 1512             $tpl->setVar('cgi_starter_path', $cgi_starter_path);
511ba5 1513             $tpl->setVar('cgi_starter_script', $cgi_config['cgi_starter_script'].(($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') ? '_web' . $data['new']['domain_id'] : ''));
46c683 1514
T 1515         }
1516
fb3339 1517         $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['new']['domain'].'.vhost');
7ed741 1518         //* Make a backup copy of vhost file
b1a6a5 1519         if(file_exists($vhost_file)) $app->system->copy($vhost_file, $vhost_file.'~');
MC 1520
a7bdf8 1521         //* create empty vhost array
T 1522         $vhosts = array();
b1a6a5 1523
526b99 1524         //* Add vhost for ipv4 IP
6c424f 1525
FS 1526         //* use ip-mapping for web-mirror
1527         if($data['new']['ip_address'] != '*' && $conf['mirror_server_id'] > 0) {
1528             $sql = "SELECT destination_ip FROM server_ip_map WHERE server_id = ? AND source_ip = ?";
1529             $newip = $app->db->queryOneRecord($sql, $conf['server_id'], $data['new']['ip_address']);
1530             $data['new']['ip_address'] = $newip['destination_ip'];
1531             unset($newip);
1532         }
1533
526b99 1534         $tmp_vhost_arr = array('ip_address' => $data['new']['ip_address'], 'ssl_enabled' => 0, 'port' => 80);
T 1535         if(count($rewrite_rules) > 0)  $tmp_vhost_arr = $tmp_vhost_arr + array('redirects' => $rewrite_rules);
1536         if(count($alias_seo_redirects) > 0) $tmp_vhost_arr = $tmp_vhost_arr + array('alias_seo_redirects' => $alias_seo_redirects);
1537         $vhosts[] = $tmp_vhost_arr;
1538         unset($tmp_vhost_arr);
b1a6a5 1539
a7bdf8 1540         //* Add vhost for ipv4 IP with SSL
481c00 1541         $ssl_dir = $data['new']['document_root'].'/ssl';
T 1542         $domain = $data['new']['ssl_domain'];
1543         $key_file = $ssl_dir.'/'.$domain.'.key';
1544         $crt_file = $ssl_dir.'/'.$domain.'.crt';
b1a6a5 1545
a7bdf8 1546         if($data['new']['ssl_domain'] != '' && $data['new']['ssl'] == 'y' && @is_file($crt_file) && @is_file($key_file) && (@filesize($crt_file)>0)  && (@filesize($key_file)>0)) {
526b99 1547             $tmp_vhost_arr = array('ip_address' => $data['new']['ip_address'], 'ssl_enabled' => 1, 'port' => '443');
T 1548             if(count($rewrite_rules) > 0)  $tmp_vhost_arr = $tmp_vhost_arr + array('redirects' => $rewrite_rules);
cc6568 1549             $ipv4_ssl_alias_seo_redirects = $alias_seo_redirects;
H 1550             if(is_array($ipv4_ssl_alias_seo_redirects) && !empty($ipv4_ssl_alias_seo_redirects)){
1551                 for($i=0;$i<count($ipv4_ssl_alias_seo_redirects);$i++){
1552                     $ipv4_ssl_alias_seo_redirects[$i]['ssl_enabled'] = 1;
1553                 }
1554             }
1555             if(count($ipv4_ssl_alias_seo_redirects) > 0) $tmp_vhost_arr = $tmp_vhost_arr + array('alias_seo_redirects' => $ipv4_ssl_alias_seo_redirects);
526b99 1556             $vhosts[] = $tmp_vhost_arr;
cc6568 1557             unset($tmp_vhost_arr, $ipv4_ssl_alias_seo_redirects);
b1a6a5 1558             $app->log('Enable SSL for: '.$domain, LOGLEVEL_DEBUG);
bd68aa 1559         }
MC 1560
b1a6a5 1561         //* Add vhost for IPv6 IP
MC 1562         if($data['new']['ipv6_address'] != '') {
fbeb11 1563             //* rewrite ipv6 on mirrors
FS 1564             /* chang $conf to $web_config */
1565             if ($web_config['serverconfig']['web']['vhost_rewrite_v6'] == 'y') {
1566                 if (isset($web_config['serverconfig']['server']['v6_prefix']) && $web_config['serverconfig']['server']['v6_prefix'] <> '') {
1567                     $explode_v6prefix=explode(':', $web_config['serverconfig']['server']['v6_prefix']);
b1a6a5 1568                     $explode_v6=explode(':', $data['new']['ipv6_address']);
MC 1569
1570                     for ( $i = 0; $i <= count($explode_v6prefix)-3; $i++ ) {
1571                         $explode_v6[$i] = $explode_v6prefix[$i];
1572                     }
1573                     $data['new']['ipv6_address'] = implode(':', $explode_v6);
bd68aa 1574                 }
MC 1575             }
b1a6a5 1576
526b99 1577             $tmp_vhost_arr = array('ip_address' => '['.$data['new']['ipv6_address'].']', 'ssl_enabled' => 0, 'port' => 80);
T 1578             if(count($rewrite_rules) > 0)  $tmp_vhost_arr = $tmp_vhost_arr + array('redirects' => $rewrite_rules);
1579             if(count($alias_seo_redirects) > 0) $tmp_vhost_arr = $tmp_vhost_arr + array('alias_seo_redirects' => $alias_seo_redirects);
1580             $vhosts[] = $tmp_vhost_arr;
1581             unset($tmp_vhost_arr);
b1a6a5 1582
a7bdf8 1583             //* Add vhost for ipv6 IP with SSL
T 1584             if($data['new']['ssl_domain'] != '' && $data['new']['ssl'] == 'y' && @is_file($crt_file) && @is_file($key_file) && (@filesize($crt_file)>0)  && (@filesize($key_file)>0)) {
526b99 1585                 $tmp_vhost_arr = array('ip_address' => '['.$data['new']['ipv6_address'].']', 'ssl_enabled' => 1, 'port' => '443');
T 1586                 if(count($rewrite_rules) > 0)  $tmp_vhost_arr = $tmp_vhost_arr + array('redirects' => $rewrite_rules);
cc6568 1587                 $ipv6_ssl_alias_seo_redirects = $alias_seo_redirects;
H 1588                 if(is_array($ipv6_ssl_alias_seo_redirects) && !empty($ipv6_ssl_alias_seo_redirects)){
1589                     for($i=0;$i<count($ipv6_ssl_alias_seo_redirects);$i++){
1590                         $ipv6_ssl_alias_seo_redirects[$i]['ssl_enabled'] = 1;
1591                     }
1592                 }
1593                 if(count($ipv6_ssl_alias_seo_redirects) > 0) $tmp_vhost_arr = $tmp_vhost_arr + array('alias_seo_redirects' => $ipv6_ssl_alias_seo_redirects);
526b99 1594                 $vhosts[] = $tmp_vhost_arr;
cc6568 1595                 unset($tmp_vhost_arr, $ipv6_ssl_alias_seo_redirects);
b1a6a5 1596                 $app->log('Enable SSL for IPv6: '.$domain, LOGLEVEL_DEBUG);
a7bdf8 1597             }
T 1598         }
b1a6a5 1599
a7bdf8 1600         //* Set the vhost loop
b1a6a5 1601         $tpl->setLoop('vhosts', $vhosts);
MC 1602
7ed741 1603         //* Write vhost file
b1a6a5 1604         $app->system->file_put_contents($vhost_file, $tpl->grab());
MC 1605         $app->log('Writing the vhost file: '.$vhost_file, LOGLEVEL_DEBUG);
46c683 1606         unset($tpl);
ac933e 1607
V 1608         /*
1609          * maybe we have some webdav - user. If so, add them...
1610         */
fb3339 1611         $this->_patchVhostWebdav($vhost_file, $data['new']['document_root'] . '/webdav');
ac933e 1612
c6a89c 1613         //* Set the symlink to enable the vhost
T 1614         //* First we check if there is a old type of symlink and remove it
fb3339 1615         $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['new']['domain'].'.vhost');
c77103 1616         if(is_link($vhost_symlink)) $app->system->unlink($vhost_symlink);
b1a6a5 1617
c6a89c 1618         //* Remove old or changed symlinks
T 1619         if($data['new']['subdomain'] != $data['old']['subdomain'] or $data['new']['active'] == 'n') {
1620             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['new']['domain'].'.vhost');
1621             if(is_link($vhost_symlink)) {
c77103 1622                 $app->system->unlink($vhost_symlink);
b1a6a5 1623                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
c6a89c 1624             }
T 1625             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['new']['domain'].'.vhost');
1626             if(is_link($vhost_symlink)) {
c77103 1627                 $app->system->unlink($vhost_symlink);
b1a6a5 1628                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
c6a89c 1629             }
T 1630         }
b1a6a5 1631
c6a89c 1632         //* New symlink
T 1633         if($data['new']['subdomain'] == '*') {
1634             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['new']['domain'].'.vhost');
1635         } else {
1636             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['new']['domain'].'.vhost');
1637         }
fb3339 1638         if($data['new']['active'] == 'y' && !is_link($vhost_symlink)) {
b1a6a5 1639             symlink($vhost_file, $vhost_symlink);
MC 1640             $app->log('Creating symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
46c683 1641         }
ac933e 1642
46c683 1643         // remove old symlink and vhost file, if domain name of the site has changed
fb3339 1644         if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
c6a89c 1645             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['old']['domain'].'.vhost');
T 1646             if(is_link($vhost_symlink)) {
c77103 1647                 $app->system->unlink($vhost_symlink);
b1a6a5 1648                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
c6a89c 1649             }
T 1650             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['old']['domain'].'.vhost');
1651             if(is_link($vhost_symlink)) {
c77103 1652                 $app->system->unlink($vhost_symlink);
b1a6a5 1653                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
c6a89c 1654             }
8cf78b 1655             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
T 1656             if(is_link($vhost_symlink)) {
c77103 1657                 $app->system->unlink($vhost_symlink);
b1a6a5 1658                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
8cf78b 1659             }
fb3339 1660             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
c77103 1661             $app->system->unlink($vhost_file);
b1a6a5 1662             $app->log('Removing file: '.$vhost_file, LOGLEVEL_DEBUG);
46c683 1663         }
ac933e 1664
46c683 1665         //* Create .htaccess and .htpasswd file for website statistics
cc6568 1666         //if(!is_file($data['new']['document_root'].'/' . $web_folder . '/stats/.htaccess') or $data['old']['document_root'] != $data['new']['document_root']) {
H 1667         if(!is_dir($data['new']['document_root'].'/' . $web_folder . '/stats')) $app->system->mkdir($data['new']['document_root'].'/' . $web_folder . '/stats');
1668         $ht_file = "AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$data['new']['document_root']."/web/stats/.htpasswd_stats\nrequire valid-user";
b1a6a5 1669         $app->system->file_put_contents($data['new']['document_root'].'/' . $web_folder . '/stats/.htaccess', $ht_file);
MC 1670         $app->system->chmod($data['new']['document_root'].'/' . $web_folder . '/stats/.htaccess', 0755);
cc6568 1671         unset($ht_file);
H 1672         //}
ac933e 1673
bfcdef 1674         if(!is_file($data['new']['document_root'].'/web/stats/.htpasswd_stats') || $data['new']['stats_password'] != $data['old']['stats_password']) {
fb3339 1675             if(trim($data['new']['stats_password']) != '') {
J 1676                 $htp_file = 'admin:'.trim($data['new']['stats_password']);
b1a6a5 1677                 $app->system->web_folder_protection($data['new']['document_root'], false);
MC 1678                 $app->system->file_put_contents($data['new']['document_root'].'/web/stats/.htpasswd_stats', $htp_file);
1679                 $app->system->web_folder_protection($data['new']['document_root'], true);
1680                 $app->system->chmod($data['new']['document_root'].'/web/stats/.htpasswd_stats', 0755);
46c683 1681                 unset($htp_file);
T 1682             }
1683         }
b1a6a5 1684
58c210 1685         //* Create awstats configuration
511ba5 1686         if($data['new']['stats_type'] == 'awstats' && ($data['new']['type'] == 'vhost' || $data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias')) {
b1a6a5 1687             $this->awstats_update($data, $web_config);
58c210 1688         }
b1a6a5 1689
MC 1690         $this->php_fpm_pool_update($data, $web_config, $pool_dir, $pool_name, $socket_dir);
c59632 1691         $this->hhvm_update($data, $web_config);
b1a6a5 1692
7ed741 1693         if($web_config['check_apache_config'] == 'y') {
T 1694             //* Test if apache starts with the new configuration file
b1a6a5 1695             $apache_online_status_before_restart = $this->_checkTcp('localhost', 80);
MC 1696             $app->log('Apache status is: '.($apache_online_status_before_restart === true? 'running' : 'down'), LOGLEVEL_DEBUG);
ac933e 1697
b1a6a5 1698             $retval = $app->services->restartService('httpd', 'restart'); // $retval['retval'] is 0 on success and > 0 on failure
MC 1699             $app->log('Apache restart return value is: '.$retval['retval'], LOGLEVEL_DEBUG);
1700
9f56bd 1701             // wait a few seconds, before we test the apache status again
bfcdef 1702             $apache_online_status_after_restart = false;
9f56bd 1703             sleep(2);
bfcdef 1704             for($i = 0; $i < 5; $i++) {
b1a6a5 1705                 $apache_online_status_after_restart = $this->_checkTcp('localhost', 80);
bfcdef 1706                 if($apache_online_status_after_restart) break;
T 1707                 sleep(1);
1708             }
7ed741 1709             //* Check if apache restarted successfully if it was online before
b1a6a5 1710             $app->log('Apache online status after restart is: '.($apache_online_status_after_restart === true? 'running' : 'down'), LOGLEVEL_DEBUG);
615a0a 1711             if($apache_online_status_before_restart && !$apache_online_status_after_restart || $retval['retval'] > 0) {
b1a6a5 1712                 $app->log('Apache did not restart after the configuration change for website '.$data['new']['domain'].'. Reverting the configuration. Saved non-working config as '.$vhost_file.'.err', LOGLEVEL_WARN);
615a0a 1713                 if(is_array($retval['output']) && !empty($retval['output'])){
b1a6a5 1714                     $app->log('Reason for Apache restart failure: '.implode("\n", $retval['output']), LOGLEVEL_WARN);
7b47c0 1715                     $app->dbmaster->datalogError(implode("\n", $retval['output']));
615a0a 1716                 } else {
T 1717                     // if no output is given, check again
1718                     $webserver_binary = '';
7b47c0 1719                     exec('which apache2ctl', $webserver_check_output, $webserver_check_retval);
615a0a 1720                     if($webserver_check_retval == 0){
7b47c0 1721                         $webserver_binary = 'apache2ctl';
615a0a 1722                     } else {
T 1723                         unset($webserver_check_output, $webserver_check_retval);
7b47c0 1724                         exec('which apache2', $webserver_check_output, $webserver_check_retval);
615a0a 1725                         if($webserver_check_retval == 0){
7b47c0 1726                             $webserver_binary = 'apache2';
615a0a 1727                         } else {
T 1728                             unset($webserver_check_output, $webserver_check_retval);
7b47c0 1729                             exec('which httpd2', $webserver_check_output, $webserver_check_retval);
615a0a 1730                             if($webserver_check_retval == 0){
7b47c0 1731                                 $webserver_binary = 'httpd2';
615a0a 1732                             } else {
T 1733                                 unset($webserver_check_output, $webserver_check_retval);
7b47c0 1734                                 exec('which httpd', $webserver_check_output, $webserver_check_retval);
615a0a 1735                                 if($webserver_check_retval == 0){
7b47c0 1736                                     $webserver_binary = 'httpd';
T 1737                                 } else {
1738                                     unset($webserver_check_output, $webserver_check_retval);
1739                                     exec('which apache', $webserver_check_output, $webserver_check_retval);
1740                                     if($webserver_check_retval == 0){
1741                                         $webserver_binary = 'apache';
1742                                     }
615a0a 1743                                 }
T 1744                             }
1745                         }
1746                     }
1747                     if($webserver_binary != ''){
1748                         exec($webserver_binary.' -t 2>&1', $tmp_output, $tmp_retval);
7b47c0 1749                         if($tmp_retval > 0 && is_array($tmp_output) && !empty($tmp_output)){
b1a6a5 1750                             $app->log('Reason for Apache restart failure: '.implode("\n", $tmp_output), LOGLEVEL_WARN);
7b47c0 1751                             $app->dbmaster->datalogError(implode("\n", $tmp_output));
T 1752                         }
615a0a 1753                         unset($tmp_output, $tmp_retval);
T 1754                     }
1755                 }
b1a6a5 1756                 $app->system->copy($vhost_file, $vhost_file.'.err');
8cf78b 1757                 if(is_file($vhost_file.'~')) {
T 1758                     //* Copy back the last backup file
b1a6a5 1759                     $app->system->copy($vhost_file.'~', $vhost_file);
8cf78b 1760                 } else {
T 1761                     //* There is no backup file, so we create a empty vhost file with a warning message inside
b1a6a5 1762                     $app->system->file_put_contents($vhost_file, "# Apache did not start after modifying this vhost file.\n# Please check file $vhost_file.err for syntax errors.");
8cf78b 1763                 }
481c00 1764                 if($this->ssl_certificate_changed === true) {
T 1765
1766                     $ssl_dir = $data['new']['document_root'].'/ssl';
1767                     $domain = $data['new']['ssl_domain'];
1768                     $key_file = $ssl_dir.'/'.$domain.'.key.org';
1769                     $key_file2 = $ssl_dir.'/'.$domain.'.key';
1770                     $csr_file = $ssl_dir.'/'.$domain.'.csr';
1771                     $crt_file = $ssl_dir.'/'.$domain.'.crt';
1772                     $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
b1a6a5 1773
481c00 1774                     //* Backup the files that might have caused the error
43b345 1775                     if(is_file($key_file)){
b1a6a5 1776                         $app->system->copy($key_file, $key_file.'.err');
MC 1777                         $app->system->chmod($key_file.'.err', 0400);
43b345 1778                     }
T 1779                     if(is_file($key_file2)){
b1a6a5 1780                         $app->system->copy($key_file2, $key_file2.'.err');
MC 1781                         $app->system->chmod($key_file2.'.err', 0400);
43b345 1782                     }
b1a6a5 1783                     if(is_file($csr_file)) $app->system->copy($csr_file, $csr_file.'.err');
MC 1784                     if(is_file($crt_file)) $app->system->copy($crt_file, $crt_file.'.err');
1785                     if(is_file($bundle_file)) $app->system->copy($bundle_file, $bundle_file.'.err');
1786
481c00 1787                     //* Restore the ~ backup files
b1a6a5 1788                     if(is_file($key_file.'~')) $app->system->copy($key_file.'~', $key_file);
MC 1789                     if(is_file($key_file2.'~')) $app->system->copy($key_file2.'~', $key_file2);
1790                     if(is_file($crt_file.'~')) $app->system->copy($crt_file.'~', $crt_file);
1791                     if(is_file($csr_file.'~')) $app->system->copy($csr_file.'~', $csr_file);
1792                     if(is_file($bundle_file.'~')) $app->system->copy($bundle_file.'~', $bundle_file);
1793
1794                     $app->log('Apache did not restart after the configuration change for website '.$data['new']['domain'].' Reverting the SSL configuration. Saved non-working SSL files with .err extension.', LOGLEVEL_WARN);
481c00 1795                 }
b1a6a5 1796
MC 1797                 $app->services->restartService('httpd', 'restart');
7ed741 1798             }
c82dc7 1799         } else {
7ed741 1800             //* We do not check the apache config after changes (is faster)
T 1801             if($apache_chrooted) {
b1a6a5 1802                 $app->services->restartServiceDelayed('httpd', 'restart');
7ed741 1803             } else {
T 1804                 // request a httpd reload when all records have been processed
b1a6a5 1805                 $app->services->restartServiceDelayed('httpd', 'reload');
7ed741 1806             }
c82dc7 1807         }
b1a6a5 1808
MC 1809         //* The vhost is written and apache has been restarted, so we
481c00 1810         // can reset the ssl changed var to false and cleanup some files
T 1811         $this->ssl_certificate_changed = false;
b1a6a5 1812
481c00 1813         $ssl_dir = $data['new']['document_root'].'/ssl';
T 1814         $domain = $data['new']['ssl_domain'];
1815         $key_file = $ssl_dir.'/'.$domain.'.key.org';
1816         $key_file2 = $ssl_dir.'/'.$domain.'.key';
1817         $csr_file = $ssl_dir.'/'.$domain.'.csr';
1818         $crt_file = $ssl_dir.'/'.$domain.'.crt';
1819         $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
b1a6a5 1820
c77103 1821         if(@is_file($key_file.'~')) $app->system->unlink($key_file.'~');
T 1822         if(@is_file($key2_file.'~')) $app->system->unlink($key2_file.'~');
1823         if(@is_file($crt_file.'~')) $app->system->unlink($crt_file.'~');
1824         if(@is_file($csr_file.'~')) $app->system->unlink($csr_file.'~');
1825         if(@is_file($bundle_file.'~')) $app->system->unlink($bundle_file.'~');
b1a6a5 1826
7ed741 1827         // Remove the backup copy of the config file.
c77103 1828         if(@is_file($vhost_file.'~')) $app->system->unlink($vhost_file.'~');
ac933e 1829
da1a7c 1830         //* Unset action to clean it for next processed vhost.
T 1831         $this->action = '';
46c683 1832     }
ac933e 1833
b1a6a5 1834     function delete($event_name, $data) {
46c683 1835         global $app, $conf;
ac933e 1836
46c683 1837         // load the server configuration options
fb3339 1838         $app->uses('getconf');
c09f04 1839         $app->uses('system');
fb3339 1840         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
cc6568 1841         $fastcgi_config = $app->getconf->get_server_config($conf['server_id'], 'fastcgi');
b1a6a5 1842
511ba5 1843         if($data['old']['type'] == 'vhost' || $data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') $app->system->web_folder_protection($data['old']['document_root'], false);
ac933e 1844
2bbc4c 1845         //* Check if this is a chrooted setup
4b72c5 1846         if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
2bbc4c 1847             $apache_chrooted = true;
T 1848         } else {
1849             $apache_chrooted = false;
1850         }
b1a6a5 1851
fea5e7 1852         //* Remove the mounts
T 1853         $log_folder = 'log';
b1a6a5 1854         $web_folder = '';
511ba5 1855         if($data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') {
2af58c 1856             $tmp = $app->db->queryOneRecord('SELECT `domain`,`document_root` FROM web_domain WHERE domain_id = ?', $data['old']['parent_domain_id']);
526b99 1857             if($tmp['domain'] != ''){
T 1858                 $subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $data['old']['domain']);
1859             } else {
1860                 // get log folder from /etc/fstab
1861                 /*
1862                 $bind_mounts = $app->system->file_get_contents('/etc/fstab');
1863                 $bind_mount_lines = explode("\n", $bind_mounts);
1864                 if(is_array($bind_mount_lines) && !empty($bind_mount_lines)){
1865                     foreach($bind_mount_lines as $bind_mount_line){
1866                         $bind_mount_line = preg_replace('/\s+/', ' ', $bind_mount_line);
1867                         $bind_mount_parts = explode(' ', $bind_mount_line);
1868                         if(is_array($bind_mount_parts) && !empty($bind_mount_parts)){
1869                             if($bind_mount_parts[0] == '/var/log/ispconfig/httpd/'.$data['old']['domain'] && $bind_mount_parts[2] == 'none' && strpos($bind_mount_parts[3], 'bind') !== false){
1870                                 $subdomain_host = str_replace($data['old']['document_root'].'/log/', '', $bind_mount_parts[1]);
1871                             }
1872                         }
1873                     }
1874                 }
1875                 */
1876                 // we are deleting the parent domain, so we can delete everything in the log directory
1877                 $subdomain_hosts = array();
b1a6a5 1878                 $files = array_diff(scandir($data['old']['document_root'].'/'.$log_folder), array('.', '..'));
526b99 1879                 if(is_array($files) && !empty($files)){
T 1880                     foreach($files as $file){
1881                         if(is_dir($data['old']['document_root'].'/'.$log_folder.'/'.$file)){
1882                             $subdomain_hosts[] = $file;
1883                         }
1884                     }
1885                 }
1886             }
b1a6a5 1887             if(is_array($subdomain_hosts) && !empty($subdomain_hosts)){
526b99 1888                 $log_folders = array();
T 1889                 foreach($subdomain_hosts as $subdomain_host){
1890                     $log_folders[] = $log_folder.'/'.$subdomain_host;
1891                 }
1892             } else {
1893                 if($subdomain_host == '') $subdomain_host = 'web'.$data['old']['domain_id'];
1894                 $log_folder .= '/' . $subdomain_host;
1895             }
1896             $web_folder = $data['old']['web_folder'];
b1a6a5 1897             unset($tmp);
526b99 1898             unset($subdomain_hosts);
3cde19 1899         }
b1a6a5 1900
511ba5 1901         if($data['old']['type'] == 'vhost' || $data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias'){
526b99 1902             if(is_array($log_folders) && !empty($log_folders)){
T 1903                 foreach($log_folders as $log_folder){
cc6568 1904                     //if($app->system->is_mounted($data['old']['document_root'].'/'.$log_folder)) exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder));
a9b325 1905                     //exec('fuser -km '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
cc6568 1906                     exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
526b99 1907                 }
T 1908             } else {
cc6568 1909                 //if($app->system->is_mounted($data['old']['document_root'].'/'.$log_folder)) exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder));
a9b325 1910                 //exec('fuser -km '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
cc6568 1911                 exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
526b99 1912             }
T 1913         }
b1a6a5 1914
fea5e7 1915         //* remove mountpoint from fstab
526b99 1916         if(is_array($log_folders) && !empty($log_folders)){
T 1917             foreach($log_folders as $log_folder){
1918                 $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$log_folder.'    none    bind';
b1a6a5 1919                 $app->system->removeLine('/etc/fstab', $fstab_line);
526b99 1920             }
T 1921         } else {
1922             $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$log_folder.'    none    bind';
b1a6a5 1923             $app->system->removeLine('/etc/fstab', $fstab_line);
526b99 1924         }
T 1925         unset($log_folders);
ac933e 1926
511ba5 1927         if($data['old']['type'] != 'vhost' && $data['old']['type'] != 'vhostsubdomain' && $data['old']['type'] != 'vhostalias' && $data['old']['parent_domain_id'] > 0) {
46c683 1928             //* This is a alias domain or subdomain, so we have to update the website instead
fb3339 1929             $parent_domain_id = intval($data['old']['parent_domain_id']);
2af58c 1930             $tmp = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ? AND active = 'y'", $parent_domain_id);
fb3339 1931             $data['new'] = $tmp;
J 1932             $data['old'] = $tmp;
46c683 1933             $this->action = 'update';
T 1934             // just run the update function
b1a6a5 1935             $this->update($event_name, $data);
ac933e 1936
46c683 1937         } else {
T 1938             //* This is a website
1939             // Deleting the vhost file, symlink and the data directory
fb3339 1940             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
b1a6a5 1941
8ab3cd 1942             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
T 1943             if(is_link($vhost_symlink)){
c77103 1944                 $app->system->unlink($vhost_symlink);
b1a6a5 1945                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
8ab3cd 1946             }
T 1947             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['old']['domain'].'.vhost');
1948             if(is_link($vhost_symlink)){
c77103 1949                 $app->system->unlink($vhost_symlink);
b1a6a5 1950                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
8ab3cd 1951             }
T 1952             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['old']['domain'].'.vhost');
1953             if(is_link($vhost_symlink)){
c77103 1954                 $app->system->unlink($vhost_symlink);
b1a6a5 1955                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
8ab3cd 1956             }
b1a6a5 1957
c77103 1958             $app->system->unlink($vhost_file);
b1a6a5 1959             $app->log('Removing vhost file: '.$vhost_file, LOGLEVEL_DEBUG);
ac933e 1960
511ba5 1961             if($data['old']['type'] == 'vhost' || $data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') {
b1a6a5 1962                 $docroot = escapeshellcmd($data['old']['document_root']);
MC 1963                 if($docroot != '' && !stristr($docroot, '..')) {
1964                     if($data['old']['type'] == 'vhost') {
1965                         // this is a vhost - we delete everything in here.
1966                         exec('rm -rf '.$docroot);
1967                     } elseif(!stristr($data['old']['web_folder'], '..')) {
1968                         // this is a vhost subdomain
1969                         // IMPORTANT: do some folder checks before we delete this!
1970                         $do_delete = true;
1971                         $delete_folder = preg_replace('/[\/]{2,}/', '/', $web_folder); // replace / occuring multiple times
1972                         if(substr($delete_folder, 0, 1) === '/') $delete_folder = substr($delete_folder, 1);
1973                         if(substr($delete_folder, -1) === '/') $delete_folder = substr($delete_folder, 0, -1);
46c683 1974
b1a6a5 1975                         $path_elements = explode('/', $delete_folder);
46c683 1976
b1a6a5 1977                         if($path_elements[0] == 'web' || $path_elements[0] === '') {
MC 1978                             // paths beginning with /web should NEVER EVER be deleted, empty paths should NEVER occur - but for safety reasons we check it here!
1979                             // we use strict check as otherwise directories named '0' may not be deleted
1980                             $do_delete = false;
1981                         } else {
511ba5 1982                             // read all vhost subdomains and alias with same parent domain
b1a6a5 1983                             $used_paths = array();
2af58c 1984                             $tmp = $app->db->queryAllRecords("SELECT `web_folder` FROM web_domain WHERE (type = 'vhostsubdomain' OR type = 'vhostalias') AND parent_domain_id = ? AND domain_id != ?", $data['old']['parent_domain_id'], $data['old']['domain_id']);
b1a6a5 1985                             foreach($tmp as $tmprec) {
MC 1986                                 // we normalize the folder entries because we need to compare them
1987                                 $tmp_folder = preg_replace('/[\/]{2,}/', '/', $tmprec['web_folder']); // replace / occuring multiple times
1988                                 if(substr($tmp_folder, 0, 1) === '/') $tmp_folder = substr($tmp_folder, 1);
1989                                 if(substr($tmp_folder, -1) === '/') $tmp_folder = substr($tmp_folder, 0, -1);
ac933e 1990
b1a6a5 1991                                 // add this path and it's parent paths to used_paths array
MC 1992                                 while(strpos($tmp_folder, '/') !== false) {
1993                                     if(in_array($tmp_folder, $used_paths) == false) $used_paths[] = $tmp_folder;
1994                                     $tmp_folder = substr($tmp_folder, 0, strrpos($tmp_folder, '/'));
1995                                 }
1996                                 if(in_array($tmp_folder, $used_paths) == false) $used_paths[] = $tmp_folder;
1997                             }
1998                             unset($tmp);
1999
2000                             // loop and check if the path is still used and stop at first used one
2001                             // set do_delete to false so nothing gets deleted if the web_folder itself is still used
2002                             $do_delete = false;
2003                             while(count($path_elements) > 0) {
2004                                 $tmp_folder = implode('/', $path_elements);
2005                                 if(in_array($tmp_folder, $used_paths) == true) break;
2006
2007                                 // this path is not used - set it as path to delete, strip the last element from the array and set do_delete to true
2008                                 $delete_folder = $tmp_folder;
2009                                 $do_delete = true;
2010                                 array_pop($path_elements);
2011                             }
2012                             unset($tmp_folder);
2013                             unset($used_paths);
2014                         }
2015
2016                         if($do_delete === true && $delete_folder !== '') exec('rm -rf '.$docroot.'/'.$delete_folder);
2017
2018                         unset($delete_folder);
2019                         unset($path_elements);
2020                     }
2021                 }
2022
2023                 //remove the php fastgi starter script if available
2024                 if ($data['old']['php'] == 'fast-cgi') {
2025                     $fastcgi_starter_path = str_replace('[system_user]', $data['old']['system_user'], $fastcgi_config['fastcgi_starter_path']);
2026                     if($data['old']['type'] == 'vhost') {
2027                         if (is_dir($fastcgi_starter_path)) {
2028                             exec('rm -rf '.$fastcgi_starter_path);
2029                         }
2030                     } else {
2031                         $fcgi_starter_script = $fastcgi_starter_path.$fastcgi_config['fastcgi_starter_script'].'_web'.$data['old']['domain_id'];
2032                         if (file_exists($fcgi_starter_script)) {
2033                             exec('rm -f '.$fcgi_starter_script);
2034                         }
2035                     }
2036                 }
2037
2038                 // remove PHP-FPM pool
2039                 if ($data['old']['php'] == 'php-fpm') {
2040                     $this->php_fpm_pool_delete($data, $web_config);
c59632 2041                 } elseif($data['old']['php'] == 'hhvm') {
MC 2042                     $this->hhvm_update($data, $web_config);
b1a6a5 2043                 }
MC 2044
2045                 //remove the php cgi starter script if available
2046                 if ($data['old']['php'] == 'cgi') {
2047                     // TODO: fetch the date from the server-settings
2048                     $web_config['cgi_starter_path'] = $web_config['website_basedir'].'/php-cgi-scripts/[system_user]/';
2049
2050                     $cgi_starter_path = str_replace('[system_user]', $data['old']['system_user'], $web_config['cgi_starter_path']);
2051                     if($data['old']['type'] == 'vhost') {
2052                         if (is_dir($cgi_starter_path)) {
2053                             exec('rm -rf '.$cgi_starter_path);
2054                         }
2055                     } else {
2056                         $cgi_starter_script = $cgi_starter_path.'php-cgi-starter_web'.$data['old']['domain_id'];
2057                         if (file_exists($cgi_starter_script)) {
2058                             exec('rm -f '.$cgi_starter_script);
2059                         }
2060                     }
2061                 }
2062
2063                 $app->log('Removing website: '.$docroot, LOGLEVEL_DEBUG);
2064
2065                 // Delete the symlinks for the sites
2af58c 2066                 $client = $app->db->queryOneRecord('SELECT client_id FROM sys_group WHERE sys_group.groupid = ?', $data['old']['sys_groupid']);
b1a6a5 2067                 $client_id = intval($client['client_id']);
MC 2068                 unset($client);
2069                 $tmp_symlinks_array = explode(':', $web_config['website_symlinks']);
2070                 if(is_array($tmp_symlinks_array)) {
2071                     foreach($tmp_symlinks_array as $tmp_symlink) {
2072                         $tmp_symlink = str_replace('[client_id]', $client_id, $tmp_symlink);
2073                         $tmp_symlink = str_replace('[website_domain]', $data['old']['domain'], $tmp_symlink);
2074                         // Remove trailing slash
2075                         if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
2076                         // delete the symlink
2077                         if(is_link($tmp_symlink)) {
2078                             $app->system->unlink($tmp_symlink);
2079                             $app->log('Removing symlink: '.$tmp_symlink, LOGLEVEL_DEBUG);
2080                         }
2081                     }
2082                 }
2083                 // end removing symlinks
3cde19 2084             }
b1a6a5 2085
MC 2086             // Delete the log file directory
2087             $vhost_logfile_dir = escapeshellcmd('/var/log/ispconfig/httpd/'.$data['old']['domain']);
2088             if($data['old']['domain'] != '' && !stristr($vhost_logfile_dir, '..')) exec('rm -rf '.$vhost_logfile_dir);
2089             $app->log('Removing website logfile directory: '.$vhost_logfile_dir, LOGLEVEL_DEBUG);
2090
2091             if($data['old']['type'] == 'vhost') {
2092                 //delete the web user
2093                 $command = 'killall -u '.escapeshellcmd($data['old']['system_user']).' ; userdel';
2094                 $command .= ' '.escapeshellcmd($data['old']['system_user']);
2095                 exec($command);
2096                 if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' '.$command);
2097
2098             }
2099
2100             //* Remove the awstats configuration file
2101             if($data['old']['stats_type'] == 'awstats') {
2102                 $this->awstats_delete($data, $web_config);
2103             }
2104
511ba5 2105             if($data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') {
b1a6a5 2106                 $app->system->web_folder_protection($parent_web_document_root, true);
MC 2107             }
2108
8ab3cd 2109             if($apache_chrooted) {
b1a6a5 2110                 $app->services->restartServiceDelayed('httpd', 'restart');
8ab3cd 2111             } else {
T 2112                 // request a httpd reload when all records have been processed
b1a6a5 2113                 $app->services->restartServiceDelayed('httpd', 'reload');
58c210 2114             }
ac933e 2115
0f89bd 2116             //* Delete the web-backups
69b1bc 2117             if($data['old']['type'] == 'vhost') {
FS 2118                 $server_config = $app->getconf->get_server_config($conf['server_id'], 'server');
2119                 $backup_dir = $server_config['backup_dir'];
2120                 $mount_backup = true;
a81238 2121                 if($server_config['backup_dir'] != '' && $server_config['backup_delete'] == 'y') {
990ca8 2122                     //* mount backup directory, if necessary
FS 2123                     if( $server_config['backup_dir_is_mount'] == 'y' && !$app->system->mount_backup_dir($backup_dir) ) $mount_backup = false;
2124
69b1bc 2125                     if($mount_backup){
FS 2126                         $web_backup_dir = $backup_dir.'/web'.$data_old['domain_id'];
2127                         //** do not use rm -rf $web_backup_dir because database(s) may exits
2128                         exec(escapeshellcmd('rm -f '.$web_backup_dir.'/web'.$data_old['domain_id'].'_').'*');
2129                         //* cleanup database
990ca8 2130                         $sql = "DELETE FROM web_backup WHERE server_id = ? AND parent_domain_id = ? AND filename LIKE ?";
FS 2131                         $app->db->query($sql, $conf['server_id'], $data_old['domain_id'], "web".$data_old['domain_id']."_%");
2132                         if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql, $conf['server_id'], $data_old['domain_id'], "web".$data_old['domain_id']."_%");
0f89bd 2133
FS 2134                         $app->log('Deleted the web backup files', LOGLEVEL_DEBUG);
69b1bc 2135                     }
FS 2136                 }
2137             }
46c683 2138         }
b1a6a5 2139         if($data['old']['type'] != 'vhost') $app->system->web_folder_protection($data['old']['document_root'], true);
46c683 2140     }
ac933e 2141
46c683 2142     //* This function is called when a IP on the server is inserted, updated or deleted
b1a6a5 2143     function server_ip($event_name, $data) {
46c683 2144         global $app, $conf;
ac933e 2145
46c683 2146         // load the server configuration options
fb3339 2147         $app->uses('getconf');
J 2148         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
ac933e 2149
46c683 2150         $app->load('tpl');
ac933e 2151
46c683 2152         $tpl = new tpl();
fb3339 2153         $tpl->newTemplate('apache_ispconfig.conf.master');
8133de 2154         $tpl->setVar('apache_version', $app->system->getapacheversion());
2af58c 2155         $records = $app->db->queryAllRecords("SELECT * FROM server_ip WHERE server_id = ? AND virtualhost = 'y'", $conf['server_id']);
b1a6a5 2156
a2156e 2157         $records_out= array();
T 2158         if(is_array($records)) {
2159             foreach($records as $rec) {
2160                 if($rec['ip_type'] == 'IPv6') {
2161                     $ip_address = '['.$rec['ip_address'].']';
2162                 } else {
2163                     $ip_address = $rec['ip_address'];
2164                 }
b1a6a5 2165                 $ports = explode(',', $rec['virtualhost_port']);
a2156e 2166                 if(is_array($ports)) {
T 2167                     foreach($ports as $port) {
2168                         $port = intval($port);
2169                         if($port > 0 && $port < 65536 && $ip_address != '') {
2170                             $records_out[] = array('ip_address' => $ip_address, 'port' => $port);
2171                         }
2172                     }
2173                 }
2174             }
2175         }
b1a6a5 2176
MC 2177
a2156e 2178         if(count($records_out) > 0) {
b1a6a5 2179             $tpl->setLoop('ip_adresses', $records_out);
46c683 2180         }
ac933e 2181
fb3339 2182         $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/ispconfig.conf');
b1a6a5 2183         $app->system->file_put_contents($vhost_file, $tpl->grab());
MC 2184         $app->log('Writing the conf file: '.$vhost_file, LOGLEVEL_DEBUG);
46c683 2185         unset($tpl);
ac933e 2186
46c683 2187     }
b1a6a5 2188
524077 2189     //* Create or update the .htaccess folder protection
b1a6a5 2190     function web_folder_user($event_name, $data) {
524077 2191         global $app, $conf;
c69439 2192
524077 2193         $app->uses('system');
b1a6a5 2194
524077 2195         if($event_name == 'web_folder_user_delete') {
T 2196             $folder_id = $data['old']['web_folder_id'];
2197         } else {
2198             $folder_id = $data['new']['web_folder_id'];
2199         }
b1a6a5 2200
2af58c 2201         $folder = $app->db->queryOneRecord("SELECT * FROM web_folder WHERE web_folder_id = ?", $folder_id);
MC 2202         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $folder['parent_domain_id']);
b1a6a5 2203
524077 2204         if(!is_array($folder) or !is_array($website)) {
b1a6a5 2205             $app->log('Not able to retrieve folder or website record.', LOGLEVEL_DEBUG);
524077 2206             return false;
T 2207         }
b1a6a5 2208
MC 2209         $web_folder = 'web';
511ba5 2210         if($website['type'] == 'vhostsubdomain' || $website['type'] == 'vhostalias') $web_folder = $website['web_folder'];
b1a6a5 2211
524077 2212         //* Get the folder path.
b1a6a5 2213         if(substr($folder['path'], 0, 1) == '/') $folder['path'] = substr($folder['path'], 1);
MC 2214         if(substr($folder['path'], -1) == '/') $folder['path'] = substr($folder['path'], 0, -1);
6fb93d 2215         $folder_path = escapeshellcmd($website['document_root'].'/' . $web_folder . '/'.$folder['path']);
b1a6a5 2216         if(substr($folder_path, -1) != '/') $folder_path .= '/';
MC 2217
524077 2218         //* Check if the resulting path is inside the docroot
b1a6a5 2219         if(stristr($folder_path, '..') || stristr($folder_path, './') || stristr($folder_path, '\\')) {
MC 2220             $app->log('Folder path "'.$folder_path.'" contains .. or ./.', LOGLEVEL_DEBUG);
524077 2221             return false;
T 2222         }
b1a6a5 2223
524077 2224         //* Create the folder path, if it does not exist
8cf78b 2225         if(!is_dir($folder_path)) {
dbae22 2226             $app->system->mkdirpath($folder_path, 0755, $website['system_user'], $website['system_group']);
8cf78b 2227         }
b1a6a5 2228
524077 2229         //* Create empty .htpasswd file, if it does not exist
T 2230         if(!is_file($folder_path.'.htpasswd')) {
4bd960 2231             $app->system->touch($folder_path.'.htpasswd');
51910d 2232             $app->system->chmod($folder_path.'.htpasswd', 0751);
b1a6a5 2233             $app->system->chown($folder_path.'.htpasswd', $website['system_user']);
MC 2234             $app->system->chgrp($folder_path.'.htpasswd', $website['system_group']);
2235             $app->log('Created file '.$folder_path.'.htpasswd', LOGLEVEL_DEBUG);
524077 2236         }
b1a6a5 2237
8ab3cd 2238         if(($data['new']['username'] != $data['old']['username'] || $data['new']['active'] == 'n') && $data['old']['username'] != '') {
b1a6a5 2239             $app->system->removeLine($folder_path.'.htpasswd', $data['old']['username'].':');
MC 2240             $app->log('Removed user: '.$data['old']['username'], LOGLEVEL_DEBUG);
c69439 2241         }
b1a6a5 2242
524077 2243         //* Add or remove the user from .htpasswd file
T 2244         if($event_name == 'web_folder_user_delete') {
b1a6a5 2245             $app->system->removeLine($folder_path.'.htpasswd', $data['old']['username'].':');
MC 2246             $app->log('Removed user: '.$data['old']['username'], LOGLEVEL_DEBUG);
524077 2247         } else {
c69439 2248             if($data['new']['active'] == 'y') {
b1a6a5 2249                 $app->system->replaceLine($folder_path.'.htpasswd', $data['new']['username'].':', $data['new']['username'].':'.$data['new']['password'], 0, 1);
MC 2250                 $app->log('Added or updated user: '.$data['new']['username'], LOGLEVEL_DEBUG);
c69439 2251             }
524077 2252         }
b1a6a5 2253
MC 2254
524077 2255         //* Create the .htaccess file
8ab3cd 2256         //if(!is_file($folder_path.'.htaccess')) {
b1a6a5 2257         $begin_marker = '### ISPConfig folder protection begin ###';
MC 2258         $end_marker = "### ISPConfig folder protection end ###\n\n";
2259         $ht_file = $begin_marker."\nAuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$folder_path.".htpasswd\nrequire valid-user\n".$end_marker;
2260
2261         if(file_exists($folder_path.'.htaccess')) {
2262             $old_content = $app->system->file_get_contents($folder_path.'.htaccess');
2263
2264             if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $old_content, $matches)) {
2265                 $ht_file = str_replace($matches[0], $ht_file, $old_content);
2266             } else {
2267                 $ht_file .= $old_content;
2268             }
2269         }
2270         unset($old_content);
2271
2272         $app->system->file_put_contents($folder_path.'.htaccess', $ht_file);
51910d 2273         $app->system->chmod($folder_path.'.htaccess', 0751);
b1a6a5 2274         $app->system->chown($folder_path.'.htaccess', $website['system_user']);
MC 2275         $app->system->chgrp($folder_path.'.htaccess', $website['system_group']);
2276         $app->log('Created/modified file '.$folder_path.'.htaccess', LOGLEVEL_DEBUG);
8ab3cd 2277         //}
b1a6a5 2278
524077 2279     }
b1a6a5 2280
524077 2281     //* Remove .htaccess and .htpasswd file, when folder protection is removed
b1a6a5 2282     function web_folder_delete($event_name, $data) {
524077 2283         global $app, $conf;
b1a6a5 2284
524077 2285         $folder_id = $data['old']['web_folder_id'];
b1a6a5 2286
8ab3cd 2287         $folder = $data['old'];
2af58c 2288         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $folder['parent_domain_id']);
b1a6a5 2289
524077 2290         if(!is_array($folder) or !is_array($website)) {
b1a6a5 2291             $app->log('Not able to retrieve folder or website record.', LOGLEVEL_DEBUG);
524077 2292             return false;
T 2293         }
b1a6a5 2294
MC 2295         $web_folder = 'web';
511ba5 2296         if($website['type'] == 'vhostsubdomain' || $website['type'] == 'vhostalias') $web_folder = $website['web_folder'];
b1a6a5 2297
524077 2298         //* Get the folder path.
b1a6a5 2299         if(substr($folder['path'], 0, 1) == '/') $folder['path'] = substr($folder['path'], 1);
MC 2300         if(substr($folder['path'], -1) == '/') $folder['path'] = substr($folder['path'], 0, -1);
6fb93d 2301         $folder_path = realpath($website['document_root'].'/' . $web_folder . '/'.$folder['path']);
b1a6a5 2302         if(substr($folder_path, -1) != '/') $folder_path .= '/';
MC 2303
524077 2304         //* Check if the resulting path is inside the docroot
b1a6a5 2305         if(substr($folder_path, 0, strlen($website['document_root'])) != $website['document_root']) {
MC 2306             $app->log('Folder path is outside of docroot.', LOGLEVEL_DEBUG);
524077 2307             return false;
T 2308         }
b1a6a5 2309
524077 2310         //* Remove .htpasswd file
T 2311         if(is_file($folder_path.'.htpasswd')) {
c77103 2312             $app->system->unlink($folder_path.'.htpasswd');
b1a6a5 2313             $app->log('Removed file '.$folder_path.'.htpasswd', LOGLEVEL_DEBUG);
524077 2314         }
b1a6a5 2315
524077 2316         //* Remove .htaccess file
T 2317         if(is_file($folder_path.'.htaccess')) {
b1a6a5 2318             $begin_marker = '### ISPConfig folder protection begin ###';
MC 2319             $end_marker = "### ISPConfig folder protection end ###\n\n";
2320
2321             $ht_file = $app->system->file_get_contents($folder_path.'.htaccess');
2322
2323             if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $ht_file, $matches)) {
2324                 $ht_file = str_replace($matches[0], '', $ht_file);
2325             } else {
2326                 $ht_file = str_replace("AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$folder_path.".htpasswd\nrequire valid-user", '', $ht_file);
2327             }
2328
2329             if(trim($ht_file) == '') {
2330                 $app->system->unlink($folder_path.'.htaccess');
2331                 $app->log('Removed file '.$folder_path.'.htaccess', LOGLEVEL_DEBUG);
2332             } else {
2333                 $app->system->file_put_contents($folder_path.'.htaccess', $ht_file);
2334                 $app->log('Removed protection content from file '.$folder_path.'.htaccess', LOGLEVEL_DEBUG);
2335             }
524077 2336         }
2023a7 2337     }
b1a6a5 2338
2023a7 2339     //* Update folder protection, when path has been changed
b1a6a5 2340     function web_folder_update($event_name, $data) {
2023a7 2341         global $app, $conf;
b1a6a5 2342
2af58c 2343         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $data['new']['parent_domain_id']);
b1a6a5 2344
2023a7 2345         if(!is_array($website)) {
b1a6a5 2346             $app->log('Not able to retrieve folder or website record.', LOGLEVEL_DEBUG);
2023a7 2347             return false;
T 2348         }
b1a6a5 2349
MC 2350         $web_folder = 'web';
511ba5 2351         if($website['type'] == 'vhostsubdomain' || $website['type'] == 'vhostalias') $web_folder = $website['web_folder'];
b1a6a5 2352
2023a7 2353         //* Get the folder path.
b1a6a5 2354         if(substr($data['old']['path'], 0, 1) == '/') $data['old']['path'] = substr($data['old']['path'], 1);
MC 2355         if(substr($data['old']['path'], -1) == '/') $data['old']['path'] = substr($data['old']['path'], 0, -1);
6fb93d 2356         $old_folder_path = realpath($website['document_root'].'/' . $web_folder . '/'.$data['old']['path']);
b1a6a5 2357         if(substr($old_folder_path, -1) != '/') $old_folder_path .= '/';
MC 2358
2359         if(substr($data['new']['path'], 0, 1) == '/') $data['new']['path'] = substr($data['new']['path'], 1);
2360         if(substr($data['new']['path'], -1) == '/') $data['new']['path'] = substr($data['new']['path'], 0, -1);
6fb93d 2361         $new_folder_path = escapeshellcmd($website['document_root'].'/' . $web_folder . '/'.$data['new']['path']);
b1a6a5 2362         if(substr($new_folder_path, -1) != '/') $new_folder_path .= '/';
MC 2363
2023a7 2364         //* Check if the resulting path is inside the docroot
b1a6a5 2365         if(stristr($new_folder_path, '..') || stristr($new_folder_path, './') || stristr($new_folder_path, '\\')) {
MC 2366             $app->log('Folder path "'.$new_folder_path.'" contains .. or ./.', LOGLEVEL_DEBUG);
2023a7 2367             return false;
T 2368         }
b1a6a5 2369         if(stristr($old_folder_path, '..') || stristr($old_folder_path, './') || stristr($old_folder_path, '\\')) {
MC 2370             $app->log('Folder path "'.$old_folder_path.'" contains .. or ./.', LOGLEVEL_DEBUG);
2023a7 2371             return false;
T 2372         }
b1a6a5 2373
2023a7 2374         //* Check if the resulting path is inside the docroot
b1a6a5 2375         if(substr($old_folder_path, 0, strlen($website['document_root'])) != $website['document_root']) {
MC 2376             $app->log('Old folder path '.$old_folder_path.' is outside of docroot.', LOGLEVEL_DEBUG);
2023a7 2377             return false;
T 2378         }
b1a6a5 2379         if(substr($new_folder_path, 0, strlen($website['document_root'])) != $website['document_root']) {
MC 2380             $app->log('New folder path '.$new_folder_path.' is outside of docroot.', LOGLEVEL_DEBUG);
2023a7 2381             return false;
T 2382         }
b1a6a5 2383
2023a7 2384         //* Create the folder path, if it does not exist
c77103 2385         if(!is_dir($new_folder_path)) $app->system->mkdirpath($new_folder_path);
b1a6a5 2386
MC 2387         $begin_marker = '### ISPConfig folder protection begin ###';
2388         $end_marker = "### ISPConfig folder protection end ###\n\n";
2389
2023a7 2390         if($data['old']['path'] != $data['new']['path']) {
T 2391
b1a6a5 2392
2023a7 2393             //* move .htpasswd file
T 2394             if(is_file($old_folder_path.'.htpasswd')) {
b1a6a5 2395                 $app->system->rename($old_folder_path.'.htpasswd', $new_folder_path.'.htpasswd');
MC 2396                 $app->log('Moved file '.$old_folder_path.'.htpasswd to '.$new_folder_path.'.htpasswd', LOGLEVEL_DEBUG);
2023a7 2397             }
b1a6a5 2398
8ab3cd 2399             //* delete old .htaccess file
2023a7 2400             if(is_file($old_folder_path.'.htaccess')) {
b1a6a5 2401                 $ht_file = $app->system->file_get_contents($old_folder_path.'.htaccess');
MC 2402
2403                 if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $ht_file, $matches)) {
2404                     $ht_file = str_replace($matches[0], '', $ht_file);
2405                 } else {
2406                     $ht_file = str_replace("AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$old_folder_path.".htpasswd\nrequire valid-user", '', $ht_file);
2407                 }
2408
2409                 if(trim($ht_file) == '') {
2410                     $app->system->unlink($old_folder_path.'.htaccess');
2411                     $app->log('Removed file '.$old_folder_path.'.htaccess', LOGLEVEL_DEBUG);
2412                 } else {
2413                     $app->system->file_put_contents($old_folder_path.'.htaccess', $ht_file);
2414                     $app->log('Removed protection content from file '.$old_folder_path.'.htaccess', LOGLEVEL_DEBUG);
2415                 }
2023a7 2416             }
b1a6a5 2417
2023a7 2418         }
b1a6a5 2419
2023a7 2420         //* Create the .htaccess file
8ab3cd 2421         if($data['new']['active'] == 'y') {
b1a6a5 2422             $ht_file = $begin_marker."\nAuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$new_folder_path.".htpasswd\nrequire valid-user\n".$end_marker;
MC 2423
2424             if(file_exists($new_folder_path.'.htaccess')) {
2425                 $old_content = $app->system->file_get_contents($new_folder_path.'.htaccess');
2426
2427                 if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $old_content, $matches)) {
2428                     $ht_file = str_replace($matches[0], $ht_file, $old_content);
2429                 } else {
2430                     $ht_file .= $old_content;
2431                 }
2432             }
2433
2434             $app->system->file_put_contents($new_folder_path.'.htaccess', $ht_file);
51910d 2435             $app->system->chmod($new_folder_path.'.htaccess', 0751);
b1a6a5 2436             $app->system->chown($new_folder_path.'.htaccess', $website['system_user']);
MC 2437             $app->system->chgrp($new_folder_path.'.htaccess', $website['system_group']);
2438             $app->log('Created/modified file '.$new_folder_path.'.htaccess', LOGLEVEL_DEBUG);
8433d0 2439             
TB 2440             //* Create empty .htpasswd file, if it does not exist
2441             if(!is_file($folder_path.'.htpasswd')) {
2442                 $app->system->touch($new_folder_path.'.htpasswd');
51910d 2443                 $app->system->chmod($new_folder_path.'.htpasswd', 0751);
8433d0 2444                 $app->system->chown($new_folder_path.'.htpasswd', $website['system_user']);
TB 2445                 $app->system->chgrp($new_folder_path.'.htpasswd', $website['system_group']);
2446                 $app->log('Created file '.$new_folder_path.'.htpasswd', LOGLEVEL_DEBUG);
2447             }
2023a7 2448         }
b1a6a5 2449
2023a7 2450         //* Remove .htaccess file
T 2451         if($data['new']['active'] == 'n' && is_file($new_folder_path.'.htaccess')) {
b1a6a5 2452             $ht_file = $app->system->file_get_contents($new_folder_path.'.htaccess');
MC 2453
2454             if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $ht_file, $matches)) {
2455                 $ht_file = str_replace($matches[0], '', $ht_file);
2456             } else {
2457                 $ht_file = str_replace("AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$new_folder_path.".htpasswd\nrequire valid-user", '', $ht_file);
2458             }
2459
2460             if(trim($ht_file) == '') {
2461                 $app->system->unlink($new_folder_path.'.htaccess');
2462                 $app->log('Removed file '.$new_folder_path.'.htaccess', LOGLEVEL_DEBUG);
2463             } else {
2464                 $app->system->file_put_contents($new_folder_path.'.htaccess', $ht_file);
2465                 $app->log('Removed protection content from file '.$new_folder_path.'.htaccess', LOGLEVEL_DEBUG);
2466             }
2023a7 2467         }
b1a6a5 2468
MC 2469
524077 2470     }
b1a6a5 2471
MC 2472     public function ftp_user_delete($event_name, $data) {
26c0fc 2473         global $app, $conf;
b1a6a5 2474
26c0fc 2475         $ftpquota_file = $data['old']['dir'].'/.ftpquota';
c77103 2476         if(file_exists($ftpquota_file)) $app->system->unlink($ftpquota_file);
b1a6a5 2477
26c0fc 2478     }
b1a6a5 2479
MC 2480
ac933e 2481
V 2482     /**
2483      * This function is called when a Webdav-User is inserted, updated or deleted.
2484      *
2485      * @author Oliver Vogel
2486      * @param string $event_name
2487      * @param array $data
2488      */
b1a6a5 2489     public function webdav($event_name, $data) {
ac933e 2490         global $app, $conf;
b1a6a5 2491
52a04e 2492         /*
T 2493          * load the server configuration options
2494         */
fb3339 2495         $app->uses('getconf');
J 2496         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
ac933e 2497
V 2498         if (($event_name == 'webdav_user_insert') || ($event_name == 'webdav_user_update')) {
2499
2500             /*
2501              * Get additional informations
2502             */
2af58c 2503             $sitedata = $app->db->queryOneRecord('SELECT document_root, domain, system_user, system_group FROM web_domain WHERE domain_id = ?', $data['new']['parent_domain_id']);
ac933e 2504             $documentRoot = $sitedata['document_root'];
V 2505             $domain = $sitedata['domain'];
ca14fe 2506             $user = $sitedata['system_user'];
V 2507             $group = $sitedata['system_group'];
b67344 2508             $webdav_user_dir = $documentRoot . '/webdav/' . $data['new']['dir'];
ac933e 2509
V 2510             /* Check if this is a chrooted setup */
2511             if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
2512                 $apache_chrooted = true;
b1a6a5 2513                 $app->log('Info: Apache is chrooted.', LOGLEVEL_DEBUG);
ac933e 2514             } else {
V 2515                 $apache_chrooted = false;
2516             }
b1a6a5 2517
b67344 2518             //* We dont want to have relative paths here
b1a6a5 2519             if(stristr($webdav_user_dir, '..')  || stristr($webdav_user_dir, './')) {
MC 2520                 $app->log('Folder path '.$webdav_user_dir.' contains ./ or .. '.$documentRoot, LOGLEVEL_WARN);
b67344 2521                 return false;
T 2522             }
b1a6a5 2523
b67344 2524             //* Check if the resulting path exists if yes, if it is inside the docroot
b1a6a5 2525             if(is_dir($webdav_user_dir) && substr(realpath($webdav_user_dir), 0, strlen($documentRoot)) != $documentRoot) {
MC 2526                 $app->log('Folder path '.$webdav_user_dir.' is outside of docroot '.$documentRoot, LOGLEVEL_WARN);
b67344 2527                 return false;
T 2528             }
ac933e 2529
V 2530             /*
2531              * First the webdav-root - folder has to exist
2532             */
b67344 2533             if(!is_dir($webdav_user_dir)) {
b1a6a5 2534                 $app->log('Webdav User directory '.$webdav_user_dir.' does not exist. Creating it now.', LOGLEVEL_DEBUG);
c77103 2535                 $app->system->mkdirpath($webdav_user_dir);
ac933e 2536             }
V 2537
2538             /*
ca14fe 2539              * The webdav - Root needs the group/user as owner and the apache as read and write
ac933e 2540             */
c77103 2541             //$this->_exec('chown ' . $user . ':' . $group . ' ' . escapeshellcmd($documentRoot . '/webdav/'));
T 2542             //$this->_exec('chmod 770 ' . escapeshellcmd($documentRoot . '/webdav/'));
b1a6a5 2543             $app->system->chown($documentRoot . '/webdav', $user);
MC 2544             $app->system->chgrp($documentRoot . '/webdav', $group);
2545             $app->system->chmod($documentRoot . '/webdav', 0770);
ac933e 2546
V 2547             /*
ca14fe 2548              * The webdav folder (not the webdav-root!) needs the same (not in ONE step, because the
V 2549              * pwd-files are owned by root)
ac933e 2550             */
c77103 2551             //$this->_exec('chown ' . $user . ':' . $group . ' ' . escapeshellcmd($webdav_user_dir.' -R'));
T 2552             //$this->_exec('chmod 770 ' . escapeshellcmd($webdav_user_dir.' -R'));
b1a6a5 2553             $app->system->chown($webdav_user_dir, $user);
MC 2554             $app->system->chgrp($webdav_user_dir, $group);
2555             $app->system->chmod($webdav_user_dir, 0770);
ca14fe 2556
V 2557             /*
2558              * if the user is active, we have to write/update the password - file
2559              * if the user is inactive, we have to inactivate the user by removing the user from the file
2560             */
2561             if ($data['new']['active'] == 'y') {
b67344 2562                 $this->_writeHtDigestFile( $webdav_user_dir . '.htdigest', $data['new']['username'], $data['new']['dir'], $data['new']['password']);
ca14fe 2563             }
V 2564             else {
2565                 /* empty pwd removes the user! */
b67344 2566                 $this->_writeHtDigestFile( $webdav_user_dir . '.htdigest', $data['new']['username'], $data['new']['dir'], '');
ca14fe 2567             }
ac933e 2568
V 2569             /*
2570              * Next step, patch the vhost - file
2571             */
fb3339 2572             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'] . '/' . $domain . '.vhost');
ac933e 2573             $this->_patchVhostWebdav($vhost_file, $documentRoot . '/webdav');
ca14fe 2574
ac933e 2575             /*
V 2576              * Last, restart apache
2577             */
2578             if($apache_chrooted) {
b1a6a5 2579                 $app->services->restartServiceDelayed('httpd', 'restart');
ac933e 2580             } else {
V 2581                 // request a httpd reload when all records have been processed
b1a6a5 2582                 $app->services->restartServiceDelayed('httpd', 'reload');
ac933e 2583             }
V 2584
2585         }
2586
2587         if ($event_name == 'webdav_user_delete') {
2588             /*
2589              * Get additional informations
2590             */
2af58c 2591             $sitedata = $app->db->queryOneRecord('SELECT document_root, domain FROM web_domain WHERE domain_id = ?', $data['old']['parent_domain_id']);
ac933e 2592             $documentRoot = $sitedata['document_root'];
52a04e 2593             $domain = $sitedata['domain'];
ac933e 2594
V 2595             /*
2596              * We dont't want to destroy any (transfer)-Data. So we do NOT delete any dir.
2597              * So the only thing, we have to do, is to delete the user from the password-file
ca14fe 2598             */
ac933e 2599             $this->_writeHtDigestFile( $documentRoot . '/webdav/' . $data['old']['dir'] . '.htdigest', $data['old']['username'], $data['old']['dir'], '');
b1a6a5 2600
52a04e 2601             /*
T 2602              * Next step, patch the vhost - file
2603             */
fb3339 2604             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'] . '/' . $domain . '.vhost');
52a04e 2605             $this->_patchVhostWebdav($vhost_file, $documentRoot . '/webdav');
b1a6a5 2606
52a04e 2607             /*
T 2608              * Last, restart apache
2609             */
2610             if($apache_chrooted) {
b1a6a5 2611                 $app->services->restartServiceDelayed('httpd', 'restart');
52a04e 2612             } else {
T 2613                 // request a httpd reload when all records have been processed
b1a6a5 2614                 $app->services->restartServiceDelayed('httpd', 'reload');
52a04e 2615             }
ac933e 2616         }
V 2617     }
2618
2619
2620     /**
2621      * This function writes the htdigest - files used by webdav and digest
ca14fe 2622      * more info: see http://riceball.com/d/node/424
ac933e 2623      * @author Oliver Vogel
V 2624      * @param string $filename The name of the digest-file
2625      * @param string $username The name of the webdav-user
2626      * @param string $authname The name of the realm
ca14fe 2627      * @param string $pwd      The password-hash of the user
ac933e 2628      */
ca14fe 2629     private function _writeHtDigestFile($filename, $username, $authname, $pwdhash ) {
4bd960 2630         global $app;
b1a6a5 2631
ac933e 2632         $changed = false;
c77103 2633         if(is_file($filename) && !is_link($filename)) {
0ff3f1 2634             $in = fopen($filename, 'r');
T 2635             $output = '';
2636             /*
2637             * read line by line and search for the username and authname
2638             */
2639             while (preg_match("/:/", $line = fgets($in))) {
2640                 $line = rtrim($line);
2641                 $tmp = explode(':', $line);
2642                 if ($tmp[0] == $username && $tmp[1] == $authname) {
2643                     /*
2644                     * found the user. delete or change it?
2645                     */
2646                     if ($pwdhash != '') {
2647                         $output .= $tmp[0] . ':' . $tmp[1] . ':' . $pwdhash . "\n";
b1a6a5 2648                     }
0ff3f1 2649                     $changed = true;
T 2650                 }
2651                 else {
2652                     $output .= $line . "\n";
2653                 }
ac933e 2654             }
0ff3f1 2655             fclose($in);
ac933e 2656         }
V 2657         /*
2658          * if we didn't change anything, we have to add the new user at the end of the file
2659         */
2660         if (!$changed) {
f17dab 2661             $output .= $username . ':' . $authname . ':' . $pwdhash . "\n";
ac933e 2662         }
b1a6a5 2663
ac933e 2664
V 2665         /*
2666          * Now lets write the new file
2667         */
52a04e 2668         if(trim($output) == '') {
c77103 2669             $app->system->unlink($filename);
52a04e 2670         } else {
c77103 2671             $app->system->file_put_contents($filename, $output);
52a04e 2672         }
ac933e 2673     }
V 2674
2675     /**
2676      * This function patches the vhost-file and adds all webdav - user.
2677      * This function is written, because the creation of the vhost - file is sophisticated and
2678      * i don't want to make it more "heavy" by also adding this code too...
2679      * @author Oliver Vogel
2680      * @param string $fileName The Name of the .vhost-File (path included)
2681      * @param string $webdavRoot The root of the webdav-folder
2682      */
2683     private function _patchVhostWebdav($fileName, $webdavRoot) {
c77103 2684         global $app;
ac933e 2685         $in = fopen($fileName, 'r');
V 2686         $output = '';
2687         $inWebdavSection = false;
2688
2689         /*
2690          * read line by line and search for the username and authname
2691         */
2692         while ($line = fgets($in)) {
2693             /*
2694              *  is the "replace-comment" found...
2695             */
2696             if (trim($line) == '# WEBDAV BEGIN') {
2697                 /*
2698                  * The begin of the webdav - section is found, so ignore all lines til the end  is found
2699                 */
2700                 $inWebdavSection = true;
2701
2702                 $output .= "      # WEBDAV BEGIN\n";
2703
2704                 /*
2705                  * add all the webdav-dirs to the webdav-section
2706                 */
fb3a98 2707                 $files = @scandir($webdavRoot);
T 2708                 if(is_array($files)) {
b1a6a5 2709                     foreach($files as $file) {
MC 2710                         if (substr($file, strlen($file) - strlen('.htdigest')) == '.htdigest' && preg_match("/^[a-zA-Z0-9\-_\.]*$/", $file)) {
2711                             /*
ac933e 2712                          * found a htdigest - file, so add it to webdav
V 2713                         */
b1a6a5 2714                             $fn = substr($file, 0, strlen($file) - strlen('.htdigest'));
MC 2715                             $output .= "\n";
2716                             // $output .= "      Alias /" . $fn . ' ' . $webdavRoot . '/' . $fn . "\n";
2717                             // $output .= "      <Location /" . $fn . ">\n";
2718                             $output .= "      Alias /webdav/" . $fn . ' ' . $webdavRoot . '/' . $fn . "\n";
2719                             $output .= "      <Location /webdav/" . $fn . ">\n";
2720                             $output .= "        DAV On\n";
2721                             $output .= '        BrowserMatch "MSIE" AuthDigestEnableQueryStringHack=On'."\n";
2722                             $output .= "        AuthType Digest\n";
2723                             $output .= "        AuthName \"" . $fn . "\"\n";
2724                             $output .= "        AuthUserFile " . $webdavRoot . '/' . $file . "\n";
2725                             $output .= "        Require valid-user \n";
2726                             $output .= "        Options +Indexes \n";
2727                             $output .= "        Order allow,deny \n";
2728                             $output .= "        Allow from all \n";
2729                             $output .= "      </Location> \n";
2730                         }
ac933e 2731                     }
fb3a98 2732                 }
ac933e 2733             }
V 2734             /*
2735              *  is the "replace-comment-end" found...
2736             */
2737             if (trim($line) == '# WEBDAV END') {
2738                 /*
2739                  * The end of the webdav - section is found, so stop ignoring
2740                 */
2741                 $inWebdavSection = false;
2742             }
2743
2744             /*
2745              * Write the line to the output, if it is not in the section
2746             */
2747             if (!$inWebdavSection) {
2748                 $output .= $line;
2749             }
2750         }
2751         fclose($in);
2752
2753         /*
2754          * Now lets write the new file
2755         */
c77103 2756         $app->system->file_put_contents($fileName, $output);
ac933e 2757
V 2758     }
b1a6a5 2759
58c210 2760     //* Update the awstats configuration file
b1a6a5 2761     private function awstats_update ($data, $web_config) {
58c210 2762         global $app;
b1a6a5 2763
MC 2764         $web_folder = $data['new']['web_folder'];
2765         if($data['new']['type'] == 'vhost') $web_folder = 'web';
2a6eac 2766         $awstats_conf_dir = $web_config['awstats_conf_dir'];
b1a6a5 2767
6fb93d 2768         if(!is_dir($data['new']['document_root']."/" . $web_folder . "/stats/")) mkdir($data['new']['document_root']."/" . $web_folder . "/stats");
fb3339 2769         if(!@is_file($awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf') || ($data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain'])) {
J 2770             if ( @is_file($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf') ) {
c77103 2771                 $app->system->unlink($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf');
58c210 2772             }
b1a6a5 2773
58c210 2774             $content = '';
e6abfe 2775             if (is_file($awstats_conf_dir."/awstats.conf")) {
CS 2776                 $include_file = $awstats_conf_dir."/awstats.conf";
2777             } elseif (is_file($awstats_conf_dir."/awstats.model.conf")) {
2778                 $include_file = $awstats_conf_dir."/awstats.model.conf";
2779             }
de6d2e 2780             $content .= "Include \"".$include_file."\"\n";
fb3339 2781             $content .= "LogFile=\"/var/log/ispconfig/httpd/".$data['new']['domain']."/access.log\"\n";
J 2782             $content .= "SiteDomain=\"".$data['new']['domain']."\"\n";
2783             $content .= "HostAliases=\"www.".$data['new']['domain']."  localhost 127.0.0.1\"\n";
b1a6a5 2784
9aaf97 2785             if (isset($include_file)) {
CS 2786                 $app->system->file_put_contents($awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf', $content);
2787                 $app->log('Created AWStats config file: '.$awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf', LOGLEVEL_DEBUG);
2788             } else {
2789                 $app->log("No awstats base config found. Either awstats.conf or awstats.model.conf must exist in ".$awstats_conf_dir.".", LOGLEVEL_WARN);
2790             }
58c210 2791         }
b1a6a5 2792
6fb93d 2793         if(is_file($data['new']['document_root']."/" . $web_folder . "/stats/index.html")) $app->system->unlink($data['new']['document_root']."/" . $web_folder . "/stats/index.html");
a464e1 2794         if(file_exists("/usr/local/ispconfig/server/conf-custom/awstats_index.php.master")) {
b1a6a5 2795             $app->system->copy("/usr/local/ispconfig/server/conf-custom/awstats_index.php.master", $data['new']['document_root']."/" . $web_folder . "/stats/index.php");
a464e1 2796         } else {
b1a6a5 2797             $app->system->copy("/usr/local/ispconfig/server/conf/awstats_index.php.master", $data['new']['document_root']."/" . $web_folder . "/stats/index.php");
a464e1 2798         }
58c210 2799     }
b1a6a5 2800
58c210 2801     //* Delete the awstats configuration file
b1a6a5 2802     private function awstats_delete ($data, $web_config) {
58c210 2803         global $app;
b1a6a5 2804
58c210 2805         $awstats_conf_dir = $web_config['awstats_conf_dir'];
b1a6a5 2806
fb3339 2807         if ( @is_file($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf') ) {
c77103 2808             $app->system->unlink($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf');
b1a6a5 2809             $app->log('Removed AWStats config file: '.$awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf', LOGLEVEL_DEBUG);
58c210 2810         }
T 2811     }
b1a6a5 2812
c59632 2813     private function hhvm_update($data, $web_config) {
MC 2814         global $app, $conf;
2815         
2816         if(file_exists($conf['rootpath'] . '/conf-custom/hhvm_starter.master')) {
2817             $content = file_get_contents($conf['rootpath'] . '/conf-custom/hhvm_starter.master');
2818         } else {
2819             $content = file_get_contents($conf['rootpath'] . '/conf/hhvm_starter.master');
2820         }
cab08c 2821         if(file_exists($conf['rootpath'] . '/conf-custom/hhvm_monit.master')) {
MC 2822             $monit_content = file_get_contents($conf['rootpath'] . '/conf-custom/hhvm_monit.master');
2823         } else {
2824             $monit_content = file_get_contents($conf['rootpath'] . '/conf/hhvm_monit.master');
2825         }
c59632 2826         
d5f2d5 2827         if($data['new']['php'] == 'hhvm' && $data['old']['php'] != 'hhvm' || $data['new']['custom_php_ini'] != $data['old']['custom_php_ini']) {
MC 2828         
2829             // Custom php.ini settings
2830             $custom_php_ini_settings = trim($data['new']['custom_php_ini']);
2831             if(intval($data['new']['directive_snippets_id']) > 0){
2832                 $snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'nginx' AND active = 'y' AND customer_viewable = 'y'", intval($data['new']['directive_snippets_id']));
2833                 if(isset($snippet['required_php_snippets']) && trim($snippet['required_php_snippets']) != ''){
2834                     $required_php_snippets = explode(',', trim($snippet['required_php_snippets']));
2835                     if(is_array($required_php_snippets) && !empty($required_php_snippets)){
2836                         foreach($required_php_snippets as $required_php_snippet){
2837                             $required_php_snippet = intval($required_php_snippet);
2838                             if($required_php_snippet > 0){
2839                                 $php_snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'php' AND active = 'y'", $required_php_snippet);
2840                                 $php_snippet['snippet'] = trim($php_snippet['snippet']);
2841                                 if($php_snippet['snippet'] != ''){
2842                                     $custom_php_ini_settings .= "\n".$php_snippet['snippet'];
2843                                 }
2844                             }
2845                         }
2846                     }
2847                 }
2848             }
2849             if($custom_php_ini_settings != ''){
2850                 // Make sure we only have Unix linebreaks
2851                 $custom_php_ini_settings = str_replace("\r\n", "\n", $custom_php_ini_settings);
2852                 $custom_php_ini_settings = str_replace("\r", "\n", $custom_php_ini_settings);
2853                 file_put_contents('/etc/hhvm/'.$data['new']['system_user'].'.ini', $custom_php_ini_settings);
2854             } else {
2855                 if(is_file('/etc/hhvm/'.$data['old']['system_user'].'.ini')) unlink('/etc/hhvm/'.$data['old']['system_user'].'.ini');
2856             }
2857             
1c6da3 2858             $content = str_replace('{SYSTEM_USER}', $data['new']['system_user'], $content);
c59632 2859             file_put_contents('/etc/init.d/hhvm_' . $data['new']['system_user'], $content);
MC 2860             exec('chmod +x /etc/init.d/hhvm_' . $data['new']['system_user'] . ' >/dev/null 2>&1');
2861             exec('/usr/sbin/update-rc.d hhvm_' . $data['new']['system_user'] . ' defaults >/dev/null 2>&1');
02e7ea 2862             exec('/etc/init.d/hhvm_' . $data['new']['system_user'] . ' restart >/dev/null 2>&1');
cab08c 2863             
02e7ea 2864             if(is_dir('/etc/monit/conf.d')){
MC 2865                 $monit_content = str_replace('{SYSTEM_USER}', $data['new']['system_user'], $monit_content);
2866                 file_put_contents('/etc/monit/conf.d/00-hhvm_' . $data['new']['system_user'], $monit_content);
2867                 if(is_file('/etc/monit/conf.d/hhvm_' . $data['new']['system_user'])) unlink('/etc/monit/conf.d/hhvm_' . $data['new']['system_user']);
2868                 exec('/etc/init.d/monit restart >/dev/null 2>&1');
2869             }
cab08c 2870             
c59632 2871          } elseif($data['new']['php'] != 'hhvm' && $data['old']['php'] == 'hhvm') {
MC 2872             exec('/etc/init.d/hhvm_' . $data['old']['system_user'] . ' stop >/dev/null 2>&1');
2873             exec('/usr/sbin/update-rc.d hhvm_' . $data['old']['system_user'] . ' remove >/dev/null 2>&1');
cdb2c6 2874             unlink('/etc/init.d/hhvm_' . $data['old']['system_user']);
d5f2d5 2875             if(is_file('/etc/hhvm/'.$data['old']['system_user'].'.ini')) unlink('/etc/hhvm/'.$data['old']['system_user'].'.ini');
cab08c 2876             
02e7ea 2877             if(is_file('/etc/monit/conf.d/hhvm_' . $data['new']['system_user']) || is_file('/etc/monit/conf.d/00-hhvm_' . $data['new']['system_user'])){
MC 2878                 if(is_file('/etc/monit/conf.d/hhvm_' . $data['new']['system_user'])){
2879                     unlink('/etc/monit/conf.d/hhvm_' . $data['new']['system_user']);
2880                 }
2881                 if(is_file('/etc/monit/conf.d/00-hhvm_' . $data['new']['system_user'])){
2882                     unlink('/etc/monit/conf.d/00-hhvm_' . $data['new']['system_user']);
2883                 }
cab08c 2884                 exec('/etc/init.d/monit restart >/dev/null 2>&1');
MC 2885             }
c59632 2886         }
MC 2887     }
2888
274362 2889     //* Update the PHP-FPM pool configuration file
b1a6a5 2890     private function php_fpm_pool_update ($data, $web_config, $pool_dir, $pool_name, $socket_dir) {
274362 2891         global $app, $conf;
ab79c2 2892         $pool_dir = trim($pool_dir);
274362 2893         //$reload = false;
b1a6a5 2894
62e4b3 2895         if($data['new']['php'] == 'php-fpm'){
F 2896             if(trim($data['new']['fastcgi_php_version']) != ''){
2897                 $default_php_fpm = false;
2898                 list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['new']['fastcgi_php_version']));
b1a6a5 2899                 if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
62e4b3 2900             } else {
F 2901                 $default_php_fpm = true;
2902             }
274362 2903         } else {
62e4b3 2904             if(trim($data['old']['fastcgi_php_version']) != '' && $data['old']['php'] == 'php-fpm'){
F 2905                 $default_php_fpm = false;
2906                 list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['old']['fastcgi_php_version']));
b1a6a5 2907                 if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
62e4b3 2908             } else {
F 2909                 $default_php_fpm = true;
2910             }
274362 2911         }
b1a6a5 2912
274362 2913         $app->uses("getconf");
F 2914         $web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
b1a6a5 2915
274362 2916         if($data['new']['php'] != 'php-fpm'){
F 2917             if(@is_file($pool_dir.$pool_name.'.conf')){
c77103 2918                 $app->system->unlink($pool_dir.$pool_name.'.conf');
274362 2919                 //$reload = true;
F 2920             }
2921             if($data['old']['php'] == 'php-fpm'){
2922                 if(!$default_php_fpm){
b1a6a5 2923                     $app->services->restartService('php-fpm', 'reload:'.$custom_php_fpm_init_script);
274362 2924                 } else {
b1a6a5 2925                     $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 2926                 }
F 2927             }
2928             //if($reload == true) $app->services->restartService('php-fpm','reload');
2929             return;
2930         }
b1a6a5 2931
274362 2932         $app->load('tpl');
F 2933         $tpl = new tpl();
2934         $tpl->newTemplate('php_fpm_pool.conf.master');
8133de 2935         $tpl->setVar('apache_version', $app->system->getapacheversion());
MC 2936         
c91c7a 2937         $apache_modules = $app->system->getapachemodules();
TB 2938         
6db036 2939         // Use sockets, but not with apache 2.4 on centos (mod_proxy_fcgi) as socket support is buggy in that version
TB 2940         if($data['new']['php_fpm_use_socket'] == 'y' && in_array('fastcgi_module',$apache_modules)){
274362 2941             $use_tcp = 0;
F 2942             $use_socket = 1;
c77103 2943             if(!is_dir($socket_dir)) $app->system->mkdirpath($socket_dir);
274362 2944         } else {
F 2945             $use_tcp = 1;
2946             $use_socket = 0;
2947         }
2948         $tpl->setVar('use_tcp', $use_tcp);
2949         $tpl->setVar('use_socket', $use_socket);
b1a6a5 2950
274362 2951         $fpm_socket = $socket_dir.$pool_name.'.sock';
F 2952         $tpl->setVar('fpm_socket', $fpm_socket);
b491ad 2953         $tpl->setVar('fpm_listen_mode', '0660');
b1a6a5 2954
274362 2955         $tpl->setVar('fpm_pool', $pool_name);
F 2956         $tpl->setVar('fpm_port', $web_config['php_fpm_start_port'] + $data['new']['domain_id'] - 1);
2957         $tpl->setVar('fpm_user', $data['new']['system_user']);
2958         $tpl->setVar('fpm_group', $data['new']['system_group']);
d33fd2 2959         $tpl->setVar('fpm_domain', $data['new']['domain']);
dd7ce4 2960         $tpl->setVar('pm', $data['new']['pm']);
274362 2961         $tpl->setVar('pm_max_children', $data['new']['pm_max_children']);
F 2962         $tpl->setVar('pm_start_servers', $data['new']['pm_start_servers']);
2963         $tpl->setVar('pm_min_spare_servers', $data['new']['pm_min_spare_servers']);
2964         $tpl->setVar('pm_max_spare_servers', $data['new']['pm_max_spare_servers']);
dd7ce4 2965         $tpl->setVar('pm_process_idle_timeout', $data['new']['pm_process_idle_timeout']);
F 2966         $tpl->setVar('pm_max_requests', $data['new']['pm_max_requests']);
274362 2967         $tpl->setVar('document_root', $data['new']['document_root']);
b1a6a5 2968         $tpl->setVar('security_level', $web_config['security_level']);
f63910 2969         $tpl->setVar('domain', $data['new']['domain']);
274362 2970         $php_open_basedir = ($data['new']['php_open_basedir'] == '')?escapeshellcmd($data['new']['document_root']):escapeshellcmd($data['new']['php_open_basedir']);
F 2971         $tpl->setVar('php_open_basedir', $php_open_basedir);
2972         if($php_open_basedir != ''){
2973             $tpl->setVar('enable_php_open_basedir', '');
2974         } else {
2975             $tpl->setVar('enable_php_open_basedir', ';');
2976         }
b1a6a5 2977
274362 2978         // Custom php.ini settings
F 2979         $final_php_ini_settings = array();
2980         $custom_php_ini_settings = trim($data['new']['custom_php_ini']);
b41803 2981         
MC 2982         if(intval($data['new']['directive_snippets_id']) > 0){
2983             $snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'apache' AND active = 'y' AND customer_viewable = 'y'", intval($data['new']['directive_snippets_id']));
2984             if(isset($snippet['required_php_snippets']) && trim($snippet['required_php_snippets']) != ''){
2985                 $required_php_snippets = explode(',', trim($snippet['required_php_snippets']));
2986                 if(is_array($required_php_snippets) && !empty($required_php_snippets)){
2987                     foreach($required_php_snippets as $required_php_snippet){
2988                         $required_php_snippet = intval($required_php_snippet);
2989                         if($required_php_snippet > 0){
2990                             $php_snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'php' AND active = 'y'", $required_php_snippet);
2991                             $php_snippet['snippet'] = trim($php_snippet['snippet']);
2992                             if($php_snippet['snippet'] != ''){
2993                                 $custom_php_ini_settings .= "\n".$php_snippet['snippet'];
2994                             }
2995                         }
2996                     }
2997                 }
2998             }
2999         }
3000         
274362 3001         if($custom_php_ini_settings != ''){
F 3002             // Make sure we only have Unix linebreaks
3003             $custom_php_ini_settings = str_replace("\r\n", "\n", $custom_php_ini_settings);
3004             $custom_php_ini_settings = str_replace("\r", "\n", $custom_php_ini_settings);
3005             $ini_settings = explode("\n", $custom_php_ini_settings);
3006             if(is_array($ini_settings) && !empty($ini_settings)){
3007                 foreach($ini_settings as $ini_setting){
254a4a 3008                     $ini_setting = trim($ini_setting);
b1a6a5 3009                     if(substr($ini_setting, 0, 1) == ';') continue;
MC 3010                     if(substr($ini_setting, 0, 1) == '#') continue;
3011                     if(substr($ini_setting, 0, 2) == '//') continue;
03cc01 3012                     list($key, $value) = explode('=', $ini_setting, 2);
1d6097 3013                     $value = trim($value);
FT 3014                     if($value != ''){
254a4a 3015                         $key = trim($key);
F 3016                         switch (strtolower($value)) {
b1a6a5 3017                         case '0':
MC 3018                             // PHP-FPM might complain about invalid boolean value if you use 0
3019                             $value = 'off';
3020                         case '1':
3021                         case 'on':
3022                         case 'off':
3023                         case 'true':
3024                         case 'false':
3025                         case 'yes':
3026                         case 'no':
3027                             $final_php_ini_settings[] = array('ini_setting' => 'php_admin_flag['.$key.'] = '.$value);
3028                             break;
3029                         default:
3030                             $final_php_ini_settings[] = array('ini_setting' => 'php_admin_value['.$key.'] = '.$value);
274362 3031                         }
254a4a 3032                     }
274362 3033                 }
F 3034             }
3035         }
b1a6a5 3036
274362 3037         $tpl->setLoop('custom_php_ini_settings', $final_php_ini_settings);
b1a6a5 3038
MC 3039         $app->system->file_put_contents($pool_dir.$pool_name.'.conf', $tpl->grab());
3040         $app->log('Writing the PHP-FPM config file: '.$pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
274362 3041         unset($tpl);
b1a6a5 3042
274362 3043         // delete pool in all other PHP versions
ab79c2 3044         $default_pool_dir = trim(escapeshellcmd($web_config['php_fpm_pool_dir']));
b1a6a5 3045         if(substr($default_pool_dir, -1) != '/') $default_pool_dir .= '/';
274362 3046         if($default_pool_dir != $pool_dir){
F 3047             if ( @is_file($default_pool_dir.$pool_name.'.conf') ) {
b1a6a5 3048                 $app->system->unlink($default_pool_dir.$pool_name.'.conf');
MC 3049                 $app->log('Removed PHP-FPM config file: '.$default_pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
3050                 $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 3051             }
F 3052         }
2af58c 3053         $php_versions = $app->db->queryAllRecords("SELECT * FROM server_php WHERE php_fpm_init_script != '' AND php_fpm_ini_dir != '' AND php_fpm_pool_dir != '' AND server_id = ?", $conf["server_id"]);
274362 3054         if(is_array($php_versions) && !empty($php_versions)){
F 3055             foreach($php_versions as $php_version){
ab79c2 3056                 $php_version['php_fpm_pool_dir'] = trim($php_version['php_fpm_pool_dir']);
b1a6a5 3057                 if(substr($php_version['php_fpm_pool_dir'], -1) != '/') $php_version['php_fpm_pool_dir'] .= '/';
274362 3058                 if($php_version['php_fpm_pool_dir'] != $pool_dir){
F 3059                     if ( @is_file($php_version['php_fpm_pool_dir'].$pool_name.'.conf') ) {
c77103 3060                         $app->system->unlink($php_version['php_fpm_pool_dir'].$pool_name.'.conf');
b1a6a5 3061                         $app->log('Removed PHP-FPM config file: '.$php_version['php_fpm_pool_dir'].$pool_name.'.conf', LOGLEVEL_DEBUG);
MC 3062                         $app->services->restartService('php-fpm', 'reload:'.$php_version['php_fpm_init_script']);
274362 3063                     }
F 3064                 }
3065             }
3066         }
3067         // Reload current PHP-FPM after all others
3068         sleep(1);
3069         if(!$default_php_fpm){
b1a6a5 3070             $app->services->restartService('php-fpm', 'reload:'.$custom_php_fpm_init_script);
274362 3071         } else {
b1a6a5 3072             $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 3073         }
b1a6a5 3074
274362 3075         //$reload = true;
F 3076
3077         //if($reload == true) $app->services->restartService('php-fpm','reload');
3078     }
b1a6a5 3079
274362 3080     //* Delete the PHP-FPM pool configuration file
b1a6a5 3081     private function php_fpm_pool_delete ($data, $web_config) {
274362 3082         global $app, $conf;
b1a6a5 3083
62e4b3 3084         if(trim($data['old']['fastcgi_php_version']) != '' && $data['old']['php'] == 'php-fpm'){
274362 3085             $default_php_fpm = false;
F 3086             list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['old']['fastcgi_php_version']));
b1a6a5 3087             if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
274362 3088         } else {
F 3089             $default_php_fpm = true;
3090         }
b1a6a5 3091
274362 3092         if($default_php_fpm){
F 3093             $pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
3094         } else {
3095             $pool_dir = $custom_php_fpm_pool_dir;
3096         }
ab79c2 3097         $pool_dir = trim($pool_dir);
b1a6a5 3098
MC 3099         if(substr($pool_dir, -1) != '/') $pool_dir .= '/';
274362 3100         $pool_name = 'web'.$data['old']['domain_id'];
b1a6a5 3101
274362 3102         if ( @is_file($pool_dir.$pool_name.'.conf') ) {
c77103 3103             $app->system->unlink($pool_dir.$pool_name.'.conf');
b1a6a5 3104             $app->log('Removed PHP-FPM config file: '.$pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
MC 3105
274362 3106             //$app->services->restartService('php-fpm','reload');
F 3107         }
b1a6a5 3108
274362 3109         // delete pool in all other PHP versions
ab79c2 3110         $default_pool_dir = trim(escapeshellcmd($web_config['php_fpm_pool_dir']));
b1a6a5 3111         if(substr($default_pool_dir, -1) != '/') $default_pool_dir .= '/';
274362 3112         if($default_pool_dir != $pool_dir){
F 3113             if ( @is_file($default_pool_dir.$pool_name.'.conf') ) {
b1a6a5 3114                 $app->system->unlink($default_pool_dir.$pool_name.'.conf');
MC 3115                 $app->log('Removed PHP-FPM config file: '.$default_pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
3116                 $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 3117             }
b1a6a5 3118         }
2af58c 3119         $php_versions = $app->db->queryAllRecords("SELECT * FROM server_php WHERE php_fpm_init_script != '' AND php_fpm_ini_dir != '' AND php_fpm_pool_dir != '' AND server_id = ?", $data['old']['server_id']);
274362 3120         if(is_array($php_versions) && !empty($php_versions)){
F 3121             foreach($php_versions as $php_version){
ab79c2 3122                 $php_version['php_fpm_pool_dir'] = trim($php_version['php_fpm_pool_dir']);
b1a6a5 3123                 if(substr($php_version['php_fpm_pool_dir'], -1) != '/') $php_version['php_fpm_pool_dir'] .= '/';
274362 3124                 if($php_version['php_fpm_pool_dir'] != $pool_dir){
F 3125                     if ( @is_file($php_version['php_fpm_pool_dir'].$pool_name.'.conf') ) {
c77103 3126                         $app->system->unlink($php_version['php_fpm_pool_dir'].$pool_name.'.conf');
b1a6a5 3127                         $app->log('Removed PHP-FPM config file: '.$php_version['php_fpm_pool_dir'].$pool_name.'.conf', LOGLEVEL_DEBUG);
MC 3128                         $app->services->restartService('php-fpm', 'reload:'.$php_version['php_fpm_init_script']);
274362 3129                     }
F 3130                 }
3131             }
3132         }
b1a6a5 3133
274362 3134         // Reload current PHP-FPM after all others
F 3135         sleep(1);
3136         if(!$default_php_fpm){
b1a6a5 3137             $app->services->restartService('php-fpm', 'reload:'.$custom_php_fpm_init_script);
274362 3138         } else {
b1a6a5 3139             $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 3140         }
F 3141     }
b1a6a5 3142
MC 3143     function client_delete($event_name, $data) {
1ca823 3144         global $app, $conf;
b1a6a5 3145
1ca823 3146         $app->uses("getconf");
T 3147         $web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
b1a6a5 3148
1ca823 3149         $client_id = intval($data['old']['client_id']);
T 3150         if($client_id > 0) {
b1a6a5 3151
1ca823 3152             $client_dir = $web_config['website_basedir'].'/clients/client'.$client_id;
b1a6a5 3153             if(is_dir($client_dir) && !stristr($client_dir, '..')) {
72695f 3154                 // remove symlinks from $client_dir
b1a6a5 3155                 $files = array_diff(scandir($client_dir), array('.', '..'));
72695f 3156                 if(is_array($files) && !empty($files)){
T 3157                     foreach($files as $file){
3158                         if(is_link($client_dir.'/'.$file)){
3159                             unlink($client_dir.'/'.$file);
b1a6a5 3160                             $app->log('Removed symlink: '.$client_dir.'/'.$file, LOGLEVEL_DEBUG);
72695f 3161                         }
T 3162                     }
3163                 }
b1a6a5 3164
1ca823 3165                 @rmdir($client_dir);
b1a6a5 3166                 $app->log('Removed client directory: '.$client_dir, LOGLEVEL_DEBUG);
1ca823 3167             }
b1a6a5 3168
615a0a 3169             if($app->system->is_group('client'.$client_id)){
T 3170                 $this->_exec('groupdel client'.$client_id);
b1a6a5 3171                 $app->log('Removed group client'.$client_id, LOGLEVEL_DEBUG);
615a0a 3172             }
1ca823 3173         }
b1a6a5 3174
1ca823 3175     }
ac933e 3176
1c40af 3177     //* Wrapper for exec function for easier debugging
T 3178     private function _exec($command) {
3179         global $app;
b1a6a5 3180         $app->log('exec: '.$command, LOGLEVEL_DEBUG);
1c40af 3181         exec($command);
T 3182     }
7ed741 3183
b1a6a5 3184     private function _checkTcp ($host, $port) {
MC 3185
3186         $fp = @fsockopen($host, $port, $errno, $errstr, 2);
7ed741 3187
T 3188         if ($fp) {
3189             fclose($fp);
3190             return true;
3191         } else {
3192             return false;
3193         }
3194     }
ac933e 3195
552178 3196     public function create_relative_link($f, $t) {
bfcdef 3197         global $app;
b1a6a5 3198
552178 3199         // $from already exists
M 3200         $from = realpath($f);
3201
3202         // realpath requires the traced file to exist - so, lets touch it first, then remove
c77103 3203         @$app->system->unlink($t); touch($t);
552178 3204         $to = realpath($t);
c77103 3205         @$app->system->unlink($t);
552178 3206
M 3207         // Remove from the left side matching path elements from $from and $to
3208         // and get path elements counts
3209         $a1 = explode('/', $from); $a2 = explode('/', $to);
3210         for ($c = 0; $a1[$c] == $a2[$c]; $c++) {
3211             unset($a1[$c]); unset($a2[$c]);
3212         }
3213         $cfrom = implode('/', $a1);
3214
3215         // Check if a path is fully a subpath of another - no way to create symlink in the case
3216         if (count($a1) == 0 || count($a2) == 0) return false;
3217
3218         // Add ($cnt_to-1) number of "../" elements to left side of $cfrom
3219         for ($c = 0; $c < (count($a2)-1); $c++) { $cfrom = '../'.$cfrom; }
3220
3221         return symlink($cfrom, $to);
3222     }
46c683 3223
b1a6a5 3224     private function _rewrite_quote($string) {
MC 3225         return str_replace(array('.', '*', '?', '+'), array('\\.', '\\*', '\\?', '\\+'), $string);
3226     }
3227
3228     private function _is_url($string) {
3229         return preg_match('/^(f|ht)tp(s)?:\/\//i', $string);
3230     }
3231
bfcdef 3232     private function get_seo_redirects($web, $prefix = ''){
T 3233         $seo_redirects = array();
b1a6a5 3234
bfcdef 3235         if(substr($web['domain'], 0, 2) === '*.') $web['subdomain'] = '*';
b1a6a5 3236
bfcdef 3237         if($web['subdomain'] == 'www' || $web['subdomain'] == '*'){
T 3238             if($web['seo_redirect'] == 'non_www_to_www'){
3239                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = str_replace('.', '\.', $web['domain']);
3240                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = 'www.'.$web['domain'];
3241                 $seo_redirects[$prefix.'seo_redirect_operator'] = '';
3242             }
3243             if($web['seo_redirect'] == '*_domain_tld_to_www_domain_tld'){
3244                 // ^(example\.com|(?!\bwww\b)\.example\.com)$
3245                 // ^(example\.com|((?:\w+(?:-\w+)*\.)*)((?!www\.)\w+(?:-\w+)*)(\.example\.com))$
3246                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = '('.str_replace('.', '\.', $web['domain']).'|((?:\w+(?:-\w+)*\.)*)((?!www\.)\w+(?:-\w+)*)(\.'.str_replace('.', '\.', $web['domain']).'))';
3247                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = 'www.'.$web['domain'];
3248                 $seo_redirects[$prefix.'seo_redirect_operator'] = '';
3249             }
3250             if($web['seo_redirect'] == '*_to_www_domain_tld'){
3251                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = 'www\.'.str_replace('.', '\.', $web['domain']);
3252                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = 'www.'.$web['domain'];
3253                 $seo_redirects[$prefix.'seo_redirect_operator'] = '!';
3254             }
3255         }
3256         if($web['seo_redirect'] == 'www_to_non_www'){
3257             $seo_redirects[$prefix.'seo_redirect_origin_domain'] = 'www\.'.str_replace('.', '\.', $web['domain']);
3258             $seo_redirects[$prefix.'seo_redirect_target_domain'] = $web['domain'];
3259             $seo_redirects[$prefix.'seo_redirect_operator'] = '';
3260         }
3261         if($web['seo_redirect'] == '*_domain_tld_to_domain_tld'){
3262             // ^(.+)\.example\.com$
3263             $seo_redirects[$prefix.'seo_redirect_origin_domain'] = '(.+)\.'.str_replace('.', '\.', $web['domain']);
3264             $seo_redirects[$prefix.'seo_redirect_target_domain'] = $web['domain'];
3265             $seo_redirects[$prefix.'seo_redirect_operator'] = '';
3266         }
3267         if($web['seo_redirect'] == '*_to_domain_tld'){
3268             $seo_redirects[$prefix.'seo_redirect_origin_domain'] = str_replace('.', '\.', $web['domain']);
3269             $seo_redirects[$prefix.'seo_redirect_target_domain'] = $web['domain'];
3270             $seo_redirects[$prefix.'seo_redirect_operator'] = '!';
3271         }
3272         return $seo_redirects;
3273     }
b1a6a5 3274
46c683 3275 } // end class
T 3276
c09f04 3277 ?>