tbrehm
2012-05-04 668ba0957994d7d5ab5b0aa5bb7020c52b2a3878
commit | author | age
46c683 1 <?php
T 2
3 /*
4 Copyright (c) 2007 - 2009, Till Brehm, projektfarm Gmbh
5 All rights reserved.
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 = '';
ac933e 38
46c683 39     //* This function is called during ispconfig installation to determine
T 40     //  if a symlink shall be created for this plugin.
41     function onInstall() {
42         global $conf;
ac933e 43
46c683 44         if($conf['services']['web'] == true) {
T 45             return true;
46         } else {
47             return false;
48         }
ac933e 49
46c683 50     }
ac933e 51
V 52
46c683 53     /*
T 54          This function is called when the plugin is loaded
55     */
ac933e 56
46c683 57     function onLoad() {
T 58         global $app;
ac933e 59
46c683 60         /*
T 61         Register for the events
62         */
63         $app->plugins->registerEvent('web_domain_insert',$this->plugin_name,'ssl');
64         $app->plugins->registerEvent('web_domain_update',$this->plugin_name,'ssl');
65         $app->plugins->registerEvent('web_domain_delete',$this->plugin_name,'ssl');
ac933e 66
46c683 67         $app->plugins->registerEvent('web_domain_insert',$this->plugin_name,'insert');
T 68         $app->plugins->registerEvent('web_domain_update',$this->plugin_name,'update');
69         $app->plugins->registerEvent('web_domain_delete',$this->plugin_name,'delete');
ac933e 70
46c683 71         $app->plugins->registerEvent('server_ip_insert',$this->plugin_name,'server_ip');
T 72         $app->plugins->registerEvent('server_ip_update',$this->plugin_name,'server_ip');
73         $app->plugins->registerEvent('server_ip_delete',$this->plugin_name,'server_ip');
ac933e 74
V 75         $app->plugins->registerEvent('webdav_user_insert',$this->plugin_name,'webdav');
76         $app->plugins->registerEvent('webdav_user_update',$this->plugin_name,'webdav');
77         $app->plugins->registerEvent('webdav_user_delete',$this->plugin_name,'webdav');
1ca823 78         
T 79         $app->plugins->registerEvent('client_delete',$this->plugin_name,'client_delete');
524077 80         
T 81         $app->plugins->registerEvent('web_folder_user_insert',$this->plugin_name,'web_folder_user');
82         $app->plugins->registerEvent('web_folder_user_update',$this->plugin_name,'web_folder_user');
83         $app->plugins->registerEvent('web_folder_user_delete',$this->plugin_name,'web_folder_user');
84         
2023a7 85         $app->plugins->registerEvent('web_folder_update',$this->plugin_name,'web_folder_update');
524077 86         $app->plugins->registerEvent('web_folder_delete',$this->plugin_name,'web_folder_delete');
T 87         
46c683 88     }
ac933e 89
46c683 90     // Handle the creation of SSL certificates
T 91     function ssl($event_name,$data) {
92         global $app, $conf;
1a2310 93
L 94         // load the server configuration options
95         $app->uses('getconf');
96         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
97         if ($web_config['CA_path']!='' && !file_exists($web_config['CA_path'].'/openssl.cnf'))
98             $app->log("CA path error, file does not exist:".$web_config['CA_path'].'/openssl.conf',LOGLEVEL_ERROR);    
1ca823 99         
T 100         //* Only vhosts can have a ssl cert
101         if($data["new"]["type"] != "vhost") return;
ac933e 102
fb3339 103         if(!is_dir($data['new']['document_root'].'/ssl')) exec('mkdir -p '.$data['new']['document_root'].'/ssl');
J 104         $ssl_dir = $data['new']['document_root'].'/ssl';
105         $domain = $data['new']['ssl_domain'];
106         $key_file = $ssl_dir.'/'.$domain.'.key.org';
107         $key_file2 = $ssl_dir.'/'.$domain.'.key';
108         $csr_file = $ssl_dir.'/'.$domain.'.csr';
109         $crt_file = $ssl_dir.'/'.$domain.'.crt';
ac933e 110
46c683 111         //* Create a SSL Certificate
fb3339 112         if($data['new']['ssl_action'] == 'create') {
668ba0 113             
T 114             //* Rename files if they exist
115             if(file_exists($key_file)) rename($key_file,$key_file.'.bak');
116             if(file_exists($key_file2)) rename($key_file2,$key_file2.'.bak');
117             if(file_exists($csr_file)) rename($csr_file,$csr_file.'.bak');
118             if(file_exists($crt_file)) rename($crt_file,$crt_file.'.bak');
119             
fb3339 120             $rand_file = $ssl_dir.'/random_file';
ac933e 121             $rand_data = md5(uniqid(microtime(),1));
V 122             for($i=0; $i<1000; $i++) {
123                 $rand_data .= md5(uniqid(microtime(),1));
124                 $rand_data .= md5(uniqid(microtime(),1));
125                 $rand_data .= md5(uniqid(microtime(),1));
126                 $rand_data .= md5(uniqid(microtime(),1));
127             }
128             file_put_contents($rand_file, $rand_data);
46c683 129
ac933e 130             $ssl_password = substr(md5(uniqid(microtime(),1)), 0, 15);
V 131
46c683 132             $ssl_cnf = "        RANDFILE               = $rand_file
T 133
134         [ req ]
6d80f5 135         default_bits           = 2048
46c683 136         default_keyfile        = keyfile.pem
T 137         distinguished_name     = req_distinguished_name
138         attributes             = req_attributes
139         prompt                 = no
140         output_password        = $ssl_password
141
142         [ req_distinguished_name ]
668ba0 143         C                      = ".trim($data['new']['ssl_country'])."
T 144         ST                     = ".trim($data['new']['ssl_state'])."
145         L                      = ".trim($data['new']['ssl_locality'])."
146         O                      = ".trim($data['new']['ssl_organisation'])."
147         OU                     = ".trim($data['new']['ssl_organisation_unit'])."
46c683 148         CN                     = $domain
T 149         emailAddress           = webmaster@".$data['new']['domain']."
150
151         [ req_attributes ]
152         challengePassword              = A challenge password";
ac933e 153
fb3339 154             $ssl_cnf_file = $ssl_dir.'/openssl.conf';
46c683 155             file_put_contents($ssl_cnf_file,$ssl_cnf);
ac933e 156
46c683 157             $rand_file = escapeshellcmd($rand_file);
T 158             $key_file = escapeshellcmd($key_file);
159             $key_file2 = escapeshellcmd($key_file2);
160             $ssl_days = 3650;
161             $csr_file = escapeshellcmd($csr_file);
162             $config_file = escapeshellcmd($ssl_cnf_file);
163             $crt_file = escapeshellcmd($crt_file);
164
ac933e 165             if(is_file($ssl_cnf_file)) {
1a2310 166                 
5c4d55 167                 exec("openssl genrsa -des3 -rand $rand_file -passout pass:$ssl_password -out $key_file 2048");
L 168                 exec("openssl req -new -passin pass:$ssl_password -passout pass:$ssl_password -key $key_file -out $csr_file -days $ssl_days -config $config_file");
1a2310 169                 exec("openssl rsa -passin pass:$ssl_password -in $key_file -out $key_file2");
L 170
171                 if(file_exists($web_config['CA_path'].'/openssl.cnf'))
5c4d55 172                 {
1a2310 173                     exec("openssl ca -batch -out $crt_file -config ".$web_config['CA_path']."/openssl.cnf -passin pass:".$web_config['CA_pass']." -in $csr_file");
5c4d55 174                     $app->log("Creating CA-signed SSL Cert for: $domain",LOGLEVEL_DEBUG);
1a2310 175                     if (filesize($crt_file)==0 || !file_exists($crt_file)) $app->log("CA-Certificate signing failed.  openssl ca -out $crt_file -config ".$web_config['CA_path']."/openssl.cnf -passin pass:".$web_config['CA_pass']." -in $csr_file",LOGLEVEL_ERROR);
L 176                 };
f442da 177                 if (@filesize($crt_file)==0 || !file_exists($crt_file)){
5c4d55 178                     exec("openssl req -x509 -passin pass:$ssl_password -passout pass:$ssl_password -key $key_file -in $csr_file -out $crt_file -days $ssl_days -config $config_file ");
L 179                     $app->log("Creating self-signed SSL Cert for: $domain",LOGLEVEL_DEBUG);
180                 };
1a2310 181             
ac933e 182             }
46c683 183
fb3339 184             exec('chmod 400 '.$key_file2);
ac933e 185             @unlink($config_file);
V 186             @unlink($rand_file);
187             $ssl_request = $app->db->quote(file_get_contents($csr_file));
188             $ssl_cert = $app->db->quote(file_get_contents($crt_file));
d1086f 189             /* Update the DB of the (local) Server */
fb3339 190             $app->db->query("UPDATE web_domain SET ssl_request = '$ssl_request', ssl_cert = '$ssl_cert' WHERE domain = '".$data['new']['domain']."'");
J 191             $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
d1086f 192             /* Update also the master-DB of the Server-Farm */
fb3339 193             $app->dbmaster->query("UPDATE web_domain SET ssl_request = '$ssl_request', ssl_cert = '$ssl_cert' WHERE domain = '".$data['new']['domain']."'");
J 194             $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
46c683 195         }
ac933e 196
46c683 197         //* Save a SSL certificate to disk
9f56bd 198         if($data["new"]["ssl_action"] == 'save') {
T 199             $ssl_dir = $data["new"]["document_root"]."/ssl";
662d4c 200             $domain = ($data["new"]["ssl_domain"] != '')?$data["new"]["ssl_domain"]:$data["new"]["domain"];
9f56bd 201             $csr_file = $ssl_dir.'/'.$domain.".csr";
T 202             $crt_file = $ssl_dir.'/'.$domain.".crt";
203             $bundle_file = $ssl_dir.'/'.$domain.".bundle";
204             if(trim($data["new"]["ssl_request"]) != '') file_put_contents($csr_file,$data["new"]["ssl_request"]);
205             if(trim($data["new"]["ssl_cert"]) != '') file_put_contents($crt_file,$data["new"]["ssl_cert"]);
206             if(trim($data["new"]["ssl_bundle"]) != '') file_put_contents($bundle_file,$data["new"]["ssl_bundle"]);
d1086f 207             /* Update the DB of the (local) Server */
fb3339 208             $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
d1086f 209             /* Update also the master-DB of the Server-Farm */
fb3339 210             $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
J 211             $app->log('Saving SSL Cert for: '.$domain,LOGLEVEL_DEBUG);
46c683 212         }
ac933e 213
46c683 214         //* Delete a SSL certificate
fb3339 215         if($data['new']['ssl_action'] == 'del') {
J 216             $ssl_dir = $data['new']['document_root'].'/ssl';
662d4c 217             $domain = ($data["new"]["ssl_domain"] != '')?$data["new"]["ssl_domain"]:$data["new"]["domain"];
fb3339 218             $csr_file = $ssl_dir.'/'.$domain.'.csr';
J 219             $crt_file = $ssl_dir.'/'.$domain.'.crt';
220             $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
1a2310 221             if(file_exists($web_config['CA_path'].'/openssl.cnf'))
5c4d55 222                 {
1a2310 223                     exec("openssl ca -batch -config ".$web_config['CA_path']."/openssl.cnf -passin pass:".$web_config['CA_pass']." -revoke $crt_file");
5c4d55 224                     $app->log("Revoking CA-signed SSL Cert for: $domain",LOGLEVEL_DEBUG);
L 225                 };
46c683 226             unlink($csr_file);
T 227             unlink($crt_file);
228             unlink($bundle_file);
d1086f 229             /* Update the DB of the (local) Server */
fb3339 230             $app->db->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '' WHERE domain = '".$data['new']['domain']."'");
J 231             $app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
d1086f 232             /* Update also the master-DB of the Server-Farm */
fb3339 233             $app->dbmaster->query("UPDATE web_domain SET ssl_request = '', ssl_cert = '' WHERE domain = '".$data['new']['domain']."'");
J 234             $app->dbmaster->query("UPDATE web_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
235             $app->log('Deleting SSL Cert for: '.$domain,LOGLEVEL_DEBUG);
46c683 236         }
ac933e 237
46c683 238     }
ac933e 239
V 240
46c683 241     function insert($event_name,$data) {
T 242         global $app, $conf;
ac933e 243
46c683 244         $this->action = 'insert';
T 245         // just run the update function
246         $this->update($event_name,$data);
ac933e 247
V 248
46c683 249     }
ac933e 250
V 251
46c683 252     function update($event_name,$data) {
T 253         global $app, $conf;
ac933e 254
46c683 255         if($this->action != 'insert') $this->action = 'update';
ac933e 256
fb3339 257         if($data['new']['type'] != 'vhost' && $data['new']['parent_domain_id'] > 0) {
ac933e 258
fb3339 259             $old_parent_domain_id = intval($data['old']['parent_domain_id']);
J 260             $new_parent_domain_id = intval($data['new']['parent_domain_id']);
ac933e 261
1ca823 262             // If the parent_domain_id has been changed, we will have to update the old site as well.
fb3339 263             if($this->action == 'update' && $data['new']['parent_domain_id'] != $data['old']['parent_domain_id']) {
J 264                 $tmp = $app->db->queryOneRecord('SELECT * FROM web_domain WHERE domain_id = '.$old_parent_domain_id." AND active = 'y'");
265                 $data['new'] = $tmp;
266                 $data['old'] = $tmp;
46c683 267                 $this->action = 'update';
T 268                 $this->update($event_name,$data);
269             }
ac933e 270
46c683 271             // This is not a vhost, so we need to update the parent record instead.
fb3339 272             $tmp = $app->db->queryOneRecord('SELECT * FROM web_domain WHERE domain_id = '.$new_parent_domain_id." AND active = 'y'");
J 273             $data['new'] = $tmp;
274             $data['old'] = $tmp;
46c683 275             $this->action = 'update';
T 276         }
ac933e 277
46c683 278         // load the server configuration options
fb3339 279         $app->uses('getconf');
J 280         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
ac933e 281
2bbc4c 282         //* Check if this is a chrooted setup
155cc0 283         if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
2bbc4c 284             $apache_chrooted = true;
fb3339 285             $app->log('Info: Apache is chrooted.',LOGLEVEL_DEBUG);
2bbc4c 286         } else {
T 287             $apache_chrooted = false;
288         }
ac933e 289
fb3339 290         if($data['new']['document_root'] == '') {
J 291             $app->log('document_root not set',LOGLEVEL_WARN);
46c683 292             return 0;
T 293         }
fb3339 294         if($data['new']['system_user'] == 'root' or $data['new']['system_group'] == 'root') {
J 295             $app->log('Websites cannot be owned by the root user or group.',LOGLEVEL_WARN);
46c683 296             return 0;
T 297         }
9add99 298         if(trim($data['new']['domain']) == '') {
T 299             $app->log('domain is empty',LOGLEVEL_WARN);
300             return 0;
301         }
dba68f 302         
T 303         // Create group and user, if not exist
304         $app->uses('system');
8d49ef 305         
T 306         if($web_config['connect_userid_to_webid'] == 'y') {
9de299 307             //* Calculate the uid and gid
8d49ef 308             $connect_userid_to_webid_start = ($web_config['connect_userid_to_webid_start'] < 1000)?1000:intval($web_config['connect_userid_to_webid_start']);
T 309             $fixed_uid_gid = intval($connect_userid_to_webid_start + $data['new']['domain_id']);
310             $fixed_uid_param = '--uid '.$fixed_uid_gid;
311             $fixed_gid_param = '--gid '.$fixed_uid_gid;
9de299 312             
T 313             //* Check if a ispconfigend user and group exists and create them
314             if(!$app->system->is_group('ispconfigend')) {
315                 exec('groupadd --gid '.($connect_userid_to_webid_start + 10000).' ispconfigend');
316             }
317             if(!$app->system->is_user('ispconfigend')) {
318                 exec('useradd -g ispconfigend -d /usr/local/ispconfig --uid '.($connect_userid_to_webid_start + 10000).' ispconfigend');
319             }
8d49ef 320         } else {
T 321             $fixed_uid_param = '';
322             $fixed_gid_param = '';
323         }
dba68f 324
T 325         $groupname = escapeshellcmd($data['new']['system_group']);
326         if($data['new']['system_group'] != '' && !$app->system->is_group($data['new']['system_group'])) {
8d49ef 327             exec('groupadd '.$fixed_gid_param.' '.$groupname);
dba68f 328             if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' groupadd '.$groupname);
T 329             $app->log('Adding the group: '.$groupname,LOGLEVEL_DEBUG);
330         }
331
332         $username = escapeshellcmd($data['new']['system_user']);
333         if($data['new']['system_user'] != '' && !$app->system->is_user($data['new']['system_user'])) {
8d49ef 334             if($web_config['add_web_users_to_sshusers_group'] == 'y') {
T 335                 exec('useradd -d '.escapeshellcmd($data['new']['document_root'])." -g $groupname $fixed_uid_param -G sshusers $username -s /bin/false");
336                 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");
337             } else {
338                 exec('useradd -d '.escapeshellcmd($data['new']['document_root'])." -g $groupname $fixed_uid_param $username -s /bin/false");
339                 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");
340             }
dba68f 341             $app->log('Adding the user: '.$username,LOGLEVEL_DEBUG);
T 342         }
ac933e 343
46c683 344         //* If the client of the site has been changed, we have a change of the document root
fb3339 345         if($this->action == 'update' && $data['new']['document_root'] != $data['old']['document_root']) {
ac933e 346
46c683 347             //* Get the old client ID
fb3339 348             $old_client = $app->dbmaster->queryOneRecord('SELECT client_id FROM sys_group WHERE sys_group.groupid = '.intval($data['old']['sys_groupid']));
J 349             $old_client_id = intval($old_client['client_id']);
46c683 350             unset($old_client);
ac933e 351
46c683 352             //* Remove the old symlinks
fb3339 353             $tmp_symlinks_array = explode(':',$web_config['website_symlinks']);
46c683 354             if(is_array($tmp_symlinks_array)) {
T 355                 foreach($tmp_symlinks_array as $tmp_symlink) {
fb3339 356                     $tmp_symlink = str_replace('[client_id]',$old_client_id,$tmp_symlink);
J 357                     $tmp_symlink = str_replace('[website_domain]',$data['old']['domain'],$tmp_symlink);
46c683 358                     // Remove trailing slash
T 359                     if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
360                     // create the symlinks, if not exist
436975 361                     if(is_link($tmp_symlink)) {
fb3339 362                         exec('rm -f '.escapeshellcmd($tmp_symlink));
J 363                         $app->log('Removed symlink: rm -f '.$tmp_symlink,LOGLEVEL_DEBUG);
46c683 364                     }
T 365                 }
366             }
ac933e 367
46c683 368             //* Move the site data
fb3339 369             $tmp_docroot = explode('/',$data['new']['document_root']);
46c683 370             unset($tmp_docroot[count($tmp_docroot)-1]);
T 371             $new_dir = implode('/',$tmp_docroot);
ac933e 372
fb3339 373             $tmp_docroot = explode('/',$data['old']['document_root']);
46c683 374             unset($tmp_docroot[count($tmp_docroot)-1]);
T 375             $old_dir = implode('/',$tmp_docroot);
ac933e 376
0d8022 377             //* 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
T 378             if(@is_dir($data['new']['document_root'])) {
379                 rename($data['new']['document_root'],$data['new']['document_root'].'_bak_'.date('Y_m_d'));
380                 $app->log('Renaming existing directory in new docroot location. mv '.$data['new']['document_root'].' '.$data['new']['document_root'].'_bak_'.date('Y_m_d'),LOGLEVEL_DEBUG);
381             }
382             
383             //* Create new base directory, if it does not exist yet
46c683 384             if(!is_dir($new_dir)) exec('mkdir -p '.$new_dir);
fb3339 385             exec('mv '.$data['old']['document_root'].' '.$new_dir);
J 386             $app->log('Moving site to new document root: mv '.$data['old']['document_root'].' '.$new_dir,LOGLEVEL_DEBUG);
ac933e 387
0930f5 388             // Handle the change in php_open_basedir
L 389             $data['new']['php_open_basedir'] = str_replace($data['old']['document_root'],$data['new']['document_root'],$data['old']['php_open_basedir']);
390
fda480 391             //* Change the owner of the website files to the new website owner
fb3339 392             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);
ac933e 393
46c683 394             //* Change the home directory and group of the website user
T 395             $command = 'usermod';
fb3339 396             $command .= ' --home '.escapeshellcmd($data['new']['document_root']);
46c683 397             $command .= ' --gid '.escapeshellcmd($data['new']['system_group']);
fb3339 398             $command .= ' '.escapeshellcmd($data['new']['system_user']);
46c683 399             exec($command);
ac933e 400
fb3339 401             if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' '.$command);
ac933e 402
V 403
46c683 404         }
ac933e 405
46c683 406         //print_r($data);
ac933e 407
fb3339 408         // Check if the directories are there and create them if necessary.
J 409         if(!is_dir($data['new']['document_root'].'/web')) exec('mkdir -p '.$data['new']['document_root'].'/web');
410         if(!is_dir($data['new']['document_root'].'/web/error') and $data['new']['errordocs']) exec('mkdir -p '.$data['new']['document_root'].'/web/error');
411         //if(!is_dir($data['new']['document_root'].'/log')) exec('mkdir -p '.$data['new']['document_root'].'/log');
412         if(!is_dir($data['new']['document_root'].'/ssl')) exec('mkdir -p '.$data['new']['document_root'].'/ssl');
413         if(!is_dir($data['new']['document_root'].'/cgi-bin')) exec('mkdir -p '.$data['new']['document_root'].'/cgi-bin');
414         if(!is_dir($data['new']['document_root'].'/tmp')) exec('mkdir -p '.$data['new']['document_root'].'/tmp');
ac933e 415
46c683 416         // Remove the symlink for the site, if site is renamed
fb3339 417         if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
J 418             if(is_dir('/var/log/ispconfig/httpd/'.$data['old']['domain'])) exec('rm -rf /var/log/ispconfig/httpd/'.$data['old']['domain']);
419             if(is_link($data['old']['document_root'].'/log')) unlink($data['old']['document_root'].'/log');
46c683 420         }
ac933e 421
46c683 422         // Create the symlink for the logfiles
fb3339 423         if(!is_dir('/var/log/ispconfig/httpd/'.$data['new']['domain'])) exec('mkdir -p /var/log/ispconfig/httpd/'.$data['new']['domain']);
J 424         if(!is_link($data['new']['document_root'].'/log')) {
552178 425 //            exec("ln -s /var/log/ispconfig/httpd/".$data["new"]["domain"]." ".$data["new"]["document_root"]."/log");
M 426             if ($web_config["website_symlinks_rel"] == 'y') {
427                 $this->create_relative_link("/var/log/ispconfig/httpd/".$data["new"]["domain"], $data["new"]["document_root"]."/log");
428             } else {
429                 exec("ln -s /var/log/ispconfig/httpd/".$data["new"]["domain"]." ".$data["new"]["document_root"]."/log");
430             }
431
fb3339 432             $app->log('Creating symlink: ln -s /var/log/ispconfig/httpd/'.$data['new']['domain'].' '.$data['new']['document_root'].'/log',LOGLEVEL_DEBUG);
46c683 433         }
T 434         /*
435         // Create the symlink for the logfiles
fb3339 436         // This does not work as vlogger cannot log trough symlinks.
J 437         if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
438             if(is_dir($data['old']['document_root'].'/log')) exec('rm -rf '.$data['old']['document_root'].'/log');
439             if(is_link('/var/log/ispconfig/httpd/'.$data['old']['domain'])) unlink('/var/log/ispconfig/httpd/'.$data['old']['domain']);
46c683 440         }
T 441         
442         // Create the symlink for the logfiles
fb3339 443         if(!is_dir($data['new']['document_root'].'/log')) exec('mkdir -p '.$data['new']['document_root'].'/log');
J 444         if(!is_link('/var/log/ispconfig/httpd/'.$data['new']['domain'])) {
445             exec('ln -s '.$data['new']['document_root'].'/log /var/log/ispconfig/httpd/'.$data['new']['domain']);
446             $app->log('Creating symlink: ln -s '.$data['new']['document_root'].'/log /var/log/ispconfig/httpd/'.$data['new']['domain'],LOGLEVEL_DEBUG);
46c683 447         }
T 448         */
ac933e 449
46c683 450         // Get the client ID
fb3339 451         $client = $app->dbmaster->queryOneRecord('SELECT client_id FROM sys_group WHERE sys_group.groupid = '.intval($data['new']['sys_groupid']));
J 452         $client_id = intval($client['client_id']);
46c683 453         unset($client);
ac933e 454
46c683 455         // Remove old symlinks, if site is renamed
fb3339 456         if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
J 457             $tmp_symlinks_array = explode(':',$web_config['website_symlinks']);
46c683 458             if(is_array($tmp_symlinks_array)) {
T 459                 foreach($tmp_symlinks_array as $tmp_symlink) {
fb3339 460                     $tmp_symlink = str_replace('[client_id]',$client_id,$tmp_symlink);
J 461                     $tmp_symlink = str_replace('[website_domain]',$data['old']['domain'],$tmp_symlink);
46c683 462                     // Remove trailing slash
T 463                     if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
464                     // remove the symlinks, if not exist
465                     if(is_link($tmp_symlink)) {
fb3339 466                         exec('rm -f '.escapeshellcmd($tmp_symlink));
J 467                         $app->log('Removed symlink: rm -f '.$tmp_symlink,LOGLEVEL_DEBUG);
46c683 468                     }
T 469                 }
470             }
471         }
ac933e 472
46c683 473         // Create the symlinks for the sites
fb3339 474         $tmp_symlinks_array = explode(':',$web_config['website_symlinks']);
46c683 475         if(is_array($tmp_symlinks_array)) {
T 476             foreach($tmp_symlinks_array as $tmp_symlink) {
fb3339 477                 $tmp_symlink = str_replace('[client_id]',$client_id,$tmp_symlink);
J 478                 $tmp_symlink = str_replace('[website_domain]',$data['new']['domain'],$tmp_symlink);
46c683 479                 // Remove trailing slash
T 480                 if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
481                 //* Remove symlink if target folder has been changed.
fb3339 482                 if($data['old']['document_root'] != '' && $data['old']['document_root'] != $data['new']['document_root'] && is_link($tmp_symlink)) {
46c683 483                     unlink($tmp_symlink);
T 484                 }
485                 // create the symlinks, if not exist
486                 if(!is_link($tmp_symlink)) {
552178 487 //                    exec("ln -s ".escapeshellcmd($data["new"]["document_root"])."/ ".escapeshellcmd($tmp_symlink));
M 488                     if ($web_config["website_symlinks_rel"] == 'y') {
489                         $this->create_relative_link(escapeshellcmd($data["new"]["document_root"]), escapeshellcmd($tmp_symlink));
490                     } else {
491                         exec("ln -s ".escapeshellcmd($data["new"]["document_root"])."/ ".escapeshellcmd($tmp_symlink));
492                     }
493
fb3339 494                     $app->log('Creating symlink: ln -s '.$data['new']['document_root'].'/ '.$tmp_symlink,LOGLEVEL_DEBUG);
46c683 495                 }
T 496             }
497         }
ac933e 498
V 499
3e41e8 500
L 501         // Install the Standard or Custom Error, Index and other related files
502         // /usr/local/ispconfig/server/conf is for the standard files
503         // /usr/local/ispconfig/server/conf-custom is for the custom files
504         // setting a local var here
505            
506         // normally $conf['templates'] = "/usr/local/ispconfig/server/conf";
507
fb3339 508         if($this->action == 'insert' && $data['new']['type'] == 'vhost') {
46c683 509             // Copy the error pages
fb3339 510             if($data['new']['errordocs']) {
J 511                 $error_page_path = escapeshellcmd($data['new']['document_root']).'/web/error/';
4ffb51 512                 if (file_exists($conf['rootpath'] . '/conf-custom/error/'.substr(escapeshellcmd($conf['language']),0,2))) {
F 513                     exec('cp ' . $conf['rootpath'] . '/conf-custom/error/'.substr(escapeshellcmd($conf['language']),0,2).'/* '.$error_page_path);
46c683 514                 }
T 515                 else {
4ffb51 516                     if (file_exists($conf['rootpath'] . '/conf-custom/error/400.html')) {
F 517                         exec('cp '. $conf['rootpath'] . '/conf-custom/error/*.html '.$error_page_path);
46c683 518                     }
T 519                     else {
4ffb51 520                         exec('cp ' . $conf['rootpath'] . '/conf/error/'.substr(escapeshellcmd($conf['language']),0,2).'/* '.$error_page_path);
46c683 521                     }
T 522                 }
fb3339 523                 exec('chmod -R a+r '.$error_page_path);
46c683 524             }
T 525
4ffb51 526             if (file_exists($conf['rootpath'] . '/conf-custom/index/standard_index.html_'.substr(escapeshellcmd($conf['language']),0,2))) {
F 527                 exec('cp ' . $conf['rootpath'] . '/conf-custom/index/standard_index.html_'.substr(escapeshellcmd($conf['language']),0,2).' '.escapeshellcmd($data['new']['document_root']).'/web/index.html');
3e41e8 528             
4ffb51 529             if(is_file($conf['rootpath'] . '/conf-custom/index/favicon.ico')) {
F 530                 exec('cp ' . $conf['rootpath'] . '/conf-custom/index/favicon.ico '.escapeshellcmd($data['new']['document_root']).'/web/');
3e41e8 531             }
4ffb51 532             if(is_file($conf['rootpath'] . '/conf-custom/index/robots.txt')) {
F 533                 exec('cp ' . $conf['rootpath'] . '/conf-custom/index/robots.txt '.escapeshellcmd($data['new']['document_root']).'/web/');
3e41e8 534                 }
4ffb51 535                 if(is_file($conf['rootpath'] . '/conf-custom/index/.htaccess')) {
F 536                     exec('cp ' . $conf['rootpath'] . '/conf-custom/index/.htaccess '.escapeshellcmd($data['new']['document_root']).'/web/');
3e41e8 537                 }
L 538             }
46c683 539             else {
4ffb51 540                 if (file_exists($conf['rootpath'] . '/conf-custom/index/standard_index.html')) {
F 541                     exec('cp ' . $conf['rootpath'] . '/conf-custom/index/standard_index.html '.escapeshellcmd($data['new']['document_root']).'/web/index.html');
46c683 542                 }
T 543                 else {
4ffb51 544                     exec('cp ' . $conf['rootpath'] . '/conf/index/standard_index.html_'.substr(escapeshellcmd($conf['language']),0,2).' '.escapeshellcmd($data['new']['document_root']).'/web/index.html');
F 545                     if(is_file($conf['rootpath'] . '/conf/index/favicon.ico')) exec('cp ' . $conf['rootpath'] . '/conf/index/favicon.ico '.escapeshellcmd($data['new']['document_root']).'/web/');
546                     if(is_file($conf['rootpath'] . '/conf/index/robots.txt')) exec('cp ' . $conf['rootpath'] . '/conf/index/robots.txt '.escapeshellcmd($data['new']['document_root']).'/web/');
547                     if(is_file($conf['rootpath'] . '/conf/index/.htaccess')) exec('cp ' . $conf['rootpath'] . '/conf/index/.htaccess '.escapeshellcmd($data['new']['document_root']).'/web/');
46c683 548                 }
T 549             }
fb3339 550             exec('chmod -R a+r '.escapeshellcmd($data['new']['document_root']).'/web/');
ac933e 551
V 552             //** Copy the error documents on update when the error document checkbox has been activated and was deactivated before
fb3339 553         } elseif ($this->action == 'update' && $data['new']['type'] == 'vhost' && $data['old']['errordocs'] == 0 && $data['new']['errordocs'] == 1) {
ac933e 554
fb3339 555             $error_page_path = escapeshellcmd($data['new']['document_root']).'/web/error/';
4ffb51 556             if (file_exists($conf['rootpath'] . '/conf-custom/error/'.substr(escapeshellcmd($conf['language']),0,2))) {
F 557                 exec('cp ' . $conf['rootpath'] . '/conf-custom/error/'.substr(escapeshellcmd($conf['language']),0,2).'/* '.$error_page_path);
46c683 558             }
T 559             else {
4ffb51 560                 if (file_exists($conf['rootpath'] . '/conf-custom/error/400.html')) {
F 561                     exec('cp ' . $conf['rootpath'] . '/conf-custom/error/*.html '.$error_page_path);
46c683 562                 }
T 563                 else {
4ffb51 564                     exec('cp ' . $conf['rootpath'] . '/conf/error/'.substr(escapeshellcmd($conf['language']),0,2).'/* '.$error_page_path);
46c683 565                 }
T 566             }
fb3339 567             exec('chmod -R a+r '.$error_page_path);
5d5d88 568             exec('chown -R '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.$error_page_path);
46c683 569         }  // end copy error docs
ac933e 570
46c683 571         // Set the quota for the user
T 572         if($username != '' && $app->system->is_user($username)) {
fb3339 573             if($data['new']['hd_quota'] > 0) {
J 574                 $blocks_soft = $data['new']['hd_quota'] * 1024;
ac933e 575                 $blocks_hard = $blocks_soft + 1024;
V 576             } else {
577                 $blocks_soft = $blocks_hard = 0;
578             }
46c683 579             exec("setquota -u $username $blocks_soft $blocks_hard 0 0 -a &> /dev/null");
fb3339 580             exec('setquota -T -u '.$username.' 604800 604800 -a &> /dev/null');
46c683 581         }
ac933e 582
1ca823 583         if($this->action == 'insert' || $data["new"]["system_user"] != $data["old"]["system_user"]) {
46c683 584             // Chown and chmod the directories below the document root
88273a 585             $this->_exec('chown -R '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']).'/web');
8db8f3 586             // The document root itself has to be owned by root in normal level and by the web owner in security level 20
T 587             if($web_config['security_level'] == 20) {
88273a 588                 $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']).'/web');
8db8f3 589             } else {
88273a 590                 $this->_exec('chown root:root '.escapeshellcmd($data['new']['document_root']).'/web');
8db8f3 591             }
46c683 592         }
ac933e 593
V 594
595
8db8f3 596         //* If the security level is set to high
49a4eb 597         if(($this->action == 'insert' && $data['new']['type'] == 'vhost') or ($web_config['set_folder_permissions_on_update'] == 'y' && $data['new']['type'] == 'vhost')) {
88273a 598             if($web_config['security_level'] == 20) {
ac933e 599
88273a 600                 $this->_exec('chmod 751 '.escapeshellcmd($data['new']['document_root']));
T 601                 $this->_exec('chmod 751 '.escapeshellcmd($data['new']['document_root']).'/*');
602                 $this->_exec('chmod 710 '.escapeshellcmd($data['new']['document_root'].'/web'));
ac933e 603
88273a 604                 // make tmp directory writable for Apache and the website users
T 605                 $this->_exec('chmod 777 '.escapeshellcmd($data['new']['document_root'].'/tmp'));
1ca823 606             
88273a 607                 // Set Log symlink to 755 to make the logs accessible by the FTP user
T 608                 $this->_exec("chmod 755 ".escapeshellcmd($data["new"]["document_root"])."/log");
8d49ef 609                 
T 610                 if($web_config['add_web_users_to_sshusers_group'] == 'y') {
611                     $command = 'usermod';
612                     $command .= ' --groups sshusers';
613                     $command .= ' '.escapeshellcmd($data['new']['system_user']);
614                     $this->_exec($command);
615                 }
ac933e 616
88273a 617                 //* if we have a chrooted Apache environment
T 618                 if($apache_chrooted) {
619                     $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' '.$command);
ac933e 620
88273a 621                     //* add the apache user to the client group in the chroot environment
T 622                     $tmp_groupfile = $app->system->server_conf['group_datei'];
623                     $app->system->server_conf['group_datei'] = $web_config['website_basedir'].'/etc/group';
624                     $app->system->add_user_to_group($groupname, escapeshellcmd($web_config['user']));
625                     $app->system->server_conf['group_datei'] = $tmp_groupfile;
626                     unset($tmp_groupfile);
627                 }
628
629                 //* add the Apache user to the client group
2bbc4c 630                 $app->system->add_user_to_group($groupname, escapeshellcmd($web_config['user']));
49a4eb 631                 
T 632                 //* Chown all default directories
e942cf 633                 $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']));
49a4eb 634                 $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/cgi-bin'));
T 635                 $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/log'));
636                 $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/ssl'));
637                 $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/tmp'));
638                 $this->_exec('chown -R '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/web'));
ac933e 639
88273a 640                 /*
T 641                 * Workaround for jailkit: If jailkit is enabled for the site, the 
642                 * website root has to be owned by the root user and we have to chmod it to 755 then
643                 */
ac933e 644
88273a 645                 //* Check if there is a jailkit user for this site
T 646                 $tmp = $app->db->queryOneRecord('SELECT count(shell_user_id) as number FROM shell_user WHERE parent_domain_id = '.$data['new']['domain_id']." AND chroot = 'jailkit'");
647                 if($tmp['number'] > 0) {
648                     $this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root']));
649                     $this->_exec('chown root:root '.escapeshellcmd($data['new']['document_root']));
650                 }
651                 unset($tmp);
ac933e 652
88273a 653                 // If the security Level is set to medium
T 654             } else {
655
fb3339 656                 $this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root']));
e942cf 657                 $this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root'].'/cgi-bin'));
T 658                 $this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root'].'/log'));
659                 $this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root'].'/ssl'));
660                 $this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root'].'/web'));
661                 
88273a 662                 // make temp directory writable for Apache and the website users
T 663                 $this->_exec('chmod 777 '.escapeshellcmd($data['new']['document_root'].'/tmp'));
e942cf 664                 
T 665                 $this->_exec('chown root:root '.escapeshellcmd($data['new']['document_root']));
666                 $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/cgi-bin'));
667                 $this->_exec('chown root:root '.escapeshellcmd($data['new']['document_root'].'/log'));
668                 $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/tmp'));
669                 $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/ssl'));
670                 $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/web'));
8db8f3 671             }
6b029a 672         }
ac933e 673
fb3339 674         // Change the ownership of the error log to the owner of the website
J 675         if(!@is_file($data['new']['document_root'].'/log/error.log')) exec('touch '.escapeshellcmd($data['new']['document_root']).'/log/error.log');
676         $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']).'/log/error.log');
ac933e 677
V 678
7fddfe 679         //* Write the custom php.ini file, if custom_php_ini filed is not empty
fb3339 680         $custom_php_ini_dir = $web_config['website_basedir'].'/conf/'.$data['new']['system_user'];
7fddfe 681         if(!is_dir($web_config['website_basedir'].'/conf')) mkdir($web_config['website_basedir'].'/conf');
fb3339 682         if(trim($data['new']['custom_php_ini']) != '') {
7fddfe 683             $has_custom_php_ini = true;
T 684             if(!is_dir($custom_php_ini_dir)) mkdir($custom_php_ini_dir);
685             $php_ini_content = '';
fb3339 686             if($data['new']['php'] == 'mod') {
7fddfe 687                 $master_php_ini_path = $web_config['php_ini_path_apache'];
T 688             } else {
9f56bd 689                 if($data["new"]['php'] == 'fast-cgi' && file_exists($fastcgi_config["fastcgi_phpini_path"])) {
T 690                     $master_php_ini_path = $fastcgi_config["fastcgi_phpini_path"];
691                 } else {
692                     $master_php_ini_path = $web_config['php_ini_path_cgi'];
693                 }
7fddfe 694             }
T 695             if($master_php_ini_path != '' && substr($master_php_ini_path,-7) == 'php.ini' && is_file($master_php_ini_path)) {
696                 $php_ini_content .= file_get_contents($master_php_ini_path)."\n";
697             }
8008bb 698             $php_ini_content .= str_replace("\r",'',trim($data['new']['custom_php_ini']));
7fddfe 699             file_put_contents($custom_php_ini_dir.'/php.ini',$php_ini_content);
T 700         } else {
701             $has_custom_php_ini = false;
702             if(is_file($custom_php_ini_dir.'/php.ini')) unlink($custom_php_ini_dir.'/php.ini');
703         }
704
705
706         //* Create the vhost config file
46c683 707         $app->load('tpl');
ac933e 708
46c683 709         $tpl = new tpl();
fb3339 710         $tpl->newTemplate('vhost.conf.master');
ac933e 711
fb3339 712         $vhost_data = $data['new'];
a7bdf8 713         //unset($vhost_data['ip_address']);
fb3339 714         $vhost_data['web_document_root'] = $data['new']['document_root'].'/web';
J 715         $vhost_data['web_document_root_www'] = $web_config['website_basedir'].'/'.$data['new']['domain'].'/web';
716         $vhost_data['web_basedir'] = $web_config['website_basedir'];
717         $vhost_data['security_level'] = $web_config['security_level'];
718         $vhost_data['allow_override'] = ($data['new']['allow_override'] == '')?'All':$data['new']['allow_override'];
719         $vhost_data['php_open_basedir'] = ($data['new']['php_open_basedir'] == '')?$data['new']['document_root']:$data['new']['php_open_basedir'];
720         $vhost_data['ssl_domain'] = $data['new']['ssl_domain'];
721         $vhost_data['has_custom_php_ini'] = $has_custom_php_ini;
722         $vhost_data['custom_php_ini_dir'] = escapeshellcmd($custom_php_ini_dir);
accfe5 723         
F 724         // Custom Apache directives
725         // Make sure we only have Unix linebreaks
726         $vhost_data['apache_directives'] = str_replace("\r\n", "\n", $vhost_data['apache_directives']);
727         $vhost_data['apache_directives'] = str_replace("\r", "\n", $vhost_data['apache_directives']);
ac933e 728
46c683 729         // Check if a SSL cert exists
fb3339 730         $ssl_dir = $data['new']['document_root'].'/ssl';
J 731         $domain = $data['new']['ssl_domain'];
732         $key_file = $ssl_dir.'/'.$domain.'.key';
733         $crt_file = $ssl_dir.'/'.$domain.'.crt';
734         $bundle_file = $ssl_dir.'/'.$domain.'.bundle';
ac933e 735
a7bdf8 736         /*
1a2310 737         if($domain!='' && $data['new']['ssl'] == 'y' && @is_file($crt_file) && @is_file($key_file) && (@filesize($crt_file)>0)  && (@filesize($key_file)>0)) {
fb3339 738             $vhost_data['ssl_enabled'] = 1;
J 739             $app->log('Enable SSL for: '.$domain,LOGLEVEL_DEBUG);
46c683 740         } else {
fb3339 741             $vhost_data['ssl_enabled'] = 0;
1a2310 742             $app->log('SSL Disabled. '.$domain,LOGLEVEL_DEBUG);
46c683 743         }
a7bdf8 744         */
ac933e 745
46c683 746         if(@is_file($bundle_file)) $vhost_data['has_bundle_cert'] = 1;
ac933e 747
fb3339 748         //$vhost_data['document_root'] = $data['new']['document_root'].'/web';
e64fbb 749         
F 750         // Set SEO Redirect
751         if($data['new']['seo_redirect'] != '' && ($data['new']['subdomain'] == 'www' || $data['new']['subdomain'] == '*')){
752             $vhost_data['seo_redirect_enabled'] = 1;
753             if($data['new']['seo_redirect'] == 'non_www_to_www'){
754                 $vhost_data['seo_redirect_origin_domain'] = $data['new']['domain'];
755                 $vhost_data['seo_redirect_target_domain'] = 'www.'.$data['new']['domain'];
756             }
757             if($data['new']['seo_redirect'] == 'www_to_non_www'){
758                 $vhost_data['seo_redirect_origin_domain'] = 'www.'.$data['new']['domain'];
759                 $vhost_data['seo_redirect_target_domain'] = $data['new']['domain'];
760             }
761         } else {
762             $vhost_data['seo_redirect_enabled'] = 0;
763         }
764         
46c683 765         $tpl->setVar($vhost_data);
ac933e 766
46c683 767         // Rewrite rules
T 768         $rewrite_rules = array();
790cb8 769         if($data['new']['redirect_type'] != '' && $data['new']['redirect_path'] != '') {
fb3339 770             if(substr($data['new']['redirect_path'],-1) != '/') $data['new']['redirect_path'] .= '/';
45ee67 771             if(substr($data['new']['redirect_path'],0,8) == '[scheme]'){
F 772                 $rewrite_target = 'http'.substr($data['new']['redirect_path'],8);
773                 $rewrite_target_ssl = 'https'.substr($data['new']['redirect_path'],8);
774             } else {
775                 $rewrite_target = $data['new']['redirect_path'];
776                 $rewrite_target_ssl = $data['new']['redirect_path'];
777             }
bc2c3e 778             /* Disabled path extension
fb3339 779             if($data['new']['redirect_type'] == 'no' && substr($data['new']['redirect_path'],0,4) != 'http') {
J 780                 $data['new']['redirect_path'] = $data['new']['document_root'].'/web'.realpath($data['new']['redirect_path']).'/';
8388ae 781             }
bc2c3e 782             */
ac933e 783
fb3339 784             switch($data['new']['subdomain']) {
ac933e 785                 case 'www':
e64fbb 786                     $rewrite_rules[] = array(    'rewrite_domain'     => '^'.$data['new']['domain'],
F 787                         'rewrite_type'         => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
788                         'rewrite_target'     => $rewrite_target,
789                         'rewrite_target_ssl' => $rewrite_target_ssl);
790                     $rewrite_rules[] = array(    'rewrite_domain'     => '^www.'.$data['new']['domain'],
fb3339 791                             'rewrite_type'         => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
e64fbb 792                             'rewrite_target'     => $rewrite_target,
F 793                             'rewrite_target_ssl' => $rewrite_target_ssl);
ac933e 794                     break;
V 795                 case '*':
876d67 796                     $rewrite_rules[] = array(    'rewrite_domain'     => '(^|\.)'.$data['new']['domain'],
e64fbb 797                         'rewrite_type'         => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
F 798                         'rewrite_target'     => $rewrite_target,
799                         'rewrite_target_ssl' => $rewrite_target_ssl);
ac933e 800                     break;
e64fbb 801                 default:
F 802                     $rewrite_rules[] = array(    'rewrite_domain'     => '^'.$data['new']['domain'],
803                         'rewrite_type'         => ($data['new']['redirect_type'] == 'no')?'':'['.$data['new']['redirect_type'].']',
804                         'rewrite_target'     => $rewrite_target,
805                         'rewrite_target_ssl' => $rewrite_target_ssl);
ac933e 806             }
46c683 807         }
ac933e 808
46c683 809         // get alias domains (co-domains and subdomains)
fb3339 810         $aliases = $app->db->queryAllRecords('SELECT * FROM web_domain WHERE parent_domain_id = '.$data['new']['domain_id']." AND active = 'y'");
ac933e 811         $server_alias = array();
fb3339 812         switch($data['new']['subdomain']) {
ac933e 813             case 'www':
fb3339 814                 $server_alias[] .= 'www.'.$data['new']['domain'].' ';
ac933e 815                 break;
V 816             case '*':
fb3339 817                 $server_alias[] .= '*.'.$data['new']['domain'].' ';
ac933e 818                 break;
V 819         }
46c683 820         if(is_array($aliases)) {
T 821             foreach($aliases as $alias) {
fb3339 822                 switch($alias['subdomain']) {
ac933e 823                     case 'www':
fb3339 824                         $server_alias[] .= 'www.'.$alias['domain'].' '.$alias['domain'].' ';
ac933e 825                         break;
V 826                     case '*':
fb3339 827                         $server_alias[] .= '*.'.$alias['domain'].' '.$alias['domain'].' ';
ac933e 828                         break;
V 829                     default:
fb3339 830                         $server_alias[] .= $alias['domain'].' ';
ac933e 831                         break;
V 832                 }
fb3339 833                 $app->log('Add server alias: '.$alias['domain'],LOGLEVEL_DEBUG);
46c683 834                 // Rewriting
790cb8 835                 if($alias['redirect_type'] != '' && $alias['redirect_path'] != '') {
e64fbb 836                     if(substr($alias['redirect_path'],-1) != '/') $alias['redirect_path'] .= '/';
F 837                     if(substr($alias['redirect_path'],0,8) == '[scheme]'){
838                         $rewrite_target = 'http'.substr($alias['redirect_path'],8);
839                         $rewrite_target_ssl = 'https'.substr($alias['redirect_path'],8);
840                     } else {
841                         $rewrite_target = $alias['redirect_path'];
842                         $rewrite_target_ssl = $alias['redirect_path'];
843                     }
bc2c3e 844                     /* Disabled the path extension
fb3339 845                     if($data['new']['redirect_type'] == 'no' && substr($data['new']['redirect_path'],0,4) != 'http') {
J 846                         $data['new']['redirect_path'] = $data['new']['document_root'].'/web'.realpath($data['new']['redirect_path']).'/';
8388ae 847                     }
bc2c3e 848                     */
e64fbb 849                     
fb3339 850                     switch($alias['subdomain']) {
ac933e 851                         case 'www':
e64fbb 852                             $rewrite_rules[] = array(    'rewrite_domain'     => '^'.$alias['domain'],
F 853                                 'rewrite_type'         => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
854                                 'rewrite_target'     => $rewrite_target,
855                                 'rewrite_target_ssl' => $rewrite_target_ssl);
856                             $rewrite_rules[] = array(    'rewrite_domain'     => '^www.'.$alias['domain'],
fb3339 857                                     'rewrite_type'         => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
e64fbb 858                                     'rewrite_target'     => $rewrite_target,
F 859                                     'rewrite_target_ssl' => $rewrite_target_ssl);
ac933e 860                             break;
V 861                         case '*':
876d67 862                             $rewrite_rules[] = array(    'rewrite_domain'     => '(^|\.)'.$alias['domain'],
e64fbb 863                                 'rewrite_type'         => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
F 864                                 'rewrite_target'     => $rewrite_target,
865                                 'rewrite_target_ssl' => $rewrite_target_ssl);
ac933e 866                             break;
e64fbb 867                         default:
F 868                             $rewrite_rules[] = array(    'rewrite_domain'     => '^'.$alias['domain'],
869                                 'rewrite_type'         => ($alias['redirect_type'] == 'no')?'':'['.$alias['redirect_type'].']',
870                                 'rewrite_target'     => $rewrite_target,
871                                 'rewrite_target_ssl' => $rewrite_target_ssl);
ac933e 872                     }
46c683 873                 }
T 874             }
875         }
ac933e 876
47cca9 877         //* If we have some alias records
T 878         if(count($server_alias) > 0) {
879             $server_alias_str = '';
880             $n = 0;
ac933e 881
47cca9 882             // begin a new ServerAlias line after 30 alias domains
T 883             foreach($server_alias as $tmp_alias) {
884                 if($n % 30 == 0) $server_alias_str .= "\n    ServerAlias ";
885                 $server_alias_str .= $tmp_alias;
886             }
887             unset($tmp_alias);
ac933e 888
47cca9 889             $tpl->setVar('alias',trim($server_alias_str));
T 890         } else {
891             $tpl->setVar('alias','');
892         }
ac933e 893
af4864 894         if(count($rewrite_rules) > 0 || $vhost_data['seo_redirect_enabled'] > 0) {
46c683 895             $tpl->setVar('rewrite_enabled',1);
T 896         } else {
897             $tpl->setVar('rewrite_enabled',0);
898         }
af4864 899
F 900         //$tpl->setLoop('redirects',$rewrite_rules);
ac933e 901
V 902         /**
903          * install fast-cgi starter script and add script aliasd config
46c683 904          * first we create the script directory if not already created, then copy over the starter script
T 905          * settings are copied over from the server ini config for now
906          * TODO: Create form for fastcgi configs per site.
907          */
ac933e 908
fb3339 909         if ($data['new']['php'] == 'fast-cgi') {
J 910             $fastcgi_config = $app->getconf->get_server_config($conf['server_id'], 'fastcgi');
ac933e 911
fb3339 912             $fastcgi_starter_path = str_replace('[system_user]',$data['new']['system_user'],$fastcgi_config['fastcgi_starter_path']);
J 913             $fastcgi_starter_path = str_replace('[client_id]',$client_id,$fastcgi_starter_path);
ac933e 914
V 915             if (!is_dir($fastcgi_starter_path)) {
fb3339 916                 exec('mkdir -p '.escapeshellcmd($fastcgi_starter_path));
J 917                 //exec('chown '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.escapeshellcmd($fastcgi_starter_path));
ac933e 918
V 919
fb3339 920                 $app->log('Creating fastcgi starter script directory: '.$fastcgi_starter_path,LOGLEVEL_DEBUG);
46c683 921             }
ac933e 922
fb3339 923             exec('chown -R '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.escapeshellcmd($fastcgi_starter_path));
ac933e 924
46c683 925             $fcgi_tpl = new tpl();
fb3339 926             $fcgi_tpl->newTemplate('php-fcgi-starter.master');
7fddfe 927             
T 928             if($has_custom_php_ini) {
929                 $fcgi_tpl->setVar('php_ini_path',escapeshellcmd($custom_php_ini_dir));
930             } else {
fb3339 931                 $fcgi_tpl->setVar('php_ini_path',escapeshellcmd($fastcgi_config['fastcgi_phpini_path']));
7fddfe 932             }
fb3339 933             $fcgi_tpl->setVar('document_root',escapeshellcmd($data['new']['document_root']));
J 934             $fcgi_tpl->setVar('php_fcgi_children',escapeshellcmd($fastcgi_config['fastcgi_children']));
935             $fcgi_tpl->setVar('php_fcgi_max_requests',escapeshellcmd($fastcgi_config['fastcgi_max_requests']));
936             $fcgi_tpl->setVar('php_fcgi_bin',escapeshellcmd($fastcgi_config['fastcgi_bin']));
937             $fcgi_tpl->setVar('security_level',intval($web_config['security_level']));
ac933e 938
fb3339 939             $php_open_basedir = ($data['new']['php_open_basedir'] == '')?$data['new']['document_root']:$data['new']['php_open_basedir'];
ff7075 940             $fcgi_tpl->setVar('open_basedir', escapeshellcmd($php_open_basedir));
ac933e 941
fb3339 942             $fcgi_starter_script = escapeshellcmd($fastcgi_starter_path.$fastcgi_config['fastcgi_starter_script']);
46c683 943             file_put_contents($fcgi_starter_script,$fcgi_tpl->grab());
T 944             unset($fcgi_tpl);
ac933e 945
fb3339 946             $app->log('Creating fastcgi starter script: '.$fcgi_starter_script,LOGLEVEL_DEBUG);
ac933e 947
V 948
fb3339 949             exec('chmod 755 '.$fcgi_starter_script);
J 950             exec('chown '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.$fcgi_starter_script);
46c683 951
fb3339 952             $tpl->setVar('fastcgi_alias',$fastcgi_config['fastcgi_alias']);
46c683 953             $tpl->setVar('fastcgi_starter_path',$fastcgi_starter_path);
fb3339 954             $tpl->setVar('fastcgi_starter_script',$fastcgi_config['fastcgi_starter_script']);
824780 955             $tpl->setVar('fastcgi_config_syntax',$fastcgi_config['fastcgi_config_syntax']);
ac933e 956
46c683 957         }
ac933e 958
46c683 959         /**
T 960          * install cgi starter script and add script alias to config.
961          * This is needed to allow cgi with suexec (to do so, we need a bin in the document-path!)
962          * first we create the script directory if not already created, then copy over the starter script.
963          * TODO: we have to fetch the data from the server-settings.
964          */
965
fb3339 966         if ($data['new']['php'] == 'cgi') {
J 967             //$cgi_config = $app->getconf->get_server_config($conf['server_id'], 'cgi');
46c683 968
fb3339 969             $cgi_config['cgi_starter_path'] = $web_config['website_basedir'].'/php-cgi-scripts/[system_user]/';
J 970             $cgi_config['cgi_starter_script'] = 'php-cgi-starter';
971             $cgi_config['cgi_bin'] = '/usr/bin/php-cgi';
46c683 972
fb3339 973             $cgi_starter_path = str_replace('[system_user]',$data['new']['system_user'],$cgi_config['cgi_starter_path']);
J 974             $cgi_starter_path = str_replace('[client_id]',$client_id,$cgi_starter_path);
46c683 975
ac933e 976             if (!is_dir($cgi_starter_path)) {
fb3339 977                 exec('mkdir -p '.escapeshellcmd($cgi_starter_path));
J 978                 exec('chown '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.escapeshellcmd($cgi_starter_path));
46c683 979
fb3339 980                 $app->log('Creating cgi starter script directory: '.$cgi_starter_path,LOGLEVEL_DEBUG);
46c683 981             }
T 982
983             $cgi_tpl = new tpl();
fb3339 984             $cgi_tpl->newTemplate('php-cgi-starter.master');
46c683 985
fb3339 986             // This works because PHP "rewrites" a symlink to the physical path
J 987             $php_open_basedir = ($data['new']['php_open_basedir'] == '')?$data['new']['document_root']:$data['new']['php_open_basedir'];
ac933e 988             $cgi_tpl->setVar('open_basedir', escapeshellcmd($php_open_basedir));
fb3339 989             $cgi_tpl->setVar('document_root', escapeshellcmd($data['new']['document_root']));
ac933e 990
46c683 991             // This will NOT work!
fb3339 992             //$cgi_tpl->setVar('open_basedir', '/var/www/' . $data['new']['domain']);
J 993             $cgi_tpl->setVar('php_cgi_bin',$cgi_config['cgi_bin']);
994             $cgi_tpl->setVar('security_level',$web_config['security_level']);
7fddfe 995             
T 996             $cgi_tpl->setVar('has_custom_php_ini',$has_custom_php_ini);
997             if($has_custom_php_ini) {
998                 $cgi_tpl->setVar('php_ini_path',escapeshellcmd($custom_php_ini_dir));
999             } else {
fb3339 1000                 $cgi_tpl->setVar('php_ini_path',escapeshellcmd($fastcgi_config['fastcgi_phpini_path']));
7fddfe 1001             }
46c683 1002
fb3339 1003             $cgi_starter_script = escapeshellcmd($cgi_starter_path.$cgi_config['cgi_starter_script']);
46c683 1004             file_put_contents($cgi_starter_script,$cgi_tpl->grab());
T 1005             unset($cgi_tpl);
1006
fb3339 1007             $app->log('Creating cgi starter script: '.$cgi_starter_script,LOGLEVEL_DEBUG);
46c683 1008
T 1009
fb3339 1010             exec('chmod 755 '.$cgi_starter_script);
J 1011             exec('chown '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.$cgi_starter_script);
46c683 1012
T 1013             $tpl->setVar('cgi_starter_path',$cgi_starter_path);
fb3339 1014             $tpl->setVar('cgi_starter_script',$cgi_config['cgi_starter_script']);
46c683 1015
T 1016         }
1017
fb3339 1018         $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['new']['domain'].'.vhost');
7ed741 1019         //* Make a backup copy of vhost file
083dc0 1020         if(file_exists($vhost_file)) copy($vhost_file,$vhost_file.'~');
7ed741 1021         
a7bdf8 1022         //* create empty vhost array
T 1023         $vhosts = array();
1024         
af4864 1025         //* Add vhost for ipv4 IP    
F 1026         if(count($rewrite_rules) > 0){
1027             $vhosts[] = array('ip_address' => $data['new']['ip_address'], 'ssl_enabled' => 0, 'port' => 80, 'redirects' => $rewrite_rules);
1028         } else {
1029             $vhosts[] = array('ip_address' => $data['new']['ip_address'], 'ssl_enabled' => 0, 'port' => 80);
1030         }
a7bdf8 1031         
T 1032         //* Add vhost for ipv4 IP with SSL
1033         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)) {
af4864 1034             if(count($rewrite_rules) > 0){
F 1035                 $vhosts[] = array('ip_address' => $data['new']['ip_address'], 'ssl_enabled' => 1, 'port' => '443', 'redirects' => $rewrite_rules);
1036             } else {
1037                 $vhosts[] = array('ip_address' => $data['new']['ip_address'], 'ssl_enabled' => 1, 'port' => '443');
1038             }
a7bdf8 1039             $app->log('Enable SSL for: '.$domain,LOGLEVEL_DEBUG);
T 1040         }
1041         
1042         //* Add vhost for IPv6 IP
1043         if($data['new']['ipv6_address'] != '') {
af4864 1044             if(count($rewrite_rules) > 0){
F 1045                 $vhosts[] = array('ip_address' => '['.$data['new']['ipv6_address'].']', 'ssl_enabled' => 0, 'port' => 80, 'redirects' => $rewrite_rules);
1046             } else {
1047                 $vhosts[] = array('ip_address' => '['.$data['new']['ipv6_address'].']', 'ssl_enabled' => 0, 'port' => 80);
1048             }
a7bdf8 1049         
T 1050             //* Add vhost for ipv6 IP with SSL
1051             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)) {
af4864 1052                 
F 1053                 if(count($rewrite_rules) > 0){
1054                     $vhosts[] = array('ip_address' => '['.$data['new']['ipv6_address'].']', 'ssl_enabled' => 1, 'port' => '443', 'redirects' => $rewrite_rules);
1055                 } else {
1056                     $vhosts[] = array('ip_address' => '['.$data['new']['ipv6_address'].']', 'ssl_enabled' => 1, 'port' => '443');
1057                 }
a7bdf8 1058                 $app->log('Enable SSL for IPv6: '.$domain,LOGLEVEL_DEBUG);
T 1059             }
1060         }
1061         
1062         //* Set the vhost loop
1063         $tpl->setLoop('vhosts',$vhosts);
1064         
7ed741 1065         //* Write vhost file
46c683 1066         file_put_contents($vhost_file,$tpl->grab());
fb3339 1067         $app->log('Writing the vhost file: '.$vhost_file,LOGLEVEL_DEBUG);
46c683 1068         unset($tpl);
ac933e 1069
V 1070         /*
1071          * maybe we have some webdav - user. If so, add them...
1072         */
fb3339 1073         $this->_patchVhostWebdav($vhost_file, $data['new']['document_root'] . '/webdav');
ac933e 1074
c6a89c 1075         //* Set the symlink to enable the vhost
T 1076         //* First we check if there is a old type of symlink and remove it
fb3339 1077         $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['new']['domain'].'.vhost');
c6a89c 1078         if(is_link($vhost_symlink)) unlink($vhost_symlink);
T 1079         
1080         //* Remove old or changed symlinks
1081         if($data['new']['subdomain'] != $data['old']['subdomain'] or $data['new']['active'] == 'n') {
1082             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['new']['domain'].'.vhost');
1083             if(is_link($vhost_symlink)) {
1084                 unlink($vhost_symlink);
1085                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
1086             }
1087             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['new']['domain'].'.vhost');
1088             if(is_link($vhost_symlink)) {
1089                 unlink($vhost_symlink);
1090                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
1091             }
1092         }
1093         
1094         //* New symlink
1095         if($data['new']['subdomain'] == '*') {
1096             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['new']['domain'].'.vhost');
1097         } else {
1098             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['new']['domain'].'.vhost');
1099         }
fb3339 1100         if($data['new']['active'] == 'y' && !is_link($vhost_symlink)) {
46c683 1101             symlink($vhost_file,$vhost_symlink);
fb3339 1102             $app->log('Creating symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
46c683 1103         }
ac933e 1104
46c683 1105         // remove old symlink and vhost file, if domain name of the site has changed
fb3339 1106         if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
c6a89c 1107             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['old']['domain'].'.vhost');
T 1108             if(is_link($vhost_symlink)) {
1109                 unlink($vhost_symlink);
1110                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
1111             }
1112             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['old']['domain'].'.vhost');
1113             if(is_link($vhost_symlink)) {
1114                 unlink($vhost_symlink);
1115                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
1116             }
276324 1117             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
T 1118             if(is_link($vhost_symlink)) {
1119                 unlink($vhost_symlink);
1120                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
1121             }
fb3339 1122             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
46c683 1123             unlink($vhost_file);
fb3339 1124             $app->log('Removing file: '.$vhost_file,LOGLEVEL_DEBUG);
46c683 1125         }
ac933e 1126
46c683 1127         //* Create .htaccess and .htpasswd file for website statistics
fb3339 1128         if(!is_file($data['new']['document_root'].'/web/stats/.htaccess') or $data['old']['document_root'] != $data['new']['document_root']) {
J 1129             if(!is_dir($data['new']['document_root'].'/web/stats')) mkdir($data['new']['document_root'].'/web/stats');
1130             $ht_file = "AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$data['new']['document_root']."/.htpasswd_stats\nrequire valid-user";
1131             file_put_contents($data['new']['document_root'].'/web/stats/.htaccess',$ht_file);
1132             chmod($data['new']['document_root'].'/web/stats/.htaccess',0755);
46c683 1133             unset($ht_file);
T 1134         }
ac933e 1135
fb3339 1136         if(!is_file($data['new']['document_root'].'/.htpasswd_stats') || $data['new']['stats_password'] != $data['old']['stats_password']) {
J 1137             if(trim($data['new']['stats_password']) != '') {
1138                 $htp_file = 'admin:'.trim($data['new']['stats_password']);
1139                 file_put_contents($data['new']['document_root'].'/.htpasswd_stats',$htp_file);
1140                 chmod($data['new']['document_root'].'/.htpasswd_stats',0755);
46c683 1141                 unset($htp_file);
T 1142             }
1143         }
58c210 1144         
T 1145         //* Create awstats configuration
fb3339 1146         if($data['new']['stats_type'] == 'awstats' && $data['new']['type'] == 'vhost') {
58c210 1147             $this->awstats_update($data,$web_config);
T 1148         }
7ed741 1149         
T 1150         if($web_config['check_apache_config'] == 'y') {
1151             //* Test if apache starts with the new configuration file
1152             $apache_online_status_before_restart = $this->_checkTcp('localhost',80);
fb3339 1153             $app->log('Apache status is: '.$apache_online_status_before_restart,LOGLEVEL_DEBUG);
ac933e 1154
7ed741 1155             $app->services->restartService('httpd','restart');
9f56bd 1156             
T 1157             // wait a few seconds, before we test the apache status again
1158             sleep(2);
7ed741 1159         
T 1160             //* Check if apache restarted successfully if it was online before
1161             $apache_online_status_after_restart = $this->_checkTcp('localhost',80);
fb3339 1162             $app->log('Apache online status after restart is: '.$apache_online_status_after_restart,LOGLEVEL_DEBUG);
7ed741 1163             if($apache_online_status_before_restart && !$apache_online_status_after_restart) {
fb3339 1164                 $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);
7ed741 1165                 copy($vhost_file,$vhost_file.'.err');
84710d 1166                 if(is_file($vhost_file.'~')) {
T 1167                     //* Copy back the last backup file
1168                     copy($vhost_file.'~',$vhost_file);
1169                 } else {
1170                     //* There is no backup file, so we create a empty vhost file with a warning message inside
1171                     file_put_contents($vhost_file,"# Apache did not start after modifying this vhost file.\n# Please check file $vhost_file.err for syntax errors.");
1172                 }
7ed741 1173                 $app->services->restartService('httpd','restart');
T 1174             }
c82dc7 1175         } else {
7ed741 1176             //* We do not check the apache config after changes (is faster)
T 1177             if($apache_chrooted) {
1178                 $app->services->restartServiceDelayed('httpd','restart');
1179             } else {
1180                 // request a httpd reload when all records have been processed
1181                 $app->services->restartServiceDelayed('httpd','reload');
1182             }
c82dc7 1183         }
7ed741 1184         
T 1185         // Remove the backup copy of the config file.
9f56bd 1186         if(@is_file($vhost_file.'~')) unlink($vhost_file.'~');
7ed741 1187         
ac933e 1188
da1a7c 1189         //* Unset action to clean it for next processed vhost.
T 1190         $this->action = '';
ac933e 1191
46c683 1192     }
ac933e 1193
46c683 1194     function delete($event_name,$data) {
T 1195         global $app, $conf;
ac933e 1196
46c683 1197         // load the server configuration options
fb3339 1198         $app->uses('getconf');
J 1199         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
ac933e 1200
2bbc4c 1201         //* Check if this is a chrooted setup
4b72c5 1202         if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
2bbc4c 1203             $apache_chrooted = true;
T 1204         } else {
1205             $apache_chrooted = false;
1206         }
ac933e 1207
fb3339 1208         if($data['old']['type'] != 'vhost' && $data['old']['parent_domain_id'] > 0) {
46c683 1209             //* This is a alias domain or subdomain, so we have to update the website instead
fb3339 1210             $parent_domain_id = intval($data['old']['parent_domain_id']);
J 1211             $tmp = $app->db->queryOneRecord('SELECT * FROM web_domain WHERE domain_id = '.$parent_domain_id." AND active = 'y'");
1212             $data['new'] = $tmp;
1213             $data['old'] = $tmp;
46c683 1214             $this->action = 'update';
T 1215             // just run the update function
1216             $this->update($event_name,$data);
ac933e 1217
46c683 1218         } else {
T 1219             //* This is a website
1220             // Deleting the vhost file, symlink and the data directory
fb3339 1221             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
f3b669 1222             
F 1223             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
1224             if(is_link($vhost_symlink)){
1225                 unlink($vhost_symlink);
1226                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
1227             }
1228             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['old']['domain'].'.vhost');
1229             if(is_link($vhost_symlink)){
1230                 unlink($vhost_symlink);
1231                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
1232             }
1233             $vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['old']['domain'].'.vhost');
1234             if(is_link($vhost_symlink)){
1235                 unlink($vhost_symlink);
1236                 $app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
1237             }
1238             
46c683 1239             unlink($vhost_file);
fb3339 1240             $app->log('Removing vhost file: '.$vhost_file,LOGLEVEL_DEBUG);
ac933e 1241
fb3339 1242             $docroot = escapeshellcmd($data['old']['document_root']);
J 1243             if($docroot != '' && !stristr($docroot,'..')) exec('rm -rf '.$docroot);
ac933e 1244
V 1245
46c683 1246             //remove the php fastgi starter script if available
fb3339 1247             if ($data['old']['php'] == 'fast-cgi') {
J 1248                 $fastcgi_starter_path = str_replace('[system_user]',$data['old']['system_user'],$web_config['fastcgi_starter_path']);
ac933e 1249                 if (is_dir($fastcgi_starter_path)) {
fb3339 1250                     exec('rm -rf '.$fastcgi_starter_path);
46c683 1251                 }
T 1252             }
ac933e 1253
46c683 1254             //remove the php cgi starter script if available
fb3339 1255             if ($data['old']['php'] == 'cgi') {
46c683 1256                 // TODO: fetch the date from the server-settings
fb3339 1257                 $web_config['cgi_starter_path'] = $web_config['website_basedir'].'/php-cgi-scripts/[system_user]/';
46c683 1258
fb3339 1259                 $cgi_starter_path = str_replace('[system_user]',$data['old']['system_user'],$web_config['cgi_starter_path']);
ac933e 1260                 if (is_dir($cgi_starter_path)) {
fb3339 1261                     exec('rm -rf '.$cgi_starter_path);
46c683 1262                 }
T 1263             }
1264
fb3339 1265             $app->log('Removing website: '.$docroot,LOGLEVEL_DEBUG);
ac933e 1266
46c683 1267             // Delete the symlinks for the sites
fb3339 1268             $client = $app->db->queryOneRecord('SELECT client_id FROM sys_group WHERE sys_group.groupid = '.intval($data['old']['sys_groupid']));
J 1269             $client_id = intval($client['client_id']);
46c683 1270             unset($client);
fb3339 1271             $tmp_symlinks_array = explode(':',$web_config['website_symlinks']);
46c683 1272             if(is_array($tmp_symlinks_array)) {
T 1273                 foreach($tmp_symlinks_array as $tmp_symlink) {
fb3339 1274                     $tmp_symlink = str_replace('[client_id]',$client_id,$tmp_symlink);
J 1275                     $tmp_symlink = str_replace('[website_domain]',$data['old']['domain'],$tmp_symlink);
46c683 1276                     // Remove trailing slash
T 1277                     if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
1278                     // create the symlinks, if not exist
1279                     if(is_link($tmp_symlink)) {
1280                         unlink($tmp_symlink);
fb3339 1281                         $app->log('Removing symlink: '.$tmp_symlink,LOGLEVEL_DEBUG);
46c683 1282                     }
T 1283                 }
1284             }
1285             // end removing symlinks
ac933e 1286
46c683 1287             // Delete the log file directory
fb3339 1288             $vhost_logfile_dir = escapeshellcmd('/var/log/ispconfig/httpd/'.$data['old']['domain']);
J 1289             if($data['old']['domain'] != '' && !stristr($vhost_logfile_dir,'..')) exec('rm -rf '.$vhost_logfile_dir);
1290             $app->log('Removing website logfile directory: '.$vhost_logfile_dir,LOGLEVEL_DEBUG);
ac933e 1291
46c683 1292             //delete the web user
T 1293             $command = 'userdel';
fb3339 1294             $command .= ' '.$data['old']['system_user'];
46c683 1295             exec($command);
fb3339 1296             if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' '.$command);
58c210 1297             
T 1298             //* Remove the awstats configuration file
fb3339 1299             if($data['old']['stats_type'] == 'awstats') {
58c210 1300                 $this->awstats_delete($data,$web_config);
T 1301             }
f3b669 1302             
F 1303             if($apache_chrooted) {
1304                 $app->services->restartServiceDelayed('httpd','restart');
1305             } else {
1306                 // request a httpd reload when all records have been processed
1307                 $app->services->restartServiceDelayed('httpd','reload');
1308             }
ac933e 1309
46c683 1310         }
T 1311     }
ac933e 1312
46c683 1313     //* This function is called when a IP on the server is inserted, updated or deleted
T 1314     function server_ip($event_name,$data) {
1315         global $app, $conf;
ac933e 1316
46c683 1317         // load the server configuration options
fb3339 1318         $app->uses('getconf');
J 1319         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
ac933e 1320
46c683 1321         $app->load('tpl');
ac933e 1322
46c683 1323         $tpl = new tpl();
fb3339 1324         $tpl->newTemplate('apache_ispconfig.conf.master');
J 1325         $records = $app->db->queryAllRecords('SELECT * FROM server_ip WHERE server_id = '.$conf['server_id']." AND virtualhost = 'y'");
a2156e 1326         
T 1327         $records_out= array();
1328         if(is_array($records)) {
1329             foreach($records as $rec) {
1330                 if($rec['ip_type'] == 'IPv6') {
1331                     $ip_address = '['.$rec['ip_address'].']';
1332                 } else {
1333                     $ip_address = $rec['ip_address'];
1334                 }
1335                 $ports = explode(',',$rec['virtualhost_port']);
1336                 if(is_array($ports)) {
1337                     foreach($ports as $port) {
1338                         $port = intval($port);
1339                         if($port > 0 && $port < 65536 && $ip_address != '') {
1340                             $records_out[] = array('ip_address' => $ip_address, 'port' => $port);
1341                         }
1342                     }
1343                 }
1344             }
1345         }
1346         
1347         
1348         if(count($records_out) > 0) {
1349             $tpl->setLoop('ip_adresses',$records_out);
46c683 1350         }
ac933e 1351
fb3339 1352         $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/ispconfig.conf');
46c683 1353         file_put_contents($vhost_file,$tpl->grab());
fb3339 1354         $app->log('Writing the conf file: '.$vhost_file,LOGLEVEL_DEBUG);
46c683 1355         unset($tpl);
ac933e 1356
46c683 1357     }
524077 1358     
T 1359     //* Create or update the .htaccess folder protection
1360     function web_folder_user($event_name,$data) {
1361         global $app, $conf;
c69439 1362
524077 1363         $app->uses('system');
T 1364         
1365         if($event_name == 'web_folder_user_delete') {
1366             $folder_id = $data['old']['web_folder_id'];
1367         } else {
1368             $folder_id = $data['new']['web_folder_id'];
1369         }
1370         
1371         $folder = $app->db->queryOneRecord("SELECT * FROM web_folder WHERE web_folder_id = ".intval($folder_id));
1372         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".intval($folder['parent_domain_id']));
1373         
1374         if(!is_array($folder) or !is_array($website)) {
1375             $app->log('Not able to retrieve folder or website record.',LOGLEVEL_DEBUG);
1376             return false;
1377         }
1378         
1379         //* Get the folder path.
c69439 1380         if(substr($folder['path'],0,1) == '/') $folder['path'] = substr($folder['path'],1);
T 1381         if(substr($folder['path'],-1) == '/') $folder['path'] = substr($folder['path'],0,-1);
1382         $folder_path = escapeshellcmd($website['document_root'].'/web/'.$folder['path']);
8f08b5 1383         if(substr($folder_path,-1) != '/') $folder_path .= '/';
524077 1384         
T 1385         //* Check if the resulting path is inside the docroot
c69439 1386         if(stristr($folder_path,'..') || stristr($folder_path,'./') || stristr($folder_path,'\\')) {
T 1387             $app->log('Folder path "'.$folder_path.'" contains .. or ./.',LOGLEVEL_DEBUG);
524077 1388             return false;
T 1389         }
1390         
1391         //* Create the folder path, if it does not exist
053547 1392         if(!is_dir($folder_path)) {
T 1393             exec('mkdir -p '.$folder_path);
1394             chown($folder_path,$website['system_user']);
1395             chgrp($folder_path,$website['system_group']);
1396         }
524077 1397         
T 1398         //* Create empty .htpasswd file, if it does not exist
1399         if(!is_file($folder_path.'.htpasswd')) {
1400             touch($folder_path.'.htpasswd');
1401             chmod($folder_path.'.htpasswd',0755);
053547 1402             chown($folder_path.'.htpasswd',$website['system_user']);
T 1403             chgrp($folder_path.'.htpasswd',$website['system_group']);
900a38 1404             $app->log('Created file '.$folder_path.'.htpasswd',LOGLEVEL_DEBUG);
524077 1405         }
T 1406         
0ea045 1407         /*
F 1408         $auth_users = $app->db->queryAllRecords("SELECT * FROM web_folder_user WHERE active = 'y' AND web_folder_id = ".intval($folder_id));
1409         $htpasswd_content = '';
1410         if(is_array($auth_users) && !empty($auth_users)){
1411             foreach($auth_users as $auth_user){
1412                 $htpasswd_content .= $auth_user['username'].':'.$auth_user['password']."\n";
1413             }
1414         }
1415         $htpasswd_content = trim($htpasswd_content);
1416         @file_put_contents($folder_path.'.htpasswd', $htpasswd_content);
1417         $app->log('Changed .htpasswd file: '.$folder_path.'.htpasswd',LOGLEVEL_DEBUG);
1418         */
1419         
1420         if(($data['new']['username'] != $data['old']['username'] || $data['new']['active'] == 'n') && $data['old']['username'] != '') {
c69439 1421             $app->system->removeLine($folder_path.'.htpasswd',$data['old']['username'].':');
T 1422             $app->log('Removed user: '.$data['old']['username'],LOGLEVEL_DEBUG);
1423         }
1424         
524077 1425         //* Add or remove the user from .htpasswd file
T 1426         if($event_name == 'web_folder_user_delete') {
c69439 1427             $app->system->removeLine($folder_path.'.htpasswd',$data['old']['username'].':');
T 1428             $app->log('Removed user: '.$data['old']['username'],LOGLEVEL_DEBUG);
524077 1429         } else {
c69439 1430             if($data['new']['active'] == 'y') {
T 1431                 $app->system->replaceLine($folder_path.'.htpasswd',$data['new']['username'].':',$data['new']['username'].':'.$data['new']['password'],0,1);
1432                 $app->log('Added or updated user: '.$data['new']['username'],LOGLEVEL_DEBUG);
1433             }
524077 1434         }
T 1435         
0ea045 1436         
524077 1437         //* Create the .htaccess file
0ea045 1438         //if(!is_file($folder_path.'.htaccess')) {
524077 1439             $ht_file = "AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$folder_path.".htpasswd\nrequire valid-user";
T 1440             file_put_contents($folder_path.'.htaccess',$ht_file);
053547 1441             chmod($folder_path.'.htaccess',0755);
T 1442             chown($folder_path.'.htaccess',$website['system_user']);
1443             chgrp($folder_path.'.htaccess',$website['system_group']);
900a38 1444             $app->log('Created file '.$folder_path.'.htaccess',LOGLEVEL_DEBUG);
0ea045 1445         //}
524077 1446         
T 1447     }
1448     
1449     //* Remove .htaccess and .htpasswd file, when folder protection is removed
1450     function web_folder_delete($event_name,$data) {
1451         global $app, $conf;
1452         
1453         $folder_id = $data['old']['web_folder_id'];
1454         
219bb4 1455         $folder = $data['old'];
524077 1456         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".intval($folder['parent_domain_id']));
T 1457         
1458         if(!is_array($folder) or !is_array($website)) {
1459             $app->log('Not able to retrieve folder or website record.',LOGLEVEL_DEBUG);
1460             return false;
1461         }
1462         
1463         //* Get the folder path.
0ea045 1464         if(substr($folder['path'],0,1) == '/') $folder['path'] = substr($folder['path'],1);
F 1465         if(substr($folder['path'],-1) == '/') $folder['path'] = substr($folder['path'],0,-1);
524077 1466         $folder_path = realpath($website['document_root'].'/web/'.$folder['path']);
8f08b5 1467         if(substr($folder_path,-1) != '/') $folder_path .= '/';
524077 1468         
T 1469         //* Check if the resulting path is inside the docroot
1470         if(substr($folder_path,0,strlen($website['document_root'])) != $website['document_root']) {
1471             $app->log('Folder path is outside of docroot.',LOGLEVEL_DEBUG);
1472             return false;
1473         }
1474         
1475         //* Remove .htpasswd file
1476         if(is_file($folder_path.'.htpasswd')) {
1477             unlink($folder_path.'.htpasswd');
900a38 1478             $app->log('Removed file '.$folder_path.'.htpasswd',LOGLEVEL_DEBUG);
524077 1479         }
T 1480         
1481         //* Remove .htaccess file
1482         if(is_file($folder_path.'.htaccess')) {
1483             unlink($folder_path.'.htaccess');
900a38 1484             $app->log('Removed file '.$folder_path.'.htaccess',LOGLEVEL_DEBUG);
524077 1485         }
2023a7 1486     }
T 1487     
1488     //* Update folder protection, when path has been changed
1489     function web_folder_update($event_name,$data) {
1490         global $app, $conf;
1491         
1492         $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".intval($data['new']['parent_domain_id']));
1493     
1494         if(!is_array($website)) {
1495             $app->log('Not able to retrieve folder or website record.',LOGLEVEL_DEBUG);
1496             return false;
1497         }
1498         
1499         //* Get the folder path.
0ea045 1500         if(substr($data['old']['path'],0,1) == '/') $data['old']['path'] = substr($data['old']['path'],1);
F 1501         if(substr($data['old']['path'],-1) == '/') $data['old']['path'] = substr($data['old']['path'],0,-1);
2023a7 1502         $old_folder_path = realpath($website['document_root'].'/web/'.$data['old']['path']);
8f08b5 1503         if(substr($old_folder_path,-1) != '/') $old_folder_path .= '/';
2023a7 1504             
0ea045 1505         if(substr($data['new']['path'],0,1) == '/') $data['new']['path'] = substr($data['new']['path'],1);
F 1506         if(substr($data['new']['path'],-1) == '/') $data['new']['path'] = substr($data['new']['path'],0,-1);
2023a7 1507         $new_folder_path = escapeshellcmd($website['document_root'].'/web/'.$data['new']['path']);
8f08b5 1508         if(substr($new_folder_path,-1) != '/') $new_folder_path .= '/';
2023a7 1509         
T 1510         //* Check if the resulting path is inside the docroot
1511         if(stristr($new_folder_path,'..') || stristr($new_folder_path,'./') || stristr($new_folder_path,'\\')) {
1512             $app->log('Folder path "'.$new_folder_path.'" contains .. or ./.',LOGLEVEL_DEBUG);
1513             return false;
1514         }
1515         if(stristr($old_folder_path,'..') || stristr($old_folder_path,'./') || stristr($old_folder_path,'\\')) {
1516             $app->log('Folder path "'.$old_folder_path.'" contains .. or ./.',LOGLEVEL_DEBUG);
1517             return false;
1518         }
1519         
1520         //* Check if the resulting path is inside the docroot
1521         if(substr($old_folder_path,0,strlen($website['document_root'])) != $website['document_root']) {
1522             $app->log('Old folder path '.$old_folder_path.' is outside of docroot.',LOGLEVEL_DEBUG);
1523             return false;
1524         }
1525         if(substr($new_folder_path,0,strlen($website['document_root'])) != $website['document_root']) {
1526             $app->log('New folder path '.$new_folder_path.' is outside of docroot.',LOGLEVEL_DEBUG);
1527             return false;
1528         }
1529             
1530         //* Create the folder path, if it does not exist
1531         if(!is_dir($new_folder_path)) exec('mkdir -p '.$new_folder_path);
1532         
1533         if($data['old']['path'] != $data['new']['path']) {
1534
1535         
1536             //* move .htpasswd file
1537             if(is_file($old_folder_path.'.htpasswd')) {
1538                 rename($old_folder_path.'.htpasswd',$new_folder_path.'.htpasswd');
0ea045 1539                 $app->log('Moved file '.$old_folder_path.'.htpasswd to '.$new_folder_path.'.htpasswd',LOGLEVEL_DEBUG);
2023a7 1540             }
T 1541             
0ea045 1542             //* delete old .htaccess file
2023a7 1543             if(is_file($old_folder_path.'.htaccess')) {
0ea045 1544                 unlink($old_folder_path.'.htaccess');
F 1545                 $app->log('Deleted file '.$old_folder_path.'.htaccess',LOGLEVEL_DEBUG);
2023a7 1546             }
T 1547         
1548         }
1549         
1550         //* Create the .htaccess file
0ea045 1551         if($data['new']['active'] == 'y') {
F 1552             $ht_file = "AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$new_folder_path.".htpasswd\nrequire valid-user";
2023a7 1553             file_put_contents($new_folder_path.'.htaccess',$ht_file);
T 1554             chmod($new_folder_path.'.htpasswd',0755);
053547 1555             chown($folder_path.'.htpasswd',$website['system_user']);
T 1556             chgrp($folder_path.'.htpasswd',$website['system_group']);
1557             $app->log('Created file '.$new_folder_path.'.htpasswd',LOGLEVEL_DEBUG);
2023a7 1558         }
T 1559         
1560         //* Remove .htaccess file
1561         if($data['new']['active'] == 'n' && is_file($new_folder_path.'.htaccess')) {
1562             unlink($new_folder_path.'.htaccess');
900a38 1563             $app->log('Removed file '.$new_folder_path.'.htaccess',LOGLEVEL_DEBUG);
2023a7 1564         }
524077 1565         
T 1566         
1567     }
ac933e 1568
V 1569     /**
1570      * This function is called when a Webdav-User is inserted, updated or deleted.
1571      *
1572      * @author Oliver Vogel
1573      * @param string $event_name
1574      * @param array $data
1575      */
1576     public function webdav($event_name,$data) {
1577         global $app, $conf;
52a04e 1578         
T 1579         /*
1580          * load the server configuration options
1581         */
fb3339 1582         $app->uses('getconf');
J 1583         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
ac933e 1584
V 1585         if (($event_name == 'webdav_user_insert') || ($event_name == 'webdav_user_update')) {
1586
1587             /*
1588              * Get additional informations
1589             */
fb3339 1590             $sitedata = $app->db->queryOneRecord('SELECT document_root, domain, system_user, system_group FROM web_domain WHERE domain_id = ' . $data['new']['parent_domain_id']);
ac933e 1591             $documentRoot = $sitedata['document_root'];
V 1592             $domain = $sitedata['domain'];
ca14fe 1593             $user = $sitedata['system_user'];
V 1594             $group = $sitedata['system_group'];
835c5d 1595             $webdav_user_dir = $documentRoot . '/webdav/' . $data['new']['dir'];
ac933e 1596
V 1597             /* Check if this is a chrooted setup */
1598             if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
1599                 $apache_chrooted = true;
fb3339 1600                 $app->log('Info: Apache is chrooted.',LOGLEVEL_DEBUG);
ac933e 1601             } else {
V 1602                 $apache_chrooted = false;
1603             }
835c5d 1604             
T 1605             //* We dont want to have relative paths here
1606             if(stristr($webdav_user_dir,'..')  || stristr($webdav_user_dir,'./')) {
1607                 $app->log('Folder path '.$webdav_user_dir.' contains ./ or .. '.$documentRoot,LOGLEVEL_WARN);
1608                 return false;
1609             }
1610             
1611             //* Check if the resulting path exists if yes, if it is inside the docroot
1612             if(is_dir($webdav_user_dir) && substr(realpath($webdav_user_dir),0,strlen($documentRoot)) != $documentRoot) {
1613                 $app->log('Folder path '.$webdav_user_dir.' is outside of docroot '.$documentRoot,LOGLEVEL_WARN);
1614                 return false;
1615             }
ac933e 1616
V 1617             /*
1618              * First the webdav-root - folder has to exist
1619             */
835c5d 1620             if(!is_dir($webdav_user_dir)) {
T 1621                 $app->log('Webdav User directory '.$webdav_user_dir.' does not exist. Creating it now.',LOGLEVEL_DEBUG);
1622                 exec('mkdir -p '.escapeshellcmd($webdav_user_dir));
ac933e 1623             }
V 1624
1625             /*
ca14fe 1626              * The webdav - Root needs the group/user as owner and the apache as read and write
ac933e 1627             */
fb3339 1628             $this->_exec('chown ' . $user . ':' . $group . ' ' . escapeshellcmd($documentRoot . '/webdav/'));
J 1629             $this->_exec('chmod 770 ' . escapeshellcmd($documentRoot . '/webdav/'));
ac933e 1630
V 1631             /*
ca14fe 1632              * The webdav folder (not the webdav-root!) needs the same (not in ONE step, because the
V 1633              * pwd-files are owned by root)
ac933e 1634             */
835c5d 1635             $this->_exec('chown ' . $user . ':' . $group . ' ' . escapeshellcmd($webdav_user_dir.' -R'));
T 1636             $this->_exec('chmod 770 ' . escapeshellcmd($webdav_user_dir.' -R'));
ca14fe 1637
V 1638             /*
1639              * if the user is active, we have to write/update the password - file
1640              * if the user is inactive, we have to inactivate the user by removing the user from the file
1641             */
1642             if ($data['new']['active'] == 'y') {
835c5d 1643                 $this->_writeHtDigestFile( $webdav_user_dir . '.htdigest', $data['new']['username'], $data['new']['dir'], $data['new']['password']);
ca14fe 1644             }
V 1645             else {
1646                 /* empty pwd removes the user! */
835c5d 1647                 $this->_writeHtDigestFile( $webdav_user_dir . '.htdigest', $data['new']['username'], $data['new']['dir'], '');
ca14fe 1648             }
ac933e 1649
V 1650             /*
1651              * Next step, patch the vhost - file
1652             */
fb3339 1653             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'] . '/' . $domain . '.vhost');
ac933e 1654             $this->_patchVhostWebdav($vhost_file, $documentRoot . '/webdav');
ca14fe 1655
ac933e 1656             /*
V 1657              * Last, restart apache
1658             */
1659             if($apache_chrooted) {
1660                 $app->services->restartServiceDelayed('httpd','restart');
1661             } else {
1662                 // request a httpd reload when all records have been processed
1663                 $app->services->restartServiceDelayed('httpd','reload');
1664             }
1665
1666         }
1667
1668         if ($event_name == 'webdav_user_delete') {
1669             /*
1670              * Get additional informations
1671             */
fb3339 1672             $sitedata = $app->db->queryOneRecord('SELECT document_root, domain FROM web_domain WHERE domain_id = ' . $data['old']['parent_domain_id']);
ac933e 1673             $documentRoot = $sitedata['document_root'];
52a04e 1674             $domain = $sitedata['domain'];
ac933e 1675
V 1676             /*
1677              * We dont't want to destroy any (transfer)-Data. So we do NOT delete any dir.
1678              * So the only thing, we have to do, is to delete the user from the password-file
ca14fe 1679             */
ac933e 1680             $this->_writeHtDigestFile( $documentRoot . '/webdav/' . $data['old']['dir'] . '.htdigest', $data['old']['username'], $data['old']['dir'], '');
52a04e 1681             
T 1682             /*
1683              * Next step, patch the vhost - file
1684             */
fb3339 1685             $vhost_file = escapeshellcmd($web_config['vhost_conf_dir'] . '/' . $domain . '.vhost');
52a04e 1686             $this->_patchVhostWebdav($vhost_file, $documentRoot . '/webdav');
T 1687             
1688             /*
1689              * Last, restart apache
1690             */
1691             if($apache_chrooted) {
1692                 $app->services->restartServiceDelayed('httpd','restart');
1693             } else {
1694                 // request a httpd reload when all records have been processed
1695                 $app->services->restartServiceDelayed('httpd','reload');
1696             }
ac933e 1697         }
V 1698     }
1699
1700
1701     /**
1702      * This function writes the htdigest - files used by webdav and digest
ca14fe 1703      * more info: see http://riceball.com/d/node/424
ac933e 1704      * @author Oliver Vogel
V 1705      * @param string $filename The name of the digest-file
1706      * @param string $username The name of the webdav-user
1707      * @param string $authname The name of the realm
ca14fe 1708      * @param string $pwd      The password-hash of the user
ac933e 1709      */
ca14fe 1710     private function _writeHtDigestFile($filename, $username, $authname, $pwdhash ) {
ac933e 1711         $changed = false;
0ff3f1 1712         if(is_file($filename)) {
T 1713             $in = fopen($filename, 'r');
1714             $output = '';
1715             /*
1716             * read line by line and search for the username and authname
1717             */
1718             while (preg_match("/:/", $line = fgets($in))) {
1719                 $line = rtrim($line);
1720                 $tmp = explode(':', $line);
1721                 if ($tmp[0] == $username && $tmp[1] == $authname) {
1722                     /*
1723                     * found the user. delete or change it?
1724                     */
1725                     if ($pwdhash != '') {
1726                         $output .= $tmp[0] . ':' . $tmp[1] . ':' . $pwdhash . "\n";
1727                         }
1728                     $changed = true;
1729                 }
1730                 else {
1731                     $output .= $line . "\n";
1732                 }
ac933e 1733             }
0ff3f1 1734             fclose($in);
ac933e 1735         }
V 1736         /*
1737          * if we didn't change anything, we have to add the new user at the end of the file
1738         */
1739         if (!$changed) {
f17dab 1740             $output .= $username . ':' . $authname . ':' . $pwdhash . "\n";
ac933e 1741         }
0ff3f1 1742         
ac933e 1743
V 1744         /*
1745          * Now lets write the new file
1746         */
52a04e 1747         if(trim($output) == '') {
T 1748             unlink($filename);
1749         } else {
1750             file_put_contents($filename, $output);
1751         }
ac933e 1752     }
V 1753
1754     /**
1755      * This function patches the vhost-file and adds all webdav - user.
1756      * This function is written, because the creation of the vhost - file is sophisticated and
1757      * i don't want to make it more "heavy" by also adding this code too...
1758      * @author Oliver Vogel
1759      * @param string $fileName The Name of the .vhost-File (path included)
1760      * @param string $webdavRoot The root of the webdav-folder
1761      */
1762     private function _patchVhostWebdav($fileName, $webdavRoot) {
1763         $in = fopen($fileName, 'r');
1764         $output = '';
1765         $inWebdavSection = false;
1766
1767         /*
1768          * read line by line and search for the username and authname
1769         */
1770         while ($line = fgets($in)) {
1771             /*
1772              *  is the "replace-comment" found...
1773             */
1774             if (trim($line) == '# WEBDAV BEGIN') {
1775                 /*
1776                  * The begin of the webdav - section is found, so ignore all lines til the end  is found
1777                 */
1778                 $inWebdavSection = true;
1779
1780                 $output .= "      # WEBDAV BEGIN\n";
1781
1782                 /*
1783                  * add all the webdav-dirs to the webdav-section
1784                 */
fb3a98 1785                 $files = @scandir($webdavRoot);
T 1786                 if(is_array($files)) {
ac933e 1787                 foreach($files as $file) {
V 1788                     if (substr($file, strlen($file) - strlen('.htdigest')) == '.htdigest') {
1789                         /*
1790                          * found a htdigest - file, so add it to webdav
1791                         */
1792                         $fn = substr($file, 0, strlen($file) - strlen('.htdigest'));
1793                         $output .= "\n";
dd1afa 1794                         // $output .= "      Alias /" . $fn . ' ' . $webdavRoot . '/' . $fn . "\n";
T 1795                         // $output .= "      <Location /" . $fn . ">\n";
9f56bd 1796                         $output .= "      Alias /webdav/" . $fn . ' ' . $webdavRoot . '/' . $fn . "\n";
T 1797                         $output .= "      <Location /webdav/" . $fn . ">\n";
ac933e 1798                         $output .= "        DAV On\n";
91aaaf 1799                         $output .= '        BrowserMatch "MSIE" AuthDigestEnableQueryStringHack=On'."\n";
ac933e 1800                         $output .= "        AuthType Digest\n";
V 1801                         $output .= "        AuthName \"" . $fn . "\"\n";
fb3339 1802                         $output .= "        AuthUserFile " . $webdavRoot . '/' . $file . "\n";
ac933e 1803                         $output .= "        Require valid-user \n";
V 1804                         $output .= "        Options +Indexes \n";
1805                         $output .= "        Order allow,deny \n";
1806                         $output .= "        Allow from all \n";
1807                         $output .= "      </Location> \n";
1808                     }
1809                 }
fb3a98 1810                 }
ac933e 1811             }
V 1812             /*
1813              *  is the "replace-comment-end" found...
1814             */
1815             if (trim($line) == '# WEBDAV END') {
1816                 /*
1817                  * The end of the webdav - section is found, so stop ignoring
1818                 */
1819                 $inWebdavSection = false;
1820             }
1821
1822             /*
1823              * Write the line to the output, if it is not in the section
1824             */
1825             if (!$inWebdavSection) {
1826                 $output .= $line;
1827             }
1828         }
1829         fclose($in);
1830
1831         /*
1832          * Now lets write the new file
1833         */
1834         file_put_contents($fileName, $output);
1835
1836     }
58c210 1837     
T 1838     //* Update the awstats configuration file
1839     private function awstats_update ($data,$web_config) {
1840         global $app;
1841         
2a6eac 1842         $awstats_conf_dir = $web_config['awstats_conf_dir'];
T 1843         
b10f96 1844         if(!is_dir($data['new']['document_root']."/web/stats/")) mkdir($data['new']['document_root']."/web/stats");
fb3339 1845         if(!@is_file($awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf') || ($data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain'])) {
J 1846             if ( @is_file($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf') ) {
1847                 unlink($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf');
58c210 1848             }
T 1849             
1850             $content = '';
2a6eac 1851             $content .= "Include \"".$awstats_conf_dir."/awstats.conf\"\n";
fb3339 1852             $content .= "LogFile=\"/var/log/ispconfig/httpd/".$data['new']['domain']."/access.log\"\n";
J 1853             $content .= "SiteDomain=\"".$data['new']['domain']."\"\n";
1854             $content .= "HostAliases=\"www.".$data['new']['domain']."  localhost 127.0.0.1\"\n";
58c210 1855             
fb3339 1856             file_put_contents($awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf',$content);
J 1857             $app->log('Created AWStats config file: '.$awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf',LOGLEVEL_DEBUG);
58c210 1858         }
d81a4c 1859         
3498f7 1860         if(is_file($data['new']['document_root']."/web/stats/index.html")) unlink($data['new']['document_root']."/web/stats/index.html");
d81a4c 1861         copy("/usr/local/ispconfig/server/conf/awstats_index.php.master",$data['new']['document_root']."/web/stats/index.php");
58c210 1862     }
T 1863     
1864     //* Delete the awstats configuration file
1865     private function awstats_delete ($data,$web_config) {
1866         global $app;
1867         
1868         $awstats_conf_dir = $web_config['awstats_conf_dir'];
1869         
fb3339 1870         if ( @is_file($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf') ) {
J 1871             unlink($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf');
1872             $app->log('Removed AWStats config file: '.$awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf',LOGLEVEL_DEBUG);
58c210 1873         }
T 1874     }
1ca823 1875     
T 1876     function client_delete($event_name,$data) {
1877         global $app, $conf;
1878         
1879         $app->uses("getconf");
1880         $web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
1881         
1882         $client_id = intval($data['old']['client_id']);
1883         if($client_id > 0) {
1884             
1885             $client_dir = $web_config['website_basedir'].'/clients/client'.$client_id;
1886             if(is_dir($client_dir) && !stristr($client_dir,'..')) {
1887                 @rmdir($client_dir);
1888                 $app->log('Removed client directory: '.$client_dir,LOGLEVEL_DEBUG);
1889             }
1890             
1891             $this->_exec('groupdel client'.$client_id);
1892             $app->log('Removed group client'.$client_id,LOGLEVEL_DEBUG);
1893         }
1894         
1895     }
ac933e 1896
1c40af 1897     //* Wrapper for exec function for easier debugging
T 1898     private function _exec($command) {
1899         global $app;
fb3339 1900         $app->log('exec: '.$command,LOGLEVEL_DEBUG);
1c40af 1901         exec($command);
T 1902     }
7ed741 1903     
T 1904     private function _checkTcp ($host,$port) {
1905
1906         $fp = @fsockopen ($host, $port, $errno, $errstr, 2);
1907
1908         if ($fp) {
1909             fclose($fp);
1910             return true;
1911         } else {
1912             return false;
1913         }
1914     }
ac933e 1915
552178 1916     public function create_relative_link($f, $t) {
M 1917         // $from already exists
1918         $from = realpath($f);
1919
1920         // realpath requires the traced file to exist - so, lets touch it first, then remove
1921         @unlink($t); touch($t);
1922         $to = realpath($t);
1923         @unlink($t);
1924
1925         // Remove from the left side matching path elements from $from and $to
1926         // and get path elements counts
1927         $a1 = explode('/', $from); $a2 = explode('/', $to);
1928         for ($c = 0; $a1[$c] == $a2[$c]; $c++) {
1929             unset($a1[$c]); unset($a2[$c]);
1930         }
1931         $cfrom = implode('/', $a1);
1932
1933         // Check if a path is fully a subpath of another - no way to create symlink in the case
1934         if (count($a1) == 0 || count($a2) == 0) return false;
1935
1936         // Add ($cnt_to-1) number of "../" elements to left side of $cfrom
1937         for ($c = 0; $c < (count($a2)-1); $c++) { $cfrom = '../'.$cfrom; }
1938
1939         return symlink($cfrom, $to);
1940     }
46c683 1941
T 1942 } // end class
1943
1c711c 1944 ?>