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