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