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