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