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