Newer
Older
$cgi_tpl->setVar('has_custom_php_ini',$has_custom_php_ini);
if($has_custom_php_ini) {
$cgi_tpl->setVar('php_ini_path',escapeshellcmd($custom_php_ini_dir));
} else {
$cgi_tpl->setVar('php_ini_path',escapeshellcmd($fastcgi_config['fastcgi_phpini_path']));
$cgi_starter_script = escapeshellcmd($cgi_starter_path.$cgi_config['cgi_starter_script']);
file_put_contents($cgi_starter_script,$cgi_tpl->grab());
unset($cgi_tpl);
$app->log('Creating cgi starter script: '.$cgi_starter_script,LOGLEVEL_DEBUG);
exec('chmod 755 '.$cgi_starter_script);
exec('chown '.$data['new']['system_user'].':'.$data['new']['system_group'].' '.$cgi_starter_script);
$tpl->setVar('cgi_starter_path',$cgi_starter_path);
$tpl->setVar('cgi_starter_script',$cgi_config['cgi_starter_script']);
}
$vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['new']['domain'].'.vhost');
//* Make a backup copy of vhost file
tbrehm
committed
if(file_exists($vhost_file)) copy($vhost_file,$vhost_file.'~');
//* create empty vhost array
$vhosts = array();
//* Add vhost for ipv4 IP
if(count($rewrite_rules) > 0){
$vhosts[] = array('ip_address' => $data['new']['ip_address'], 'ssl_enabled' => 0, 'port' => 80, 'redirects' => $rewrite_rules);
} else {
$vhosts[] = array('ip_address' => $data['new']['ip_address'], 'ssl_enabled' => 0, 'port' => 80);
}
//* Add vhost for ipv4 IP with SSL
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)) {
if(count($rewrite_rules) > 0){
$vhosts[] = array('ip_address' => $data['new']['ip_address'], 'ssl_enabled' => 1, 'port' => '443', 'redirects' => $rewrite_rules);
} else {
$vhosts[] = array('ip_address' => $data['new']['ip_address'], 'ssl_enabled' => 1, 'port' => '443');
}
$app->log('Enable SSL for: '.$domain,LOGLEVEL_DEBUG);
}
//* Add vhost for IPv6 IP
if($data['new']['ipv6_address'] != '') {
if(count($rewrite_rules) > 0){
$vhosts[] = array('ip_address' => '['.$data['new']['ipv6_address'].']', 'ssl_enabled' => 0, 'port' => 80, 'redirects' => $rewrite_rules);
} else {
$vhosts[] = array('ip_address' => '['.$data['new']['ipv6_address'].']', 'ssl_enabled' => 0, 'port' => 80);
}
//* Add vhost for ipv6 IP with SSL
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)) {
if(count($rewrite_rules) > 0){
$vhosts[] = array('ip_address' => '['.$data['new']['ipv6_address'].']', 'ssl_enabled' => 1, 'port' => '443', 'redirects' => $rewrite_rules);
} else {
$vhosts[] = array('ip_address' => '['.$data['new']['ipv6_address'].']', 'ssl_enabled' => 1, 'port' => '443');
}
$app->log('Enable SSL for IPv6: '.$domain,LOGLEVEL_DEBUG);
}
}
//* Set the vhost loop
$tpl->setLoop('vhosts',$vhosts);
//* Write vhost file
file_put_contents($vhost_file,$tpl->grab());
$app->log('Writing the vhost file: '.$vhost_file,LOGLEVEL_DEBUG);
unset($tpl);
/*
* maybe we have some webdav - user. If so, add them...
*/
$this->_patchVhostWebdav($vhost_file, $data['new']['document_root'] . '/webdav');
//* Set the symlink to enable the vhost
//* First we check if there is a old type of symlink and remove it
$vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['new']['domain'].'.vhost');
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
if(is_link($vhost_symlink)) unlink($vhost_symlink);
//* Remove old or changed symlinks
if($data['new']['subdomain'] != $data['old']['subdomain'] or $data['new']['active'] == 'n') {
$vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['new']['domain'].'.vhost');
if(is_link($vhost_symlink)) {
unlink($vhost_symlink);
$app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
}
$vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['new']['domain'].'.vhost');
if(is_link($vhost_symlink)) {
unlink($vhost_symlink);
$app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
}
}
//* New symlink
if($data['new']['subdomain'] == '*') {
$vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['new']['domain'].'.vhost');
} else {
$vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['new']['domain'].'.vhost');
}
if($data['new']['active'] == 'y' && !is_link($vhost_symlink)) {
symlink($vhost_file,$vhost_symlink);
$app->log('Creating symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
// remove old symlink and vhost file, if domain name of the site has changed
if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
$vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['old']['domain'].'.vhost');
if(is_link($vhost_symlink)) {
unlink($vhost_symlink);
$app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
}
$vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['old']['domain'].'.vhost');
if(is_link($vhost_symlink)) {
unlink($vhost_symlink);
$app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
}
$vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
if(is_link($vhost_symlink)) {
unlink($vhost_symlink);
$app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
}
$vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
unlink($vhost_file);
$app->log('Removing file: '.$vhost_file,LOGLEVEL_DEBUG);
//* Create .htaccess and .htpasswd file for website statistics
if(!is_file($data['new']['document_root'].'/web/stats/.htaccess') or $data['old']['document_root'] != $data['new']['document_root']) {
if(!is_dir($data['new']['document_root'].'/web/stats')) mkdir($data['new']['document_root'].'/web/stats');
$ht_file = "AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$data['new']['document_root']."/.htpasswd_stats\nrequire valid-user";
file_put_contents($data['new']['document_root'].'/web/stats/.htaccess',$ht_file);
chmod($data['new']['document_root'].'/web/stats/.htaccess',0755);
unset($ht_file);
}
if(!is_file($data['new']['document_root'].'/.htpasswd_stats') || $data['new']['stats_password'] != $data['old']['stats_password']) {
if(trim($data['new']['stats_password']) != '') {
$htp_file = 'admin:'.trim($data['new']['stats_password']);
file_put_contents($data['new']['document_root'].'/.htpasswd_stats',$htp_file);
chmod($data['new']['document_root'].'/.htpasswd_stats',0755);
unset($htp_file);
}
}
//* Create awstats configuration
if($data['new']['stats_type'] == 'awstats' && $data['new']['type'] == 'vhost') {
$this->awstats_update($data,$web_config);
}
if($web_config['check_apache_config'] == 'y') {
//* Test if apache starts with the new configuration file
$apache_online_status_before_restart = $this->_checkTcp('localhost',80);
$app->log('Apache status is: '.$apache_online_status_before_restart,LOGLEVEL_DEBUG);
$app->services->restartService('httpd','restart');
// wait a few seconds, before we test the apache status again
sleep(2);
//* Check if apache restarted successfully if it was online before
$apache_online_status_after_restart = $this->_checkTcp('localhost',80);
$app->log('Apache online status after restart is: '.$apache_online_status_after_restart,LOGLEVEL_DEBUG);
if($apache_online_status_before_restart && !$apache_online_status_after_restart) {
$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);
copy($vhost_file,$vhost_file.'.err');
if(is_file($vhost_file.'~')) {
//* Copy back the last backup file
copy($vhost_file.'~',$vhost_file);
} else {
//* There is no backup file, so we create a empty vhost file with a warning message inside
file_put_contents($vhost_file,"# Apache did not start after modifying this vhost file.\n# Please check file $vhost_file.err for syntax errors.");
}
$app->services->restartService('httpd','restart');
}
} else {
//* We do not check the apache config after changes (is faster)
if($apache_chrooted) {
$app->services->restartServiceDelayed('httpd','restart');
} else {
// request a httpd reload when all records have been processed
$app->services->restartServiceDelayed('httpd','reload');
}
}
// Remove the backup copy of the config file.
if(@is_file($vhost_file.'~')) unlink($vhost_file.'~');
//* Unset action to clean it for next processed vhost.
$this->action = '';
function delete($event_name,$data) {
global $app, $conf;
// load the server configuration options
$app->uses('getconf');
$web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
tbrehm
committed
//* Check if this is a chrooted setup
if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
tbrehm
committed
$apache_chrooted = true;
} else {
$apache_chrooted = false;
}
if($data['old']['type'] != 'vhost' && $data['old']['parent_domain_id'] > 0) {
//* This is a alias domain or subdomain, so we have to update the website instead
$parent_domain_id = intval($data['old']['parent_domain_id']);
$tmp = $app->db->queryOneRecord('SELECT * FROM web_domain WHERE domain_id = '.$parent_domain_id." AND active = 'y'");
$data['new'] = $tmp;
$data['old'] = $tmp;
$this->action = 'update';
// just run the update function
$this->update($event_name,$data);
} else {
//* This is a website
// Deleting the vhost file, symlink and the data directory
$vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
$vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
if(is_link($vhost_symlink)){
unlink($vhost_symlink);
$app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
}
$vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/900-'.$data['old']['domain'].'.vhost');
if(is_link($vhost_symlink)){
unlink($vhost_symlink);
$app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
}
$vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/100-'.$data['old']['domain'].'.vhost');
if(is_link($vhost_symlink)){
unlink($vhost_symlink);
$app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
}
unlink($vhost_file);
$app->log('Removing vhost file: '.$vhost_file,LOGLEVEL_DEBUG);
$docroot = escapeshellcmd($data['old']['document_root']);
if($docroot != '' && !stristr($docroot,'..')) exec('rm -rf '.$docroot);
//remove the php fastgi starter script if available
if ($data['old']['php'] == 'fast-cgi') {
$fastcgi_starter_path = str_replace('[system_user]',$data['old']['system_user'],$web_config['fastcgi_starter_path']);
exec('rm -rf '.$fastcgi_starter_path);
//remove the php cgi starter script if available
if ($data['old']['php'] == 'cgi') {
// TODO: fetch the date from the server-settings
$web_config['cgi_starter_path'] = $web_config['website_basedir'].'/php-cgi-scripts/[system_user]/';
$cgi_starter_path = str_replace('[system_user]',$data['old']['system_user'],$web_config['cgi_starter_path']);
exec('rm -rf '.$cgi_starter_path);
}
}
$app->log('Removing website: '.$docroot,LOGLEVEL_DEBUG);
// Delete the symlinks for the sites
$client = $app->db->queryOneRecord('SELECT client_id FROM sys_group WHERE sys_group.groupid = '.intval($data['old']['sys_groupid']));
$client_id = intval($client['client_id']);
unset($client);
$tmp_symlinks_array = explode(':',$web_config['website_symlinks']);
if(is_array($tmp_symlinks_array)) {
foreach($tmp_symlinks_array as $tmp_symlink) {
$tmp_symlink = str_replace('[client_id]',$client_id,$tmp_symlink);
$tmp_symlink = str_replace('[website_domain]',$data['old']['domain'],$tmp_symlink);
// Remove trailing slash
if(substr($tmp_symlink, -1, 1) == '/') $tmp_symlink = substr($tmp_symlink, 0, -1);
// create the symlinks, if not exist
if(is_link($tmp_symlink)) {
unlink($tmp_symlink);
$app->log('Removing symlink: '.$tmp_symlink,LOGLEVEL_DEBUG);
}
}
}
// end removing symlinks
// Delete the log file directory
$vhost_logfile_dir = escapeshellcmd('/var/log/ispconfig/httpd/'.$data['old']['domain']);
if($data['old']['domain'] != '' && !stristr($vhost_logfile_dir,'..')) exec('rm -rf '.$vhost_logfile_dir);
$app->log('Removing website logfile directory: '.$vhost_logfile_dir,LOGLEVEL_DEBUG);
//delete the web user
$command = 'userdel';
$command .= ' '.$data['old']['system_user'];
exec($command);
if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' '.$command);
//* Remove the awstats configuration file
if($data['old']['stats_type'] == 'awstats') {
$this->awstats_delete($data,$web_config);
}
if($apache_chrooted) {
$app->services->restartServiceDelayed('httpd','restart');
} else {
// request a httpd reload when all records have been processed
$app->services->restartServiceDelayed('httpd','reload');
}
//* This function is called when a IP on the server is inserted, updated or deleted
function server_ip($event_name,$data) {
global $app, $conf;
// load the server configuration options
$app->uses('getconf');
$web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
$app->load('tpl');
$tpl = new tpl();
$tpl->newTemplate('apache_ispconfig.conf.master');
$records = $app->db->queryAllRecords('SELECT * FROM server_ip WHERE server_id = '.$conf['server_id']." AND virtualhost = 'y'");
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
$records_out= array();
if(is_array($records)) {
foreach($records as $rec) {
if($rec['ip_type'] == 'IPv6') {
$ip_address = '['.$rec['ip_address'].']';
} else {
$ip_address = $rec['ip_address'];
}
$ports = explode(',',$rec['virtualhost_port']);
if(is_array($ports)) {
foreach($ports as $port) {
$port = intval($port);
if($port > 0 && $port < 65536 && $ip_address != '') {
$records_out[] = array('ip_address' => $ip_address, 'port' => $port);
}
}
}
}
}
if(count($records_out) > 0) {
$tpl->setLoop('ip_adresses',$records_out);
$vhost_file = escapeshellcmd($web_config['vhost_conf_dir'].'/ispconfig.conf');
file_put_contents($vhost_file,$tpl->grab());
$app->log('Writing the conf file: '.$vhost_file,LOGLEVEL_DEBUG);
unset($tpl);
}
//* Create or update the .htaccess folder protection
function web_folder_user($event_name,$data) {
global $app, $conf;
$app->uses('system');
if($event_name == 'web_folder_user_delete') {
$folder_id = $data['old']['web_folder_id'];
} else {
$folder_id = $data['new']['web_folder_id'];
}
$folder = $app->db->queryOneRecord("SELECT * FROM web_folder WHERE web_folder_id = ".intval($folder_id));
$website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".intval($folder['parent_domain_id']));
if(!is_array($folder) or !is_array($website)) {
$app->log('Not able to retrieve folder or website record.',LOGLEVEL_DEBUG);
return false;
}
//* Get the folder path.
if(substr($folder['path'],0,1) == '/') $folder['path'] = substr($folder['path'],1);
if(substr($folder['path'],-1) == '/') $folder['path'] = substr($folder['path'],0,-1);
$folder_path = escapeshellcmd($website['document_root'].'/web/'.$folder['path']);
if(substr($folder_path,-1) != '/') $folder_path .= '/';
//* Check if the resulting path is inside the docroot
if(stristr($folder_path,'..') || stristr($folder_path,'./') || stristr($folder_path,'\\')) {
$app->log('Folder path "'.$folder_path.'" contains .. or ./.',LOGLEVEL_DEBUG);
return false;
}
//* Create the folder path, if it does not exist
if(!is_dir($folder_path)) {
exec('mkdir -p '.$folder_path);
chown($folder_path,$website['system_user']);
chgrp($folder_path,$website['system_group']);
}
//* Create empty .htpasswd file, if it does not exist
if(!is_file($folder_path.'.htpasswd')) {
touch($folder_path.'.htpasswd');
chmod($folder_path.'.htpasswd',0755);
chown($folder_path.'.htpasswd',$website['system_user']);
chgrp($folder_path.'.htpasswd',$website['system_group']);
$app->log('Created file '.$folder_path.'.htpasswd',LOGLEVEL_DEBUG);
}
/*
$auth_users = $app->db->queryAllRecords("SELECT * FROM web_folder_user WHERE active = 'y' AND web_folder_id = ".intval($folder_id));
$htpasswd_content = '';
if(is_array($auth_users) && !empty($auth_users)){
foreach($auth_users as $auth_user){
$htpasswd_content .= $auth_user['username'].':'.$auth_user['password']."\n";
}
$htpasswd_content = trim($htpasswd_content);
@file_put_contents($folder_path.'.htpasswd', $htpasswd_content);
$app->log('Changed .htpasswd file: '.$folder_path.'.htpasswd',LOGLEVEL_DEBUG);
*/
if(($data['new']['username'] != $data['old']['username'] || $data['new']['active'] == 'n') && $data['old']['username'] != '') {
$app->system->removeLine($folder_path.'.htpasswd',$data['old']['username'].':');
$app->log('Removed user: '.$data['old']['username'],LOGLEVEL_DEBUG);
}
//* Add or remove the user from .htpasswd file
if($event_name == 'web_folder_user_delete') {
$app->system->removeLine($folder_path.'.htpasswd',$data['old']['username'].':');
$app->log('Removed user: '.$data['old']['username'],LOGLEVEL_DEBUG);
if($data['new']['active'] == 'y') {
$app->system->replaceLine($folder_path.'.htpasswd',$data['new']['username'].':',$data['new']['username'].':'.$data['new']['password'],0,1);
$app->log('Added or updated user: '.$data['new']['username'],LOGLEVEL_DEBUG);
}
//if(!is_file($folder_path.'.htaccess')) {
$ht_file = "AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$folder_path.".htpasswd\nrequire valid-user";
file_put_contents($folder_path.'.htaccess',$ht_file);
chmod($folder_path.'.htaccess',0755);
chown($folder_path.'.htaccess',$website['system_user']);
chgrp($folder_path.'.htaccess',$website['system_group']);
$app->log('Created file '.$folder_path.'.htaccess',LOGLEVEL_DEBUG);
//}
}
//* Remove .htaccess and .htpasswd file, when folder protection is removed
function web_folder_delete($event_name,$data) {
global $app, $conf;
$folder_id = $data['old']['web_folder_id'];
$website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".intval($folder['parent_domain_id']));
if(!is_array($folder) or !is_array($website)) {
$app->log('Not able to retrieve folder or website record.',LOGLEVEL_DEBUG);
return false;
}
//* Get the folder path.
if(substr($folder['path'],0,1) == '/') $folder['path'] = substr($folder['path'],1);
if(substr($folder['path'],-1) == '/') $folder['path'] = substr($folder['path'],0,-1);
$folder_path = realpath($website['document_root'].'/web/'.$folder['path']);
if(substr($folder_path,-1) != '/') $folder_path .= '/';
//* Check if the resulting path is inside the docroot
if(substr($folder_path,0,strlen($website['document_root'])) != $website['document_root']) {
$app->log('Folder path is outside of docroot.',LOGLEVEL_DEBUG);
return false;
}
//* Remove .htpasswd file
if(is_file($folder_path.'.htpasswd')) {
unlink($folder_path.'.htpasswd');
$app->log('Removed file '.$folder_path.'.htpasswd',LOGLEVEL_DEBUG);
}
//* Remove .htaccess file
if(is_file($folder_path.'.htaccess')) {
unlink($folder_path.'.htaccess');
$app->log('Removed file '.$folder_path.'.htaccess',LOGLEVEL_DEBUG);
}
//* Update folder protection, when path has been changed
function web_folder_update($event_name,$data) {
global $app, $conf;
$website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".intval($data['new']['parent_domain_id']));
if(!is_array($website)) {
$app->log('Not able to retrieve folder or website record.',LOGLEVEL_DEBUG);
return false;
}
//* Get the folder path.
if(substr($data['old']['path'],0,1) == '/') $data['old']['path'] = substr($data['old']['path'],1);
if(substr($data['old']['path'],-1) == '/') $data['old']['path'] = substr($data['old']['path'],0,-1);
$old_folder_path = realpath($website['document_root'].'/web/'.$data['old']['path']);
if(substr($old_folder_path,-1) != '/') $old_folder_path .= '/';
if(substr($data['new']['path'],0,1) == '/') $data['new']['path'] = substr($data['new']['path'],1);
if(substr($data['new']['path'],-1) == '/') $data['new']['path'] = substr($data['new']['path'],0,-1);
$new_folder_path = escapeshellcmd($website['document_root'].'/web/'.$data['new']['path']);
if(substr($new_folder_path,-1) != '/') $new_folder_path .= '/';
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
//* Check if the resulting path is inside the docroot
if(stristr($new_folder_path,'..') || stristr($new_folder_path,'./') || stristr($new_folder_path,'\\')) {
$app->log('Folder path "'.$new_folder_path.'" contains .. or ./.',LOGLEVEL_DEBUG);
return false;
}
if(stristr($old_folder_path,'..') || stristr($old_folder_path,'./') || stristr($old_folder_path,'\\')) {
$app->log('Folder path "'.$old_folder_path.'" contains .. or ./.',LOGLEVEL_DEBUG);
return false;
}
//* Check if the resulting path is inside the docroot
if(substr($old_folder_path,0,strlen($website['document_root'])) != $website['document_root']) {
$app->log('Old folder path '.$old_folder_path.' is outside of docroot.',LOGLEVEL_DEBUG);
return false;
}
if(substr($new_folder_path,0,strlen($website['document_root'])) != $website['document_root']) {
$app->log('New folder path '.$new_folder_path.' is outside of docroot.',LOGLEVEL_DEBUG);
return false;
}
//* Create the folder path, if it does not exist
if(!is_dir($new_folder_path)) exec('mkdir -p '.$new_folder_path);
if($data['old']['path'] != $data['new']['path']) {
//* move .htpasswd file
if(is_file($old_folder_path.'.htpasswd')) {
rename($old_folder_path.'.htpasswd',$new_folder_path.'.htpasswd');
$app->log('Moved file '.$old_folder_path.'.htpasswd to '.$new_folder_path.'.htpasswd',LOGLEVEL_DEBUG);
//* delete old .htaccess file
unlink($old_folder_path.'.htaccess');
$app->log('Deleted file '.$old_folder_path.'.htaccess',LOGLEVEL_DEBUG);
}
}
//* Create the .htaccess file
if($data['new']['active'] == 'y') {
$ht_file = "AuthType Basic\nAuthName \"Members Only\"\nAuthUserFile ".$new_folder_path.".htpasswd\nrequire valid-user";
file_put_contents($new_folder_path.'.htaccess',$ht_file);
chmod($new_folder_path.'.htpasswd',0755);
chown($folder_path.'.htpasswd',$website['system_user']);
chgrp($folder_path.'.htpasswd',$website['system_group']);
$app->log('Created file '.$new_folder_path.'.htpasswd',LOGLEVEL_DEBUG);
}
//* Remove .htaccess file
if($data['new']['active'] == 'n' && is_file($new_folder_path.'.htaccess')) {
unlink($new_folder_path.'.htaccess');
$app->log('Removed file '.$new_folder_path.'.htaccess',LOGLEVEL_DEBUG);
/**
* This function is called when a Webdav-User is inserted, updated or deleted.
*
* @author Oliver Vogel
* @param string $event_name
* @param array $data
*/
public function webdav($event_name,$data) {
global $app, $conf;
/*
* load the server configuration options
*/
$app->uses('getconf');
$web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
if (($event_name == 'webdav_user_insert') || ($event_name == 'webdav_user_update')) {
/*
* Get additional informations
*/
$sitedata = $app->db->queryOneRecord('SELECT document_root, domain, system_user, system_group FROM web_domain WHERE domain_id = ' . $data['new']['parent_domain_id']);
$documentRoot = $sitedata['document_root'];
$domain = $sitedata['domain'];
$user = $sitedata['system_user'];
$group = $sitedata['system_group'];
$webdav_user_dir = $documentRoot . '/webdav/' . $data['new']['dir'];
/* Check if this is a chrooted setup */
if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
$apache_chrooted = true;
$app->log('Info: Apache is chrooted.',LOGLEVEL_DEBUG);
} else {
$apache_chrooted = false;
}
//* We dont want to have relative paths here
if(stristr($webdav_user_dir,'..') || stristr($webdav_user_dir,'./')) {
$app->log('Folder path '.$webdav_user_dir.' contains ./ or .. '.$documentRoot,LOGLEVEL_WARN);
return false;
}
//* Check if the resulting path exists if yes, if it is inside the docroot
if(is_dir($webdav_user_dir) && substr(realpath($webdav_user_dir),0,strlen($documentRoot)) != $documentRoot) {
$app->log('Folder path '.$webdav_user_dir.' is outside of docroot '.$documentRoot,LOGLEVEL_WARN);
return false;
}
/*
* First the webdav-root - folder has to exist
*/
if(!is_dir($webdav_user_dir)) {
$app->log('Webdav User directory '.$webdav_user_dir.' does not exist. Creating it now.',LOGLEVEL_DEBUG);
exec('mkdir -p '.escapeshellcmd($webdav_user_dir));
* The webdav - Root needs the group/user as owner and the apache as read and write
$this->_exec('chown ' . $user . ':' . $group . ' ' . escapeshellcmd($documentRoot . '/webdav/'));
$this->_exec('chmod 770 ' . escapeshellcmd($documentRoot . '/webdav/'));
* The webdav folder (not the webdav-root!) needs the same (not in ONE step, because the
* pwd-files are owned by root)
$this->_exec('chown ' . $user . ':' . $group . ' ' . escapeshellcmd($webdav_user_dir.' -R'));
$this->_exec('chmod 770 ' . escapeshellcmd($webdav_user_dir.' -R'));
/*
* if the user is active, we have to write/update the password - file
* if the user is inactive, we have to inactivate the user by removing the user from the file
*/
if ($data['new']['active'] == 'y') {
$this->_writeHtDigestFile( $webdav_user_dir . '.htdigest', $data['new']['username'], $data['new']['dir'], $data['new']['password']);
}
else {
/* empty pwd removes the user! */
$this->_writeHtDigestFile( $webdav_user_dir . '.htdigest', $data['new']['username'], $data['new']['dir'], '');
/*
* Next step, patch the vhost - file
*/
$vhost_file = escapeshellcmd($web_config['vhost_conf_dir'] . '/' . $domain . '.vhost');
$this->_patchVhostWebdav($vhost_file, $documentRoot . '/webdav');
/*
* Last, restart apache
*/
if($apache_chrooted) {
$app->services->restartServiceDelayed('httpd','restart');
} else {
// request a httpd reload when all records have been processed
$app->services->restartServiceDelayed('httpd','reload');
}
}
if ($event_name == 'webdav_user_delete') {
/*
* Get additional informations
*/
$sitedata = $app->db->queryOneRecord('SELECT document_root, domain FROM web_domain WHERE domain_id = ' . $data['old']['parent_domain_id']);
$documentRoot = $sitedata['document_root'];
/*
* We dont't want to destroy any (transfer)-Data. So we do NOT delete any dir.
* So the only thing, we have to do, is to delete the user from the password-file
$this->_writeHtDigestFile( $documentRoot . '/webdav/' . $data['old']['dir'] . '.htdigest', $data['old']['username'], $data['old']['dir'], '');
/*
* Next step, patch the vhost - file
*/
$vhost_file = escapeshellcmd($web_config['vhost_conf_dir'] . '/' . $domain . '.vhost');
$this->_patchVhostWebdav($vhost_file, $documentRoot . '/webdav');
/*
* Last, restart apache
*/
if($apache_chrooted) {
$app->services->restartServiceDelayed('httpd','restart');
} else {
// request a httpd reload when all records have been processed
$app->services->restartServiceDelayed('httpd','reload');
}
}
}
/**
* This function writes the htdigest - files used by webdav and digest
* more info: see http://riceball.com/d/node/424
* @author Oliver Vogel
* @param string $filename The name of the digest-file
* @param string $username The name of the webdav-user
* @param string $authname The name of the realm
* @param string $pwd The password-hash of the user
private function _writeHtDigestFile($filename, $username, $authname, $pwdhash ) {
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
if(is_file($filename)) {
$in = fopen($filename, 'r');
$output = '';
/*
* read line by line and search for the username and authname
*/
while (preg_match("/:/", $line = fgets($in))) {
$line = rtrim($line);
$tmp = explode(':', $line);
if ($tmp[0] == $username && $tmp[1] == $authname) {
/*
* found the user. delete or change it?
*/
if ($pwdhash != '') {
$output .= $tmp[0] . ':' . $tmp[1] . ':' . $pwdhash . "\n";
}
$changed = true;
}
else {
$output .= $line . "\n";
}
fclose($in);
}
/*
* if we didn't change anything, we have to add the new user at the end of the file
*/
if (!$changed) {
$output .= $username . ':' . $authname . ':' . $pwdhash . "\n";
/*
* Now lets write the new file
*/
if(trim($output) == '') {
unlink($filename);
} else {
file_put_contents($filename, $output);
}
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
}
/**
* This function patches the vhost-file and adds all webdav - user.
* This function is written, because the creation of the vhost - file is sophisticated and
* i don't want to make it more "heavy" by also adding this code too...
* @author Oliver Vogel
* @param string $fileName The Name of the .vhost-File (path included)
* @param string $webdavRoot The root of the webdav-folder
*/
private function _patchVhostWebdav($fileName, $webdavRoot) {
$in = fopen($fileName, 'r');
$output = '';
$inWebdavSection = false;
/*
* read line by line and search for the username and authname
*/
while ($line = fgets($in)) {
/*
* is the "replace-comment" found...
*/
if (trim($line) == '# WEBDAV BEGIN') {
/*
* The begin of the webdav - section is found, so ignore all lines til the end is found
*/
$inWebdavSection = true;
$output .= " # WEBDAV BEGIN\n";
/*
* add all the webdav-dirs to the webdav-section
*/
tbrehm
committed
$files = @scandir($webdavRoot);
if(is_array($files)) {
foreach($files as $file) {
if (substr($file, strlen($file) - strlen('.htdigest')) == '.htdigest') {
/*
* found a htdigest - file, so add it to webdav
*/
$fn = substr($file, 0, strlen($file) - strlen('.htdigest'));
$output .= "\n";
// $output .= " Alias /" . $fn . ' ' . $webdavRoot . '/' . $fn . "\n";
// $output .= " <Location /" . $fn . ">\n";
$output .= " Alias /webdav/" . $fn . ' ' . $webdavRoot . '/' . $fn . "\n";
$output .= " <Location /webdav/" . $fn . ">\n";
$output .= ' BrowserMatch "MSIE" AuthDigestEnableQueryStringHack=On'."\n";
$output .= " AuthType Digest\n";
$output .= " AuthName \"" . $fn . "\"\n";
$output .= " AuthUserFile " . $webdavRoot . '/' . $file . "\n";
$output .= " Require valid-user \n";
$output .= " Options +Indexes \n";
$output .= " Order allow,deny \n";
$output .= " Allow from all \n";
$output .= " </Location> \n";
}
}
tbrehm
committed
}
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
}
/*
* is the "replace-comment-end" found...
*/
if (trim($line) == '# WEBDAV END') {
/*
* The end of the webdav - section is found, so stop ignoring
*/
$inWebdavSection = false;
}
/*
* Write the line to the output, if it is not in the section
*/
if (!$inWebdavSection) {
$output .= $line;
}
}
fclose($in);
/*
* Now lets write the new file
*/
file_put_contents($fileName, $output);
}
//* Update the awstats configuration file
private function awstats_update ($data,$web_config) {
global $app;
$awstats_conf_dir = $web_config['awstats_conf_dir'];
if(!is_dir($data['new']['document_root']."/web/stats/")) mkdir($data['new']['document_root']."/web/stats");
if(!@is_file($awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf') || ($data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain'])) {
if ( @is_file($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf') ) {
unlink($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf');
$content .= "Include \"".$awstats_conf_dir."/awstats.conf\"\n";
$content .= "LogFile=\"/var/log/ispconfig/httpd/".$data['new']['domain']."/access.log\"\n";
$content .= "SiteDomain=\"".$data['new']['domain']."\"\n";
$content .= "HostAliases=\"www.".$data['new']['domain']." localhost 127.0.0.1\"\n";
file_put_contents($awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf',$content);
$app->log('Created AWStats config file: '.$awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf',LOGLEVEL_DEBUG);
if(is_file($data['new']['document_root']."/web/stats/index.html")) unlink($data['new']['document_root']."/web/stats/index.html");
copy("/usr/local/ispconfig/server/conf/awstats_index.php.master",$data['new']['document_root']."/web/stats/index.php");
}
//* Delete the awstats configuration file
private function awstats_delete ($data,$web_config) {
global $app;
$awstats_conf_dir = $web_config['awstats_conf_dir'];
if ( @is_file($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf') ) {
unlink($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf');
$app->log('Removed AWStats config file: '.$awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf',LOGLEVEL_DEBUG);
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
function client_delete($event_name,$data) {
global $app, $conf;
$app->uses("getconf");
$web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
$client_id = intval($data['old']['client_id']);
if($client_id > 0) {
$client_dir = $web_config['website_basedir'].'/clients/client'.$client_id;
if(is_dir($client_dir) && !stristr($client_dir,'..')) {
@rmdir($client_dir);
$app->log('Removed client directory: '.$client_dir,LOGLEVEL_DEBUG);
}
$this->_exec('groupdel client'.$client_id);
$app->log('Removed group client'.$client_id,LOGLEVEL_DEBUG);
}
}
//* Wrapper for exec function for easier debugging
private function _exec($command) {
global $app;
$app->log('exec: '.$command,LOGLEVEL_DEBUG);
exec($command);
}
private function _checkTcp ($host,$port) {
$fp = @fsockopen ($host, $port, $errno, $errstr, 2);
if ($fp) {
fclose($fp);
return true;
} else {
return false;
}
}
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
public function create_relative_link($f, $t) {
// $from already exists
$from = realpath($f);
// realpath requires the traced file to exist - so, lets touch it first, then remove
@unlink($t); touch($t);
$to = realpath($t);
@unlink($t);
// Remove from the left side matching path elements from $from and $to
// and get path elements counts
$a1 = explode('/', $from); $a2 = explode('/', $to);
for ($c = 0; $a1[$c] == $a2[$c]; $c++) {
unset($a1[$c]); unset($a2[$c]);
}
$cfrom = implode('/', $a1);
// Check if a path is fully a subpath of another - no way to create symlink in the case
if (count($a1) == 0 || count($a2) == 0) return false;
// Add ($cnt_to-1) number of "../" elements to left side of $cfrom
for ($c = 0; $c < (count($a2)-1); $c++) { $cfrom = '../'.$cfrom; }
return symlink($cfrom, $to);
}
} // end class