Pascal Dreissen
2016-07-08 e8dda462f3b02628b4d878ed2c133f1f04d26a50
commit | author | age
46c683 1 <?php
T 2
3 /*
cea1e5 4 Copyright (c) 2007 - 2012, Till Brehm, projektfarm Gmbh
46c683 5 All rights reserved.
T 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 apache2_plugin {
ac933e 32
46c683 33     var $plugin_name = 'apache2_plugin';
T 34     var $class_name = 'apache2_plugin';
ac933e 35
46c683 36     // private variables
T 37     var $action = '';
481c00 38     var $ssl_certificate_changed = false;
496602 39     var $update_letsencrypt = false;
ac933e 40
46c683 41     //* This function is called during ispconfig installation to determine
T 42     //  if a symlink shall be created for this plugin.
43     function onInstall() {
44         global $conf;
ac933e 45
46c683 46         if($conf['services']['web'] == true) {
T 47             return true;
48         } else {
49             return false;
50         }
ac933e 51
46c683 52     }
ac933e 53
V 54
46c683 55     /*
T 56          This function is called when the plugin is loaded
57     */
ac933e 58
46c683 59     function onLoad() {
T 60         global $app;
ac933e 61
46c683 62         /*
T 63         Register for the events
64         */
b1a6a5 65         $app->plugins->registerEvent('web_domain_insert', $this->plugin_name, 'ssl');
MC 66         $app->plugins->registerEvent('web_domain_update', $this->plugin_name, 'ssl');
67         $app->plugins->registerEvent('web_domain_delete', $this->plugin_name, 'ssl');
ac933e 68
b1a6a5 69         $app->plugins->registerEvent('web_domain_insert', $this->plugin_name, 'insert');
MC 70         $app->plugins->registerEvent('web_domain_update', $this->plugin_name, 'update');
71         $app->plugins->registerEvent('web_domain_delete', $this->plugin_name, 'delete');
ac933e 72
b1a6a5 73         $app->plugins->registerEvent('server_ip_insert', $this->plugin_name, 'server_ip');
MC 74         $app->plugins->registerEvent('server_ip_update', $this->plugin_name, 'server_ip');
75         $app->plugins->registerEvent('server_ip_delete', $this->plugin_name, 'server_ip');
ac933e 76
b1a6a5 77         $app->plugins->registerEvent('webdav_user_insert', $this->plugin_name, 'webdav');
MC 78         $app->plugins->registerEvent('webdav_user_update', $this->plugin_name, 'webdav');
79         $app->plugins->registerEvent('webdav_user_delete', $this->plugin_name, 'webdav');
80
81         $app->plugins->registerEvent('client_delete', $this->plugin_name, 'client_delete');
82
83         $app->plugins->registerEvent('web_folder_user_insert', $this->plugin_name, 'web_folder_user');
84         $app->plugins->registerEvent('web_folder_user_update', $this->plugin_name, 'web_folder_user');
85         $app->plugins->registerEvent('web_folder_user_delete', $this->plugin_name, 'web_folder_user');
86
87         $app->plugins->registerEvent('web_folder_update', $this->plugin_name, 'web_folder_update');
88         $app->plugins->registerEvent('web_folder_delete', $this->plugin_name, 'web_folder_delete');
89
90         $app->plugins->registerEvent('ftp_user_delete', $this->plugin_name, 'ftp_user_delete');
91
92         $app->plugins->registerAction('php_ini_changed', $this->plugin_name, 'php_ini_changed');
46c683 93     }
b1a6a5 94
93292a 95     private function get_master_php_ini_content($web_data) {
MB 96         global $app, $conf;
97         
98         $app->uses('getconf');
99         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
100         $fastcgi_config = $app->getconf->get_server_config($conf['server_id'], 'fastcgi');
101         
102         $php_ini_content = '';
103         $master_php_ini_path = '';
104         
105         if($web_data['php'] == 'mod') {
106             $master_php_ini_path = $web_config['php_ini_path_apache'];
107         } else {
108             // check for custom php
109             if($web_data['fastcgi_php_version'] != '') {
110                 $tmp = explode(':', $web_data['fastcgi_php_version']);
111                 if(isset($tmp[2])) {
112                     $tmppath = $tmp[2];
113                     if(substr($tmppath, -7) != 'php.ini') {
114                         if(substr($tmppath, -1) != '/') $tmppath .= '/';
115                         $tmppath .= 'php.ini';
116                     }
117                     if(file_exists($tmppath)) {
118                         $master_php_ini_path = $tmppath;
119                     }
120                     unset($tmppath);
121                 }
122                 unset($tmp);
123             }
124             
125             if(!$master_php_ini_path) {
126                 if($web_data['php'] == 'fast-cgi' && file_exists($fastcgi_config["fastcgi_phpini_path"])) {
127                     $master_php_ini_path = $fastcgi_config["fastcgi_phpini_path"];
128                 } elseif($web_data['php'] == 'php-fpm' && file_exists($web_config['php_fpm_ini_path'])) {
129                     $master_php_ini_path = $fastcgi_config["fastcgi_phpini_path"];
130                 } else {
131                     $master_php_ini_path = $web_config['php_ini_path_cgi'];
132                 }
133             }
134         }
135         if($master_php_ini_path != '' && substr($master_php_ini_path, -7) == 'php.ini' && is_file($master_php_ini_path)) {
136             $php_ini_content .= $app->system->file_get_contents($master_php_ini_path)."\n";
137         }
138         
139         return $php_ini_content;
140     }
b1a6a5 141
MC 142     // Handle php.ini changes
143     function php_ini_changed($event_name, $data) {
144         global $app, $conf;
145
146         $app->uses('getconf');
bd68aa 147         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
MC 148         $fastcgi_config = $app->getconf->get_server_config($conf['server_id'], 'fastcgi');
b1a6a5 149
MC 150         /* $data contains an array with these keys:
bd68aa 151          * file -> full path of changed php_ini
c59632 152          * mode -> web_domain php modes to change (mod, fast-cgi, php-fpm, hhvm or '' for all except 'mod')
bd68aa 153          * php_version -> php ini path that changed (additional php versions)
MC 154          */
b1a6a5 155
2af58c 156         $param = '';
b1a6a5 157         $qrystr = "SELECT * FROM web_domain WHERE custom_php_ini != ''";
MC 158         if($data['mode'] == 'mod') {
159             $qrystr .= " AND php = 'mod'";
160         } elseif($data['mode'] == 'fast-cgi') {
161             $qrystr .= " AND php = 'fast-cgi'";
162             if($data['php_version']) {
2af58c 163                 $qrystr .= " AND fastcgi_php_version LIKE ?";
MC 164                 $param = '%:' . $data['php_version'];
b1a6a5 165             }
MC 166         } elseif($data['mode'] == 'php-fpm') {
167             $qrystr .= " AND php = 'php-fpm'";
c59632 168             if($data['php_version']) {
2af58c 169                 $qrystr .= " AND fastcgi_php_version LIKE ?";
MC 170                 $param = '%:' . $data['php_version'] . ':%';
c59632 171             }
MC 172         } elseif($data['mode'] == 'hhvm') {
173             $qrystr .= " AND php = 'hhvm'";
b1a6a5 174             if($data['php_version']) {
2af58c 175                 $qrystr .= " AND fastcgi_php_version LIKE ?";
MC 176                 $param = '%:' . $data['php_version'] . ':%';
b1a6a5 177             }
MC 178         } else {
179             $qrystr .= " AND php != 'mod' AND php != 'fast-cgi'";
180         }
ac933e 181
bd68aa 182
b1a6a5 183         //** Get all the webs
2af58c 184         $web_domains = $app->db->queryAllRecords($qrystr, $param);
b1a6a5 185         foreach($web_domains as $web_data) {
MC 186             $custom_php_ini_dir = $web_config['website_basedir'].'/conf/'.$web_data['system_user'];
187             $web_folder = 'web';
511ba5 188             if($web_data['type'] == 'vhostsubdomain' || $web_data['type'] == 'vhostalias') {
b1a6a5 189                 $web_folder = $web_data['web_folder'];
MC 190                 $custom_php_ini_dir .= '_' . $web_folder;
191             }
192             if(!is_dir($web_config['website_basedir'].'/conf')) $app->system->mkdir($web_config['website_basedir'].'/conf');
93292a 193             
b1a6a5 194             if(!is_dir($custom_php_ini_dir)) $app->system->mkdir($custom_php_ini_dir);
93292a 195             
MB 196             $php_ini_content = $this->get_master_php_ini_content($web_data);
b41803 197             
MC 198             if(intval($web_data['directive_snippets_id']) > 0){
d22277 199                 $snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'apache' AND active = 'y' AND customer_viewable = 'y'", intval($web_data['directive_snippets_id']));
b41803 200                 if(isset($snippet['required_php_snippets']) && trim($snippet['required_php_snippets']) != ''){
MC 201                     $required_php_snippets = explode(',', trim($snippet['required_php_snippets']));
202                     if(is_array($required_php_snippets) && !empty($required_php_snippets)){
203                         foreach($required_php_snippets as $required_php_snippet){
204                             $required_php_snippet = intval($required_php_snippet);
205                             if($required_php_snippet > 0){
206                                 $php_snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'php' AND active = 'y'", $required_php_snippet);
207                                 $php_snippet['snippet'] = trim($php_snippet['snippet']);
208                                 if($php_snippet['snippet'] != ''){
209                                     $web_data['custom_php_ini'] .= "\n".$php_snippet['snippet'];
210                                 }
211                             }
212                         }
213                     }
214                 }
215             }
216         
b1a6a5 217             $php_ini_content .= str_replace("\r", '', trim($web_data['custom_php_ini']));
MC 218             $app->system->file_put_contents($custom_php_ini_dir.'/php.ini', $php_ini_content);
219             $app->log('Info: rewrote custom php.ini for web ' . $web_data['domain_id'] . ' (' . $web_data['domain'] . ').', LOGLEVEL_DEBUG);
220         }
221
222         if(count($web_domains) > 0) {
223             //* We do not check the apache config here - we only changed the php.ini
224             //* Check if this is a chrooted setup
225             if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
226                 $apache_chrooted = true;
227                 $app->log('Info: Apache is chrooted.', LOGLEVEL_DEBUG);
228             } else {
229                 $apache_chrooted = false;
230             }
231
232             $app->log('Info: rewrote all php.ini and reloading apache now.', LOGLEVEL_DEBUG);
233             if($apache_chrooted) {
234                 $app->services->restartServiceDelayed('httpd', 'restart');
235             } else {
236                 // request a httpd reload when all records have been processed
237                 $app->services->restartServiceDelayed('httpd', 'reload');
238             }
239         } else {
240             $app->log('Info: No webs affected by php.ini change.', LOGLEVEL_DEBUG);
241         }
242     }
243
46c683 244     // Handle the creation of SSL certificates
b1a6a5 245     function ssl($event_name, $data) {
46c683 246         global $app, $conf;
b1a6a5 247
c77103 248         $app->uses('system');
1a2310 249
L 250         // load the server configuration options
251         $app->uses('getconf');
252         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
253         if ($web_config['CA_path']!='' && !file_exists($web_config['CA_path'].'/openssl.cnf'))
b1a6a5 254             $app->log("CA path error, file does not exist:".$web_config['CA_path'].'/openssl.cnf', LOGLEVEL_ERROR);
MC 255
1ca823 256         //* Only vhosts can have a ssl cert
511ba5 257         if($data["new"]["type"] != "vhost" && $data["new"]["type"] != "vhostsubdomain" && $data["new"]["type"] != "vhostalias") return;
ac933e 258
c77103 259         // if(!is_dir($data['new']['document_root'].'/ssl')) exec('mkdir -p '.$data['new']['document_root'].'/ssl');
T 260         if(!is_dir($data['new']['document_root'].'/ssl')) $app->system->mkdirpath($data['new']['document_root'].'/ssl');
b1a6a5 261
fb3339 262         $ssl_dir = $data['new']['document_root'].'/ssl';
J 263         $domain = $data['new']['ssl_domain'];
264         $key_file = $ssl_dir.'/'.$domain.'.key.org';
265         $key_file2 = $ssl_dir.'/'.$domain.'.key';
266         $csr_file = $ssl_dir.'/'.$domain.'.csr';
267         $crt_file = $ssl_dir.'/'.$domain.'.crt';
ac933e 268
4bd960 269         //* Create a SSL Certificate, but only if this is not a mirror server.
T 270         if($data['new']['ssl_action'] == 'create' && $conf['mirror_server_id'] == 0) {
b1a6a5 271
481c00 272             $this->ssl_certificate_changed = true;
b1a6a5 273
e94a9f 274             //* Rename files if they exist
43b345 275             if(file_exists($key_file)){
b1a6a5 276                 $app->system->rename($key_file, $key_file.'.bak');
MC 277                 $app->system->chmod($key_file.'.bak', 0400);
43b345 278             }
T 279             if(file_exists($key_file2)){
b1a6a5 280                 $app->system->rename($key_file2, $key_file2.'.bak');
MC 281                 $app->system->chmod($key_file2.'.bak', 0400);
43b345 282             }
b1a6a5 283             if(file_exists($csr_file)) $app->system->rename($csr_file, $csr_file.'.bak');
MC 284             if(file_exists($crt_file)) $app->system->rename($crt_file, $crt_file.'.bak');
285
fb3339 286             $rand_file = $ssl_dir.'/random_file';
b1a6a5 287             $rand_data = md5(uniqid(microtime(), 1));
ac933e 288             for($i=0; $i<1000; $i++) {
b1a6a5 289                 $rand_data .= md5(uniqid(microtime(), 1));
MC 290                 $rand_data .= md5(uniqid(microtime(), 1));
291                 $rand_data .= md5(uniqid(microtime(), 1));
292                 $rand_data .= md5(uniqid(microtime(), 1));
ac933e 293             }
c77103 294             $app->system->file_put_contents($rand_file, $rand_data);
46c683 295
b1a6a5 296             $ssl_password = substr(md5(uniqid(microtime(), 1)), 0, 15);
ac933e 297
46c683 298             $ssl_cnf = "        RANDFILE               = $rand_file
T 299
300         [ req ]
6d80f5 301         default_bits           = 2048
6068b7 302         default_md             = sha256
46c683 303         default_keyfile        = keyfile.pem
T 304         distinguished_name     = req_distinguished_name
305         attributes             = req_attributes
306         prompt                 = no
307         output_password        = $ssl_password
308
309         [ req_distinguished_name ]
e94a9f 310         C                      = ".trim($data['new']['ssl_country'])."
243697 311         " . (trim($data['new']['ssl_state']) == '' ? '' : "ST                     = ".trim($data['new']['ssl_state'])) . "
MB 312         " . (trim($data['new']['ssl_locality']) == '' ? '' : "L                      = ".trim($data['new']['ssl_locality']))."
313         " . (trim($data['new']['ssl_organisation']) == '' ? '' : "O                      = ".trim($data['new']['ssl_organisation']))."
314         " . (trim($data['new']['ssl_organisation_unit']) == '' ? '' : "OU                     = ".trim($data['new']['ssl_organisation_unit']))."
46c683 315         CN                     = $domain
T 316         emailAddress           = webmaster@".$data['new']['domain']."
317
318         [ req_attributes ]
5a4285 319         ";//challengePassword              = A challenge password";
ac933e 320
fb3339 321             $ssl_cnf_file = $ssl_dir.'/openssl.conf';
b1a6a5 322             $app->system->file_put_contents($ssl_cnf_file, $ssl_cnf);
ac933e 323
46c683 324             $rand_file = escapeshellcmd($rand_file);
T 325             $key_file = escapeshellcmd($key_file);
8c82ef 326             $openssl_cmd_key_file = $key_file;
992797 327             if(substr($domain, 0, 2) == '*.' && strpos($key_file, '/ssl/\*.') !== false) $key_file = str_replace('/ssl/\*.', '/ssl/*.', $key_file); // wildcard certificate
46c683 328             $key_file2 = escapeshellcmd($key_file2);
8c82ef 329             $openssl_cmd_key_file2 = $key_file2;
992797 330             if(substr($domain, 0, 2) == '*.' && strpos($key_file2, '/ssl/\*.') !== false) $key_file2 = str_replace('/ssl/\*.', '/ssl/*.', $key_file2); // wildcard certificate
46c683 331             $ssl_days = 3650;
T 332             $csr_file = escapeshellcmd($csr_file);
8c82ef 333             $openssl_cmd_csr_file = $csr_file;
992797 334             if(substr($domain, 0, 2) == '*.' && strpos($csr_file, '/ssl/\*.') !== false) $csr_file = str_replace('/ssl/\*.', '/ssl/*.', $csr_file); // wildcard certificate
46c683 335             $config_file = escapeshellcmd($ssl_cnf_file);
T 336             $crt_file = escapeshellcmd($crt_file);
8c82ef 337             $openssl_cmd_crt_file = $crt_file;
992797 338             if(substr($domain, 0, 2) == '*.' && strpos($crt_file, '/ssl/\*.') !== false) $crt_file = str_replace('/ssl/\*.', '/ssl/*.', $crt_file); // wildcard certificate
46c683 339
c77103 340             if(is_file($ssl_cnf_file) && !is_link($ssl_cnf_file)) {
b1a6a5 341
8c82ef 342                 exec("openssl genrsa -des3 -rand $rand_file -passout pass:$ssl_password -out $openssl_cmd_key_file 2048");
6068b7 343                 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 344                 exec("openssl rsa -passin pass:$ssl_password -in $openssl_cmd_key_file -out $openssl_cmd_key_file2");
1a2310 345
L 346                 if(file_exists($web_config['CA_path'].'/openssl.cnf'))
5c4d55 347                 {
8c82ef 348                     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");
b1a6a5 349                     $app->log("Creating CA-signed SSL Cert for: $domain", LOGLEVEL_DEBUG);
8c82ef 350                     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);
1a2310 351                 };
723662 352                 if (@filesize($crt_file)==0 || !file_exists($crt_file)){
8c82ef 353                     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 ");
b1a6a5 354                     $app->log("Creating self-signed SSL Cert for: $domain", LOGLEVEL_DEBUG);
5c4d55 355                 };
b1a6a5 356
ac933e 357             }
46c683 358
b1a6a5 359             $app->system->chmod($key_file, 0400);
MC 360             $app->system->chmod($key_file2, 0400);
c77103 361             @$app->system->unlink($config_file);
T 362             @$app->system->unlink($rand_file);
2af58c 363             $ssl_request = $app->system->file_get_contents($csr_file);
MC 364             $ssl_cert = $app->system->file_get_contents($crt_file);
365             $ssl_key2 = $app->system->file_get_contents($key_file2);
d1086f 366             /* Update the DB of the (local) Server */
2af58c 367             $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 368             $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
d1086f 369             /* Update also the master-DB of the Server-Farm */
2af58c 370             $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 371             $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
46c683 372         }
bff982 373         
TB 374         //* Check that the SSL key is not password protected
375         if($data["new"]["ssl_action"] == 'save') {
376             if(stristr($data["new"]["ssl_key"],'Proc-Type: 4,ENCRYPTED')) {
377                 $data["new"]["ssl_action"] = '';
378             
379                 $app->log('SSL Certificate not saved. The SSL key is encrypted.', LOGLEVEL_WARN);
380                 $app->dbmaster->datalogError('SSL Certificate not saved. The SSL key is encrypted.');
381             
382                 /* Update the DB of the (local) Server */
383                 $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
384
385                 /* Update also the master-DB of the Server-Farm */
386                 $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
387             }
388         }
ac933e 389
46c683 390         //* Save a SSL certificate to disk
9f56bd 391         if($data["new"]["ssl_action"] == 'save') {
481c00 392             $this->ssl_certificate_changed = true;
9f56bd 393             $ssl_dir = $data["new"]["document_root"]."/ssl";
edf806 394             $domain = ($data["new"]["ssl_domain"] != '')?$data["new"]["ssl_domain"]:$data["new"]["domain"];
481c00 395             $key_file = $ssl_dir.'/'.$domain.'.key.org';
0d20af 396             $key_file2 = $ssl_dir.'/'.$domain.'.key';
9f56bd 397             $csr_file = $ssl_dir.'/'.$domain.".csr";
T 398             $crt_file = $ssl_dir.'/'.$domain.".crt";
399             $bundle_file = $ssl_dir.'/'.$domain.".bundle";
b1a6a5 400
481c00 401             //* Backup files
43b345 402             if(file_exists($key_file)){
b1a6a5 403                 $app->system->copy($key_file, $key_file.'~');
MC 404                 $app->system->chmod($key_file.'~', 0400);
43b345 405             }
T 406             if(file_exists($key_file2)){
b1a6a5 407                 $app->system->copy($key_file2, $key_file2.'~');
MC 408                 $app->system->chmod($key_file2.'~', 0400);
43b345 409             }
b1a6a5 410             if(file_exists($csr_file)) $app->system->copy($csr_file, $csr_file.'~');
MC 411             if(file_exists($crt_file)) $app->system->copy($crt_file, $crt_file.'~');
412             if(file_exists($bundle_file)) $app->system->copy($bundle_file, $bundle_file.'~');
413
481c00 414             //* Write new ssl files
b1a6a5 415             if(trim($data["new"]["ssl_request"]) != '') $app->system->file_put_contents($csr_file, $data["new"]["ssl_request"]);
f78f1e 416             if(version_compare($app->system->getapacheversion(true), '2.4.8', '>=')) {
MC 417                 $tmp_data = '';
418                 if(trim($data["new"]["ssl_cert"]) != '') $tmp_data .= $data["new"]["ssl_cert"] . "\n";
419                 if(trim($data["new"]["ssl_bundle"]) != '') $tmp_data .= $data["new"]["ssl_bundle"];
420                 if(trim($tmp_data) != '') $app->system->file_put_contents($crt_file, $tmp_data);
421             } else {
422                 if(trim($data["new"]["ssl_cert"]) != '') $app->system->file_put_contents($crt_file, $data["new"]["ssl_cert"]);
423                 if(trim($data["new"]["ssl_bundle"]) != '') $app->system->file_put_contents($bundle_file, $data["new"]["ssl_bundle"]);
424             }
b1a6a5 425
72695f 426             //* Write the key file, if field is empty then import the key into the db
T 427             if(trim($data["new"]["ssl_key"]) != '') {
b1a6a5 428                 $app->system->file_put_contents($key_file2, $data["new"]["ssl_key"]);
MC 429                 $app->system->chmod($key_file2, 0400);
72695f 430             } else {
2af58c 431                 $ssl_key2 = $app->system->file_get_contents($key_file2);
72695f 432                 /* Update the DB of the (local) Server */
2af58c 433                 $app->db->query("UPDATE web_domain SET ssl_key = ? WHERE domain = ?", $ssl_key2, $data['new']['domain']);
72695f 434                 /* Update also the master-DB of the Server-Farm */
2af58c 435                 $app->dbmaster->query("UPDATE web_domain SET ssl_key = ? WHERE domain = ?", $ssl_key2, $data['new']['domain']);
72695f 436             }
b1a6a5 437
d1086f 438             /* Update the DB of the (local) Server */
2af58c 439             $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
b1a6a5 440
d1086f 441             /* Update also the master-DB of the Server-Farm */
2af58c 442             $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
b1a6a5 443             $app->log('Saving SSL Cert for: '.$domain, LOGLEVEL_DEBUG);
46c683 444         }
ac933e 445
46c683 446         //* Delete a SSL certificate
fb3339 447         if($data['new']['ssl_action'] == 'del') {
J 448             $ssl_dir = $data['new']['document_root'].'/ssl';
edf806 449             $domain = ($data["new"]["ssl_domain"] != '')?$data["new"]["ssl_domain"]:$data["new"]["domain"];
fb3339 450             $csr_file = $ssl_dir.'/'.$domain.'.csr';
J 451             $crt_file = $ssl_dir.'/'.$domain.'.crt';
452             $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
c77103 453             if(file_exists($web_config['CA_path'].'/openssl.cnf') && !is_link($web_config['CA_path'].'/openssl.cnf'))
b1a6a5 454             {
8c82ef 455                 exec("openssl ca -batch -config ".$web_config['CA_path']."/openssl.cnf -passin pass:".$web_config['CA_pass']." -revoke ".escapeshellcmd($crt_file));
b1a6a5 456                 $app->log("Revoking CA-signed SSL Cert for: $domain", LOGLEVEL_DEBUG);
MC 457             };
c77103 458             $app->system->unlink($csr_file);
T 459             $app->system->unlink($crt_file);
460             $app->system->unlink($bundle_file);
d1086f 461             /* Update the DB of the (local) Server */
2af58c 462             $app->db->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '' WHERE domain = ?", $data['new']['domain']);
MC 463             $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
d1086f 464             /* Update also the master-DB of the Server-Farm */
2af58c 465             $app->dbmaster->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '' WHERE domain = ?", $data['new']['domain']);
MC 466             $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
b1a6a5 467             $app->log('Deleting SSL Cert for: '.$domain, LOGLEVEL_DEBUG);
46c683 468         }
ac933e 469
46c683 470     }
ac933e 471
V 472
b1a6a5 473     function insert($event_name, $data) {
46c683 474         global $app, $conf;
ac933e 475
46c683 476         $this->action = 'insert';
T 477         // just run the update function
b1a6a5 478         $this->update($event_name, $data);
ac933e 479
V 480
46c683 481     }
ac933e 482
V 483
b1a6a5 484     function update($event_name, $data) {
46c683 485         global $app, $conf;
ac933e 486
46c683 487         if($this->action != 'insert') $this->action = 'update';
ac933e 488
511ba5 489         if($data['new']['type'] != 'vhost' && $data['new']['type'] != 'vhostsubdomain' && $data['new']['type'] != 'vhostalias' && $data['new']['parent_domain_id'] > 0) {
ac933e 490
fb3339 491             $old_parent_domain_id = intval($data['old']['parent_domain_id']);
J 492             $new_parent_domain_id = intval($data['new']['parent_domain_id']);
ac933e 493
1ca823 494             // If the parent_domain_id has been changed, we will have to update the old site as well.
fb3339 495             if($this->action == 'update' && $data['new']['parent_domain_id'] != $data['old']['parent_domain_id']) {
2af58c 496                 $tmp = $app->db->queryOneRecord('SELECT * FROM web_domain WHERE domain_id = ? AND active = ?', $old_parent_domain_id, 'y');
fb3339 497                 $data['new'] = $tmp;
J 498                 $data['old'] = $tmp;
46c683 499                 $this->action = 'update';
b1a6a5 500                 $this->update($event_name, $data);
46c683 501             }
ac933e 502
46c683 503             // This is not a vhost, so we need to update the parent record instead.
5d0363 504             $tmp = $app->db->queryOneRecord('SELECT * FROM web_domain WHERE domain_id = ? AND active = ?', $new_parent_domain_id, 'y');
fb3339 505             $data['new'] = $tmp;
J 506             $data['old'] = $tmp;
46c683 507             $this->action = 'update';
496602 508             $this->update_letsencrypt = true;
46c683 509         }
ac933e 510
46c683 511         // load the server configuration options
fb3339 512         $app->uses('getconf');
J 513         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
ac933e 514
2bbc4c 515         //* Check if this is a chrooted setup
155cc0 516         if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
2bbc4c 517             $apache_chrooted = true;
b1a6a5 518             $app->log('Info: Apache is chrooted.', LOGLEVEL_DEBUG);
2bbc4c 519         } else {
T 520             $apache_chrooted = false;
521         }
ac933e 522
fb3339 523         if($data['new']['document_root'] == '') {
511ba5 524             if($data['new']['type'] == 'vhost' || $data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') $app->log('document_root not set', LOGLEVEL_WARN);
46c683 525             return 0;
T 526         }
15687e 527         if($app->system->is_allowed_user($data['new']['system_user'], $app->system->is_user($data['new']['system_user']), true) == false
TB 528             || $app->system->is_allowed_group($data['new']['system_group'], $app->system->is_group($data['new']['system_group']), true) == false) {
529             $app->log('Websites cannot be owned by the root user or group. User: '.$data['new']['system_user'].' Group: '.$data['new']['system_group'], LOGLEVEL_WARN);
46c683 530             return 0;
T 531         }
e94a9f 532         if(trim($data['new']['domain']) == '') {
b1a6a5 533             $app->log('domain is empty', LOGLEVEL_WARN);
e94a9f 534             return 0;
T 535         }
b1a6a5 536
MC 537         $web_folder = 'web';
538         $log_folder = 'log';
79d955 539         $old_web_folder = 'web';
MC 540         $old_log_folder = 'log';
511ba5 541         if($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') {
79d955 542             // new one
2af58c 543             $tmp = $app->db->queryOneRecord('SELECT `domain` FROM web_domain WHERE domain_id = ?', $data['new']['parent_domain_id']);
b1a6a5 544             $subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $data['new']['domain']);
MC 545             if($subdomain_host == '') $subdomain_host = 'web'.$data['new']['domain_id'];
546             $web_folder = $data['new']['web_folder'];
547             $log_folder .= '/' . $subdomain_host;
548             unset($tmp);
79d955 549             
MC 550             if(isset($data['old']['parent_domain_id'])) {
551                 // old one
2af58c 552                 $tmp = $app->db->queryOneRecord('SELECT `domain` FROM web_domain WHERE domain_id = ?', $data['old']['parent_domain_id']);
79d955 553                 $subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $data['old']['domain']);
MC 554                 if($subdomain_host == '') $subdomain_host = 'web'.$data['old']['domain_id'];
555                 $old_web_folder = $data['old']['web_folder'];
556                 $old_log_folder .= '/' . $subdomain_host;
557                 unset($tmp);
558             }
b1a6a5 559         }
6fb93d 560
dba68f 561         // Create group and user, if not exist
T 562         $app->uses('system');
b1a6a5 563
8cf78b 564         if($web_config['connect_userid_to_webid'] == 'y') {
T 565             //* Calculate the uid and gid
566             $connect_userid_to_webid_start = ($web_config['connect_userid_to_webid_start'] < 1000)?1000:intval($web_config['connect_userid_to_webid_start']);
567             $fixed_uid_gid = intval($connect_userid_to_webid_start + $data['new']['domain_id']);
568             $fixed_uid_param = '--uid '.$fixed_uid_gid;
569             $fixed_gid_param = '--gid '.$fixed_uid_gid;
b1a6a5 570
8cf78b 571             //* Check if a ispconfigend user and group exists and create them
T 572             if(!$app->system->is_group('ispconfigend')) {
573                 exec('groupadd --gid '.($connect_userid_to_webid_start + 10000).' ispconfigend');
574             }
575             if(!$app->system->is_user('ispconfigend')) {
576                 exec('useradd -g ispconfigend -d /usr/local/ispconfig --uid '.($connect_userid_to_webid_start + 10000).' ispconfigend');
577             }
578         } else {
579             $fixed_uid_param = '';
580             $fixed_gid_param = '';
581         }
dba68f 582
T 583         $groupname = escapeshellcmd($data['new']['system_group']);
584         if($data['new']['system_group'] != '' && !$app->system->is_group($data['new']['system_group'])) {
8cf78b 585             exec('groupadd '.$fixed_gid_param.' '.$groupname);
dba68f 586             if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' groupadd '.$groupname);
b1a6a5 587             $app->log('Adding the group: '.$groupname, LOGLEVEL_DEBUG);
dba68f 588         }
T 589
590         $username = escapeshellcmd($data['new']['system_user']);
591         if($data['new']['system_user'] != '' && !$app->system->is_user($data['new']['system_user'])) {
8cf78b 592             if($web_config['add_web_users_to_sshusers_group'] == 'y') {
T 593                 exec('useradd -d '.escapeshellcmd($data['new']['document_root'])." -g $groupname $fixed_uid_param -G sshusers $username -s /bin/false");
594                 if($apache_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");
595             } else {
596                 exec('useradd -d '.escapeshellcmd($data['new']['document_root'])." -g $groupname $fixed_uid_param $username -s /bin/false");
597                 if($apache_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");
598             }
b1a6a5 599             $app->log('Adding the user: '.$username, LOGLEVEL_DEBUG);
dba68f 600         }
ac933e 601
46c683 602         //* If the client of the site has been changed, we have a change of the document root
fb3339 603         if($this->action == 'update' && $data['new']['document_root'] != $data['old']['document_root']) {
ac933e 604
46c683 605             //* Get the old client ID
2af58c 606             $old_client = $app->dbmaster->queryOneRecord('SELECT client_id FROM sys_group WHERE sys_group.groupid = ?', $data['old']['sys_groupid']);
fb3339 607             $old_client_id = intval($old_client['client_id']);
46c683 608             unset($old_client);
ac933e 609
46c683 610             //* Remove the old symlinks
b1a6a5 611             $tmp_symlinks_array = explode(':', $web_config['website_symlinks']);
46c683 612             if(is_array($tmp_symlinks_array)) {
T 613                 foreach($tmp_symlinks_array as $tmp_symlink) {
b1a6a5 614                     $tmp_symlink = str_replace('[client_id]', $old_client_id, $tmp_symlink);
MC 615                     $tmp_symlink = str_replace('[website_domain]', $data['old']['domain'], $tmp_symlink);
46c683 616                     // Remove trailing slash
T 617                     if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
618                     // create the symlinks, if not exist
436975 619                     if(is_link($tmp_symlink)) {
fb3339 620                         exec('rm -f '.escapeshellcmd($tmp_symlink));
b1a6a5 621                         $app->log('Removed symlink: rm -f '.$tmp_symlink, LOGLEVEL_DEBUG);
46c683 622                     }
T 623                 }
624             }
b1a6a5 625
4b9329 626             //* Remove protection of old folders
b1a6a5 627             $app->system->web_folder_protection($data['old']['document_root'], false);
ac933e 628
511ba5 629             if($data["new"]["type"] != "vhostsubdomain" && $data["new"]["type"] != "vhostalias") {
b1a6a5 630                 //* Move the site data
MC 631                 $tmp_docroot = explode('/', $data['new']['document_root']);
632                 unset($tmp_docroot[count($tmp_docroot)-1]);
633                 $new_dir = implode('/', $tmp_docroot);
ac933e 634
b1a6a5 635                 $tmp_docroot = explode('/', $data['old']['document_root']);
MC 636                 unset($tmp_docroot[count($tmp_docroot)-1]);
637                 $old_dir = implode('/', $tmp_docroot);
ac933e 638
b1a6a5 639                 //* 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
MC 640                 if(@is_dir($data['new']['document_root'])) {
641                     $app->system->web_folder_protection($data['new']['document_root'], false);
642                     $app->system->rename($data['new']['document_root'], $data['new']['document_root'].'_bak_'.date('Y_m_d_H_i_s'));
643                     $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);
644                 }
3fb802 645                 
TB 646                 //* Unmount the old log directory bfore we move the log dir
a9b325 647                 //exec('fuser -km '.escapeshellcmd($old_dir.'/log'));
c8679f 648                 exec('umount '.escapeshellcmd($data['old']['document_root'].'/log'));
ac933e 649
b1a6a5 650                 //* Create new base directory, if it does not exist yet
MC 651                 if(!is_dir($new_dir)) $app->system->mkdirpath($new_dir);
652                 $app->system->web_folder_protection($data['old']['document_root'], false);
653                 exec('mv '.escapeshellarg($data['old']['document_root']).' '.escapeshellarg($new_dir));
654                 //$app->system->rename($data['old']['document_root'],$new_dir);
655                 $app->log('Moving site to new document root: mv '.$data['old']['document_root'].' '.$new_dir, LOGLEVEL_DEBUG);
0930f5 656
b1a6a5 657                 // Handle the change in php_open_basedir
MC 658                 $data['new']['php_open_basedir'] = str_replace($data['old']['document_root'], $data['new']['document_root'], $data['old']['php_open_basedir']);
659
660                 //* Change the owner of the website files to the new website owner
661                 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);
662
663                 //* Change the home directory and group of the website user
664                 $command = 'killall -u '.escapeshellcmd($data['new']['system_user']).' ; usermod';
665                 $command .= ' --home '.escapeshellcmd($data['new']['document_root']);
666                 $command .= ' --gid '.escapeshellcmd($data['new']['system_group']);
667                 $command .= ' '.escapeshellcmd($data['new']['system_user']).' 2>/dev/null';
668                 exec($command);
669             }
670
fb3339 671             if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' '.$command);
b1a6a5 672
10b4c8 673             //* Change the log mount
074a57 674             /*
79d955 675             $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$old_log_folder.'    none    bind';
b1a6a5 676             $app->system->removeLine('/etc/fstab', $fstab_line);
79d955 677             $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$old_log_folder.'    none    bind,nobootwait';
ff5b86 678             $app->system->removeLine('/etc/fstab', $fstab_line);
074a57 679             $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$old_log_folder.'    none    bind,nobootwait';
TB 680             $app->system->removeLine('/etc/fstab', $fstab_line);
681             */
682             
683             $fstab_line_old = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$old_log_folder.'    none    bind';
684             
685             if($web_config['network_filesystem'] == 'y') {
686                 $fstab_line = '/var/log/ispconfig/httpd/'.$data['new']['domain'].' '.$data['new']['document_root'].'/'.$log_folder.'    none    bind,nobootwait,_netdev    0 0';
687                 $app->system->replaceLine('/etc/fstab', $fstab_line_old, $fstab_line, 0, 1);
688             } else {
689                 $fstab_line = '/var/log/ispconfig/httpd/'.$data['new']['domain'].' '.$data['new']['document_root'].'/'.$log_folder.'    none    bind,nobootwait    0 0';
690                 $app->system->replaceLine('/etc/fstab', $fstab_line_old, $fstab_line, 0, 1);
691             }
3fb802 692             
TB 693             exec('mount --bind '.escapeshellarg('/var/log/ispconfig/httpd/'.$data['new']['domain']).' '.escapeshellarg($data['new']['document_root'].'/'.$log_folder));
074a57 694             
46c683 695         }
ac933e 696
46c683 697         //print_r($data);
ac933e 698
fb3339 699         // Check if the directories are there and create them if necessary.
b1a6a5 700         $app->system->web_folder_protection($data['new']['document_root'], false);
MC 701
6fb93d 702         if(!is_dir($data['new']['document_root'].'/' . $web_folder)) $app->system->mkdirpath($data['new']['document_root'].'/' . $web_folder);
M 703         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 704         if(!is_dir($data['new']['document_root'].'/' . $web_folder . '/stats')) $app->system->mkdirpath($data['new']['document_root'].'/' . $web_folder . '/stats');
6fb93d 705         //if(!is_dir($data['new']['document_root'].'/'.$log_folder)) exec('mkdir -p '.$data['new']['document_root'].'/'.$log_folder);
c77103 706         if(!is_dir($data['new']['document_root'].'/ssl')) $app->system->mkdirpath($data['new']['document_root'].'/ssl');
T 707         if(!is_dir($data['new']['document_root'].'/cgi-bin')) $app->system->mkdirpath($data['new']['document_root'].'/cgi-bin');
708         if(!is_dir($data['new']['document_root'].'/tmp')) $app->system->mkdirpath($data['new']['document_root'].'/tmp');
709         if(!is_dir($data['new']['document_root'].'/webdav')) $app->system->mkdirpath($data['new']['document_root'].'/webdav');
b1a6a5 710
d87f76 711         //* Create the new private directory
T 712         if(!is_dir($data['new']['document_root'].'/private')) {
713             $app->system->mkdirpath($data['new']['document_root'].'/private');
b1a6a5 714             $app->system->chmod($data['new']['document_root'].'/private', 0710);
MC 715             $app->system->chown($data['new']['document_root'].'/private', $username);
716             $app->system->chgrp($data['new']['document_root'].'/private', $groupname);
d87f76 717         }
b1a6a5 718
MC 719
46c683 720         // Remove the symlink for the site, if site is renamed
fb3339 721         if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
J 722             if(is_dir('/var/log/ispconfig/httpd/'.$data['old']['domain'])) exec('rm -rf /var/log/ispconfig/httpd/'.$data['old']['domain']);
79d955 723             if(is_link($data['old']['document_root'].'/'.$old_log_folder)) $app->system->unlink($data['old']['document_root'].'/'.$old_log_folder);
b1a6a5 724
10b4c8 725             //* remove old log mount
79d955 726             $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$old_log_folder.'    none    bind';
b1a6a5 727             $app->system->removeLine('/etc/fstab', $fstab_line);
MC 728
10b4c8 729             //* Unmount log directory
a9b325 730             //exec('fuser -km '.escapeshellarg($data['old']['document_root'].'/'.$old_log_folder));
79d955 731             exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$old_log_folder));
46c683 732         }
b1a6a5 733
d5a517 734         //* Create the log dir if nescessary and mount it
10b4c8 735         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)) {
6fb93d 736             if(is_link($data['new']['document_root'].'/'.$log_folder)) unlink($data['new']['document_root'].'/'.$log_folder);
10b4c8 737             if(!is_dir('/var/log/ispconfig/httpd/'.$data['new']['domain'])) exec('mkdir -p /var/log/ispconfig/httpd/'.$data['new']['domain']);
c3bf39 738             $app->system->mkdirpath($data['new']['document_root'].'/'.$log_folder);
b1a6a5 739             $app->system->chown($data['new']['document_root'].'/'.$log_folder, 'root');
MC 740             $app->system->chgrp($data['new']['document_root'].'/'.$log_folder, 'root');
741             $app->system->chmod($data['new']['document_root'].'/'.$log_folder, 0755);
6fb93d 742             exec('mount --bind '.escapeshellarg('/var/log/ispconfig/httpd/'.$data['new']['domain']).' '.escapeshellarg($data['new']['document_root'].'/'.$log_folder));
d5a517 743             //* add mountpoint to fstab
c8679f 744             $fstab_line = '/var/log/ispconfig/httpd/'.$data['new']['domain'].' '.$data['new']['document_root'].'/'.$log_folder.'    none    bind,nobootwait';
FS 745             $fstab_line .= @($web_config['network_filesystem'] == 'y')?',_netdev    0 0':'    0 0';
b1a6a5 746             $app->system->replaceLine('/etc/fstab', $fstab_line, $fstab_line, 1, 1);
d5a517 747         }
b1a6a5 748
MC 749         $app->system->web_folder_protection($data['new']['document_root'], true);
ac933e 750
46c683 751         // Get the client ID
2af58c 752         $client = $app->dbmaster->queryOneRecord('SELECT client_id FROM sys_group WHERE sys_group.groupid = ?', $data['new']['sys_groupid']);
fb3339 753         $client_id = intval($client['client_id']);
46c683 754         unset($client);
ac933e 755
46c683 756         // Remove old symlinks, if site is renamed
fb3339 757         if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
b1a6a5 758             $tmp_symlinks_array = explode(':', $web_config['website_symlinks']);
46c683 759             if(is_array($tmp_symlinks_array)) {
T 760                 foreach($tmp_symlinks_array as $tmp_symlink) {
b1a6a5 761                     $tmp_symlink = str_replace('[client_id]', $client_id, $tmp_symlink);
MC 762                     $tmp_symlink = str_replace('[website_domain]', $data['old']['domain'], $tmp_symlink);
46c683 763                     // Remove trailing slash
T 764                     if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
765                     // remove the symlinks, if not exist
766                     if(is_link($tmp_symlink)) {
fb3339 767                         exec('rm -f '.escapeshellcmd($tmp_symlink));
b1a6a5 768                         $app->log('Removed symlink: rm -f '.$tmp_symlink, LOGLEVEL_DEBUG);
46c683 769                     }
T 770                 }
771             }
772         }
ac933e 773
46c683 774         // Create the symlinks for the sites
b1a6a5 775         $tmp_symlinks_array = explode(':', $web_config['website_symlinks']);
46c683 776         if(is_array($tmp_symlinks_array)) {
T 777             foreach($tmp_symlinks_array as $tmp_symlink) {
b1a6a5 778                 $tmp_symlink = str_replace('[client_id]', $client_id, $tmp_symlink);
MC 779                 $tmp_symlink = str_replace('[website_domain]', $data['new']['domain'], $tmp_symlink);
46c683 780                 // Remove trailing slash
T 781                 if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
782                 //* Remove symlink if target folder has been changed.
fb3339 783                 if($data['old']['document_root'] != '' && $data['old']['document_root'] != $data['new']['document_root'] && is_link($tmp_symlink)) {
c77103 784                     $app->system->unlink($tmp_symlink);
46c683 785                 }
T 786                 // create the symlinks, if not exist
787                 if(!is_link($tmp_symlink)) {
b1a6a5 788                     //     exec("ln -s ".escapeshellcmd($data["new"]["document_root"])."/ ".escapeshellcmd($tmp_symlink));
552178 789                     if ($web_config["website_symlinks_rel"] == 'y') {
M 790                         $this->create_relative_link(escapeshellcmd($data["new"]["document_root"]), escapeshellcmd($tmp_symlink));
791                     } else {
792                         exec("ln -s ".escapeshellcmd($data["new"]["document_root"])."/ ".escapeshellcmd($tmp_symlink));
793                     }
794
b1a6a5 795                     $app->log('Creating symlink: ln -s '.$data['new']['document_root'].'/ '.$tmp_symlink, LOGLEVEL_DEBUG);
46c683 796                 }
T 797             }
798         }
ac933e 799
V 800
3e41e8 801
b1a6a5 802         // Install the Standard or Custom Error, Index and other related files
MC 803         // /usr/local/ispconfig/server/conf is for the standard files
804         // /usr/local/ispconfig/server/conf-custom is for the custom files
805         // setting a local var here
806
807         // normally $conf['templates'] = "/usr/local/ispconfig/server/conf";
511ba5 808         if($this->action == 'insert' && ($data['new']['type'] == 'vhost' || $data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias')) {
b1a6a5 809
MC 810             // Copy the error pages
fb3339 811             if($data['new']['errordocs']) {
6fb93d 812                 $error_page_path = escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/error/';
b1a6a5 813                 if (file_exists($conf['rootpath'] . '/conf-custom/error/'.substr(escapeshellcmd($conf['language']), 0, 2))) {
MC 814                     exec('cp ' . $conf['rootpath'] . '/conf-custom/error/'.substr(escapeshellcmd($conf['language']), 0, 2).'/* '.$error_page_path);
46c683 815                 }
T 816                 else {
4ffb51 817                     if (file_exists($conf['rootpath'] . '/conf-custom/error/400.html')) {
F 818                         exec('cp '. $conf['rootpath'] . '/conf-custom/error/*.html '.$error_page_path);
46c683 819                     }
T 820                     else {
b1a6a5 821                         exec('cp ' . $conf['rootpath'] . '/conf/error/'.substr(escapeshellcmd($conf['language']), 0, 2).'/* '.$error_page_path);
46c683 822                     }
T 823                 }
fb3339 824                 exec('chmod -R a+r '.$error_page_path);
46c683 825             }
T 826
b1a6a5 827             if (file_exists($conf['rootpath'] . '/conf-custom/index/standard_index.html_'.substr(escapeshellcmd($conf['language']), 0, 2))) {
f0dfa9 828                 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');
b1a6a5 829
MC 830                 if(is_file($conf['rootpath'] . '/conf-custom/index/favicon.ico')) {
f0dfa9 831                     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 . '/');
b1a6a5 832                 }
MC 833                 if(is_file($conf['rootpath'] . '/conf-custom/index/robots.txt')) {
f0dfa9 834                     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 . '/');
b1a6a5 835                 }
MC 836                 if(is_file($conf['rootpath'] . '/conf-custom/index/.htaccess')) {
f0dfa9 837                     if(!file_exists(escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/.htaccess')) exec('cp ' . $conf['rootpath'] . '/conf-custom/index/.htaccess '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/');
b1a6a5 838                 }
f0dfa9 839             } else {
4ffb51 840                 if (file_exists($conf['rootpath'] . '/conf-custom/index/standard_index.html')) {
f0dfa9 841                     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 842                 } else {
843                     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');
844                     if(is_file($conf['rootpath'] . '/conf/index/favicon.ico')){
845                         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 . '/');
846                     }
847                     if(is_file($conf['rootpath'] . '/conf/index/robots.txt')){
848                         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 . '/');
849                     }
850                     if(is_file($conf['rootpath'] . '/conf/index/.htaccess')){
851                         if(!file_exists(escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/.htaccess')) exec('cp ' . $conf['rootpath'] . '/conf/index/.htaccess '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/');
852                     }
46c683 853                 }
T 854             }
6fb93d 855             exec('chmod -R a+r '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/');
ac933e 856
V 857             //** Copy the error documents on update when the error document checkbox has been activated and was deactivated before
511ba5 858         } elseif ($this->action == 'update' && ($data['new']['type'] == 'vhost' || $data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') && $data['old']['errordocs'] == 0 && $data['new']['errordocs'] == 1) {
b1a6a5 859
6fb93d 860             $error_page_path = escapeshellcmd($data['new']['document_root']).'/' . $web_folder . '/error/';
b1a6a5 861             if (file_exists($conf['rootpath'] . '/conf-custom/error/'.substr(escapeshellcmd($conf['language']), 0, 2))) {
MC 862                 exec('cp ' . $conf['rootpath'] . '/conf-custom/error/'.substr(escapeshellcmd($conf['language']), 0, 2).'/* '.$error_page_path);
46c683 863             }
T 864             else {
4ffb51 865                 if (file_exists($conf['rootpath'] . '/conf-custom/error/400.html')) {
F 866                     exec('cp ' . $conf['rootpath'] . '/conf-custom/error/*.html '.$error_page_path);
46c683 867                 }
T 868                 else {
b1a6a5 869                     exec('cp ' . $conf['rootpath'] . '/conf/error/'.substr(escapeshellcmd($conf['language']), 0, 2).'/* '.$error_page_path);
46c683 870                 }
T 871             }
fb3339 872             exec('chmod -R a+r '.$error_page_path);
5d5d88 873             exec('chown -R '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.$error_page_path);
46c683 874         }  // end copy error docs
ac933e 875
511ba5 876         // Set the quota for the user, but only for vhosts, not vhostsubdomains or vhostalias
cc6568 877         if($username != '' && $app->system->is_user($username) && $data['new']['type'] == 'vhost') {
fb3339 878             if($data['new']['hd_quota'] > 0) {
J 879                 $blocks_soft = $data['new']['hd_quota'] * 1024;
ac933e 880                 $blocks_hard = $blocks_soft + 1024;
e14c6e 881                 $mb_hard = $mb_soft + 1;
ac933e 882             } else {
e14c6e 883                 $mb_soft = $mb_hard = $blocks_soft = $blocks_hard = 0;
ac933e 884             }
e14c6e 885             
D 886           // get the primitive folder for document_root and the filesystem, will need it later.
e8dda4 887           $df_output=explode(" ", exec("df -T " . escapeshellarg($data['new']['document_root']) . "|awk 'END{print \$2,\$NF}'"));
7de9c4 888           $file_system = $df_output[0];
TB 889           $primitive_root = $df_output[1];
e14c6e 890
e4393f 891           if ( in_array($file_system , array('ext2','ext3','ext4'), true) ) {
e14c6e 892             exec('setquota -u '. $username . ' ' . $blocks_soft . ' ' . $blocks_hard . ' 0 0 -a &> /dev/null');
D 893             exec('setquota -T -u '.$username.' 604800 604800 -a &> /dev/null');
894           } elseif ($file_system == 'xfs') {
895
896             exec("xfs_quota -x -c 'limit -g bsoft=$mb_soft" . 'm'. " bhard=$mb_hard" . 'm'. " $username' $primitive_root");
897
898             // xfs only supports timers globally, not per user.
899             exec("xfs_quota -x -c 'timer -bir -i 604800'");
900
901             unset($project_uid, $username_position, $xfs_projects);
902             unset($primitive_root, $df_output, $mb_hard, $mb_soft);
903           }
46c683 904         }
ac933e 905
1ca823 906         if($this->action == 'insert' || $data["new"]["system_user"] != $data["old"]["system_user"]) {
46c683 907             // Chown and chmod the directories below the document root
6fb93d 908             $this->_exec('chown -R '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder);
8db8f3 909             // The document root itself has to be owned by root in normal level and by the web owner in security level 20
T 910             if($web_config['security_level'] == 20) {
6fb93d 911                 $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder);
8db8f3 912             } else {
6fb93d 913                 $this->_exec('chown root:root '.escapeshellcmd($data['new']['document_root']).'/' . $web_folder);
8db8f3 914             }
46c683 915         }
b1a6a5 916
615a0a 917         //* add the Apache 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
T 918         if($data['new']['type'] == 'vhost' && $web_config['security_level'] == 20) $app->system->add_user_to_group($groupname, escapeshellcmd($web_config['user']));
ac933e 919
8db8f3 920         //* If the security level is set to high
8cf78b 921         if(($this->action == 'insert' && $data['new']['type'] == 'vhost') or ($web_config['set_folder_permissions_on_update'] == 'y' && $data['new']['type'] == 'vhost')) {
b1a6a5 922
MC 923             $app->system->web_folder_protection($data['new']['document_root'], false);
924
d87f76 925             //* Check if we have the new private folder and create it if nescessary
T 926             if(!is_dir($data['new']['document_root'].'/private')) $app->system->mkdir($data['new']['document_root'].'/private');
b1a6a5 927
edf806 928             if($web_config['security_level'] == 20) {
b1a6a5 929
MC 930                 $app->system->chmod($data['new']['document_root'], 0755);
7c37ed 931                 $app->system->chmod($data['new']['document_root'].'/web', 0711);
b1a6a5 932                 $app->system->chmod($data['new']['document_root'].'/webdav', 0710);
MC 933                 $app->system->chmod($data['new']['document_root'].'/private', 0710);
934                 $app->system->chmod($data['new']['document_root'].'/ssl', 0755);
ac933e 935
edf806 936                 // make tmp directory writable for Apache and the website users
5aedfd 937                 $app->system->chmod($data['new']['document_root'].'/tmp', 0770);
b1a6a5 938
cea1e5 939                 // Set Log directory to 755 to make the logs accessible by the FTP user
418b41 940                 if(realpath($data['new']['document_root'].'/'.$log_folder . '/error.log') == '/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log') {
b1a6a5 941                     $app->system->chmod($data['new']['document_root'].'/'.$log_folder, 0755);
c77103 942                 }
b1a6a5 943
8cf78b 944                 if($web_config['add_web_users_to_sshusers_group'] == 'y') {
T 945                     $command = 'usermod';
946                     $command .= ' --groups sshusers';
526b99 947                     $command .= ' '.escapeshellcmd($data['new']['system_user']).' 2>/dev/null';
8cf78b 948                     $this->_exec($command);
T 949                 }
ac933e 950
edf806 951                 //* if we have a chrooted Apache environment
T 952                 if($apache_chrooted) {
953                     $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' '.$command);
ac933e 954
edf806 955                     //* add the apache user to the client group in the chroot environment
T 956                     $tmp_groupfile = $app->system->server_conf['group_datei'];
957                     $app->system->server_conf['group_datei'] = $web_config['website_basedir'].'/etc/group';
958                     $app->system->add_user_to_group($groupname, escapeshellcmd($web_config['user']));
959                     $app->system->server_conf['group_datei'] = $tmp_groupfile;
960                     unset($tmp_groupfile);
961                 }
b1a6a5 962
8cf78b 963                 //* Chown all default directories
b1a6a5 964                 $app->system->chown($data['new']['document_root'], 'root');
MC 965                 $app->system->chgrp($data['new']['document_root'], 'root');
966                 $app->system->chown($data['new']['document_root'].'/cgi-bin', $username);
967                 $app->system->chgrp($data['new']['document_root'].'/cgi-bin', $groupname);
418b41 968                 if(realpath($data['new']['document_root'].'/'.$log_folder . '/error.log') == '/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log') {
b1a6a5 969                     $app->system->chown($data['new']['document_root'].'/'.$log_folder, 'root', false);
MC 970                     $app->system->chgrp($data['new']['document_root'].'/'.$log_folder, $groupname, false);
c77103 971                 }
b1a6a5 972                 $app->system->chown($data['new']['document_root'].'/ssl', 'root');
MC 973                 $app->system->chgrp($data['new']['document_root'].'/ssl', 'root');
974                 $app->system->chown($data['new']['document_root'].'/tmp', $username);
975                 $app->system->chgrp($data['new']['document_root'].'/tmp', $groupname);
976                 $app->system->chown($data['new']['document_root'].'/web', $username);
977                 $app->system->chgrp($data['new']['document_root'].'/web', $groupname);
978                 $app->system->chown($data['new']['document_root'].'/web/error', $username);
979                 $app->system->chgrp($data['new']['document_root'].'/web/error', $groupname);
980                 $app->system->chown($data['new']['document_root'].'/web/stats', $username);
981                 $app->system->chgrp($data['new']['document_root'].'/web/stats', $groupname);
982                 $app->system->chown($data['new']['document_root'].'/webdav', $username);
983                 $app->system->chgrp($data['new']['document_root'].'/webdav', $groupname);
984                 $app->system->chown($data['new']['document_root'].'/private', $username);
985                 $app->system->chgrp($data['new']['document_root'].'/private', $groupname);
ac933e 986
edf806 987                 // If the security Level is set to medium
T 988             } else {
989
b1a6a5 990                 $app->system->chmod($data['new']['document_root'], 0755);
MC 991                 $app->system->chmod($data['new']['document_root'].'/web', 0755);
992                 $app->system->chmod($data['new']['document_root'].'/webdav', 0755);
993                 $app->system->chmod($data['new']['document_root'].'/ssl', 0755);
994                 $app->system->chmod($data['new']['document_root'].'/cgi-bin', 0755);
995
edf806 996                 // make temp directory writable for Apache and the website users
5aedfd 997                 $app->system->chmod($data['new']['document_root'].'/tmp', 0770);
b1a6a5 998
6fb93d 999                 // Set Log directory to 755 to make the logs accessible by the FTP user
418b41 1000                 if(realpath($data['new']['document_root'].'/'.$log_folder . '/error.log') == '/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log') {
b1a6a5 1001                     $app->system->chmod($data['new']['document_root'].'/'.$log_folder, 0755);
6fb93d 1002                 }
b1a6a5 1003
MC 1004                 $app->system->chown($data['new']['document_root'], 'root');
1005                 $app->system->chgrp($data['new']['document_root'], 'root');
1006                 $app->system->chown($data['new']['document_root'].'/cgi-bin', $username);
1007                 $app->system->chgrp($data['new']['document_root'].'/cgi-bin', $groupname);
418b41 1008                 if(realpath($data['new']['document_root'].'/'.$log_folder . '/error.log') == '/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log') {
b1a6a5 1009                     $app->system->chown($data['new']['document_root'].'/'.$log_folder, 'root', false);
MC 1010                     $app->system->chgrp($data['new']['document_root'].'/'.$log_folder, $groupname, false);
c77103 1011                 }
b1a6a5 1012
MC 1013                 $app->system->chown($data['new']['document_root'].'/ssl', 'root');
1014                 $app->system->chgrp($data['new']['document_root'].'/ssl', 'root');
1015                 $app->system->chown($data['new']['document_root'].'/tmp', $username);
1016                 $app->system->chgrp($data['new']['document_root'].'/tmp', $groupname);
1017                 $app->system->chown($data['new']['document_root'].'/web', $username);
1018                 $app->system->chgrp($data['new']['document_root'].'/web', $groupname);
1019                 $app->system->chown($data['new']['document_root'].'/web/error', $username);
1020                 $app->system->chgrp($data['new']['document_root'].'/web/error', $groupname);
1021                 $app->system->chown($data['new']['document_root'].'/web/stats', $username);
1022                 $app->system->chgrp($data['new']['document_root'].'/web/stats', $groupname);
1023                 $app->system->chown($data['new']['document_root'].'/webdav', $username);
1024                 $app->system->chgrp($data['new']['document_root'].'/webdav', $groupname);
8db8f3 1025             }
511ba5 1026         } elseif((($data['new']['type'] == 'vhostsubdomain') || ($data['new']['type'] == 'vhostalias')) &&
DM 1027                  (($this->action == 'insert') || ($web_config['set_folder_permissions_on_update'] == 'y'))) {
1028
6fb93d 1029             if($web_config['security_level'] == 20) {
b1a6a5 1030                 $app->system->chmod($data['new']['document_root'].'/' . $web_folder, 0710);
MC 1031                 $app->system->chown($data['new']['document_root'].'/' . $web_folder, $username);
1032                 $app->system->chgrp($data['new']['document_root'].'/' . $web_folder, $groupname);
1033                 $app->system->chown($data['new']['document_root'].'/' . $web_folder . '/error', $username);
1034                 $app->system->chgrp($data['new']['document_root'].'/' . $web_folder . '/error', $groupname);
1035                 $app->system->chown($data['new']['document_root'].'/' . $web_folder . '/stats', $username);
1036                 $app->system->chgrp($data['new']['document_root'].'/' . $web_folder . '/stats', $groupname);
1037             } else {
1038                 $app->system->chmod($data['new']['document_root'].'/' . $web_folder, 0755);
1039                 $app->system->chown($data['new']['document_root'].'/' . $web_folder, $username);
1040                 $app->system->chgrp($data['new']['document_root'].'/' . $web_folder, $groupname);
1041                 $app->system->chown($data['new']['document_root'].'/' . $web_folder . '/error', $username);
1042                 $app->system->chgrp($data['new']['document_root'].'/' . $web_folder . '/error', $groupname);
1043                 $app->system->chown($data['new']['document_root'].'/' . $web_folder . '/stats', $username);
1044                 $app->system->chgrp($data['new']['document_root'].'/' . $web_folder . '/stats', $groupname);
1045             }
1046         }
1047
4b9329 1048         //* Protect web folders
b1a6a5 1049         $app->system->web_folder_protection($data['new']['document_root'], true);
ac933e 1050
6fb93d 1051         if($data['new']['type'] == 'vhost') {
b1a6a5 1052             // Change the ownership of the error log to the root user
MC 1053             if(!@is_file('/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log')) exec('touch '.escapeshellcmd('/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log'));
1054             $app->system->chown('/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log', 'root');
1055             $app->system->chgrp('/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log', 'root');
1056         }
ac933e 1057
26c0fc 1058         //* Write the custom php.ini file, if custom_php_ini fieled is not empty
fb3339 1059         $custom_php_ini_dir = $web_config['website_basedir'].'/conf/'.$data['new']['system_user'];
511ba5 1060         if($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') $custom_php_ini_dir .= '_' . $web_folder;
c77103 1061         if(!is_dir($web_config['website_basedir'].'/conf')) $app->system->mkdir($web_config['website_basedir'].'/conf');
b1a6a5 1062
26c0fc 1063         //* add open_basedir restriction to custom php.ini content, required for suphp only
b1a6a5 1064         if(!stristr($data['new']['custom_php_ini'], 'open_basedir') && $data['new']['php'] == 'suphp') {
26c0fc 1065             $data['new']['custom_php_ini'] .= "\nopen_basedir = '".$data['new']['php_open_basedir']."'\n";
T 1066         }
b1a6a5 1067
cc6568 1068         $fastcgi_config = $app->getconf->get_server_config($conf['server_id'], 'fastcgi');
b1a6a5 1069
cc6568 1070         if(trim($data['new']['fastcgi_php_version']) != ''){
H 1071             list($custom_fastcgi_php_name, $custom_fastcgi_php_executable, $custom_fastcgi_php_ini_dir) = explode(':', trim($data['new']['fastcgi_php_version']));
1072             if(is_file($custom_fastcgi_php_ini_dir)) $custom_fastcgi_php_ini_dir = dirname($custom_fastcgi_php_ini_dir);
b1a6a5 1073             if(substr($custom_fastcgi_php_ini_dir, -1) == '/') $custom_fastcgi_php_ini_dir = substr($custom_fastcgi_php_ini_dir, 0, -1);
cc6568 1074         }
H 1075
26c0fc 1076         //* Create custom php.ini
fb3339 1077         if(trim($data['new']['custom_php_ini']) != '') {
7fddfe 1078             $has_custom_php_ini = true;
3f478f 1079             if(!is_dir($custom_php_ini_dir)) $app->system->mkdirpath($custom_php_ini_dir);
93292a 1080             
MB 1081             $php_ini_content = $this->get_master_php_ini_content($data['new']);
b1a6a5 1082             $php_ini_content .= str_replace("\r", '', trim($data['new']['custom_php_ini']));
b41803 1083             
MC 1084             if(intval($data['new']['directive_snippets_id']) > 0){
d22277 1085                 $snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'apache' AND active = 'y' AND customer_viewable = 'y'", intval($data['new']['directive_snippets_id']));
b41803 1086                 if(isset($snippet['required_php_snippets']) && trim($snippet['required_php_snippets']) != ''){
MC 1087                     $required_php_snippets = explode(',', trim($snippet['required_php_snippets']));
1088                     if(is_array($required_php_snippets) && !empty($required_php_snippets)){
1089                         foreach($required_php_snippets as $required_php_snippet){
1090                             $required_php_snippet = intval($required_php_snippet);
1091                             if($required_php_snippet > 0){
1092                                 $php_snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'php' AND active = 'y'", $required_php_snippet);
1093                                 $php_snippet['snippet'] = trim($php_snippet['snippet']);
1094                                 if($php_snippet['snippet'] != ''){
1095                                     $php_ini_content .= "\n".$php_snippet['snippet'];
1096                                 }
1097                             }
1098                         }
34c940 1099
MB 1100                         foreach($sub_prefixes as $s) {
1101                             $temp_domains[] = $s . $aliasdomain['domain'];
1102                         }
b41803 1103                     }
MC 1104                 }
1105             }
1106         
b1a6a5 1107             $app->system->file_put_contents($custom_php_ini_dir.'/php.ini', $php_ini_content);
7fddfe 1108         } else {
T 1109             $has_custom_php_ini = false;
c77103 1110             if(is_file($custom_php_ini_dir.'/php.ini')) $app->system->unlink($custom_php_ini_dir.'/php.ini');
7fddfe 1111         }
T 1112
1113
1114         //* Create the vhost config file
46c683 1115         $app->load('tpl');
ac933e 1116
46c683 1117         $tpl = new tpl();
fb3339 1118         $tpl->newTemplate('vhost.conf.master');
ac933e 1119
fb3339 1120         $vhost_data = $data['new'];
a7bdf8 1121         //unset($vhost_data['ip_address']);
6fb93d 1122         $vhost_data['web_document_root'] = $data['new']['document_root'].'/' . $web_folder;
M 1123         $vhost_data['web_document_root_www'] = $web_config['website_basedir'].'/'.$data['new']['domain'].'/' . $web_folder;
fb3339 1124         $vhost_data['web_basedir'] = $web_config['website_basedir'];
J 1125         $vhost_data['security_level'] = $web_config['security_level'];
1126         $vhost_data['allow_override'] = ($data['new']['allow_override'] == '')?'All':$data['new']['allow_override'];
1127         $vhost_data['php_open_basedir'] = ($data['new']['php_open_basedir'] == '')?$data['new']['document_root']:$data['new']['php_open_basedir'];
1128         $vhost_data['ssl_domain'] = $data['new']['ssl_domain'];
1129         $vhost_data['has_custom_php_ini'] = $has_custom_php_ini;
1130         $vhost_data['custom_php_ini_dir'] = escapeshellcmd($custom_php_ini_dir);
b1a6a5 1131
02bf99 1132         // Custom Apache directives
1fa8f4 1133         if(intval($data['new']['directive_snippets_id']) > 0){
2af58c 1134             $snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'apache' AND active = 'y' AND customer_viewable = 'y'", $data['new']['directive_snippets_id']);
1fa8f4 1135             if(isset($snippet['snippet'])){
FT 1136                 $vhost_data['apache_directives'] = $snippet['snippet'];
1137             }
1138         }
02bf99 1139         // Make sure we only have Unix linebreaks
T 1140         $vhost_data['apache_directives'] = str_replace("\r\n", "\n", $vhost_data['apache_directives']);
1141         $vhost_data['apache_directives'] = str_replace("\r", "\n", $vhost_data['apache_directives']);
6b15d5 1142         $trans = array(
MB 1143             '{DOCROOT}' => $vhost_data['web_document_root_www'],
1144             '{DOCROOT_CLIENT}' => $vhost_data['web_document_root']
1145         );
018955 1146         $vhost_data['apache_directives'] = strtr($vhost_data['apache_directives'], $trans);
ac933e 1147
46c683 1148         // Check if a SSL cert exists
fb3339 1149         $ssl_dir = $data['new']['document_root'].'/ssl';
J 1150         $domain = $data['new']['ssl_domain'];
394f3e 1151         if(!$domain) $domain = $data['new']['domain'];
fb3339 1152         $key_file = $ssl_dir.'/'.$domain.'.key';
J 1153         $crt_file = $ssl_dir.'/'.$domain.'.crt';
1154         $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
ac933e 1155
a7bdf8 1156         /*
1a2310 1157         if($domain!='' && $data['new']['ssl'] == 'y' && @is_file($crt_file) && @is_file($key_file) && (@filesize($crt_file)>0)  && (@filesize($key_file)>0)) {
fb3339 1158             $vhost_data['ssl_enabled'] = 1;
J 1159             $app->log('Enable SSL for: '.$domain,LOGLEVEL_DEBUG);
46c683 1160         } else {
fb3339 1161             $vhost_data['ssl_enabled'] = 0;
1a2310 1162             $app->log('SSL Disabled. '.$domain,LOGLEVEL_DEBUG);
46c683 1163         }
a7bdf8 1164         */
ac933e 1165
50306f 1166         if($data['new']['ssl'] == 'y' && $data['new']['ssl_letsencrypt'] == 'y') {
46230b 1167             if(substr($domain, 0, 2) === '*.') {
MC 1168                 // wildcard domain not yet supported by letsencrypt!
1169                 $app->log('Wildcard domains not yet supported by letsencrypt, so changing ' . $domain . ' to ' . substr($domain, 2), LOGLEVEL_WARN);
1170                 $domain = substr($domain, 2);
1171             }
1172             
018c55 1173             $data['new']['ssl_domain'] = $domain;
MC 1174             $vhost_data['ssl_domain'] = $domain;
50306f 1175         }
018c55 1176
50306f 1177         //* Generate Let's Encrypt SSL certificat
MB 1178         if($data['new']['ssl'] == 'y' && $data['new']['ssl_letsencrypt'] == 'y' && ( // ssl and let's encrypt is active
1179             ($data['old']['ssl'] == 'n' || $data['old']['ssl_letsencrypt'] == 'n') // we have new let's encrypt configuration
1180             || ($data['old']['domain'] != $data['new']['domain']) // we have domain update
1181             || ($data['old']['subdomain'] != $data['new']['subdomain']) // we have new or update on "auto" subdomain
496602 1182             || $this->update_letsencrypt == true
50306f 1183         )) {
a20ec4 1184             // default values
MB 1185             $temp_domains = array();
1186             $lddomain = $domain;
1187             $subdomains = null;
1ba089 1188             $aliasdomains = null;
34c940 1189             $sub_prefixes = array();
a20ec4 1190
018c55 1191             //* be sure to have good domain
MC 1192             if($data['new']['subdomain'] == "www" OR $data['new']['subdomain'] == "*") {
a20ec4 1193                 $temp_domains[] = "www." . $domain;
018c55 1194             }
MC 1195
a20ec4 1196             //* then, add subdomain if we have
MB 1197             $subdomains = $app->db->queryAllRecords('SELECT domain FROM web_domain WHERE parent_domain_id = '.intval($data['new']['domain_id'])." AND active = 'y' AND type = 'subdomain'");
1198             if(is_array($subdomains)) {
1199                 foreach($subdomains as $subdomain) {
1200                     $temp_domains[] = $subdomain['domain'];
34c940 1201                     $sub_prefixes[] = str_replace($domain, "", $subdomain['domain']);
a20ec4 1202                 }
MB 1203             }
1ba089 1204             
MB 1205             //* then, add alias domain if we have
1206             $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'");
1207             if(is_array($aliasdomains)) {
1208                 foreach($aliasdomains as $aliasdomain) {
1209                     $temp_domains[] = $aliasdomain['domain'];
8c93e1 1210                     if(isset($aliasdomain['subdomain']) && ($aliasdomain['subdomain'] != "none")) {
M 1211                         $temp_domains[] = "www." . $aliasdomain['domain'];
1ba089 1212                     }
MB 1213                 }
1214             }
018c55 1215
a20ec4 1216             // prevent duplicate
MB 1217             $temp_domains = array_unique($temp_domains);
018c55 1218
a20ec4 1219             // generate cli format
MB 1220             foreach($temp_domains as $temp_domain) {
1221                 $lddomain .= (string) " --domains " . $temp_domain;
1222             }
018c55 1223
a20ec4 1224             // useless data
MB 1225             unset($subdomains);
1226             unset($temp_domains);
018c55 1227
a20ec4 1228             $crt_tmp_file = "/etc/letsencrypt/live/".$domain."/cert.pem";
MB 1229             $key_tmp_file = "/etc/letsencrypt/live/".$domain."/privkey.pem";
1230             $bundle_tmp_file = "/etc/letsencrypt/live/".$domain."/chain.pem";
1231             $webroot = $data['new']['document_root']."/web";
018c55 1232
a20ec4 1233             //* check if we have already a Let's Encrypt cert
a49635 1234             //if(!file_exists($crt_tmp_file) && !file_exists($key_tmp_file)) {
MB 1235                 // we must not skip if cert exists, otherwise changed domains (alias or sub) won't make it to the cert
a20ec4 1236                 $app->log("Create Let's Encrypt SSL Cert for: $domain", LOGLEVEL_DEBUG);
551d9a 1237                 
MB 1238                 $success = false;
312ab0 1239                 $letsencrypt = explode("\n", shell_exec('which letsencrypt certbot /root/.local/share/letsencrypt/bin/letsencrypt'));
MB 1240                 $letsencrypt = reset($letsencrypt);
190275 1241                 if(is_executable($letsencrypt)) {
cae251 1242                     $success = $this->_exec($letsencrypt . " certonly -n --text --agree-tos --expand --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");
018c55 1243                 }
551d9a 1244                 if(!$success) {
MB 1245                     // error issuing cert
1246                     $app->log('Let\'s Encrypt SSL Cert for: ' . $domain . ' could not be issued.', LOGLEVEL_WARN);
1247                     $data['new']['ssl_letsencrypt'] = 'n';
1248                     if($data['old']['ssl'] == 'n') $data['new']['ssl'] = 'n';
1249                     /* Update the DB of the (local) Server */
1250                     $app->db->query("UPDATE web_domain SET `ssl` = ?, `ssl_letsencrypt` = ? WHERE `domain` = ?", $data['new']['ssl'], 'n', $data['new']['domain']);
1251                     /* Update also the master-DB of the Server-Farm */
1252                     $app->dbmaster->query("UPDATE web_domain SET `ssl` = ?, `ssl_letsencrypt` = ? WHERE `domain` = ?", $data['new']['ssl'], 'n', $data['new']['domain']);
1253                 }
a49635 1254             //}
018c55 1255
a20ec4 1256             //* check is been correctly created
MB 1257             if(file_exists($crt_tmp_file) OR file_exists($key_tmp_file)) {
1258                 $date = date("YmdHis");
1259                 if(is_file($key_file)) {
1260                     $app->system->copy($key_file, $key_file.'.old'.$date);
1261                     $app->system->chmod($key_file.'.old.'.$date, 0400);
1262                     $app->system->unlink($key_file);
1263                 }
1264
1265                 if ($web_config["website_symlinks_rel"] == 'y') {
1266                     $this->create_relative_link(escapeshellcmd($key_tmp_file), escapeshellcmd($key_file));
1267                 } else {
1268                     exec("ln -s ".escapeshellcmd($key_tmp_file)." ".escapeshellcmd($key_file));
1269                 }
1270
1271                 if(is_file($crt_file)) {
1272                     $app->system->copy($crt_file, $crt_file.'.old.'.$date);
1273                     $app->system->chmod($crt_file.'.old.'.$date, 0400);
1274                     $app->system->unlink($crt_file);
1275                 }
1276
1277                 if($web_config["website_symlinks_rel"] == 'y') {
1278                     $this->create_relative_link(escapeshellcmd($crt_tmp_file), escapeshellcmd($crt_file));
1279                 } else {
1280                     exec("ln -s ".escapeshellcmd($crt_tmp_file)." ".escapeshellcmd($crt_file));
1281                 }
1282
1283                 if(is_file($bundle_file)) {
1284                     $app->system->copy($bundle_file, $bundle_file.'.old.'.$date);
1285                     $app->system->chmod($bundle_file.'.old.'.$date, 0400);
1286                     $app->system->unlink($bundle_file);
1287                 }
1288
1289                 if($web_config["website_symlinks_rel"] == 'y') {
1290                     $this->create_relative_link(escapeshellcmd($bundle_tmp_file), escapeshellcmd($bundle_file));
1291                 } else {
1292                     exec("ln -s ".escapeshellcmd($bundle_tmp_file)." ".escapeshellcmd($bundle_file));
1293                 }
1294
1295                 /* we don't need to store it.
1296                 /* Update the DB of the (local) Server */
551d9a 1297                 $app->db->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '', ssl_key = '' WHERE domain = ?", $data['new']['domain']);
MB 1298                 $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
a20ec4 1299                 /* Update also the master-DB of the Server-Farm */
551d9a 1300                 $app->dbmaster->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '', ssl_key = '' WHERE domain = ?", $data['new']['domain']);
MB 1301                 $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
a20ec4 1302             }
MB 1303         }
1304
46c683 1305         if(@is_file($bundle_file)) $vhost_data['has_bundle_cert'] = 1;
ac933e 1306
6fb93d 1307         //$vhost_data['document_root'] = $data['new']['document_root'].'/' . $web_folder;
b1a6a5 1308
e64fbb 1309         // Set SEO Redirect
bfcdef 1310         if($data['new']['seo_redirect'] != ''){
e64fbb 1311             $vhost_data['seo_redirect_enabled'] = 1;
bfcdef 1312             $tmp_seo_redirects = $this->get_seo_redirects($data['new']);
T 1313             if(is_array($tmp_seo_redirects) && !empty($tmp_seo_redirects)){
1314                 foreach($tmp_seo_redirects as $key => $val){
1315                     $vhost_data[$key] = $val;
1316                 }
1317             } else {
1318                 $vhost_data['seo_redirect_enabled'] = 0;
e64fbb 1319             }
F 1320         } else {
1321             $vhost_data['seo_redirect_enabled'] = 0;
1322         }
b1a6a5 1323
46c683 1324         $tpl->setVar($vhost_data);
8133de 1325         $tpl->setVar('apache_version', $app->system->getapacheversion());
ac933e 1326
46c683 1327         // Rewrite rules
T 1328         $rewrite_rules = array();
a639ee 1329         $rewrite_wildcard_rules = array();
02bf99 1330         if($data['new']['redirect_type'] != '' && $data['new']['redirect_path'] != '') {
b1a6a5 1331             if(substr($data['new']['redirect_path'], -1) != '/' && !preg_match('/^(https?|\[scheme\]):\/\//', $data['new']['redirect_path'])) $data['new']['redirect_path'] .= '/';
MC 1332             if(substr($data['new']['redirect_path'], 0, 8) == '[scheme]'){
1333                 $rewrite_target = 'http'.substr($data['new']['redirect_path'], 8);
1334                 $rewrite_target_ssl = 'https'.substr($data['new']['redirect_path'], 8);
45ee67 1335             } else {
F 1336                 $rewrite_target = $data['new']['redirect_path'];
1337                 $rewrite_target_ssl = $data['new']['redirect_path'];
1338             }
bc2c3e 1339             /* Disabled path extension
fb3339 1340             if($data['new']['redirect_type'] == 'no' && substr($data['new']['redirect_path'],0,4) != 'http') {
J 1341                 $data['new']['redirect_path'] = $data['new']['document_root'].'/web'.realpath($data['new']['redirect_path']).'/';
8388ae 1342             }
bc2c3e 1343             */
ac933e 1344
fb3339 1345             switch($data['new']['subdomain']) {
b1a6a5 1346             case 'www':
MC 1347                 $rewrite_rules[] = array( 'rewrite_domain'  => '^'.$this->_rewrite_quote($data['new']['domain']),
1348                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
1349                     'rewrite_target'  => $rewrite_target,
1350                     'rewrite_target_ssl' => $rewrite_target_ssl,
1351                     'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1352                     'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1353                 $rewrite_rules[] = array( 'rewrite_domain'  => '^' . $this->_rewrite_quote('www.'.$data['new']['domain']),
1354                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
1355                     'rewrite_target'  => $rewrite_target,
1356                     'rewrite_target_ssl' => $rewrite_target_ssl,
1357                     'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1358                     'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1359                 break;
1360             case '*':
a639ee 1361                 $rewrite_wildcard_rules[] = array( 'rewrite_domain'  => '(^|\.)'.$this->_rewrite_quote($data['new']['domain']),
b1a6a5 1362                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
MC 1363                     'rewrite_target'  => $rewrite_target,
1364                     'rewrite_target_ssl' => $rewrite_target_ssl,
1365                     'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1366                     'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1367                 break;
1368             default:
1369                 $rewrite_rules[] = array( 'rewrite_domain'  => '^'.$this->_rewrite_quote($data['new']['domain']),
1370                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
1371                     'rewrite_target'  => $rewrite_target,
1372                     'rewrite_target_ssl' => $rewrite_target_ssl,
1373                     'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1374                     'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
ac933e 1375             }
46c683 1376         }
b1a6a5 1377
3501f9 1378         $server_alias = array();
b1a6a5 1379
3501f9 1380         // get autoalias
M 1381         $auto_alias = $web_config['website_autoalias'];
1382         if($auto_alias != '') {
1383             // get the client username
2af58c 1384             $client = $app->db->queryOneRecord("SELECT `username` FROM `client` WHERE `client_id` = ?", $client_id);
3501f9 1385             $aa_search = array('[client_id]', '[website_id]', '[client_username]', '[website_domain]');
M 1386             $aa_replace = array($client_id, $data['new']['domain_id'], $client['username'], $data['new']['domain']);
1387             $auto_alias = str_replace($aa_search, $aa_replace, $auto_alias);
1388             unset($client);
1389             unset($aa_search);
1390             unset($aa_replace);
cece69 1391             $server_alias[] .= $auto_alias.' ';
3501f9 1392         }
b1a6a5 1393
46c683 1394         // get alias domains (co-domains and subdomains)
2af58c 1395         $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']);
bfcdef 1396         $alias_seo_redirects = array();
fb3339 1397         switch($data['new']['subdomain']) {
b1a6a5 1398         case 'www':
MC 1399             $server_alias[] .= 'www.'.$data['new']['domain'].' ';
1400             break;
1401         case '*':
1402             $server_alias[] .= '*.'.$data['new']['domain'].' ';
1403             break;
ac933e 1404         }
46c683 1405         if(is_array($aliases)) {
T 1406             foreach($aliases as $alias) {
fb3339 1407                 switch($alias['subdomain']) {
b1a6a5 1408                 case 'www':
MC 1409                     $server_alias[] .= 'www.'.$alias['domain'].' '.$alias['domain'].' ';
1410                     break;
1411                 case '*':
1412                     $server_alias[] .= '*.'.$alias['domain'].' '.$alias['domain'].' ';
1413                     break;
1414                 default:
1415                     $server_alias[] .= $alias['domain'].' ';
1416                     break;
ac933e 1417                 }
b1a6a5 1418                 $app->log('Add server alias: '.$alias['domain'], LOGLEVEL_DEBUG);
MC 1419
bfcdef 1420                 // Add SEO redirects for alias domains
T 1421                 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'))){
1422                     $tmp_seo_redirects = $this->get_seo_redirects($alias, 'alias_');
1423                     if(is_array($tmp_seo_redirects) && !empty($tmp_seo_redirects)){
1424                         $alias_seo_redirects[] = $tmp_seo_redirects;
1425                     }
1426                 }
b1a6a5 1427
46c683 1428                 // Rewriting
02bf99 1429                 if($alias['redirect_type'] != '' && $alias['redirect_path'] != '') {
b1a6a5 1430                     if(substr($alias['redirect_path'], -1) != '/' && !preg_match('/^(https?|\[scheme\]):\/\//', $alias['redirect_path'])) $alias['redirect_path'] .= '/';
MC 1431                     if(substr($alias['redirect_path'], 0, 8) == '[scheme]'){
1432                         $rewrite_target = 'http'.substr($alias['redirect_path'], 8);
1433                         $rewrite_target_ssl = 'https'.substr($alias['redirect_path'], 8);
e64fbb 1434                     } else {
F 1435                         $rewrite_target = $alias['redirect_path'];
1436                         $rewrite_target_ssl = $alias['redirect_path'];
1437                     }
bc2c3e 1438                     /* Disabled the path extension
fb3339 1439                     if($data['new']['redirect_type'] == 'no' && substr($data['new']['redirect_path'],0,4) != 'http') {
J 1440                         $data['new']['redirect_path'] = $data['new']['document_root'].'/web'.realpath($data['new']['redirect_path']).'/';
8388ae 1441                     }
bc2c3e 1442                     */
b1a6a5 1443
fb3339 1444                     switch($alias['subdomain']) {
b1a6a5 1445                     case 'www':
MC 1446                         $rewrite_rules[] = array( 'rewrite_domain'  => '^'.$this->_rewrite_quote($alias['domain']),
1447                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
1448                             'rewrite_target'  => $rewrite_target,
1449                             'rewrite_target_ssl' => $rewrite_target_ssl,
1450                             'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1451                             'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1452                         $rewrite_rules[] = array( 'rewrite_domain'  => '^' . $this->_rewrite_quote('www.'.$alias['domain']),
1453                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
1454                             'rewrite_target'  => $rewrite_target,
1455                             'rewrite_target_ssl' => $rewrite_target_ssl,
1456                             'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1457                             'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1458                         break;
1459                     case '*':
a639ee 1460                         $rewrite_wildcard_rules[] = array( 'rewrite_domain'  => '(^|\.)'.$this->_rewrite_quote($alias['domain']),
b1a6a5 1461                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
MC 1462                             'rewrite_target'  => $rewrite_target,
1463                             'rewrite_target_ssl' => $rewrite_target_ssl,
1464                             'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1465                             'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1466                         break;
1467                     default:
1468                         if(substr($alias['domain'], 0, 2) === '*.') $domain_rule = '(^|\.)'.$this->_rewrite_quote(substr($alias['domain'], 2));
1469                         else $domain_rule = '^'.$this->_rewrite_quote($alias['domain']);
1470                         $rewrite_rules[] = array( 'rewrite_domain'  => $domain_rule,
1471                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
1472                             'rewrite_target'  => $rewrite_target,
1473                             'rewrite_target_ssl' => $rewrite_target_ssl,
1474                             'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1475                             'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
ac933e 1476                     }
46c683 1477                 }
T 1478             }
1479         }
ac933e 1480
47cca9 1481         //* If we have some alias records
T 1482         if(count($server_alias) > 0) {
1483             $server_alias_str = '';
1484             $n = 0;
ac933e 1485
47cca9 1486             // begin a new ServerAlias line after 30 alias domains
T 1487             foreach($server_alias as $tmp_alias) {
1488                 if($n % 30 == 0) $server_alias_str .= "\n    ServerAlias ";
1489                 $server_alias_str .= $tmp_alias;
1490             }
1491             unset($tmp_alias);
ac933e 1492
b1a6a5 1493             $tpl->setVar('alias', trim($server_alias_str));
47cca9 1494         } else {
b1a6a5 1495             $tpl->setVar('alias', '');
47cca9 1496         }
a639ee 1497         
D 1498         if (count($rewrite_wildcard_rules) > 0) $rewrite_rules = array_merge($rewrite_rules, $rewrite_wildcard_rules); // Append wildcard rules to the end of rules
ac933e 1499
3ad844 1500         if(count($rewrite_rules) > 0 || $vhost_data['seo_redirect_enabled'] > 0 || count($alias_seo_redirects) > 0 || $data['new']['rewrite_to_https'] == 'y') {
b1a6a5 1501             $tpl->setVar('rewrite_enabled', 1);
46c683 1502         } else {
b1a6a5 1503             $tpl->setVar('rewrite_enabled', 0);
bfcdef 1504         }
8ab3cd 1505
T 1506         //$tpl->setLoop('redirects',$rewrite_rules);
ac933e 1507
V 1508         /**
1509          * install fast-cgi starter script and add script aliasd config
46c683 1510          * first we create the script directory if not already created, then copy over the starter script
T 1511          * settings are copied over from the server ini config for now
1512          * TODO: Create form for fastcgi configs per site.
1513          */
ac933e 1514
b1a6a5 1515
fb3339 1516         if ($data['new']['php'] == 'fast-cgi') {
ac933e 1517
b1a6a5 1518             $fastcgi_starter_path = str_replace('[system_user]', $data['new']['system_user'], $fastcgi_config['fastcgi_starter_path']);
MC 1519             $fastcgi_starter_path = str_replace('[client_id]', $client_id, $fastcgi_starter_path);
ac933e 1520
V 1521             if (!is_dir($fastcgi_starter_path)) {
c77103 1522                 $app->system->mkdirpath($fastcgi_starter_path);
fb3339 1523                 //exec('chown '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.escapeshellcmd($fastcgi_starter_path));
ac933e 1524
V 1525
b1a6a5 1526                 $app->log('Creating fastcgi starter script directory: '.$fastcgi_starter_path, LOGLEVEL_DEBUG);
46c683 1527             }
ac933e 1528
c77103 1529             //exec('chown -R '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.escapeshellcmd($fastcgi_starter_path));
b1a6a5 1530             $app->system->chown($fastcgi_starter_path, $data['new']['system_user']);
MC 1531             $app->system->chgrp($fastcgi_starter_path, $data['new']['system_group']);
1532
46c683 1533             $fcgi_tpl = new tpl();
fb3339 1534             $fcgi_tpl->newTemplate('php-fcgi-starter.master');
8133de 1535             $fcgi_tpl->setVar('apache_version', $app->system->getapacheversion());
b1a6a5 1536
62b385 1537             // Support for multiple PHP versions (FastCGI)
F 1538             if(trim($data['new']['fastcgi_php_version']) != ''){
1539                 $default_fastcgi_php = false;
b1a6a5 1540                 if(substr($custom_fastcgi_php_ini_dir, -1) != '/') $custom_fastcgi_php_ini_dir .= '/';
62b385 1541             } else {
F 1542                 $default_fastcgi_php = true;
1543             }
b1a6a5 1544
7fddfe 1545             if($has_custom_php_ini) {
b1a6a5 1546                 $fcgi_tpl->setVar('php_ini_path', escapeshellcmd($custom_php_ini_dir));
7fddfe 1547             } else {
62b385 1548                 if($default_fastcgi_php){
b1a6a5 1549                     $fcgi_tpl->setVar('php_ini_path', escapeshellcmd($fastcgi_config['fastcgi_phpini_path']));
62b385 1550                 } else {
b1a6a5 1551                     $fcgi_tpl->setVar('php_ini_path', escapeshellcmd($custom_fastcgi_php_ini_dir));
62b385 1552                 }
7fddfe 1553             }
b1a6a5 1554             $fcgi_tpl->setVar('document_root', escapeshellcmd($data['new']['document_root']));
MC 1555             $fcgi_tpl->setVar('php_fcgi_children', escapeshellcmd($fastcgi_config['fastcgi_children']));
1556             $fcgi_tpl->setVar('php_fcgi_max_requests', escapeshellcmd($fastcgi_config['fastcgi_max_requests']));
62b385 1557             if($default_fastcgi_php){
b1a6a5 1558                 $fcgi_tpl->setVar('php_fcgi_bin', escapeshellcmd($fastcgi_config['fastcgi_bin']));
62b385 1559             } else {
b1a6a5 1560                 $fcgi_tpl->setVar('php_fcgi_bin', escapeshellcmd($custom_fastcgi_php_executable));
62b385 1561             }
b1a6a5 1562             $fcgi_tpl->setVar('security_level', intval($web_config['security_level']));
f63910 1563             $fcgi_tpl->setVar('domain', escapeshellcmd($data['new']['domain']));
ac933e 1564
fb3339 1565             $php_open_basedir = ($data['new']['php_open_basedir'] == '')?$data['new']['document_root']:$data['new']['php_open_basedir'];
ff7075 1566             $fcgi_tpl->setVar('open_basedir', escapeshellcmd($php_open_basedir));
ac933e 1567
511ba5 1568             $fcgi_starter_script = escapeshellcmd($fastcgi_starter_path.$fastcgi_config['fastcgi_starter_script'].(($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') ? '_web' . $data['new']['domain_id'] : ''));
b1a6a5 1569             $app->system->file_put_contents($fcgi_starter_script, $fcgi_tpl->grab());
46c683 1570             unset($fcgi_tpl);
ac933e 1571
b1a6a5 1572             $app->log('Creating fastcgi starter script: '.$fcgi_starter_script, LOGLEVEL_DEBUG);
ac933e 1573
b1a6a5 1574             $app->system->chmod($fcgi_starter_script, 0755);
MC 1575             $app->system->chown($fcgi_starter_script, $data['new']['system_user']);
1576             $app->system->chgrp($fcgi_starter_script, $data['new']['system_group']);
1577
1578             $tpl->setVar('fastcgi_alias', $fastcgi_config['fastcgi_alias']);
1579             $tpl->setVar('fastcgi_starter_path', $fastcgi_starter_path);
511ba5 1580             $tpl->setVar('fastcgi_starter_script', $fastcgi_config['fastcgi_starter_script'].(($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') ? '_web' . $data['new']['domain_id'] : ''));
b1a6a5 1581             $tpl->setVar('fastcgi_config_syntax', $fastcgi_config['fastcgi_config_syntax']);
MC 1582             $tpl->setVar('fastcgi_max_requests', $fastcgi_config['fastcgi_max_requests']);
ac933e 1583
62e4b3 1584         } else {
F 1585             //remove the php fastgi starter script if available
b5b862 1586             $fastcgi_starter_script = $fastcgi_config['fastcgi_starter_script'].($data['old']['type'] == 'vhostsubdomain' ? '_web' . $data['old']['domain_id'] : '');
62e4b3 1587             if ($data['old']['php'] == 'fast-cgi') {
b1a6a5 1588                 $fastcgi_starter_path = str_replace('[system_user]', $data['old']['system_user'], $fastcgi_config['fastcgi_starter_path']);
MC 1589                 $fastcgi_starter_path = str_replace('[client_id]', $client_id, $fastcgi_starter_path);
1590                 if($data['old']['type'] == 'vhost') {
b5b862 1591                     if(is_file($fastcgi_starter_script)) @unlink($fastcgi_starter_script);
TB 1592                     if (is_dir($fastcgi_starter_path)) @rmdir($fastcgi_starter_path);
b1a6a5 1593                 } else {
b5b862 1594                     if(is_file($fastcgi_starter_script)) @unlink($fastcgi_starter_script);
b1a6a5 1595                 }
62e4b3 1596             }
46c683 1597         }
b1a6a5 1598
MC 1599
1600
274362 1601         /**
b1a6a5 1602          * PHP-FPM
MC 1603          */
274362 1604         // Support for multiple PHP versions
02e7ea 1605         if($data['new']['php'] == 'php-fpm'){
62e4b3 1606             if(trim($data['new']['fastcgi_php_version']) != ''){
F 1607                 $default_php_fpm = false;
1608                 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']));
b1a6a5 1609                 if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
62e4b3 1610             } else {
F 1611                 $default_php_fpm = true;
1612             }
274362 1613         } else {
c59632 1614             if(trim($data['old']['fastcgi_php_version']) != '' && ($data['old']['php'] == 'php-fpm' || $data['old']['php'] == 'hhvm')){
62e4b3 1615                 $default_php_fpm = false;
F 1616                 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']));
b1a6a5 1617                 if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
62e4b3 1618             } else {
F 1619                 $default_php_fpm = true;
1620             }
274362 1621         }
b1a6a5 1622
274362 1623         if($default_php_fpm){
F 1624             $pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
1625         } else {
1626             $pool_dir = $custom_php_fpm_pool_dir;
1627         }
ab79c2 1628         $pool_dir = trim($pool_dir);
b1a6a5 1629         if(substr($pool_dir, -1) != '/') $pool_dir .= '/';
274362 1630         $pool_name = 'web'.$data['new']['domain_id'];
F 1631         $socket_dir = escapeshellcmd($web_config['php_fpm_socket_dir']);
b1a6a5 1632         if(substr($socket_dir, -1) != '/') $socket_dir .= '/';
9b021b 1633         
1e67c1 1634         $apache_modules = $app->system->getapachemodules();
TB 1635         
1636         // Use sockets, but not with apache 2.4 on centos (mod_proxy_fcgi) as socket support is buggy in that version
1637         if($data['new']['php_fpm_use_socket'] == 'y' && in_array('fastcgi_module',$apache_modules)){
274362 1638             $use_tcp = 0;
F 1639             $use_socket = 1;
1640         } else {
1641             $use_tcp = 1;
1642             $use_socket = 0;
1643         }
1644         $tpl->setVar('use_tcp', $use_tcp);
1645         $tpl->setVar('use_socket', $use_socket);
1646         $fpm_socket = $socket_dir.$pool_name.'.sock';
1647         $tpl->setVar('fpm_socket', $fpm_socket);
1648         $tpl->setVar('fpm_port', $web_config['php_fpm_start_port'] + $data['new']['domain_id'] - 1);
ac933e 1649
46c683 1650         /**
T 1651          * install cgi starter script and add script alias to config.
1652          * This is needed to allow cgi with suexec (to do so, we need a bin in the document-path!)
1653          * first we create the script directory if not already created, then copy over the starter script.
1654          * TODO: we have to fetch the data from the server-settings.
1655          */
fb3339 1656         if ($data['new']['php'] == 'cgi') {
J 1657             //$cgi_config = $app->getconf->get_server_config($conf['server_id'], 'cgi');
46c683 1658
fb3339 1659             $cgi_config['cgi_starter_path'] = $web_config['website_basedir'].'/php-cgi-scripts/[system_user]/';
511ba5 1660             $cgi_config['cgi_starter_script'] = 'php-cgi-starter'.(($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') ? '_web' . $data['new']['domain_id'] : '');
fb3339 1661             $cgi_config['cgi_bin'] = '/usr/bin/php-cgi';
46c683 1662
b1a6a5 1663             $cgi_starter_path = str_replace('[system_user]', $data['new']['system_user'], $cgi_config['cgi_starter_path']);
MC 1664             $cgi_starter_path = str_replace('[client_id]', $client_id, $cgi_starter_path);
46c683 1665
ac933e 1666             if (!is_dir($cgi_starter_path)) {
c77103 1667                 $app->system->mkdirpath($cgi_starter_path);
b1a6a5 1668                 $app->system->chown($cgi_starter_path, $data['new']['system_user']);
MC 1669                 $app->system->chgrp($cgi_starter_path, $data['new']['system_group']);
1670                 $app->system->chmod($cgi_starter_path, 0755);
46c683 1671
b1a6a5 1672                 $app->log('Creating cgi starter script directory: '.$cgi_starter_path, LOGLEVEL_DEBUG);
46c683 1673             }
T 1674
1675             $cgi_tpl = new tpl();
fb3339 1676             $cgi_tpl->newTemplate('php-cgi-starter.master');
8133de 1677             $cgi_tpl->setVar('apache_version', $app->system->getapacheversion());
46c683 1678
fb3339 1679             // This works because PHP "rewrites" a symlink to the physical path
J 1680             $php_open_basedir = ($data['new']['php_open_basedir'] == '')?$data['new']['document_root']:$data['new']['php_open_basedir'];
ac933e 1681             $cgi_tpl->setVar('open_basedir', escapeshellcmd($php_open_basedir));
fb3339 1682             $cgi_tpl->setVar('document_root', escapeshellcmd($data['new']['document_root']));
ac933e 1683
46c683 1684             // This will NOT work!
fb3339 1685             //$cgi_tpl->setVar('open_basedir', '/var/www/' . $data['new']['domain']);
b1a6a5 1686             $cgi_tpl->setVar('php_cgi_bin', $cgi_config['cgi_bin']);
MC 1687             $cgi_tpl->setVar('security_level', $web_config['security_level']);
1688
1689             $cgi_tpl->setVar('has_custom_php_ini', $has_custom_php_ini);
7fddfe 1690             if($has_custom_php_ini) {
b1a6a5 1691                 $cgi_tpl->setVar('php_ini_path', escapeshellcmd($custom_php_ini_dir));
7fddfe 1692             } else {
b1a6a5 1693                 $cgi_tpl->setVar('php_ini_path', escapeshellcmd($fastcgi_config['fastcgi_phpini_path']));
7fddfe 1694             }
46c683 1695
511ba5 1696             $cgi_starter_script = escapeshellcmd($cgi_starter_path.$cgi_config['cgi_starter_script'].(($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') ? '_web' . $data['new']['domain_id'] : ''));
b1a6a5 1697             $app->system->file_put_contents($cgi_starter_script, $cgi_tpl->grab());
46c683 1698             unset($cgi_tpl);
T 1699
b1a6a5 1700             $app->log('Creating cgi starter script: '.$cgi_starter_script, LOGLEVEL_DEBUG);
46c683 1701
T 1702
b1a6a5 1703             $app->system->chmod($cgi_starter_script, 0755);
MC 1704             $app->system->chown($cgi_starter_script, $data['new']['system_user']);
1705             $app->system->chgrp($cgi_starter_script, $data['new']['system_group']);
46c683 1706
b1a6a5 1707             $tpl->setVar('cgi_starter_path', $cgi_starter_path);
511ba5 1708             $tpl->setVar('cgi_starter_script', $cgi_config['cgi_starter_script'].(($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') ? '_web' . $data['new']['domain_id'] : ''));
46c683 1709
T 1710         }
1711
fb3339 1712         $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['new']['domain'].'.vhost');
7ed741 1713         //* Make a backup copy of vhost file
b1a6a5 1714         if(file_exists($vhost_file)) $app->system->copy($vhost_file, $vhost_file.'~');
MC 1715
a7bdf8 1716         //* create empty vhost array
T 1717         $vhosts = array();
b1a6a5 1718
526b99 1719         //* Add vhost for ipv4 IP
6c424f 1720
FS 1721         //* use ip-mapping for web-mirror
1722         if($data['new']['ip_address'] != '*' && $conf['mirror_server_id'] > 0) {
1723             $sql = "SELECT destination_ip FROM server_ip_map WHERE server_id = ? AND source_ip = ?";
1724             $newip = $app->db->queryOneRecord($sql, $conf['server_id'], $data['new']['ip_address']);
1725             $data['new']['ip_address'] = $newip['destination_ip'];
1726             unset($newip);
1727         }
1728
526b99 1729         $tmp_vhost_arr = array('ip_address' => $data['new']['ip_address'], 'ssl_enabled' => 0, 'port' => 80);
T 1730         if(count($rewrite_rules) > 0)  $tmp_vhost_arr = $tmp_vhost_arr + array('redirects' => $rewrite_rules);
1731         if(count($alias_seo_redirects) > 0) $tmp_vhost_arr = $tmp_vhost_arr + array('alias_seo_redirects' => $alias_seo_redirects);
1732         $vhosts[] = $tmp_vhost_arr;
1733         unset($tmp_vhost_arr);
b1a6a5 1734
a7bdf8 1735         //* Add vhost for ipv4 IP with SSL
481c00 1736         $ssl_dir = $data['new']['document_root'].'/ssl';
T 1737         $domain = $data['new']['ssl_domain'];
1738         $key_file = $ssl_dir.'/'.$domain.'.key';
1739         $crt_file = $ssl_dir.'/'.$domain.'.crt';
b1a6a5 1740
a7bdf8 1741         if($data['new']['ssl_domain'] != '' && $data['new']['ssl'] == 'y' && @is_file($crt_file) && @is_file($key_file) && (@filesize($crt_file)>0)  && (@filesize($key_file)>0)) {
526b99 1742             $tmp_vhost_arr = array('ip_address' => $data['new']['ip_address'], 'ssl_enabled' => 1, 'port' => '443');
T 1743             if(count($rewrite_rules) > 0)  $tmp_vhost_arr = $tmp_vhost_arr + array('redirects' => $rewrite_rules);
cc6568 1744             $ipv4_ssl_alias_seo_redirects = $alias_seo_redirects;
H 1745             if(is_array($ipv4_ssl_alias_seo_redirects) && !empty($ipv4_ssl_alias_seo_redirects)){
1746                 for($i=0;$i<count($ipv4_ssl_alias_seo_redirects);$i++){
1747                     $ipv4_ssl_alias_seo_redirects[$i]['ssl_enabled'] = 1;
1748                 }
1749             }
1750             if(count($ipv4_ssl_alias_seo_redirects) > 0) $tmp_vhost_arr = $tmp_vhost_arr + array('alias_seo_redirects' => $ipv4_ssl_alias_seo_redirects);
526b99 1751             $vhosts[] = $tmp_vhost_arr;
cc6568 1752             unset($tmp_vhost_arr, $ipv4_ssl_alias_seo_redirects);
b1a6a5 1753             $app->log('Enable SSL for: '.$domain, LOGLEVEL_DEBUG);
bd68aa 1754         }
MC 1755
b1a6a5 1756         //* Add vhost for IPv6 IP
MC 1757         if($data['new']['ipv6_address'] != '') {
fbeb11 1758             //* rewrite ipv6 on mirrors
FS 1759             /* chang $conf to $web_config */
1760             if ($web_config['serverconfig']['web']['vhost_rewrite_v6'] == 'y') {
1761                 if (isset($web_config['serverconfig']['server']['v6_prefix']) && $web_config['serverconfig']['server']['v6_prefix'] <> '') {
1762                     $explode_v6prefix=explode(':', $web_config['serverconfig']['server']['v6_prefix']);
b1a6a5 1763                     $explode_v6=explode(':', $data['new']['ipv6_address']);
MC 1764
1765                     for ( $i = 0; $i <= count($explode_v6prefix)-3; $i++ ) {
1766                         $explode_v6[$i] = $explode_v6prefix[$i];
1767                     }
1768                     $data['new']['ipv6_address'] = implode(':', $explode_v6);
bd68aa 1769                 }
MC 1770             }
96f31d 1771             if($data['new']['ipv6_address'] == '*') $data['new']['ipv6_address'] = '::';
526b99 1772             $tmp_vhost_arr = array('ip_address' => '['.$data['new']['ipv6_address'].']', 'ssl_enabled' => 0, 'port' => 80);
T 1773             if(count($rewrite_rules) > 0)  $tmp_vhost_arr = $tmp_vhost_arr + array('redirects' => $rewrite_rules);
1774             if(count($alias_seo_redirects) > 0) $tmp_vhost_arr = $tmp_vhost_arr + array('alias_seo_redirects' => $alias_seo_redirects);
1775             $vhosts[] = $tmp_vhost_arr;
1776             unset($tmp_vhost_arr);
b1a6a5 1777
a7bdf8 1778             //* Add vhost for ipv6 IP with SSL
T 1779             if($data['new']['ssl_domain'] != '' && $data['new']['ssl'] == 'y' && @is_file($crt_file) && @is_file($key_file) && (@filesize($crt_file)>0)  && (@filesize($key_file)>0)) {
526b99 1780                 $tmp_vhost_arr = array('ip_address' => '['.$data['new']['ipv6_address'].']', 'ssl_enabled' => 1, 'port' => '443');
T 1781                 if(count($rewrite_rules) > 0)  $tmp_vhost_arr = $tmp_vhost_arr + array('redirects' => $rewrite_rules);
cc6568 1782                 $ipv6_ssl_alias_seo_redirects = $alias_seo_redirects;
H 1783                 if(is_array($ipv6_ssl_alias_seo_redirects) && !empty($ipv6_ssl_alias_seo_redirects)){
1784                     for($i=0;$i<count($ipv6_ssl_alias_seo_redirects);$i++){
1785                         $ipv6_ssl_alias_seo_redirects[$i]['ssl_enabled'] = 1;
1786                     }
1787                 }
1788                 if(count($ipv6_ssl_alias_seo_redirects) > 0) $tmp_vhost_arr = $tmp_vhost_arr + array('alias_seo_redirects' => $ipv6_ssl_alias_seo_redirects);
526b99 1789                 $vhosts[] = $tmp_vhost_arr;
cc6568 1790                 unset($tmp_vhost_arr, $ipv6_ssl_alias_seo_redirects);
b1a6a5 1791                 $app->log('Enable SSL for IPv6: '.$domain, LOGLEVEL_DEBUG);
a7bdf8 1792             }
T 1793         }
b1a6a5 1794
a7bdf8 1795         //* Set the vhost loop
b1a6a5 1796         $tpl->setLoop('vhosts', $vhosts);
MC 1797
7ed741 1798         //* Write vhost file
b1a6a5 1799         $app->system->file_put_contents($vhost_file, $tpl->grab());
MC 1800         $app->log('Writing the vhost file: '.$vhost_file, LOGLEVEL_DEBUG);
46c683 1801         unset($tpl);
ac933e 1802
V 1803         /*
1804          * maybe we have some webdav - user. If so, add them...
1805         */
fb3339 1806         $this->_patchVhostWebdav($vhost_file, $data['new']['document_root'] . '/webdav');
ac933e 1807
c6a89c 1808         //* Set the symlink to enable the vhost
T 1809         //* First we check if there is a old type of symlink and remove it
fb3339 1810         $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['new']['domain'].'.vhost');
c77103 1811         if(is_link($vhost_symlink)) $app->system->unlink($vhost_symlink);
b1a6a5 1812
c6a89c 1813         //* Remove old or changed symlinks
T 1814         if($data['new']['subdomain'] != $data['old']['subdomain'] or $data['new']['active'] == 'n') {
1815             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['new']['domain'].'.vhost');
1816             if(is_link($vhost_symlink)) {
c77103 1817                 $app->system->unlink($vhost_symlink);
b1a6a5 1818                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
c6a89c 1819             }
T 1820             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['new']['domain'].'.vhost');
1821             if(is_link($vhost_symlink)) {
c77103 1822                 $app->system->unlink($vhost_symlink);
b1a6a5 1823                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
c6a89c 1824             }
T 1825         }
b1a6a5 1826
c6a89c 1827         //* New symlink
T 1828         if($data['new']['subdomain'] == '*') {
1829             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['new']['domain'].'.vhost');
1830         } else {
1831             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['new']['domain'].'.vhost');
1832         }
fb3339 1833         if($data['new']['active'] == 'y' && !is_link($vhost_symlink)) {
b1a6a5 1834             symlink($vhost_file, $vhost_symlink);
MC 1835             $app->log('Creating symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
46c683 1836         }
ac933e 1837
46c683 1838         // remove old symlink and vhost file, if domain name of the site has changed
fb3339 1839         if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
c6a89c 1840             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['old']['domain'].'.vhost');
T 1841             if(is_link($vhost_symlink)) {
c77103 1842                 $app->system->unlink($vhost_symlink);
b1a6a5 1843                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
c6a89c 1844             }
T 1845             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['old']['domain'].'.vhost');
1846             if(is_link($vhost_symlink)) {
c77103 1847                 $app->system->unlink($vhost_symlink);
b1a6a5 1848                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
c6a89c 1849             }
8cf78b 1850             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
T 1851             if(is_link($vhost_symlink)) {
c77103 1852                 $app->system->unlink($vhost_symlink);
b1a6a5 1853                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
8cf78b 1854             }
fb3339 1855             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
c77103 1856             $app->system->unlink($vhost_file);
b1a6a5 1857             $app->log('Removing file: '.$vhost_file, LOGLEVEL_DEBUG);
46c683 1858         }
ac933e 1859
46c683 1860         //* Create .htaccess and .htpasswd file for website statistics
cc6568 1861         //if(!is_file($data['new']['document_root'].'/' . $web_folder . '/stats/.htaccess') or $data['old']['document_root'] != $data['new']['document_root']) {
H 1862         if(!is_dir($data['new']['document_root'].'/' . $web_folder . '/stats')) $app->system->mkdir($data['new']['document_root'].'/' . $web_folder . '/stats');
1863         $ht_file = "AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$data['new']['document_root']."/web/stats/.htpasswd_stats\nrequire valid-user";
b1a6a5 1864         $app->system->file_put_contents($data['new']['document_root'].'/' . $web_folder . '/stats/.htaccess', $ht_file);
MC 1865         $app->system->chmod($data['new']['document_root'].'/' . $web_folder . '/stats/.htaccess', 0755);
cc6568 1866         unset($ht_file);
H 1867         //}
ac933e 1868
bfcdef 1869         if(!is_file($data['new']['document_root'].'/web/stats/.htpasswd_stats') || $data['new']['stats_password'] != $data['old']['stats_password']) {
fb3339 1870             if(trim($data['new']['stats_password']) != '') {
J 1871                 $htp_file = 'admin:'.trim($data['new']['stats_password']);
b1a6a5 1872                 $app->system->web_folder_protection($data['new']['document_root'], false);
MC 1873                 $app->system->file_put_contents($data['new']['document_root'].'/web/stats/.htpasswd_stats', $htp_file);
1874                 $app->system->web_folder_protection($data['new']['document_root'], true);
1875                 $app->system->chmod($data['new']['document_root'].'/web/stats/.htpasswd_stats', 0755);
46c683 1876                 unset($htp_file);
T 1877             }
1878         }
b1a6a5 1879
58c210 1880         //* Create awstats configuration
511ba5 1881         if($data['new']['stats_type'] == 'awstats' && ($data['new']['type'] == 'vhost' || $data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias')) {
b1a6a5 1882             $this->awstats_update($data, $web_config);
58c210 1883         }
b1a6a5 1884
MC 1885         $this->php_fpm_pool_update($data, $web_config, $pool_dir, $pool_name, $socket_dir);
c59632 1886         $this->hhvm_update($data, $web_config);
b1a6a5 1887
7ed741 1888         if($web_config['check_apache_config'] == 'y') {
T 1889             //* Test if apache starts with the new configuration file
b1a6a5 1890             $apache_online_status_before_restart = $this->_checkTcp('localhost', 80);
MC 1891             $app->log('Apache status is: '.($apache_online_status_before_restart === true? 'running' : 'down'), LOGLEVEL_DEBUG);
ac933e 1892
b1a6a5 1893             $retval = $app->services->restartService('httpd', 'restart'); // $retval['retval'] is 0 on success and > 0 on failure
MC 1894             $app->log('Apache restart return value is: '.$retval['retval'], LOGLEVEL_DEBUG);
1895
9f56bd 1896             // wait a few seconds, before we test the apache status again
bfcdef 1897             $apache_online_status_after_restart = false;
9f56bd 1898             sleep(2);
bfcdef 1899             for($i = 0; $i < 5; $i++) {
b1a6a5 1900                 $apache_online_status_after_restart = $this->_checkTcp('localhost', 80);
bfcdef 1901                 if($apache_online_status_after_restart) break;
T 1902                 sleep(1);
1903             }
7ed741 1904             //* Check if apache restarted successfully if it was online before
b1a6a5 1905             $app->log('Apache online status after restart is: '.($apache_online_status_after_restart === true? 'running' : 'down'), LOGLEVEL_DEBUG);
615a0a 1906             if($apache_online_status_before_restart && !$apache_online_status_after_restart || $retval['retval'] > 0) {
b1a6a5 1907                 $app->log('Apache 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);
615a0a 1908                 if(is_array($retval['output']) && !empty($retval['output'])){
b1a6a5 1909                     $app->log('Reason for Apache restart failure: '.implode("\n", $retval['output']), LOGLEVEL_WARN);
7b47c0 1910                     $app->dbmaster->datalogError(implode("\n", $retval['output']));
615a0a 1911                 } else {
T 1912                     // if no output is given, check again
1913                     $webserver_binary = '';
7b47c0 1914                     exec('which apache2ctl', $webserver_check_output, $webserver_check_retval);
615a0a 1915                     if($webserver_check_retval == 0){
7b47c0 1916                         $webserver_binary = 'apache2ctl';
615a0a 1917                     } else {
T 1918                         unset($webserver_check_output, $webserver_check_retval);
7b47c0 1919                         exec('which apache2', $webserver_check_output, $webserver_check_retval);
615a0a 1920                         if($webserver_check_retval == 0){
7b47c0 1921                             $webserver_binary = 'apache2';
615a0a 1922                         } else {
T 1923                             unset($webserver_check_output, $webserver_check_retval);
7b47c0 1924                             exec('which httpd2', $webserver_check_output, $webserver_check_retval);
615a0a 1925                             if($webserver_check_retval == 0){
7b47c0 1926                                 $webserver_binary = 'httpd2';
615a0a 1927                             } else {
T 1928                                 unset($webserver_check_output, $webserver_check_retval);
7b47c0 1929                                 exec('which httpd', $webserver_check_output, $webserver_check_retval);
615a0a 1930                                 if($webserver_check_retval == 0){
7b47c0 1931                                     $webserver_binary = 'httpd';
T 1932                                 } else {
1933                                     unset($webserver_check_output, $webserver_check_retval);
1934                                     exec('which apache', $webserver_check_output, $webserver_check_retval);
1935                                     if($webserver_check_retval == 0){
1936                                         $webserver_binary = 'apache';
1937                                     }
615a0a 1938                                 }
T 1939                             }
1940                         }
1941                     }
1942                     if($webserver_binary != ''){
1943                         exec($webserver_binary.' -t 2>&1', $tmp_output, $tmp_retval);
7b47c0 1944                         if($tmp_retval > 0 && is_array($tmp_output) && !empty($tmp_output)){
b1a6a5 1945                             $app->log('Reason for Apache restart failure: '.implode("\n", $tmp_output), LOGLEVEL_WARN);
7b47c0 1946                             $app->dbmaster->datalogError(implode("\n", $tmp_output));
T 1947                         }
615a0a 1948                         unset($tmp_output, $tmp_retval);
T 1949                     }
1950                 }
b1a6a5 1951                 $app->system->copy($vhost_file, $vhost_file.'.err');
8cf78b 1952                 if(is_file($vhost_file.'~')) {
T 1953                     //* Copy back the last backup file
b1a6a5 1954                     $app->system->copy($vhost_file.'~', $vhost_file);
8cf78b 1955                 } else {
T 1956                     //* There is no backup file, so we create a empty vhost file with a warning message inside
b1a6a5 1957                     $app->system->file_put_contents($vhost_file, "# Apache did not start after modifying this vhost file.\n# Please check file $vhost_file.err for syntax errors.");
8cf78b 1958                 }
481c00 1959                 if($this->ssl_certificate_changed === true) {
T 1960
1961                     $ssl_dir = $data['new']['document_root'].'/ssl';
1962                     $domain = $data['new']['ssl_domain'];
1963                     $key_file = $ssl_dir.'/'.$domain.'.key.org';
1964                     $key_file2 = $ssl_dir.'/'.$domain.'.key';
1965                     $csr_file = $ssl_dir.'/'.$domain.'.csr';
1966                     $crt_file = $ssl_dir.'/'.$domain.'.crt';
1967                     $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
b1a6a5 1968
481c00 1969                     //* Backup the files that might have caused the error
43b345 1970                     if(is_file($key_file)){
b1a6a5 1971                         $app->system->copy($key_file, $key_file.'.err');
MC 1972                         $app->system->chmod($key_file.'.err', 0400);
43b345 1973                     }
T 1974                     if(is_file($key_file2)){
b1a6a5 1975                         $app->system->copy($key_file2, $key_file2.'.err');
MC 1976                         $app->system->chmod($key_file2.'.err', 0400);
43b345 1977                     }
b1a6a5 1978                     if(is_file($csr_file)) $app->system->copy($csr_file, $csr_file.'.err');
MC 1979                     if(is_file($crt_file)) $app->system->copy($crt_file, $crt_file.'.err');
1980                     if(is_file($bundle_file)) $app->system->copy($bundle_file, $bundle_file.'.err');
1981
481c00 1982                     //* Restore the ~ backup files
b1a6a5 1983                     if(is_file($key_file.'~')) $app->system->copy($key_file.'~', $key_file);
MC 1984                     if(is_file($key_file2.'~')) $app->system->copy($key_file2.'~', $key_file2);
1985                     if(is_file($crt_file.'~')) $app->system->copy($crt_file.'~', $crt_file);
1986                     if(is_file($csr_file.'~')) $app->system->copy($csr_file.'~', $csr_file);
1987                     if(is_file($bundle_file.'~')) $app->system->copy($bundle_file.'~', $bundle_file);
1988
1989                     $app->log('Apache 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);
481c00 1990                 }
b1a6a5 1991
MC 1992                 $app->services->restartService('httpd', 'restart');
7ed741 1993             }
c82dc7 1994         } else {
7ed741 1995             //* We do not check the apache config after changes (is faster)
T 1996             if($apache_chrooted) {
b1a6a5 1997                 $app->services->restartServiceDelayed('httpd', 'restart');
7ed741 1998             } else {
T 1999                 // request a httpd reload when all records have been processed
b1a6a5 2000                 $app->services->restartServiceDelayed('httpd', 'reload');
7ed741 2001             }
c82dc7 2002         }
b1a6a5 2003
MC 2004         //* The vhost is written and apache has been restarted, so we
481c00 2005         // can reset the ssl changed var to false and cleanup some files
T 2006         $this->ssl_certificate_changed = false;
b1a6a5 2007
481c00 2008         $ssl_dir = $data['new']['document_root'].'/ssl';
T 2009         $domain = $data['new']['ssl_domain'];
2010         $key_file = $ssl_dir.'/'.$domain.'.key.org';
2011         $key_file2 = $ssl_dir.'/'.$domain.'.key';
2012         $csr_file = $ssl_dir.'/'.$domain.'.csr';
2013         $crt_file = $ssl_dir.'/'.$domain.'.crt';
2014         $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
b1a6a5 2015
c77103 2016         if(@is_file($key_file.'~')) $app->system->unlink($key_file.'~');
T 2017         if(@is_file($key2_file.'~')) $app->system->unlink($key2_file.'~');
2018         if(@is_file($crt_file.'~')) $app->system->unlink($crt_file.'~');
2019         if(@is_file($csr_file.'~')) $app->system->unlink($csr_file.'~');
2020         if(@is_file($bundle_file.'~')) $app->system->unlink($bundle_file.'~');
b1a6a5 2021
7ed741 2022         // Remove the backup copy of the config file.
c77103 2023         if(@is_file($vhost_file.'~')) $app->system->unlink($vhost_file.'~');
ac933e 2024
da1a7c 2025         //* Unset action to clean it for next processed vhost.
T 2026         $this->action = '';
46c683 2027     }
ac933e 2028
b1a6a5 2029     function delete($event_name, $data) {
46c683 2030         global $app, $conf;
ac933e 2031
46c683 2032         // load the server configuration options
fb3339 2033         $app->uses('getconf');
c09f04 2034         $app->uses('system');
fb3339 2035         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
cc6568 2036         $fastcgi_config = $app->getconf->get_server_config($conf['server_id'], 'fastcgi');
b1a6a5 2037
511ba5 2038         if($data['old']['type'] == 'vhost' || $data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') $app->system->web_folder_protection($data['old']['document_root'], false);
ac933e 2039
2bbc4c 2040         //* Check if this is a chrooted setup
4b72c5 2041         if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
2bbc4c 2042             $apache_chrooted = true;
T 2043         } else {
2044             $apache_chrooted = false;
2045         }
b1a6a5 2046
fea5e7 2047         //* Remove the mounts
T 2048         $log_folder = 'log';
b1a6a5 2049         $web_folder = '';
511ba5 2050         if($data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') {
2af58c 2051             $tmp = $app->db->queryOneRecord('SELECT `domain`,`document_root` FROM web_domain WHERE domain_id = ?', $data['old']['parent_domain_id']);
526b99 2052             if($tmp['domain'] != ''){
T 2053                 $subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $data['old']['domain']);
2054             } else {
2055                 // get log folder from /etc/fstab
2056                 /*
2057                 $bind_mounts = $app->system->file_get_contents('/etc/fstab');
2058                 $bind_mount_lines = explode("\n", $bind_mounts);
2059                 if(is_array($bind_mount_lines) && !empty($bind_mount_lines)){
2060                     foreach($bind_mount_lines as $bind_mount_line){
2061                         $bind_mount_line = preg_replace('/\s+/', ' ', $bind_mount_line);
2062                         $bind_mount_parts = explode(' ', $bind_mount_line);
2063                         if(is_array($bind_mount_parts) && !empty($bind_mount_parts)){
2064                             if($bind_mount_parts[0] == '/var/log/ispconfig/httpd/'.$data['old']['domain'] && $bind_mount_parts[2] == 'none' && strpos($bind_mount_parts[3], 'bind') !== false){
2065                                 $subdomain_host = str_replace($data['old']['document_root'].'/log/', '', $bind_mount_parts[1]);
2066                             }
2067                         }
2068                     }
2069                 }
2070                 */
2071                 // we are deleting the parent domain, so we can delete everything in the log directory
2072                 $subdomain_hosts = array();
b1a6a5 2073                 $files = array_diff(scandir($data['old']['document_root'].'/'.$log_folder), array('.', '..'));
526b99 2074                 if(is_array($files) && !empty($files)){
T 2075                     foreach($files as $file){
2076                         if(is_dir($data['old']['document_root'].'/'.$log_folder.'/'.$file)){
2077                             $subdomain_hosts[] = $file;
2078                         }
2079                     }
2080                 }
2081             }
b1a6a5 2082             if(is_array($subdomain_hosts) && !empty($subdomain_hosts)){
526b99 2083                 $log_folders = array();
T 2084                 foreach($subdomain_hosts as $subdomain_host){
2085                     $log_folders[] = $log_folder.'/'.$subdomain_host;
2086                 }
2087             } else {
2088                 if($subdomain_host == '') $subdomain_host = 'web'.$data['old']['domain_id'];
2089                 $log_folder .= '/' . $subdomain_host;
2090             }
2091             $web_folder = $data['old']['web_folder'];
b1a6a5 2092             unset($tmp);
526b99 2093             unset($subdomain_hosts);
3cde19 2094         }
b1a6a5 2095
511ba5 2096         if($data['old']['type'] == 'vhost' || $data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias'){
526b99 2097             if(is_array($log_folders) && !empty($log_folders)){
T 2098                 foreach($log_folders as $log_folder){
cc6568 2099                     //if($app->system->is_mounted($data['old']['document_root'].'/'.$log_folder)) exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder));
a9b325 2100                     //exec('fuser -km '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
cc6568 2101                     exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
526b99 2102                 }
T 2103             } else {
cc6568 2104                 //if($app->system->is_mounted($data['old']['document_root'].'/'.$log_folder)) exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder));
a9b325 2105                 //exec('fuser -km '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
cc6568 2106                 exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
526b99 2107             }
a49635 2108             
MB 2109             // remove letsencrypt if it exists (renew will always fail otherwise)
2110             
2111             $domain = $data['old']['ssl_domain'];
2112             if(!$domain) $domain = $data['old']['domain'];
2113             if(substr($domain, 0, 2) === '*.') {
2114                 // wildcard domain not yet supported by letsencrypt!
2115                 $domain = substr($domain, 2);
2116             }
2117             //$crt_tmp_file = "/etc/letsencrypt/live/".$domain."/cert.pem";
2118             //$key_tmp_file = "/etc/letsencrypt/live/".$domain."/privkey.pem";
2119             $le_conf_file = '/etc/letsencrypt/renewal/' . $domain . '.conf';
2120             @rename('/etc/letsencrypt/renewal/' . $domain . '.conf', '/etc/letsencrypt/renewal/' . $domain . '.conf~backup');
526b99 2121         }
b1a6a5 2122
fea5e7 2123         //* remove mountpoint from fstab
526b99 2124         if(is_array($log_folders) && !empty($log_folders)){
T 2125             foreach($log_folders as $log_folder){
2126                 $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$log_folder.'    none    bind';
b1a6a5 2127                 $app->system->removeLine('/etc/fstab', $fstab_line);
526b99 2128             }
T 2129         } else {
2130             $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$log_folder.'    none    bind';
b1a6a5 2131             $app->system->removeLine('/etc/fstab', $fstab_line);
526b99 2132         }
T 2133         unset($log_folders);
ac933e 2134
511ba5 2135         if($data['old']['type'] != 'vhost' && $data['old']['type'] != 'vhostsubdomain' && $data['old']['type'] != 'vhostalias' && $data['old']['parent_domain_id'] > 0) {
46c683 2136             //* This is a alias domain or subdomain, so we have to update the website instead
fb3339 2137             $parent_domain_id = intval($data['old']['parent_domain_id']);
2af58c 2138             $tmp = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ? AND active = 'y'", $parent_domain_id);
fb3339 2139             $data['new'] = $tmp;
J 2140             $data['old'] = $tmp;
46c683 2141             $this->action = 'update';
496602 2142             $this->update_letsencrypt = true;
46c683 2143             // just run the update function
b1a6a5 2144             $this->update($event_name, $data);
ac933e 2145
46c683 2146         } else {
T 2147             //* This is a website
2148             // Deleting the vhost file, symlink and the data directory
fb3339 2149             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
b1a6a5 2150
8ab3cd 2151             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
T 2152             if(is_link($vhost_symlink)){
c77103 2153                 $app->system->unlink($vhost_symlink);
b1a6a5 2154                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
8ab3cd 2155             }
T 2156             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['old']['domain'].'.vhost');
2157             if(is_link($vhost_symlink)){
c77103 2158                 $app->system->unlink($vhost_symlink);
b1a6a5 2159                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
8ab3cd 2160             }
T 2161             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['old']['domain'].'.vhost');
2162             if(is_link($vhost_symlink)){
c77103 2163                 $app->system->unlink($vhost_symlink);
b1a6a5 2164                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
8ab3cd 2165             }
b1a6a5 2166
c77103 2167             $app->system->unlink($vhost_file);
b1a6a5 2168             $app->log('Removing vhost file: '.$vhost_file, LOGLEVEL_DEBUG);
ac933e 2169
511ba5 2170             if($data['old']['type'] == 'vhost' || $data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') {
b1a6a5 2171                 $docroot = escapeshellcmd($data['old']['document_root']);
MC 2172                 if($docroot != '' && !stristr($docroot, '..')) {
2173                     if($data['old']['type'] == 'vhost') {
2174                         // this is a vhost - we delete everything in here.
2175                         exec('rm -rf '.$docroot);
2176                     } elseif(!stristr($data['old']['web_folder'], '..')) {
2177                         // this is a vhost subdomain
2178                         // IMPORTANT: do some folder checks before we delete this!
2179                         $do_delete = true;
2180                         $delete_folder = preg_replace('/[\/]{2,}/', '/', $web_folder); // replace / occuring multiple times
2181                         if(substr($delete_folder, 0, 1) === '/') $delete_folder = substr($delete_folder, 1);
2182                         if(substr($delete_folder, -1) === '/') $delete_folder = substr($delete_folder, 0, -1);
46c683 2183
b1a6a5 2184                         $path_elements = explode('/', $delete_folder);
46c683 2185
b1a6a5 2186                         if($path_elements[0] == 'web' || $path_elements[0] === '') {
MC 2187                             // paths beginning with /web should NEVER EVER be deleted, empty paths should NEVER occur - but for safety reasons we check it here!
2188                             // we use strict check as otherwise directories named '0' may not be deleted
2189                             $do_delete = false;
2190                         } else {
511ba5 2191                             // read all vhost subdomains and alias with same parent domain
b1a6a5 2192                             $used_paths = array();
2af58c 2193                             $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']);
b1a6a5 2194                             foreach($tmp as $tmprec) {
MC 2195                                 // we normalize the folder entries because we need to compare them
2196                                 $tmp_folder = preg_replace('/[\/]{2,}/', '/', $tmprec['web_folder']); // replace / occuring multiple times
2197                                 if(substr($tmp_folder, 0, 1) === '/') $tmp_folder = substr($tmp_folder, 1);
2198                                 if(substr($tmp_folder, -1) === '/') $tmp_folder = substr($tmp_folder, 0, -1);
ac933e 2199
b1a6a5 2200                                 // add this path and it's parent paths to used_paths array
MC 2201                                 while(strpos($tmp_folder, '/') !== false) {
2202                                     if(in_array($tmp_folder, $used_paths) == false) $used_paths[] = $tmp_folder;
2203                                     $tmp_folder = substr($tmp_folder, 0, strrpos($tmp_folder, '/'));
2204                                 }
2205                                 if(in_array($tmp_folder, $used_paths) == false) $used_paths[] = $tmp_folder;
2206                             }
2207                             unset($tmp);
2208
2209                             // loop and check if the path is still used and stop at first used one
2210                             // set do_delete to false so nothing gets deleted if the web_folder itself is still used
2211                             $do_delete = false;
2212                             while(count($path_elements) > 0) {
2213                                 $tmp_folder = implode('/', $path_elements);
2214                                 if(in_array($tmp_folder, $used_paths) == true) break;
2215
2216                                 // this path is not used - set it as path to delete, strip the last element from the array and set do_delete to true
2217                                 $delete_folder = $tmp_folder;
2218                                 $do_delete = true;
2219                                 array_pop($path_elements);
2220                             }
2221                             unset($tmp_folder);
2222                             unset($used_paths);
2223                         }
2224
2225                         if($do_delete === true && $delete_folder !== '') exec('rm -rf '.$docroot.'/'.$delete_folder);
2226
2227                         unset($delete_folder);
2228                         unset($path_elements);
2229                     }
2230                 }
2231
2232                 //remove the php fastgi starter script if available
2233                 if ($data['old']['php'] == 'fast-cgi') {
2234                     $fastcgi_starter_path = str_replace('[system_user]', $data['old']['system_user'], $fastcgi_config['fastcgi_starter_path']);
2235                     if($data['old']['type'] == 'vhost') {
2236                         if (is_dir($fastcgi_starter_path)) {
2237                             exec('rm -rf '.$fastcgi_starter_path);
2238                         }
2239                     } else {
2240                         $fcgi_starter_script = $fastcgi_starter_path.$fastcgi_config['fastcgi_starter_script'].'_web'.$data['old']['domain_id'];
2241                         if (file_exists($fcgi_starter_script)) {
2242                             exec('rm -f '.$fcgi_starter_script);
2243                         }
2244                     }
2245                 }
2246
2247                 // remove PHP-FPM pool
2248                 if ($data['old']['php'] == 'php-fpm') {
2249                     $this->php_fpm_pool_delete($data, $web_config);
c59632 2250                 } elseif($data['old']['php'] == 'hhvm') {
MC 2251                     $this->hhvm_update($data, $web_config);
b1a6a5 2252                 }
MC 2253
2254                 //remove the php cgi starter script if available
2255                 if ($data['old']['php'] == 'cgi') {
2256                     // TODO: fetch the date from the server-settings
2257                     $web_config['cgi_starter_path'] = $web_config['website_basedir'].'/php-cgi-scripts/[system_user]/';
2258
2259                     $cgi_starter_path = str_replace('[system_user]', $data['old']['system_user'], $web_config['cgi_starter_path']);
2260                     if($data['old']['type'] == 'vhost') {
2261                         if (is_dir($cgi_starter_path)) {
2262                             exec('rm -rf '.$cgi_starter_path);
2263                         }
2264                     } else {
2265                         $cgi_starter_script = $cgi_starter_path.'php-cgi-starter_web'.$data['old']['domain_id'];
2266                         if (file_exists($cgi_starter_script)) {
2267                             exec('rm -f '.$cgi_starter_script);
2268                         }
2269                     }
2270                 }
2271
2272                 $app->log('Removing website: '.$docroot, LOGLEVEL_DEBUG);
2273
2274                 // Delete the symlinks for the sites
2af58c 2275                 $client = $app->db->queryOneRecord('SELECT client_id FROM sys_group WHERE sys_group.groupid = ?', $data['old']['sys_groupid']);
b1a6a5 2276                 $client_id = intval($client['client_id']);
MC 2277                 unset($client);
2278                 $tmp_symlinks_array = explode(':', $web_config['website_symlinks']);
2279                 if(is_array($tmp_symlinks_array)) {
2280                     foreach($tmp_symlinks_array as $tmp_symlink) {
2281                         $tmp_symlink = str_replace('[client_id]', $client_id, $tmp_symlink);
2282                         $tmp_symlink = str_replace('[website_domain]', $data['old']['domain'], $tmp_symlink);
2283                         // Remove trailing slash
2284                         if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
2285                         // delete the symlink
2286                         if(is_link($tmp_symlink)) {
2287                             $app->system->unlink($tmp_symlink);
2288                             $app->log('Removing symlink: '.$tmp_symlink, LOGLEVEL_DEBUG);
2289                         }
2290                     }
2291                 }
2292                 // end removing symlinks
3cde19 2293             }
b1a6a5 2294
MC 2295             // Delete the log file directory
2296             $vhost_logfile_dir = escapeshellcmd('/var/log/ispconfig/httpd/'.$data['old']['domain']);
2297             if($data['old']['domain'] != '' && !stristr($vhost_logfile_dir, '..')) exec('rm -rf '.$vhost_logfile_dir);
2298             $app->log('Removing website logfile directory: '.$vhost_logfile_dir, LOGLEVEL_DEBUG);
2299
2300             if($data['old']['type'] == 'vhost') {
2301                 //delete the web user
2302                 $command = 'killall -u '.escapeshellcmd($data['old']['system_user']).' ; userdel';
2303                 $command .= ' '.escapeshellcmd($data['old']['system_user']);
2304                 exec($command);
2305                 if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' '.$command);
2306
2307             }
2308
2309             //* Remove the awstats configuration file
2310             if($data['old']['stats_type'] == 'awstats') {
2311                 $this->awstats_delete($data, $web_config);
2312             }
2313
511ba5 2314             if($data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') {
b1a6a5 2315                 $app->system->web_folder_protection($parent_web_document_root, true);
MC 2316             }
2317
8ab3cd 2318             if($apache_chrooted) {
b1a6a5 2319                 $app->services->restartServiceDelayed('httpd', 'restart');
8ab3cd 2320             } else {
T 2321                 // request a httpd reload when all records have been processed
b1a6a5 2322                 $app->services->restartServiceDelayed('httpd', 'reload');
58c210 2323             }
ac933e 2324
0f89bd 2325             //* Delete the web-backups
69b1bc 2326             if($data['old']['type'] == 'vhost') {
FS 2327                 $server_config = $app->getconf->get_server_config($conf['server_id'], 'server');
2328                 $backup_dir = $server_config['backup_dir'];
2329                 $mount_backup = true;
a81238 2330                 if($server_config['backup_dir'] != '' && $server_config['backup_delete'] == 'y') {
990ca8 2331                     //* mount backup directory, if necessary
FS 2332                     if( $server_config['backup_dir_is_mount'] == 'y' && !$app->system->mount_backup_dir($backup_dir) ) $mount_backup = false;
2333
69b1bc 2334                     if($mount_backup){
FS 2335                         $web_backup_dir = $backup_dir.'/web'.$data_old['domain_id'];
2336                         //** do not use rm -rf $web_backup_dir because database(s) may exits
2337                         exec(escapeshellcmd('rm -f '.$web_backup_dir.'/web'.$data_old['domain_id'].'_').'*');
2338                         //* cleanup database
990ca8 2339                         $sql = "DELETE FROM web_backup WHERE server_id = ? AND parent_domain_id = ? AND filename LIKE ?";
FS 2340                         $app->db->query($sql, $conf['server_id'], $data_old['domain_id'], "web".$data_old['domain_id']."_%");
2341                         if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql, $conf['server_id'], $data_old['domain_id'], "web".$data_old['domain_id']."_%");
0f89bd 2342
FS 2343                         $app->log('Deleted the web backup files', LOGLEVEL_DEBUG);
69b1bc 2344                     }
FS 2345                 }
2346             }
46c683 2347         }
b1a6a5 2348         if($data['old']['type'] != 'vhost') $app->system->web_folder_protection($data['old']['document_root'], true);
46c683 2349     }
ac933e 2350
46c683 2351     //* This function is called when a IP on the server is inserted, updated or deleted
b1a6a5 2352     function server_ip($event_name, $data) {
46c683 2353         global $app, $conf;
ac933e 2354
46c683 2355         // load the server configuration options
fb3339 2356         $app->uses('getconf');
J 2357         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
ac933e 2358
46c683 2359         $app->load('tpl');
ac933e 2360
46c683 2361         $tpl = new tpl();
fb3339 2362         $tpl->newTemplate('apache_ispconfig.conf.master');
8133de 2363         $tpl->setVar('apache_version', $app->system->getapacheversion());
2af58c 2364         $records = $app->db->queryAllRecords("SELECT * FROM server_ip WHERE server_id = ? AND virtualhost = 'y'", $conf['server_id']);
b1a6a5 2365
a2156e 2366         $records_out= array();
T 2367         if(is_array($records)) {
2368             foreach($records as $rec) {
2369                 if($rec['ip_type'] == 'IPv6') {
2370                     $ip_address = '['.$rec['ip_address'].']';
2371                 } else {
2372                     $ip_address = $rec['ip_address'];
2373                 }
b1a6a5 2374                 $ports = explode(',', $rec['virtualhost_port']);
a2156e 2375                 if(is_array($ports)) {
T 2376                     foreach($ports as $port) {
2377                         $port = intval($port);
2378                         if($port > 0 && $port < 65536 && $ip_address != '') {
2379                             $records_out[] = array('ip_address' => $ip_address, 'port' => $port);
2380                         }
2381                     }
2382                 }
2383             }
2384         }
b1a6a5 2385
MC 2386
a2156e 2387         if(count($records_out) > 0) {
b1a6a5 2388             $tpl->setLoop('ip_adresses', $records_out);
46c683 2389         }
ac933e 2390
fb3339 2391         $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/ispconfig.conf');
b1a6a5 2392         $app->system->file_put_contents($vhost_file, $tpl->grab());
MC 2393         $app->log('Writing the conf file: '.$vhost_file, LOGLEVEL_DEBUG);
46c683 2394         unset($tpl);
ac933e 2395
46c683 2396     }
b1a6a5 2397
524077 2398     //* Create or update the .htaccess folder protection
b1a6a5 2399     function web_folder_user($event_name, $data) {
524077 2400         global $app, $conf;
c69439 2401
524077 2402         $app->uses('system');
b1a6a5 2403
524077 2404         if($event_name == 'web_folder_user_delete') {
T 2405             $folder_id = $data['old']['web_folder_id'];
2406         } else {
2407             $folder_id = $data['new']['web_folder_id'];
2408         }
b1a6a5 2409
2af58c 2410         $folder = $app->db->queryOneRecord("SELECT * FROM web_folder WHERE web_folder_id = ?", $folder_id);
MC 2411         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $folder['parent_domain_id']);
b1a6a5 2412
524077 2413         if(!is_array($folder) or !is_array($website)) {
b1a6a5 2414             $app->log('Not able to retrieve folder or website record.', LOGLEVEL_DEBUG);
524077 2415             return false;
T 2416         }
b1a6a5 2417
MC 2418         $web_folder = 'web';
511ba5 2419         if($website['type'] == 'vhostsubdomain' || $website['type'] == 'vhostalias') $web_folder = $website['web_folder'];
b1a6a5 2420
524077 2421         //* Get the folder path.
b1a6a5 2422         if(substr($folder['path'], 0, 1) == '/') $folder['path'] = substr($folder['path'], 1);
MC 2423         if(substr($folder['path'], -1) == '/') $folder['path'] = substr($folder['path'], 0, -1);
6fb93d 2424         $folder_path = escapeshellcmd($website['document_root'].'/' . $web_folder . '/'.$folder['path']);
b1a6a5 2425         if(substr($folder_path, -1) != '/') $folder_path .= '/';
MC 2426
524077 2427         //* Check if the resulting path is inside the docroot
b1a6a5 2428         if(stristr($folder_path, '..') || stristr($folder_path, './') || stristr($folder_path, '\\')) {
MC 2429             $app->log('Folder path "'.$folder_path.'" contains .. or ./.', LOGLEVEL_DEBUG);
524077 2430             return false;
T 2431         }
b1a6a5 2432
524077 2433         //* Create the folder path, if it does not exist
8cf78b 2434         if(!is_dir($folder_path)) {
dbae22 2435             $app->system->mkdirpath($folder_path, 0755, $website['system_user'], $website['system_group']);
8cf78b 2436         }
b1a6a5 2437
524077 2438         //* Create empty .htpasswd file, if it does not exist
T 2439         if(!is_file($folder_path.'.htpasswd')) {
4bd960 2440             $app->system->touch($folder_path.'.htpasswd');
51910d 2441             $app->system->chmod($folder_path.'.htpasswd', 0751);
b1a6a5 2442             $app->system->chown($folder_path.'.htpasswd', $website['system_user']);
MC 2443             $app->system->chgrp($folder_path.'.htpasswd', $website['system_group']);
2444             $app->log('Created file '.$folder_path.'.htpasswd', LOGLEVEL_DEBUG);
524077 2445         }
b1a6a5 2446
8ab3cd 2447         if(($data['new']['username'] != $data['old']['username'] || $data['new']['active'] == 'n') && $data['old']['username'] != '') {
b1a6a5 2448             $app->system->removeLine($folder_path.'.htpasswd', $data['old']['username'].':');
MC 2449             $app->log('Removed user: '.$data['old']['username'], LOGLEVEL_DEBUG);
c69439 2450         }
b1a6a5 2451
524077 2452         //* Add or remove the user from .htpasswd file
T 2453         if($event_name == 'web_folder_user_delete') {
b1a6a5 2454             $app->system->removeLine($folder_path.'.htpasswd', $data['old']['username'].':');
MC 2455             $app->log('Removed user: '.$data['old']['username'], LOGLEVEL_DEBUG);
524077 2456         } else {
c69439 2457             if($data['new']['active'] == 'y') {
b1a6a5 2458                 $app->system->replaceLine($folder_path.'.htpasswd', $data['new']['username'].':', $data['new']['username'].':'.$data['new']['password'], 0, 1);
MC 2459                 $app->log('Added or updated user: '.$data['new']['username'], LOGLEVEL_DEBUG);
c69439 2460             }
524077 2461         }
b1a6a5 2462
MC 2463
524077 2464         //* Create the .htaccess file
8ab3cd 2465         //if(!is_file($folder_path.'.htaccess')) {
b1a6a5 2466         $begin_marker = '### ISPConfig folder protection begin ###';
MC 2467         $end_marker = "### ISPConfig folder protection end ###\n\n";
2468         $ht_file = $begin_marker."\nAuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$folder_path.".htpasswd\nrequire valid-user\n".$end_marker;
2469
2470         if(file_exists($folder_path.'.htaccess')) {
2471             $old_content = $app->system->file_get_contents($folder_path.'.htaccess');
2472
2473             if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $old_content, $matches)) {
2474                 $ht_file = str_replace($matches[0], $ht_file, $old_content);
2475             } else {
2476                 $ht_file .= $old_content;
2477             }
2478         }
2479         unset($old_content);
2480
2481         $app->system->file_put_contents($folder_path.'.htaccess', $ht_file);
51910d 2482         $app->system->chmod($folder_path.'.htaccess', 0751);
b1a6a5 2483         $app->system->chown($folder_path.'.htaccess', $website['system_user']);
MC 2484         $app->system->chgrp($folder_path.'.htaccess', $website['system_group']);
2485         $app->log('Created/modified file '.$folder_path.'.htaccess', LOGLEVEL_DEBUG);
8ab3cd 2486         //}
b1a6a5 2487
524077 2488     }
b1a6a5 2489
524077 2490     //* Remove .htaccess and .htpasswd file, when folder protection is removed
b1a6a5 2491     function web_folder_delete($event_name, $data) {
524077 2492         global $app, $conf;
b1a6a5 2493
524077 2494         $folder_id = $data['old']['web_folder_id'];
b1a6a5 2495
8ab3cd 2496         $folder = $data['old'];
2af58c 2497         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $folder['parent_domain_id']);
b1a6a5 2498
524077 2499         if(!is_array($folder) or !is_array($website)) {
b1a6a5 2500             $app->log('Not able to retrieve folder or website record.', LOGLEVEL_DEBUG);
524077 2501             return false;
T 2502         }
b1a6a5 2503
MC 2504         $web_folder = 'web';
511ba5 2505         if($website['type'] == 'vhostsubdomain' || $website['type'] == 'vhostalias') $web_folder = $website['web_folder'];
b1a6a5 2506
524077 2507         //* Get the folder path.
b1a6a5 2508         if(substr($folder['path'], 0, 1) == '/') $folder['path'] = substr($folder['path'], 1);
MC 2509         if(substr($folder['path'], -1) == '/') $folder['path'] = substr($folder['path'], 0, -1);
6fb93d 2510         $folder_path = realpath($website['document_root'].'/' . $web_folder . '/'.$folder['path']);
b1a6a5 2511         if(substr($folder_path, -1) != '/') $folder_path .= '/';
MC 2512
524077 2513         //* Check if the resulting path is inside the docroot
b1a6a5 2514         if(substr($folder_path, 0, strlen($website['document_root'])) != $website['document_root']) {
MC 2515             $app->log('Folder path is outside of docroot.', LOGLEVEL_DEBUG);
524077 2516             return false;
T 2517         }
b1a6a5 2518
524077 2519         //* Remove .htpasswd file
T 2520         if(is_file($folder_path.'.htpasswd')) {
c77103 2521             $app->system->unlink($folder_path.'.htpasswd');
b1a6a5 2522             $app->log('Removed file '.$folder_path.'.htpasswd', LOGLEVEL_DEBUG);
524077 2523         }
b1a6a5 2524
524077 2525         //* Remove .htaccess file
T 2526         if(is_file($folder_path.'.htaccess')) {
b1a6a5 2527             $begin_marker = '### ISPConfig folder protection begin ###';
MC 2528             $end_marker = "### ISPConfig folder protection end ###\n\n";
2529
2530             $ht_file = $app->system->file_get_contents($folder_path.'.htaccess');
2531
2532             if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $ht_file, $matches)) {
2533                 $ht_file = str_replace($matches[0], '', $ht_file);
2534             } else {
2535                 $ht_file = str_replace("AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$folder_path.".htpasswd\nrequire valid-user", '', $ht_file);
2536             }
2537
2538             if(trim($ht_file) == '') {
2539                 $app->system->unlink($folder_path.'.htaccess');
2540                 $app->log('Removed file '.$folder_path.'.htaccess', LOGLEVEL_DEBUG);
2541             } else {
2542                 $app->system->file_put_contents($folder_path.'.htaccess', $ht_file);
2543                 $app->log('Removed protection content from file '.$folder_path.'.htaccess', LOGLEVEL_DEBUG);
2544             }
524077 2545         }
2023a7 2546     }
b1a6a5 2547
2023a7 2548     //* Update folder protection, when path has been changed
b1a6a5 2549     function web_folder_update($event_name, $data) {
2023a7 2550         global $app, $conf;
b1a6a5 2551
2af58c 2552         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $data['new']['parent_domain_id']);
b1a6a5 2553
2023a7 2554         if(!is_array($website)) {
b1a6a5 2555             $app->log('Not able to retrieve folder or website record.', LOGLEVEL_DEBUG);
2023a7 2556             return false;
T 2557         }
b1a6a5 2558
MC 2559         $web_folder = 'web';
511ba5 2560         if($website['type'] == 'vhostsubdomain' || $website['type'] == 'vhostalias') $web_folder = $website['web_folder'];
b1a6a5 2561
2023a7 2562         //* Get the folder path.
b1a6a5 2563         if(substr($data['old']['path'], 0, 1) == '/') $data['old']['path'] = substr($data['old']['path'], 1);
MC 2564         if(substr($data['old']['path'], -1) == '/') $data['old']['path'] = substr($data['old']['path'], 0, -1);
6fb93d 2565         $old_folder_path = realpath($website['document_root'].'/' . $web_folder . '/'.$data['old']['path']);
b1a6a5 2566         if(substr($old_folder_path, -1) != '/') $old_folder_path .= '/';
MC 2567
2568         if(substr($data['new']['path'], 0, 1) == '/') $data['new']['path'] = substr($data['new']['path'], 1);
2569         if(substr($data['new']['path'], -1) == '/') $data['new']['path'] = substr($data['new']['path'], 0, -1);
6fb93d 2570         $new_folder_path = escapeshellcmd($website['document_root'].'/' . $web_folder . '/'.$data['new']['path']);
b1a6a5 2571         if(substr($new_folder_path, -1) != '/') $new_folder_path .= '/';
MC 2572
2023a7 2573         //* Check if the resulting path is inside the docroot
b1a6a5 2574         if(stristr($new_folder_path, '..') || stristr($new_folder_path, './') || stristr($new_folder_path, '\\')) {
MC 2575             $app->log('Folder path "'.$new_folder_path.'" contains .. or ./.', LOGLEVEL_DEBUG);
2023a7 2576             return false;
T 2577         }
b1a6a5 2578         if(stristr($old_folder_path, '..') || stristr($old_folder_path, './') || stristr($old_folder_path, '\\')) {
MC 2579             $app->log('Folder path "'.$old_folder_path.'" contains .. or ./.', LOGLEVEL_DEBUG);
2023a7 2580             return false;
T 2581         }
b1a6a5 2582
2023a7 2583         //* Check if the resulting path is inside the docroot
b1a6a5 2584         if(substr($old_folder_path, 0, strlen($website['document_root'])) != $website['document_root']) {
MC 2585             $app->log('Old folder path '.$old_folder_path.' is outside of docroot.', LOGLEVEL_DEBUG);
2023a7 2586             return false;
T 2587         }
b1a6a5 2588         if(substr($new_folder_path, 0, strlen($website['document_root'])) != $website['document_root']) {
MC 2589             $app->log('New folder path '.$new_folder_path.' is outside of docroot.', LOGLEVEL_DEBUG);
2023a7 2590             return false;
T 2591         }
b1a6a5 2592
2023a7 2593         //* Create the folder path, if it does not exist
c77103 2594         if(!is_dir($new_folder_path)) $app->system->mkdirpath($new_folder_path);
b1a6a5 2595
MC 2596         $begin_marker = '### ISPConfig folder protection begin ###';
2597         $end_marker = "### ISPConfig folder protection end ###\n\n";
2598
2023a7 2599         if($data['old']['path'] != $data['new']['path']) {
T 2600
b1a6a5 2601
2023a7 2602             //* move .htpasswd file
T 2603             if(is_file($old_folder_path.'.htpasswd')) {
b1a6a5 2604                 $app->system->rename($old_folder_path.'.htpasswd', $new_folder_path.'.htpasswd');
MC 2605                 $app->log('Moved file '.$old_folder_path.'.htpasswd to '.$new_folder_path.'.htpasswd', LOGLEVEL_DEBUG);
2023a7 2606             }
b1a6a5 2607
8ab3cd 2608             //* delete old .htaccess file
2023a7 2609             if(is_file($old_folder_path.'.htaccess')) {
b1a6a5 2610                 $ht_file = $app->system->file_get_contents($old_folder_path.'.htaccess');
MC 2611
2612                 if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $ht_file, $matches)) {
2613                     $ht_file = str_replace($matches[0], '', $ht_file);
2614                 } else {
2615                     $ht_file = str_replace("AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$old_folder_path.".htpasswd\nrequire valid-user", '', $ht_file);
2616                 }
2617
2618                 if(trim($ht_file) == '') {
2619                     $app->system->unlink($old_folder_path.'.htaccess');
2620                     $app->log('Removed file '.$old_folder_path.'.htaccess', LOGLEVEL_DEBUG);
2621                 } else {
2622                     $app->system->file_put_contents($old_folder_path.'.htaccess', $ht_file);
2623                     $app->log('Removed protection content from file '.$old_folder_path.'.htaccess', LOGLEVEL_DEBUG);
2624                 }
2023a7 2625             }
b1a6a5 2626
2023a7 2627         }
b1a6a5 2628
2023a7 2629         //* Create the .htaccess file
8ab3cd 2630         if($data['new']['active'] == 'y') {
b1a6a5 2631             $ht_file = $begin_marker."\nAuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$new_folder_path.".htpasswd\nrequire valid-user\n".$end_marker;
MC 2632
2633             if(file_exists($new_folder_path.'.htaccess')) {
2634                 $old_content = $app->system->file_get_contents($new_folder_path.'.htaccess');
2635
2636                 if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $old_content, $matches)) {
2637                     $ht_file = str_replace($matches[0], $ht_file, $old_content);
2638                 } else {
2639                     $ht_file .= $old_content;
2640                 }
2641             }
2642
2643             $app->system->file_put_contents($new_folder_path.'.htaccess', $ht_file);
51910d 2644             $app->system->chmod($new_folder_path.'.htaccess', 0751);
b1a6a5 2645             $app->system->chown($new_folder_path.'.htaccess', $website['system_user']);
MC 2646             $app->system->chgrp($new_folder_path.'.htaccess', $website['system_group']);
2647             $app->log('Created/modified file '.$new_folder_path.'.htaccess', LOGLEVEL_DEBUG);
8433d0 2648             
TB 2649             //* Create empty .htpasswd file, if it does not exist
2650             if(!is_file($folder_path.'.htpasswd')) {
2651                 $app->system->touch($new_folder_path.'.htpasswd');
51910d 2652                 $app->system->chmod($new_folder_path.'.htpasswd', 0751);
8433d0 2653                 $app->system->chown($new_folder_path.'.htpasswd', $website['system_user']);
TB 2654                 $app->system->chgrp($new_folder_path.'.htpasswd', $website['system_group']);
2655                 $app->log('Created file '.$new_folder_path.'.htpasswd', LOGLEVEL_DEBUG);
2656             }
2023a7 2657         }
b1a6a5 2658
2023a7 2659         //* Remove .htaccess file
T 2660         if($data['new']['active'] == 'n' && is_file($new_folder_path.'.htaccess')) {
b1a6a5 2661             $ht_file = $app->system->file_get_contents($new_folder_path.'.htaccess');
MC 2662
2663             if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $ht_file, $matches)) {
2664                 $ht_file = str_replace($matches[0], '', $ht_file);
2665             } else {
2666                 $ht_file = str_replace("AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$new_folder_path.".htpasswd\nrequire valid-user", '', $ht_file);
2667             }
2668
2669             if(trim($ht_file) == '') {
2670                 $app->system->unlink($new_folder_path.'.htaccess');
2671                 $app->log('Removed file '.$new_folder_path.'.htaccess', LOGLEVEL_DEBUG);
2672             } else {
2673                 $app->system->file_put_contents($new_folder_path.'.htaccess', $ht_file);
2674                 $app->log('Removed protection content from file '.$new_folder_path.'.htaccess', LOGLEVEL_DEBUG);
2675             }
2023a7 2676         }
b1a6a5 2677
MC 2678
524077 2679     }
b1a6a5 2680
MC 2681     public function ftp_user_delete($event_name, $data) {
26c0fc 2682         global $app, $conf;
b1a6a5 2683
26c0fc 2684         $ftpquota_file = $data['old']['dir'].'/.ftpquota';
c77103 2685         if(file_exists($ftpquota_file)) $app->system->unlink($ftpquota_file);
b1a6a5 2686
26c0fc 2687     }
b1a6a5 2688
MC 2689
ac933e 2690
V 2691     /**
2692      * This function is called when a Webdav-User is inserted, updated or deleted.
2693      *
2694      * @author Oliver Vogel
2695      * @param string $event_name
2696      * @param array $data
2697      */
b1a6a5 2698     public function webdav($event_name, $data) {
ac933e 2699         global $app, $conf;
b1a6a5 2700
52a04e 2701         /*
T 2702          * load the server configuration options
2703         */
fb3339 2704         $app->uses('getconf');
J 2705         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
ac933e 2706
V 2707         if (($event_name == 'webdav_user_insert') || ($event_name == 'webdav_user_update')) {
2708
2709             /*
2710              * Get additional informations
2711             */
2af58c 2712             $sitedata = $app->db->queryOneRecord('SELECT document_root, domain, system_user, system_group FROM web_domain WHERE domain_id = ?', $data['new']['parent_domain_id']);
ac933e 2713             $documentRoot = $sitedata['document_root'];
V 2714             $domain = $sitedata['domain'];
ca14fe 2715             $user = $sitedata['system_user'];
V 2716             $group = $sitedata['system_group'];
b67344 2717             $webdav_user_dir = $documentRoot . '/webdav/' . $data['new']['dir'];
ac933e 2718
V 2719             /* Check if this is a chrooted setup */
2720             if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
2721                 $apache_chrooted = true;
b1a6a5 2722                 $app->log('Info: Apache is chrooted.', LOGLEVEL_DEBUG);
ac933e 2723             } else {
V 2724                 $apache_chrooted = false;
2725             }
b1a6a5 2726
b67344 2727             //* We dont want to have relative paths here
b1a6a5 2728             if(stristr($webdav_user_dir, '..')  || stristr($webdav_user_dir, './')) {
MC 2729                 $app->log('Folder path '.$webdav_user_dir.' contains ./ or .. '.$documentRoot, LOGLEVEL_WARN);
b67344 2730                 return false;
T 2731             }
b1a6a5 2732
b67344 2733             //* Check if the resulting path exists if yes, if it is inside the docroot
b1a6a5 2734             if(is_dir($webdav_user_dir) && substr(realpath($webdav_user_dir), 0, strlen($documentRoot)) != $documentRoot) {
MC 2735                 $app->log('Folder path '.$webdav_user_dir.' is outside of docroot '.$documentRoot, LOGLEVEL_WARN);
b67344 2736                 return false;
T 2737             }
ac933e 2738
V 2739             /*
2740              * First the webdav-root - folder has to exist
2741             */
b67344 2742             if(!is_dir($webdav_user_dir)) {
b1a6a5 2743                 $app->log('Webdav User directory '.$webdav_user_dir.' does not exist. Creating it now.', LOGLEVEL_DEBUG);
c77103 2744                 $app->system->mkdirpath($webdav_user_dir);
ac933e 2745             }
V 2746
2747             /*
ca14fe 2748              * The webdav - Root needs the group/user as owner and the apache as read and write
ac933e 2749             */
c77103 2750             //$this->_exec('chown ' . $user . ':' . $group . ' ' . escapeshellcmd($documentRoot . '/webdav/'));
T 2751             //$this->_exec('chmod 770 ' . escapeshellcmd($documentRoot . '/webdav/'));
b1a6a5 2752             $app->system->chown($documentRoot . '/webdav', $user);
MC 2753             $app->system->chgrp($documentRoot . '/webdav', $group);
2754             $app->system->chmod($documentRoot . '/webdav', 0770);
ac933e 2755
V 2756             /*
ca14fe 2757              * The webdav folder (not the webdav-root!) needs the same (not in ONE step, because the
V 2758              * pwd-files are owned by root)
ac933e 2759             */
c77103 2760             //$this->_exec('chown ' . $user . ':' . $group . ' ' . escapeshellcmd($webdav_user_dir.' -R'));
T 2761             //$this->_exec('chmod 770 ' . escapeshellcmd($webdav_user_dir.' -R'));
b1a6a5 2762             $app->system->chown($webdav_user_dir, $user);
MC 2763             $app->system->chgrp($webdav_user_dir, $group);
2764             $app->system->chmod($webdav_user_dir, 0770);
ca14fe 2765
V 2766             /*
2767              * if the user is active, we have to write/update the password - file
2768              * if the user is inactive, we have to inactivate the user by removing the user from the file
2769             */
2770             if ($data['new']['active'] == 'y') {
b67344 2771                 $this->_writeHtDigestFile( $webdav_user_dir . '.htdigest', $data['new']['username'], $data['new']['dir'], $data['new']['password']);
ca14fe 2772             }
V 2773             else {
2774                 /* empty pwd removes the user! */
b67344 2775                 $this->_writeHtDigestFile( $webdav_user_dir . '.htdigest', $data['new']['username'], $data['new']['dir'], '');
ca14fe 2776             }
ac933e 2777
V 2778             /*
2779              * Next step, patch the vhost - file
2780             */
fb3339 2781             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'] . '/' . $domain . '.vhost');
ac933e 2782             $this->_patchVhostWebdav($vhost_file, $documentRoot . '/webdav');
ca14fe 2783
ac933e 2784             /*
V 2785              * Last, restart apache
2786             */
2787             if($apache_chrooted) {
b1a6a5 2788                 $app->services->restartServiceDelayed('httpd', 'restart');
ac933e 2789             } else {
V 2790                 // request a httpd reload when all records have been processed
b1a6a5 2791                 $app->services->restartServiceDelayed('httpd', 'reload');
ac933e 2792             }
V 2793
2794         }
2795
2796         if ($event_name == 'webdav_user_delete') {
2797             /*
2798              * Get additional informations
2799             */
2af58c 2800             $sitedata = $app->db->queryOneRecord('SELECT document_root, domain FROM web_domain WHERE domain_id = ?', $data['old']['parent_domain_id']);
ac933e 2801             $documentRoot = $sitedata['document_root'];
52a04e 2802             $domain = $sitedata['domain'];
ac933e 2803
V 2804             /*
2805              * We dont't want to destroy any (transfer)-Data. So we do NOT delete any dir.
2806              * So the only thing, we have to do, is to delete the user from the password-file
ca14fe 2807             */
ac933e 2808             $this->_writeHtDigestFile( $documentRoot . '/webdav/' . $data['old']['dir'] . '.htdigest', $data['old']['username'], $data['old']['dir'], '');
b1a6a5 2809
52a04e 2810             /*
T 2811              * Next step, patch the vhost - file
2812             */
fb3339 2813             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'] . '/' . $domain . '.vhost');
52a04e 2814             $this->_patchVhostWebdav($vhost_file, $documentRoot . '/webdav');
b1a6a5 2815
52a04e 2816             /*
T 2817              * Last, restart apache
2818             */
2819             if($apache_chrooted) {
b1a6a5 2820                 $app->services->restartServiceDelayed('httpd', 'restart');
52a04e 2821             } else {
T 2822                 // request a httpd reload when all records have been processed
b1a6a5 2823                 $app->services->restartServiceDelayed('httpd', 'reload');
52a04e 2824             }
ac933e 2825         }
V 2826     }
2827
2828
2829     /**
2830      * This function writes the htdigest - files used by webdav and digest
ca14fe 2831      * more info: see http://riceball.com/d/node/424
ac933e 2832      * @author Oliver Vogel
V 2833      * @param string $filename The name of the digest-file
2834      * @param string $username The name of the webdav-user
2835      * @param string $authname The name of the realm
ca14fe 2836      * @param string $pwd      The password-hash of the user
ac933e 2837      */
ca14fe 2838     private function _writeHtDigestFile($filename, $username, $authname, $pwdhash ) {
4bd960 2839         global $app;
b1a6a5 2840
ac933e 2841         $changed = false;
c77103 2842         if(is_file($filename) && !is_link($filename)) {
0ff3f1 2843             $in = fopen($filename, 'r');
T 2844             $output = '';
2845             /*
2846             * read line by line and search for the username and authname
2847             */
2848             while (preg_match("/:/", $line = fgets($in))) {
2849                 $line = rtrim($line);
2850                 $tmp = explode(':', $line);
2851                 if ($tmp[0] == $username && $tmp[1] == $authname) {
2852                     /*
2853                     * found the user. delete or change it?
2854                     */
2855                     if ($pwdhash != '') {
2856                         $output .= $tmp[0] . ':' . $tmp[1] . ':' . $pwdhash . "\n";
b1a6a5 2857                     }
0ff3f1 2858                     $changed = true;
T 2859                 }
2860                 else {
2861                     $output .= $line . "\n";
2862                 }
ac933e 2863             }
0ff3f1 2864             fclose($in);
ac933e 2865         }
V 2866         /*
2867          * if we didn't change anything, we have to add the new user at the end of the file
2868         */
2869         if (!$changed) {
f17dab 2870             $output .= $username . ':' . $authname . ':' . $pwdhash . "\n";
ac933e 2871         }
b1a6a5 2872
ac933e 2873
V 2874         /*
2875          * Now lets write the new file
2876         */
52a04e 2877         if(trim($output) == '') {
c77103 2878             $app->system->unlink($filename);
52a04e 2879         } else {
c77103 2880             $app->system->file_put_contents($filename, $output);
52a04e 2881         }
ac933e 2882     }
V 2883
2884     /**
2885      * This function patches the vhost-file and adds all webdav - user.
2886      * This function is written, because the creation of the vhost - file is sophisticated and
2887      * i don't want to make it more "heavy" by also adding this code too...
2888      * @author Oliver Vogel
2889      * @param string $fileName The Name of the .vhost-File (path included)
2890      * @param string $webdavRoot The root of the webdav-folder
2891      */
2892     private function _patchVhostWebdav($fileName, $webdavRoot) {
c77103 2893         global $app;
ac933e 2894         $in = fopen($fileName, 'r');
V 2895         $output = '';
2896         $inWebdavSection = false;
2897
2898         /*
2899          * read line by line and search for the username and authname
2900         */
2901         while ($line = fgets($in)) {
2902             /*
2903              *  is the "replace-comment" found...
2904             */
2905             if (trim($line) == '# WEBDAV BEGIN') {
2906                 /*
2907                  * The begin of the webdav - section is found, so ignore all lines til the end  is found
2908                 */
2909                 $inWebdavSection = true;
2910
2911                 $output .= "      # WEBDAV BEGIN\n";
2912
2913                 /*
2914                  * add all the webdav-dirs to the webdav-section
2915                 */
fb3a98 2916                 $files = @scandir($webdavRoot);
T 2917                 if(is_array($files)) {
b1a6a5 2918                     foreach($files as $file) {
MC 2919                         if (substr($file, strlen($file) - strlen('.htdigest')) == '.htdigest' && preg_match("/^[a-zA-Z0-9\-_\.]*$/", $file)) {
2920                             /*
ac933e 2921                          * found a htdigest - file, so add it to webdav
V 2922                         */
b1a6a5 2923                             $fn = substr($file, 0, strlen($file) - strlen('.htdigest'));
MC 2924                             $output .= "\n";
2925                             // $output .= "      Alias /" . $fn . ' ' . $webdavRoot . '/' . $fn . "\n";
2926                             // $output .= "      <Location /" . $fn . ">\n";
2927                             $output .= "      Alias /webdav/" . $fn . ' ' . $webdavRoot . '/' . $fn . "\n";
2928                             $output .= "      <Location /webdav/" . $fn . ">\n";
2929                             $output .= "        DAV On\n";
2930                             $output .= '        BrowserMatch "MSIE" AuthDigestEnableQueryStringHack=On'."\n";
2931                             $output .= "        AuthType Digest\n";
2932                             $output .= "        AuthName \"" . $fn . "\"\n";
2933                             $output .= "        AuthUserFile " . $webdavRoot . '/' . $file . "\n";
2934                             $output .= "        Require valid-user \n";
2935                             $output .= "        Options +Indexes \n";
2936                             $output .= "        Order allow,deny \n";
2937                             $output .= "        Allow from all \n";
2938                             $output .= "      </Location> \n";
2939                         }
ac933e 2940                     }
fb3a98 2941                 }
ac933e 2942             }
V 2943             /*
2944              *  is the "replace-comment-end" found...
2945             */
2946             if (trim($line) == '# WEBDAV END') {
2947                 /*
2948                  * The end of the webdav - section is found, so stop ignoring
2949                 */
2950                 $inWebdavSection = false;
2951             }
2952
2953             /*
2954              * Write the line to the output, if it is not in the section
2955             */
2956             if (!$inWebdavSection) {
2957                 $output .= $line;
2958             }
2959         }
2960         fclose($in);
2961
2962         /*
2963          * Now lets write the new file
2964         */
c77103 2965         $app->system->file_put_contents($fileName, $output);
ac933e 2966
V 2967     }
b1a6a5 2968
58c210 2969     //* Update the awstats configuration file
b1a6a5 2970     private function awstats_update ($data, $web_config) {
58c210 2971         global $app;
b1a6a5 2972
MC 2973         $web_folder = $data['new']['web_folder'];
2974         if($data['new']['type'] == 'vhost') $web_folder = 'web';
2a6eac 2975         $awstats_conf_dir = $web_config['awstats_conf_dir'];
b1a6a5 2976
6fb93d 2977         if(!is_dir($data['new']['document_root']."/" . $web_folder . "/stats/")) mkdir($data['new']['document_root']."/" . $web_folder . "/stats");
fb3339 2978         if(!@is_file($awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf') || ($data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain'])) {
J 2979             if ( @is_file($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf') ) {
c77103 2980                 $app->system->unlink($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf');
58c210 2981             }
b1a6a5 2982
58c210 2983             $content = '';
e6abfe 2984             if (is_file($awstats_conf_dir."/awstats.conf")) {
CS 2985                 $include_file = $awstats_conf_dir."/awstats.conf";
2986             } elseif (is_file($awstats_conf_dir."/awstats.model.conf")) {
2987                 $include_file = $awstats_conf_dir."/awstats.model.conf";
2988             }
de6d2e 2989             $content .= "Include \"".$include_file."\"\n";
fb3339 2990             $content .= "LogFile=\"/var/log/ispconfig/httpd/".$data['new']['domain']."/access.log\"\n";
J 2991             $content .= "SiteDomain=\"".$data['new']['domain']."\"\n";
2992             $content .= "HostAliases=\"www.".$data['new']['domain']."  localhost 127.0.0.1\"\n";
b1a6a5 2993
9aaf97 2994             if (isset($include_file)) {
CS 2995                 $app->system->file_put_contents($awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf', $content);
2996                 $app->log('Created AWStats config file: '.$awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf', LOGLEVEL_DEBUG);
2997             } else {
2998                 $app->log("No awstats base config found. Either awstats.conf or awstats.model.conf must exist in ".$awstats_conf_dir.".", LOGLEVEL_WARN);
2999             }
58c210 3000         }
b1a6a5 3001
6fb93d 3002         if(is_file($data['new']['document_root']."/" . $web_folder . "/stats/index.html")) $app->system->unlink($data['new']['document_root']."/" . $web_folder . "/stats/index.html");
a464e1 3003         if(file_exists("/usr/local/ispconfig/server/conf-custom/awstats_index.php.master")) {
b1a6a5 3004             $app->system->copy("/usr/local/ispconfig/server/conf-custom/awstats_index.php.master", $data['new']['document_root']."/" . $web_folder . "/stats/index.php");
a464e1 3005         } else {
b1a6a5 3006             $app->system->copy("/usr/local/ispconfig/server/conf/awstats_index.php.master", $data['new']['document_root']."/" . $web_folder . "/stats/index.php");
a464e1 3007         }
58c210 3008     }
b1a6a5 3009
58c210 3010     //* Delete the awstats configuration file
b1a6a5 3011     private function awstats_delete ($data, $web_config) {
58c210 3012         global $app;
b1a6a5 3013
58c210 3014         $awstats_conf_dir = $web_config['awstats_conf_dir'];
b1a6a5 3015
fb3339 3016         if ( @is_file($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf') ) {
c77103 3017             $app->system->unlink($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf');
b1a6a5 3018             $app->log('Removed AWStats config file: '.$awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf', LOGLEVEL_DEBUG);
58c210 3019         }
T 3020     }
b1a6a5 3021
c59632 3022     private function hhvm_update($data, $web_config) {
MC 3023         global $app, $conf;
3024         
3025         if(file_exists($conf['rootpath'] . '/conf-custom/hhvm_starter.master')) {
3026             $content = file_get_contents($conf['rootpath'] . '/conf-custom/hhvm_starter.master');
3027         } else {
3028             $content = file_get_contents($conf['rootpath'] . '/conf/hhvm_starter.master');
3029         }
cab08c 3030         if(file_exists($conf['rootpath'] . '/conf-custom/hhvm_monit.master')) {
MC 3031             $monit_content = file_get_contents($conf['rootpath'] . '/conf-custom/hhvm_monit.master');
3032         } else {
3033             $monit_content = file_get_contents($conf['rootpath'] . '/conf/hhvm_monit.master');
3034         }
c59632 3035         
d22277 3036         if($data['new']['php'] == 'hhvm' && $data['old']['php'] != 'hhvm' || (isset($data['old']['custom_php_ini']) && $data['new']['custom_php_ini'] != $data['old']['custom_php_ini'])) {
d5f2d5 3037         
MC 3038             // Custom php.ini settings
3039             $custom_php_ini_settings = trim($data['new']['custom_php_ini']);
3040             if(intval($data['new']['directive_snippets_id']) > 0){
d22277 3041                 $snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'apache' AND active = 'y' AND customer_viewable = 'y'", intval($data['new']['directive_snippets_id']));
d5f2d5 3042                 if(isset($snippet['required_php_snippets']) && trim($snippet['required_php_snippets']) != ''){
MC 3043                     $required_php_snippets = explode(',', trim($snippet['required_php_snippets']));
3044                     if(is_array($required_php_snippets) && !empty($required_php_snippets)){
3045                         foreach($required_php_snippets as $required_php_snippet){
3046                             $required_php_snippet = intval($required_php_snippet);
3047                             if($required_php_snippet > 0){
d22277 3048                                 $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 3049                                 $php_snippet['snippet'] = trim($php_snippet['snippet']);
MC 3050                                 if($php_snippet['snippet'] != ''){
3051                                     $custom_php_ini_settings .= "\n".$php_snippet['snippet'];
3052                                 }
3053                             }
3054                         }
3055                     }
3056                 }
3057             }
3058             if($custom_php_ini_settings != ''){
3059                 // Make sure we only have Unix linebreaks
3060                 $custom_php_ini_settings = str_replace("\r\n", "\n", $custom_php_ini_settings);
3061                 $custom_php_ini_settings = str_replace("\r", "\n", $custom_php_ini_settings);
3062                 file_put_contents('/etc/hhvm/'.$data['new']['system_user'].'.ini', $custom_php_ini_settings);
3063             } else {
d22277 3064                 if($data['old']['system_user'] != '' && is_file('/etc/hhvm/'.$data['old']['system_user'].'.ini')) unlink('/etc/hhvm/'.$data['old']['system_user'].'.ini');
d5f2d5 3065             }
MC 3066             
1c6da3 3067             $content = str_replace('{SYSTEM_USER}', $data['new']['system_user'], $content);
c59632 3068             file_put_contents('/etc/init.d/hhvm_' . $data['new']['system_user'], $content);
MC 3069             exec('chmod +x /etc/init.d/hhvm_' . $data['new']['system_user'] . ' >/dev/null 2>&1');
3070             exec('/usr/sbin/update-rc.d hhvm_' . $data['new']['system_user'] . ' defaults >/dev/null 2>&1');
02e7ea 3071             exec('/etc/init.d/hhvm_' . $data['new']['system_user'] . ' restart >/dev/null 2>&1');
cab08c 3072             
02e7ea 3073             if(is_dir('/etc/monit/conf.d')){
MC 3074                 $monit_content = str_replace('{SYSTEM_USER}', $data['new']['system_user'], $monit_content);
3075                 file_put_contents('/etc/monit/conf.d/00-hhvm_' . $data['new']['system_user'], $monit_content);
3076                 if(is_file('/etc/monit/conf.d/hhvm_' . $data['new']['system_user'])) unlink('/etc/monit/conf.d/hhvm_' . $data['new']['system_user']);
3077                 exec('/etc/init.d/monit restart >/dev/null 2>&1');
3078             }
cab08c 3079             
c59632 3080          } elseif($data['new']['php'] != 'hhvm' && $data['old']['php'] == 'hhvm') {
d22277 3081             if($data['old']['system_user'] != ''){
MB 3082                 exec('/etc/init.d/hhvm_' . $data['old']['system_user'] . ' stop >/dev/null 2>&1');
3083                 exec('/usr/sbin/update-rc.d hhvm_' . $data['old']['system_user'] . ' remove >/dev/null 2>&1');
3084                 unlink('/etc/init.d/hhvm_' . $data['old']['system_user']);
3085                 if(is_file('/etc/hhvm/'.$data['old']['system_user'].'.ini')) unlink('/etc/hhvm/'.$data['old']['system_user'].'.ini');
3086             }
cab08c 3087             
02e7ea 3088             if(is_file('/etc/monit/conf.d/hhvm_' . $data['new']['system_user']) || is_file('/etc/monit/conf.d/00-hhvm_' . $data['new']['system_user'])){
MC 3089                 if(is_file('/etc/monit/conf.d/hhvm_' . $data['new']['system_user'])){
3090                     unlink('/etc/monit/conf.d/hhvm_' . $data['new']['system_user']);
3091                 }
3092                 if(is_file('/etc/monit/conf.d/00-hhvm_' . $data['new']['system_user'])){
3093                     unlink('/etc/monit/conf.d/00-hhvm_' . $data['new']['system_user']);
3094                 }
cab08c 3095                 exec('/etc/init.d/monit restart >/dev/null 2>&1');
MC 3096             }
c59632 3097         }
MC 3098     }
3099
274362 3100     //* Update the PHP-FPM pool configuration file
b1a6a5 3101     private function php_fpm_pool_update ($data, $web_config, $pool_dir, $pool_name, $socket_dir) {
274362 3102         global $app, $conf;
ab79c2 3103         $pool_dir = trim($pool_dir);
274362 3104         //$reload = false;
b1a6a5 3105
62e4b3 3106         if($data['new']['php'] == 'php-fpm'){
F 3107             if(trim($data['new']['fastcgi_php_version']) != ''){
3108                 $default_php_fpm = false;
3109                 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']));
b1a6a5 3110                 if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
62e4b3 3111             } else {
F 3112                 $default_php_fpm = true;
3113             }
274362 3114         } else {
62e4b3 3115             if(trim($data['old']['fastcgi_php_version']) != '' && $data['old']['php'] == 'php-fpm'){
F 3116                 $default_php_fpm = false;
3117                 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']));
b1a6a5 3118                 if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
62e4b3 3119             } else {
F 3120                 $default_php_fpm = true;
3121             }
274362 3122         }
b1a6a5 3123
274362 3124         $app->uses("getconf");
F 3125         $web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
b1a6a5 3126
274362 3127         if($data['new']['php'] != 'php-fpm'){
F 3128             if(@is_file($pool_dir.$pool_name.'.conf')){
c77103 3129                 $app->system->unlink($pool_dir.$pool_name.'.conf');
274362 3130                 //$reload = true;
F 3131             }
3132             if($data['old']['php'] == 'php-fpm'){
3133                 if(!$default_php_fpm){
b1a6a5 3134                     $app->services->restartService('php-fpm', 'reload:'.$custom_php_fpm_init_script);
274362 3135                 } else {
b1a6a5 3136                     $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 3137                 }
F 3138             }
3139             //if($reload == true) $app->services->restartService('php-fpm','reload');
3140             return;
3141         }
b1a6a5 3142
274362 3143         $app->load('tpl');
F 3144         $tpl = new tpl();
3145         $tpl->newTemplate('php_fpm_pool.conf.master');
8133de 3146         $tpl->setVar('apache_version', $app->system->getapacheversion());
MC 3147         
c91c7a 3148         $apache_modules = $app->system->getapachemodules();
TB 3149         
6db036 3150         // Use sockets, but not with apache 2.4 on centos (mod_proxy_fcgi) as socket support is buggy in that version
TB 3151         if($data['new']['php_fpm_use_socket'] == 'y' && in_array('fastcgi_module',$apache_modules)){
274362 3152             $use_tcp = 0;
F 3153             $use_socket = 1;
c77103 3154             if(!is_dir($socket_dir)) $app->system->mkdirpath($socket_dir);
274362 3155         } else {
F 3156             $use_tcp = 1;
3157             $use_socket = 0;
3158         }
3159         $tpl->setVar('use_tcp', $use_tcp);
3160         $tpl->setVar('use_socket', $use_socket);
b1a6a5 3161
274362 3162         $fpm_socket = $socket_dir.$pool_name.'.sock';
F 3163         $tpl->setVar('fpm_socket', $fpm_socket);
b491ad 3164         $tpl->setVar('fpm_listen_mode', '0660');
b1a6a5 3165
274362 3166         $tpl->setVar('fpm_pool', $pool_name);
F 3167         $tpl->setVar('fpm_port', $web_config['php_fpm_start_port'] + $data['new']['domain_id'] - 1);
3168         $tpl->setVar('fpm_user', $data['new']['system_user']);
0dfb2d 3169         $tpl->setVar('fpm_group', $web_config['group']);
d33fd2 3170         $tpl->setVar('fpm_domain', $data['new']['domain']);
dd7ce4 3171         $tpl->setVar('pm', $data['new']['pm']);
274362 3172         $tpl->setVar('pm_max_children', $data['new']['pm_max_children']);
F 3173         $tpl->setVar('pm_start_servers', $data['new']['pm_start_servers']);
3174         $tpl->setVar('pm_min_spare_servers', $data['new']['pm_min_spare_servers']);
3175         $tpl->setVar('pm_max_spare_servers', $data['new']['pm_max_spare_servers']);
dd7ce4 3176         $tpl->setVar('pm_process_idle_timeout', $data['new']['pm_process_idle_timeout']);
F 3177         $tpl->setVar('pm_max_requests', $data['new']['pm_max_requests']);
274362 3178         $tpl->setVar('document_root', $data['new']['document_root']);
b1a6a5 3179         $tpl->setVar('security_level', $web_config['security_level']);
f63910 3180         $tpl->setVar('domain', $data['new']['domain']);
274362 3181         $php_open_basedir = ($data['new']['php_open_basedir'] == '')?escapeshellcmd($data['new']['document_root']):escapeshellcmd($data['new']['php_open_basedir']);
F 3182         $tpl->setVar('php_open_basedir', $php_open_basedir);
3183         if($php_open_basedir != ''){
3184             $tpl->setVar('enable_php_open_basedir', '');
3185         } else {
3186             $tpl->setVar('enable_php_open_basedir', ';');
3187         }
b1a6a5 3188
274362 3189         // Custom php.ini settings
F 3190         $final_php_ini_settings = array();
3191         $custom_php_ini_settings = trim($data['new']['custom_php_ini']);
b41803 3192         
MC 3193         if(intval($data['new']['directive_snippets_id']) > 0){
3194             $snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'apache' AND active = 'y' AND customer_viewable = 'y'", intval($data['new']['directive_snippets_id']));
3195             if(isset($snippet['required_php_snippets']) && trim($snippet['required_php_snippets']) != ''){
3196                 $required_php_snippets = explode(',', trim($snippet['required_php_snippets']));
3197                 if(is_array($required_php_snippets) && !empty($required_php_snippets)){
3198                     foreach($required_php_snippets as $required_php_snippet){
3199                         $required_php_snippet = intval($required_php_snippet);
3200                         if($required_php_snippet > 0){
d22277 3201                             $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 3202                             $php_snippet['snippet'] = trim($php_snippet['snippet']);
MC 3203                             if($php_snippet['snippet'] != ''){
3204                                 $custom_php_ini_settings .= "\n".$php_snippet['snippet'];
3205                             }
3206                         }
3207                     }
3208                 }
3209             }
3210         }
3211         
9fd930 3212         $custom_session_save_path = false;
274362 3213         if($custom_php_ini_settings != ''){
F 3214             // Make sure we only have Unix linebreaks
3215             $custom_php_ini_settings = str_replace("\r\n", "\n", $custom_php_ini_settings);
3216             $custom_php_ini_settings = str_replace("\r", "\n", $custom_php_ini_settings);
3217             $ini_settings = explode("\n", $custom_php_ini_settings);
3218             if(is_array($ini_settings) && !empty($ini_settings)){
3219                 foreach($ini_settings as $ini_setting){
254a4a 3220                     $ini_setting = trim($ini_setting);
b1a6a5 3221                     if(substr($ini_setting, 0, 1) == ';') continue;
MC 3222                     if(substr($ini_setting, 0, 1) == '#') continue;
3223                     if(substr($ini_setting, 0, 2) == '//') continue;
03cc01 3224                     list($key, $value) = explode('=', $ini_setting, 2);
1d6097 3225                     $value = trim($value);
FT 3226                     if($value != ''){
254a4a 3227                         $key = trim($key);
9fd930 3228                         if($key == 'session.save_path') $custom_session_save_path = true;
254a4a 3229                         switch (strtolower($value)) {
b1a6a5 3230                         case '0':
MC 3231                             // PHP-FPM might complain about invalid boolean value if you use 0
3232                             $value = 'off';
3233                         case '1':
3234                         case 'on':
3235                         case 'off':
3236                         case 'true':
3237                         case 'false':
3238                         case 'yes':
3239                         case 'no':
3240                             $final_php_ini_settings[] = array('ini_setting' => 'php_admin_flag['.$key.'] = '.$value);
3241                             break;
3242                         default:
3243                             $final_php_ini_settings[] = array('ini_setting' => 'php_admin_value['.$key.'] = '.$value);
274362 3244                         }
254a4a 3245                     }
274362 3246                 }
F 3247             }
3248         }
9fd930 3249         
MB 3250         $tpl->setVar('custom_session_save_path', ($custom_session_save_path ? 'y' : 'n'));
3251         
274362 3252         $tpl->setLoop('custom_php_ini_settings', $final_php_ini_settings);
b1a6a5 3253
MC 3254         $app->system->file_put_contents($pool_dir.$pool_name.'.conf', $tpl->grab());
3255         $app->log('Writing the PHP-FPM config file: '.$pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
274362 3256         unset($tpl);
b1a6a5 3257
274362 3258         // delete pool in all other PHP versions
ab79c2 3259         $default_pool_dir = trim(escapeshellcmd($web_config['php_fpm_pool_dir']));
b1a6a5 3260         if(substr($default_pool_dir, -1) != '/') $default_pool_dir .= '/';
274362 3261         if($default_pool_dir != $pool_dir){
F 3262             if ( @is_file($default_pool_dir.$pool_name.'.conf') ) {
b1a6a5 3263                 $app->system->unlink($default_pool_dir.$pool_name.'.conf');
MC 3264                 $app->log('Removed PHP-FPM config file: '.$default_pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
3265                 $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 3266             }
F 3267         }
2af58c 3268         $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"]);
274362 3269         if(is_array($php_versions) && !empty($php_versions)){
F 3270             foreach($php_versions as $php_version){
ab79c2 3271                 $php_version['php_fpm_pool_dir'] = trim($php_version['php_fpm_pool_dir']);
b1a6a5 3272                 if(substr($php_version['php_fpm_pool_dir'], -1) != '/') $php_version['php_fpm_pool_dir'] .= '/';
274362 3273                 if($php_version['php_fpm_pool_dir'] != $pool_dir){
F 3274                     if ( @is_file($php_version['php_fpm_pool_dir'].$pool_name.'.conf') ) {
c77103 3275                         $app->system->unlink($php_version['php_fpm_pool_dir'].$pool_name.'.conf');
b1a6a5 3276                         $app->log('Removed PHP-FPM config file: '.$php_version['php_fpm_pool_dir'].$pool_name.'.conf', LOGLEVEL_DEBUG);
MC 3277                         $app->services->restartService('php-fpm', 'reload:'.$php_version['php_fpm_init_script']);
274362 3278                     }
F 3279                 }
3280             }
3281         }
3282         // Reload current PHP-FPM after all others
3283         sleep(1);
3284         if(!$default_php_fpm){
b1a6a5 3285             $app->services->restartService('php-fpm', 'reload:'.$custom_php_fpm_init_script);
274362 3286         } else {
b1a6a5 3287             $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 3288         }
b1a6a5 3289
274362 3290         //$reload = true;
F 3291
3292         //if($reload == true) $app->services->restartService('php-fpm','reload');
3293     }
b1a6a5 3294
274362 3295     //* Delete the PHP-FPM pool configuration file
b1a6a5 3296     private function php_fpm_pool_delete ($data, $web_config) {
274362 3297         global $app, $conf;
b1a6a5 3298
62e4b3 3299         if(trim($data['old']['fastcgi_php_version']) != '' && $data['old']['php'] == 'php-fpm'){
274362 3300             $default_php_fpm = false;
F 3301             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']));
b1a6a5 3302             if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
274362 3303         } else {
F 3304             $default_php_fpm = true;
3305         }
b1a6a5 3306
274362 3307         if($default_php_fpm){
F 3308             $pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
3309         } else {
3310             $pool_dir = $custom_php_fpm_pool_dir;
3311         }
ab79c2 3312         $pool_dir = trim($pool_dir);
b1a6a5 3313
MC 3314         if(substr($pool_dir, -1) != '/') $pool_dir .= '/';
274362 3315         $pool_name = 'web'.$data['old']['domain_id'];
b1a6a5 3316
274362 3317         if ( @is_file($pool_dir.$pool_name.'.conf') ) {
c77103 3318             $app->system->unlink($pool_dir.$pool_name.'.conf');
b1a6a5 3319             $app->log('Removed PHP-FPM config file: '.$pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
MC 3320
274362 3321             //$app->services->restartService('php-fpm','reload');
F 3322         }
b1a6a5 3323
274362 3324         // delete pool in all other PHP versions
ab79c2 3325         $default_pool_dir = trim(escapeshellcmd($web_config['php_fpm_pool_dir']));
b1a6a5 3326         if(substr($default_pool_dir, -1) != '/') $default_pool_dir .= '/';
274362 3327         if($default_pool_dir != $pool_dir){
F 3328             if ( @is_file($default_pool_dir.$pool_name.'.conf') ) {
b1a6a5 3329                 $app->system->unlink($default_pool_dir.$pool_name.'.conf');
MC 3330                 $app->log('Removed PHP-FPM config file: '.$default_pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
3331                 $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 3332             }
b1a6a5 3333         }
2af58c 3334         $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']);
274362 3335         if(is_array($php_versions) && !empty($php_versions)){
F 3336             foreach($php_versions as $php_version){
ab79c2 3337                 $php_version['php_fpm_pool_dir'] = trim($php_version['php_fpm_pool_dir']);
b1a6a5 3338                 if(substr($php_version['php_fpm_pool_dir'], -1) != '/') $php_version['php_fpm_pool_dir'] .= '/';
274362 3339                 if($php_version['php_fpm_pool_dir'] != $pool_dir){
F 3340                     if ( @is_file($php_version['php_fpm_pool_dir'].$pool_name.'.conf') ) {
c77103 3341                         $app->system->unlink($php_version['php_fpm_pool_dir'].$pool_name.'.conf');
b1a6a5 3342                         $app->log('Removed PHP-FPM config file: '.$php_version['php_fpm_pool_dir'].$pool_name.'.conf', LOGLEVEL_DEBUG);
MC 3343                         $app->services->restartService('php-fpm', 'reload:'.$php_version['php_fpm_init_script']);
274362 3344                     }
F 3345                 }
3346             }
3347         }
b1a6a5 3348
274362 3349         // Reload current PHP-FPM after all others
F 3350         sleep(1);
3351         if(!$default_php_fpm){
b1a6a5 3352             $app->services->restartService('php-fpm', 'reload:'.$custom_php_fpm_init_script);
274362 3353         } else {
b1a6a5 3354             $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 3355         }
F 3356     }
b1a6a5 3357
MC 3358     function client_delete($event_name, $data) {
1ca823 3359         global $app, $conf;
b1a6a5 3360
1ca823 3361         $app->uses("getconf");
T 3362         $web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
b1a6a5 3363
1ca823 3364         $client_id = intval($data['old']['client_id']);
T 3365         if($client_id > 0) {
b1a6a5 3366
1ca823 3367             $client_dir = $web_config['website_basedir'].'/clients/client'.$client_id;
b1a6a5 3368             if(is_dir($client_dir) && !stristr($client_dir, '..')) {
72695f 3369                 // remove symlinks from $client_dir
b1a6a5 3370                 $files = array_diff(scandir($client_dir), array('.', '..'));
72695f 3371                 if(is_array($files) && !empty($files)){
T 3372                     foreach($files as $file){
3373                         if(is_link($client_dir.'/'.$file)){
3374                             unlink($client_dir.'/'.$file);
b1a6a5 3375                             $app->log('Removed symlink: '.$client_dir.'/'.$file, LOGLEVEL_DEBUG);
72695f 3376                         }
T 3377                     }
3378                 }
b1a6a5 3379
1ca823 3380                 @rmdir($client_dir);
b1a6a5 3381                 $app->log('Removed client directory: '.$client_dir, LOGLEVEL_DEBUG);
1ca823 3382             }
b1a6a5 3383
615a0a 3384             if($app->system->is_group('client'.$client_id)){
T 3385                 $this->_exec('groupdel client'.$client_id);
b1a6a5 3386                 $app->log('Removed group client'.$client_id, LOGLEVEL_DEBUG);
615a0a 3387             }
1ca823 3388         }
b1a6a5 3389
1ca823 3390     }
ac933e 3391
1c40af 3392     //* Wrapper for exec function for easier debugging
T 3393     private function _exec($command) {
3394         global $app;
551d9a 3395         $out = array();
MB 3396         $ret = 0;
b1a6a5 3397         $app->log('exec: '.$command, LOGLEVEL_DEBUG);
551d9a 3398         exec($command, $out, $ret);
MB 3399         if($ret != 0) return false;
3400         else return true;
1c40af 3401     }
7ed741 3402
b1a6a5 3403     private function _checkTcp ($host, $port) {
MC 3404
3405         $fp = @fsockopen($host, $port, $errno, $errstr, 2);
7ed741 3406
T 3407         if ($fp) {
3408             fclose($fp);
3409             return true;
3410         } else {
3411             return false;
3412         }
3413     }
ac933e 3414
552178 3415     public function create_relative_link($f, $t) {
bfcdef 3416         global $app;
b1a6a5 3417
552178 3418         // $from already exists
M 3419         $from = realpath($f);
3420
3421         // realpath requires the traced file to exist - so, lets touch it first, then remove
c77103 3422         @$app->system->unlink($t); touch($t);
552178 3423         $to = realpath($t);
c77103 3424         @$app->system->unlink($t);
552178 3425
M 3426         // Remove from the left side matching path elements from $from and $to
3427         // and get path elements counts
3428         $a1 = explode('/', $from); $a2 = explode('/', $to);
3429         for ($c = 0; $a1[$c] == $a2[$c]; $c++) {
3430             unset($a1[$c]); unset($a2[$c]);
3431         }
3432         $cfrom = implode('/', $a1);
3433
3434         // Check if a path is fully a subpath of another - no way to create symlink in the case
3435         if (count($a1) == 0 || count($a2) == 0) return false;
3436
3437         // Add ($cnt_to-1) number of "../" elements to left side of $cfrom
3438         for ($c = 0; $c < (count($a2)-1); $c++) { $cfrom = '../'.$cfrom; }
3439
3440         return symlink($cfrom, $to);
3441     }
46c683 3442
b1a6a5 3443     private function _rewrite_quote($string) {
MC 3444         return str_replace(array('.', '*', '?', '+'), array('\\.', '\\*', '\\?', '\\+'), $string);
3445     }
3446
3447     private function _is_url($string) {
3448         return preg_match('/^(f|ht)tp(s)?:\/\//i', $string);
3449     }
3450
bfcdef 3451     private function get_seo_redirects($web, $prefix = ''){
T 3452         $seo_redirects = array();
b1a6a5 3453
bfcdef 3454         if(substr($web['domain'], 0, 2) === '*.') $web['subdomain'] = '*';
b1a6a5 3455
bfcdef 3456         if($web['subdomain'] == 'www' || $web['subdomain'] == '*'){
T 3457             if($web['seo_redirect'] == 'non_www_to_www'){
3458                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = str_replace('.', '\.', $web['domain']);
3459                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = 'www.'.$web['domain'];
3460                 $seo_redirects[$prefix.'seo_redirect_operator'] = '';
3461             }
3462             if($web['seo_redirect'] == '*_domain_tld_to_www_domain_tld'){
3463                 // ^(example\.com|(?!\bwww\b)\.example\.com)$
3464                 // ^(example\.com|((?:\w+(?:-\w+)*\.)*)((?!www\.)\w+(?:-\w+)*)(\.example\.com))$
3465                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = '('.str_replace('.', '\.', $web['domain']).'|((?:\w+(?:-\w+)*\.)*)((?!www\.)\w+(?:-\w+)*)(\.'.str_replace('.', '\.', $web['domain']).'))';
3466                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = 'www.'.$web['domain'];
3467                 $seo_redirects[$prefix.'seo_redirect_operator'] = '';
3468             }
3469             if($web['seo_redirect'] == '*_to_www_domain_tld'){
3470                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = 'www\.'.str_replace('.', '\.', $web['domain']);
3471                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = 'www.'.$web['domain'];
3472                 $seo_redirects[$prefix.'seo_redirect_operator'] = '!';
3473             }
3474         }
3475         if($web['seo_redirect'] == 'www_to_non_www'){
3476             $seo_redirects[$prefix.'seo_redirect_origin_domain'] = 'www\.'.str_replace('.', '\.', $web['domain']);
3477             $seo_redirects[$prefix.'seo_redirect_target_domain'] = $web['domain'];
3478             $seo_redirects[$prefix.'seo_redirect_operator'] = '';
3479         }
3480         if($web['seo_redirect'] == '*_domain_tld_to_domain_tld'){
3481             // ^(.+)\.example\.com$
3482             $seo_redirects[$prefix.'seo_redirect_origin_domain'] = '(.+)\.'.str_replace('.', '\.', $web['domain']);
3483             $seo_redirects[$prefix.'seo_redirect_target_domain'] = $web['domain'];
3484             $seo_redirects[$prefix.'seo_redirect_operator'] = '';
3485         }
3486         if($web['seo_redirect'] == '*_to_domain_tld'){
3487             $seo_redirects[$prefix.'seo_redirect_origin_domain'] = str_replace('.', '\.', $web['domain']);
3488             $seo_redirects[$prefix.'seo_redirect_target_domain'] = $web['domain'];
3489             $seo_redirects[$prefix.'seo_redirect_operator'] = '!';
3490         }
3491         return $seo_redirects;
3492     }
b1a6a5 3493
46c683 3494 } // end class
T 3495
c09f04 3496 ?>