Till Brehm
2016-07-24 b9a3ef486ebcde18a5ade37865ff8f397185d24f
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
e74390 750           if ( in_array($file_system , array('ext2','ext3','ext4','simfs','reiserfs'), 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
8a1f4c 1266              if(substr($domain,0,4) != 'www.' && ($data['new']['subdomain'] == "www" OR $data['new']['subdomain'] == "*")) {
a20ec4 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'];
8a1f4c 1284                     if(isset($aliasdomain['subdomain']) && substr($aliasdomain['domain'],0,4) != 'www.' && ($aliasdomain['subdomain'] == "www" OR $aliasdomain['subdomain'] == "*")) {
8c93e1 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);
8a1f4c 1316                 $app->log("Let's Encrypt SSL Cert domains: $lddomain", LOGLEVEL_DEBUG);
551d9a 1317                 
MB 1318                 $success = false;
312ab0 1319                 $letsencrypt = explode("\n", shell_exec('which letsencrypt certbot /root/.local/share/letsencrypt/bin/letsencrypt'));
MB 1320                 $letsencrypt = reset($letsencrypt);
190275 1321                 if(is_executable($letsencrypt)) {
cae251 1322                     $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 1323                 }
551d9a 1324                 if(!$success) {
MB 1325                     // error issuing cert
1326                     $app->log('Let\'s Encrypt SSL Cert for: ' . $domain . ' could not be issued.', LOGLEVEL_WARN);
1327                     $data['new']['ssl_letsencrypt'] = 'n';
1328                     if($data['old']['ssl'] == 'n') $data['new']['ssl'] = 'n';
1329                     /* Update the DB of the (local) Server */
1330                     $app->db->query("UPDATE web_domain SET `ssl` = ?, `ssl_letsencrypt` = ? WHERE `domain` = ?", $data['new']['ssl'], 'n', $data['new']['domain']);
1331                     /* Update also the master-DB of the Server-Farm */
1332                     $app->dbmaster->query("UPDATE web_domain SET `ssl` = ?, `ssl_letsencrypt` = ? WHERE `domain` = ?", $data['new']['ssl'], 'n', $data['new']['domain']);
1333                 }
a49635 1334             //}
018c55 1335
MC 1336             //* check is been correctly created
1337             if(file_exists($crt_tmp_file) OR file_exists($key_tmp_file)) {
1ba089 1338                 $date = date("YmdHis");
MB 1339                 //* TODO: check if is a symlink, if target same keep it, either remove it
018c55 1340                 if(is_file($key_file)) {
1ba089 1341                     $app->system->copy($key_file, $key_file.'.old.'.$date);
018c55 1342                     $app->system->chmod($key_file.'.old.'.$date, 0400);
MC 1343                     $app->system->unlink($key_file);
1344                 }
1345
1346                 if ($web_config["website_symlinks_rel"] == 'y') {
1347                     $this->create_relative_link(escapeshellcmd($key_tmp_file), escapeshellcmd($key_file));
1348                 } else {
1349                     exec("ln -s ".escapeshellcmd($key_tmp_file)." ".escapeshellcmd($key_file));
1350                 }
1351
1352                 if(is_file($crt_file)) {
1353                     $app->system->copy($crt_file, $crt_file.'.old.'.$date);
1354                     $app->system->chmod($crt_file.'.old.'.$date, 0400);
1355                     $app->system->unlink($crt_file);
1356                 }
1357
1358                 if($web_config["website_symlinks_rel"] == 'y') {
1359                     $this->create_relative_link(escapeshellcmd($crt_tmp_file), escapeshellcmd($crt_file));
1360                 } else {
1361                     exec("ln -s ".escapeshellcmd($crt_tmp_file)." ".escapeshellcmd($crt_file));
1362                 }
1363
1364                 /* we don't need to store it.
1365                 /* Update the DB of the (local) Server */
551d9a 1366                 $app->db->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '', ssl_key = '' WHERE domain = ?", $data['new']['domain']);
MB 1367                 $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
018c55 1368                 /* Update also the master-DB of the Server-Farm */
551d9a 1369                 $app->dbmaster->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '', ssl_key = '' WHERE domain = ?", $data['new']['domain']);
MB 1370                 $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
018c55 1371             }
MC 1372         };
1373
146783 1374         if($domain!='' && $data['new']['ssl'] == 'y' && @is_file($crt_file) && @is_file($key_file) && (@filesize($crt_file)>0)  && (@filesize($key_file)>0)) {
MC 1375             $vhost_data['ssl_enabled'] = 1;
7fe908 1376             $app->log('Enable SSL for: '.$domain, LOGLEVEL_DEBUG);
146783 1377         } else {
MC 1378             $vhost_data['ssl_enabled'] = 0;
7fe908 1379             $app->log('SSL Disabled. '.$domain, LOGLEVEL_DEBUG);
146783 1380         }
MC 1381
1382         // Set SEO Redirect
1383         if($data['new']['seo_redirect'] != ''){
1384             $vhost_data['seo_redirect_enabled'] = 1;
1385             $tmp_seo_redirects = $this->get_seo_redirects($data['new']);
1386             if(is_array($tmp_seo_redirects) && !empty($tmp_seo_redirects)){
1387                 foreach($tmp_seo_redirects as $key => $val){
1388                     $vhost_data[$key] = $val;
1389                 }
1390             } else {
1391                 $vhost_data['seo_redirect_enabled'] = 0;
1392             }
1393         } else {
1394             $vhost_data['seo_redirect_enabled'] = 0;
1395         }
7fe908 1396
MC 1397
146783 1398
MC 1399         // Rewrite rules
1400         $own_rewrite_rules = array();
1401         $rewrite_rules = array();
1402         $local_rewrite_rules = array();
1403         if($data['new']['redirect_type'] != '' && $data['new']['redirect_path'] != '') {
7fe908 1404             if(substr($data['new']['redirect_path'], -1) != '/') $data['new']['redirect_path'] .= '/';
MC 1405             if(substr($data['new']['redirect_path'], 0, 8) == '[scheme]'){
146783 1406                 if($data['new']['redirect_type'] != 'proxy'){
7fe908 1407                     $data['new']['redirect_path'] = '$scheme'.substr($data['new']['redirect_path'], 8);
146783 1408                 } else {
7fe908 1409                     $data['new']['redirect_path'] = 'http'.substr($data['new']['redirect_path'], 8);
146783 1410                 }
MC 1411             }
7fe908 1412
146783 1413             // Custom proxy directives
MC 1414             if($data['new']['redirect_type'] == 'proxy' && trim($data['new']['proxy_directives'] != '')){
1415                 $final_proxy_directives = array();
1416                 $proxy_directives = $data['new']['proxy_directives'];
1417                 // Make sure we only have Unix linebreaks
1418                 $proxy_directives = str_replace("\r\n", "\n", $proxy_directives);
1419                 $proxy_directives = str_replace("\r", "\n", $proxy_directives);
1420                 $proxy_directive_lines = explode("\n", $proxy_directives);
1421                 if(is_array($proxy_directive_lines) && !empty($proxy_directive_lines)){
1422                     foreach($proxy_directive_lines as $proxy_directive_line){
1423                         $final_proxy_directives[] = array('proxy_directive' => $proxy_directive_line);
1424                     }
1425                 }
1426             } else {
1427                 $final_proxy_directives = false;
1428             }
1429
1430             switch($data['new']['subdomain']) {
7fe908 1431             case 'www':
MC 1432                 $exclude_own_hostname = '';
1433                 if(substr($data['new']['redirect_path'], 0, 1) == '/'){ // relative path
1434                     if($data['new']['redirect_type'] == 'proxy'){
1435                         $vhost_data['web_document_root_www_proxy'] = 'root '.$vhost_data['web_document_root_www'].';';
1436                         $vhost_data['web_document_root_www'] .= substr($data['new']['redirect_path'], 0, -1);
1437                         break;
1438                     }
1439                     $rewrite_exclude = '(?!/\b('.substr($data['new']['redirect_path'], 1, -1).(substr($data['new']['redirect_path'], 1, -1) != ''? '|': '').'stats'.($vhost_data['errordocs'] == 1 ? '|error' : '').')\b)/';
1440                 } else { // URL - check if URL is local
1441                     $tmp_redirect_path = $data['new']['redirect_path'];
1442                     if(substr($tmp_redirect_path, 0, 7) == '$scheme') $tmp_redirect_path = 'http'.substr($tmp_redirect_path, 7);
1443                     $tmp_redirect_path_parts = parse_url($tmp_redirect_path);
1444                     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']))){
1445                         // URL is local
1446                         if(substr($tmp_redirect_path_parts['path'], -1) == '/') $tmp_redirect_path_parts['path'] = substr($tmp_redirect_path_parts['path'], 0, -1);
1447                         if(substr($tmp_redirect_path_parts['path'], 0, 1) != '/') $tmp_redirect_path_parts['path'] = '/'.$tmp_redirect_path_parts['path'];
1448                         //$rewrite_exclude = '((?!'.$tmp_redirect_path_parts['path'].'))';
1449                         if($data['new']['redirect_type'] == 'proxy'){
1450                             $vhost_data['web_document_root_www_proxy'] = 'root '.$vhost_data['web_document_root_www'].';';
1451                             $vhost_data['web_document_root_www'] .= $tmp_redirect_path_parts['path'];
1452                             break;
1453                         } else {
1454                             $rewrite_exclude = '(?!/\b('.substr($tmp_redirect_path_parts['path'], 1).(substr($tmp_redirect_path_parts['path'], 1) != ''? '|': '').'stats'.($vhost_data['errordocs'] == 1 ? '|error' : '').')\b)/';
1455                             $exclude_own_hostname = $tmp_redirect_path_parts['host'];
1456                         }
1457                     } else {
1458                         // external URL
1459                         $rewrite_exclude = '(.?)/';
1460                         if($data['new']['redirect_type'] == 'proxy'){
1461                             $vhost_data['use_proxy'] = 'y';
1462                             $rewrite_subdir = $tmp_redirect_path_parts['path'];
1463                             if(substr($rewrite_subdir, 0, 1) == '/') $rewrite_subdir = substr($rewrite_subdir, 1);
1464                             if(substr($rewrite_subdir, -1) != '/') $rewrite_subdir .= '/';
1465                             if($rewrite_subdir == '/') $rewrite_subdir = '';
1466                         }
1467                     }
1468                     unset($tmp_redirect_path);
1469                     unset($tmp_redirect_path_parts);
1470                 }
1471                 $own_rewrite_rules[] = array( 'rewrite_domain'  => '^'.$this->_rewrite_quote($data['new']['domain']),
1472                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':$data['new']['redirect_type'],
1473                     'rewrite_target'  => $data['new']['redirect_path'],
1474                     'rewrite_exclude' => $rewrite_exclude,
1475                     'rewrite_subdir' => $rewrite_subdir,
1476                     'exclude_own_hostname' => $exclude_own_hostname,
1477                     'proxy_directives' => $final_proxy_directives,
1478                     'use_rewrite' => ($data['new']['redirect_type'] == 'proxy' ? false:true),
1479                     'use_proxy' => ($data['new']['redirect_type'] == 'proxy' ? true:false));
1480                 break;
1481             case '*':
1482                 $exclude_own_hostname = '';
1483                 if(substr($data['new']['redirect_path'], 0, 1) == '/'){ // relative path
1484                     if($data['new']['redirect_type'] == 'proxy'){
1485                         $vhost_data['web_document_root_www_proxy'] = 'root '.$vhost_data['web_document_root_www'].';';
1486                         $vhost_data['web_document_root_www'] .= substr($data['new']['redirect_path'], 0, -1);
1487                         break;
1488                     }
1489                     $rewrite_exclude = '(?!/\b('.substr($data['new']['redirect_path'], 1, -1).(substr($data['new']['redirect_path'], 1, -1) != ''? '|': '').'stats'.($vhost_data['errordocs'] == 1 ? '|error' : '').')\b)/';
1490                 } else { // URL - check if URL is local
1491                     $tmp_redirect_path = $data['new']['redirect_path'];
1492                     if(substr($tmp_redirect_path, 0, 7) == '$scheme') $tmp_redirect_path = 'http'.substr($tmp_redirect_path, 7);
1493                     $tmp_redirect_path_parts = parse_url($tmp_redirect_path);
1494
1495                     //if($is_serveralias && ($tmp_redirect_path_parts['port'] == '80' || $tmp_redirect_path_parts['port'] == '443' || !isset($tmp_redirect_path_parts['port']))){
1496                     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']))){
1497                         // URL is local
1498                         if(substr($tmp_redirect_path_parts['path'], -1) == '/') $tmp_redirect_path_parts['path'] = substr($tmp_redirect_path_parts['path'], 0, -1);
1499                         if(substr($tmp_redirect_path_parts['path'], 0, 1) != '/') $tmp_redirect_path_parts['path'] = '/'.$tmp_redirect_path_parts['path'];
1500                         //$rewrite_exclude = '((?!'.$tmp_redirect_path_parts['path'].'))';
1501                         if($data['new']['redirect_type'] == 'proxy'){
1502                             $vhost_data['web_document_root_www_proxy'] = 'root '.$vhost_data['web_document_root_www'].';';
1503                             $vhost_data['web_document_root_www'] .= $tmp_redirect_path_parts['path'];
1504                             break;
1505                         } else {
1506                             $rewrite_exclude = '(?!/\b('.substr($tmp_redirect_path_parts['path'], 1).(substr($tmp_redirect_path_parts['path'], 1) != ''? '|': '').'stats'.($vhost_data['errordocs'] == 1 ? '|error' : '').')\b)/';
1507                             $exclude_own_hostname = $tmp_redirect_path_parts['host'];
1508                         }
1509                     } else {
1510                         // external URL
1511                         $rewrite_exclude = '(.?)/';
1512                         if($data['new']['redirect_type'] == 'proxy'){
1513                             $vhost_data['use_proxy'] = 'y';
1514                             $rewrite_subdir = $tmp_redirect_path_parts['path'];
1515                             if(substr($rewrite_subdir, 0, 1) == '/') $rewrite_subdir = substr($rewrite_subdir, 1);
1516                             if(substr($rewrite_subdir, -1) != '/') $rewrite_subdir .= '/';
1517                             if($rewrite_subdir == '/') $rewrite_subdir = '';
1518                         }
1519                     }
1520                     unset($tmp_redirect_path);
1521                     unset($tmp_redirect_path_parts);
1522                 }
1523                 $own_rewrite_rules[] = array( 'rewrite_domain'  => '(^|\.)'.$this->_rewrite_quote($data['new']['domain']),
1524                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':$data['new']['redirect_type'],
1525                     'rewrite_target'  => $data['new']['redirect_path'],
1526                     'rewrite_exclude' => $rewrite_exclude,
1527                     'rewrite_subdir' => $rewrite_subdir,
1528                     'exclude_own_hostname' => $exclude_own_hostname,
1529                     'proxy_directives' => $final_proxy_directives,
1530                     'use_rewrite' => ($data['new']['redirect_type'] == 'proxy' ? false:true),
1531                     'use_proxy' => ($data['new']['redirect_type'] == 'proxy' ? true:false));
1532                 break;
1533             default:
1534                 if(substr($data['new']['redirect_path'], 0, 1) == '/'){ // relative path
146783 1535                     $exclude_own_hostname = '';
7fe908 1536                     if($data['new']['redirect_type'] == 'proxy'){
MC 1537                         $vhost_data['web_document_root_www_proxy'] = 'root '.$vhost_data['web_document_root_www'].';';
1538                         $vhost_data['web_document_root_www'] .= substr($data['new']['redirect_path'], 0, -1);
1539                         break;
1540                     }
1541                     $rewrite_exclude = '(?!/\b('.substr($data['new']['redirect_path'], 1, -1).(substr($data['new']['redirect_path'], 1, -1) != ''? '|': '').'stats'.($vhost_data['errordocs'] == 1 ? '|error' : '').')\b)/';
1542                 } else { // URL - check if URL is local
1543                     $tmp_redirect_path = $data['new']['redirect_path'];
1544                     if(substr($tmp_redirect_path, 0, 7) == '$scheme') $tmp_redirect_path = 'http'.substr($tmp_redirect_path, 7);
1545                     $tmp_redirect_path_parts = parse_url($tmp_redirect_path);
1546                     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']))){
1547                         // URL is local
1548                         if(substr($tmp_redirect_path_parts['path'], -1) == '/') $tmp_redirect_path_parts['path'] = substr($tmp_redirect_path_parts['path'], 0, -1);
1549                         if(substr($tmp_redirect_path_parts['path'], 0, 1) != '/') $tmp_redirect_path_parts['path'] = '/'.$tmp_redirect_path_parts['path'];
1550                         //$rewrite_exclude = '((?!'.$tmp_redirect_path_parts['path'].'))';
146783 1551                         if($data['new']['redirect_type'] == 'proxy'){
MC 1552                             $vhost_data['web_document_root_www_proxy'] = 'root '.$vhost_data['web_document_root_www'].';';
7fe908 1553                             $vhost_data['web_document_root_www'] .= $tmp_redirect_path_parts['path'];
146783 1554                             break;
MC 1555                         } else {
7fe908 1556                             $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 1557                             $exclude_own_hostname = $tmp_redirect_path_parts['host'];
146783 1558                         }
7fe908 1559                     } else {
MC 1560                         // external URL
1561                         $rewrite_exclude = '(.?)/';
146783 1562                         if($data['new']['redirect_type'] == 'proxy'){
7fe908 1563                             $vhost_data['use_proxy'] = 'y';
MC 1564                             $rewrite_subdir = $tmp_redirect_path_parts['path'];
1565                             if(substr($rewrite_subdir, 0, 1) == '/') $rewrite_subdir = substr($rewrite_subdir, 1);
1566                             if(substr($rewrite_subdir, -1) != '/') $rewrite_subdir .= '/';
1567                             if($rewrite_subdir == '/') $rewrite_subdir = '';
146783 1568                         }
MC 1569                     }
7fe908 1570                     unset($tmp_redirect_path);
MC 1571                     unset($tmp_redirect_path_parts);
1572                 }
1573                 $own_rewrite_rules[] = array( 'rewrite_domain'  => '^'.$this->_rewrite_quote($data['new']['domain']),
1574                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':$data['new']['redirect_type'],
1575                     'rewrite_target'  => $data['new']['redirect_path'],
1576                     'rewrite_exclude' => $rewrite_exclude,
1577                     'rewrite_subdir' => $rewrite_subdir,
1578                     'exclude_own_hostname' => $exclude_own_hostname,
1579                     'proxy_directives' => $final_proxy_directives,
1580                     'use_rewrite' => ($data['new']['redirect_type'] == 'proxy' ? false:true),
1581                     'use_proxy' => ($data['new']['redirect_type'] == 'proxy' ? true:false));
146783 1582             }
d22277 1583         }
MB 1584         
1585         // http2 or spdy?
1586         $vhost_data['enable_http2']  = 'n';
1587         if($vhost_data['enable_spdy'] == 'y'){
1588             // check if nginx support http_v2; if so, use that instead of spdy
1589             exec("2>&1 nginx -V | tr -- - '\n' | grep http_v2_module", $tmp_output, $tmp_retval);
1590             if($tmp_retval == 0){
1591                 $vhost_data['enable_http2']  = 'y';
1592                 $vhost_data['enable_spdy'] = 'n';
1593             }
1594             unset($tmp_output, $tmp_retval);
146783 1595         }
MC 1596
1597         $tpl->setVar($vhost_data);
7fe908 1598
146783 1599         $server_alias = array();
7fe908 1600
146783 1601         // get autoalias
MC 1602         $auto_alias = $web_config['website_autoalias'];
1603         if($auto_alias != '') {
1604             // get the client username
2af58c 1605             $client = $app->db->queryOneRecord("SELECT `username` FROM `client` WHERE `client_id` = ?", $client_id);
146783 1606             $aa_search = array('[client_id]', '[website_id]', '[client_username]', '[website_domain]');
MC 1607             $aa_replace = array($client_id, $data['new']['domain_id'], $client['username'], $data['new']['domain']);
1608             $auto_alias = str_replace($aa_search, $aa_replace, $auto_alias);
1609             unset($client);
1610             unset($aa_search);
1611             unset($aa_replace);
1612             $server_alias[] .= $auto_alias.' ';
1613         }
7fe908 1614
146783 1615         switch($data['new']['subdomain']) {
7fe908 1616         case 'www':
MC 1617             $server_alias[] = 'www.'.$data['new']['domain'].' ';
1618             break;
1619         case '*':
1620             $server_alias[] = '*.'.$data['new']['domain'].' ';
1621             break;
146783 1622         }
MC 1623
1624         // get alias domains (co-domains and subdomains)
2af58c 1625         $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 1626         $alias_seo_redirects = array();
MC 1627         if(is_array($aliases)) {
1628             foreach($aliases as $alias) {
7fe908 1629
146783 1630                 // Custom proxy directives
MC 1631                 if($alias['redirect_type'] == 'proxy' && trim($alias['proxy_directives'] != '')){
1632                     $final_proxy_directives = array();
1633                     $proxy_directives = $alias['proxy_directives'];
1634                     // Make sure we only have Unix linebreaks
1635                     $proxy_directives = str_replace("\r\n", "\n", $proxy_directives);
1636                     $proxy_directives = str_replace("\r", "\n", $proxy_directives);
1637                     $proxy_directive_lines = explode("\n", $proxy_directives);
1638                     if(is_array($proxy_directive_lines) && !empty($proxy_directive_lines)){
1639                         foreach($proxy_directive_lines as $proxy_directive_line){
1640                             $final_proxy_directives[] = array('proxy_directive' => $proxy_directive_line);
1641                         }
1642                     }
1643                 } else {
1644                     $final_proxy_directives = false;
1645                 }
7fe908 1646
MC 1647                 if($alias['redirect_type'] == '' || $alias['redirect_path'] == '' || substr($alias['redirect_path'], 0, 1) == '/') {
146783 1648                     switch($alias['subdomain']) {
7fe908 1649                     case 'www':
MC 1650                         $server_alias[] = 'www.'.$alias['domain'].' '.$alias['domain'].' ';
1651                         break;
1652                     case '*':
1653                         $server_alias[] = '*.'.$alias['domain'].' '.$alias['domain'].' ';
1654                         break;
1655                     default:
1656                         $server_alias[] = $alias['domain'].' ';
1657                         break;
146783 1658                     }
7fe908 1659                     $app->log('Add server alias: '.$alias['domain'], LOGLEVEL_DEBUG);
MC 1660
146783 1661                     // Add SEO redirects for alias domains
MC 1662                     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'))){
1663                         $tmp_seo_redirects = $this->get_seo_redirects($alias, 'alias_');
1664                         if(is_array($tmp_seo_redirects) && !empty($tmp_seo_redirects)){
1665                             $alias_seo_redirects[] = $tmp_seo_redirects;
1666                         }
1667                     }
1668                 }
1669
7fe908 1670                 // Local Rewriting (inside vhost server {} container)
MC 1671                 if($alias['redirect_type'] != '' && substr($alias['redirect_path'], 0, 1) == '/' && $alias['redirect_type'] != 'proxy') {  // proxy makes no sense with local path
1672                     if(substr($alias['redirect_path'], -1) != '/') $alias['redirect_path'] .= '/';
1673                     $rewrite_exclude = '(?!/\b('.substr($alias['redirect_path'], 1, -1).(substr($alias['redirect_path'], 1, -1) != ''? '|': '').'stats'.($vhost_data['errordocs'] == 1 ? '|error' : '').')\b)/';
1674                     switch($alias['subdomain']) {
1675                     case 'www':
1676                         // example.com
1677                         $local_rewrite_rules[] = array( 'local_redirect_origin_domain'  => $alias['domain'],
1678                             'local_redirect_operator' => '=',
1679                             'local_redirect_exclude' => $rewrite_exclude,
1680                             'local_redirect_target' => $alias['redirect_path'],
1681                             'local_redirect_type' => ($alias['redirect_type'] == 'no')?'':$alias['redirect_type']);
1682
1683                         // www.example.com
1684                         $local_rewrite_rules[] = array( 'local_redirect_origin_domain'  => 'www.'.$alias['domain'],
1685                             'local_redirect_operator' => '=',
1686                             'local_redirect_exclude' => $rewrite_exclude,
1687                             'local_redirect_target' => $alias['redirect_path'],
1688                             'local_redirect_type' => ($alias['redirect_type'] == 'no')?'':$alias['redirect_type']);
1689                         break;
1690                     case '*':
1691                         $local_rewrite_rules[] = array( 'local_redirect_origin_domain'  => '^('.str_replace('.', '\.', $alias['domain']).'|.+\.'.str_replace('.', '\.', $alias['domain']).')$',
1692                             'local_redirect_operator' => '~*',
1693                             'local_redirect_exclude' => $rewrite_exclude,
1694                             'local_redirect_target' => $alias['redirect_path'],
1695                             'local_redirect_type' => ($alias['redirect_type'] == 'no')?'':$alias['redirect_type']);
1696                         break;
1697                     default:
1698                         $local_rewrite_rules[] = array( 'local_redirect_origin_domain'  => $alias['domain'],
1699                             'local_redirect_operator' => '=',
1700                             'local_redirect_exclude' => $rewrite_exclude,
1701                             'local_redirect_target' => $alias['redirect_path'],
1702                             'local_redirect_type' => ($alias['redirect_type'] == 'no')?'':$alias['redirect_type']);
146783 1703                     }
MC 1704                 }
7fe908 1705
146783 1706                 // External Rewriting (extra server {} containers)
7fe908 1707                 if($alias['redirect_type'] != '' && $alias['redirect_path'] != '' && substr($alias['redirect_path'], 0, 1) != '/') {
MC 1708                     if(substr($alias['redirect_path'], -1) != '/') $alias['redirect_path'] .= '/';
1709                     if(substr($alias['redirect_path'], 0, 8) == '[scheme]'){
146783 1710                         if($alias['redirect_type'] != 'proxy'){
7fe908 1711                             $alias['redirect_path'] = '$scheme'.substr($alias['redirect_path'], 8);
146783 1712                         } else {
7fe908 1713                             $alias['redirect_path'] = 'http'.substr($alias['redirect_path'], 8);
146783 1714                         }
MC 1715                     }
1716
7fe908 1717                     switch($alias['subdomain']) {
MC 1718                     case 'www':
1719                         if($alias['redirect_type'] == 'proxy'){
1720                             $tmp_redirect_path = $alias['redirect_path'];
1721                             $tmp_redirect_path_parts = parse_url($tmp_redirect_path);
1722                             $rewrite_subdir = $tmp_redirect_path_parts['path'];
1723                             if(substr($rewrite_subdir, 0, 1) == '/') $rewrite_subdir = substr($rewrite_subdir, 1);
1724                             if(substr($rewrite_subdir, -1) != '/') $rewrite_subdir .= '/';
1725                             if($rewrite_subdir == '/') $rewrite_subdir = '';
1726                         }
1727
1728                         if($alias['redirect_type'] != 'proxy'){
1729                             if(substr($alias['redirect_path'], -1) == '/') $alias['redirect_path'] = substr($alias['redirect_path'], 0, -1);
1730                         }
1731                         // Add SEO redirects for alias domains
1732                         $alias_seo_redirects2 = array();
1733                         if($alias['seo_redirect'] != ''){
1734                             $tmp_seo_redirects = $this->get_seo_redirects($alias, 'alias_', 'none');
1735                             if(is_array($tmp_seo_redirects) && !empty($tmp_seo_redirects)){
1736                                 $alias_seo_redirects2[] = $tmp_seo_redirects;
146783 1737                             }
7fe908 1738                         }
MC 1739                         $rewrite_rules[] = array( 'rewrite_domain'  => $alias['domain'],
1740                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':$alias['redirect_type'],
1741                             'rewrite_target'  => $alias['redirect_path'],
1742                             'rewrite_subdir' => $rewrite_subdir,
1743                             'proxy_directives' => $final_proxy_directives,
1744                             'use_rewrite' => ($alias['redirect_type'] == 'proxy' ? false:true),
1745                             'use_proxy' => ($alias['redirect_type'] == 'proxy' ? true:false),
1746                             'alias_seo_redirects2' => (count($alias_seo_redirects2) > 0 ? $alias_seo_redirects2 : false));
1747
1748                         // Add SEO redirects for alias domains
1749                         $alias_seo_redirects2 = array();
1750                         if($alias['seo_redirect'] != ''){
1751                             $tmp_seo_redirects = $this->get_seo_redirects($alias, 'alias_', 'www');
1752                             if(is_array($tmp_seo_redirects) && !empty($tmp_seo_redirects)){
1753                                 $alias_seo_redirects2[] = $tmp_seo_redirects;
146783 1754                             }
7fe908 1755                         }
MC 1756                         $rewrite_rules[] = array( 'rewrite_domain'  => 'www.'.$alias['domain'],
1757                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':$alias['redirect_type'],
1758                             'rewrite_target'  => $alias['redirect_path'],
1759                             'rewrite_subdir' => $rewrite_subdir,
1760                             'proxy_directives' => $final_proxy_directives,
1761                             'use_rewrite' => ($alias['redirect_type'] == 'proxy' ? false:true),
1762                             'use_proxy' => ($alias['redirect_type'] == 'proxy' ? true:false),
1763                             'alias_seo_redirects2' => (count($alias_seo_redirects2) > 0 ? $alias_seo_redirects2 : false));
1764                         break;
1765                     case '*':
1766                         if($alias['redirect_type'] == 'proxy'){
1767                             $tmp_redirect_path = $alias['redirect_path'];
1768                             $tmp_redirect_path_parts = parse_url($tmp_redirect_path);
1769                             $rewrite_subdir = $tmp_redirect_path_parts['path'];
1770                             if(substr($rewrite_subdir, 0, 1) == '/') $rewrite_subdir = substr($rewrite_subdir, 1);
1771                             if(substr($rewrite_subdir, -1) != '/') $rewrite_subdir .= '/';
1772                             if($rewrite_subdir == '/') $rewrite_subdir = '';
1773                         }
1774
1775                         if($alias['redirect_type'] != 'proxy'){
1776                             if(substr($alias['redirect_path'], -1) == '/') $alias['redirect_path'] = substr($alias['redirect_path'], 0, -1);
1777                         }
1778                         // Add SEO redirects for alias domains
1779                         $alias_seo_redirects2 = array();
1780                         if($alias['seo_redirect'] != ''){
1781                             $tmp_seo_redirects = $this->get_seo_redirects($alias, 'alias_');
1782                             if(is_array($tmp_seo_redirects) && !empty($tmp_seo_redirects)){
1783                                 $alias_seo_redirects2[] = $tmp_seo_redirects;
146783 1784                             }
7fe908 1785                         }
MC 1786                         $rewrite_rules[] = array( 'rewrite_domain'  => $alias['domain'].' *.'.$alias['domain'],
1787                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':$alias['redirect_type'],
1788                             'rewrite_target'  => $alias['redirect_path'],
1789                             'rewrite_subdir' => $rewrite_subdir,
1790                             'proxy_directives' => $final_proxy_directives,
1791                             'use_rewrite' => ($alias['redirect_type'] == 'proxy' ? false:true),
1792                             'use_proxy' => ($alias['redirect_type'] == 'proxy' ? true:false),
1793                             'alias_seo_redirects2' => (count($alias_seo_redirects2) > 0 ? $alias_seo_redirects2 : false));
1794                         break;
1795                     default:
1796                         if($alias['redirect_type'] == 'proxy'){
1797                             $tmp_redirect_path = $alias['redirect_path'];
1798                             $tmp_redirect_path_parts = parse_url($tmp_redirect_path);
1799                             $rewrite_subdir = $tmp_redirect_path_parts['path'];
1800                             if(substr($rewrite_subdir, 0, 1) == '/') $rewrite_subdir = substr($rewrite_subdir, 1);
1801                             if(substr($rewrite_subdir, -1) != '/') $rewrite_subdir .= '/';
1802                             if($rewrite_subdir == '/') $rewrite_subdir = '';
1803                         }
1804
1805                         if($alias['redirect_type'] != 'proxy'){
1806                             if(substr($alias['redirect_path'], -1) == '/') $alias['redirect_path'] = substr($alias['redirect_path'], 0, -1);
1807                         }
1808                         if(substr($alias['domain'], 0, 2) === '*.') $domain_rule = '*.'.substr($alias['domain'], 2);
1809                         else $domain_rule = $alias['domain'];
1810                         // Add SEO redirects for alias domains
1811                         $alias_seo_redirects2 = array();
1812                         if($alias['seo_redirect'] != ''){
1813                             if(substr($alias['domain'], 0, 2) === '*.'){
146783 1814                                 $tmp_seo_redirects = $this->get_seo_redirects($alias, 'alias_');
7fe908 1815                             } else {
MC 1816                                 $tmp_seo_redirects = $this->get_seo_redirects($alias, 'alias_', 'none');
146783 1817                             }
7fe908 1818                             if(is_array($tmp_seo_redirects) && !empty($tmp_seo_redirects)){
MC 1819                                 $alias_seo_redirects2[] = $tmp_seo_redirects;
146783 1820                             }
7fe908 1821                         }
MC 1822                         $rewrite_rules[] = array( 'rewrite_domain'  => $domain_rule,
1823                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':$alias['redirect_type'],
1824                             'rewrite_target'  => $alias['redirect_path'],
1825                             'rewrite_subdir' => $rewrite_subdir,
1826                             'proxy_directives' => $final_proxy_directives,
1827                             'use_rewrite' => ($alias['redirect_type'] == 'proxy' ? false:true),
1828                             'use_proxy' => ($alias['redirect_type'] == 'proxy' ? true:false),
1829                             'alias_seo_redirects2' => (count($alias_seo_redirects2) > 0 ? $alias_seo_redirects2 : false));
146783 1830                     }
MC 1831                 }
1832             }
1833         }
1834
1835         //* If we have some alias records
1836         if(count($server_alias) > 0) {
1837             $server_alias_str = '';
1838             $n = 0;
1839
1840             foreach($server_alias as $tmp_alias) {
1841                 $server_alias_str .= $tmp_alias;
1842             }
1843             unset($tmp_alias);
1844
7fe908 1845             $tpl->setVar('alias', trim($server_alias_str));
146783 1846         } else {
7fe908 1847             $tpl->setVar('alias', '');
146783 1848         }
MC 1849
1850         if(count($rewrite_rules) > 0) {
7fe908 1851             $tpl->setLoop('redirects', $rewrite_rules);
146783 1852         }
MC 1853         if(count($own_rewrite_rules) > 0) {
7fe908 1854             $tpl->setLoop('own_redirects', $own_rewrite_rules);
146783 1855         }
MC 1856         if(count($local_rewrite_rules) > 0) {
7fe908 1857             $tpl->setLoop('local_redirects', $local_rewrite_rules);
146783 1858         }
MC 1859         if(count($alias_seo_redirects) > 0) {
7fe908 1860             $tpl->setLoop('alias_seo_redirects', $alias_seo_redirects);
146783 1861         }
7fe908 1862
146783 1863         //* Create basic http auth for website statistics
MC 1864         $tpl->setVar('stats_auth_passwd_file', $data['new']['document_root']."/web/stats/.htpasswd_stats");
7fe908 1865
146783 1866         // Create basic http auth for other directories
MC 1867         $basic_auth_locations = $this->_create_web_folder_auth_configuration($data['new']);
1868         if(is_array($basic_auth_locations) && !empty($basic_auth_locations)) $tpl->setLoop('basic_auth_locations', $basic_auth_locations);
1869
1870         $vhost_file = escapeshellcmd($web_config['nginx_vhost_conf_dir'].'/'.$data['new']['domain'].'.vhost');
1871         //* Make a backup copy of vhost file
7fe908 1872         if(file_exists($vhost_file)) copy($vhost_file, $vhost_file.'~');
MC 1873
146783 1874         //* Write vhost file
7fe908 1875         $app->system->file_put_contents($vhost_file, $this->nginx_merge_locations($tpl->grab()));
MC 1876         $app->log('Writing the vhost file: '.$vhost_file, LOGLEVEL_DEBUG);
146783 1877         unset($tpl);
MC 1878
1879         //* Set the symlink to enable the vhost
1880         //* First we check if there is a old type of symlink and remove it
1881         $vhost_symlink = escapeshellcmd($web_config['nginx_vhost_conf_enabled_dir'].'/'.$data['new']['domain'].'.vhost');
1882         if(is_link($vhost_symlink)) unlink($vhost_symlink);
7fe908 1883
146783 1884         //* Remove old or changed symlinks
MC 1885         if($data['new']['subdomain'] != $data['old']['subdomain'] or $data['new']['active'] == 'n') {
1886             $vhost_symlink = escapeshellcmd($web_config['nginx_vhost_conf_enabled_dir'].'/900-'.$data['new']['domain'].'.vhost');
1887             if(is_link($vhost_symlink)) {
1888                 $app->system->unlink($vhost_symlink);
7fe908 1889                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
146783 1890             }
MC 1891             $vhost_symlink = escapeshellcmd($web_config['nginx_vhost_conf_enabled_dir'].'/100-'.$data['new']['domain'].'.vhost');
1892             if(is_link($vhost_symlink)) {
1893                 $app->system->unlink($vhost_symlink);
7fe908 1894                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
146783 1895             }
MC 1896         }
7fe908 1897
146783 1898         //* New symlink
MC 1899         if($data['new']['subdomain'] == '*') {
1900             $vhost_symlink = escapeshellcmd($web_config['nginx_vhost_conf_enabled_dir'].'/900-'.$data['new']['domain'].'.vhost');
1901         } else {
1902             $vhost_symlink = escapeshellcmd($web_config['nginx_vhost_conf_enabled_dir'].'/100-'.$data['new']['domain'].'.vhost');
1903         }
1904         if($data['new']['active'] == 'y' && !is_link($vhost_symlink)) {
7fe908 1905             symlink($vhost_file, $vhost_symlink);
MC 1906             $app->log('Creating symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
146783 1907         }
MC 1908
1909         // remove old symlink and vhost file, if domain name of the site has changed
1910         if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
1911             $vhost_symlink = escapeshellcmd($web_config['nginx_vhost_conf_enabled_dir'].'/900-'.$data['old']['domain'].'.vhost');
1912             if(is_link($vhost_symlink)) {
1913                 $app->system->unlink($vhost_symlink);
7fe908 1914                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
146783 1915             }
MC 1916             $vhost_symlink = escapeshellcmd($web_config['nginx_vhost_conf_enabled_dir'].'/100-'.$data['old']['domain'].'.vhost');
1917             if(is_link($vhost_symlink)) {
1918                 $app->system->unlink($vhost_symlink);
7fe908 1919                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
146783 1920             }
MC 1921             $vhost_symlink = escapeshellcmd($web_config['nginx_vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
1922             if(is_link($vhost_symlink)) {
1923                 $app->system->unlink($vhost_symlink);
7fe908 1924                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
146783 1925             }
MC 1926             $vhost_file = escapeshellcmd($web_config['nginx_vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
1927             $app->system->unlink($vhost_file);
7fe908 1928             $app->log('Removing file: '.$vhost_file, LOGLEVEL_DEBUG);
146783 1929         }
7fe908 1930
146783 1931         // create password file for stats directory
MC 1932         if(!is_file($data['new']['document_root'].'/web/stats/.htpasswd_stats') || $data['new']['stats_password'] != $data['old']['stats_password']) {
1933             if(trim($data['new']['stats_password']) != '') {
1934                 $htp_file = 'admin:'.trim($data['new']['stats_password']);
7fe908 1935                 $app->system->file_put_contents($data['new']['document_root'].'/web/stats/.htpasswd_stats', $htp_file);
MC 1936                 $app->system->chmod($data['new']['document_root'].'/web/stats/.htpasswd_stats', 0755);
146783 1937                 unset($htp_file);
MC 1938             }
1939         }
7fe908 1940
146783 1941         //* Create awstats configuration
511ba5 1942         if($data['new']['stats_type'] == 'awstats' && ($data['new']['type'] == 'vhost' || $data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias')) {
7fe908 1943             $this->awstats_update($data, $web_config);
146783 1944         }
7fe908 1945
MC 1946         $this->php_fpm_pool_update($data, $web_config, $pool_dir, $pool_name, $socket_dir);
1c6da3 1947         $this->hhvm_update($data, $web_config);
7fe908 1948
146783 1949         if($web_config['check_apache_config'] == 'y') {
MC 1950             //* Test if nginx starts with the new configuration file
7fe908 1951             $nginx_online_status_before_restart = $this->_checkTcp('localhost', 80);
MC 1952             $app->log('nginx status is: '.($nginx_online_status_before_restart === true? 'running' : 'down'), LOGLEVEL_DEBUG);
146783 1953
7fe908 1954             $retval = $app->services->restartService('httpd', 'restart'); // $retval['retval'] is 0 on success and > 0 on failure
MC 1955             $app->log('nginx restart return value is: '.$retval['retval'], LOGLEVEL_DEBUG);
1956
146783 1957             // wait a few seconds, before we test the apache status again
MC 1958             sleep(2);
7fe908 1959
146783 1960             //* Check if nginx restarted successfully if it was online before
7fe908 1961             $nginx_online_status_after_restart = $this->_checkTcp('localhost', 80);
MC 1962             $app->log('nginx online status after restart is: '.($nginx_online_status_after_restart === true? 'running' : 'down'), LOGLEVEL_DEBUG);
1963             if($nginx_online_status_before_restart && !$nginx_online_status_after_restart || $retval['retval'] > 0) {
1964                 $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 1965                 if(is_array($retval['output']) && !empty($retval['output'])){
7fe908 1966                     $app->log('Reason for nginx restart failure: '.implode("\n", $retval['output']), LOGLEVEL_WARN);
146783 1967                     $app->dbmaster->datalogError(implode("\n", $retval['output']));
MC 1968                 } else {
1969                     // if no output is given, check again
1970                     exec('nginx -t 2>&1', $tmp_output, $tmp_retval);
1971                     if($tmp_retval > 0 && is_array($tmp_output) && !empty($tmp_output)){
7fe908 1972                         $app->log('Reason for nginx restart failure: '.implode("\n", $tmp_output), LOGLEVEL_WARN);
146783 1973                         $app->dbmaster->datalogError(implode("\n", $tmp_output));
MC 1974                     }
1975                     unset($tmp_output, $tmp_retval);
1976                 }
7fe908 1977                 $app->system->copy($vhost_file, $vhost_file.'.err');
MC 1978
146783 1979                 if(is_file($vhost_file.'~')) {
MC 1980                     //* Copy back the last backup file
7fe908 1981                     $app->system->copy($vhost_file.'~', $vhost_file);
146783 1982                 } else {
MC 1983                     //* There is no backup file, so we create a empty vhost file with a warning message inside
7fe908 1984                     $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 1985                 }
7fe908 1986
146783 1987                 if($this->ssl_certificate_changed === true) {
MC 1988
1989                     $ssl_dir = $data['new']['document_root'].'/ssl';
1990                     $domain = $data['new']['ssl_domain'];
1991                     $key_file = $ssl_dir.'/'.$domain.'.key.org';
1992                     $key_file2 = $ssl_dir.'/'.$domain.'.key';
1993                     $csr_file = $ssl_dir.'/'.$domain.'.csr';
1994                     $crt_file = $ssl_dir.'/'.$domain.'.crt';
1995                     //$bundle_file = $ssl_dir.'/'.$domain.'.bundle';
7fe908 1996
146783 1997                     //* Backup the files that might have caused the error
MC 1998                     if(is_file($key_file)){
7fe908 1999                         $app->system->copy($key_file, $key_file.'.err');
MC 2000                         $app->system->chmod($key_file.'.err', 0400);
146783 2001                     }
MC 2002                     if(is_file($key_file2)){
7fe908 2003                         $app->system->copy($key_file2, $key_file2.'.err');
MC 2004                         $app->system->chmod($key_file2.'.err', 0400);
146783 2005                     }
7fe908 2006                     if(is_file($csr_file)) $app->system->copy($csr_file, $csr_file.'.err');
MC 2007                     if(is_file($crt_file)) $app->system->copy($crt_file, $crt_file.'.err');
146783 2008                     //if(is_file($bundle_file)) $app->system->copy($bundle_file,$bundle_file.'.err');
7fe908 2009
146783 2010                     //* Restore the ~ backup files
7fe908 2011                     if(is_file($key_file.'~')) $app->system->copy($key_file.'~', $key_file);
MC 2012                     if(is_file($key_file2.'~')) $app->system->copy($key_file2.'~', $key_file2);
2013                     if(is_file($crt_file.'~')) $app->system->copy($crt_file.'~', $crt_file);
2014                     if(is_file($csr_file.'~')) $app->system->copy($csr_file.'~', $csr_file);
146783 2015                     //if(is_file($bundle_file.'~')) $app->system->copy($bundle_file.'~',$bundle_file);
7fe908 2016
MC 2017                     $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 2018                 }
7fe908 2019
MC 2020                 $app->services->restartService('httpd', 'restart');
146783 2021             }
MC 2022         } else {
2023             //* We do not check the nginx config after changes (is faster)
7fe908 2024             $app->services->restartServiceDelayed('httpd', 'reload');
146783 2025         }
7fe908 2026
MC 2027         //* The vhost is written and apache has been restarted, so we
146783 2028         // can reset the ssl changed var to false and cleanup some files
MC 2029         $this->ssl_certificate_changed = false;
7fe908 2030
146783 2031         $ssl_dir = $data['new']['document_root'].'/ssl';
MC 2032         $domain = $data['new']['ssl_domain'];
2033         $key_file = $ssl_dir.'/'.$domain.'.key.org';
2034         $key_file2 = $ssl_dir.'/'.$domain.'.key';
2035         $csr_file = $ssl_dir.'/'.$domain.'.csr';
2036         $crt_file = $ssl_dir.'/'.$domain.'.crt';
2037         //$bundle_file = $ssl_dir.'/'.$domain.'.bundle';
7fe908 2038
146783 2039         if(@is_file($key_file.'~')) $app->system->unlink($key_file.'~');
MC 2040         if(@is_file($key2_file.'~')) $app->system->unlink($key2_file.'~');
2041         if(@is_file($crt_file.'~')) $app->system->unlink($crt_file.'~');
2042         if(@is_file($csr_file.'~')) $app->system->unlink($csr_file.'~');
2043         //if(@is_file($bundle_file.'~')) $app->system->unlink($bundle_file.'~');
7fe908 2044
146783 2045         // Remove the backup copy of the config file.
MC 2046         if(@is_file($vhost_file.'~')) $app->system->unlink($vhost_file.'~');
2047
2048         //* Unset action to clean it for next processed vhost.
2049         $this->action = '';
2050
2051     }
2052
7fe908 2053     function delete($event_name, $data) {
146783 2054         global $app, $conf;
MC 2055
2056         // load the server configuration options
2057         $app->uses('getconf');
2058         $app->uses('system');
2059         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
7fe908 2060
511ba5 2061         if($data['old']['type'] == 'vhost' || $data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') $app->system->web_folder_protection($data['old']['document_root'], false);
146783 2062
MC 2063         //* Check if this is a chrooted setup
2064         if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
2065             $nginx_chrooted = true;
2066         } else {
2067             $nginx_chrooted = false;
2068         }
7fe908 2069
146783 2070         //* Remove the mounts
MC 2071         $log_folder = 'log';
7fe908 2072         $web_folder = '';
511ba5 2073         if($data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') {
2af58c 2074             $tmp = $app->db->queryOneRecord('SELECT `domain`,`document_root` FROM web_domain WHERE domain_id = ?', $data['old']['parent_domain_id']);
146783 2075             if($tmp['domain'] != ''){
MC 2076                 $subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $data['old']['domain']);
2077             } else {
2078                 // get log folder from /etc/fstab
2079                 /*
2080                 $bind_mounts = $app->system->file_get_contents('/etc/fstab');
2081                 $bind_mount_lines = explode("\n", $bind_mounts);
2082                 if(is_array($bind_mount_lines) && !empty($bind_mount_lines)){
2083                     foreach($bind_mount_lines as $bind_mount_line){
2084                         $bind_mount_line = preg_replace('/\s+/', ' ', $bind_mount_line);
2085                         $bind_mount_parts = explode(' ', $bind_mount_line);
2086                         if(is_array($bind_mount_parts) && !empty($bind_mount_parts)){
2087                             if($bind_mount_parts[0] == '/var/log/ispconfig/httpd/'.$data['old']['domain'] && $bind_mount_parts[2] == 'none' && strpos($bind_mount_parts[3], 'bind') !== false){
2088                                 $subdomain_host = str_replace($data['old']['document_root'].'/log/', '', $bind_mount_parts[1]);
2089                             }
2090                         }
2091                     }
2092                 }
2093                 */
2094                 // we are deleting the parent domain, so we can delete everything in the log directory
2095                 $subdomain_hosts = array();
7fe908 2096                 $files = array_diff(scandir($data['old']['document_root'].'/'.$log_folder), array('.', '..'));
146783 2097                 if(is_array($files) && !empty($files)){
MC 2098                     foreach($files as $file){
2099                         if(is_dir($data['old']['document_root'].'/'.$log_folder.'/'.$file)){
2100                             $subdomain_hosts[] = $file;
2101                         }
2102                     }
2103                 }
2104             }
2105             if(is_array($subdomain_hosts) && !empty($subdomain_hosts)){
2106                 $log_folders = array();
2107                 foreach($subdomain_hosts as $subdomain_host){
2108                     $log_folders[] = $log_folder.'/'.$subdomain_host;
2109                 }
2110             } else {
2111                 if($subdomain_host == '') $subdomain_host = 'web'.$data['old']['domain_id'];
2112                 $log_folder .= '/' . $subdomain_host;
2113             }
2114             $web_folder = $data['old']['web_folder'];
7fe908 2115             unset($tmp);
146783 2116             unset($subdomain_hosts);
MC 2117         }
7fe908 2118
511ba5 2119         if($data['old']['type'] == 'vhost' || $data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias'){
146783 2120             if(is_array($log_folders) && !empty($log_folders)){
MC 2121                 foreach($log_folders as $log_folder){
2122                     //if($app->system->is_mounted($data['old']['document_root'].'/'.$log_folder)) exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder));
a9b325 2123                     //exec('fuser -km '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
146783 2124                     exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
MC 2125                 }
2126             } else {
2127                 //if($app->system->is_mounted($data['old']['document_root'].'/'.$log_folder)) exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder));
a9b325 2128                 //exec('fuser -km '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
146783 2129                 exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
MC 2130             }
a49635 2131
MB 2132             // remove letsencrypt if it exists (renew will always fail otherwise)
2133             $domain = $data['old']['ssl_domain'];
2134             if(!$domain) $domain = $data['old']['domain'];
2135             if(substr($domain, 0, 2) === '*.') {
2136                 // wildcard domain not yet supported by letsencrypt!
2137                 $domain = substr($domain, 2);
2138             }
2139             //$crt_tmp_file = "/etc/letsencrypt/live/".$domain."/cert.pem";
2140             //$key_tmp_file = "/etc/letsencrypt/live/".$domain."/privkey.pem";
2141             $le_conf_file = '/etc/letsencrypt/renewal/' . $domain . '.conf';
2142             @rename('/etc/letsencrypt/renewal/' . $domain . '.conf', '/etc/letsencrypt/renewal/' . $domain . '.conf~backup');
146783 2143         }
7fe908 2144
146783 2145         //* remove mountpoint from fstab
MC 2146         if(is_array($log_folders) && !empty($log_folders)){
2147             foreach($log_folders as $log_folder){
2148                 $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$log_folder.'    none    bind';
7fe908 2149                 $app->system->removeLine('/etc/fstab', $fstab_line);
146783 2150             }
MC 2151         } else {
2152             $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$log_folder.'    none    bind';
7fe908 2153             $app->system->removeLine('/etc/fstab', $fstab_line);
146783 2154         }
MC 2155         unset($log_folders);
2156
511ba5 2157         if($data['old']['type'] != 'vhost' && $data['old']['type'] != 'vhostsubdomain' && $data['old']['type'] != 'vhostalias' && $data['old']['parent_domain_id'] > 0) {
146783 2158             //* This is a alias domain or subdomain, so we have to update the website instead
MC 2159             $parent_domain_id = intval($data['old']['parent_domain_id']);
2af58c 2160             $tmp = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ? AND active = 'y'", $parent_domain_id);
146783 2161             $data['new'] = $tmp;
MC 2162             $data['old'] = $tmp;
2163             $this->action = 'update';
496602 2164             $this->update_letsencrypt = true;
146783 2165             // just run the update function
7fe908 2166             $this->update($event_name, $data);
146783 2167
MC 2168         } else {
2169             //* This is a website
7fe908 2170             // Deleting the vhost file, symlink and the data directory
146783 2171             $vhost_file = escapeshellcmd($web_config['nginx_vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
7fe908 2172
146783 2173             $vhost_symlink = escapeshellcmd($web_config['nginx_vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
MC 2174             if(is_link($vhost_symlink)){
2175                 $app->system->unlink($vhost_symlink);
7fe908 2176                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
146783 2177             }
MC 2178             $vhost_symlink = escapeshellcmd($web_config['nginx_vhost_conf_enabled_dir'].'/900-'.$data['old']['domain'].'.vhost');
2179             if(is_link($vhost_symlink)){
2180                 $app->system->unlink($vhost_symlink);
7fe908 2181                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
146783 2182             }
MC 2183             $vhost_symlink = escapeshellcmd($web_config['nginx_vhost_conf_enabled_dir'].'/100-'.$data['old']['domain'].'.vhost');
2184             if(is_link($vhost_symlink)){
2185                 $app->system->unlink($vhost_symlink);
7fe908 2186                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
146783 2187             }
7fe908 2188
146783 2189             $app->system->unlink($vhost_file);
7fe908 2190             $app->log('Removing vhost file: '.$vhost_file, LOGLEVEL_DEBUG);
146783 2191
511ba5 2192             if($data['old']['type'] == 'vhost' || $data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') {
7fe908 2193                 $docroot = escapeshellcmd($data['old']['document_root']);
MC 2194                 if($docroot != '' && !stristr($docroot, '..')) {
2195                     if($data['old']['type'] == 'vhost') {
2196                         // this is a vhost - we delete everything in here.
2197                         exec('rm -rf '.$docroot);
2198                     } elseif(!stristr($data['old']['web_folder'], '..')) {
2199                         // this is a vhost subdomain
2200                         // IMPORTANT: do some folder checks before we delete this!
2201                         $do_delete = true;
2202                         $delete_folder = preg_replace('/[\/]{2,}/', '/', $web_folder); // replace / occuring multiple times
2203                         if(substr($delete_folder, 0, 1) === '/') $delete_folder = substr($delete_folder, 1);
2204                         if(substr($delete_folder, -1) === '/') $delete_folder = substr($delete_folder, 0, -1);
146783 2205
7fe908 2206                         $path_elements = explode('/', $delete_folder);
146783 2207
7fe908 2208                         if($path_elements[0] == 'web' || $path_elements[0] === '') {
MC 2209                             // paths beginning with /web should NEVER EVER be deleted, empty paths should NEVER occur - but for safety reasons we check it here!
2210                             // we use strict check as otherwise directories named '0' may not be deleted
2211                             $do_delete = false;
2212                         } else {
2213                             // read all vhost subdomains with same parent domain
2214                             $used_paths = array();
2af58c 2215                             $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 2216                             foreach($tmp as $tmprec) {
MC 2217                                 // we normalize the folder entries because we need to compare them
2218                                 $tmp_folder = preg_replace('/[\/]{2,}/', '/', $tmprec['web_folder']); // replace / occuring multiple times
2219                                 if(substr($tmp_folder, 0, 1) === '/') $tmp_folder = substr($tmp_folder, 1);
2220                                 if(substr($tmp_folder, -1) === '/') $tmp_folder = substr($tmp_folder, 0, -1);
146783 2221
7fe908 2222                                 // add this path and it's parent paths to used_paths array
MC 2223                                 while(strpos($tmp_folder, '/') !== false) {
2224                                     if(in_array($tmp_folder, $used_paths) == false) $used_paths[] = $tmp_folder;
2225                                     $tmp_folder = substr($tmp_folder, 0, strrpos($tmp_folder, '/'));
2226                                 }
2227                                 if(in_array($tmp_folder, $used_paths) == false) $used_paths[] = $tmp_folder;
2228                             }
2229                             unset($tmp);
146783 2230
7fe908 2231                             // loop and check if the path is still used and stop at first used one
MC 2232                             // set do_delete to false so nothing gets deleted if the web_folder itself is still used
2233                             $do_delete = false;
2234                             while(count($path_elements) > 0) {
2235                                 $tmp_folder = implode('/', $path_elements);
2236                                 if(in_array($tmp_folder, $used_paths) == true) break;
2237
2238                                 // this path is not used - set it as path to delete, strip the last element from the array and set do_delete to true
2239                                 $delete_folder = $tmp_folder;
2240                                 $do_delete = true;
2241                                 array_pop($path_elements);
2242                             }
2243                             unset($tmp_folder);
2244                             unset($used_paths);
2245                         }
2246
2247                         if($do_delete === true && $delete_folder !== '') exec('rm -rf '.$docroot.'/'.$delete_folder);
2248
2249                         unset($delete_folder);
2250                         unset($path_elements);
2251                     }
2252                 }
2253
2254                 //remove the php fastgi starter script if available
2255                 if ($data['old']['php'] == 'fast-cgi') {
2256                     $this->php_fpm_pool_delete($data, $web_config);
2257                     $fastcgi_starter_path = str_replace('[system_user]', $data['old']['system_user'], $web_config['fastcgi_starter_path']);
2258                     if($data['old']['type'] == 'vhost') {
2259                         if (is_dir($fastcgi_starter_path)) {
2260                             exec('rm -rf '.$fastcgi_starter_path);
2261                         }
2262                     } else {
2263                         $fcgi_starter_script = $fastcgi_starter_path.$web_config['fastcgi_starter_script'].'_web'.$data['old']['domain_id'];
2264                         if (file_exists($fcgi_starter_script)) {
2265                             exec('rm -f '.$fcgi_starter_script);
2266                         }
2267                     }
2268                 }
2269
2270                 // remove PHP-FPM pool
2271                 if ($data['old']['php'] == 'php-fpm') {
2272                     $this->php_fpm_pool_delete($data, $web_config);
1c6da3 2273                 } elseif($data['old']['php'] == 'hhvm') {
MC 2274                     $this->hhvm_update($data, $web_config);
d22277 2275                     $this->php_fpm_pool_delete($data, $web_config);
7fe908 2276                 }
MC 2277
2278                 //remove the php cgi starter script if available
2279                 if ($data['old']['php'] == 'cgi') {
2280                     // TODO: fetch the date from the server-settings
2281                     $web_config['cgi_starter_path'] = $web_config['website_basedir'].'/php-cgi-scripts/[system_user]/';
2282
2283                     $cgi_starter_path = str_replace('[system_user]', $data['old']['system_user'], $web_config['cgi_starter_path']);
2284                     if($data['old']['type'] == 'vhost') {
2285                         if (is_dir($cgi_starter_path)) {
2286                             exec('rm -rf '.$cgi_starter_path);
2287                         }
2288                     } else {
2289                         $cgi_starter_script = $cgi_starter_path.'php-cgi-starter_web'.$data['old']['domain_id'];
2290                         if (file_exists($cgi_starter_script)) {
2291                             exec('rm -f '.$cgi_starter_script);
2292                         }
2293                     }
2294                 }
2295
2296                 $app->log('Removing website: '.$docroot, LOGLEVEL_DEBUG);
2297
2298                 // Delete the symlinks for the sites
2af58c 2299                 $client = $app->db->queryOneRecord('SELECT client_id FROM sys_group WHERE sys_group.groupid = ?', $data['old']['sys_groupid']);
7fe908 2300                 $client_id = intval($client['client_id']);
MC 2301                 unset($client);
2302                 $tmp_symlinks_array = explode(':', $web_config['website_symlinks']);
2303                 if(is_array($tmp_symlinks_array)) {
2304                     foreach($tmp_symlinks_array as $tmp_symlink) {
2305                         $tmp_symlink = str_replace('[client_id]', $client_id, $tmp_symlink);
2306                         $tmp_symlink = str_replace('[website_domain]', $data['old']['domain'], $tmp_symlink);
2307                         // Remove trailing slash
2308                         if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
2309                         // create the symlinks, if not exist
2310                         if(is_link($tmp_symlink)) {
2311                             $app->system->unlink($tmp_symlink);
2312                             $app->log('Removing symlink: '.$tmp_symlink, LOGLEVEL_DEBUG);
2313                         }
2314                     }
2315                 }
2316                 // end removing symlinks
2317             } else {
2318                 // vhost subdomain
146783 2319             }
7fe908 2320
MC 2321             // Delete the log file directory
2322             $vhost_logfile_dir = escapeshellcmd('/var/log/ispconfig/httpd/'.$data['old']['domain']);
2323             if($data['old']['domain'] != '' && !stristr($vhost_logfile_dir, '..')) exec('rm -rf '.$vhost_logfile_dir);
2324             $app->log('Removing website logfile directory: '.$vhost_logfile_dir, LOGLEVEL_DEBUG);
2325
2326             if($data['old']['type'] == 'vhost') {
2327                 //delete the web user
2328                 $command = 'killall -u '.escapeshellcmd($data['old']['system_user']).' ; userdel';
2329                 $command .= ' '.escapeshellcmd($data['old']['system_user']);
2330                 exec($command);
2331                 if($nginx_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' '.$command);
2332
2333             }
2334
2335             //* Remove the awstats configuration file
2336             if($data['old']['stats_type'] == 'awstats') {
2337                 $this->awstats_delete($data, $web_config);
2338             }
2339
990ca8 2340             //* Delete the web-backups
FS 2341             if($data['old']['type'] == 'vhost') {
2342                 $server_config = $app->getconf->get_server_config($conf['server_id'], 'server');
2343                 $backup_dir = $server_config['backup_dir'];
2344                 $mount_backup = true;
2345                 if($server_config['backup_dir'] != '' && $server_config['backup_delete'] == 'y') {
2346                     //* mount backup directory, if necessary
2347                     if( $server_config['backup_dir_is_mount'] == 'y' && !$app->system->mount_backup_dir($backup_dir) ) $mount_backup = false;
2348                     if($mount_backup){
2349                         $web_backup_dir = $backup_dir.'/web'.$data_old['domain_id'];
2350                         //** do not use rm -rf $web_backup_dir because database(s) may exits
2351                         exec(escapeshellcmd('rm -f '.$web_backup_dir.'/web'.$data_old['domain_id'].'_').'*');
2352                         //* cleanup database
2353                         $sql = "DELETE FROM web_backup WHERE server_id = ? AND parent_domain_id = ? AND filename LIKE ?";
2354                         $app->db->query($sql, $conf['server_id'], $data_old['domain_id'], "web".$data_old['domain_id']."_%");
2355                         if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql, $conf['server_id'], $data_old['domain_id'], "web".$data_old['domain_id']."_%");
2356
2357                         $app->log('Deleted the web backup files', LOGLEVEL_DEBUG);
2358                     }
2359                 }
2360             }
2361
7fe908 2362             $app->services->restartServiceDelayed('httpd', 'reload');
146783 2363
MC 2364         }
7fe908 2365
MC 2366
2367         if($data['old']['type'] != 'vhost') $app->system->web_folder_protection($data['old']['document_root'], true);
146783 2368     }
MC 2369
2370     //* This function is called when a IP on the server is inserted, updated or deleted
7fe908 2371     function server_ip($event_name, $data) {
146783 2372         return;
MC 2373     }
7fe908 2374
146783 2375     //* Create or update the .htaccess folder protection
7fe908 2376     function web_folder_user($event_name, $data) {
146783 2377         global $app, $conf;
MC 2378
2379         $app->uses('system');
7fe908 2380
146783 2381         if($event_name == 'web_folder_user_delete') {
MC 2382             $folder_id = $data['old']['web_folder_id'];
2383         } else {
2384             $folder_id = $data['new']['web_folder_id'];
2385         }
7fe908 2386
2af58c 2387         $folder = $app->db->queryOneRecord("SELECT * FROM web_folder WHERE web_folder_id = ?", $folder_id);
MC 2388         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $folder['parent_domain_id']);
7fe908 2389
146783 2390         if(!is_array($folder) or !is_array($website)) {
7fe908 2391             $app->log('Not able to retrieve folder or website record.', LOGLEVEL_DEBUG);
146783 2392             return false;
MC 2393         }
7fe908 2394
MC 2395         $web_folder = 'web';
511ba5 2396         if($website['type'] == 'vhostsubdomain' || $website['type'] == 'vhostalias') $web_folder = $website['web_folder'];
7fe908 2397
146783 2398         //* Get the folder path.
7fe908 2399         if(substr($folder['path'], 0, 1) == '/') $folder['path'] = substr($folder['path'], 1);
MC 2400         if(substr($folder['path'], -1) == '/') $folder['path'] = substr($folder['path'], 0, -1);
146783 2401         $folder_path = escapeshellcmd($website['document_root'].'/' . $web_folder . '/'.$folder['path']);
7fe908 2402         if(substr($folder_path, -1) != '/') $folder_path .= '/';
MC 2403
146783 2404         //* Check if the resulting path is inside the docroot
7fe908 2405         if(stristr($folder_path, '..') || stristr($folder_path, './') || stristr($folder_path, '\\')) {
MC 2406             $app->log('Folder path "'.$folder_path.'" contains .. or ./.', LOGLEVEL_DEBUG);
146783 2407             return false;
MC 2408         }
7fe908 2409
146783 2410         //* Create the folder path, if it does not exist
MC 2411         if(!is_dir($folder_path)) {
dbae22 2412             $app->system->mkdirpath($folder_path, 0755, $website['system_user'], $website['system_group']);
146783 2413         }
7fe908 2414
146783 2415         //* Create empty .htpasswd file, if it does not exist
MC 2416         if(!is_file($folder_path.'.htpasswd')) {
2417             touch($folder_path.'.htpasswd');
7fe908 2418             $app->system->chmod($folder_path.'.htpasswd', 0755);
MC 2419             $app->system->chown($folder_path.'.htpasswd', $website['system_user']);
2420             $app->system->chgrp($folder_path.'.htpasswd', $website['system_group']);
2421             $app->log('Created file '.$folder_path.'.htpasswd', LOGLEVEL_DEBUG);
146783 2422         }
7fe908 2423
146783 2424         if(($data['new']['username'] != $data['old']['username'] || $data['new']['active'] == 'n') && $data['old']['username'] != '') {
7fe908 2425             $app->system->removeLine($folder_path.'.htpasswd', $data['old']['username'].':');
MC 2426             $app->log('Removed user: '.$data['old']['username'], LOGLEVEL_DEBUG);
146783 2427         }
7fe908 2428
146783 2429         //* Add or remove the user from .htpasswd file
MC 2430         if($event_name == 'web_folder_user_delete') {
7fe908 2431             $app->system->removeLine($folder_path.'.htpasswd', $data['old']['username'].':');
MC 2432             $app->log('Removed user: '.$data['old']['username'], LOGLEVEL_DEBUG);
146783 2433         } else {
MC 2434             if($data['new']['active'] == 'y') {
7fe908 2435                 $app->system->replaceLine($folder_path.'.htpasswd', $data['new']['username'].':', $data['new']['username'].':'.$data['new']['password'], 0, 1);
MC 2436                 $app->log('Added or updated user: '.$data['new']['username'], LOGLEVEL_DEBUG);
146783 2437             }
MC 2438         }
7fe908 2439
146783 2440         // write basic auth configuration to vhost file because nginx does not support .htaccess
MC 2441         $webdata['new'] = $webdata['old'] = $website;
2442         $this->update('web_domain_update', $webdata);
2443     }
7fe908 2444
146783 2445     //* Remove .htpasswd file, when folder protection is removed
7fe908 2446     function web_folder_delete($event_name, $data) {
146783 2447         global $app, $conf;
7fe908 2448
146783 2449         $folder_id = $data['old']['web_folder_id'];
7fe908 2450
146783 2451         $folder = $data['old'];
2af58c 2452         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $folder['parent_domain_id']);
7fe908 2453
146783 2454         if(!is_array($folder) or !is_array($website)) {
7fe908 2455             $app->log('Not able to retrieve folder or website record.', LOGLEVEL_DEBUG);
146783 2456             return false;
MC 2457         }
7fe908 2458
MC 2459         $web_folder = 'web';
511ba5 2460         if($website['type'] == 'vhostsubdomain' || $website['type'] == 'vhostalias') $web_folder = $website['web_folder'];
7fe908 2461
146783 2462         //* Get the folder path.
7fe908 2463         if(substr($folder['path'], 0, 1) == '/') $folder['path'] = substr($folder['path'], 1);
MC 2464         if(substr($folder['path'], -1) == '/') $folder['path'] = substr($folder['path'], 0, -1);
146783 2465         $folder_path = realpath($website['document_root'].'/' . $web_folder . '/'.$folder['path']);
7fe908 2466         if(substr($folder_path, -1) != '/') $folder_path .= '/';
MC 2467
146783 2468         //* Check if the resulting path is inside the docroot
7fe908 2469         if(substr($folder_path, 0, strlen($website['document_root'])) != $website['document_root']) {
MC 2470             $app->log('Folder path is outside of docroot.', LOGLEVEL_DEBUG);
146783 2471             return false;
MC 2472         }
7fe908 2473
146783 2474         //* Remove .htpasswd file
MC 2475         if(is_file($folder_path.'.htpasswd')) {
2476             $app->system->unlink($folder_path.'.htpasswd');
7fe908 2477             $app->log('Removed file '.$folder_path.'.htpasswd', LOGLEVEL_DEBUG);
146783 2478         }
7fe908 2479
146783 2480         // write basic auth configuration to vhost file because nginx does not support .htaccess
MC 2481         $webdata['new'] = $webdata['old'] = $website;
2482         $this->update('web_domain_update', $webdata);
2483     }
7fe908 2484
146783 2485     //* Update folder protection, when path has been changed
7fe908 2486     function web_folder_update($event_name, $data) {
146783 2487         global $app, $conf;
7fe908 2488
2af58c 2489         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $data['new']['parent_domain_id']);
7fe908 2490
146783 2491         if(!is_array($website)) {
7fe908 2492             $app->log('Not able to retrieve folder or website record.', LOGLEVEL_DEBUG);
146783 2493             return false;
MC 2494         }
7fe908 2495
MC 2496         $web_folder = 'web';
511ba5 2497         if($website['type'] == 'vhostsubdomain' || $website['type'] == 'vhostalias') $web_folder = $website['web_folder'];
7fe908 2498
146783 2499         //* Get the folder path.
7fe908 2500         if(substr($data['old']['path'], 0, 1) == '/') $data['old']['path'] = substr($data['old']['path'], 1);
MC 2501         if(substr($data['old']['path'], -1) == '/') $data['old']['path'] = substr($data['old']['path'], 0, -1);
146783 2502         $old_folder_path = realpath($website['document_root'].'/' . $web_folder . '/'.$data['old']['path']);
7fe908 2503         if(substr($old_folder_path, -1) != '/') $old_folder_path .= '/';
MC 2504
2505         if(substr($data['new']['path'], 0, 1) == '/') $data['new']['path'] = substr($data['new']['path'], 1);
2506         if(substr($data['new']['path'], -1) == '/') $data['new']['path'] = substr($data['new']['path'], 0, -1);
146783 2507         $new_folder_path = escapeshellcmd($website['document_root'].'/' . $web_folder . '/'.$data['new']['path']);
7fe908 2508         if(substr($new_folder_path, -1) != '/') $new_folder_path .= '/';
MC 2509
146783 2510         //* Check if the resulting path is inside the docroot
7fe908 2511         if(stristr($new_folder_path, '..') || stristr($new_folder_path, './') || stristr($new_folder_path, '\\')) {
MC 2512             $app->log('Folder path "'.$new_folder_path.'" contains .. or ./.', LOGLEVEL_DEBUG);
146783 2513             return false;
MC 2514         }
7fe908 2515         if(stristr($old_folder_path, '..') || stristr($old_folder_path, './') || stristr($old_folder_path, '\\')) {
MC 2516             $app->log('Folder path "'.$old_folder_path.'" contains .. or ./.', LOGLEVEL_DEBUG);
146783 2517             return false;
MC 2518         }
7fe908 2519
146783 2520         //* Check if the resulting path is inside the docroot
7fe908 2521         if(substr($old_folder_path, 0, strlen($website['document_root'])) != $website['document_root']) {
MC 2522             $app->log('Old folder path '.$old_folder_path.' is outside of docroot.', LOGLEVEL_DEBUG);
146783 2523             return false;
MC 2524         }
7fe908 2525         if(substr($new_folder_path, 0, strlen($website['document_root'])) != $website['document_root']) {
MC 2526             $app->log('New folder path '.$new_folder_path.' is outside of docroot.', LOGLEVEL_DEBUG);
146783 2527             return false;
MC 2528         }
7fe908 2529
146783 2530         //* Create the folder path, if it does not exist
MC 2531         if(!is_dir($new_folder_path)) $app->system->mkdirpath($new_folder_path);
7fe908 2532
146783 2533         if($data['old']['path'] != $data['new']['path']) {
MC 2534
7fe908 2535
146783 2536             //* move .htpasswd file
MC 2537             if(is_file($old_folder_path.'.htpasswd')) {
7fe908 2538                 $app->system->rename($old_folder_path.'.htpasswd', $new_folder_path.'.htpasswd');
MC 2539                 $app->log('Moved file '.$old_folder_path.'.htpasswd to '.$new_folder_path.'.htpasswd', LOGLEVEL_DEBUG);
146783 2540             }
7fe908 2541
146783 2542         }
MC 2543
2544         // write basic auth configuration to vhost file because nginx does not support .htaccess
2545         $webdata['new'] = $webdata['old'] = $website;
2546         $this->update('web_domain_update', $webdata);
2547     }
7fe908 2548
146783 2549     function _create_web_folder_auth_configuration($website){
MC 2550         global $app, $conf;
2551         //* Create the domain.auth file which is included in the vhost configuration file
2552         $app->uses('getconf');
2553         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
2554         $basic_auth_file = escapeshellcmd($web_config['nginx_vhost_conf_dir'].'/'.$website['domain'].'.auth');
2555         //$app->load('tpl');
2556         //$tpl = new tpl();
2557         //$tpl->newTemplate('nginx_http_authentication.auth.master');
2af58c 2558         $website_auth_locations = $app->db->queryAllRecords("SELECT * FROM web_folder WHERE active = 'y' AND parent_domain_id = ?", $website['domain_id']);
146783 2559         $basic_auth_locations = array();
MC 2560         if(is_array($website_auth_locations) && !empty($website_auth_locations)){
2561             foreach($website_auth_locations as $website_auth_location){
7fe908 2562                 if(substr($website_auth_location['path'], 0, 1) == '/') $website_auth_location['path'] = substr($website_auth_location['path'], 1);
MC 2563                 if(substr($website_auth_location['path'], -1) == '/') $website_auth_location['path'] = substr($website_auth_location['path'], 0, -1);
146783 2564                 if($website_auth_location['path'] != ''){
MC 2565                     $website_auth_location['path'] .= '/';
2566                 }
2567                 $basic_auth_locations[] = array('htpasswd_location' => '/'.$website_auth_location['path'],
511ba5 2568                     'htpasswd_path' => $website['document_root'].'/' . (($website['type'] == 'vhostsubdomain' || $website['type'] == 'vhostalias') ? $website['web_folder'] : 'web') . '/'.$website_auth_location['path']);
146783 2569             }
MC 2570         }
2571         return $basic_auth_locations;
2572         //$tpl->setLoop('basic_auth_locations', $basic_auth_locations);
2573         //file_put_contents($basic_auth_file,$tpl->grab());
2574         //$app->log('Writing the http basic authentication file: '.$basic_auth_file,LOGLEVEL_DEBUG);
2575         //unset($tpl);
2576         //$app->services->restartServiceDelayed('httpd','reload');
2577     }
7fe908 2578
146783 2579     //* Update the awstats configuration file
7fe908 2580     private function awstats_update ($data, $web_config) {
146783 2581         global $app;
7fe908 2582
MC 2583         $web_folder = $data['new']['web_folder'];
2584         if($data['new']['type'] == 'vhost') $web_folder = 'web';
146783 2585         $awstats_conf_dir = $web_config['awstats_conf_dir'];
7fe908 2586
146783 2587         if(!is_dir($data['new']['document_root']."/" . $web_folder . "/stats/")) mkdir($data['new']['document_root']."/" . $web_folder . "/stats");
MC 2588         if(!@is_file($awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf') || ($data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain'])) {
2589             if ( @is_file($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf') ) {
2590                 $app->system->unlink($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf');
2591             }
7fe908 2592
146783 2593             $content = '';
e6abfe 2594             if (is_file($awstats_conf_dir."/awstats.conf")) {
CS 2595                 $include_file = $awstats_conf_dir."/awstats.conf";
2596             } elseif (is_file($awstats_conf_dir."/awstats.model.conf")) {
2597                 $include_file = $awstats_conf_dir."/awstats.model.conf";
2598             }
de6d2e 2599             $content .= "Include \"".$include_file."\"\n";
146783 2600             $content .= "LogFile=\"/var/log/ispconfig/httpd/".$data['new']['domain']."/access.log\"\n";
MC 2601             $content .= "SiteDomain=\"".$data['new']['domain']."\"\n";
2602             $content .= "HostAliases=\"www.".$data['new']['domain']."  localhost 127.0.0.1\"\n";
7fe908 2603
9aaf97 2604             if (isset($include_file)) {
CS 2605                 $app->system->file_put_contents($awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf', $content);
2606                 $app->log('Created AWStats config file: '.$awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf', LOGLEVEL_DEBUG);
2607             } else {
2608                 $app->log("No awstats base config found. Either awstats.conf or awstats.model.conf must exist in ".$awstats_conf_dir.".", LOGLEVEL_WARN);
2609             }
146783 2610         }
7fe908 2611
146783 2612         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 2613         if(file_exists("/usr/local/ispconfig/server/conf-custom/awstats_index.php.master")) {
7fe908 2614             $app->system->copy("/usr/local/ispconfig/server/conf-custom/awstats_index.php.master", $data['new']['document_root']."/" . $web_folder . "/stats/index.php");
146783 2615         } else {
7fe908 2616             $app->system->copy("/usr/local/ispconfig/server/conf/awstats_index.php.master", $data['new']['document_root']."/" . $web_folder . "/stats/index.php");
146783 2617         }
MC 2618     }
7fe908 2619
146783 2620     //* Delete the awstats configuration file
7fe908 2621     private function awstats_delete ($data, $web_config) {
146783 2622         global $app;
7fe908 2623
146783 2624         $awstats_conf_dir = $web_config['awstats_conf_dir'];
7fe908 2625
146783 2626         if ( @is_file($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf') ) {
MC 2627             $app->system->unlink($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf');
7fe908 2628             $app->log('Removed AWStats config file: '.$awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf', LOGLEVEL_DEBUG);
146783 2629         }
MC 2630     }
7fe908 2631
1c6da3 2632     private function hhvm_update($data, $web_config) {
MC 2633         global $app, $conf;
2634         
2635         if(file_exists($conf['rootpath'] . '/conf-custom/hhvm_starter.master')) {
2636             $content = file_get_contents($conf['rootpath'] . '/conf-custom/hhvm_starter.master');
2637         } else {
2638             $content = file_get_contents($conf['rootpath'] . '/conf/hhvm_starter.master');
2639         }
cab08c 2640         if(file_exists($conf['rootpath'] . '/conf-custom/hhvm_monit.master')) {
MC 2641             $monit_content = file_get_contents($conf['rootpath'] . '/conf-custom/hhvm_monit.master');
2642         } else {
2643             $monit_content = file_get_contents($conf['rootpath'] . '/conf/hhvm_monit.master');
2644         }
1c6da3 2645         
d22277 2646         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 2647
MC 2648             // Custom php.ini settings
2649             $custom_php_ini_settings = trim($data['new']['custom_php_ini']);
2650             if(intval($data['new']['directive_snippets_id']) > 0){
2651                 $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']));
2652                 if(isset($snippet['required_php_snippets']) && trim($snippet['required_php_snippets']) != ''){
2653                     $required_php_snippets = explode(',', trim($snippet['required_php_snippets']));
2654                     if(is_array($required_php_snippets) && !empty($required_php_snippets)){
2655                         foreach($required_php_snippets as $required_php_snippet){
2656                             $required_php_snippet = intval($required_php_snippet);
2657                             if($required_php_snippet > 0){
d22277 2658                                 $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 2659                                 $php_snippet['snippet'] = trim($php_snippet['snippet']);
MC 2660                                 if($php_snippet['snippet'] != ''){
2661                                     $custom_php_ini_settings .= "\n".$php_snippet['snippet'];
2662                                 }
2663                             }
2664                         }
2665                     }
2666                 }
2667             }
d22277 2668             
d5f2d5 2669             if($custom_php_ini_settings != ''){
MC 2670                 // Make sure we only have Unix linebreaks
2671                 $custom_php_ini_settings = str_replace("\r\n", "\n", $custom_php_ini_settings);
2672                 $custom_php_ini_settings = str_replace("\r", "\n", $custom_php_ini_settings);
2673                 file_put_contents('/etc/hhvm/'.$data['new']['system_user'].'.ini', $custom_php_ini_settings);
2674             } else {
d22277 2675                 if($data['old']['system_user'] != '' && is_file('/etc/hhvm/'.$data['old']['system_user'].'.ini')) unlink('/etc/hhvm/'.$data['old']['system_user'].'.ini');
d5f2d5 2676             }
MC 2677         
1c6da3 2678             $content = str_replace('{SYSTEM_USER}', $data['new']['system_user'], $content);
MC 2679             file_put_contents('/etc/init.d/hhvm_' . $data['new']['system_user'], $content);
2680             exec('chmod +x /etc/init.d/hhvm_' . $data['new']['system_user'] . ' >/dev/null 2>&1');
2681             exec('/usr/sbin/update-rc.d hhvm_' . $data['new']['system_user'] . ' defaults >/dev/null 2>&1');
d5f2d5 2682             exec('/etc/init.d/hhvm_' . $data['new']['system_user'] . ' restart >/dev/null 2>&1');
cab08c 2683             
02e7ea 2684             if(is_dir('/etc/monit/conf.d')){
MC 2685                 $monit_content = str_replace('{SYSTEM_USER}', $data['new']['system_user'], $monit_content);
2686                 file_put_contents('/etc/monit/conf.d/00-hhvm_' . $data['new']['system_user'], $monit_content);
2687                 if(is_file('/etc/monit/conf.d/hhvm_' . $data['new']['system_user'])) unlink('/etc/monit/conf.d/hhvm_' . $data['new']['system_user']);
2688                 exec('/etc/init.d/monit restart >/dev/null 2>&1');
2689             }
cab08c 2690             
1c6da3 2691          } elseif($data['new']['php'] != 'hhvm' && $data['old']['php'] == 'hhvm') {
d22277 2692             if($data['old']['system_user'] != ''){
MB 2693                 exec('/etc/init.d/hhvm_' . $data['old']['system_user'] . ' stop >/dev/null 2>&1');
2694                 exec('/usr/sbin/update-rc.d hhvm_' . $data['old']['system_user'] . ' remove >/dev/null 2>&1');
2695                 unlink('/etc/init.d/hhvm_' . $data['old']['system_user']);
2696                 if(is_file('/etc/hhvm/'.$data['old']['system_user'].'.ini')) unlink('/etc/hhvm/'.$data['old']['system_user'].'.ini');
2697             }
cab08c 2698             
d22277 2699             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 2700                 if(is_file('/etc/monit/conf.d/hhvm_' . $data['old']['system_user'])){
2701                     unlink('/etc/monit/conf.d/hhvm_' . $data['old']['system_user']);
02e7ea 2702                 }
d22277 2703                 if(is_file('/etc/monit/conf.d/00-hhvm_' . $data['old']['system_user'])){
MB 2704                     unlink('/etc/monit/conf.d/00-hhvm_' . $data['old']['system_user']);
02e7ea 2705                 }
cab08c 2706                 exec('/etc/init.d/monit restart >/dev/null 2>&1');
MC 2707             }
1c6da3 2708         }
MC 2709     }
2710
146783 2711     //* Update the PHP-FPM pool configuration file
7fe908 2712     private function php_fpm_pool_update ($data, $web_config, $pool_dir, $pool_name, $socket_dir) {
146783 2713         global $app, $conf;
ab79c2 2714         $pool_dir = trim($pool_dir);
146783 2715         /*
MC 2716         if(trim($data['new']['fastcgi_php_version']) != ''){
2717             $default_php_fpm = false;
2718             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']));
2719             if(substr($custom_php_fpm_ini_dir,-1) != '/') $custom_php_fpm_ini_dir .= '/';
2720         } else {
2721             $default_php_fpm = true;
2722         }
2723         */
d22277 2724         // HHVM => PHP-FPM-Fallback
MB 2725         if($data['new']['php'] == 'php-fpm' || $data['new']['php'] == 'hhvm'){
146783 2726             if(trim($data['new']['fastcgi_php_version']) != ''){
MC 2727                 $default_php_fpm = false;
2728                 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 2729                 if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
146783 2730             } else {
MC 2731                 $default_php_fpm = true;
2732             }
2733         } else {
2734             if(trim($data['old']['fastcgi_php_version']) != '' && $data['old']['php'] != 'no'){
2735                 $default_php_fpm = false;
2736                 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 2737                 if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
146783 2738             } else {
MC 2739                 $default_php_fpm = true;
2740             }
2741         }
7fe908 2742
146783 2743         $app->uses("getconf");
MC 2744         $web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
7fe908 2745
d22277 2746         // HHVM => PHP-FPM-Fallback
MB 2747         if($data['new']['php'] != 'php-fpm' && $data['new']['php'] != 'hhvm'){
146783 2748             if(@is_file($pool_dir.$pool_name.'.conf')){
MC 2749                 $app->system->unlink($pool_dir.$pool_name.'.conf');
2750                 //$reload = true;
2751             }
2752             if($data['old']['php'] != 'no'){
2753                 if(!$default_php_fpm){
7fe908 2754                     $app->services->restartService('php-fpm', 'reload:'.$custom_php_fpm_init_script);
146783 2755                 } else {
7fe908 2756                     $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
146783 2757                 }
MC 2758             }
2759             return;
2760         }
7fe908 2761
146783 2762         $app->load('tpl');
MC 2763         $tpl = new tpl();
2764         $tpl->newTemplate('php_fpm_pool.conf.master');
2765
2766         if($data['new']['php_fpm_use_socket'] == 'y'){
2767             $use_tcp = 0;
2768             $use_socket = 1;
2769             if(!is_dir($socket_dir)) $app->system->mkdirpath($socket_dir);
2770         } else {
2771             $use_tcp = 1;
2772             $use_socket = 0;
2773         }
2774         $tpl->setVar('use_tcp', $use_tcp);
2775         $tpl->setVar('use_socket', $use_socket);
7fe908 2776
146783 2777         $fpm_socket = $socket_dir.$pool_name.'.sock';
MC 2778         $tpl->setVar('fpm_socket', $fpm_socket);
1890ca 2779         $tpl->setVar('fpm_listen_mode', '0660');
7fe908 2780
146783 2781         $tpl->setVar('fpm_pool', $pool_name);
MC 2782         $tpl->setVar('fpm_port', $web_config['php_fpm_start_port'] + $data['new']['domain_id'] - 1);
2783         $tpl->setVar('fpm_user', $data['new']['system_user']);
0dfb2d 2784         $tpl->setVar('fpm_group', $web_config['group']);
146783 2785         $tpl->setVar('pm', $data['new']['pm']);
MC 2786         $tpl->setVar('pm_max_children', $data['new']['pm_max_children']);
2787         $tpl->setVar('pm_start_servers', $data['new']['pm_start_servers']);
2788         $tpl->setVar('pm_min_spare_servers', $data['new']['pm_min_spare_servers']);
2789         $tpl->setVar('pm_max_spare_servers', $data['new']['pm_max_spare_servers']);
2790         $tpl->setVar('pm_process_idle_timeout', $data['new']['pm_process_idle_timeout']);
2791         $tpl->setVar('pm_max_requests', $data['new']['pm_max_requests']);
2792         $tpl->setVar('document_root', $data['new']['document_root']);
7fe908 2793         $tpl->setVar('security_level', $web_config['security_level']);
f63910 2794         $tpl->setVar('domain', $data['new']['domain']);
146783 2795         $php_open_basedir = ($data['new']['php_open_basedir'] == '')?escapeshellcmd($data['new']['document_root']):escapeshellcmd($data['new']['php_open_basedir']);
MC 2796         $tpl->setVar('php_open_basedir', $php_open_basedir);
2797         if($php_open_basedir != ''){
2798             $tpl->setVar('enable_php_open_basedir', '');
2799         } else {
2800             $tpl->setVar('enable_php_open_basedir', ';');
2801         }
7fe908 2802
146783 2803         // Custom php.ini settings
MC 2804         $final_php_ini_settings = array();
2805         $custom_php_ini_settings = trim($data['new']['custom_php_ini']);
b41803 2806         
MC 2807         if(intval($data['new']['directive_snippets_id']) > 0){
2808             $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']));
2809             if(isset($snippet['required_php_snippets']) && trim($snippet['required_php_snippets']) != ''){
2810                 $required_php_snippets = explode(',', trim($snippet['required_php_snippets']));
2811                 if(is_array($required_php_snippets) && !empty($required_php_snippets)){
2812                     foreach($required_php_snippets as $required_php_snippet){
2813                         $required_php_snippet = intval($required_php_snippet);
2814                         if($required_php_snippet > 0){
d22277 2815                             $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 2816                             $php_snippet['snippet'] = trim($php_snippet['snippet']);
MC 2817                             if($php_snippet['snippet'] != ''){
2818                                 $custom_php_ini_settings .= "\n".$php_snippet['snippet'];
2819                             }
2820                         }
2821                     }
2822                 }
2823             }
2824         }
2825         
9fd930 2826         $custom_session_save_path = false;
146783 2827         if($custom_php_ini_settings != ''){
MC 2828             // Make sure we only have Unix linebreaks
2829             $custom_php_ini_settings = str_replace("\r\n", "\n", $custom_php_ini_settings);
2830             $custom_php_ini_settings = str_replace("\r", "\n", $custom_php_ini_settings);
2831             $ini_settings = explode("\n", $custom_php_ini_settings);
2832             if(is_array($ini_settings) && !empty($ini_settings)){
2833                 foreach($ini_settings as $ini_setting){
2834                     $ini_setting = trim($ini_setting);
7fe908 2835                     if(substr($ini_setting, 0, 1) == ';') continue;
MC 2836                     if(substr($ini_setting, 0, 1) == '#') continue;
2837                     if(substr($ini_setting, 0, 2) == '//') continue;
03cc01 2838                     list($key, $value) = explode('=', $ini_setting, 2);
1d6097 2839                     $value = trim($value);
FT 2840                     if($value != ''){
146783 2841                         $key = trim($key);
9fd930 2842                         if($key == 'session.save_path') $custom_session_save_path = true;
146783 2843                         switch (strtolower($value)) {
7fe908 2844                         case '0':
MC 2845                             // PHP-FPM might complain about invalid boolean value if you use 0
2846                             $value = 'off';
2847                         case '1':
2848                         case 'on':
2849                         case 'off':
2850                         case 'true':
2851                         case 'false':
2852                         case 'yes':
2853                         case 'no':
2854                             $final_php_ini_settings[] = array('ini_setting' => 'php_admin_flag['.$key.'] = '.$value);
2855                             break;
2856                         default:
2857                             $final_php_ini_settings[] = array('ini_setting' => 'php_admin_value['.$key.'] = '.$value);
146783 2858                         }
MC 2859                     }
2860                 }
2861             }
2862         }
7fe908 2863
9fd930 2864         $tpl->setVar('custom_session_save_path', ($custom_session_save_path ? 'y' : 'n'));
MB 2865
146783 2866         $tpl->setLoop('custom_php_ini_settings', $final_php_ini_settings);
7fe908 2867
MC 2868         $app->system->file_put_contents($pool_dir.$pool_name.'.conf', $tpl->grab());
2869         $app->log('Writing the PHP-FPM config file: '.$pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
146783 2870         unset($tpl);
7fe908 2871
146783 2872         // delete pool in all other PHP versions
ab79c2 2873         $default_pool_dir = trim(escapeshellcmd($web_config['php_fpm_pool_dir']));
7fe908 2874         if(substr($default_pool_dir, -1) != '/') $default_pool_dir .= '/';
146783 2875         if($default_pool_dir != $pool_dir){
MC 2876             if ( @is_file($default_pool_dir.$pool_name.'.conf') ) {
7fe908 2877                 $app->system->unlink($default_pool_dir.$pool_name.'.conf');
MC 2878                 $app->log('Removed PHP-FPM config file: '.$default_pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
2879                 $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
146783 2880             }
MC 2881         }
2af58c 2882         $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 2883         if(is_array($php_versions) && !empty($php_versions)){
MC 2884             foreach($php_versions as $php_version){
ab79c2 2885                 $php_version['php_fpm_pool_dir'] = trim($php_version['php_fpm_pool_dir']);
7fe908 2886                 if(substr($php_version['php_fpm_pool_dir'], -1) != '/') $php_version['php_fpm_pool_dir'] .= '/';
146783 2887                 if($php_version['php_fpm_pool_dir'] != $pool_dir){
MC 2888                     if ( @is_file($php_version['php_fpm_pool_dir'].$pool_name.'.conf') ) {
2889                         $app->system->unlink($php_version['php_fpm_pool_dir'].$pool_name.'.conf');
7fe908 2890                         $app->log('Removed PHP-FPM config file: '.$php_version['php_fpm_pool_dir'].$pool_name.'.conf', LOGLEVEL_DEBUG);
MC 2891                         $app->services->restartService('php-fpm', 'reload:'.$php_version['php_fpm_init_script']);
146783 2892                     }
MC 2893                 }
2894             }
2895         }
2896         // Reload current PHP-FPM after all others
2897         sleep(1);
2898         if(!$default_php_fpm){
7fe908 2899             $app->services->restartService('php-fpm', 'reload:'.$custom_php_fpm_init_script);
146783 2900         } else {
7fe908 2901             $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
146783 2902         }
MC 2903     }
7fe908 2904
146783 2905     //* Delete the PHP-FPM pool configuration file
7fe908 2906     private function php_fpm_pool_delete ($data, $web_config) {
146783 2907         global $app, $conf;
7fe908 2908
146783 2909         if(trim($data['old']['fastcgi_php_version']) != '' && $data['old']['php'] != 'no'){
MC 2910             $default_php_fpm = false;
2911             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 2912             if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
146783 2913         } else {
MC 2914             $default_php_fpm = true;
2915         }
7fe908 2916
146783 2917         if($default_php_fpm){
MC 2918             $pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
2919         } else {
2920             $pool_dir = $custom_php_fpm_pool_dir;
2921         }
ab79c2 2922         $pool_dir = trim($pool_dir);
7fe908 2923
MC 2924         if(substr($pool_dir, -1) != '/') $pool_dir .= '/';
146783 2925         $pool_name = 'web'.$data['old']['domain_id'];
7fe908 2926
146783 2927         if ( @is_file($pool_dir.$pool_name.'.conf') ) {
MC 2928             $app->system->unlink($pool_dir.$pool_name.'.conf');
7fe908 2929             $app->log('Removed PHP-FPM config file: '.$pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
146783 2930         }
7fe908 2931
146783 2932         // delete pool in all other PHP versions
ab79c2 2933         $default_pool_dir = trim(escapeshellcmd($web_config['php_fpm_pool_dir']));
7fe908 2934         if(substr($default_pool_dir, -1) != '/') $default_pool_dir .= '/';
146783 2935         if($default_pool_dir != $pool_dir){
MC 2936             if ( @is_file($default_pool_dir.$pool_name.'.conf') ) {
7fe908 2937                 $app->system->unlink($default_pool_dir.$pool_name.'.conf');
MC 2938                 $app->log('Removed PHP-FPM config file: '.$default_pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
2939                 $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
146783 2940             }
7fe908 2941         }
2af58c 2942         $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 2943         if(is_array($php_versions) && !empty($php_versions)){
MC 2944             foreach($php_versions as $php_version){
ab79c2 2945                 $php_version['php_fpm_pool_dir'] = trim($php_version['php_fpm_pool_dir']);
7fe908 2946                 if(substr($php_version['php_fpm_pool_dir'], -1) != '/') $php_version['php_fpm_pool_dir'] .= '/';
146783 2947                 if($php_version['php_fpm_pool_dir'] != $pool_dir){
MC 2948                     if ( @is_file($php_version['php_fpm_pool_dir'].$pool_name.'.conf') ) {
2949                         $app->system->unlink($php_version['php_fpm_pool_dir'].$pool_name.'.conf');
7fe908 2950                         $app->log('Removed PHP-FPM config file: '.$php_version['php_fpm_pool_dir'].$pool_name.'.conf', LOGLEVEL_DEBUG);
MC 2951                         $app->services->restartService('php-fpm', 'reload:'.$php_version['php_fpm_init_script']);
146783 2952                     }
MC 2953                 }
2954             }
2955         }
7fe908 2956
146783 2957         // Reload current PHP-FPM after all others
MC 2958         sleep(1);
2959         if(!$default_php_fpm){
7fe908 2960             $app->services->restartService('php-fpm', 'reload:'.$custom_php_fpm_init_script);
146783 2961         } else {
7fe908 2962             $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
146783 2963         }
MC 2964     }
7fe908 2965
146783 2966     private function nginx_replace($matches){
MC 2967         $location = 'location'.($matches[1] != '' ? ' '.$matches[1] : '').' '.$matches[2].' '.$matches[3];
2968         if($matches[4] == '##merge##' || $matches[7] == '##merge##') $location .= ' ##merge##';
2969         if($matches[4] == '##delete##' || $matches[7] == '##delete##') $location .= ' ##delete##';
2970         $location .= "\n";
2971         $location .= $matches[5]."\n";
2972         $location .= $matches[6];
2973         return $location;
2974     }
7fe908 2975
146783 2976     private function nginx_merge_locations($vhost_conf){
MC 2977
2978         $lines = explode("\n", $vhost_conf);
7fe908 2979
146783 2980         // if whole location block is in one line, split it up into multiple lines
MC 2981         if(is_array($lines) && !empty($lines)){
2982             $linecount = sizeof($lines);
2983             for($h=0;$h<$linecount;$h++){
2984                 // remove comments
7fe908 2985                 if(substr(trim($lines[$h]), 0, 1) == '#'){
146783 2986                     unset($lines[$h]);
MC 2987                     continue;
2988                 }
7fe908 2989
146783 2990                 $lines[$h] = rtrim($lines[$h]);
MC 2991                 /*
2992                 if(substr(ltrim($lines[$h]), 0, 8) == 'location' && strpos($lines[$h], '{') !== false && strpos($lines[$h], ';') !== false){
2993                     $lines[$h] = str_replace("{", "{\n", $lines[$h]);
2994                     $lines[$h] = str_replace(";", ";\n", $lines[$h]);
2995                     if(strpos($lines[$h], '##merge##') !== false){
2996                         $lines[$h] = str_replace('##merge##', '', $lines[$h]);
2997                         $lines[$h] = substr($lines[$h],0,strpos($lines[$h], '{')).' ##merge##'.substr($lines[$h],strpos($lines[$h], '{')+1);
2998                     }
2999                 }
3000                 if(substr(ltrim($lines[$h]), 0, 8) == 'location' && strpos($lines[$h], '{') !== false && strpos($lines[$h], '}') !== false && strpos($lines[$h], ';') === false){
3001                     $lines[$h] = str_replace("{", "{\n", $lines[$h]);
3002                     if(strpos($lines[$h], '##merge##') !== false){
3003                         $lines[$h] = str_replace('##merge##', '', $lines[$h]);
3004                         $lines[$h] = substr($lines[$h],0,strpos($lines[$h], '{')).' ##merge##'.substr($lines[$h],strpos($lines[$h], '{')+1);
3005                     }
3006                 }
3007                 */
3008                 $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 3009                 $lines[$h] = preg_replace_callback($pattern, array($this, 'nginx_replace') , $lines[$h]);
146783 3010             }
MC 3011         }
3012         $vhost_conf = implode("\n", $lines);
3013         unset($lines);
3014         unset($linecount);
7fe908 3015
146783 3016         $lines = explode("\n", $vhost_conf);
7fe908 3017
MC 3018         if(is_array($lines) && !empty($lines)){
146783 3019             $locations = array();
MC 3020             $locations_to_delete = array();
3021             $islocation = false;
3022             $linecount = sizeof($lines);
3023             $server_count = 0;
3024
3025             for($i=0;$i<$linecount;$i++){
3026                 $l = trim($lines[$i]);
3027                 if(substr($l, 0, 8) == 'server {') $server_count += 1;
3028                 if($server_count > 1) break;
3029                 if(substr($l, 0, 8) == 'location' && !$islocation){
7fe908 3030
146783 3031                     $islocation = true;
MC 3032                     $level = 0;
7fe908 3033
146783 3034                     // Remove unnecessary whitespace
MC 3035                     $l = preg_replace('/\s\s+/', ' ', $l);
7fe908 3036
146783 3037                     $loc_parts = explode(' ', $l);
MC 3038                     // see http://wiki.nginx.org/HttpCoreModule#location
3039                     if($loc_parts[1] == '=' || $loc_parts[1] == '~' || $loc_parts[1] == '~*' || $loc_parts[1] == '^~'){
3040                         $location = $loc_parts[1].' '.$loc_parts[2];
3041                     } else {
3042                         $location = $loc_parts[1];
3043                     }
3044                     unset($loc_parts);
7fe908 3045
146783 3046                     if(!isset($locations[$location]['action'])) $locations[$location]['action'] = 'replace';
MC 3047                     if(substr($l, -9) == '##merge##') $locations[$location]['action'] = 'merge';
3048                     if(substr($l, -10) == '##delete##') $locations[$location]['action'] = 'delete';
7fe908 3049
146783 3050                     if(!isset($locations[$location]['open_tag'])) $locations[$location]['open_tag'] = '        location '.$location.' {';
MC 3051                     if(!isset($locations[$location]['location']) || $locations[$location]['action'] == 'replace') $locations[$location]['location'] = '';
3052                     if($locations[$location]['action'] == 'delete') $locations_to_delete[] = $location;
3053                     if(!isset($locations[$location]['end_tag'])) $locations[$location]['end_tag'] = '        }';
3054                     if(!isset($locations[$location]['start_line'])) $locations[$location]['start_line'] = $i;
3055
3056                     unset($lines[$i]);
7fe908 3057
146783 3058                 } else {
7fe908 3059
146783 3060                     if($islocation){
a71305 3061                         $openingbracketpos = strrpos($l, '{');
MB 3062                         if($openingbracketpos !== false){
146783 3063                             $level += 1;
MC 3064                         }
a71305 3065                         $closingbracketpos = strrpos($l, '}');
MB 3066                         if($closingbracketpos !== false && $level > 0 && $closingbracketpos >= intval($openingbracketpos)){
146783 3067                             $level -= 1;
MC 3068                             $locations[$location]['location'] .= $lines[$i]."\n";
a71305 3069                         } elseif($closingbracketpos !== false && $level == 0 && $closingbracketpos >= intval($openingbracketpos)){
146783 3070                             $islocation = false;
MC 3071                         } else {
3072                             $locations[$location]['location'] .= $lines[$i]."\n";
3073                         }
3074                         unset($lines[$i]);
3075                     }
7fe908 3076
146783 3077                 }
MC 3078             }
7fe908 3079
146783 3080             if(is_array($locations) && !empty($locations)){
MC 3081                 if(is_array($locations_to_delete) && !empty($locations_to_delete)){
3082                     foreach($locations_to_delete as $location_to_delete){
3083                         if(isset($locations[$location_to_delete])) unset($locations[$location_to_delete]);
3084                     }
3085                 }
7fe908 3086
146783 3087                 foreach($locations as $key => $val){
MC 3088                     $new_location = $val['open_tag']."\n".$val['location'].$val['end_tag'];
3089                     $lines[$val['start_line']] = $new_location;
3090                 }
3091             }
3092             ksort($lines);
3093             $vhost_conf = implode("\n", $lines);
3094         }
7fe908 3095
146783 3096         return trim($vhost_conf);
MC 3097     }
7fe908 3098
MC 3099     function client_delete($event_name, $data) {
146783 3100         global $app, $conf;
7fe908 3101
146783 3102         $app->uses("getconf");
MC 3103         $web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
7fe908 3104
146783 3105         $client_id = intval($data['old']['client_id']);
MC 3106         if($client_id > 0) {
7fe908 3107
146783 3108             $client_dir = $web_config['website_basedir'].'/clients/client'.$client_id;
7fe908 3109             if(is_dir($client_dir) && !stristr($client_dir, '..')) {
146783 3110                 // remove symlinks from $client_dir
7fe908 3111                 $files = array_diff(scandir($client_dir), array('.', '..'));
146783 3112                 if(is_array($files) && !empty($files)){
MC 3113                     foreach($files as $file){
3114                         if(is_link($client_dir.'/'.$file)){
3115                             unlink($client_dir.'/'.$file);
7fe908 3116                             $app->log('Removed symlink: '.$client_dir.'/'.$file, LOGLEVEL_DEBUG);
146783 3117                         }
MC 3118                     }
3119                 }
7fe908 3120
146783 3121                 @rmdir($client_dir);
7fe908 3122                 $app->log('Removed client directory: '.$client_dir, LOGLEVEL_DEBUG);
146783 3123             }
7fe908 3124
146783 3125             if($app->system->is_group('client'.$client_id)){
MC 3126                 $this->_exec('groupdel client'.$client_id);
7fe908 3127                 $app->log('Removed group client'.$client_id, LOGLEVEL_DEBUG);
146783 3128             }
MC 3129         }
7fe908 3130
146783 3131     }
MC 3132
3133     //* Wrapper for exec function for easier debugging
3134     private function _exec($command) {
3135         global $app;
551d9a 3136         $out = array();
MB 3137         $ret = 0;
7fe908 3138         $app->log('exec: '.$command, LOGLEVEL_DEBUG);
551d9a 3139         exec($command, $out, $ret);
MB 3140         if($ret != 0) return false;
3141         else return true;
146783 3142     }
MC 3143
7fe908 3144     private function _checkTcp ($host, $port) {
MC 3145
3146         $fp = @fsockopen($host, $port, $errno, $errstr, 2);
146783 3147
MC 3148         if ($fp) {
3149             fclose($fp);
3150             return true;
3151         } else {
3152             return false;
3153         }
3154     }
7fe908 3155
146783 3156     public function create_relative_link($f, $t) {
MC 3157         global $app;
3158         // $from already exists
3159         $from = realpath($f);
3160
3161         // realpath requires the traced file to exist - so, lets touch it first, then remove
3162         @$app->system->unlink($t); touch($t);
3163         $to = realpath($t);
3164         @$app->system->unlink($t);
3165
3166         // Remove from the left side matching path elements from $from and $to
3167         // and get path elements counts
3168         $a1 = explode('/', $from); $a2 = explode('/', $to);
3169         for ($c = 0; $a1[$c] == $a2[$c]; $c++) {
3170             unset($a1[$c]); unset($a2[$c]);
3171         }
3172         $cfrom = implode('/', $a1);
3173
3174         // Check if a path is fully a subpath of another - no way to create symlink in the case
3175         if (count($a1) == 0 || count($a2) == 0) return false;
3176
3177         // Add ($cnt_to-1) number of "../" elements to left side of $cfrom
3178         for ($c = 0; $c < (count($a2)-1); $c++) { $cfrom = '../'.$cfrom; }
3179
3180         return symlink($cfrom, $to);
3181     }
7fe908 3182
MC 3183     private function _rewrite_quote($string) {
3184         return str_replace(array('.', '*', '?', '+'), array('\\.', '\\*', '\\?', '\\+'), $string);
3185     }
3186
146783 3187     private function url_is_local($hostname, $domain_id){
MC 3188         global $app;
3189
3190         // ORDER BY clause makes sure wildcard subdomains (*) are listed last in the result array so that we can find direct matches first
3191         $webs = $app->db->queryAllRecords("SELECT * FROM web_domain WHERE active = 'y' ORDER BY subdomain ASC");
3192         if(is_array($webs) && !empty($webs)){
3193             foreach($webs as $web){
3194                 // web domain doesn't match hostname
7fe908 3195                 if(substr($hostname, -strlen($web['domain'])) != $web['domain']) continue;
146783 3196                 // own vhost and therefore server {} container of its own
511ba5 3197                 //if($web['type'] == 'vhostsubdomain' || $web['type'] == 'vhostalias') continue;
146783 3198                 // alias domains/subdomains using rewrites and therefore a server {} container of their own
MC 3199                 //if(($web['type'] == 'alias' || $web['type'] == 'subdomain') && $web['redirect_type'] != '' && $web['redirect_path'] != '') continue;
7fe908 3200
146783 3201                 if($web['subdomain'] == '*'){
MC 3202                     $pattern = '/\.?'.str_replace('.', '\.', $web['domain']).'$/i';
3203                 }
3204                 if($web['subdomain'] == 'none'){
3205                     if($web['domain'] == $hostname){
3206                         if($web['domain_id'] == $domain_id || $web['parent_domain_id'] == $domain_id){
3207                             // own vhost and therefore server {} container of its own
511ba5 3208                             if($web['type'] == 'vhostsubdomain' || $web['type'] == 'vhostalias') return false;
146783 3209                             // alias domains/subdomains using rewrites and therefore a server {} container of their own
MC 3210                             if(($web['type'] == 'alias' || $web['type'] == 'subdomain') && $web['redirect_type'] != '' && $web['redirect_path'] != '') return false;
3211                             return true;
3212                         } else {
3213                             return false;
3214                         }
3215                     }
3216                     $pattern = '/^'.str_replace('.', '\.', $web['domain']).'$/i';
3217                 }
3218                 if($web['subdomain'] == 'www'){
3219                     if($web['domain'] == $hostname || $web['subdomain'].'.'.$web['domain'] == $hostname){
3220                         if($web['domain_id'] == $domain_id || $web['parent_domain_id'] == $domain_id){
3221                             // own vhost and therefore server {} container of its own
511ba5 3222                             if($web['type'] == 'vhostsubdomain' || $web['type'] == 'vhostalias') return false;
146783 3223                             // alias domains/subdomains using rewrites and therefore a server {} container of their own
MC 3224                             if(($web['type'] == 'alias' || $web['type'] == 'subdomain') && $web['redirect_type'] != '' && $web['redirect_path'] != '') return false;
3225                             return true;
3226                         } else {
3227                             return false;
3228                         }
3229                     }
3230                     $pattern = '/^(www\.)?'.str_replace('.', '\.', $web['domain']).'$/i';
3231                 }
3232                 if(preg_match($pattern, $hostname)){
3233                     if($web['domain_id'] == $domain_id || $web['parent_domain_id'] == $domain_id){
3234                         // own vhost and therefore server {} container of its own
511ba5 3235                         if($web['type'] == 'vhostsubdomain' || $web['type'] == 'vhostalias') return false;
146783 3236                         // alias domains/subdomains using rewrites and therefore a server {} container of their own
MC 3237                         if(($web['type'] == 'alias' || $web['type'] == 'subdomain') && $web['redirect_type'] != '' && $web['redirect_path'] != '') return false;
3238                         return true;
3239                     } else {
3240                         return false;
3241                     }
3242                 }
3243             }
3244         }
7fe908 3245
146783 3246         return false;
MC 3247     }
7fe908 3248
146783 3249     private function get_seo_redirects($web, $prefix = '', $force_subdomain = false){
MC 3250         // $force_subdomain = 'none|www'
3251         $seo_redirects = array();
7fe908 3252
146783 3253         if(substr($web['domain'], 0, 2) === '*.') $web['subdomain'] = '*';
7fe908 3254
146783 3255         if(($web['subdomain'] == 'www' || $web['subdomain'] == '*') && $force_subdomain != 'www'){
MC 3256             if($web['seo_redirect'] == 'non_www_to_www'){
3257                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = $web['domain'];
3258                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = 'www.'.$web['domain'];
3259                 $seo_redirects[$prefix.'seo_redirect_operator'] = '=';
3260             }
3261             if($web['seo_redirect'] == '*_domain_tld_to_www_domain_tld'){
3262                 // ^(example\.com|(?!\bwww\b)\.example\.com)$
3263                 // ^(example\.com|((?:\w+(?:-\w+)*\.)*)((?!www\.)\w+(?:-\w+)*)(\.example\.com))$
3264                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = '^('.str_replace('.', '\.', $web['domain']).'|((?:\w+(?:-\w+)*\.)*)((?!www\.)\w+(?:-\w+)*)(\.'.str_replace('.', '\.', $web['domain']).'))$';
3265                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = 'www.'.$web['domain'];
3266                 $seo_redirects[$prefix.'seo_redirect_operator'] = '~*';
3267             }
3268             if($web['seo_redirect'] == '*_to_www_domain_tld'){
3269                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = 'www.'.$web['domain'];
3270                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = 'www.'.$web['domain'];
3271                 $seo_redirects[$prefix.'seo_redirect_operator'] = '!=';
3272             }
3273         }
3274         if($force_subdomain != 'none'){
3275             if($web['seo_redirect'] == 'www_to_non_www'){
3276                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = 'www.'.$web['domain'];
3277                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = $web['domain'];
3278                 $seo_redirects[$prefix.'seo_redirect_operator'] = '=';
3279             }
3280             if($web['seo_redirect'] == '*_domain_tld_to_domain_tld'){
3281                 // ^(.+)\.example\.com$
3282                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = '^(.+)\.'.str_replace('.', '\.', $web['domain']).'$';
3283                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = $web['domain'];
3284                 $seo_redirects[$prefix.'seo_redirect_operator'] = '~*';
3285             }
3286             if($web['seo_redirect'] == '*_to_domain_tld'){
3287                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = $web['domain'];
3288                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = $web['domain'];
3289                 $seo_redirects[$prefix.'seo_redirect_operator'] = '!=';
3290             }
3291         }
3292         return $seo_redirects;
3293     }
3294
3295 } // end class
3296
3297 ?>