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