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