Till Brehm
2016-07-24 b9a3ef486ebcde18a5ade37865ff8f397185d24f
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
e74390 891           if ( in_array($file_system , array('ext2','ext3','ext4','simfs','reiserfs'), 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
8a1f4c 1192             if(substr($domain,0,4) != 'www.' && ($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'];
8a1f4c 1210                     if(isset($aliasdomain['subdomain']) && substr($aliasdomain['domain'],0,4) != 'www.' && ($aliasdomain['subdomain'] == "www" OR $aliasdomain['subdomain'] == "*")) {
8c93e1 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);
8a1f4c 1237                 $app->log("Let's Encrypt SSL Cert domains: $lddomain", LOGLEVEL_DEBUG);
551d9a 1238                 
MB 1239                 $success = false;
312ab0 1240                 $letsencrypt = explode("\n", shell_exec('which letsencrypt certbot /root/.local/share/letsencrypt/bin/letsencrypt'));
MB 1241                 $letsencrypt = reset($letsencrypt);
190275 1242                 if(is_executable($letsencrypt)) {
cae251 1243                     $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 1244                 }
551d9a 1245                 if(!$success) {
MB 1246                     // error issuing cert
1247                     $app->log('Let\'s Encrypt SSL Cert for: ' . $domain . ' could not be issued.', LOGLEVEL_WARN);
1248                     $data['new']['ssl_letsencrypt'] = 'n';
1249                     if($data['old']['ssl'] == 'n') $data['new']['ssl'] = 'n';
1250                     /* Update the DB of the (local) Server */
1251                     $app->db->query("UPDATE web_domain SET `ssl` = ?, `ssl_letsencrypt` = ? WHERE `domain` = ?", $data['new']['ssl'], 'n', $data['new']['domain']);
1252                     /* Update also the master-DB of the Server-Farm */
1253                     $app->dbmaster->query("UPDATE web_domain SET `ssl` = ?, `ssl_letsencrypt` = ? WHERE `domain` = ?", $data['new']['ssl'], 'n', $data['new']['domain']);
1254                 }
a49635 1255             //}
018c55 1256
a20ec4 1257             //* check is been correctly created
MB 1258             if(file_exists($crt_tmp_file) OR file_exists($key_tmp_file)) {
1259                 $date = date("YmdHis");
1260                 if(is_file($key_file)) {
1261                     $app->system->copy($key_file, $key_file.'.old'.$date);
1262                     $app->system->chmod($key_file.'.old.'.$date, 0400);
1263                     $app->system->unlink($key_file);
1264                 }
1265
1266                 if ($web_config["website_symlinks_rel"] == 'y') {
1267                     $this->create_relative_link(escapeshellcmd($key_tmp_file), escapeshellcmd($key_file));
1268                 } else {
1269                     exec("ln -s ".escapeshellcmd($key_tmp_file)." ".escapeshellcmd($key_file));
1270                 }
1271
1272                 if(is_file($crt_file)) {
1273                     $app->system->copy($crt_file, $crt_file.'.old.'.$date);
1274                     $app->system->chmod($crt_file.'.old.'.$date, 0400);
1275                     $app->system->unlink($crt_file);
1276                 }
1277
1278                 if($web_config["website_symlinks_rel"] == 'y') {
1279                     $this->create_relative_link(escapeshellcmd($crt_tmp_file), escapeshellcmd($crt_file));
1280                 } else {
1281                     exec("ln -s ".escapeshellcmd($crt_tmp_file)." ".escapeshellcmd($crt_file));
1282                 }
1283
1284                 if(is_file($bundle_file)) {
1285                     $app->system->copy($bundle_file, $bundle_file.'.old.'.$date);
1286                     $app->system->chmod($bundle_file.'.old.'.$date, 0400);
1287                     $app->system->unlink($bundle_file);
1288                 }
1289
1290                 if($web_config["website_symlinks_rel"] == 'y') {
1291                     $this->create_relative_link(escapeshellcmd($bundle_tmp_file), escapeshellcmd($bundle_file));
1292                 } else {
1293                     exec("ln -s ".escapeshellcmd($bundle_tmp_file)." ".escapeshellcmd($bundle_file));
1294                 }
1295
1296                 /* we don't need to store it.
1297                 /* Update the DB of the (local) Server */
551d9a 1298                 $app->db->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '', ssl_key = '' WHERE domain = ?", $data['new']['domain']);
MB 1299                 $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
a20ec4 1300                 /* Update also the master-DB of the Server-Farm */
551d9a 1301                 $app->dbmaster->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '', ssl_key = '' WHERE domain = ?", $data['new']['domain']);
MB 1302                 $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
a20ec4 1303             }
MB 1304         }
1305
46c683 1306         if(@is_file($bundle_file)) $vhost_data['has_bundle_cert'] = 1;
ac933e 1307
6fb93d 1308         //$vhost_data['document_root'] = $data['new']['document_root'].'/' . $web_folder;
b1a6a5 1309
e64fbb 1310         // Set SEO Redirect
bfcdef 1311         if($data['new']['seo_redirect'] != ''){
e64fbb 1312             $vhost_data['seo_redirect_enabled'] = 1;
bfcdef 1313             $tmp_seo_redirects = $this->get_seo_redirects($data['new']);
T 1314             if(is_array($tmp_seo_redirects) && !empty($tmp_seo_redirects)){
1315                 foreach($tmp_seo_redirects as $key => $val){
1316                     $vhost_data[$key] = $val;
1317                 }
1318             } else {
1319                 $vhost_data['seo_redirect_enabled'] = 0;
e64fbb 1320             }
F 1321         } else {
1322             $vhost_data['seo_redirect_enabled'] = 0;
1323         }
b1a6a5 1324
46c683 1325         $tpl->setVar($vhost_data);
8133de 1326         $tpl->setVar('apache_version', $app->system->getapacheversion());
ac933e 1327
46c683 1328         // Rewrite rules
T 1329         $rewrite_rules = array();
a639ee 1330         $rewrite_wildcard_rules = array();
02bf99 1331         if($data['new']['redirect_type'] != '' && $data['new']['redirect_path'] != '') {
b1a6a5 1332             if(substr($data['new']['redirect_path'], -1) != '/' && !preg_match('/^(https?|\[scheme\]):\/\//', $data['new']['redirect_path'])) $data['new']['redirect_path'] .= '/';
MC 1333             if(substr($data['new']['redirect_path'], 0, 8) == '[scheme]'){
1334                 $rewrite_target = 'http'.substr($data['new']['redirect_path'], 8);
1335                 $rewrite_target_ssl = 'https'.substr($data['new']['redirect_path'], 8);
45ee67 1336             } else {
F 1337                 $rewrite_target = $data['new']['redirect_path'];
1338                 $rewrite_target_ssl = $data['new']['redirect_path'];
1339             }
bc2c3e 1340             /* Disabled path extension
fb3339 1341             if($data['new']['redirect_type'] == 'no' && substr($data['new']['redirect_path'],0,4) != 'http') {
J 1342                 $data['new']['redirect_path'] = $data['new']['document_root'].'/web'.realpath($data['new']['redirect_path']).'/';
8388ae 1343             }
bc2c3e 1344             */
ac933e 1345
fb3339 1346             switch($data['new']['subdomain']) {
b1a6a5 1347             case 'www':
MC 1348                 $rewrite_rules[] = array( 'rewrite_domain'  => '^'.$this->_rewrite_quote($data['new']['domain']),
1349                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
1350                     'rewrite_target'  => $rewrite_target,
1351                     'rewrite_target_ssl' => $rewrite_target_ssl,
1352                     'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1353                     'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1354                 $rewrite_rules[] = array( 'rewrite_domain'  => '^' . $this->_rewrite_quote('www.'.$data['new']['domain']),
1355                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
1356                     'rewrite_target'  => $rewrite_target,
1357                     'rewrite_target_ssl' => $rewrite_target_ssl,
1358                     'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1359                     'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1360                 break;
1361             case '*':
a639ee 1362                 $rewrite_wildcard_rules[] = array( 'rewrite_domain'  => '(^|\.)'.$this->_rewrite_quote($data['new']['domain']),
b1a6a5 1363                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
MC 1364                     'rewrite_target'  => $rewrite_target,
1365                     'rewrite_target_ssl' => $rewrite_target_ssl,
1366                     'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1367                     'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1368                 break;
1369             default:
1370                 $rewrite_rules[] = array( 'rewrite_domain'  => '^'.$this->_rewrite_quote($data['new']['domain']),
1371                     'rewrite_type'   => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
1372                     'rewrite_target'  => $rewrite_target,
1373                     'rewrite_target_ssl' => $rewrite_target_ssl,
1374                     'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1375                     'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
ac933e 1376             }
46c683 1377         }
b1a6a5 1378
3501f9 1379         $server_alias = array();
b1a6a5 1380
3501f9 1381         // get autoalias
M 1382         $auto_alias = $web_config['website_autoalias'];
1383         if($auto_alias != '') {
1384             // get the client username
2af58c 1385             $client = $app->db->queryOneRecord("SELECT `username` FROM `client` WHERE `client_id` = ?", $client_id);
3501f9 1386             $aa_search = array('[client_id]', '[website_id]', '[client_username]', '[website_domain]');
M 1387             $aa_replace = array($client_id, $data['new']['domain_id'], $client['username'], $data['new']['domain']);
1388             $auto_alias = str_replace($aa_search, $aa_replace, $auto_alias);
1389             unset($client);
1390             unset($aa_search);
1391             unset($aa_replace);
cece69 1392             $server_alias[] .= $auto_alias.' ';
3501f9 1393         }
b1a6a5 1394
46c683 1395         // get alias domains (co-domains and subdomains)
2af58c 1396         $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 1397         $alias_seo_redirects = array();
fb3339 1398         switch($data['new']['subdomain']) {
b1a6a5 1399         case 'www':
MC 1400             $server_alias[] .= 'www.'.$data['new']['domain'].' ';
1401             break;
1402         case '*':
1403             $server_alias[] .= '*.'.$data['new']['domain'].' ';
1404             break;
ac933e 1405         }
46c683 1406         if(is_array($aliases)) {
T 1407             foreach($aliases as $alias) {
fb3339 1408                 switch($alias['subdomain']) {
b1a6a5 1409                 case 'www':
MC 1410                     $server_alias[] .= 'www.'.$alias['domain'].' '.$alias['domain'].' ';
1411                     break;
1412                 case '*':
1413                     $server_alias[] .= '*.'.$alias['domain'].' '.$alias['domain'].' ';
1414                     break;
1415                 default:
1416                     $server_alias[] .= $alias['domain'].' ';
1417                     break;
ac933e 1418                 }
b1a6a5 1419                 $app->log('Add server alias: '.$alias['domain'], LOGLEVEL_DEBUG);
MC 1420
bfcdef 1421                 // Add SEO redirects for alias domains
T 1422                 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'))){
1423                     $tmp_seo_redirects = $this->get_seo_redirects($alias, 'alias_');
1424                     if(is_array($tmp_seo_redirects) && !empty($tmp_seo_redirects)){
1425                         $alias_seo_redirects[] = $tmp_seo_redirects;
1426                     }
1427                 }
b1a6a5 1428
46c683 1429                 // Rewriting
02bf99 1430                 if($alias['redirect_type'] != '' && $alias['redirect_path'] != '') {
b1a6a5 1431                     if(substr($alias['redirect_path'], -1) != '/' && !preg_match('/^(https?|\[scheme\]):\/\//', $alias['redirect_path'])) $alias['redirect_path'] .= '/';
MC 1432                     if(substr($alias['redirect_path'], 0, 8) == '[scheme]'){
1433                         $rewrite_target = 'http'.substr($alias['redirect_path'], 8);
1434                         $rewrite_target_ssl = 'https'.substr($alias['redirect_path'], 8);
e64fbb 1435                     } else {
F 1436                         $rewrite_target = $alias['redirect_path'];
1437                         $rewrite_target_ssl = $alias['redirect_path'];
1438                     }
bc2c3e 1439                     /* Disabled the path extension
fb3339 1440                     if($data['new']['redirect_type'] == 'no' && substr($data['new']['redirect_path'],0,4) != 'http') {
J 1441                         $data['new']['redirect_path'] = $data['new']['document_root'].'/web'.realpath($data['new']['redirect_path']).'/';
8388ae 1442                     }
bc2c3e 1443                     */
b1a6a5 1444
fb3339 1445                     switch($alias['subdomain']) {
b1a6a5 1446                     case 'www':
MC 1447                         $rewrite_rules[] = array( 'rewrite_domain'  => '^'.$this->_rewrite_quote($alias['domain']),
1448                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
1449                             'rewrite_target'  => $rewrite_target,
1450                             'rewrite_target_ssl' => $rewrite_target_ssl,
1451                             'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1452                             'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1453                         $rewrite_rules[] = array( 'rewrite_domain'  => '^' . $this->_rewrite_quote('www.'.$alias['domain']),
1454                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
1455                             'rewrite_target'  => $rewrite_target,
1456                             'rewrite_target_ssl' => $rewrite_target_ssl,
1457                             'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1458                             'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1459                         break;
1460                     case '*':
a639ee 1461                         $rewrite_wildcard_rules[] = array( 'rewrite_domain'  => '(^|\.)'.$this->_rewrite_quote($alias['domain']),
b1a6a5 1462                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
MC 1463                             'rewrite_target'  => $rewrite_target,
1464                             'rewrite_target_ssl' => $rewrite_target_ssl,
1465                             'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1466                             'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
1467                         break;
1468                     default:
1469                         if(substr($alias['domain'], 0, 2) === '*.') $domain_rule = '(^|\.)'.$this->_rewrite_quote(substr($alias['domain'], 2));
1470                         else $domain_rule = '^'.$this->_rewrite_quote($alias['domain']);
1471                         $rewrite_rules[] = array( 'rewrite_domain'  => $domain_rule,
1472                             'rewrite_type'   => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
1473                             'rewrite_target'  => $rewrite_target,
1474                             'rewrite_target_ssl' => $rewrite_target_ssl,
1475                             'rewrite_is_url'    => ($this->_is_url($rewrite_target) ? 'y' : 'n'),
1476                             'rewrite_add_path' => (substr($rewrite_target, -1) == '/' ? 'y' : 'n'));
ac933e 1477                     }
46c683 1478                 }
T 1479             }
1480         }
ac933e 1481
47cca9 1482         //* If we have some alias records
T 1483         if(count($server_alias) > 0) {
1484             $server_alias_str = '';
1485             $n = 0;
ac933e 1486
47cca9 1487             // begin a new ServerAlias line after 30 alias domains
T 1488             foreach($server_alias as $tmp_alias) {
1489                 if($n % 30 == 0) $server_alias_str .= "\n    ServerAlias ";
1490                 $server_alias_str .= $tmp_alias;
1491             }
1492             unset($tmp_alias);
ac933e 1493
b1a6a5 1494             $tpl->setVar('alias', trim($server_alias_str));
47cca9 1495         } else {
b1a6a5 1496             $tpl->setVar('alias', '');
47cca9 1497         }
a639ee 1498         
D 1499         if (count($rewrite_wildcard_rules) > 0) $rewrite_rules = array_merge($rewrite_rules, $rewrite_wildcard_rules); // Append wildcard rules to the end of rules
ac933e 1500
3ad844 1501         if(count($rewrite_rules) > 0 || $vhost_data['seo_redirect_enabled'] > 0 || count($alias_seo_redirects) > 0 || $data['new']['rewrite_to_https'] == 'y') {
b1a6a5 1502             $tpl->setVar('rewrite_enabled', 1);
46c683 1503         } else {
b1a6a5 1504             $tpl->setVar('rewrite_enabled', 0);
bfcdef 1505         }
8ab3cd 1506
T 1507         //$tpl->setLoop('redirects',$rewrite_rules);
ac933e 1508
V 1509         /**
1510          * install fast-cgi starter script and add script aliasd config
46c683 1511          * first we create the script directory if not already created, then copy over the starter script
T 1512          * settings are copied over from the server ini config for now
1513          * TODO: Create form for fastcgi configs per site.
1514          */
ac933e 1515
b1a6a5 1516
fb3339 1517         if ($data['new']['php'] == 'fast-cgi') {
ac933e 1518
b1a6a5 1519             $fastcgi_starter_path = str_replace('[system_user]', $data['new']['system_user'], $fastcgi_config['fastcgi_starter_path']);
MC 1520             $fastcgi_starter_path = str_replace('[client_id]', $client_id, $fastcgi_starter_path);
ac933e 1521
V 1522             if (!is_dir($fastcgi_starter_path)) {
c77103 1523                 $app->system->mkdirpath($fastcgi_starter_path);
fb3339 1524                 //exec('chown '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.escapeshellcmd($fastcgi_starter_path));
ac933e 1525
V 1526
b1a6a5 1527                 $app->log('Creating fastcgi starter script directory: '.$fastcgi_starter_path, LOGLEVEL_DEBUG);
46c683 1528             }
ac933e 1529
c77103 1530             //exec('chown -R '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.escapeshellcmd($fastcgi_starter_path));
b1a6a5 1531             $app->system->chown($fastcgi_starter_path, $data['new']['system_user']);
MC 1532             $app->system->chgrp($fastcgi_starter_path, $data['new']['system_group']);
1533
46c683 1534             $fcgi_tpl = new tpl();
fb3339 1535             $fcgi_tpl->newTemplate('php-fcgi-starter.master');
8133de 1536             $fcgi_tpl->setVar('apache_version', $app->system->getapacheversion());
b1a6a5 1537
62b385 1538             // Support for multiple PHP versions (FastCGI)
F 1539             if(trim($data['new']['fastcgi_php_version']) != ''){
1540                 $default_fastcgi_php = false;
b1a6a5 1541                 if(substr($custom_fastcgi_php_ini_dir, -1) != '/') $custom_fastcgi_php_ini_dir .= '/';
62b385 1542             } else {
F 1543                 $default_fastcgi_php = true;
1544             }
b1a6a5 1545
7fddfe 1546             if($has_custom_php_ini) {
b1a6a5 1547                 $fcgi_tpl->setVar('php_ini_path', escapeshellcmd($custom_php_ini_dir));
7fddfe 1548             } else {
62b385 1549                 if($default_fastcgi_php){
b1a6a5 1550                     $fcgi_tpl->setVar('php_ini_path', escapeshellcmd($fastcgi_config['fastcgi_phpini_path']));
62b385 1551                 } else {
b1a6a5 1552                     $fcgi_tpl->setVar('php_ini_path', escapeshellcmd($custom_fastcgi_php_ini_dir));
62b385 1553                 }
7fddfe 1554             }
b1a6a5 1555             $fcgi_tpl->setVar('document_root', escapeshellcmd($data['new']['document_root']));
MC 1556             $fcgi_tpl->setVar('php_fcgi_children', escapeshellcmd($fastcgi_config['fastcgi_children']));
1557             $fcgi_tpl->setVar('php_fcgi_max_requests', escapeshellcmd($fastcgi_config['fastcgi_max_requests']));
62b385 1558             if($default_fastcgi_php){
b1a6a5 1559                 $fcgi_tpl->setVar('php_fcgi_bin', escapeshellcmd($fastcgi_config['fastcgi_bin']));
62b385 1560             } else {
b1a6a5 1561                 $fcgi_tpl->setVar('php_fcgi_bin', escapeshellcmd($custom_fastcgi_php_executable));
62b385 1562             }
b1a6a5 1563             $fcgi_tpl->setVar('security_level', intval($web_config['security_level']));
f63910 1564             $fcgi_tpl->setVar('domain', escapeshellcmd($data['new']['domain']));
ac933e 1565
fb3339 1566             $php_open_basedir = ($data['new']['php_open_basedir'] == '')?$data['new']['document_root']:$data['new']['php_open_basedir'];
ff7075 1567             $fcgi_tpl->setVar('open_basedir', escapeshellcmd($php_open_basedir));
ac933e 1568
511ba5 1569             $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 1570             $app->system->file_put_contents($fcgi_starter_script, $fcgi_tpl->grab());
46c683 1571             unset($fcgi_tpl);
ac933e 1572
b1a6a5 1573             $app->log('Creating fastcgi starter script: '.$fcgi_starter_script, LOGLEVEL_DEBUG);
ac933e 1574
b1a6a5 1575             $app->system->chmod($fcgi_starter_script, 0755);
MC 1576             $app->system->chown($fcgi_starter_script, $data['new']['system_user']);
1577             $app->system->chgrp($fcgi_starter_script, $data['new']['system_group']);
1578
1579             $tpl->setVar('fastcgi_alias', $fastcgi_config['fastcgi_alias']);
1580             $tpl->setVar('fastcgi_starter_path', $fastcgi_starter_path);
511ba5 1581             $tpl->setVar('fastcgi_starter_script', $fastcgi_config['fastcgi_starter_script'].(($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') ? '_web' . $data['new']['domain_id'] : ''));
b1a6a5 1582             $tpl->setVar('fastcgi_config_syntax', $fastcgi_config['fastcgi_config_syntax']);
MC 1583             $tpl->setVar('fastcgi_max_requests', $fastcgi_config['fastcgi_max_requests']);
ac933e 1584
62e4b3 1585         } else {
F 1586             //remove the php fastgi starter script if available
b5b862 1587             $fastcgi_starter_script = $fastcgi_config['fastcgi_starter_script'].($data['old']['type'] == 'vhostsubdomain' ? '_web' . $data['old']['domain_id'] : '');
62e4b3 1588             if ($data['old']['php'] == 'fast-cgi') {
b1a6a5 1589                 $fastcgi_starter_path = str_replace('[system_user]', $data['old']['system_user'], $fastcgi_config['fastcgi_starter_path']);
MC 1590                 $fastcgi_starter_path = str_replace('[client_id]', $client_id, $fastcgi_starter_path);
1591                 if($data['old']['type'] == 'vhost') {
b5b862 1592                     if(is_file($fastcgi_starter_script)) @unlink($fastcgi_starter_script);
TB 1593                     if (is_dir($fastcgi_starter_path)) @rmdir($fastcgi_starter_path);
b1a6a5 1594                 } else {
b5b862 1595                     if(is_file($fastcgi_starter_script)) @unlink($fastcgi_starter_script);
b1a6a5 1596                 }
62e4b3 1597             }
46c683 1598         }
b1a6a5 1599
MC 1600
1601
274362 1602         /**
b1a6a5 1603          * PHP-FPM
MC 1604          */
274362 1605         // Support for multiple PHP versions
02e7ea 1606         if($data['new']['php'] == 'php-fpm'){
62e4b3 1607             if(trim($data['new']['fastcgi_php_version']) != ''){
F 1608                 $default_php_fpm = false;
1609                 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 1610                 if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
62e4b3 1611             } else {
F 1612                 $default_php_fpm = true;
1613             }
274362 1614         } else {
c59632 1615             if(trim($data['old']['fastcgi_php_version']) != '' && ($data['old']['php'] == 'php-fpm' || $data['old']['php'] == 'hhvm')){
62e4b3 1616                 $default_php_fpm = false;
F 1617                 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 1618                 if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
62e4b3 1619             } else {
F 1620                 $default_php_fpm = true;
1621             }
274362 1622         }
b1a6a5 1623
274362 1624         if($default_php_fpm){
F 1625             $pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
1626         } else {
1627             $pool_dir = $custom_php_fpm_pool_dir;
1628         }
ab79c2 1629         $pool_dir = trim($pool_dir);
b1a6a5 1630         if(substr($pool_dir, -1) != '/') $pool_dir .= '/';
274362 1631         $pool_name = 'web'.$data['new']['domain_id'];
F 1632         $socket_dir = escapeshellcmd($web_config['php_fpm_socket_dir']);
b1a6a5 1633         if(substr($socket_dir, -1) != '/') $socket_dir .= '/';
9b021b 1634         
1e67c1 1635         $apache_modules = $app->system->getapachemodules();
TB 1636         
1637         // Use sockets, but not with apache 2.4 on centos (mod_proxy_fcgi) as socket support is buggy in that version
1638         if($data['new']['php_fpm_use_socket'] == 'y' && in_array('fastcgi_module',$apache_modules)){
274362 1639             $use_tcp = 0;
F 1640             $use_socket = 1;
1641         } else {
1642             $use_tcp = 1;
1643             $use_socket = 0;
1644         }
1645         $tpl->setVar('use_tcp', $use_tcp);
1646         $tpl->setVar('use_socket', $use_socket);
1647         $fpm_socket = $socket_dir.$pool_name.'.sock';
1648         $tpl->setVar('fpm_socket', $fpm_socket);
1649         $tpl->setVar('fpm_port', $web_config['php_fpm_start_port'] + $data['new']['domain_id'] - 1);
ac933e 1650
46c683 1651         /**
T 1652          * install cgi starter script and add script alias to config.
1653          * This is needed to allow cgi with suexec (to do so, we need a bin in the document-path!)
1654          * first we create the script directory if not already created, then copy over the starter script.
1655          * TODO: we have to fetch the data from the server-settings.
1656          */
fb3339 1657         if ($data['new']['php'] == 'cgi') {
J 1658             //$cgi_config = $app->getconf->get_server_config($conf['server_id'], 'cgi');
46c683 1659
fb3339 1660             $cgi_config['cgi_starter_path'] = $web_config['website_basedir'].'/php-cgi-scripts/[system_user]/';
511ba5 1661             $cgi_config['cgi_starter_script'] = 'php-cgi-starter'.(($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') ? '_web' . $data['new']['domain_id'] : '');
fb3339 1662             $cgi_config['cgi_bin'] = '/usr/bin/php-cgi';
46c683 1663
b1a6a5 1664             $cgi_starter_path = str_replace('[system_user]', $data['new']['system_user'], $cgi_config['cgi_starter_path']);
MC 1665             $cgi_starter_path = str_replace('[client_id]', $client_id, $cgi_starter_path);
46c683 1666
ac933e 1667             if (!is_dir($cgi_starter_path)) {
c77103 1668                 $app->system->mkdirpath($cgi_starter_path);
b1a6a5 1669                 $app->system->chown($cgi_starter_path, $data['new']['system_user']);
MC 1670                 $app->system->chgrp($cgi_starter_path, $data['new']['system_group']);
1671                 $app->system->chmod($cgi_starter_path, 0755);
46c683 1672
b1a6a5 1673                 $app->log('Creating cgi starter script directory: '.$cgi_starter_path, LOGLEVEL_DEBUG);
46c683 1674             }
T 1675
1676             $cgi_tpl = new tpl();
fb3339 1677             $cgi_tpl->newTemplate('php-cgi-starter.master');
8133de 1678             $cgi_tpl->setVar('apache_version', $app->system->getapacheversion());
46c683 1679
fb3339 1680             // This works because PHP "rewrites" a symlink to the physical path
J 1681             $php_open_basedir = ($data['new']['php_open_basedir'] == '')?$data['new']['document_root']:$data['new']['php_open_basedir'];
ac933e 1682             $cgi_tpl->setVar('open_basedir', escapeshellcmd($php_open_basedir));
fb3339 1683             $cgi_tpl->setVar('document_root', escapeshellcmd($data['new']['document_root']));
ac933e 1684
46c683 1685             // This will NOT work!
fb3339 1686             //$cgi_tpl->setVar('open_basedir', '/var/www/' . $data['new']['domain']);
b1a6a5 1687             $cgi_tpl->setVar('php_cgi_bin', $cgi_config['cgi_bin']);
MC 1688             $cgi_tpl->setVar('security_level', $web_config['security_level']);
1689
1690             $cgi_tpl->setVar('has_custom_php_ini', $has_custom_php_ini);
7fddfe 1691             if($has_custom_php_ini) {
b1a6a5 1692                 $cgi_tpl->setVar('php_ini_path', escapeshellcmd($custom_php_ini_dir));
7fddfe 1693             } else {
b1a6a5 1694                 $cgi_tpl->setVar('php_ini_path', escapeshellcmd($fastcgi_config['fastcgi_phpini_path']));
7fddfe 1695             }
46c683 1696
511ba5 1697             $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 1698             $app->system->file_put_contents($cgi_starter_script, $cgi_tpl->grab());
46c683 1699             unset($cgi_tpl);
T 1700
b1a6a5 1701             $app->log('Creating cgi starter script: '.$cgi_starter_script, LOGLEVEL_DEBUG);
46c683 1702
T 1703
b1a6a5 1704             $app->system->chmod($cgi_starter_script, 0755);
MC 1705             $app->system->chown($cgi_starter_script, $data['new']['system_user']);
1706             $app->system->chgrp($cgi_starter_script, $data['new']['system_group']);
46c683 1707
b1a6a5 1708             $tpl->setVar('cgi_starter_path', $cgi_starter_path);
511ba5 1709             $tpl->setVar('cgi_starter_script', $cgi_config['cgi_starter_script'].(($data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias') ? '_web' . $data['new']['domain_id'] : ''));
46c683 1710
T 1711         }
1712
fb3339 1713         $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['new']['domain'].'.vhost');
7ed741 1714         //* Make a backup copy of vhost file
b1a6a5 1715         if(file_exists($vhost_file)) $app->system->copy($vhost_file, $vhost_file.'~');
MC 1716
a7bdf8 1717         //* create empty vhost array
T 1718         $vhosts = array();
b1a6a5 1719
526b99 1720         //* Add vhost for ipv4 IP
6c424f 1721
FS 1722         //* use ip-mapping for web-mirror
1723         if($data['new']['ip_address'] != '*' && $conf['mirror_server_id'] > 0) {
1724             $sql = "SELECT destination_ip FROM server_ip_map WHERE server_id = ? AND source_ip = ?";
1725             $newip = $app->db->queryOneRecord($sql, $conf['server_id'], $data['new']['ip_address']);
1726             $data['new']['ip_address'] = $newip['destination_ip'];
1727             unset($newip);
1728         }
1729
526b99 1730         $tmp_vhost_arr = array('ip_address' => $data['new']['ip_address'], 'ssl_enabled' => 0, 'port' => 80);
T 1731         if(count($rewrite_rules) > 0)  $tmp_vhost_arr = $tmp_vhost_arr + array('redirects' => $rewrite_rules);
1732         if(count($alias_seo_redirects) > 0) $tmp_vhost_arr = $tmp_vhost_arr + array('alias_seo_redirects' => $alias_seo_redirects);
1733         $vhosts[] = $tmp_vhost_arr;
1734         unset($tmp_vhost_arr);
b1a6a5 1735
a7bdf8 1736         //* Add vhost for ipv4 IP with SSL
481c00 1737         $ssl_dir = $data['new']['document_root'].'/ssl';
T 1738         $domain = $data['new']['ssl_domain'];
1739         $key_file = $ssl_dir.'/'.$domain.'.key';
1740         $crt_file = $ssl_dir.'/'.$domain.'.crt';
b1a6a5 1741
a7bdf8 1742         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 1743             $tmp_vhost_arr = array('ip_address' => $data['new']['ip_address'], 'ssl_enabled' => 1, 'port' => '443');
T 1744             if(count($rewrite_rules) > 0)  $tmp_vhost_arr = $tmp_vhost_arr + array('redirects' => $rewrite_rules);
cc6568 1745             $ipv4_ssl_alias_seo_redirects = $alias_seo_redirects;
H 1746             if(is_array($ipv4_ssl_alias_seo_redirects) && !empty($ipv4_ssl_alias_seo_redirects)){
1747                 for($i=0;$i<count($ipv4_ssl_alias_seo_redirects);$i++){
1748                     $ipv4_ssl_alias_seo_redirects[$i]['ssl_enabled'] = 1;
1749                 }
1750             }
1751             if(count($ipv4_ssl_alias_seo_redirects) > 0) $tmp_vhost_arr = $tmp_vhost_arr + array('alias_seo_redirects' => $ipv4_ssl_alias_seo_redirects);
526b99 1752             $vhosts[] = $tmp_vhost_arr;
cc6568 1753             unset($tmp_vhost_arr, $ipv4_ssl_alias_seo_redirects);
b1a6a5 1754             $app->log('Enable SSL for: '.$domain, LOGLEVEL_DEBUG);
bd68aa 1755         }
MC 1756
b1a6a5 1757         //* Add vhost for IPv6 IP
MC 1758         if($data['new']['ipv6_address'] != '') {
fbeb11 1759             //* rewrite ipv6 on mirrors
FS 1760             /* chang $conf to $web_config */
1761             if ($web_config['serverconfig']['web']['vhost_rewrite_v6'] == 'y') {
1762                 if (isset($web_config['serverconfig']['server']['v6_prefix']) && $web_config['serverconfig']['server']['v6_prefix'] <> '') {
1763                     $explode_v6prefix=explode(':', $web_config['serverconfig']['server']['v6_prefix']);
b1a6a5 1764                     $explode_v6=explode(':', $data['new']['ipv6_address']);
MC 1765
1766                     for ( $i = 0; $i <= count($explode_v6prefix)-3; $i++ ) {
1767                         $explode_v6[$i] = $explode_v6prefix[$i];
1768                     }
1769                     $data['new']['ipv6_address'] = implode(':', $explode_v6);
bd68aa 1770                 }
MC 1771             }
96f31d 1772             if($data['new']['ipv6_address'] == '*') $data['new']['ipv6_address'] = '::';
526b99 1773             $tmp_vhost_arr = array('ip_address' => '['.$data['new']['ipv6_address'].']', 'ssl_enabled' => 0, 'port' => 80);
T 1774             if(count($rewrite_rules) > 0)  $tmp_vhost_arr = $tmp_vhost_arr + array('redirects' => $rewrite_rules);
1775             if(count($alias_seo_redirects) > 0) $tmp_vhost_arr = $tmp_vhost_arr + array('alias_seo_redirects' => $alias_seo_redirects);
1776             $vhosts[] = $tmp_vhost_arr;
1777             unset($tmp_vhost_arr);
b1a6a5 1778
a7bdf8 1779             //* Add vhost for ipv6 IP with SSL
T 1780             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 1781                 $tmp_vhost_arr = array('ip_address' => '['.$data['new']['ipv6_address'].']', 'ssl_enabled' => 1, 'port' => '443');
T 1782                 if(count($rewrite_rules) > 0)  $tmp_vhost_arr = $tmp_vhost_arr + array('redirects' => $rewrite_rules);
cc6568 1783                 $ipv6_ssl_alias_seo_redirects = $alias_seo_redirects;
H 1784                 if(is_array($ipv6_ssl_alias_seo_redirects) && !empty($ipv6_ssl_alias_seo_redirects)){
1785                     for($i=0;$i<count($ipv6_ssl_alias_seo_redirects);$i++){
1786                         $ipv6_ssl_alias_seo_redirects[$i]['ssl_enabled'] = 1;
1787                     }
1788                 }
1789                 if(count($ipv6_ssl_alias_seo_redirects) > 0) $tmp_vhost_arr = $tmp_vhost_arr + array('alias_seo_redirects' => $ipv6_ssl_alias_seo_redirects);
526b99 1790                 $vhosts[] = $tmp_vhost_arr;
cc6568 1791                 unset($tmp_vhost_arr, $ipv6_ssl_alias_seo_redirects);
b1a6a5 1792                 $app->log('Enable SSL for IPv6: '.$domain, LOGLEVEL_DEBUG);
a7bdf8 1793             }
T 1794         }
b1a6a5 1795
a7bdf8 1796         //* Set the vhost loop
b1a6a5 1797         $tpl->setLoop('vhosts', $vhosts);
MC 1798
7ed741 1799         //* Write vhost file
b1a6a5 1800         $app->system->file_put_contents($vhost_file, $tpl->grab());
MC 1801         $app->log('Writing the vhost file: '.$vhost_file, LOGLEVEL_DEBUG);
46c683 1802         unset($tpl);
ac933e 1803
V 1804         /*
1805          * maybe we have some webdav - user. If so, add them...
1806         */
fb3339 1807         $this->_patchVhostWebdav($vhost_file, $data['new']['document_root'] . '/webdav');
ac933e 1808
c6a89c 1809         //* Set the symlink to enable the vhost
T 1810         //* First we check if there is a old type of symlink and remove it
fb3339 1811         $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['new']['domain'].'.vhost');
c77103 1812         if(is_link($vhost_symlink)) $app->system->unlink($vhost_symlink);
b1a6a5 1813
c6a89c 1814         //* Remove old or changed symlinks
T 1815         if($data['new']['subdomain'] != $data['old']['subdomain'] or $data['new']['active'] == 'n') {
1816             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['new']['domain'].'.vhost');
1817             if(is_link($vhost_symlink)) {
c77103 1818                 $app->system->unlink($vhost_symlink);
b1a6a5 1819                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
c6a89c 1820             }
T 1821             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['new']['domain'].'.vhost');
1822             if(is_link($vhost_symlink)) {
c77103 1823                 $app->system->unlink($vhost_symlink);
b1a6a5 1824                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
c6a89c 1825             }
T 1826         }
b1a6a5 1827
c6a89c 1828         //* New symlink
T 1829         if($data['new']['subdomain'] == '*') {
1830             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['new']['domain'].'.vhost');
1831         } else {
1832             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['new']['domain'].'.vhost');
1833         }
fb3339 1834         if($data['new']['active'] == 'y' && !is_link($vhost_symlink)) {
b1a6a5 1835             symlink($vhost_file, $vhost_symlink);
MC 1836             $app->log('Creating symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
46c683 1837         }
ac933e 1838
46c683 1839         // remove old symlink and vhost file, if domain name of the site has changed
fb3339 1840         if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
c6a89c 1841             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['old']['domain'].'.vhost');
T 1842             if(is_link($vhost_symlink)) {
c77103 1843                 $app->system->unlink($vhost_symlink);
b1a6a5 1844                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
c6a89c 1845             }
T 1846             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['old']['domain'].'.vhost');
1847             if(is_link($vhost_symlink)) {
c77103 1848                 $app->system->unlink($vhost_symlink);
b1a6a5 1849                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
c6a89c 1850             }
8cf78b 1851             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
T 1852             if(is_link($vhost_symlink)) {
c77103 1853                 $app->system->unlink($vhost_symlink);
b1a6a5 1854                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
8cf78b 1855             }
fb3339 1856             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
c77103 1857             $app->system->unlink($vhost_file);
b1a6a5 1858             $app->log('Removing file: '.$vhost_file, LOGLEVEL_DEBUG);
46c683 1859         }
ac933e 1860
46c683 1861         //* Create .htaccess and .htpasswd file for website statistics
cc6568 1862         //if(!is_file($data['new']['document_root'].'/' . $web_folder . '/stats/.htaccess') or $data['old']['document_root'] != $data['new']['document_root']) {
H 1863         if(!is_dir($data['new']['document_root'].'/' . $web_folder . '/stats')) $app->system->mkdir($data['new']['document_root'].'/' . $web_folder . '/stats');
1864         $ht_file = "AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$data['new']['document_root']."/web/stats/.htpasswd_stats\nrequire valid-user";
b1a6a5 1865         $app->system->file_put_contents($data['new']['document_root'].'/' . $web_folder . '/stats/.htaccess', $ht_file);
MC 1866         $app->system->chmod($data['new']['document_root'].'/' . $web_folder . '/stats/.htaccess', 0755);
cc6568 1867         unset($ht_file);
H 1868         //}
ac933e 1869
bfcdef 1870         if(!is_file($data['new']['document_root'].'/web/stats/.htpasswd_stats') || $data['new']['stats_password'] != $data['old']['stats_password']) {
fb3339 1871             if(trim($data['new']['stats_password']) != '') {
J 1872                 $htp_file = 'admin:'.trim($data['new']['stats_password']);
b1a6a5 1873                 $app->system->web_folder_protection($data['new']['document_root'], false);
MC 1874                 $app->system->file_put_contents($data['new']['document_root'].'/web/stats/.htpasswd_stats', $htp_file);
1875                 $app->system->web_folder_protection($data['new']['document_root'], true);
1876                 $app->system->chmod($data['new']['document_root'].'/web/stats/.htpasswd_stats', 0755);
46c683 1877                 unset($htp_file);
T 1878             }
1879         }
b1a6a5 1880
58c210 1881         //* Create awstats configuration
511ba5 1882         if($data['new']['stats_type'] == 'awstats' && ($data['new']['type'] == 'vhost' || $data['new']['type'] == 'vhostsubdomain' || $data['new']['type'] == 'vhostalias')) {
b1a6a5 1883             $this->awstats_update($data, $web_config);
58c210 1884         }
b1a6a5 1885
MC 1886         $this->php_fpm_pool_update($data, $web_config, $pool_dir, $pool_name, $socket_dir);
c59632 1887         $this->hhvm_update($data, $web_config);
b1a6a5 1888
7ed741 1889         if($web_config['check_apache_config'] == 'y') {
T 1890             //* Test if apache starts with the new configuration file
b1a6a5 1891             $apache_online_status_before_restart = $this->_checkTcp('localhost', 80);
MC 1892             $app->log('Apache status is: '.($apache_online_status_before_restart === true? 'running' : 'down'), LOGLEVEL_DEBUG);
ac933e 1893
b1a6a5 1894             $retval = $app->services->restartService('httpd', 'restart'); // $retval['retval'] is 0 on success and > 0 on failure
MC 1895             $app->log('Apache restart return value is: '.$retval['retval'], LOGLEVEL_DEBUG);
1896
9f56bd 1897             // wait a few seconds, before we test the apache status again
bfcdef 1898             $apache_online_status_after_restart = false;
9f56bd 1899             sleep(2);
bfcdef 1900             for($i = 0; $i < 5; $i++) {
b1a6a5 1901                 $apache_online_status_after_restart = $this->_checkTcp('localhost', 80);
bfcdef 1902                 if($apache_online_status_after_restart) break;
T 1903                 sleep(1);
1904             }
7ed741 1905             //* Check if apache restarted successfully if it was online before
b1a6a5 1906             $app->log('Apache online status after restart is: '.($apache_online_status_after_restart === true? 'running' : 'down'), LOGLEVEL_DEBUG);
615a0a 1907             if($apache_online_status_before_restart && !$apache_online_status_after_restart || $retval['retval'] > 0) {
b1a6a5 1908                 $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 1909                 if(is_array($retval['output']) && !empty($retval['output'])){
b1a6a5 1910                     $app->log('Reason for Apache restart failure: '.implode("\n", $retval['output']), LOGLEVEL_WARN);
7b47c0 1911                     $app->dbmaster->datalogError(implode("\n", $retval['output']));
615a0a 1912                 } else {
T 1913                     // if no output is given, check again
1914                     $webserver_binary = '';
7b47c0 1915                     exec('which apache2ctl', $webserver_check_output, $webserver_check_retval);
615a0a 1916                     if($webserver_check_retval == 0){
7b47c0 1917                         $webserver_binary = 'apache2ctl';
615a0a 1918                     } else {
T 1919                         unset($webserver_check_output, $webserver_check_retval);
7b47c0 1920                         exec('which apache2', $webserver_check_output, $webserver_check_retval);
615a0a 1921                         if($webserver_check_retval == 0){
7b47c0 1922                             $webserver_binary = 'apache2';
615a0a 1923                         } else {
T 1924                             unset($webserver_check_output, $webserver_check_retval);
7b47c0 1925                             exec('which httpd2', $webserver_check_output, $webserver_check_retval);
615a0a 1926                             if($webserver_check_retval == 0){
7b47c0 1927                                 $webserver_binary = 'httpd2';
615a0a 1928                             } else {
T 1929                                 unset($webserver_check_output, $webserver_check_retval);
7b47c0 1930                                 exec('which httpd', $webserver_check_output, $webserver_check_retval);
615a0a 1931                                 if($webserver_check_retval == 0){
7b47c0 1932                                     $webserver_binary = 'httpd';
T 1933                                 } else {
1934                                     unset($webserver_check_output, $webserver_check_retval);
1935                                     exec('which apache', $webserver_check_output, $webserver_check_retval);
1936                                     if($webserver_check_retval == 0){
1937                                         $webserver_binary = 'apache';
1938                                     }
615a0a 1939                                 }
T 1940                             }
1941                         }
1942                     }
1943                     if($webserver_binary != ''){
1944                         exec($webserver_binary.' -t 2>&1', $tmp_output, $tmp_retval);
7b47c0 1945                         if($tmp_retval > 0 && is_array($tmp_output) && !empty($tmp_output)){
b1a6a5 1946                             $app->log('Reason for Apache restart failure: '.implode("\n", $tmp_output), LOGLEVEL_WARN);
7b47c0 1947                             $app->dbmaster->datalogError(implode("\n", $tmp_output));
T 1948                         }
615a0a 1949                         unset($tmp_output, $tmp_retval);
T 1950                     }
1951                 }
b1a6a5 1952                 $app->system->copy($vhost_file, $vhost_file.'.err');
8cf78b 1953                 if(is_file($vhost_file.'~')) {
T 1954                     //* Copy back the last backup file
b1a6a5 1955                     $app->system->copy($vhost_file.'~', $vhost_file);
8cf78b 1956                 } else {
T 1957                     //* There is no backup file, so we create a empty vhost file with a warning message inside
b1a6a5 1958                     $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 1959                 }
481c00 1960                 if($this->ssl_certificate_changed === true) {
T 1961
1962                     $ssl_dir = $data['new']['document_root'].'/ssl';
1963                     $domain = $data['new']['ssl_domain'];
1964                     $key_file = $ssl_dir.'/'.$domain.'.key.org';
1965                     $key_file2 = $ssl_dir.'/'.$domain.'.key';
1966                     $csr_file = $ssl_dir.'/'.$domain.'.csr';
1967                     $crt_file = $ssl_dir.'/'.$domain.'.crt';
1968                     $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
b1a6a5 1969
481c00 1970                     //* Backup the files that might have caused the error
43b345 1971                     if(is_file($key_file)){
b1a6a5 1972                         $app->system->copy($key_file, $key_file.'.err');
MC 1973                         $app->system->chmod($key_file.'.err', 0400);
43b345 1974                     }
T 1975                     if(is_file($key_file2)){
b1a6a5 1976                         $app->system->copy($key_file2, $key_file2.'.err');
MC 1977                         $app->system->chmod($key_file2.'.err', 0400);
43b345 1978                     }
b1a6a5 1979                     if(is_file($csr_file)) $app->system->copy($csr_file, $csr_file.'.err');
MC 1980                     if(is_file($crt_file)) $app->system->copy($crt_file, $crt_file.'.err');
1981                     if(is_file($bundle_file)) $app->system->copy($bundle_file, $bundle_file.'.err');
1982
481c00 1983                     //* Restore the ~ backup files
b1a6a5 1984                     if(is_file($key_file.'~')) $app->system->copy($key_file.'~', $key_file);
MC 1985                     if(is_file($key_file2.'~')) $app->system->copy($key_file2.'~', $key_file2);
1986                     if(is_file($crt_file.'~')) $app->system->copy($crt_file.'~', $crt_file);
1987                     if(is_file($csr_file.'~')) $app->system->copy($csr_file.'~', $csr_file);
1988                     if(is_file($bundle_file.'~')) $app->system->copy($bundle_file.'~', $bundle_file);
1989
1990                     $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 1991                 }
b1a6a5 1992
MC 1993                 $app->services->restartService('httpd', 'restart');
7ed741 1994             }
c82dc7 1995         } else {
7ed741 1996             //* We do not check the apache config after changes (is faster)
T 1997             if($apache_chrooted) {
b1a6a5 1998                 $app->services->restartServiceDelayed('httpd', 'restart');
7ed741 1999             } else {
T 2000                 // request a httpd reload when all records have been processed
b1a6a5 2001                 $app->services->restartServiceDelayed('httpd', 'reload');
7ed741 2002             }
c82dc7 2003         }
b1a6a5 2004
MC 2005         //* The vhost is written and apache has been restarted, so we
481c00 2006         // can reset the ssl changed var to false and cleanup some files
T 2007         $this->ssl_certificate_changed = false;
b1a6a5 2008
481c00 2009         $ssl_dir = $data['new']['document_root'].'/ssl';
T 2010         $domain = $data['new']['ssl_domain'];
2011         $key_file = $ssl_dir.'/'.$domain.'.key.org';
2012         $key_file2 = $ssl_dir.'/'.$domain.'.key';
2013         $csr_file = $ssl_dir.'/'.$domain.'.csr';
2014         $crt_file = $ssl_dir.'/'.$domain.'.crt';
2015         $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
b1a6a5 2016
c77103 2017         if(@is_file($key_file.'~')) $app->system->unlink($key_file.'~');
T 2018         if(@is_file($key2_file.'~')) $app->system->unlink($key2_file.'~');
2019         if(@is_file($crt_file.'~')) $app->system->unlink($crt_file.'~');
2020         if(@is_file($csr_file.'~')) $app->system->unlink($csr_file.'~');
2021         if(@is_file($bundle_file.'~')) $app->system->unlink($bundle_file.'~');
b1a6a5 2022
7ed741 2023         // Remove the backup copy of the config file.
c77103 2024         if(@is_file($vhost_file.'~')) $app->system->unlink($vhost_file.'~');
ac933e 2025
da1a7c 2026         //* Unset action to clean it for next processed vhost.
T 2027         $this->action = '';
46c683 2028     }
ac933e 2029
b1a6a5 2030     function delete($event_name, $data) {
46c683 2031         global $app, $conf;
ac933e 2032
46c683 2033         // load the server configuration options
fb3339 2034         $app->uses('getconf');
c09f04 2035         $app->uses('system');
fb3339 2036         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
cc6568 2037         $fastcgi_config = $app->getconf->get_server_config($conf['server_id'], 'fastcgi');
b1a6a5 2038
511ba5 2039         if($data['old']['type'] == 'vhost' || $data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') $app->system->web_folder_protection($data['old']['document_root'], false);
ac933e 2040
2bbc4c 2041         //* Check if this is a chrooted setup
4b72c5 2042         if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
2bbc4c 2043             $apache_chrooted = true;
T 2044         } else {
2045             $apache_chrooted = false;
2046         }
b1a6a5 2047
fea5e7 2048         //* Remove the mounts
T 2049         $log_folder = 'log';
b1a6a5 2050         $web_folder = '';
511ba5 2051         if($data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') {
2af58c 2052             $tmp = $app->db->queryOneRecord('SELECT `domain`,`document_root` FROM web_domain WHERE domain_id = ?', $data['old']['parent_domain_id']);
526b99 2053             if($tmp['domain'] != ''){
T 2054                 $subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $data['old']['domain']);
2055             } else {
2056                 // get log folder from /etc/fstab
2057                 /*
2058                 $bind_mounts = $app->system->file_get_contents('/etc/fstab');
2059                 $bind_mount_lines = explode("\n", $bind_mounts);
2060                 if(is_array($bind_mount_lines) && !empty($bind_mount_lines)){
2061                     foreach($bind_mount_lines as $bind_mount_line){
2062                         $bind_mount_line = preg_replace('/\s+/', ' ', $bind_mount_line);
2063                         $bind_mount_parts = explode(' ', $bind_mount_line);
2064                         if(is_array($bind_mount_parts) && !empty($bind_mount_parts)){
2065                             if($bind_mount_parts[0] == '/var/log/ispconfig/httpd/'.$data['old']['domain'] && $bind_mount_parts[2] == 'none' && strpos($bind_mount_parts[3], 'bind') !== false){
2066                                 $subdomain_host = str_replace($data['old']['document_root'].'/log/', '', $bind_mount_parts[1]);
2067                             }
2068                         }
2069                     }
2070                 }
2071                 */
2072                 // we are deleting the parent domain, so we can delete everything in the log directory
2073                 $subdomain_hosts = array();
b1a6a5 2074                 $files = array_diff(scandir($data['old']['document_root'].'/'.$log_folder), array('.', '..'));
526b99 2075                 if(is_array($files) && !empty($files)){
T 2076                     foreach($files as $file){
2077                         if(is_dir($data['old']['document_root'].'/'.$log_folder.'/'.$file)){
2078                             $subdomain_hosts[] = $file;
2079                         }
2080                     }
2081                 }
2082             }
b1a6a5 2083             if(is_array($subdomain_hosts) && !empty($subdomain_hosts)){
526b99 2084                 $log_folders = array();
T 2085                 foreach($subdomain_hosts as $subdomain_host){
2086                     $log_folders[] = $log_folder.'/'.$subdomain_host;
2087                 }
2088             } else {
2089                 if($subdomain_host == '') $subdomain_host = 'web'.$data['old']['domain_id'];
2090                 $log_folder .= '/' . $subdomain_host;
2091             }
2092             $web_folder = $data['old']['web_folder'];
b1a6a5 2093             unset($tmp);
526b99 2094             unset($subdomain_hosts);
3cde19 2095         }
b1a6a5 2096
511ba5 2097         if($data['old']['type'] == 'vhost' || $data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias'){
526b99 2098             if(is_array($log_folders) && !empty($log_folders)){
T 2099                 foreach($log_folders as $log_folder){
cc6568 2100                     //if($app->system->is_mounted($data['old']['document_root'].'/'.$log_folder)) exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder));
a9b325 2101                     //exec('fuser -km '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
cc6568 2102                     exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
526b99 2103                 }
T 2104             } else {
cc6568 2105                 //if($app->system->is_mounted($data['old']['document_root'].'/'.$log_folder)) exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder));
a9b325 2106                 //exec('fuser -km '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
cc6568 2107                 exec('umount '.escapeshellarg($data['old']['document_root'].'/'.$log_folder).' 2>/dev/null');
526b99 2108             }
a49635 2109             
MB 2110             // remove letsencrypt if it exists (renew will always fail otherwise)
2111             
2112             $domain = $data['old']['ssl_domain'];
2113             if(!$domain) $domain = $data['old']['domain'];
2114             if(substr($domain, 0, 2) === '*.') {
2115                 // wildcard domain not yet supported by letsencrypt!
2116                 $domain = substr($domain, 2);
2117             }
2118             //$crt_tmp_file = "/etc/letsencrypt/live/".$domain."/cert.pem";
2119             //$key_tmp_file = "/etc/letsencrypt/live/".$domain."/privkey.pem";
2120             $le_conf_file = '/etc/letsencrypt/renewal/' . $domain . '.conf';
2121             @rename('/etc/letsencrypt/renewal/' . $domain . '.conf', '/etc/letsencrypt/renewal/' . $domain . '.conf~backup');
526b99 2122         }
b1a6a5 2123
fea5e7 2124         //* remove mountpoint from fstab
526b99 2125         if(is_array($log_folders) && !empty($log_folders)){
T 2126             foreach($log_folders as $log_folder){
2127                 $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$log_folder.'    none    bind';
b1a6a5 2128                 $app->system->removeLine('/etc/fstab', $fstab_line);
526b99 2129             }
T 2130         } else {
2131             $fstab_line = '/var/log/ispconfig/httpd/'.$data['old']['domain'].' '.$data['old']['document_root'].'/'.$log_folder.'    none    bind';
b1a6a5 2132             $app->system->removeLine('/etc/fstab', $fstab_line);
526b99 2133         }
T 2134         unset($log_folders);
ac933e 2135
511ba5 2136         if($data['old']['type'] != 'vhost' && $data['old']['type'] != 'vhostsubdomain' && $data['old']['type'] != 'vhostalias' && $data['old']['parent_domain_id'] > 0) {
46c683 2137             //* This is a alias domain or subdomain, so we have to update the website instead
fb3339 2138             $parent_domain_id = intval($data['old']['parent_domain_id']);
2af58c 2139             $tmp = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ? AND active = 'y'", $parent_domain_id);
fb3339 2140             $data['new'] = $tmp;
J 2141             $data['old'] = $tmp;
46c683 2142             $this->action = 'update';
496602 2143             $this->update_letsencrypt = true;
46c683 2144             // just run the update function
b1a6a5 2145             $this->update($event_name, $data);
ac933e 2146
46c683 2147         } else {
T 2148             //* This is a website
2149             // Deleting the vhost file, symlink and the data directory
fb3339 2150             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
b1a6a5 2151
8ab3cd 2152             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
T 2153             if(is_link($vhost_symlink)){
c77103 2154                 $app->system->unlink($vhost_symlink);
b1a6a5 2155                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
8ab3cd 2156             }
T 2157             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['old']['domain'].'.vhost');
2158             if(is_link($vhost_symlink)){
c77103 2159                 $app->system->unlink($vhost_symlink);
b1a6a5 2160                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
8ab3cd 2161             }
T 2162             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['old']['domain'].'.vhost');
2163             if(is_link($vhost_symlink)){
c77103 2164                 $app->system->unlink($vhost_symlink);
b1a6a5 2165                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file, LOGLEVEL_DEBUG);
8ab3cd 2166             }
b1a6a5 2167
c77103 2168             $app->system->unlink($vhost_file);
b1a6a5 2169             $app->log('Removing vhost file: '.$vhost_file, LOGLEVEL_DEBUG);
ac933e 2170
511ba5 2171             if($data['old']['type'] == 'vhost' || $data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') {
b1a6a5 2172                 $docroot = escapeshellcmd($data['old']['document_root']);
MC 2173                 if($docroot != '' && !stristr($docroot, '..')) {
2174                     if($data['old']['type'] == 'vhost') {
2175                         // this is a vhost - we delete everything in here.
2176                         exec('rm -rf '.$docroot);
2177                     } elseif(!stristr($data['old']['web_folder'], '..')) {
2178                         // this is a vhost subdomain
2179                         // IMPORTANT: do some folder checks before we delete this!
2180                         $do_delete = true;
2181                         $delete_folder = preg_replace('/[\/]{2,}/', '/', $web_folder); // replace / occuring multiple times
2182                         if(substr($delete_folder, 0, 1) === '/') $delete_folder = substr($delete_folder, 1);
2183                         if(substr($delete_folder, -1) === '/') $delete_folder = substr($delete_folder, 0, -1);
46c683 2184
b1a6a5 2185                         $path_elements = explode('/', $delete_folder);
46c683 2186
b1a6a5 2187                         if($path_elements[0] == 'web' || $path_elements[0] === '') {
MC 2188                             // paths beginning with /web should NEVER EVER be deleted, empty paths should NEVER occur - but for safety reasons we check it here!
2189                             // we use strict check as otherwise directories named '0' may not be deleted
2190                             $do_delete = false;
2191                         } else {
511ba5 2192                             // read all vhost subdomains and alias with same parent domain
b1a6a5 2193                             $used_paths = array();
2af58c 2194                             $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 2195                             foreach($tmp as $tmprec) {
MC 2196                                 // we normalize the folder entries because we need to compare them
2197                                 $tmp_folder = preg_replace('/[\/]{2,}/', '/', $tmprec['web_folder']); // replace / occuring multiple times
2198                                 if(substr($tmp_folder, 0, 1) === '/') $tmp_folder = substr($tmp_folder, 1);
2199                                 if(substr($tmp_folder, -1) === '/') $tmp_folder = substr($tmp_folder, 0, -1);
ac933e 2200
b1a6a5 2201                                 // add this path and it's parent paths to used_paths array
MC 2202                                 while(strpos($tmp_folder, '/') !== false) {
2203                                     if(in_array($tmp_folder, $used_paths) == false) $used_paths[] = $tmp_folder;
2204                                     $tmp_folder = substr($tmp_folder, 0, strrpos($tmp_folder, '/'));
2205                                 }
2206                                 if(in_array($tmp_folder, $used_paths) == false) $used_paths[] = $tmp_folder;
2207                             }
2208                             unset($tmp);
2209
2210                             // loop and check if the path is still used and stop at first used one
2211                             // set do_delete to false so nothing gets deleted if the web_folder itself is still used
2212                             $do_delete = false;
2213                             while(count($path_elements) > 0) {
2214                                 $tmp_folder = implode('/', $path_elements);
2215                                 if(in_array($tmp_folder, $used_paths) == true) break;
2216
2217                                 // this path is not used - set it as path to delete, strip the last element from the array and set do_delete to true
2218                                 $delete_folder = $tmp_folder;
2219                                 $do_delete = true;
2220                                 array_pop($path_elements);
2221                             }
2222                             unset($tmp_folder);
2223                             unset($used_paths);
2224                         }
2225
2226                         if($do_delete === true && $delete_folder !== '') exec('rm -rf '.$docroot.'/'.$delete_folder);
2227
2228                         unset($delete_folder);
2229                         unset($path_elements);
2230                     }
2231                 }
2232
2233                 //remove the php fastgi starter script if available
2234                 if ($data['old']['php'] == 'fast-cgi') {
2235                     $fastcgi_starter_path = str_replace('[system_user]', $data['old']['system_user'], $fastcgi_config['fastcgi_starter_path']);
2236                     if($data['old']['type'] == 'vhost') {
2237                         if (is_dir($fastcgi_starter_path)) {
2238                             exec('rm -rf '.$fastcgi_starter_path);
2239                         }
2240                     } else {
2241                         $fcgi_starter_script = $fastcgi_starter_path.$fastcgi_config['fastcgi_starter_script'].'_web'.$data['old']['domain_id'];
2242                         if (file_exists($fcgi_starter_script)) {
2243                             exec('rm -f '.$fcgi_starter_script);
2244                         }
2245                     }
2246                 }
2247
2248                 // remove PHP-FPM pool
2249                 if ($data['old']['php'] == 'php-fpm') {
2250                     $this->php_fpm_pool_delete($data, $web_config);
c59632 2251                 } elseif($data['old']['php'] == 'hhvm') {
MC 2252                     $this->hhvm_update($data, $web_config);
b1a6a5 2253                 }
MC 2254
2255                 //remove the php cgi starter script if available
2256                 if ($data['old']['php'] == 'cgi') {
2257                     // TODO: fetch the date from the server-settings
2258                     $web_config['cgi_starter_path'] = $web_config['website_basedir'].'/php-cgi-scripts/[system_user]/';
2259
2260                     $cgi_starter_path = str_replace('[system_user]', $data['old']['system_user'], $web_config['cgi_starter_path']);
2261                     if($data['old']['type'] == 'vhost') {
2262                         if (is_dir($cgi_starter_path)) {
2263                             exec('rm -rf '.$cgi_starter_path);
2264                         }
2265                     } else {
2266                         $cgi_starter_script = $cgi_starter_path.'php-cgi-starter_web'.$data['old']['domain_id'];
2267                         if (file_exists($cgi_starter_script)) {
2268                             exec('rm -f '.$cgi_starter_script);
2269                         }
2270                     }
2271                 }
2272
2273                 $app->log('Removing website: '.$docroot, LOGLEVEL_DEBUG);
2274
2275                 // Delete the symlinks for the sites
2af58c 2276                 $client = $app->db->queryOneRecord('SELECT client_id FROM sys_group WHERE sys_group.groupid = ?', $data['old']['sys_groupid']);
b1a6a5 2277                 $client_id = intval($client['client_id']);
MC 2278                 unset($client);
2279                 $tmp_symlinks_array = explode(':', $web_config['website_symlinks']);
2280                 if(is_array($tmp_symlinks_array)) {
2281                     foreach($tmp_symlinks_array as $tmp_symlink) {
2282                         $tmp_symlink = str_replace('[client_id]', $client_id, $tmp_symlink);
2283                         $tmp_symlink = str_replace('[website_domain]', $data['old']['domain'], $tmp_symlink);
2284                         // Remove trailing slash
2285                         if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
2286                         // delete the symlink
2287                         if(is_link($tmp_symlink)) {
2288                             $app->system->unlink($tmp_symlink);
2289                             $app->log('Removing symlink: '.$tmp_symlink, LOGLEVEL_DEBUG);
2290                         }
2291                     }
2292                 }
2293                 // end removing symlinks
3cde19 2294             }
b1a6a5 2295
MC 2296             // Delete the log file directory
2297             $vhost_logfile_dir = escapeshellcmd('/var/log/ispconfig/httpd/'.$data['old']['domain']);
2298             if($data['old']['domain'] != '' && !stristr($vhost_logfile_dir, '..')) exec('rm -rf '.$vhost_logfile_dir);
2299             $app->log('Removing website logfile directory: '.$vhost_logfile_dir, LOGLEVEL_DEBUG);
2300
2301             if($data['old']['type'] == 'vhost') {
2302                 //delete the web user
2303                 $command = 'killall -u '.escapeshellcmd($data['old']['system_user']).' ; userdel';
2304                 $command .= ' '.escapeshellcmd($data['old']['system_user']);
2305                 exec($command);
2306                 if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' '.$command);
2307
2308             }
2309
2310             //* Remove the awstats configuration file
2311             if($data['old']['stats_type'] == 'awstats') {
2312                 $this->awstats_delete($data, $web_config);
2313             }
2314
511ba5 2315             if($data['old']['type'] == 'vhostsubdomain' || $data['old']['type'] == 'vhostalias') {
b1a6a5 2316                 $app->system->web_folder_protection($parent_web_document_root, true);
MC 2317             }
2318
8ab3cd 2319             if($apache_chrooted) {
b1a6a5 2320                 $app->services->restartServiceDelayed('httpd', 'restart');
8ab3cd 2321             } else {
T 2322                 // request a httpd reload when all records have been processed
b1a6a5 2323                 $app->services->restartServiceDelayed('httpd', 'reload');
58c210 2324             }
ac933e 2325
0f89bd 2326             //* Delete the web-backups
69b1bc 2327             if($data['old']['type'] == 'vhost') {
FS 2328                 $server_config = $app->getconf->get_server_config($conf['server_id'], 'server');
2329                 $backup_dir = $server_config['backup_dir'];
2330                 $mount_backup = true;
a81238 2331                 if($server_config['backup_dir'] != '' && $server_config['backup_delete'] == 'y') {
990ca8 2332                     //* mount backup directory, if necessary
FS 2333                     if( $server_config['backup_dir_is_mount'] == 'y' && !$app->system->mount_backup_dir($backup_dir) ) $mount_backup = false;
2334
69b1bc 2335                     if($mount_backup){
FS 2336                         $web_backup_dir = $backup_dir.'/web'.$data_old['domain_id'];
2337                         //** do not use rm -rf $web_backup_dir because database(s) may exits
2338                         exec(escapeshellcmd('rm -f '.$web_backup_dir.'/web'.$data_old['domain_id'].'_').'*');
2339                         //* cleanup database
990ca8 2340                         $sql = "DELETE FROM web_backup WHERE server_id = ? AND parent_domain_id = ? AND filename LIKE ?";
FS 2341                         $app->db->query($sql, $conf['server_id'], $data_old['domain_id'], "web".$data_old['domain_id']."_%");
2342                         if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql, $conf['server_id'], $data_old['domain_id'], "web".$data_old['domain_id']."_%");
0f89bd 2343
FS 2344                         $app->log('Deleted the web backup files', LOGLEVEL_DEBUG);
69b1bc 2345                     }
FS 2346                 }
2347             }
46c683 2348         }
b1a6a5 2349         if($data['old']['type'] != 'vhost') $app->system->web_folder_protection($data['old']['document_root'], true);
46c683 2350     }
ac933e 2351
46c683 2352     //* This function is called when a IP on the server is inserted, updated or deleted
b1a6a5 2353     function server_ip($event_name, $data) {
46c683 2354         global $app, $conf;
ac933e 2355
46c683 2356         // load the server configuration options
fb3339 2357         $app->uses('getconf');
J 2358         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
ac933e 2359
46c683 2360         $app->load('tpl');
ac933e 2361
46c683 2362         $tpl = new tpl();
fb3339 2363         $tpl->newTemplate('apache_ispconfig.conf.master');
8133de 2364         $tpl->setVar('apache_version', $app->system->getapacheversion());
2af58c 2365         $records = $app->db->queryAllRecords("SELECT * FROM server_ip WHERE server_id = ? AND virtualhost = 'y'", $conf['server_id']);
b1a6a5 2366
a2156e 2367         $records_out= array();
T 2368         if(is_array($records)) {
2369             foreach($records as $rec) {
2370                 if($rec['ip_type'] == 'IPv6') {
2371                     $ip_address = '['.$rec['ip_address'].']';
2372                 } else {
2373                     $ip_address = $rec['ip_address'];
2374                 }
b1a6a5 2375                 $ports = explode(',', $rec['virtualhost_port']);
a2156e 2376                 if(is_array($ports)) {
T 2377                     foreach($ports as $port) {
2378                         $port = intval($port);
2379                         if($port > 0 && $port < 65536 && $ip_address != '') {
2380                             $records_out[] = array('ip_address' => $ip_address, 'port' => $port);
2381                         }
2382                     }
2383                 }
2384             }
2385         }
b1a6a5 2386
MC 2387
a2156e 2388         if(count($records_out) > 0) {
b1a6a5 2389             $tpl->setLoop('ip_adresses', $records_out);
46c683 2390         }
ac933e 2391
fb3339 2392         $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/ispconfig.conf');
b1a6a5 2393         $app->system->file_put_contents($vhost_file, $tpl->grab());
MC 2394         $app->log('Writing the conf file: '.$vhost_file, LOGLEVEL_DEBUG);
46c683 2395         unset($tpl);
ac933e 2396
46c683 2397     }
b1a6a5 2398
524077 2399     //* Create or update the .htaccess folder protection
b1a6a5 2400     function web_folder_user($event_name, $data) {
524077 2401         global $app, $conf;
c69439 2402
524077 2403         $app->uses('system');
b1a6a5 2404
524077 2405         if($event_name == 'web_folder_user_delete') {
T 2406             $folder_id = $data['old']['web_folder_id'];
2407         } else {
2408             $folder_id = $data['new']['web_folder_id'];
2409         }
b1a6a5 2410
2af58c 2411         $folder = $app->db->queryOneRecord("SELECT * FROM web_folder WHERE web_folder_id = ?", $folder_id);
MC 2412         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $folder['parent_domain_id']);
b1a6a5 2413
524077 2414         if(!is_array($folder) or !is_array($website)) {
b1a6a5 2415             $app->log('Not able to retrieve folder or website record.', LOGLEVEL_DEBUG);
524077 2416             return false;
T 2417         }
b1a6a5 2418
MC 2419         $web_folder = 'web';
511ba5 2420         if($website['type'] == 'vhostsubdomain' || $website['type'] == 'vhostalias') $web_folder = $website['web_folder'];
b1a6a5 2421
524077 2422         //* Get the folder path.
b1a6a5 2423         if(substr($folder['path'], 0, 1) == '/') $folder['path'] = substr($folder['path'], 1);
MC 2424         if(substr($folder['path'], -1) == '/') $folder['path'] = substr($folder['path'], 0, -1);
6fb93d 2425         $folder_path = escapeshellcmd($website['document_root'].'/' . $web_folder . '/'.$folder['path']);
b1a6a5 2426         if(substr($folder_path, -1) != '/') $folder_path .= '/';
MC 2427
524077 2428         //* Check if the resulting path is inside the docroot
b1a6a5 2429         if(stristr($folder_path, '..') || stristr($folder_path, './') || stristr($folder_path, '\\')) {
MC 2430             $app->log('Folder path "'.$folder_path.'" contains .. or ./.', LOGLEVEL_DEBUG);
524077 2431             return false;
T 2432         }
b1a6a5 2433
524077 2434         //* Create the folder path, if it does not exist
8cf78b 2435         if(!is_dir($folder_path)) {
dbae22 2436             $app->system->mkdirpath($folder_path, 0755, $website['system_user'], $website['system_group']);
8cf78b 2437         }
b1a6a5 2438
524077 2439         //* Create empty .htpasswd file, if it does not exist
T 2440         if(!is_file($folder_path.'.htpasswd')) {
4bd960 2441             $app->system->touch($folder_path.'.htpasswd');
51910d 2442             $app->system->chmod($folder_path.'.htpasswd', 0751);
b1a6a5 2443             $app->system->chown($folder_path.'.htpasswd', $website['system_user']);
MC 2444             $app->system->chgrp($folder_path.'.htpasswd', $website['system_group']);
2445             $app->log('Created file '.$folder_path.'.htpasswd', LOGLEVEL_DEBUG);
524077 2446         }
b1a6a5 2447
8ab3cd 2448         if(($data['new']['username'] != $data['old']['username'] || $data['new']['active'] == 'n') && $data['old']['username'] != '') {
b1a6a5 2449             $app->system->removeLine($folder_path.'.htpasswd', $data['old']['username'].':');
MC 2450             $app->log('Removed user: '.$data['old']['username'], LOGLEVEL_DEBUG);
c69439 2451         }
b1a6a5 2452
524077 2453         //* Add or remove the user from .htpasswd file
T 2454         if($event_name == 'web_folder_user_delete') {
b1a6a5 2455             $app->system->removeLine($folder_path.'.htpasswd', $data['old']['username'].':');
MC 2456             $app->log('Removed user: '.$data['old']['username'], LOGLEVEL_DEBUG);
524077 2457         } else {
c69439 2458             if($data['new']['active'] == 'y') {
b1a6a5 2459                 $app->system->replaceLine($folder_path.'.htpasswd', $data['new']['username'].':', $data['new']['username'].':'.$data['new']['password'], 0, 1);
MC 2460                 $app->log('Added or updated user: '.$data['new']['username'], LOGLEVEL_DEBUG);
c69439 2461             }
524077 2462         }
b1a6a5 2463
MC 2464
524077 2465         //* Create the .htaccess file
8ab3cd 2466         //if(!is_file($folder_path.'.htaccess')) {
b1a6a5 2467         $begin_marker = '### ISPConfig folder protection begin ###';
MC 2468         $end_marker = "### ISPConfig folder protection end ###\n\n";
2469         $ht_file = $begin_marker."\nAuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$folder_path.".htpasswd\nrequire valid-user\n".$end_marker;
2470
2471         if(file_exists($folder_path.'.htaccess')) {
2472             $old_content = $app->system->file_get_contents($folder_path.'.htaccess');
2473
2474             if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $old_content, $matches)) {
2475                 $ht_file = str_replace($matches[0], $ht_file, $old_content);
2476             } else {
2477                 $ht_file .= $old_content;
2478             }
2479         }
2480         unset($old_content);
2481
2482         $app->system->file_put_contents($folder_path.'.htaccess', $ht_file);
51910d 2483         $app->system->chmod($folder_path.'.htaccess', 0751);
b1a6a5 2484         $app->system->chown($folder_path.'.htaccess', $website['system_user']);
MC 2485         $app->system->chgrp($folder_path.'.htaccess', $website['system_group']);
2486         $app->log('Created/modified file '.$folder_path.'.htaccess', LOGLEVEL_DEBUG);
8ab3cd 2487         //}
b1a6a5 2488
524077 2489     }
b1a6a5 2490
524077 2491     //* Remove .htaccess and .htpasswd file, when folder protection is removed
b1a6a5 2492     function web_folder_delete($event_name, $data) {
524077 2493         global $app, $conf;
b1a6a5 2494
524077 2495         $folder_id = $data['old']['web_folder_id'];
b1a6a5 2496
8ab3cd 2497         $folder = $data['old'];
2af58c 2498         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $folder['parent_domain_id']);
b1a6a5 2499
524077 2500         if(!is_array($folder) or !is_array($website)) {
b1a6a5 2501             $app->log('Not able to retrieve folder or website record.', LOGLEVEL_DEBUG);
524077 2502             return false;
T 2503         }
b1a6a5 2504
MC 2505         $web_folder = 'web';
511ba5 2506         if($website['type'] == 'vhostsubdomain' || $website['type'] == 'vhostalias') $web_folder = $website['web_folder'];
b1a6a5 2507
524077 2508         //* Get the folder path.
b1a6a5 2509         if(substr($folder['path'], 0, 1) == '/') $folder['path'] = substr($folder['path'], 1);
MC 2510         if(substr($folder['path'], -1) == '/') $folder['path'] = substr($folder['path'], 0, -1);
6fb93d 2511         $folder_path = realpath($website['document_root'].'/' . $web_folder . '/'.$folder['path']);
b1a6a5 2512         if(substr($folder_path, -1) != '/') $folder_path .= '/';
MC 2513
524077 2514         //* Check if the resulting path is inside the docroot
b1a6a5 2515         if(substr($folder_path, 0, strlen($website['document_root'])) != $website['document_root']) {
MC 2516             $app->log('Folder path is outside of docroot.', LOGLEVEL_DEBUG);
524077 2517             return false;
T 2518         }
b1a6a5 2519
524077 2520         //* Remove .htpasswd file
T 2521         if(is_file($folder_path.'.htpasswd')) {
c77103 2522             $app->system->unlink($folder_path.'.htpasswd');
b1a6a5 2523             $app->log('Removed file '.$folder_path.'.htpasswd', LOGLEVEL_DEBUG);
524077 2524         }
b1a6a5 2525
524077 2526         //* Remove .htaccess file
T 2527         if(is_file($folder_path.'.htaccess')) {
b1a6a5 2528             $begin_marker = '### ISPConfig folder protection begin ###';
MC 2529             $end_marker = "### ISPConfig folder protection end ###\n\n";
2530
2531             $ht_file = $app->system->file_get_contents($folder_path.'.htaccess');
2532
2533             if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $ht_file, $matches)) {
2534                 $ht_file = str_replace($matches[0], '', $ht_file);
2535             } else {
2536                 $ht_file = str_replace("AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$folder_path.".htpasswd\nrequire valid-user", '', $ht_file);
2537             }
2538
2539             if(trim($ht_file) == '') {
2540                 $app->system->unlink($folder_path.'.htaccess');
2541                 $app->log('Removed file '.$folder_path.'.htaccess', LOGLEVEL_DEBUG);
2542             } else {
2543                 $app->system->file_put_contents($folder_path.'.htaccess', $ht_file);
2544                 $app->log('Removed protection content from file '.$folder_path.'.htaccess', LOGLEVEL_DEBUG);
2545             }
524077 2546         }
2023a7 2547     }
b1a6a5 2548
2023a7 2549     //* Update folder protection, when path has been changed
b1a6a5 2550     function web_folder_update($event_name, $data) {
2023a7 2551         global $app, $conf;
b1a6a5 2552
2af58c 2553         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $data['new']['parent_domain_id']);
b1a6a5 2554
2023a7 2555         if(!is_array($website)) {
b1a6a5 2556             $app->log('Not able to retrieve folder or website record.', LOGLEVEL_DEBUG);
2023a7 2557             return false;
T 2558         }
b1a6a5 2559
MC 2560         $web_folder = 'web';
511ba5 2561         if($website['type'] == 'vhostsubdomain' || $website['type'] == 'vhostalias') $web_folder = $website['web_folder'];
b1a6a5 2562
2023a7 2563         //* Get the folder path.
b1a6a5 2564         if(substr($data['old']['path'], 0, 1) == '/') $data['old']['path'] = substr($data['old']['path'], 1);
MC 2565         if(substr($data['old']['path'], -1) == '/') $data['old']['path'] = substr($data['old']['path'], 0, -1);
6fb93d 2566         $old_folder_path = realpath($website['document_root'].'/' . $web_folder . '/'.$data['old']['path']);
b1a6a5 2567         if(substr($old_folder_path, -1) != '/') $old_folder_path .= '/';
MC 2568
2569         if(substr($data['new']['path'], 0, 1) == '/') $data['new']['path'] = substr($data['new']['path'], 1);
2570         if(substr($data['new']['path'], -1) == '/') $data['new']['path'] = substr($data['new']['path'], 0, -1);
6fb93d 2571         $new_folder_path = escapeshellcmd($website['document_root'].'/' . $web_folder . '/'.$data['new']['path']);
b1a6a5 2572         if(substr($new_folder_path, -1) != '/') $new_folder_path .= '/';
MC 2573
2023a7 2574         //* Check if the resulting path is inside the docroot
b1a6a5 2575         if(stristr($new_folder_path, '..') || stristr($new_folder_path, './') || stristr($new_folder_path, '\\')) {
MC 2576             $app->log('Folder path "'.$new_folder_path.'" contains .. or ./.', LOGLEVEL_DEBUG);
2023a7 2577             return false;
T 2578         }
b1a6a5 2579         if(stristr($old_folder_path, '..') || stristr($old_folder_path, './') || stristr($old_folder_path, '\\')) {
MC 2580             $app->log('Folder path "'.$old_folder_path.'" contains .. or ./.', LOGLEVEL_DEBUG);
2023a7 2581             return false;
T 2582         }
b1a6a5 2583
2023a7 2584         //* Check if the resulting path is inside the docroot
b1a6a5 2585         if(substr($old_folder_path, 0, strlen($website['document_root'])) != $website['document_root']) {
MC 2586             $app->log('Old folder path '.$old_folder_path.' is outside of docroot.', LOGLEVEL_DEBUG);
2023a7 2587             return false;
T 2588         }
b1a6a5 2589         if(substr($new_folder_path, 0, strlen($website['document_root'])) != $website['document_root']) {
MC 2590             $app->log('New folder path '.$new_folder_path.' is outside of docroot.', LOGLEVEL_DEBUG);
2023a7 2591             return false;
T 2592         }
b1a6a5 2593
2023a7 2594         //* Create the folder path, if it does not exist
c77103 2595         if(!is_dir($new_folder_path)) $app->system->mkdirpath($new_folder_path);
b1a6a5 2596
MC 2597         $begin_marker = '### ISPConfig folder protection begin ###';
2598         $end_marker = "### ISPConfig folder protection end ###\n\n";
2599
2023a7 2600         if($data['old']['path'] != $data['new']['path']) {
T 2601
b1a6a5 2602
2023a7 2603             //* move .htpasswd file
T 2604             if(is_file($old_folder_path.'.htpasswd')) {
b1a6a5 2605                 $app->system->rename($old_folder_path.'.htpasswd', $new_folder_path.'.htpasswd');
MC 2606                 $app->log('Moved file '.$old_folder_path.'.htpasswd to '.$new_folder_path.'.htpasswd', LOGLEVEL_DEBUG);
2023a7 2607             }
b1a6a5 2608
8ab3cd 2609             //* delete old .htaccess file
2023a7 2610             if(is_file($old_folder_path.'.htaccess')) {
b1a6a5 2611                 $ht_file = $app->system->file_get_contents($old_folder_path.'.htaccess');
MC 2612
2613                 if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $ht_file, $matches)) {
2614                     $ht_file = str_replace($matches[0], '', $ht_file);
2615                 } else {
2616                     $ht_file = str_replace("AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$old_folder_path.".htpasswd\nrequire valid-user", '', $ht_file);
2617                 }
2618
2619                 if(trim($ht_file) == '') {
2620                     $app->system->unlink($old_folder_path.'.htaccess');
2621                     $app->log('Removed file '.$old_folder_path.'.htaccess', LOGLEVEL_DEBUG);
2622                 } else {
2623                     $app->system->file_put_contents($old_folder_path.'.htaccess', $ht_file);
2624                     $app->log('Removed protection content from file '.$old_folder_path.'.htaccess', LOGLEVEL_DEBUG);
2625                 }
2023a7 2626             }
b1a6a5 2627
2023a7 2628         }
b1a6a5 2629
2023a7 2630         //* Create the .htaccess file
8ab3cd 2631         if($data['new']['active'] == 'y') {
b1a6a5 2632             $ht_file = $begin_marker."\nAuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$new_folder_path.".htpasswd\nrequire valid-user\n".$end_marker;
MC 2633
2634             if(file_exists($new_folder_path.'.htaccess')) {
2635                 $old_content = $app->system->file_get_contents($new_folder_path.'.htaccess');
2636
2637                 if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $old_content, $matches)) {
2638                     $ht_file = str_replace($matches[0], $ht_file, $old_content);
2639                 } else {
2640                     $ht_file .= $old_content;
2641                 }
2642             }
2643
2644             $app->system->file_put_contents($new_folder_path.'.htaccess', $ht_file);
51910d 2645             $app->system->chmod($new_folder_path.'.htaccess', 0751);
b1a6a5 2646             $app->system->chown($new_folder_path.'.htaccess', $website['system_user']);
MC 2647             $app->system->chgrp($new_folder_path.'.htaccess', $website['system_group']);
2648             $app->log('Created/modified file '.$new_folder_path.'.htaccess', LOGLEVEL_DEBUG);
8433d0 2649             
TB 2650             //* Create empty .htpasswd file, if it does not exist
2651             if(!is_file($folder_path.'.htpasswd')) {
2652                 $app->system->touch($new_folder_path.'.htpasswd');
51910d 2653                 $app->system->chmod($new_folder_path.'.htpasswd', 0751);
8433d0 2654                 $app->system->chown($new_folder_path.'.htpasswd', $website['system_user']);
TB 2655                 $app->system->chgrp($new_folder_path.'.htpasswd', $website['system_group']);
2656                 $app->log('Created file '.$new_folder_path.'.htpasswd', LOGLEVEL_DEBUG);
2657             }
2023a7 2658         }
b1a6a5 2659
2023a7 2660         //* Remove .htaccess file
T 2661         if($data['new']['active'] == 'n' && is_file($new_folder_path.'.htaccess')) {
b1a6a5 2662             $ht_file = $app->system->file_get_contents($new_folder_path.'.htaccess');
MC 2663
2664             if(preg_match('/' . preg_quote($begin_marker, '/') . '(.*?)' . preg_quote($end_marker, '/') . '/s', $ht_file, $matches)) {
2665                 $ht_file = str_replace($matches[0], '', $ht_file);
2666             } else {
2667                 $ht_file = str_replace("AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$new_folder_path.".htpasswd\nrequire valid-user", '', $ht_file);
2668             }
2669
2670             if(trim($ht_file) == '') {
2671                 $app->system->unlink($new_folder_path.'.htaccess');
2672                 $app->log('Removed file '.$new_folder_path.'.htaccess', LOGLEVEL_DEBUG);
2673             } else {
2674                 $app->system->file_put_contents($new_folder_path.'.htaccess', $ht_file);
2675                 $app->log('Removed protection content from file '.$new_folder_path.'.htaccess', LOGLEVEL_DEBUG);
2676             }
2023a7 2677         }
b1a6a5 2678
MC 2679
524077 2680     }
b1a6a5 2681
MC 2682     public function ftp_user_delete($event_name, $data) {
26c0fc 2683         global $app, $conf;
b1a6a5 2684
26c0fc 2685         $ftpquota_file = $data['old']['dir'].'/.ftpquota';
c77103 2686         if(file_exists($ftpquota_file)) $app->system->unlink($ftpquota_file);
b1a6a5 2687
26c0fc 2688     }
b1a6a5 2689
MC 2690
ac933e 2691
V 2692     /**
2693      * This function is called when a Webdav-User is inserted, updated or deleted.
2694      *
2695      * @author Oliver Vogel
2696      * @param string $event_name
2697      * @param array $data
2698      */
b1a6a5 2699     public function webdav($event_name, $data) {
ac933e 2700         global $app, $conf;
b1a6a5 2701
52a04e 2702         /*
T 2703          * load the server configuration options
2704         */
fb3339 2705         $app->uses('getconf');
J 2706         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
ac933e 2707
V 2708         if (($event_name == 'webdav_user_insert') || ($event_name == 'webdav_user_update')) {
2709
2710             /*
2711              * Get additional informations
2712             */
2af58c 2713             $sitedata = $app->db->queryOneRecord('SELECT document_root, domain, system_user, system_group FROM web_domain WHERE domain_id = ?', $data['new']['parent_domain_id']);
ac933e 2714             $documentRoot = $sitedata['document_root'];
V 2715             $domain = $sitedata['domain'];
ca14fe 2716             $user = $sitedata['system_user'];
V 2717             $group = $sitedata['system_group'];
b67344 2718             $webdav_user_dir = $documentRoot . '/webdav/' . $data['new']['dir'];
ac933e 2719
V 2720             /* Check if this is a chrooted setup */
2721             if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
2722                 $apache_chrooted = true;
b1a6a5 2723                 $app->log('Info: Apache is chrooted.', LOGLEVEL_DEBUG);
ac933e 2724             } else {
V 2725                 $apache_chrooted = false;
2726             }
b1a6a5 2727
b67344 2728             //* We dont want to have relative paths here
b1a6a5 2729             if(stristr($webdav_user_dir, '..')  || stristr($webdav_user_dir, './')) {
MC 2730                 $app->log('Folder path '.$webdav_user_dir.' contains ./ or .. '.$documentRoot, LOGLEVEL_WARN);
b67344 2731                 return false;
T 2732             }
b1a6a5 2733
b67344 2734             //* Check if the resulting path exists if yes, if it is inside the docroot
b1a6a5 2735             if(is_dir($webdav_user_dir) && substr(realpath($webdav_user_dir), 0, strlen($documentRoot)) != $documentRoot) {
MC 2736                 $app->log('Folder path '.$webdav_user_dir.' is outside of docroot '.$documentRoot, LOGLEVEL_WARN);
b67344 2737                 return false;
T 2738             }
ac933e 2739
V 2740             /*
2741              * First the webdav-root - folder has to exist
2742             */
b67344 2743             if(!is_dir($webdav_user_dir)) {
b1a6a5 2744                 $app->log('Webdav User directory '.$webdav_user_dir.' does not exist. Creating it now.', LOGLEVEL_DEBUG);
c77103 2745                 $app->system->mkdirpath($webdav_user_dir);
ac933e 2746             }
V 2747
2748             /*
ca14fe 2749              * The webdav - Root needs the group/user as owner and the apache as read and write
ac933e 2750             */
c77103 2751             //$this->_exec('chown ' . $user . ':' . $group . ' ' . escapeshellcmd($documentRoot . '/webdav/'));
T 2752             //$this->_exec('chmod 770 ' . escapeshellcmd($documentRoot . '/webdav/'));
b1a6a5 2753             $app->system->chown($documentRoot . '/webdav', $user);
MC 2754             $app->system->chgrp($documentRoot . '/webdav', $group);
2755             $app->system->chmod($documentRoot . '/webdav', 0770);
ac933e 2756
V 2757             /*
ca14fe 2758              * The webdav folder (not the webdav-root!) needs the same (not in ONE step, because the
V 2759              * pwd-files are owned by root)
ac933e 2760             */
c77103 2761             //$this->_exec('chown ' . $user . ':' . $group . ' ' . escapeshellcmd($webdav_user_dir.' -R'));
T 2762             //$this->_exec('chmod 770 ' . escapeshellcmd($webdav_user_dir.' -R'));
b1a6a5 2763             $app->system->chown($webdav_user_dir, $user);
MC 2764             $app->system->chgrp($webdav_user_dir, $group);
2765             $app->system->chmod($webdav_user_dir, 0770);
ca14fe 2766
V 2767             /*
2768              * if the user is active, we have to write/update the password - file
2769              * if the user is inactive, we have to inactivate the user by removing the user from the file
2770             */
2771             if ($data['new']['active'] == 'y') {
b67344 2772                 $this->_writeHtDigestFile( $webdav_user_dir . '.htdigest', $data['new']['username'], $data['new']['dir'], $data['new']['password']);
ca14fe 2773             }
V 2774             else {
2775                 /* empty pwd removes the user! */
b67344 2776                 $this->_writeHtDigestFile( $webdav_user_dir . '.htdigest', $data['new']['username'], $data['new']['dir'], '');
ca14fe 2777             }
ac933e 2778
V 2779             /*
2780              * Next step, patch the vhost - file
2781             */
fb3339 2782             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'] . '/' . $domain . '.vhost');
ac933e 2783             $this->_patchVhostWebdav($vhost_file, $documentRoot . '/webdav');
ca14fe 2784
ac933e 2785             /*
V 2786              * Last, restart apache
2787             */
2788             if($apache_chrooted) {
b1a6a5 2789                 $app->services->restartServiceDelayed('httpd', 'restart');
ac933e 2790             } else {
V 2791                 // request a httpd reload when all records have been processed
b1a6a5 2792                 $app->services->restartServiceDelayed('httpd', 'reload');
ac933e 2793             }
V 2794
2795         }
2796
2797         if ($event_name == 'webdav_user_delete') {
2798             /*
2799              * Get additional informations
2800             */
2af58c 2801             $sitedata = $app->db->queryOneRecord('SELECT document_root, domain FROM web_domain WHERE domain_id = ?', $data['old']['parent_domain_id']);
ac933e 2802             $documentRoot = $sitedata['document_root'];
52a04e 2803             $domain = $sitedata['domain'];
ac933e 2804
V 2805             /*
2806              * We dont't want to destroy any (transfer)-Data. So we do NOT delete any dir.
2807              * So the only thing, we have to do, is to delete the user from the password-file
ca14fe 2808             */
ac933e 2809             $this->_writeHtDigestFile( $documentRoot . '/webdav/' . $data['old']['dir'] . '.htdigest', $data['old']['username'], $data['old']['dir'], '');
b1a6a5 2810
52a04e 2811             /*
T 2812              * Next step, patch the vhost - file
2813             */
fb3339 2814             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'] . '/' . $domain . '.vhost');
52a04e 2815             $this->_patchVhostWebdav($vhost_file, $documentRoot . '/webdav');
b1a6a5 2816
52a04e 2817             /*
T 2818              * Last, restart apache
2819             */
2820             if($apache_chrooted) {
b1a6a5 2821                 $app->services->restartServiceDelayed('httpd', 'restart');
52a04e 2822             } else {
T 2823                 // request a httpd reload when all records have been processed
b1a6a5 2824                 $app->services->restartServiceDelayed('httpd', 'reload');
52a04e 2825             }
ac933e 2826         }
V 2827     }
2828
2829
2830     /**
2831      * This function writes the htdigest - files used by webdav and digest
ca14fe 2832      * more info: see http://riceball.com/d/node/424
ac933e 2833      * @author Oliver Vogel
V 2834      * @param string $filename The name of the digest-file
2835      * @param string $username The name of the webdav-user
2836      * @param string $authname The name of the realm
ca14fe 2837      * @param string $pwd      The password-hash of the user
ac933e 2838      */
ca14fe 2839     private function _writeHtDigestFile($filename, $username, $authname, $pwdhash ) {
4bd960 2840         global $app;
b1a6a5 2841
ac933e 2842         $changed = false;
c77103 2843         if(is_file($filename) && !is_link($filename)) {
0ff3f1 2844             $in = fopen($filename, 'r');
T 2845             $output = '';
2846             /*
2847             * read line by line and search for the username and authname
2848             */
2849             while (preg_match("/:/", $line = fgets($in))) {
2850                 $line = rtrim($line);
2851                 $tmp = explode(':', $line);
2852                 if ($tmp[0] == $username && $tmp[1] == $authname) {
2853                     /*
2854                     * found the user. delete or change it?
2855                     */
2856                     if ($pwdhash != '') {
2857                         $output .= $tmp[0] . ':' . $tmp[1] . ':' . $pwdhash . "\n";
b1a6a5 2858                     }
0ff3f1 2859                     $changed = true;
T 2860                 }
2861                 else {
2862                     $output .= $line . "\n";
2863                 }
ac933e 2864             }
0ff3f1 2865             fclose($in);
ac933e 2866         }
V 2867         /*
2868          * if we didn't change anything, we have to add the new user at the end of the file
2869         */
2870         if (!$changed) {
f17dab 2871             $output .= $username . ':' . $authname . ':' . $pwdhash . "\n";
ac933e 2872         }
b1a6a5 2873
ac933e 2874
V 2875         /*
2876          * Now lets write the new file
2877         */
52a04e 2878         if(trim($output) == '') {
c77103 2879             $app->system->unlink($filename);
52a04e 2880         } else {
c77103 2881             $app->system->file_put_contents($filename, $output);
52a04e 2882         }
ac933e 2883     }
V 2884
2885     /**
2886      * This function patches the vhost-file and adds all webdav - user.
2887      * This function is written, because the creation of the vhost - file is sophisticated and
2888      * i don't want to make it more "heavy" by also adding this code too...
2889      * @author Oliver Vogel
2890      * @param string $fileName The Name of the .vhost-File (path included)
2891      * @param string $webdavRoot The root of the webdav-folder
2892      */
2893     private function _patchVhostWebdav($fileName, $webdavRoot) {
c77103 2894         global $app;
ac933e 2895         $in = fopen($fileName, 'r');
V 2896         $output = '';
2897         $inWebdavSection = false;
2898
2899         /*
2900          * read line by line and search for the username and authname
2901         */
2902         while ($line = fgets($in)) {
2903             /*
2904              *  is the "replace-comment" found...
2905             */
2906             if (trim($line) == '# WEBDAV BEGIN') {
2907                 /*
2908                  * The begin of the webdav - section is found, so ignore all lines til the end  is found
2909                 */
2910                 $inWebdavSection = true;
2911
2912                 $output .= "      # WEBDAV BEGIN\n";
2913
2914                 /*
2915                  * add all the webdav-dirs to the webdav-section
2916                 */
fb3a98 2917                 $files = @scandir($webdavRoot);
T 2918                 if(is_array($files)) {
b1a6a5 2919                     foreach($files as $file) {
MC 2920                         if (substr($file, strlen($file) - strlen('.htdigest')) == '.htdigest' && preg_match("/^[a-zA-Z0-9\-_\.]*$/", $file)) {
2921                             /*
ac933e 2922                          * found a htdigest - file, so add it to webdav
V 2923                         */
b1a6a5 2924                             $fn = substr($file, 0, strlen($file) - strlen('.htdigest'));
MC 2925                             $output .= "\n";
2926                             // $output .= "      Alias /" . $fn . ' ' . $webdavRoot . '/' . $fn . "\n";
2927                             // $output .= "      <Location /" . $fn . ">\n";
2928                             $output .= "      Alias /webdav/" . $fn . ' ' . $webdavRoot . '/' . $fn . "\n";
2929                             $output .= "      <Location /webdav/" . $fn . ">\n";
2930                             $output .= "        DAV On\n";
2931                             $output .= '        BrowserMatch "MSIE" AuthDigestEnableQueryStringHack=On'."\n";
2932                             $output .= "        AuthType Digest\n";
2933                             $output .= "        AuthName \"" . $fn . "\"\n";
2934                             $output .= "        AuthUserFile " . $webdavRoot . '/' . $file . "\n";
2935                             $output .= "        Require valid-user \n";
2936                             $output .= "        Options +Indexes \n";
2937                             $output .= "        Order allow,deny \n";
2938                             $output .= "        Allow from all \n";
2939                             $output .= "      </Location> \n";
2940                         }
ac933e 2941                     }
fb3a98 2942                 }
ac933e 2943             }
V 2944             /*
2945              *  is the "replace-comment-end" found...
2946             */
2947             if (trim($line) == '# WEBDAV END') {
2948                 /*
2949                  * The end of the webdav - section is found, so stop ignoring
2950                 */
2951                 $inWebdavSection = false;
2952             }
2953
2954             /*
2955              * Write the line to the output, if it is not in the section
2956             */
2957             if (!$inWebdavSection) {
2958                 $output .= $line;
2959             }
2960         }
2961         fclose($in);
2962
2963         /*
2964          * Now lets write the new file
2965         */
c77103 2966         $app->system->file_put_contents($fileName, $output);
ac933e 2967
V 2968     }
b1a6a5 2969
58c210 2970     //* Update the awstats configuration file
b1a6a5 2971     private function awstats_update ($data, $web_config) {
58c210 2972         global $app;
b1a6a5 2973
MC 2974         $web_folder = $data['new']['web_folder'];
2975         if($data['new']['type'] == 'vhost') $web_folder = 'web';
2a6eac 2976         $awstats_conf_dir = $web_config['awstats_conf_dir'];
b1a6a5 2977
6fb93d 2978         if(!is_dir($data['new']['document_root']."/" . $web_folder . "/stats/")) mkdir($data['new']['document_root']."/" . $web_folder . "/stats");
fb3339 2979         if(!@is_file($awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf') || ($data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain'])) {
J 2980             if ( @is_file($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf') ) {
c77103 2981                 $app->system->unlink($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf');
58c210 2982             }
b1a6a5 2983
58c210 2984             $content = '';
e6abfe 2985             if (is_file($awstats_conf_dir."/awstats.conf")) {
CS 2986                 $include_file = $awstats_conf_dir."/awstats.conf";
2987             } elseif (is_file($awstats_conf_dir."/awstats.model.conf")) {
2988                 $include_file = $awstats_conf_dir."/awstats.model.conf";
2989             }
de6d2e 2990             $content .= "Include \"".$include_file."\"\n";
fb3339 2991             $content .= "LogFile=\"/var/log/ispconfig/httpd/".$data['new']['domain']."/access.log\"\n";
J 2992             $content .= "SiteDomain=\"".$data['new']['domain']."\"\n";
2993             $content .= "HostAliases=\"www.".$data['new']['domain']."  localhost 127.0.0.1\"\n";
b1a6a5 2994
9aaf97 2995             if (isset($include_file)) {
CS 2996                 $app->system->file_put_contents($awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf', $content);
2997                 $app->log('Created AWStats config file: '.$awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf', LOGLEVEL_DEBUG);
2998             } else {
2999                 $app->log("No awstats base config found. Either awstats.conf or awstats.model.conf must exist in ".$awstats_conf_dir.".", LOGLEVEL_WARN);
3000             }
58c210 3001         }
b1a6a5 3002
6fb93d 3003         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 3004         if(file_exists("/usr/local/ispconfig/server/conf-custom/awstats_index.php.master")) {
b1a6a5 3005             $app->system->copy("/usr/local/ispconfig/server/conf-custom/awstats_index.php.master", $data['new']['document_root']."/" . $web_folder . "/stats/index.php");
a464e1 3006         } else {
b1a6a5 3007             $app->system->copy("/usr/local/ispconfig/server/conf/awstats_index.php.master", $data['new']['document_root']."/" . $web_folder . "/stats/index.php");
a464e1 3008         }
58c210 3009     }
b1a6a5 3010
58c210 3011     //* Delete the awstats configuration file
b1a6a5 3012     private function awstats_delete ($data, $web_config) {
58c210 3013         global $app;
b1a6a5 3014
58c210 3015         $awstats_conf_dir = $web_config['awstats_conf_dir'];
b1a6a5 3016
fb3339 3017         if ( @is_file($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf') ) {
c77103 3018             $app->system->unlink($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf');
b1a6a5 3019             $app->log('Removed AWStats config file: '.$awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf', LOGLEVEL_DEBUG);
58c210 3020         }
T 3021     }
b1a6a5 3022
c59632 3023     private function hhvm_update($data, $web_config) {
MC 3024         global $app, $conf;
3025         
3026         if(file_exists($conf['rootpath'] . '/conf-custom/hhvm_starter.master')) {
3027             $content = file_get_contents($conf['rootpath'] . '/conf-custom/hhvm_starter.master');
3028         } else {
3029             $content = file_get_contents($conf['rootpath'] . '/conf/hhvm_starter.master');
3030         }
cab08c 3031         if(file_exists($conf['rootpath'] . '/conf-custom/hhvm_monit.master')) {
MC 3032             $monit_content = file_get_contents($conf['rootpath'] . '/conf-custom/hhvm_monit.master');
3033         } else {
3034             $monit_content = file_get_contents($conf['rootpath'] . '/conf/hhvm_monit.master');
3035         }
c59632 3036         
d22277 3037         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 3038         
MC 3039             // Custom php.ini settings
3040             $custom_php_ini_settings = trim($data['new']['custom_php_ini']);
3041             if(intval($data['new']['directive_snippets_id']) > 0){
d22277 3042                 $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 3043                 if(isset($snippet['required_php_snippets']) && trim($snippet['required_php_snippets']) != ''){
MC 3044                     $required_php_snippets = explode(',', trim($snippet['required_php_snippets']));
3045                     if(is_array($required_php_snippets) && !empty($required_php_snippets)){
3046                         foreach($required_php_snippets as $required_php_snippet){
3047                             $required_php_snippet = intval($required_php_snippet);
3048                             if($required_php_snippet > 0){
d22277 3049                                 $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 3050                                 $php_snippet['snippet'] = trim($php_snippet['snippet']);
MC 3051                                 if($php_snippet['snippet'] != ''){
3052                                     $custom_php_ini_settings .= "\n".$php_snippet['snippet'];
3053                                 }
3054                             }
3055                         }
3056                     }
3057                 }
3058             }
3059             if($custom_php_ini_settings != ''){
3060                 // Make sure we only have Unix linebreaks
3061                 $custom_php_ini_settings = str_replace("\r\n", "\n", $custom_php_ini_settings);
3062                 $custom_php_ini_settings = str_replace("\r", "\n", $custom_php_ini_settings);
3063                 file_put_contents('/etc/hhvm/'.$data['new']['system_user'].'.ini', $custom_php_ini_settings);
3064             } else {
d22277 3065                 if($data['old']['system_user'] != '' && is_file('/etc/hhvm/'.$data['old']['system_user'].'.ini')) unlink('/etc/hhvm/'.$data['old']['system_user'].'.ini');
d5f2d5 3066             }
MC 3067             
1c6da3 3068             $content = str_replace('{SYSTEM_USER}', $data['new']['system_user'], $content);
c59632 3069             file_put_contents('/etc/init.d/hhvm_' . $data['new']['system_user'], $content);
MC 3070             exec('chmod +x /etc/init.d/hhvm_' . $data['new']['system_user'] . ' >/dev/null 2>&1');
3071             exec('/usr/sbin/update-rc.d hhvm_' . $data['new']['system_user'] . ' defaults >/dev/null 2>&1');
02e7ea 3072             exec('/etc/init.d/hhvm_' . $data['new']['system_user'] . ' restart >/dev/null 2>&1');
cab08c 3073             
02e7ea 3074             if(is_dir('/etc/monit/conf.d')){
MC 3075                 $monit_content = str_replace('{SYSTEM_USER}', $data['new']['system_user'], $monit_content);
3076                 file_put_contents('/etc/monit/conf.d/00-hhvm_' . $data['new']['system_user'], $monit_content);
3077                 if(is_file('/etc/monit/conf.d/hhvm_' . $data['new']['system_user'])) unlink('/etc/monit/conf.d/hhvm_' . $data['new']['system_user']);
3078                 exec('/etc/init.d/monit restart >/dev/null 2>&1');
3079             }
cab08c 3080             
c59632 3081          } elseif($data['new']['php'] != 'hhvm' && $data['old']['php'] == 'hhvm') {
d22277 3082             if($data['old']['system_user'] != ''){
MB 3083                 exec('/etc/init.d/hhvm_' . $data['old']['system_user'] . ' stop >/dev/null 2>&1');
3084                 exec('/usr/sbin/update-rc.d hhvm_' . $data['old']['system_user'] . ' remove >/dev/null 2>&1');
3085                 unlink('/etc/init.d/hhvm_' . $data['old']['system_user']);
3086                 if(is_file('/etc/hhvm/'.$data['old']['system_user'].'.ini')) unlink('/etc/hhvm/'.$data['old']['system_user'].'.ini');
3087             }
cab08c 3088             
02e7ea 3089             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 3090                 if(is_file('/etc/monit/conf.d/hhvm_' . $data['new']['system_user'])){
3091                     unlink('/etc/monit/conf.d/hhvm_' . $data['new']['system_user']);
3092                 }
3093                 if(is_file('/etc/monit/conf.d/00-hhvm_' . $data['new']['system_user'])){
3094                     unlink('/etc/monit/conf.d/00-hhvm_' . $data['new']['system_user']);
3095                 }
cab08c 3096                 exec('/etc/init.d/monit restart >/dev/null 2>&1');
MC 3097             }
c59632 3098         }
MC 3099     }
3100
274362 3101     //* Update the PHP-FPM pool configuration file
b1a6a5 3102     private function php_fpm_pool_update ($data, $web_config, $pool_dir, $pool_name, $socket_dir) {
274362 3103         global $app, $conf;
ab79c2 3104         $pool_dir = trim($pool_dir);
274362 3105         //$reload = false;
b1a6a5 3106
62e4b3 3107         if($data['new']['php'] == 'php-fpm'){
F 3108             if(trim($data['new']['fastcgi_php_version']) != ''){
3109                 $default_php_fpm = false;
3110                 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 3111                 if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
62e4b3 3112             } else {
F 3113                 $default_php_fpm = true;
3114             }
274362 3115         } else {
62e4b3 3116             if(trim($data['old']['fastcgi_php_version']) != '' && $data['old']['php'] == 'php-fpm'){
F 3117                 $default_php_fpm = false;
3118                 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 3119                 if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
62e4b3 3120             } else {
F 3121                 $default_php_fpm = true;
3122             }
274362 3123         }
b1a6a5 3124
274362 3125         $app->uses("getconf");
F 3126         $web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
b1a6a5 3127
274362 3128         if($data['new']['php'] != 'php-fpm'){
F 3129             if(@is_file($pool_dir.$pool_name.'.conf')){
c77103 3130                 $app->system->unlink($pool_dir.$pool_name.'.conf');
274362 3131                 //$reload = true;
F 3132             }
3133             if($data['old']['php'] == 'php-fpm'){
3134                 if(!$default_php_fpm){
b1a6a5 3135                     $app->services->restartService('php-fpm', 'reload:'.$custom_php_fpm_init_script);
274362 3136                 } else {
b1a6a5 3137                     $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 3138                 }
F 3139             }
3140             //if($reload == true) $app->services->restartService('php-fpm','reload');
3141             return;
3142         }
b1a6a5 3143
274362 3144         $app->load('tpl');
F 3145         $tpl = new tpl();
3146         $tpl->newTemplate('php_fpm_pool.conf.master');
8133de 3147         $tpl->setVar('apache_version', $app->system->getapacheversion());
MC 3148         
c91c7a 3149         $apache_modules = $app->system->getapachemodules();
TB 3150         
6db036 3151         // Use sockets, but not with apache 2.4 on centos (mod_proxy_fcgi) as socket support is buggy in that version
TB 3152         if($data['new']['php_fpm_use_socket'] == 'y' && in_array('fastcgi_module',$apache_modules)){
274362 3153             $use_tcp = 0;
F 3154             $use_socket = 1;
c77103 3155             if(!is_dir($socket_dir)) $app->system->mkdirpath($socket_dir);
274362 3156         } else {
F 3157             $use_tcp = 1;
3158             $use_socket = 0;
3159         }
3160         $tpl->setVar('use_tcp', $use_tcp);
3161         $tpl->setVar('use_socket', $use_socket);
b1a6a5 3162
274362 3163         $fpm_socket = $socket_dir.$pool_name.'.sock';
F 3164         $tpl->setVar('fpm_socket', $fpm_socket);
b491ad 3165         $tpl->setVar('fpm_listen_mode', '0660');
b1a6a5 3166
274362 3167         $tpl->setVar('fpm_pool', $pool_name);
F 3168         $tpl->setVar('fpm_port', $web_config['php_fpm_start_port'] + $data['new']['domain_id'] - 1);
3169         $tpl->setVar('fpm_user', $data['new']['system_user']);
0dfb2d 3170         $tpl->setVar('fpm_group', $web_config['group']);
d33fd2 3171         $tpl->setVar('fpm_domain', $data['new']['domain']);
dd7ce4 3172         $tpl->setVar('pm', $data['new']['pm']);
274362 3173         $tpl->setVar('pm_max_children', $data['new']['pm_max_children']);
F 3174         $tpl->setVar('pm_start_servers', $data['new']['pm_start_servers']);
3175         $tpl->setVar('pm_min_spare_servers', $data['new']['pm_min_spare_servers']);
3176         $tpl->setVar('pm_max_spare_servers', $data['new']['pm_max_spare_servers']);
dd7ce4 3177         $tpl->setVar('pm_process_idle_timeout', $data['new']['pm_process_idle_timeout']);
F 3178         $tpl->setVar('pm_max_requests', $data['new']['pm_max_requests']);
274362 3179         $tpl->setVar('document_root', $data['new']['document_root']);
b1a6a5 3180         $tpl->setVar('security_level', $web_config['security_level']);
f63910 3181         $tpl->setVar('domain', $data['new']['domain']);
274362 3182         $php_open_basedir = ($data['new']['php_open_basedir'] == '')?escapeshellcmd($data['new']['document_root']):escapeshellcmd($data['new']['php_open_basedir']);
F 3183         $tpl->setVar('php_open_basedir', $php_open_basedir);
3184         if($php_open_basedir != ''){
3185             $tpl->setVar('enable_php_open_basedir', '');
3186         } else {
3187             $tpl->setVar('enable_php_open_basedir', ';');
3188         }
b1a6a5 3189
274362 3190         // Custom php.ini settings
F 3191         $final_php_ini_settings = array();
3192         $custom_php_ini_settings = trim($data['new']['custom_php_ini']);
b41803 3193         
MC 3194         if(intval($data['new']['directive_snippets_id']) > 0){
3195             $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']));
3196             if(isset($snippet['required_php_snippets']) && trim($snippet['required_php_snippets']) != ''){
3197                 $required_php_snippets = explode(',', trim($snippet['required_php_snippets']));
3198                 if(is_array($required_php_snippets) && !empty($required_php_snippets)){
3199                     foreach($required_php_snippets as $required_php_snippet){
3200                         $required_php_snippet = intval($required_php_snippet);
3201                         if($required_php_snippet > 0){
d22277 3202                             $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 3203                             $php_snippet['snippet'] = trim($php_snippet['snippet']);
MC 3204                             if($php_snippet['snippet'] != ''){
3205                                 $custom_php_ini_settings .= "\n".$php_snippet['snippet'];
3206                             }
3207                         }
3208                     }
3209                 }
3210             }
3211         }
3212         
9fd930 3213         $custom_session_save_path = false;
274362 3214         if($custom_php_ini_settings != ''){
F 3215             // Make sure we only have Unix linebreaks
3216             $custom_php_ini_settings = str_replace("\r\n", "\n", $custom_php_ini_settings);
3217             $custom_php_ini_settings = str_replace("\r", "\n", $custom_php_ini_settings);
3218             $ini_settings = explode("\n", $custom_php_ini_settings);
3219             if(is_array($ini_settings) && !empty($ini_settings)){
3220                 foreach($ini_settings as $ini_setting){
254a4a 3221                     $ini_setting = trim($ini_setting);
b1a6a5 3222                     if(substr($ini_setting, 0, 1) == ';') continue;
MC 3223                     if(substr($ini_setting, 0, 1) == '#') continue;
3224                     if(substr($ini_setting, 0, 2) == '//') continue;
03cc01 3225                     list($key, $value) = explode('=', $ini_setting, 2);
1d6097 3226                     $value = trim($value);
FT 3227                     if($value != ''){
254a4a 3228                         $key = trim($key);
9fd930 3229                         if($key == 'session.save_path') $custom_session_save_path = true;
254a4a 3230                         switch (strtolower($value)) {
b1a6a5 3231                         case '0':
MC 3232                             // PHP-FPM might complain about invalid boolean value if you use 0
3233                             $value = 'off';
3234                         case '1':
3235                         case 'on':
3236                         case 'off':
3237                         case 'true':
3238                         case 'false':
3239                         case 'yes':
3240                         case 'no':
3241                             $final_php_ini_settings[] = array('ini_setting' => 'php_admin_flag['.$key.'] = '.$value);
3242                             break;
3243                         default:
3244                             $final_php_ini_settings[] = array('ini_setting' => 'php_admin_value['.$key.'] = '.$value);
274362 3245                         }
254a4a 3246                     }
274362 3247                 }
F 3248             }
3249         }
9fd930 3250         
MB 3251         $tpl->setVar('custom_session_save_path', ($custom_session_save_path ? 'y' : 'n'));
3252         
274362 3253         $tpl->setLoop('custom_php_ini_settings', $final_php_ini_settings);
b1a6a5 3254
MC 3255         $app->system->file_put_contents($pool_dir.$pool_name.'.conf', $tpl->grab());
3256         $app->log('Writing the PHP-FPM config file: '.$pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
274362 3257         unset($tpl);
b1a6a5 3258
274362 3259         // delete pool in all other PHP versions
ab79c2 3260         $default_pool_dir = trim(escapeshellcmd($web_config['php_fpm_pool_dir']));
b1a6a5 3261         if(substr($default_pool_dir, -1) != '/') $default_pool_dir .= '/';
274362 3262         if($default_pool_dir != $pool_dir){
F 3263             if ( @is_file($default_pool_dir.$pool_name.'.conf') ) {
b1a6a5 3264                 $app->system->unlink($default_pool_dir.$pool_name.'.conf');
MC 3265                 $app->log('Removed PHP-FPM config file: '.$default_pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
3266                 $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 3267             }
F 3268         }
2af58c 3269         $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 3270         if(is_array($php_versions) && !empty($php_versions)){
F 3271             foreach($php_versions as $php_version){
ab79c2 3272                 $php_version['php_fpm_pool_dir'] = trim($php_version['php_fpm_pool_dir']);
b1a6a5 3273                 if(substr($php_version['php_fpm_pool_dir'], -1) != '/') $php_version['php_fpm_pool_dir'] .= '/';
274362 3274                 if($php_version['php_fpm_pool_dir'] != $pool_dir){
F 3275                     if ( @is_file($php_version['php_fpm_pool_dir'].$pool_name.'.conf') ) {
c77103 3276                         $app->system->unlink($php_version['php_fpm_pool_dir'].$pool_name.'.conf');
b1a6a5 3277                         $app->log('Removed PHP-FPM config file: '.$php_version['php_fpm_pool_dir'].$pool_name.'.conf', LOGLEVEL_DEBUG);
MC 3278                         $app->services->restartService('php-fpm', 'reload:'.$php_version['php_fpm_init_script']);
274362 3279                     }
F 3280                 }
3281             }
3282         }
3283         // Reload current PHP-FPM after all others
3284         sleep(1);
3285         if(!$default_php_fpm){
b1a6a5 3286             $app->services->restartService('php-fpm', 'reload:'.$custom_php_fpm_init_script);
274362 3287         } else {
b1a6a5 3288             $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 3289         }
b1a6a5 3290
274362 3291         //$reload = true;
F 3292
3293         //if($reload == true) $app->services->restartService('php-fpm','reload');
3294     }
b1a6a5 3295
274362 3296     //* Delete the PHP-FPM pool configuration file
b1a6a5 3297     private function php_fpm_pool_delete ($data, $web_config) {
274362 3298         global $app, $conf;
b1a6a5 3299
62e4b3 3300         if(trim($data['old']['fastcgi_php_version']) != '' && $data['old']['php'] == 'php-fpm'){
274362 3301             $default_php_fpm = false;
F 3302             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 3303             if(substr($custom_php_fpm_ini_dir, -1) != '/') $custom_php_fpm_ini_dir .= '/';
274362 3304         } else {
F 3305             $default_php_fpm = true;
3306         }
b1a6a5 3307
274362 3308         if($default_php_fpm){
F 3309             $pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
3310         } else {
3311             $pool_dir = $custom_php_fpm_pool_dir;
3312         }
ab79c2 3313         $pool_dir = trim($pool_dir);
b1a6a5 3314
MC 3315         if(substr($pool_dir, -1) != '/') $pool_dir .= '/';
274362 3316         $pool_name = 'web'.$data['old']['domain_id'];
b1a6a5 3317
274362 3318         if ( @is_file($pool_dir.$pool_name.'.conf') ) {
c77103 3319             $app->system->unlink($pool_dir.$pool_name.'.conf');
b1a6a5 3320             $app->log('Removed PHP-FPM config file: '.$pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
MC 3321
274362 3322             //$app->services->restartService('php-fpm','reload');
F 3323         }
b1a6a5 3324
274362 3325         // delete pool in all other PHP versions
ab79c2 3326         $default_pool_dir = trim(escapeshellcmd($web_config['php_fpm_pool_dir']));
b1a6a5 3327         if(substr($default_pool_dir, -1) != '/') $default_pool_dir .= '/';
274362 3328         if($default_pool_dir != $pool_dir){
F 3329             if ( @is_file($default_pool_dir.$pool_name.'.conf') ) {
b1a6a5 3330                 $app->system->unlink($default_pool_dir.$pool_name.'.conf');
MC 3331                 $app->log('Removed PHP-FPM config file: '.$default_pool_dir.$pool_name.'.conf', LOGLEVEL_DEBUG);
3332                 $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 3333             }
b1a6a5 3334         }
2af58c 3335         $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 3336         if(is_array($php_versions) && !empty($php_versions)){
F 3337             foreach($php_versions as $php_version){
ab79c2 3338                 $php_version['php_fpm_pool_dir'] = trim($php_version['php_fpm_pool_dir']);
b1a6a5 3339                 if(substr($php_version['php_fpm_pool_dir'], -1) != '/') $php_version['php_fpm_pool_dir'] .= '/';
274362 3340                 if($php_version['php_fpm_pool_dir'] != $pool_dir){
F 3341                     if ( @is_file($php_version['php_fpm_pool_dir'].$pool_name.'.conf') ) {
c77103 3342                         $app->system->unlink($php_version['php_fpm_pool_dir'].$pool_name.'.conf');
b1a6a5 3343                         $app->log('Removed PHP-FPM config file: '.$php_version['php_fpm_pool_dir'].$pool_name.'.conf', LOGLEVEL_DEBUG);
MC 3344                         $app->services->restartService('php-fpm', 'reload:'.$php_version['php_fpm_init_script']);
274362 3345                     }
F 3346                 }
3347             }
3348         }
b1a6a5 3349
274362 3350         // Reload current PHP-FPM after all others
F 3351         sleep(1);
3352         if(!$default_php_fpm){
b1a6a5 3353             $app->services->restartService('php-fpm', 'reload:'.$custom_php_fpm_init_script);
274362 3354         } else {
b1a6a5 3355             $app->services->restartService('php-fpm', 'reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
274362 3356         }
F 3357     }
b1a6a5 3358
MC 3359     function client_delete($event_name, $data) {
1ca823 3360         global $app, $conf;
b1a6a5 3361
1ca823 3362         $app->uses("getconf");
T 3363         $web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
b1a6a5 3364
1ca823 3365         $client_id = intval($data['old']['client_id']);
T 3366         if($client_id > 0) {
b1a6a5 3367
1ca823 3368             $client_dir = $web_config['website_basedir'].'/clients/client'.$client_id;
b1a6a5 3369             if(is_dir($client_dir) && !stristr($client_dir, '..')) {
72695f 3370                 // remove symlinks from $client_dir
b1a6a5 3371                 $files = array_diff(scandir($client_dir), array('.', '..'));
72695f 3372                 if(is_array($files) && !empty($files)){
T 3373                     foreach($files as $file){
3374                         if(is_link($client_dir.'/'.$file)){
3375                             unlink($client_dir.'/'.$file);
b1a6a5 3376                             $app->log('Removed symlink: '.$client_dir.'/'.$file, LOGLEVEL_DEBUG);
72695f 3377                         }
T 3378                     }
3379                 }
b1a6a5 3380
1ca823 3381                 @rmdir($client_dir);
b1a6a5 3382                 $app->log('Removed client directory: '.$client_dir, LOGLEVEL_DEBUG);
1ca823 3383             }
b1a6a5 3384
615a0a 3385             if($app->system->is_group('client'.$client_id)){
T 3386                 $this->_exec('groupdel client'.$client_id);
b1a6a5 3387                 $app->log('Removed group client'.$client_id, LOGLEVEL_DEBUG);
615a0a 3388             }
1ca823 3389         }
b1a6a5 3390
1ca823 3391     }
ac933e 3392
1c40af 3393     //* Wrapper for exec function for easier debugging
T 3394     private function _exec($command) {
3395         global $app;
551d9a 3396         $out = array();
MB 3397         $ret = 0;
b1a6a5 3398         $app->log('exec: '.$command, LOGLEVEL_DEBUG);
551d9a 3399         exec($command, $out, $ret);
MB 3400         if($ret != 0) return false;
3401         else return true;
1c40af 3402     }
7ed741 3403
b1a6a5 3404     private function _checkTcp ($host, $port) {
MC 3405
3406         $fp = @fsockopen($host, $port, $errno, $errstr, 2);
7ed741 3407
T 3408         if ($fp) {
3409             fclose($fp);
3410             return true;
3411         } else {
3412             return false;
3413         }
3414     }
ac933e 3415
552178 3416     public function create_relative_link($f, $t) {
bfcdef 3417         global $app;
b1a6a5 3418
552178 3419         // $from already exists
M 3420         $from = realpath($f);
3421
3422         // realpath requires the traced file to exist - so, lets touch it first, then remove
c77103 3423         @$app->system->unlink($t); touch($t);
552178 3424         $to = realpath($t);
c77103 3425         @$app->system->unlink($t);
552178 3426
M 3427         // Remove from the left side matching path elements from $from and $to
3428         // and get path elements counts
3429         $a1 = explode('/', $from); $a2 = explode('/', $to);
3430         for ($c = 0; $a1[$c] == $a2[$c]; $c++) {
3431             unset($a1[$c]); unset($a2[$c]);
3432         }
3433         $cfrom = implode('/', $a1);
3434
3435         // Check if a path is fully a subpath of another - no way to create symlink in the case
3436         if (count($a1) == 0 || count($a2) == 0) return false;
3437
3438         // Add ($cnt_to-1) number of "../" elements to left side of $cfrom
3439         for ($c = 0; $c < (count($a2)-1); $c++) { $cfrom = '../'.$cfrom; }
3440
3441         return symlink($cfrom, $to);
3442     }
46c683 3443
b1a6a5 3444     private function _rewrite_quote($string) {
MC 3445         return str_replace(array('.', '*', '?', '+'), array('\\.', '\\*', '\\?', '\\+'), $string);
3446     }
3447
3448     private function _is_url($string) {
3449         return preg_match('/^(f|ht)tp(s)?:\/\//i', $string);
3450     }
3451
bfcdef 3452     private function get_seo_redirects($web, $prefix = ''){
T 3453         $seo_redirects = array();
b1a6a5 3454
bfcdef 3455         if(substr($web['domain'], 0, 2) === '*.') $web['subdomain'] = '*';
b1a6a5 3456
bfcdef 3457         if($web['subdomain'] == 'www' || $web['subdomain'] == '*'){
T 3458             if($web['seo_redirect'] == 'non_www_to_www'){
3459                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = str_replace('.', '\.', $web['domain']);
3460                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = 'www.'.$web['domain'];
3461                 $seo_redirects[$prefix.'seo_redirect_operator'] = '';
3462             }
3463             if($web['seo_redirect'] == '*_domain_tld_to_www_domain_tld'){
3464                 // ^(example\.com|(?!\bwww\b)\.example\.com)$
3465                 // ^(example\.com|((?:\w+(?:-\w+)*\.)*)((?!www\.)\w+(?:-\w+)*)(\.example\.com))$
3466                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = '('.str_replace('.', '\.', $web['domain']).'|((?:\w+(?:-\w+)*\.)*)((?!www\.)\w+(?:-\w+)*)(\.'.str_replace('.', '\.', $web['domain']).'))';
3467                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = 'www.'.$web['domain'];
3468                 $seo_redirects[$prefix.'seo_redirect_operator'] = '';
3469             }
3470             if($web['seo_redirect'] == '*_to_www_domain_tld'){
3471                 $seo_redirects[$prefix.'seo_redirect_origin_domain'] = 'www\.'.str_replace('.', '\.', $web['domain']);
3472                 $seo_redirects[$prefix.'seo_redirect_target_domain'] = 'www.'.$web['domain'];
3473                 $seo_redirects[$prefix.'seo_redirect_operator'] = '!';
3474             }
3475         }
3476         if($web['seo_redirect'] == 'www_to_non_www'){
3477             $seo_redirects[$prefix.'seo_redirect_origin_domain'] = 'www\.'.str_replace('.', '\.', $web['domain']);
3478             $seo_redirects[$prefix.'seo_redirect_target_domain'] = $web['domain'];
3479             $seo_redirects[$prefix.'seo_redirect_operator'] = '';
3480         }
3481         if($web['seo_redirect'] == '*_domain_tld_to_domain_tld'){
3482             // ^(.+)\.example\.com$
3483             $seo_redirects[$prefix.'seo_redirect_origin_domain'] = '(.+)\.'.str_replace('.', '\.', $web['domain']);
3484             $seo_redirects[$prefix.'seo_redirect_target_domain'] = $web['domain'];
3485             $seo_redirects[$prefix.'seo_redirect_operator'] = '';
3486         }
3487         if($web['seo_redirect'] == '*_to_domain_tld'){
3488             $seo_redirects[$prefix.'seo_redirect_origin_domain'] = str_replace('.', '\.', $web['domain']);
3489             $seo_redirects[$prefix.'seo_redirect_target_domain'] = $web['domain'];
3490             $seo_redirects[$prefix.'seo_redirect_operator'] = '!';
3491         }
3492         return $seo_redirects;
3493     }
b1a6a5 3494
46c683 3495 } // end class
T 3496
c09f04 3497 ?>