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