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