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