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