REFACTORING: code formatting of the panel + braces on if/while/for + fixe some missing or too many Globals in functions

This commit is contained in:
Benjamin Sonntag 2015-09-25 17:42:00 +02:00
parent 3e42567048
commit d3ab589e56
19 changed files with 6838 additions and 6706 deletions

View File

@ -2,92 +2,90 @@
require_once("../class/config.php"); require_once("../class/config.php");
if (!$admin->enabled) { if (!$admin->enabled) {
__("This page is restricted to authorized staff"); __("This page is restricted to authorized staff");
exit(); exit();
} }
include_once("head.php"); include_once("head.php");
?>
<h3><?php __("Manage defaults domains type"); ?></h3>
<hr id="topbar" />
<p><?php __("If you don't know what this page is about, don't touch anything, and read AlternC documentation about domain types"); ?></p>
<p><?php __("The Type column contains a type of available VirtualHost config on The server."); ?></p>
<p><?php __("The Setting column contains the variables to be expanded in the defaults configuration. Available values are: "); ?></p>
<ul>
<li><?php __("%%DOMAIN%% : the Domain name"); ?></li>
<li><?php __("%%TARGETDOM%%: The destination domain"); ?></li>
<li><?php __("%%SUB%% : The subdomain name"); ?></li>
<li><?php __("%%DOMAINDIR%%: the domain directory on the file system"); ?></li>
</ul>
?> <br />
<h3><?php __("Manage defaults domains type"); ?></h3> <?php
<hr id="topbar" /> if (isset($error) && $error) {
<p><?php __("If you don't know what this page is about, don't touch anything, and read AlternC documentation about domain types"); ?></p> echo "<p class=\"alert alert-danger\">$error</p>";
<p><?php __("The Type column contains a type of available VirtualHost config on The server."); ?></p> }
<p><?php __("The Setting column contains the variables to be expanded in the defaults configuration. Available values are: "); ?></p>
<ul>
<li><?php __("%%DOMAIN%% : the Domain name"); ?></li>
<li><?php __("%%TARGETDOM%%: The destination domain"); ?></li>
<li><?php __("%%SUB%% : The subdomain name"); ?></li>
<li><?php __("%%DOMAINDIR%%: the domain directory on the file system"); ?></li>
</ul>
<br />
<?php
if (isset($error) && $error) {
echo "<p class=\"alert alert-danger\">$error</p>";
}
$fields = array ( $fields = array(
"domup" => array ("post", "array", ""), "domup" => array("post", "array", ""),
); );
getFields($fields); getFields($fields);
if (!empty($domup)) { if (!empty($domup)) {
if (!$dom->update_default_subdomains($domup) ) { if (!$dom->update_default_subdomains($domup)) {
$error=_("There was an error during the record."); $error = _("There was an error during the record.");
} else { } else {
$error=_("Save done."); $error = _("Save done.");
} }
} }
$tab=$dom->lst_default_subdomains(); $tab = $dom->lst_default_subdomains();
?> ?>
<form method="post" action="adm_doms_def_type.php" name="main" id="main"> <form method="post" action="adm_doms_def_type.php" name="main" id="main">
<table class="tlist"> <table class="tlist">
<tr><th>&nbsp;</th><th><?php __("Sub"); ?></th><th><?php __("Type"); ?></th><th><?php __("settings"); ?></th><th><?php __("Concerned"); ?></th><th><?php __("Activation"); ?></th></tr> <tr><th>&nbsp;</th><th><?php __("Sub"); ?></th><th><?php __("Type"); ?></th><th><?php __("settings"); ?></th><th><?php __("Concerned"); ?></th><th><?php __("Activation"); ?></th></tr>
<?php <?php for ($i = 0; $i < count($tab) + 1; $i++) { ?>
for($i=0;$i<count($tab)+1;$i++) {?> <tr class="lst">
<tr class="lst"> <td>
<td> <?php
@$val = $tab[$i];
if (isset($tab[$i])) {
echo "<input type='hidden' name='domup[$i][id]' value='" . $val['id'] . "' />";
}
?>
<div class="ina delete"><a href="dom_defdel.php?id=<?php echo $val['id']; ?>"><?php __("Delete"); ?></a></div>
</td>
<?php <td><input type='text' size="16" name='domup[<?php echo $i; ?>][sub]' value="<?php echo $val['sub']; ?>"/></td>
@$val=$tab[$i]; <?php
if (isset($tab[$i])){ $type = array("VHOST", "URL", "WEBMAIL", "");
echo "<input type='hidden' name='domup[$i][id]' value='".$val['id']."' />"; if (in_array($val['domain_type'], $type)) {
} ?>
?> <td><select name='domup[<?php echo $i; ?>][domain_type]'>
<div class="ina delete"><a href='dom_defdel.php?id=<?php echo $val['id']; ?>' type=''><?php __("Delete"); ?></a></div> <option value='VHOST' <?php if ($val['domain_type'] == 'VHOST') echo "selected=\"selected\""; ?> >VHOST</option>
</td> <option value='URL' <?php if ($val['domain_type'] == 'URL') echo "selected=\"selected\""; ?> >URL</option>
<option value='WEBMAIL' <?php if ($val['domain_type'] == 'WEBMAIL') echo "selected=\"selected\""; ?> >WEBMAIL</option>
<td><input type='text' size="16" name='domup[<?php echo $i; ?>][sub]' value="<?php echo $val['sub']; ?>"/></td> </select>
<?php $type=array("VHOST","URL","WEBMAIL",""); <?php } else { ?>
if(in_array($val['domain_type'],$type)){?> <td><input type="text" style="width:100px" name="domup[<?php echo $i; ?>][domain_type]" value="<?php echo $val['domain_type'] ?>" ></td>
<td><select name='domup[<?php echo $i; ?>][domain_type]'> <?php } ?>
<option value='VHOST' <?php if($val['domain_type']=='VHOST') echo "selected=\"selected\""; ?> >VHOST</option> <td><input type ='text' name='domup[<?php echo $i; ?>][domain_type_parameter]' value='<?php echo $val['domain_type_parameter'] ?>' /></td>
<option value='URL' <?php if($val['domain_type']=='URL') echo "selected=\"selected\""; ?> >URL</option> <td><select name='domup[<?php echo $i; ?>][concerned]'>
<option value='WEBMAIL' <?php if($val['domain_type']=='WEBMAIL') echo "selected=\"selected\""; ?> >WEBMAIL</option> <option value='MAIN' <?php if ($val['concerned'] == 'MAIN') echo "selected=\"selected\""; ?> >MAIN</option>
</select> <option value='SLAVE' <?php if ($val['concerned'] == 'SLAVE') echo "selected=\"selected\""; ?> >SLAVE</option>
<?php }else{?> <option value='BOTH' <?php if ($val['concerned'] == 'BOTH') echo "selected=\"selected\""; ?> >BOTH</option>
<td><input type ='text' width="100px" style="width:100px" name='domup[<?php echo $i; ?>][domain_type]' value='<?php echo $val['domain_type']?>' ></td> </select>
<? }?> </td>
</td> <td><input type="checkbox" name="domup[<?php echo $i; ?>][enabled]" value="1" <?php if ($val['enabled'] == 1) echo "checked=\"checked\""; ?> /></td>
<td><input type ='text' name='domup[<?php echo $i; ?>][domain_type_parameter]' value='<?php echo $val['domain_type_parameter']?>' /></td> </tr>
<td><select name='domup[<?php echo $i; ?>][concerned]'> <?php
<option value='MAIN' <?php if($val['concerned']=='MAIN') echo "selected=\"selected\""; ?> >MAIN</option> }
<option value='SLAVE' <?php if($val['concerned']=='SLAVE') echo "selected=\"selected\""; ?> >SLAVE</option> ?>
<option value='BOTH' <?php if($val['concerned']=='BOTH') echo "selected=\"selected\""; ?> >BOTH</option> <tr>
</select> <td colspan='6'><p><input type="submit" class="inb" name="submit" value="<?php __("Save"); ?>" /></p></td>
</td> </tr>
<td><input type="checkbox" name="domup[<?php echo $i; ?>][enabled]" value="1" <?php if ($val['enabled']==1) echo "checked=\"checked\""; ?> /></td> </table>
</tr>
<?php
}
?>
<tr>
<td colspan='6'><p><input type="submit" class="inb" name="submit" value="<?php __("Save"); ?>" /></p></td>
</tr>
</table>
</form> </form>
<?php <?php include_once("foot.php");
include_once("foot.php"); ?>

View File

@ -1,414 +1,423 @@
<?php <?php
/** /**
$Id: m_authip.php $Id: m_authip.php
---------------------------------------------------------------------- ----------------------------------------------------------------------
LICENSE LICENSE
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License (GPL) modify it under the terms of the GNU General Public License (GPL)
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
To read the license please visit http://www.gnu.org/copyleft/gpl.html
----------------------------------------------------------------------
Original Author of file: Fufroma
----------------------------------------------------------------------
*/
To read the license please visit http://www.gnu.org/copyleft/gpl.html
----------------------------------------------------------------------
Original Author of file: Fufroma
----------------------------------------------------------------------
*/
/** /**
* Classe de gestion des IP authorisée * Classe de gestion des IP authorisée
* @group alternc * @group alternc
**/ * */
class m_authip { class m_authip {
/** /**
* Retourne la liste des ip whitelist * Retourne la liste des ip whitelist
* *
* @global m_mem $mem * @global m_mem $mem
* @return array retourne un tableau indexé des ip de l'utilisateur * @return array retourne un tableau indexé des ip de l'utilisateur
*/ */
function list_ip_whitelist() { function list_ip_whitelist() {
global $mem; global $mem;
if (!$mem->checkRight()) return false; if (!$mem->checkRight()) {
return $this->list_ip(true); return false;
} }
return $this->list_ip(true);
/**
*
* @return array
*/
function hook_menu() {
$obj = array(
'title' => _("FTP Access Security"),
'ico' => 'images/ip.png',
'link' => 'ip_main.php',
'pos' => 120,
) ;
return $obj;
}
/**
* Retourne la liste des ip spécifiées par cet utilisateur
*
*
* @global m_mysql $db
* @global m_mem $mem
* @global int $cuid
* @param boolean $whitelist
* @return array Retourne un tableau indexé des ip de l'utilisateur
*/
function list_ip($whitelist=false) {
global $db, $mem;
if ($whitelist && $mem->checkRight() ) {
$cuid=0;
} else {
global $cuid;
} }
$r = array(); /**
$db->query("SELECT * FROM authorised_ip WHERE uid='$cuid' order by ip,subnet;"); *
while ($db->next_record()) { * @return array
$r[$db->f('id')]=$db->Record; */
if ( (checkip($db->f('ip')) && $db->f('subnet') == 32) || function hook_menu() {
(checkipv6($db->f('ip')) && $db->f('subnet') == 128) ) { $obj = array(
$r[$db->f('id')]['ip_human']=$db->f('ip'); 'title' => _("FTP Access Security"),
} else { 'ico' => 'images/ip.png',
$r[$db->f('id')]['ip_human']=$db->f('ip')."/".$db->f('subnet'); 'link' => 'ip_main.php',
} 'pos' => 120,
);
return $obj;
} }
return $r;
}
/**
* Retourne la liste des ip spécifiées par cet utilisateur
*
*
* @global m_mysql $db
* @global m_mem $mem
* @global int $cuid
* @param boolean $whitelist
* @return array Retourne un tableau indexé des ip de l'utilisateur
*/
function list_ip($whitelist = false) {
global $db, $mem;
if ($whitelist && $mem->checkRight()) {
$cuid = 0;
} else {
global $cuid;
}
/** $r = array();
* Supprime une IP des IP de l'utilisateur $db->query("SELECT * FROM authorised_ip WHERE uid='$cuid' order by ip,subnet;");
* et supprime les droits attaché en cascade while ($db->next_record()) {
* $r[$db->f('id')] = $db->Record;
* @param integer $id if ((checkip($db->f('ip')) && $db->f('subnet') == 32) ||
* @return boolean (checkipv6($db->f('ip')) && $db->f('subnet') == 128)) {
* $r[$db->f('id')]['ip_human'] = $db->f('ip');
* @global m_mysql $db } else {
* @global int $cuid $r[$db->f('id')]['ip_human'] = $db->f('ip') . "/" . $db->f('subnet');
* @param int $id id de la ligne à supprimer }
* @return boolean Retourne FALSE si erreur, sinon TRUE }
*/ return $r;
function ip_delete($id) {
global $db, $cuid;
$id=intval($id);
$db->query("SELECT id FROM authorised_ip_affected where authorised_ip_id ='$id';");
while ($db->next_record()) {
$this->ip_affected_delete($db->f('id'));
} }
if (! $db->query("delete from authorised_ip where id='$id' and ( uid='$cuid' or uid=0) limit 1;") ) {
echo "query failed: ".$db->Error; /**
return false; * Supprime une IP des IP de l'utilisateur
* et supprime les droits attaché en cascade
*
* @param integer $id
* @return boolean
*
* @global m_mysql $db
* @global int $cuid
* @param int $id id de la ligne à supprimer
* @return boolean Retourne FALSE si erreur, sinon TRUE
*/
function ip_delete($id) {
global $db, $cuid;
$id = intval($id);
$db->query("SELECT id FROM authorised_ip_affected where authorised_ip_id ='$id';");
while ($db->next_record()) {
$this->ip_affected_delete($db->f('id'));
}
if (!$db->query("delete from authorised_ip where id='$id' and ( uid='$cuid' or uid=0) limit 1;")) {
echo "query failed: " . $db->Error;
return false;
}
return true;
} }
return true;
}
/** /**
* Liste les IP et subnet authorisés * Liste les IP et subnet authorisés
* pour une classe donnée * pour une classe donnée
* *
* @global m_mysql $db * @global m_mysql $db
* @global int $cuid * @global int $cuid
* @param string $s Classe concernée * @param string $s Classe concernée
* @return array * @return array
*/ */
function get_allowed($s) { function get_allowed($s) {
global $db, $cuid; global $db, $cuid;
if (! $db->query("select ai.ip, ai.subnet, ai.infos, aia.parameters from authorised_ip ai, authorised_ip_affected aia where aia.protocol='$s' and aia.authorised_ip_id = ai.id and ai.uid='$cuid';") ) { if (!$db->query("select ai.ip, ai.subnet, ai.infos, aia.parameters from authorised_ip ai, authorised_ip_affected aia where aia.protocol='$s' and aia.authorised_ip_id = ai.id and ai.uid='$cuid';")) {
echo "query failed: ".$db->Error; echo "query failed: " . $db->Error;
return false; return false;
}
$r = Array();
while ($db->next_record()) {
$r[] = Array("ip" => $db->f("ip"), "subnet" => $db->f("subnet"), "infos" => $db->f("infos"), "parameters" => $db->f("parameters"));
}
return $r;
} }
$r=Array();
while ($db->next_record()) {
$r[]=Array("ip"=>$db->f("ip"), "subnet"=>$db->f("subnet"), "infos"=>$db->f("infos"), "parameters"=>$db->f("parameters"));
}
return $r;
}
/** /**
* *
* @global m_mysql $db * @global m_mysql $db
* @param string $ip * @param string $ip
* @return boolean * @return boolean
*/ */
function is_wl($ip) { function is_wl($ip) {
global $db; global $db;
if (! $db->query("select ai.ip, ai.subnet from authorised_ip ai where ai.uid='0';") ) { if (!$db->query("select ai.ip, ai.subnet from authorised_ip ai where ai.uid='0';")) {
echo "query failed: ".$db->Error; echo "query failed: " . $db->Error;
return false; return false;
} }
while ($db->next_record()) { while ($db->next_record()) {
if ( $this->is_in_subnet($ip, $db->f('ip'), $db->f('subnet') ) ) return true; if ($this->is_in_subnet($ip, $db->f('ip'), $db->f('subnet')))
} return true;
return false; }
}
/**
* Retourne si l'ip appartient au subnet.
*
* @param string $o
* @param string $ip
* @param string $sub
* @return boolean
*/
function is_in_subnet($o, $ip, $sub) {
$o = inet_pton($o);
$ip = inet_pton($ip);
$sub = pow(2, $sub);
if ( $o >= $ip && $o <= ($ip+$sub) ) return true;
return false;
}
/**
* Sauvegarde une IP dans les IP TOUJOURS authorisée
*
* @global m_mem $mem
*/
function ip_save_whitelist($id, $ipsub, $infos) {
global $mem;
if (!$mem->checkRight()) return false;
return $this->ip_save($id, $ipsub, $infos, 0);
}
/**
* Sauvegarde une IP dans les IP authorisée
*
* @global m_mysql $db
* @global m_mem $mem
* @global int $cuid
* @param int $id id de la ligne à modifier. Si vide ou
* égal à 0, alors c'est une insertion
* @param string $ipsub IP (v4 ou v6), potentiellement avec un subnet ( /24)
* @param string $infos Commentaire pour l'utilisateur
* @param int $uid Si $uid=0 et qu'on est super-admin, insertion avec uid=0
* ce qui correspond a une ip toujours authorisée
* @return boolean Retourne FALSE si erreur, sinon TRUE
*
*/
function ip_save($id, $ipsub, $infos, $uid=null) {
global $db, $mem;
// If we ask for uid=0, we have to check to be super-user
// else, juste use global cuid;
if ($uid === 0 && $mem->checkRight() ) {
$cuid=0;
} else {
global $cuid;
}
$id=intval($id);
$infos=mysql_real_escape_string($infos);
// Extract subnet from ipsub
$tmp=explode('/',$ipsub);
$ip=$tmp[0];
// Error if $ip not an IP
if ( ! checkip($ip) && ! checkipv6($ip) ) {
echo "Failed : not an IP address";
return false; return false;
} }
// Check the subnet, if not defined, give a /32 or a /128 /**
if (isset($tmp[1])) { * Retourne si l'ip appartient au subnet.
$subnet=intval($tmp[1]); *
} else { * @param string $o
if ( checkip($ip) ) $subnet=32; * @param string $ip
else $subnet=128; * @param string $sub
} * @return boolean
*/
function is_in_subnet($o, $ip, $sub) {
$o = inet_pton($o);
$ip = inet_pton($ip);
$sub = pow(2, $sub);
// An IPv4 can't have subnet > 32 if ($o >= $ip && $o <= ($ip + $sub)) {
if (checkip($ip) && $subnet > 32 ) $subnet=32; return true;
}
if ($id) { // Update
$list_affected = $this->list_affected($id);
foreach($list_affected as $k => $v) {
$this->call_hooks("authip_on_delete", $k );
}
if (! $db->query("update authorised_ip set ip='$ip', subnet='$subnet', infos='$infos' where id='$id' and uid='$cuid' ;") ) {
echo "query failed: ".$db->Error;
return false; return false;
}
foreach($list_affected as $k => $v) {
$this->call_hooks("authip_on_create", $k );
}
} else { // Insert
if (! $db->query("insert into authorised_ip (uid, ip, subnet, infos) values ('$cuid', '$ip', '$subnet', '$infos' );") ) {
echo "query failed: ".$db->Error;
return false;
}
}
return true;
}
/**
* Fonction appelée par Alternc lors de la suppression d'un utilisateur
*
* @global int $cuid
* @global m_mysql $db
* @return boolean Retourne TRUE
*/
function alternc_del_member() {
global $cuid,$db;
$db->query("SELECT id FROM authorised_ip WHERE uid ='$cuid';");
while ($db->next_record()) {
$this->ip_delete($db->f('id'));
}
return true;
}
/**
* Analyse les classes et récupéres les informations
* des classes voulant de la restriction IP
*
* @return array Retourne un tableau compliqué
*/
function get_auth_class() {
global $hooks;
$authclass = $hooks->invoke('authip_class');
// Je rajoute la class DANS l'objet parce que
// ca m'interesse
foreach ($authclass as $k => $v) {
$authclass[$k]['class']=$k;
} }
return $authclass; /**
} * Sauvegarde une IP dans les IP TOUJOURS authorisée
*
/** * @global m_mem $mem
* Enregistre ou modifie une affectation ip<=>ressource */
* Nota : lance des hooks sur la classe correspondante pour function ip_save_whitelist($id, $ipsub, $infos) {
* informer de l'édition/création global $mem;
* if (!$mem->checkRight()) {
* @global m_mysql $db return false;
* @param int $authorised_ip_id id de l'ip affecté }
* @param string $protocol nom du protocole (définie dans la classe correspondante) return $this->ip_save($id, $ipsub, $infos, 0);
* @param string $parameters information propre au protocole
* @param int $id $id présent si c'est une édition
* @return boolean Retourne FALSE si erreur, sinon TRUE
*/
function ip_affected_save($authorised_ip_id, $protocol, $parameters, $id=null) {
global $db;
$authorised_ip_id=intval($authorised_ip_id);
$protocol=mysql_real_escape_string($protocol);
$parameters=mysql_real_escape_string($parameters);
if ($id) {
$id=intval($id);
$this->call_hooks("authip_on_delete", $id );
if (! $db->query("update authorised_ip_affected set authorised_ip_id='$authorised_ip_id', protocol='$protocol', parameters='$parameters' where id ='$id' limit 1;") ) {
echo "query failed: ".$db->Error;
return false;
}
$this->call_hooks("authip_on_create", $id );
} else {
if (! $db->query("insert into authorised_ip_affected (authorised_ip_id, protocol, parameters) values ('$authorised_ip_id', '$protocol', '$parameters');") ) {
echo "query failed: ".$db->Error;
return false;
}
$this->call_hooks("authip_on_create", mysql_insert_id() );
}
return true;
}
/**
* Supprime une affectation ip<=>ressource
* Nota : lance des hooks dans la classe correspondante
* pour informer de la suppression
*
* @global m_mysql $db
* @param int $id id de la ligne à supprimer
* @return boolean Retourne FALSE si erreur, sinon TRUE
*/
function ip_affected_delete($id) {
global $db;
$id=intval($id);
// Call hooks
$this->call_hooks("authip_on_delete", $id );
if (! $db->query("delete from authorised_ip_affected where id='$id' limit 1;") ) {
echo "query failed: ".$db->Error;
return false;
}
return true;
}
/**
* Appel les hooks demandé avec en parametres les
* affectationt ip<=>ressource dont l'id est en parametre
*
* @global m_hooks $hooks
* @global m_err $err
* @param string $function Nom de la fonction a rechercher et appeller dans les classes
* @param integer $affectation_id Id de l'affectation correspondante
* @return boolean Retourne TRUE
*/
function call_hooks($function, $affectation_id) {
global $hooks,$err;
// On récure l'objet dont on parle
$d = $this->list_affected();
if (! isset($d[$affectation_id] )) {
$err->raise('authip', _("Object not available"));
return false;
} }
$affectation = $d[$affectation_id]; /**
* Sauvegarde une IP dans les IP authorisée
*
* @global m_mysql $db
* @global m_mem $mem
* @global int $cuid
* @param int $id id de la ligne à modifier. Si vide ou
* égal à 0, alors c'est une insertion
* @param string $ipsub IP (v4 ou v6), potentiellement avec un subnet ( /24)
* @param string $infos Commentaire pour l'utilisateur
* @param int $uid Si $uid=0 et qu'on est super-admin, insertion avec uid=0
* ce qui correspond a une ip toujours authorisée
* @return boolean Retourne FALSE si erreur, sinon TRUE
*
*/
function ip_save($id, $ipsub, $infos, $uid = null) {
global $db, $mem;
// On en déduis la classe qui le concerne // If we ask for uid=0, we have to check to be super-user
$e = $this->get_auth_class(); // else, juste use global cuid;
if (! isset($e[$affectation['protocol']])) { if ($uid === 0 && $mem->checkRight()) {
$err->raise('authip', sprintf(_("Can't identified class for the protocole %s"), $affectation['protocol'])); $cuid = 0;
return false; } else {
global $cuid;
}
$id = intval($id);
$infos = mysql_real_escape_string($infos);
// Extract subnet from ipsub
$tmp = explode('/', $ipsub);
$ip = $tmp[0];
// Error if $ip not an IP
if (!checkip($ip) && !checkipv6($ip)) {
echo "Failed : not an IP address";
return false;
}
// Check the subnet, if not defined, give a /32 or a /128
if (isset($tmp[1])) {
$subnet = intval($tmp[1]);
} else {
if (checkip($ip)) {
$subnet = 32;
} else {
$subnet = 128;
}
}
// An IPv4 can't have subnet > 32
if (checkip($ip) && $subnet > 32) {
$subnet = 32;
}
if ($id) { // Update
$list_affected = $this->list_affected($id);
foreach ($list_affected as $k => $v) {
$this->call_hooks("authip_on_delete", $k);
}
if (!$db->query("update authorised_ip set ip='$ip', subnet='$subnet', infos='$infos' where id='$id' and uid='$cuid' ;")) {
echo "query failed: " . $db->Error;
return false;
}
foreach ($list_affected as $k => $v) {
$this->call_hooks("authip_on_create", $k);
}
} else { // Insert
if (!$db->query("insert into authorised_ip (uid, ip, subnet, infos) values ('$cuid', '$ip', '$subnet', '$infos' );")) {
echo "query failed: " . $db->Error;
return false;
}
}
return true;
} }
$c = $e[$affectation['protocol']]['class'];
// On appelle le hooks de cette classe /**
$hooks->invoke($function, Array($affectation), Array($c) ); * Fonction appelée par Alternc lors de la suppression d'un utilisateur
*
return true; * @global int $cuid
} * @global m_mysql $db
* @return boolean Retourne TRUE
/** */
* Liste les affectation ip<=>ressource d'un utilisateur function alternc_del_member() {
* global $cuid, $db;
* @global m_mysql $db $db->query("SELECT id FROM authorised_ip WHERE uid ='$cuid';");
* @global int $cuid while ($db->next_record()) {
* @param int $ip_id $this->ip_delete($db->f('id'));
* @return array Retourne un tableau de valeurs }
*/ return true;
function list_affected($ip_id=null) {
global $db, $cuid;
$r = array();
if ( is_null($ip_id) ) {
$db->query("select aia.* from authorised_ip_affected aia, authorised_ip ai where ai.uid='$cuid' and aia.authorised_ip_id = ai.id order by protocol, parameters;");
} else {
$db->query("select aia.* from authorised_ip_affected aia, authorised_ip ai where ai.uid='$cuid' and aia.authorised_ip_id = '".intval($ip_id)."' order by protocol, parameters;");
} }
while ($db->next_record()) {
$r[$db->f('id')]=$db->Record; /**
* Analyse les classes et récupéres les informations
* des classes voulant de la restriction IP
*
* @return array Retourne un tableau compliqué
*/
function get_auth_class() {
global $hooks;
$authclass = $hooks->invoke('authip_class');
// Je rajoute la class DANS l'objet parce que
// ca m'interesse
foreach ($authclass as $k => $v) {
$authclass[$k]['class'] = $k;
}
return $authclass;
} }
return $r;
}
}; /* Classe m_authip */ /**
* Enregistre ou modifie une affectation ip<=>ressource
* Nota : lance des hooks sur la classe correspondante pour
* informer de l'édition/création
*
* @global m_mysql $db
* @param int $authorised_ip_id id de l'ip affecté
* @param string $protocol nom du protocole (définie dans la classe correspondante)
* @param string $parameters information propre au protocole
* @param int $id $id présent si c'est une édition
* @return boolean Retourne FALSE si erreur, sinon TRUE
*/
function ip_affected_save($authorised_ip_id, $protocol, $parameters, $id = null) {
global $db;
$authorised_ip_id = intval($authorised_ip_id);
$protocol = mysql_real_escape_string($protocol);
$parameters = mysql_real_escape_string($parameters);
?> if ($id) {
$id = intval($id);
$this->call_hooks("authip_on_delete", $id);
if (!$db->query("update authorised_ip_affected set authorised_ip_id='$authorised_ip_id', protocol='$protocol', parameters='$parameters' where id ='$id' limit 1;")) {
echo "query failed: " . $db->Error;
return false;
}
$this->call_hooks("authip_on_create", $id);
} else {
if (!$db->query("insert into authorised_ip_affected (authorised_ip_id, protocol, parameters) values ('$authorised_ip_id', '$protocol', '$parameters');")) {
echo "query failed: " . $db->Error;
return false;
}
$this->call_hooks("authip_on_create", mysql_insert_id());
}
return true;
}
/**
* Supprime une affectation ip<=>ressource
* Nota : lance des hooks dans la classe correspondante
* pour informer de la suppression
*
* @global m_mysql $db
* @param int $id id de la ligne à supprimer
* @return boolean Retourne FALSE si erreur, sinon TRUE
*/
function ip_affected_delete($id) {
global $db;
$id = intval($id);
// Call hooks
$this->call_hooks("authip_on_delete", $id);
if (!$db->query("delete from authorised_ip_affected where id='$id' limit 1;")) {
echo "query failed: " . $db->Error;
return false;
}
return true;
}
/**
* Appel les hooks demandé avec en parametres les
* affectationt ip<=>ressource dont l'id est en parametre
*
* @global m_hooks $hooks
* @global m_err $err
* @param string $function Nom de la fonction a rechercher et appeller dans les classes
* @param integer $affectation_id Id de l'affectation correspondante
* @return boolean Retourne TRUE
*/
function call_hooks($function, $affectation_id) {
global $hooks, $err;
// On récure l'objet dont on parle
$d = $this->list_affected();
if (!isset($d[$affectation_id])) {
$err->raise('authip', _("Object not available"));
return false;
}
$affectation = $d[$affectation_id];
// On en déduis la classe qui le concerne
$e = $this->get_auth_class();
if (!isset($e[$affectation['protocol']])) {
$err->raise('authip', sprintf(_("Can't identified class for the protocole %s"), $affectation['protocol']));
return false;
}
$c = $e[$affectation['protocol']]['class'];
// On appelle le hooks de cette classe
$hooks->invoke($function, Array($affectation), Array($c));
return true;
}
/**
* Liste les affectation ip<=>ressource d'un utilisateur
*
* @global m_mysql $db
* @global int $cuid
* @param int $ip_id
* @return array Retourne un tableau de valeurs
*/
function list_affected($ip_id = null) {
global $db, $cuid;
$r = array();
if (is_null($ip_id)) {
$db->query("select aia.* from authorised_ip_affected aia, authorised_ip ai where ai.uid='$cuid' and aia.authorised_ip_id = ai.id order by protocol, parameters;");
} else {
$db->query("select aia.* from authorised_ip_affected aia, authorised_ip ai where ai.uid='$cuid' and aia.authorised_ip_id = '" . intval($ip_id) . "' order by protocol, parameters;");
}
while ($db->next_record()) {
$r[$db->f('id')] = $db->Record;
}
return $r;
}
}
/* Classe m_authip */

File diff suppressed because it is too large Load Diff

View File

@ -1,364 +1,404 @@
<?php <?php
/* /*
---------------------------------------------------------------------- ----------------------------------------------------------------------
AlternC - Web Hosting System AlternC - Web Hosting System
Copyright (C) 2000-2012 by the AlternC Development Team. Copyright (C) 2000-2012 by the AlternC Development Team.
https://alternc.org/ https://alternc.org/
---------------------------------------------------------------------- ----------------------------------------------------------------------
LICENSE LICENSE
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License (GPL) modify it under the terms of the GNU General Public License (GPL)
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
To read the license please visit http://www.gnu.org/copyleft/gpl.html To read the license please visit http://www.gnu.org/copyleft/gpl.html
---------------------------------------------------------------------- ----------------------------------------------------------------------
Purpose of file: Manage hook system. Purpose of file: Manage hook system.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** /**
* This class manage web-cron tasks * This class manage web-cron tasks
*/ */
class m_cron { class m_cron {
const MAX_SOCKETS=8; const MAX_SOCKETS = 8;
const DEFAULT_CAFILE="/etc/ssl/certs/ca-certificates.crt"; const DEFAULT_CAFILE = "/etc/ssl/certs/ca-certificates.crt";
/*---------------------------------------------------------------------------*/ /* --------------------------------------------------------------------------- */
/** Constructor
*/
function m_cron() {
}
function schedule() { /** Constructor
return Array( */
Array('unit'=>1440, 'name'=>_("Daily")), function m_cron() {
Array('unit'=>60, 'name'=>_("Hour")),
Array('unit'=>30, 'name'=>_("Half Hour")),
);
}
/*---------------------------------------------------------------------------*/
/** List the crontab for the current user.
* @return array an hash for each crontab.
*/
function lst_cron() {
global $cuid,$db,$err;
$err->log("cron","lst_cron");
$db->query("SELECT * FROM cron WHERE uid = $cuid ORDER BY url;");
$r=Array();
while ($db->next_record()) {
$tmp=Array();
$tmp['id']=$db->f('id');
$tmp['url']=urldecode($db->f('url'));
$tmp['user']=urldecode($db->f('user'));
$tmp['password']=urldecode($db->f('password'));
$tmp['schedule']=$db->f('schedule');
$tmp['email']=urldecode($db->f('email'));
$tmp['next_execution']=$db->f('next_execution');
$r[]=$tmp;
}
return $r;
}
function hook_menu() {
$obj = array(
'title' => _("Scheduled tasks"),
'ico' => 'images/schedule.png',
'link' => 'cron.php',
'pos' => 90,
) ;
return $obj;
}
/*---------------------------------------------------------------------------*/
/** update the crontab
* @param $arr array the crontab information, including its ID
* @return boolean TRUE if the crontab has been edited
*/
function update($arr) {
$ok=true;
foreach ($arr as $a) {
if (! isset($a['id'])) $a['id']=null;
if (empty($a['url']) && is_null($a['id'])) continue;
if (! $this->_update_one($a['url'], $a['user'], $a['password'], $a['email'], $a['schedule'], $a['id']) ) {
$ok=false;
}
}
return $ok;
}
/*---------------------------------------------------------------------------*/
/** delete a crontab
* @param $id the id of the crontab to delete
* @return boolean TRUE if the crontab has been deleted
*/
function delete_one($id) {
global $db,$err,$cuid;
$err->log("cron","delete_one");
return $db->query("DELETE FROM cron WHERE id=".intval($id)." AND uid=$cuid LIMIT 1;");
}
/*---------------------------------------------------------------------------*/
/** update a crontab,
* @return boolean TRUE if the crontab has been edited
*/
private function _update_one($url, $user, $password, $email, $schedule, $id=null) {
global $db,$err,$quota,$cuid;
$err->log("cron","update_one");
if (empty($url) && !is_null($id)) {
return $this->delete_one($id);
} }
function schedule() {
if(filter_var($url,FILTER_VALIDATE_URL)===false){ return Array(
$err->raise("cron",_("URL not valid")); Array('unit' => 1440, 'name' => _("Daily")),
return false; Array('unit' => 60, 'name' => _("Hour")),
Array('unit' => 30, 'name' => _("Half Hour")),
);
} }
$url=urlencode($url);
$user=urlencode($user); /* --------------------------------------------------------------------------- */
if (empty($user)) $password='';
$password=urlencode($password); /** List the crontab for the current user.
* @return array an hash for each crontab.
//@todo remove checkmail cf functions.php */
if (!empty($email) && ! checkmail($email) == 0 ){ function lst_cron() {
$err->raise("cron",_("Email address is not valid")); global $cuid, $db, $err;
return false; $err->log("cron", "lst_cron");
$db->query("SELECT * FROM cron WHERE uid = $cuid ORDER BY url;");
$r = Array();
while ($db->next_record()) {
$tmp = Array();
$tmp['id'] = $db->f('id');
$tmp['url'] = urldecode($db->f('url'));
$tmp['user'] = urldecode($db->f('user'));
$tmp['password'] = urldecode($db->f('password'));
$tmp['schedule'] = $db->f('schedule');
$tmp['email'] = urldecode($db->f('email'));
$tmp['next_execution'] = $db->f('next_execution');
$r[] = $tmp;
}
return $r;
} }
$email=urlencode($email);
if (! $this->valid_schedule($schedule)) return false;
if (is_null($id)) { // if a new insert, quotacheck function hook_menu() {
$q = $quota->getquota("cron"); $obj = array(
if ( $q["u"] >= $q["t"] ) { 'title' => _("Scheduled tasks"),
$err->raise("cron",_("You quota of cron entries is over. You cannot create more cron entries")); 'ico' => 'images/schedule.png',
return false; 'link' => 'cron.php',
} 'pos' => 90,
} else { // if not a new insert, check the $cuid );
$db->query("SELECT uid FROM cron WHERE id = $id;");
if (! $db->next_record()) { return $obj;
return "false";
} // return false if pb
if ( $db->f('uid') != $cuid ) {
$err->raise("cron",_("Identity problem"));
return false;
}
} }
$query = "REPLACE INTO cron (id, uid, url, user, password, schedule, email) VALUES ('$id', '$cuid', '$url', '$user', '$password', '$schedule', '$email') ;";
return $db->query("$query");
}
/* --------------------------------------------------------------------------- */
/*---------------------------------------------------------------------------*/ /** update the crontab
/** validate a crontab schedule * @param $arr array the crontab information, including its ID
* @param $s array schedule paramters * @return boolean TRUE if the crontab has been edited
* @return boolean TRUE if the schedule is valid */
*/ function update($arr) {
function valid_schedule($s) { $ok = true;
$s2 = intval($s); foreach ($arr as $a) {
if ($s2 != $s) return false; if (!isset($a['id'])) {
$r=false; $a['id'] = null;
foreach ($this->schedule() as $cs ) { }
if ($cs['unit'] == $s) return true; if (empty($a['url']) && is_null($a['id'])) {
continue;
}
if (!$this->_update_one($a['url'], $a['user'], $a['password'], $a['email'], $a['schedule'], $a['id'])) {
$ok = false;
}
}
return $ok;
} }
return $r;
}
/*---------------------------------------------------------------------------*/ /* --------------------------------------------------------------------------- */
/** hook for quota computation
*/ /** delete a crontab
function hook_quota_get() { * @param $id the id of the crontab to delete
global $cuid,$db,$err; * @return boolean TRUE if the crontab has been deleted
$err->log("cron","alternc_get_quota"); */
$q=Array("name"=>"cron", "description"=>_("Scheduled tasks"), "used"=>0); function delete_one($id) {
$db->query("select count(*) as cnt from cron where uid = $cuid;"); global $db, $err, $cuid;
if ($db->next_record()) { $err->log("cron", "delete_one");
$q['used']=$db->f('cnt'); return $db->query("DELETE FROM cron WHERE id=" . intval($id) . " AND uid=$cuid LIMIT 1;");
} }
return $q;
}
/*---------------------------------------------------------------------------*/ /* --------------------------------------------------------------------------- */
/**
* Execute the required crontab of AlternC users
* this function EXIT at the end.
*/
function execute_cron() {
global $db;
if (!isset($GLOBALS["DEBUG"])) $GLOBALS["DEBUG"]=false; /** update a crontab,
$db->query("SELECT id, url, email, schedule, user, password FROM cron WHERE next_execution <= NOW();"); * @return boolean TRUE if the crontab has been edited
$urllist=array(); */
private function _update_one($url, $user, $password, $email, $schedule, $id = null) {
while ($db->next_record()) { global $db, $err, $quota, $cuid;
$db->Record["url"]=urldecode($db->Record["url"]); $db->Record["user"]=urldecode($db->Record["user"]); $err->log("cron", "update_one");
$db->Record["email"]=urldecode($db->Record["email"]); $db->Record["password"]=urldecode($db->Record["password"]);
// we support only http or https schemes: if (empty($url) && !is_null($id)) {
if (substr($db->Record["url"],0,7)=="http://" || substr($db->Record["url"],0,8)=="https://") { return $this->delete_one($id);
$u=array( }
"url" => $db->Record["url"],
"id" => $db->Record["id"], "email" =>$db->Record["email"],
); if (filter_var($url, FILTER_VALIDATE_URL) === false) {
$err->raise("cron", _("URL not valid"));
if ($db->Record["user"] && $db->Record["password"]) { return false;
$u["login"]=$db->Record["user"]; }
$u["password"]=$db->Record["password"]; $url = urlencode($url);
} $user = urlencode($user);
if ($GLOBALS["DEBUG"]) echo "Will run cron :\n".print_r($u,true)."\n"; if (empty($user)) {
$urllist[]=$u; $password = '';
} }
$password = urlencode($password);
if (empty($urllist)) { // nothing to do :
exit(0); //@todo remove checkmail cf functions.php
} if (!empty($email) && !checkmail($email) == 0) {
$err->raise("cron", _("Email address is not valid"));
// cron_callback($url, $content, $curlobj) will be called at the end of each http call. return false;
$this->rolling_curl($urllist, array("m_cron","cron_callback")); }
$email = urlencode($email);
if (!$this->valid_schedule($schedule)) {
return false;
}
if (is_null($id)) { // if a new insert, quotacheck
$q = $quota->getquota("cron");
if ($q["u"] >= $q["t"]) {
$err->raise("cron", _("You quota of cron entries is over. You cannot create more cron entries"));
return false;
}
} else { // if not a new insert, check the $cuid
$db->query("SELECT uid FROM cron WHERE id = $id;");
if (!$db->next_record()) {
return "false";
} // return false if pb
if ($db->f('uid') != $cuid) {
$err->raise("cron", _("Identity problem"));
return false;
}
}
$query = "REPLACE INTO cron (id, uid, url, user, password, schedule, email) VALUES ('$id', '$cuid', '$url', '$user', '$password', '$schedule', '$email') ;";
return $db->query("$query");
} }
}
/* --------------------------------------------------------------------------- */
/*---------------------------------------------------------------------------*/
/**
* Callback function called by rolling_curl when a cron resulr has been received
* schedule it for next run and send the mail if needed
*/
function cron_callback($url,$content,$curl) {
global $db,$L_FQDN;
if (empty($url["id"])) return; // not normal...
$id=intval($url["id"]);
if ($curl["http_code"]==200) { /** validate a crontab schedule
$ok=true; * @param $s array schedule paramters
} else { * @return boolean TRUE if the schedule is valid
$ok=false; */
function valid_schedule($s) {
$s2 = intval($s);
if ($s2 != $s) {
return false;
}
$r = false;
foreach ($this->schedule() as $cs) {
if ($cs['unit'] == $s) {
return true;
}
}
return $r;
} }
if (isset($url["email"]) && $url["email"] && $content) {
if (!mail($url["email"],"AlternC Cron #$id - Report ".date("r"),"Please find below the stdout content produced by your cron task.\n------------------------------------------------------------\n\n".$content,"From: postmaster@$L_FQDN")) { /* --------------------------------------------------------------------------- */
echo "Error sending mail for cron #$id to address '".$url["email"]."'\n";
} /** hook for quota computation
*/
function hook_quota_get() {
global $cuid, $db, $err;
$err->log("cron", "alternc_get_quota");
$q = Array("name" => "cron", "description" => _("Scheduled tasks"), "used" => 0);
$db->query("select count(*) as cnt from cron where uid = $cuid;");
if ($db->next_record()) {
$q['used'] = $db->f('cnt');
}
return $q;
} }
// now schedule it for next run:
$db->query("UPDATE cron SET next_execution=FROM_UNIXTIME( UNIX_TIMESTAMP(NOW()) + schedule * 60) WHERE id=$id");
}
/* --------------------------------------------------------------------------- */
/*---------------------------------------------------------------------------*/ /**
/** * Execute the required crontab of AlternC users
* Launch parallel (using MAX_SOCKETS sockets maximum) retrieval * this function EXIT at the end.
* of URL using CURL */
* @param $urls array of associative array, each having the following keys : function execute_cron() {
* url = url to get (of the form http[s]://login:password@host/path/file?querystring ) global $db;
* login & password = if set, tell the login and password to use as simple HTTP AUTH.
* - any other key will be sent as it is to the callback function
* @param $callback function called for each request when completing. First argument is the $url object, second is the content (output)
* third is the info structure from curl for the returned page. 200 for OK, 403 for AUTH FAILED, 0 for timeout, dump it to know it ;)
* this function should return as soon as possible to allow other curl calls to complete properly.
* @param $cursom_options array of custom CURL options for all transfers
*/
function rolling_curl($urls, $callback, $custom_options = null) {
// make sure the rolling window isn't greater than the # of urls
if (!isset($GLOBALS["DEBUG"])) $GLOBALS["DEBUG"]=false;
$rolling_window = m_cron::MAX_SOCKETS;
$rolling_window = (count($urls) < $rolling_window) ? count($urls) : $rolling_window;
$master = curl_multi_init();
$curl_arr = array();
// add additional curl options here
$std_options = array(CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_TIMEOUT => 240, // 4 minutes timeout for a page
CURLOPT_USERAGENT => "AlternC (Cron Daemon)",
CURLOPT_MAXREDIRS => 0);
if ($GLOBALS["DEBUG"]) $std_options[CURLOPT_VERBOSE]=true; if (!isset($GLOBALS["DEBUG"])) {
$options = ($custom_options) ? ($std_options + $custom_options) : $std_options; $GLOBALS["DEBUG"] = false;
}
// start the first batch of requests $db->query("SELECT id, url, email, schedule, user, password FROM cron WHERE next_execution <= NOW();");
for ($i = 0; $i < $rolling_window; $i++) { $urllist = array();
$ch = curl_init();
$options[CURLOPT_URL] = $urls[$i]["url"]; while ($db->next_record()) {
if ($GLOBALS["DEBUG"]) echo "URL: ".$urls[$i]["url"]."\n"; $db->Record["url"] = urldecode($db->Record["url"]);
curl_setopt_array($ch,$options); $db->Record["user"] = urldecode($db->Record["user"]);
// Handle custom cafile for some https url $db->Record["email"] = urldecode($db->Record["email"]);
if (strtolower(substr($options[CURLOPT_URL],0,5))=="https") { $db->Record["password"] = urldecode($db->Record["password"]);
curl_setopt($ch,CURLOPT_CAINFO,m_cron::DEFAULT_CAFILE);
if ($GLOBALS["DEBUG"]) echo "cainfo set to DEFAULT\n"; // we support only http or https schemes:
} if (substr($db->Record["url"], 0, 7) == "http://" || substr($db->Record["url"], 0, 8) == "https://") {
if (isset($urls[$i]["login"]) && isset($urls[$i]["password"])) { // set basic http authentication $u = array(
curl_setopt($ch,CURLOPT_HTTPAUTH,CURLAUTH_BASIC); "url" => $db->Record["url"],
curl_setopt($ch,CURLOPT_USERPWD,$urls[$i]["login"].":".$urls[$i]["password"]); "id" => $db->Record["id"], "email" => $db->Record["email"],
if ($GLOBALS["DEBUG"]) echo "set basic auth\n"; );
}
curl_multi_add_handle($master, $ch); if ($db->Record["user"] && $db->Record["password"]) {
$u["login"] = $db->Record["user"];
$u["password"] = $db->Record["password"];
}
if ($GLOBALS["DEBUG"])
echo "Will run cron :\n" . print_r($u, true) . "\n";
$urllist[] = $u;
}
if (empty($urllist)) { // nothing to do :
exit(0);
}
// cron_callback($url, $content, $curlobj) will be called at the end of each http call.
$this->rolling_curl($urllist, array("m_cron", "cron_callback"));
}
} }
do {
while(($execrun = curl_multi_exec($master, $running)) == CURLM_CALL_MULTI_PERFORM);
if($execrun != CURLM_OK)
break;
// a request was just completed -- find out which one
while($done = curl_multi_info_read($master)) {
$info = curl_getinfo($done['handle']);
// TODO : since ssl_verify_result is buggy, if we have [header_size] => 0 && [request_size] => 0 && [http_code] => 0, AND https, we can pretend the SSL certificate is buggy.
if ($GLOBALS["DEBUG"]) { echo "Info for ".$done['handle']." \n"; print_r($info); }
if ($info['http_code'] == 200) {
$output = curl_multi_getcontent($done['handle']);
} else {
// request failed. add error handling.
$output="";
}
// request terminated. process output using the callback function.
// Pass the url array to the callback, so we need to search it
foreach($urls as $url) {
if ($url["url"]==$info["url"]) {
call_user_func($callback,$url,$output,$info);
break;
}
}
// If there is more: start a new request
// (it's important to do this before removing the old one)
if ($i<count($urls)) {
$ch = curl_init();
$options[CURLOPT_URL] = $urls[$i++]; // increment i
curl_setopt_array($ch,$options);
if (strtolower(substr($options[CURLOPT_URL],0,5))=="https") {
curl_setopt($ch,CURLOPT_CAINFO,m_cron::DEFAULT_CAFILE);
if ($GLOBALS["DEBUG"]) echo "cainfo set to DEFAULT\n";
}
if (isset($urls[$i]["login"]) && isset($urls[$i]["password"])) { // set basic http authentication
curl_setopt($ch,CURLOPT_HTTPAUTH,CURLAUTH_BASIC);
curl_setopt($ch,CURLOPT_USERPWD,urlencode($urls[$i]["login"]).":".urlencode($urls[$i]["password"]));
if ($GLOBALS["DEBUG"]) echo "set basic auth\n";
}
curl_multi_add_handle($master, $ch);
}
// remove the curl handle that just completed
curl_multi_remove_handle($master, $done['handle']);
}
} while ($running);
curl_multi_close($master);
return true;
}
/* --------------------------------------------------------------------------- */
} /* Class cron */ /**
* Callback function called by rolling_curl when a cron resulr has been received
* schedule it for next run and send the mail if needed
*/
function cron_callback($url, $content, $curl) {
global $db, $L_FQDN;
if (empty($url["id"])) {
return; // not normal...
}
$id = intval($url["id"]);
if ($curl["http_code"] == 200) {
$ok = true;
} else {
$ok = false;
}
if (isset($url["email"]) && $url["email"] && $content) {
if (!mail($url["email"], "AlternC Cron #$id - Report " . date("r"), "Please find below the stdout content produced by your cron task.\n------------------------------------------------------------\n\n" . $content, "From: postmaster@$L_FQDN")) {
echo "Error sending mail for cron #$id to address '" . $url["email"] . "'\n";
}
}
// now schedule it for next run:
$db->query("UPDATE cron SET next_execution=FROM_UNIXTIME( UNIX_TIMESTAMP(NOW()) + schedule * 60) WHERE id=$id");
}
/* --------------------------------------------------------------------------- */
/**
* Launch parallel (using MAX_SOCKETS sockets maximum) retrieval
* of URL using CURL
* @param $urls array of associative array, each having the following keys :
* url = url to get (of the form http[s]://login:password@host/path/file?querystring )
* login & password = if set, tell the login and password to use as simple HTTP AUTH.
* - any other key will be sent as it is to the callback function
* @param $callback function called for each request when completing. First argument is the $url object, second is the content (output)
* third is the info structure from curl for the returned page. 200 for OK, 403 for AUTH FAILED, 0 for timeout, dump it to know it ;)
* this function should return as soon as possible to allow other curl calls to complete properly.
* @param $cursom_options array of custom CURL options for all transfers
*/
function rolling_curl($urls, $callback, $custom_options = null) {
// make sure the rolling window isn't greater than the # of urls
if (!isset($GLOBALS["DEBUG"]))
$GLOBALS["DEBUG"] = false;
$rolling_window = m_cron::MAX_SOCKETS;
$rolling_window = (count($urls) < $rolling_window) ? count($urls) : $rolling_window;
$master = curl_multi_init();
// add additional curl options here
$std_options = array(CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_TIMEOUT => 240, // 4 minutes timeout for a page
CURLOPT_USERAGENT => "AlternC (Cron Daemon)",
CURLOPT_MAXREDIRS => 0);
if ($GLOBALS["DEBUG"]) {
$std_options[CURLOPT_VERBOSE] = true;
}
$options = ($custom_options) ? ($std_options + $custom_options) : $std_options;
// start the first batch of requests
for ($i = 0; $i < $rolling_window; $i++) {
$ch = curl_init();
$options[CURLOPT_URL] = $urls[$i]["url"];
if ($GLOBALS["DEBUG"]) {
echo "URL: " . $urls[$i]["url"] . "\n";
}
curl_setopt_array($ch, $options);
// Handle custom cafile for some https url
if (strtolower(substr($options[CURLOPT_URL], 0, 5)) == "https") {
curl_setopt($ch, CURLOPT_CAINFO, m_cron::DEFAULT_CAFILE);
if ($GLOBALS["DEBUG"]) {
echo "cainfo set to DEFAULT\n";
}
}
if (isset($urls[$i]["login"]) && isset($urls[$i]["password"])) { // set basic http authentication
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $urls[$i]["login"] . ":" . $urls[$i]["password"]);
if ($GLOBALS["DEBUG"]) {
echo "set basic auth\n";
}
}
curl_multi_add_handle($master, $ch);
}
do {
while (($execrun = curl_multi_exec($master, $running)) == CURLM_CALL_MULTI_PERFORM);
if ($execrun != CURLM_OK) {
break;
}
// a request was just completed -- find out which one
while ($done = curl_multi_info_read($master)) {
$info = curl_getinfo($done['handle']);
// TODO : since ssl_verify_result is buggy, if we have [header_size] => 0 && [request_size] => 0 && [http_code] => 0, AND https, we can pretend the SSL certificate is buggy.
if ($GLOBALS["DEBUG"]) {
echo "Info for " . $done['handle'] . " \n";
print_r($info);
}
if ($info['http_code'] == 200) {
$output = curl_multi_getcontent($done['handle']);
} else {
// request failed. add error handling.
$output = "";
}
// request terminated. process output using the callback function.
// Pass the url array to the callback, so we need to search it
foreach ($urls as $url) {
if ($url["url"] == $info["url"]) {
call_user_func($callback, $url, $output, $info);
break;
}
}
// If there is more: start a new request
// (it's important to do this before removing the old one)
if ($i < count($urls)) {
$ch = curl_init();
$options[CURLOPT_URL] = $urls[$i++]; // increment i
curl_setopt_array($ch, $options);
if (strtolower(substr($options[CURLOPT_URL], 0, 5)) == "https") {
curl_setopt($ch, CURLOPT_CAINFO, m_cron::DEFAULT_CAFILE);
if ($GLOBALS["DEBUG"]) {
echo "cainfo set to DEFAULT\n";
}
}
if (isset($urls[$i]["login"]) && isset($urls[$i]["password"])) { // set basic http authentication
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, urlencode($urls[$i]["login"]) . ":" . urlencode($urls[$i]["password"]));
if ($GLOBALS["DEBUG"]) {
echo "set basic auth\n";
}
}
curl_multi_add_handle($master, $ch);
}
// remove the curl handle that just completed
curl_multi_remove_handle($master, $done['handle']);
}
} while ($running);
curl_multi_close($master);
return true;
}
}
/* Class cron */

View File

@ -1,44 +1,31 @@
<?php <?php
class m_crypto class m_crypto {
{
function encrypt($sValue, $sSecretKey)
{
return rtrim(
base64_encode(
mcrypt_encrypt(
MCRYPT_RIJNDAEL_256,
$sSecretKey, $sValue,
MCRYPT_MODE_ECB,
mcrypt_create_iv(
mcrypt_get_iv_size(
MCRYPT_RIJNDAEL_256,
MCRYPT_MODE_ECB
),
MCRYPT_RAND
)
)
), "\0"
);
}
function decrypt($sValue, $sSecretKey) function encrypt($sValue, $sSecretKey) {
{ return rtrim(
return rtrim( base64_encode(
mcrypt_decrypt( mcrypt_encrypt(
MCRYPT_RIJNDAEL_256, MCRYPT_RIJNDAEL_256, $sSecretKey, $sValue, MCRYPT_MODE_ECB, mcrypt_create_iv(
$sSecretKey, mcrypt_get_iv_size(
base64_decode($sValue), MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB
MCRYPT_MODE_ECB, ), MCRYPT_RAND
mcrypt_create_iv( )
mcrypt_get_iv_size( )
MCRYPT_RIJNDAEL_256, ), "\0"
MCRYPT_MODE_ECB );
), }
MCRYPT_RAND
) function decrypt($sValue, $sSecretKey) {
), "\0" return rtrim(
); mcrypt_decrypt(
} MCRYPT_RIJNDAEL_256, $sSecretKey, base64_decode($sValue), MCRYPT_MODE_ECB, mcrypt_create_iv(
mcrypt_get_iv_size(
MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB
), MCRYPT_RAND
)
), "\0"
);
}
} }

View File

@ -1,94 +1,102 @@
<?php <?php
/* /*
LICENSE LICENSE
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License (GPL) modify it under the terms of the GNU General Public License (GPL)
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
To read the license please visit http://www.gnu.org/copyleft/gpl.html
----------------------------------------------------------------------
Original Author of file: Camille Lafitte
Purpose of file: Manage hook system.
----------------------------------------------------------------------
*/
To read the license please visit http://www.gnu.org/copyleft/gpl.html
----------------------------------------------------------------------
Original Author of file: Camille Lafitte
Purpose of file: Manage hook system.
----------------------------------------------------------------------
*/
/** /**
* This class manage debug. * This class manage debug.
* *
* @copyright AlternC-Team 2002-2005 http://alternc.org/ * @copyright AlternC-Team 2002-2005 http://alternc.org/
*/ */
class m_debug_alternc { class m_debug_alternc {
var $infos="";
var $status=false;
var $nb_sql_query=0;
var $tps_sql_query=0;
var $generation_started=null;
/*---------------------------------------------------------------------------*/ var $infos = "";
/** Constructor var $status = false;
*/ var $nb_sql_query = 0;
function m_debug_alternc() { var $tps_sql_query = 0;
if ( isset($_COOKIE['alternc_debugme']) && $_COOKIE['alternc_debugme'] ) { var $generation_started = null;
$this->status=true;
ini_set('display_errors', '1'); /* --------------------------------------------------------------------------- */
/** Constructor
*/
function m_debug_alternc() {
if (isset($_COOKIE['alternc_debugme']) && $_COOKIE['alternc_debugme']) {
$this->status = true;
ini_set('display_errors', '1');
}
$this->nb_sql_query = 0;
$this->tps_sql_query = 0;
$this->generation_started = microtime(true);
} }
$this->nb_sql_query=0;
$this->tps_sql_query=0;
$this->generation_started=microtime(true);
}
function activate() { function activate() {
setcookie('alternc_debugme','1', time()+3600); // expire in 1 hour setcookie('alternc_debugme', '1', time() + 3600); // expire in 1 hour
$this->status=""; $this->status = "";
return true; return true;
} }
function desactivate() { function desactivate() {
setcookie('alternc_debugme','0'); setcookie('alternc_debugme', '0');
$this->status=false; $this->status = false;
return true; return true;
} }
function add($txt) { function add($txt) {
$this->infos .= "\n$txt"; $this->infos .= "\n$txt";
return true; return true;
} }
function dump() { function dump() {
global $cuid; global $cuid;
if ( $cuid!=2000 ) return false; if ($cuid != 2000) {
if ( ! $this->status ) return false; return false;
}
if (!$this->status) {
return false;
}
$generation_time = (microtime(true) - $this->generation_started) * 1000; $generation_time = (microtime(true) - $this->generation_started) * 1000;
echo "<fieldset style='background-color: silver;'>"; echo "<fieldset style='background-color: silver;'>";
echo "<pre>"; echo "<pre>";
echo "+++ BEGIN Debug Mode+++\n"; echo "+++ BEGIN Debug Mode+++\n";
echo "Total generation time : $generation_time ms\n"; echo "Total generation time : $generation_time ms\n";
print_r("\n--- Total SQL Query : ".$this->nb_sql_query." req / ".$this->tps_sql_query." ms ---\n"); print_r("\n--- Total SQL Query : " . $this->nb_sql_query . " req / " . $this->tps_sql_query . " ms ---\n");
print_r($this->infos); print_r($this->infos);
echo "\n\n--- GET ---\n"; echo "\n\n--- GET ---\n";
print_r($_GET); print_r($_GET);
echo "\n\n--- POST ---\n"; echo "\n\n--- POST ---\n";
print_r($_POST); print_r($_POST);
echo "\n\n--- SESSION ---\n"; echo "\n\n--- SESSION ---\n";
@print_r($_SESSION); @print_r($_SESSION);
echo "\n\n--- COOKIE ---\n"; echo "\n\n--- COOKIE ---\n";
print_r($_COOKIE); print_r($_COOKIE);
echo "\n\n--- SERVER ---\n"; echo "\n\n--- SERVER ---\n";
print_r($_SERVER); print_r($_SERVER);
echo "\n\n+++ END Debug Mode+++"; echo "\n\n+++ END Debug Mode+++";
echo "</pre>"; echo "</pre>";
echo "</fieldset>"; echo "</fieldset>";
return true; return true;
} }
} /* Class debug_alternc */ }
?> /* Class debug_alternc */

View File

@ -85,7 +85,7 @@ class m_dom {
* Constructeur * Constructeur
*/ */
function m_dom() { function m_dom() {
global $L_FQDN; global $L_FQDN;
$this->tld_no_check_at_all = variable_get('tld_no_check_at_all', 0, 'Disable ALL check on the TLD (users will be able to add any domain)', array('desc' => 'Disabled', 'type' => 'boolean')); $this->tld_no_check_at_all = variable_get('tld_no_check_at_all', 0, 'Disable ALL check on the TLD (users will be able to add any domain)', array('desc' => 'Disabled', 'type' => 'boolean'));
variable_get('mailname_bounce', $L_FQDN, 'FQDN of the mail server, used to create vhost virtual mail_adress.', array('desc' => 'FQDN', 'type' => 'string')); variable_get('mailname_bounce', $L_FQDN, 'FQDN of the mail server, used to create vhost virtual mail_adress.', array('desc' => 'FQDN', 'type' => 'string'));
} }
@ -105,16 +105,16 @@ class m_dom {
* @param string $fqdn * @param string $fqdn
*/ */
public static function get_sub_domain_id_and_member_by_name($fqdn) { public static function get_sub_domain_id_and_member_by_name($fqdn) {
global $db, $err, $cuid; global $db, $err;
$err->log("dom", "get_sub_domain_by_name"); $err->log("dom", "get_sub_domain_by_name");
$fqdn = mysql_real_escape_string($fqdn); $fqdn = mysql_real_escape_string($fqdn);
$db->query("select sd.* from sub_domaines sd where if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine) = '$fqdn';"); $db->query("select sd.* from sub_domaines sd where if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine) = '$fqdn';");
if (!$db->next_record()) if (!$db->next_record()) {
return false; return false;
}
return array('sub_id' => intval($db->f('id')), 'member_id' => intval($db->f('compte'))); return array('sub_id' => intval($db->f('id')), 'member_id' => intval($db->f('compte')));
} }
function hook_menu() { function hook_menu() {
global $quota; global $quota;
$obj = array( $obj = array(
@ -123,22 +123,20 @@ class m_dom {
'link' => 'toggle', 'link' => 'toggle',
'pos' => 20, 'pos' => 20,
'links' => array(), 'links' => array(),
); );
if ($quota->cancreate("dom")) { if ($quota->cancreate("dom")) {
$obj['links'][] = $obj['links'][] = array(
array( 'ico' => 'images/new.png',
'ico' => 'images/new.png', 'txt' => _("Add a domain"),
'txt' => _("Add a domain"), 'url' => "dom_add.php",
'url' => "dom_add.php",
); );
} }
foreach ($this->enum_domains() as $d) { foreach ($this->enum_domains() as $d) {
$obj['links'][] = $obj['links'][] = array(
array( 'txt' => htmlentities($d),
'txt' => htmlentities($d), 'url' => "dom_edit.php?domain=" . urlencode($d),
'url' => "dom_edit.php?domain=" . urlencode($d),
); );
} }
@ -186,7 +184,7 @@ class m_dom {
* @param integer $type * @param integer $type
*/ */
function domains_type_target_values($type = null) { function domains_type_target_values($type = null) {
global $db, $err, $cuid; global $db, $err;
$err->log("dom", "domains_type_target_values"); $err->log("dom", "domains_type_target_values");
if (is_null($type)) { if (is_null($type)) {
$db->query("desc domaines_type;"); $db->query("desc domaines_type;");
@ -202,8 +200,9 @@ class m_dom {
return $r; return $r;
} else { } else {
$db->query("select target from domaines_type where name='$type';"); $db->query("select target from domaines_type where name='$type';");
if (!$db->next_record()) if (!$db->next_record()) {
return false; return false;
}
return $db->f('target'); return $db->f('target');
} }
} }
@ -220,8 +219,9 @@ class m_dom {
$val = array(); $val = array();
foreach (explode("\n", $zone) as $z) { foreach (explode("\n", $zone) as $z) {
$z = trim($z); $z = trim($z);
if (empty($z)) if (empty($z)) {
continue; continue;
}
$val[] = $this->import_manual_dns_entry($z, $domain, $detect_redirect, $save); $val[] = $this->import_manual_dns_entry($z, $domain, $detect_redirect, $save);
} }
return $val; return $val;
@ -231,11 +231,12 @@ class m_dom {
* @param string $zone * @param string $zone
*/ */
function import_manual_dns_entry($zone, $domain, $detect_redirect = true, $save = false) { function import_manual_dns_entry($zone, $domain, $detect_redirect = true, $save = false) {
global $cuid, $err; global $err;
$err->log("dom", "import_manual_dns_entry"); $err->log("dom", "import_manual_dns_entry");
$zone = trim($zone); $zone = trim($zone);
if (empty($zone)) if (empty($zone)) {
return false; return false;
}
$domain = trim($domain); $domain = trim($domain);
if (empty($domain)) { if (empty($domain)) {
@ -409,7 +410,6 @@ class m_dom {
} }
private function import_manual_dns_entry_doit($entry) { private function import_manual_dns_entry_doit($entry) {
global $err;
$entry['did_it'] = 0; $entry['did_it'] = 0;
if ($entry['status'] == 'err') { if ($entry['status'] == 'err') {
return $entry; return $entry;
@ -417,14 +417,14 @@ class m_dom {
$val = $entry['entry_new']; $val = $entry['entry_new'];
if (empty($val['type'])) if (empty($val['type'])) {
return false; return false;
}
switch ($val['type']) { switch ($val['type']) {
case "set_ttl": case "set_ttl":
$entry['did_it'] = $this->set_ttl($this->get_domain_byname($val['domain']), $val['value']); $entry['did_it'] = $this->set_ttl($this->get_domain_byname($val['domain']), $val['value']);
return $entry; return $entry;
break;
} }
// If it is an unknown domains type // If it is an unknown domains type
@ -435,8 +435,9 @@ class m_dom {
} }
// If the subdomain is @, we want an empty subdomain // If the subdomain is @, we want an empty subdomain
if ($val['sub'] == '@') if ($val['sub'] == '@') {
$val['sub'] = ''; $val['sub'] = '';
}
$this->lock(); $this->lock();
$entry['did_it'] = $this->set_sub_domain($val['domain'], $val['sub'], $val['type'], $val['value']); $entry['did_it'] = $this->set_sub_domain($val['domain'], $val['sub'], $val['type'], $val['value']);
@ -492,7 +493,6 @@ class m_dom {
if ($result === false) { if ($result === false) {
throw new Exception("Could not read data from {$url}"); throw new Exception("Could not read data from {$url}");
return false;
} }
if (strstr($http_response_header[0], '301') || strstr($http_response_header[0], '302')) { if (strstr($http_response_header[0], '301') || strstr($http_response_header[0], '302')) {
// This is a redirection // This is a redirection
@ -528,7 +528,7 @@ class m_dom {
} }
function domains_type_get($name) { function domains_type_get($name) {
global $db, $err, $cuid; global $db;
$name = mysql_real_escape_string($name); $name = mysql_real_escape_string($name);
$db->query("select * from domaines_type where name='$name' ;"); $db->query("select * from domaines_type where name='$name' ;");
$db->next_record(); $db->next_record();
@ -536,14 +536,14 @@ class m_dom {
} }
function domains_type_del($name) { function domains_type_del($name) {
global $db, $err, $cuid; global $db;
$name = mysql_real_escape_string($name); $name = mysql_real_escape_string($name);
$db->query("delete domaines_type where name='$name';"); $db->query("delete domaines_type where name='$name';");
return true; return true;
} }
function domains_type_update($name, $description, $target, $entry, $compatibility, $enable, $only_dns, $need_dns, $advanced, $create_tmpdir, $create_targetdir) { function domains_type_update($name, $description, $target, $entry, $compatibility, $enable, $only_dns, $need_dns, $advanced, $create_tmpdir, $create_targetdir) {
global $err, $cuid, $db; global $err, $db;
// The name MUST contain only letter and digits, it's an identifier after all ... // The name MUST contain only letter and digits, it's an identifier after all ...
if (!preg_match("#^[a-z0-9]+$#", $name)) { if (!preg_match("#^[a-z0-9]+$#", $name)) {
$err->raise("dom", _("The name MUST contain only letter and digits")); $err->raise("dom", _("The name MUST contain only letter and digits"));
@ -565,12 +565,13 @@ class m_dom {
} }
function sub_domain_change_status($sub_id, $status) { function sub_domain_change_status($sub_id, $status) {
global $db, $err, $cuid; global $db, $err;
$err->log("dom", "sub_domain_change_status"); $err->log("dom", "sub_domain_change_status");
$sub_id = intval($sub_id); $sub_id = intval($sub_id);
$status = strtoupper($status); $status = strtoupper($status);
if (!in_array($status, array('ENABLE', 'DISABLE'))) if (!in_array($status, array('ENABLE', 'DISABLE'))) {
return false; return false;
}
$jh = $this->get_sub_domain_all($sub_id); $jh = $this->get_sub_domain_all($sub_id);
if ($status == 'ENABLE') { // check compatibility with existing sub_domains if ($status == 'ENABLE') { // check compatibility with existing sub_domains
@ -618,9 +619,7 @@ class m_dom {
$dom = strtolower($dom); $dom = strtolower($dom);
$db->query("UPDATE sub_domaines SET web_action='UPDATE' WHERE domaine='$dom';"); $db->query("UPDATE sub_domaines SET web_action='UPDATE' WHERE domaine='$dom';");
$this->set_dns_action($dom, 'UPDATE'); $this->set_dns_action($dom, 'UPDATE');
# TODO : some work with domain sensitive classes # TODO : some work with domain sensitive classes
return true; return true;
} }
@ -638,7 +637,7 @@ class m_dom {
* @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon. * @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
*/ */
function del_domain($dom) { function del_domain($dom) {
global $db, $err, $classes, $cuid, $hooks; global $db, $err, $hooks;
$err->log("dom", "del_domain", $dom); $err->log("dom", "del_domain", $dom);
$dom = strtolower($dom); $dom = strtolower($dom);
@ -689,7 +688,7 @@ class m_dom {
$ @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon. $ @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
*/ */
function add_domain($domain, $dns, $noerase = false, $force = false, $isslave = false, $slavedom = "") { function add_domain($domain, $dns, $noerase = false, $force = false, $isslave = false, $slavedom = "") {
global $db, $err, $quota, $classes, $L_MX, $L_FQDN, $tld, $cuid, $bro, $hooks; global $db, $err, $quota, $L_FQDN, $tld, $cuid, $hooks;
$err->log("dom", "add_domain", $domain); $err->log("dom", "add_domain", $domain);
// Locked ? // Locked ?
@ -740,14 +739,15 @@ class m_dom {
return false; return false;
} }
if ($dns) if ($dns) {
$dns = "1"; $dns = "1";
else } else {
$dns = "0"; $dns = "0";
}
// mode 5 : force DNS to NO. // mode 5 : force DNS to NO.
if ($tld[$v] == 5) if ($tld[$v] == 5) {
$dns = 0; $dns = 0;
}
// It must be a real domain (no subdomain) // It must be a real domain (no subdomain)
if (!$dns) { if (!$dns) {
$v = checkhostallow_nodns($domain); $v = checkhostallow_nodns($domain);
@ -762,14 +762,16 @@ class m_dom {
$err->raise("dom", _("Your domain quota is over, you cannot create more domain names")); $err->raise("dom", _("Your domain quota is over, you cannot create more domain names"));
return false; return false;
} }
if ($noerase) if ($noerase) {
$noerase = "1"; $noerase = "1";
else } else {
$noerase = "0"; $noerase = "0";
if ($dns) }
if ($dns) {
$gesmx = "1"; $gesmx = "1";
else } else {
$gesmx = "0"; // do not host mx by default if not hosting the DNS $gesmx = "0"; // do not host mx by default if not hosting the DNS
}
$db->query("INSERT INTO domaines (compte,domaine,gesdns,gesmx,noerase,dns_action) VALUES ('$cuid','$domain','$dns','$gesmx','$noerase','UPDATE');"); $db->query("INSERT INTO domaines (compte,domaine,gesdns,gesmx,noerase,dns_action) VALUES ('$cuid','$domain','$dns','$gesmx','$noerase','UPDATE');");
if (!($id = $db->lastid())) { if (!($id = $db->lastid())) {
$err->raise("dom", _("An unexpected error occured when creating the domain")); $err->raise("dom", _("An unexpected error occured when creating the domain"));
@ -798,8 +800,9 @@ class m_dom {
} }
// New Hooks: // New Hooks:
$hooks->invoke("hook_dom_add_domain", array($id)); $hooks->invoke("hook_dom_add_domain", array($id));
if ($gesmx) if ($gesmx) {
$hooks->invoke("hook_dom_add_mx_domain", array($id)); $hooks->invoke("hook_dom_add_mx_domain", array($id));
}
if ($isslave) { if ($isslave) {
$hooks->invoke("hook_dom_add_slave_domain", array($id, $slavedom)); $hooks->invoke("hook_dom_add_slave_domain", array($id, $slavedom));
} }
@ -834,13 +837,11 @@ class m_dom {
* @param string $domain * @param string $domain
*/ */
function domdefaultdir($domain) { function domdefaultdir($domain) {
global $bro, $cuid;
$dest_root = $bro->get_userid_root($cuid);
# return $dest_root."/www/".$this->domshort($domain);
return "/www/" . $this->domshort($domain); return "/www/" . $this->domshort($domain);
} }
function dump_axfr($domain, $ns = 'localhost') { function dump_axfr($domain, $ns = 'localhost') {
$axfr = array();
exec('/usr/bin/dig AXFR "' . escapeshellcmd($domain) . '" @"' . escapeshellcmd($ns) . '"', $axfr); exec('/usr/bin/dig AXFR "' . escapeshellcmd($domain) . '" @"' . escapeshellcmd($ns) . '"', $axfr);
return $axfr; return $axfr;
} }
@ -858,7 +859,7 @@ class m_dom {
'domain_type_parameter' => $db->f('domain_type_parameter'), 'domain_type_parameter' => $db->f('domain_type_parameter'),
'concerned' => $db->f('concerned'), 'concerned' => $db->f('concerned'),
'enabled' => $db->f('enabled') 'enabled' => $db->f('enabled')
); );
} }
return $c; return $c;
@ -869,12 +870,14 @@ class m_dom {
$err->log("dom", "update_default_subdomains"); $err->log("dom", "update_default_subdomains");
$ok = true; $ok = true;
foreach ($arr as $a) { foreach ($arr as $a) {
if (!isset($a['id'])) if (!isset($a['id'])) {
$a['id'] = null; $a['id'] = null;
}
if (!empty($a['sub']) || !empty($a['domain_type_parameter'])) { if (!empty($a['sub']) || !empty($a['domain_type_parameter'])) {
if (!isset($a['enabled'])) if (!isset($a['enabled'])) {
$a['enabled'] = 0; $a['enabled'] = 0;
}
if (!$this->update_one_default($a['domain_type'], $a['sub'], $a['domain_type_parameter'], $a['concerned'], $a['enabled'], $a['id'])) { if (!$this->update_one_default($a['domain_type'], $a['sub'], $a['domain_type_parameter'], $a['concerned'], $a['enabled'], $a['id'])) {
$ok = false; $ok = false;
} }
@ -887,10 +890,11 @@ class m_dom {
global $db, $err; global $db, $err;
$err->log("dom", "update_one_default"); $err->log("dom", "update_one_default");
if ($id == null) if ($id == null) {
$db->query("INSERT INTO default_subdomains values ('','" . addslashes($sub) . "','" . addslashes($domain_type) . "','" . addslashes($domain_type_parameter) . "','" . addslashes($concerned) . "','" . addslashes($enabled) . "');"); $db->query("INSERT INTO default_subdomains values ('','" . addslashes($sub) . "','" . addslashes($domain_type) . "','" . addslashes($domain_type_parameter) . "','" . addslashes($concerned) . "','" . addslashes($enabled) . "');");
else } else {
$db->query("UPDATE default_subdomains set sub='" . addslashes($sub) . "', domain_type='" . addslashes($domain_type) . "',domain_type_parameter='" . addslashes($domain_type_parameter) . "',concerned='" . addslashes($concerned) . "',enabled='" . addslashes($enabled) . "' where id=" . addslashes($id) . ";"); $db->query("UPDATE default_subdomains set sub='" . addslashes($sub) . "', domain_type='" . addslashes($domain_type) . "',domain_type_parameter='" . addslashes($domain_type_parameter) . "',concerned='" . addslashes($concerned) . "',enabled='" . addslashes($enabled) . "' where id=" . addslashes($id) . ";");
}
return true; return true;
//update //update
} }
@ -924,7 +928,7 @@ class m_dom {
* *
*/ */
function whois($domain) { function whois($domain) {
global $db, $err; global $err;
$err->log("dom", "whois", $domain); $err->log("dom", "whois", $domain);
// pour ajouter un nouveau TLD, utiliser le code ci-dessous. // pour ajouter un nouveau TLD, utiliser le code ci-dessous.
// echo "whois : $domain<br />"; // echo "whois : $domain<br />";
@ -978,16 +982,19 @@ class m_dom {
if (preg_match("#Name Server:#", $ligne)) { if (preg_match("#Name Server:#", $ligne)) {
$found = true; $found = true;
$tmp = strtolower(str_replace(chr(10), "", str_replace(chr(13), "", str_replace(" ", "", str_replace("Name Server:", "", $ligne))))); $tmp = strtolower(str_replace(chr(10), "", str_replace(chr(13), "", str_replace(" ", "", str_replace("Name Server:", "", $ligne)))));
if ($tmp) if ($tmp) {
$serveurList[] = $tmp; $serveurList[] = $tmp;
}
} }
break; break;
case "cx": case "cx":
$ligne = str_replace(chr(10), "", str_replace(chr(13), "", str_replace(" ", "", $ligne))); $ligne = str_replace(chr(10), "", str_replace(chr(13), "", str_replace(" ", "", $ligne)));
if ($ligne == "" && $state == 1) if ($ligne == "" && $state == 1) {
$state = 2; $state = 2;
if ($state == 1) }
if ($state == 1) {
$serveurList[] = strtolower($ligne); $serveurList[] = strtolower($ligne);
}
if ($ligne == "Nameservers:" && $state == 0) { if ($ligne == "Nameservers:" && $state == 0) {
$state = 1; $state = 1;
$found = true; $found = true;
@ -996,10 +1003,12 @@ class m_dom {
case "eu": case "eu":
case "be": case "be":
$ligne = preg_replace("/^ *([^ ]*) \(.*\)$/", "\\1", trim($ligne)); $ligne = preg_replace("/^ *([^ ]*) \(.*\)$/", "\\1", trim($ligne));
if ($found) if ($found) {
$tmp = trim($ligne); $tmp = trim($ligne);
if ($tmp) }
if ($tmp) {
$serveurList[] = $tmp; $serveurList[] = $tmp;
}
if ($ligne == "Nameservers:") { if ($ligne == "Nameservers:") {
$state = 1; $state = 1;
$found = true; $found = true;
@ -1011,16 +1020,18 @@ class m_dom {
// weird regexp (trailing garbage after name server), but I could not make it work otherwise // weird regexp (trailing garbage after name server), but I could not make it work otherwise
$tmp = strtolower(preg_replace('/Name Server: ([^ ]+)\..$/', "\\1", $ligne)); $tmp = strtolower(preg_replace('/Name Server: ([^ ]+)\..$/', "\\1", $ligne));
$tmp = preg_replace('/[^-_a-z0-9\.]/', '', $tmp); $tmp = preg_replace('/[^-_a-z0-9\.]/', '', $tmp);
if ($tmp) if ($tmp) {
$serveurList[] = $tmp; $serveurList[] = $tmp;
}
} }
break; break;
case "it": case "it":
if (preg_match("#nserver:#", $ligne)) { if (preg_match("#nserver:#", $ligne)) {
$found = true; $found = true;
$tmp = strtolower(preg_replace("/nserver:\s*[^ ]*\s*([^\s]*)$/", "\\1", $ligne)); $tmp = strtolower(preg_replace("/nserver:\s*[^ ]*\s*([^\s]*)$/", "\\1", $ligne));
if ($tmp) if ($tmp) {
$serveurList[] = $tmp; $serveurList[] = $tmp;
}
} }
break; break;
case "fr": case "fr":
@ -1028,8 +1039,9 @@ class m_dom {
if (preg_match("#nserver:#", $ligne)) { if (preg_match("#nserver:#", $ligne)) {
$found = true; $found = true;
$tmp = strtolower(preg_replace("#nserver:\s*([^\s]*)\s*.*$#", "\\1", $ligne)); $tmp = strtolower(preg_replace("#nserver:\s*([^\s]*)\s*.*$#", "\\1", $ligne));
if ($tmp) if ($tmp) {
$serveurList[] = $tmp; $serveurList[] = $tmp;
}
} }
break; break;
case "ca": case "ca":
@ -1082,6 +1094,8 @@ class m_dom {
function checkmx($domaine, $ref_domain = '') { function checkmx($domaine, $ref_domain = '') {
global $L_DEFAULT_MX, $L_DEFAULT_SECONDARY_MX; global $L_DEFAULT_MX, $L_DEFAULT_SECONDARY_MX;
$ref_mx = array();
$mxhosts = array();
if (!empty($ref_domain)) { if (!empty($ref_domain)) {
getmxrr($ref_domain, $ref_mx); getmxrr($ref_domain, $ref_mx);
} else { } else {
@ -1114,9 +1128,6 @@ class m_dom {
return 0; return 0;
} }
//checkmx
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
/** /**
@ -1245,7 +1256,7 @@ class m_dom {
* @param string $value * @param string $value
*/ */
function check_type_value($type, $value) { function check_type_value($type, $value) {
global $db, $err, $cuid; global $err;
// check the type we can have in domaines_type.target // check the type we can have in domaines_type.target
switch ($this->domains_type_target_values($type)) { switch ($this->domains_type_target_values($type)) {
@ -1273,7 +1284,6 @@ class m_dom {
return false; return false;
} }
return true; return true;
break;
case 'IP': case 'IP':
if (checkip($value)) { if (checkip($value)) {
return true; return true;
@ -1309,14 +1319,10 @@ class m_dom {
default: default:
$err->raise("dom", _("Invalid domain type selected, please check")); $err->raise("dom", _("Invalid domain type selected, please check"));
return false; return false;
break;
} }
return false; return false;
} }
//check_type_value
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
/** /**
@ -1328,13 +1334,14 @@ class m_dom {
* @return boolean tell you if the subdomain can be installed there * @return boolean tell you if the subdomain can be installed there
*/ */
function can_create_subdomain($dom, $sub, $type, $sub_domain_id = 'null') { function can_create_subdomain($dom, $sub, $type, $sub_domain_id = 'null') {
global $db, $err, $cuid; global $db, $err;
$err->log("dom", "can_create_subdomain", $dom . "/" . $sub); $err->log("dom", "can_create_subdomain", $dom . "/" . $sub);
// Get the compatibility list for this domain type // Get the compatibility list for this domain type
$db->query("select upper(compatibility) as compatibility from domaines_type where upper(name)=upper('$type');"); $db->query("select upper(compatibility) as compatibility from domaines_type where upper(name)=upper('$type');");
if (!$db->next_record()) if (!$db->next_record()) {
return false; return false;
}
$compatibility_lst = explode(",", $db->f('compatibility')); $compatibility_lst = explode(",", $db->f('compatibility'));
// Get the list of type of subdomains already here who have the same name // Get the list of type of subdomains already here who have the same name
@ -1342,8 +1349,9 @@ class m_dom {
#$db->query("select * from sub_domaines where sub='$sub' and domaine='$dom';"); #$db->query("select * from sub_domaines where sub='$sub' and domaine='$dom';");
while ($db->next_record()) { while ($db->next_record()) {
// And if there is a domain with a incompatible type, return false // And if there is a domain with a incompatible type, return false
if (!in_array(strtoupper($db->f('type')), $compatibility_lst)) if (!in_array(strtoupper($db->f('type')), $compatibility_lst)) {
return false; return false;
}
} }
// All is right, go ! Create ur domain ! // All is right, go ! Create ur domain !
@ -1393,7 +1401,7 @@ class m_dom {
} }
// On a épuré $dir des problémes eventuels ... On est en DESSOUS du dossier de l'utilisateur. // On a épuré $dir des problémes eventuels ... On est en DESSOUS du dossier de l'utilisateur.
if ($t = checkfqdn($dom)) { if (($t = checkfqdn($dom))) {
$err->raise("dom", _("The domain name is syntaxically incorrect")); $err->raise("dom", _("The domain name is syntaxically incorrect"));
return false; return false;
} }
@ -1415,7 +1423,7 @@ class m_dom {
// Create TMP dir and TARGET dir if needed by the domains_type // Create TMP dir and TARGET dir if needed by the domains_type
$dest_root = $bro->get_userid_root($cuid); $dest_root = $bro->get_userid_root($cuid);
$domshort = $this->domshort($dom, $sub); //$domshort = $this->domshort($dom, $sub);
$db->query("select create_tmpdir, create_targetdir from domaines_type where name = '$type';"); $db->query("select create_tmpdir, create_targetdir from domaines_type where name = '$type';");
$db->next_record(); $db->next_record();
if ($db->f('create_tmpdir')) { if ($db->f('create_tmpdir')) {
@ -1444,9 +1452,6 @@ class m_dom {
return true; return true;
} }
// set_sub_domain
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
/** /**
@ -1456,7 +1461,7 @@ class m_dom {
* *
*/ */
function del_sub_domain($sub_domain_id) { function del_sub_domain($sub_domain_id) {
global $db, $err, $cuid; global $db, $err;
$err->log("dom", "del_sub_domain", $sub_domain_id); $err->log("dom", "del_sub_domain", $sub_domain_id);
// Locked ? // Locked ?
if (!$this->islocked) { if (!$this->islocked) {
@ -1473,8 +1478,6 @@ class m_dom {
return true; return true;
} }
// del_sub_domain
/** /**
* @param integer $dom_id * @param integer $dom_id
*/ */
@ -1505,7 +1508,7 @@ class m_dom {
* *
*/ */
function edit_domain($dom, $dns, $gesmx, $force = false, $ttl = 86400) { function edit_domain($dom, $dns, $gesmx, $force = false, $ttl = 86400) {
global $db, $err, $L_MX, $classes, $cuid, $hooks; global $db, $err, $hooks;
$err->log("dom", "edit_domain", $dom . "/" . $dns . "/" . $gesmx); $err->log("dom", "edit_domain", $dom . "/" . $dns . "/" . $gesmx);
// Locked ? // Locked ?
if (!$this->islocked && !$force) { if (!$this->islocked && !$force) {
@ -1544,8 +1547,9 @@ class m_dom {
$err->raise("dom", _("The domain name %s does not exist"), $dom); $err->raise("dom", _("The domain name %s does not exist"), $dom);
return false; return false;
} }
if ($dns != "1") if ($dns != "1") {
$dns = "0"; $dns = "0";
}
// On vérifie que des modifications ont bien eu lieu :) // On vérifie que des modifications ont bien eu lieu :)
if ($r["dns"] == $dns && $r["mail"] == $gesmx && $r["zonettl"] == $ttl) { if ($r["dns"] == $dns && $r["mail"] == $gesmx && $r["zonettl"] == $ttl) {
$err->raise("dom", _("No change has been requested...")); $err->raise("dom", _("No change has been requested..."));
@ -1579,14 +1583,10 @@ class m_dom {
return true; return true;
} }
// edit_domain
/* * ************************* */ /* * ************************* */
/* Slave dns ip managment */ /* Slave dns ip managment */
/* * ************************* */ /* * ************************* */
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
/** Return the list of ip addresses and classes that are allowed access to domain list /** Return the list of ip addresses and classes that are allowed access to domain list
@ -1616,8 +1616,9 @@ class m_dom {
return false; return false;
} }
$class = intval($class); $class = intval($class);
if ($class < 8 || $class > 32) if ($class < 8 || $class > 32) {
$class = 32; $class = 32;
}
$db->query("SELECT * FROM slaveip WHERE ip='$ip' AND class='$class';"); $db->query("SELECT * FROM slaveip WHERE ip='$ip' AND class='$class';");
if ($db->next_record()) { if ($db->next_record()) {
$err->raise("err", _("The requested domain is forbidden in this server, please contact the administrator")); $err->raise("err", _("The requested domain is forbidden in this server, please contact the administrator"));
@ -1652,7 +1653,7 @@ class m_dom {
/** Check for a slave account /** Check for a slave account
*/ */
function check_slave_account($login, $pass) { function check_slave_account($login, $pass) {
global $db, $err; global $db;
$db->query("SELECT * FROM slaveaccount WHERE login='$login' AND pass='$pass';"); $db->query("SELECT * FROM slaveaccount WHERE login='$login' AND pass='$pass';");
if ($db->next_record()) { if ($db->next_record()) {
return true; return true;
@ -1665,7 +1666,7 @@ class m_dom {
/** Out (echo) the complete hosted domain list : /** Out (echo) the complete hosted domain list :
*/ */
function echo_domain_list($integrity = false) { function echo_domain_list($integrity = false) {
global $db, $err; global $db;
$db->query("SELECT domaine FROM domaines WHERE gesdns=1 ORDER BY domaine"); $db->query("SELECT domaine FROM domaines WHERE gesdns=1 ORDER BY domaine");
$tt = ""; $tt = "";
while ($db->next_record()) { while ($db->next_record()) {
@ -1684,7 +1685,7 @@ class m_dom {
/** Returns the complete hosted domain list : /** Returns the complete hosted domain list :
*/ */
function get_domain_list($uid = -1) { function get_domain_list($uid = -1) {
global $db, $err; global $db;
$uid = intval($uid); $uid = intval($uid);
$res = array(); $res = array();
$sql = ""; $sql = "";
@ -1703,7 +1704,7 @@ class m_dom {
* @return array * @return array
*/ */
function get_domain_all_summary() { function get_domain_all_summary() {
global $db, $err; global $db;
$res = array(); $res = array();
$db->query("SELECT domaine, gesdns, gesmx, dns_action, zonettl FROM domaines ORDER BY domaine"); $db->query("SELECT domaine, gesdns, gesmx, dns_action, zonettl FROM domaines ORDER BY domaine");
while ($db->next_record()) { while ($db->next_record()) {
@ -1770,7 +1771,7 @@ class m_dom {
/** Count all domains, for all users /** Count all domains, for all users
*/ */
function count_domains_all() { function count_domains_all() {
global $db, $err, $cuid; global $db;
$db->query("SELECT COUNT(*) AS count FROM domaines;"); $db->query("SELECT COUNT(*) AS count FROM domaines;");
if ($db->next_record()) { if ($db->next_record()) {
return $db->f('count'); return $db->f('count');
@ -1784,14 +1785,15 @@ class m_dom {
/** Return the list of allowed slave accounts /** Return the list of allowed slave accounts
*/ */
function enum_slave_account() { function enum_slave_account() {
global $db, $err; global $db;
$db->query("SELECT * FROM slaveaccount;"); $db->query("SELECT * FROM slaveaccount;");
$res = array(); $res = array();
while ($db->next_record()) { while ($db->next_record()) {
$res[] = $db->Record; $res[] = $db->Record;
} }
if (!count($res)) if (!count($res)) {
return false; return false;
}
return $res; return $res;
} }
@ -1831,7 +1833,7 @@ class m_dom {
* @access private * @access private
*/ */
function lock() { function lock() {
global $db, $err; global $err;
$err->log("dom", "lock"); $err->log("dom", "lock");
if ($this->islocked) { if ($this->islocked) {
$err->raise("dom", _("--- Program error --- Lock already obtained!")); $err->raise("dom", _("--- Program error --- Lock already obtained!"));
@ -1850,7 +1852,7 @@ class m_dom {
* @access private * @access private
*/ */
function unlock() { function unlock() {
global $db, $err; global $err;
$err->log("dom", "unlock"); $err->log("dom", "unlock");
if (!$this->islocked) { if (!$this->islocked) {
$err->raise("dom", _("--- Program error --- No lock on the domains!")); $err->raise("dom", _("--- Program error --- No lock on the domains!"));
@ -1914,10 +1916,10 @@ class m_dom {
* No parameters needed * No parameters needed
* */ * */
function alternc_export_conf() { function alternc_export_conf() {
global $db, $err; global $err;
$err->log("dom", "export"); $err->log("dom", "export");
$this->enum_domains(); $this->enum_domains();
$str=""; $str = "";
foreach ($this->domains as $d) { foreach ($this->domains as $d) {
$str.= " <domaines>\n"; $str.= " <domaines>\n";
$str.=" <nom>" . $d . "</nom>\n"; $str.=" <nom>" . $d . "</nom>\n";
@ -1975,6 +1977,7 @@ class m_dom {
if ($only_apache) { if ($only_apache) {
$params.=" and dt.only_dns is false "; $params.=" and dt.only_dns is false ";
} }
// BUG BUG BUG FIXME // BUG BUG BUG FIXME
// Suppression de comptes -> membres existe pas -> domaines a supprimer ne sont pas lister // Suppression de comptes -> membres existe pas -> domaines a supprimer ne sont pas lister
$db->query(" $db->query("
@ -2017,8 +2020,9 @@ order by
global $dom; global $dom;
$d = array(); $d = array();
foreach ($dom->domains_type_lst() as $k => $v) { foreach ($dom->domains_type_lst() as $k => $v) {
if ($v['only_dns'] == true) if ($v['only_dns'] == true) {
continue; continue;
}
if (!$j = file_get_contents(ALTERNC_APACHE2_GEN_TMPL_DIR . '/' . strtolower($k) . '.conf')) { if (!$j = file_get_contents(ALTERNC_APACHE2_GEN_TMPL_DIR . '/' . strtolower($k) . '.conf')) {
die("Error: missing file for $k"); die("Error: missing file for $k");
} }
@ -2030,9 +2034,9 @@ order by
// Launch old fashionned hooks as there was in AlternC 1.0 // Launch old fashionned hooks as there was in AlternC 1.0
function generate_conf_oldhook($action, $lst_sub, $sub_obj = null) { function generate_conf_oldhook($action, $lst_sub, $sub_obj = null) {
if (is_null($sub_obj)) if (is_null($sub_obj)) {
$sub_obj = $this->generation_parameters(null, false); $sub_obj = $this->generation_parameters(null, false);
}
if (!isset($lst_sub[strtoupper($action)]) || empty($lst_sub[strtoupper($action)])) { if (!isset($lst_sub[strtoupper($action)]) || empty($lst_sub[strtoupper($action)])) {
return false; return false;
} }
@ -2173,12 +2177,14 @@ order by
// by subdomain // by subdomain
$tmp = array(); $tmp = array();
foreach ($da['sub'] as $sub) { foreach ($da['sub'] as $sub) {
if ($sub['web_action']!='OK') continue; if ($sub['web_action'] != 'OK') {
continue;
}
if (!$sub['only_dns']) { if (!$sub['only_dns']) {
if (!isset($tmp[$sub['fqdn']])) { if (!isset($tmp[$sub['fqdn']])) {
$tmp[$sub['fqdn']] = 0; $tmp[$sub['fqdn']] = 0;
} }
$tmp[$sub['fqdn']]++; $tmp[$sub['fqdn']] ++;
if ($tmp[$sub['fqdn']] >= 2) { if ($tmp[$sub['fqdn']] >= 2) {
$errors[$sub['fqdn']] = sprintf(_("Problem on %s: there is more than 1 web configuration going to be generated for this sub-domain."), $sub['fqdn']); $errors[$sub['fqdn']] = sprintf(_("Problem on %s: there is more than 1 web configuration going to be generated for this sub-domain."), $sub['fqdn']);
} }

View File

@ -1,142 +1,144 @@
<?php <?php
/* /*
$Id: m_err.php,v 1.4 2004/05/19 14:23:06 benjamin Exp $ $Id: m_err.php,v 1.4 2004/05/19 14:23:06 benjamin Exp $
---------------------------------------------------------------------- ----------------------------------------------------------------------
LICENSE LICENSE
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License (GPL) modify it under the terms of the GNU General Public License (GPL)
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
To read the license please visit http://www.gnu.org/copyleft/gpl.html
----------------------------------------------------------------------
Original Author of file: Benjamin Sonntag, Franck Missoum
----------------------------------------------------------------------
*/
To read the license please visit http://www.gnu.org/copyleft/gpl.html
----------------------------------------------------------------------
Original Author of file: Benjamin Sonntag, Franck Missoum
----------------------------------------------------------------------
*/
/** /**
* Classe de gestion des erreurs apparaissant lors d'appels API. * Classe de gestion des erreurs apparaissant lors d'appels API.
* *
* <p>Cette classe gère les erreurs qui peuvent apparaitre lors d'appels * <p>Cette classe gère les erreurs qui peuvent apparaitre lors d'appels
* à l'API d'AlternC. Ces erreurs sont stockées sous la forme de 2 nombres * à l'API d'AlternC. Ces erreurs sont stockées sous la forme de 2 nombres
* (Classe ID et Numéro d'erreur) ainsi qu'un texte facultatif associé. * (Classe ID et Numéro d'erreur) ainsi qu'un texte facultatif associé.
* Des textes d'erreurs localisés sont aussi disponibles.</p> * Des textes d'erreurs localisés sont aussi disponibles.</p>
* <p>Cette classe se charge aussi d'insérer les appels à l'API d'AlternC * <p>Cette classe se charge aussi d'insérer les appels à l'API d'AlternC
* dans les logs du système dans /var/log/alternc/bureau.log * dans les logs du système dans /var/log/alternc/bureau.log
* </p> * </p>
* Copyleft {@link http://alternc.net/ AlternC Team} * Copyleft {@link http://alternc.net/ AlternC Team}
* *
* @copyright AlternC-Team 2002-11-01 http://alternc.net/ * @copyright AlternC-Team 2002-11-01 http://alternc.net/
*/ */
class m_err { class m_err {
/** Numero de classe d'erreur actuelle */ /** Numero de classe d'erreur actuelle */
var $clsid=0; var $clsid = 0;
/** Dernière erreur enregistrée par la classe */ /** Dernière erreur enregistrée par la classe */
var $error=0; var $error = 0;
/** Paramètre chaine eventuellement associé à la dernière erreur */ /** Paramètre chaine eventuellement associé à la dernière erreur */
var $param=""; var $param = "";
/** Emplacement du fichier de logs d'AlternC */ /** Emplacement du fichier de logs d'AlternC */
var $logfile="/var/log/alternc/bureau.log"; var $logfile = "/var/log/alternc/bureau.log";
/** /**
* Leve une erreur, signale celle-ci dans les logs et stocke le code erreur * Leve une erreur, signale celle-ci dans les logs et stocke le code erreur
* *
* Cette fonction lance une erreur, l'ajoute dans les logs d'AlternC, * Cette fonction lance une erreur, l'ajoute dans les logs d'AlternC,
* et la met à disposition pour le bureau virtuel pour affichage ultérieur. * et la met à disposition pour le bureau virtuel pour affichage ultérieur.
* *
* @todo ne plus utiliser $error de façon numérique, nulle part * @todo ne plus utiliser $error de façon numérique, nulle part
* *
* @param integer $clsid Classe qui lève l'erreur * @param integer $clsid Classe qui lève l'erreur
* @param mixed $error Numéro de l'erreur ou chaîne décrivant l'erreur * @param mixed $error Numéro de l'erreur ou chaîne décrivant l'erreur
* @param string $param Paramètre chaine associé à l'erreur (facultatif) * @param string $param Paramètre chaine associé à l'erreur (facultatif)
* @return boolean TRUE si l'erreur est connue, FALSE sinon. * @return boolean TRUE si l'erreur est connue, FALSE sinon.
* *
*/ */
function raise($clsid,$error,$param="") { function raise($clsid, $error, $param = "") {
/* Leve une exception. Si elle existe, sinon, stocke un message d'erreur sur erreur ...*/ /* Leve une exception. Si elle existe, sinon, stocke un message d'erreur sur erreur ... */
if (_("err_".$clsid."_".$error)!="err_".$clsid."_".$error || is_string($error)) { if (_("err_" . $clsid . "_" . $error) != "err_" . $clsid . "_" . $error || is_string($error)) {
$this->clsid=$clsid; $this->clsid = $clsid;
$this->error=$error; $this->error = $error;
$args = func_get_args(); $args = func_get_args();
$this->param=array_slice($args, 2); $this->param = array_slice($args, 2);
$this->logerr(); $this->logerr();
return true; return true;
} else { } else {
$this->clsid="err"; $this->clsid = "err";
$this->error=1; $this->error = 1;
$this->param="Error # $error in Class $clsid, Value is $param. (sorry, no text for this error in your language at the moment)"; $this->param = "Error # $error in Class $clsid, Value is $param. (sorry, no text for this error in your language at the moment)";
$this->logerr(); $this->logerr();
return false; return false;
}
} }
}
/** /**
* Retourne la chaine d'erreur correspondant à la dernière erreur rencontrée * Retourne la chaine d'erreur correspondant à la dernière erreur rencontrée
* *
* Si la dernière erreur rencontrée est connue, retourne l'erreur en toute lettre * Si la dernière erreur rencontrée est connue, retourne l'erreur en toute lettre
* dans la langue actuellement sélectionnée, ou en anglais par défaut. * dans la langue actuellement sélectionnée, ou en anglais par défaut.
* Si l'erreur n'est pas connue, retourne son numéro de classe et d'ereur. * Si l'erreur n'est pas connue, retourne son numéro de classe et d'ereur.
* *
* @return string Chaine d'erreur. * @return string Chaine d'erreur.
* *
*/ */
function errstr() { function errstr() {
if (is_string($this->error)) { if (is_string($this->error)) {
// new way of handling errors: message directly in the class // new way of handling errors: message directly in the class
$str = $this->error."\n"; $str = $this->error . "\n";
} else { } else {
// old way: message in the locales files (ugly) // old way: message in the locales files (ugly)
$str = _("err_".$this->clsid."_".$this->error)."\n"; $str = _("err_" . $this->clsid . "_" . $this->error) . "\n";
}
$args = $this->param;
if (is_array($args)) {
array_unshift($args, $str);
$msg = call_user_func_array("sprintf", $args);
return $msg;
} else {
return $args;
}
} }
$args = $this->param;
if (is_array($args)) { /**
array_unshift($args, $str); * Envoi un log d'erreur dans /var/log/alternc/bureau.log
$msg = call_user_func_array("sprintf", $args); *
return $msg; * Cette fonction Loggue la dernière erreur dans /var/log sur la machine,
} else { * permettant ainsi aux admins de savoir ce qu'il se passe...
return $args; * Elle est appelée automatiquement par error
* @access private
*/
function logerr() {
global $mem;
@file_put_contents($this->logfile, date("d/m/Y H:i:s") . " - ERROR - " . $mem->user["login"] . " - " . $this->errstr(), FILE_APPEND);
} }
}
/** /**
* Envoi un log d'erreur dans /var/log/alternc/bureau.log * Envoi un log d'appel d'API dans /var/log/alternc/bureau.log
* *
* Cette fonction Loggue la dernière erreur dans /var/log sur la machine, * Cette fonction loggue dans /var/log l'appel à la fonction de l'API
* permettant ainsi aux admins de savoir ce qu'il se passe... * d'AlternC.
* Elle est appelée automatiquement par error *
* @access private * @param integer $clsid Numéro de la classe dont on a appelé une fonction
*/ * @param string $function Nom de la fonction appelée
function logerr() { * @param string $param Paramètre (facultatif) passés à la fonction de l'API.
global $mem; * @return boolean TRUE si le log a été ajouté, FALSE sinon
@file_put_contents($this->logfile, date("d/m/Y H:i:s")." - ERROR - ".$mem->user["login"]." - ".$this->errstr(), FILE_APPEND ); *
} */
function log($clsid, $function, $param = "") {
global $mem;
return @file_put_contents($this->logfile, date("d/m/Y H:i:s") . " - " . get_remote_ip() . " - CALL - " . $mem->user["login"] . " - $clsid - $function - $param\n", FILE_APPEND);
}
/** }
* Envoi un log d'appel d'API dans /var/log/alternc/bureau.log
*
* Cette fonction loggue dans /var/log l'appel à la fonction de l'API
* d'AlternC.
*
* @param integer $clsid Numéro de la classe dont on a appelé une fonction
* @param string $function Nom de la fonction appelée
* @param string $param Paramètre (facultatif) passés à la fonction de l'API.
* @return boolean TRUE si le log a été ajouté, FALSE sinon
*
*/
function log($clsid,$function,$param="") {
global $mem,$cuid;
return @file_put_contents($this->logfile,date("d/m/Y H:i:s")." - " .get_remote_ip(). " - CALL - ".$mem->user["login"]." - $clsid - $function - $param\n", FILE_APPEND );
}
}; /* Classe m_err */ /* Classe m_err */
?>

View File

@ -1,29 +1,35 @@
<?php <?php
/*---------------------------------------------------------------------------*/
/** Constructor /* --------------------------------------------------------------------------- */
Classe d'export de compte Alternc.
Cette classe ce contente d'invoquer les fonctions d'exportation de configuration et de données d'un compte, /** Constructor
presentes dans les classes concernées. Classe d'export de compte Alternc.
*/ Cette classe ce contente d'invoquer les fonctions d'exportation de configuration et de données d'un compte,
presentes dans les classes concernées.
*/
Class m_export { Class m_export {
function m_export() { function m_export() {
} }
function export_conf(){ function export_conf() {
global $hooks; global $hooks;
$config=$hooks->invoke('alternc_export_conf'); $config = $hooks->invoke('alternc_export_conf');
return $config; return $config;
} }
/** le repertoire de base est passé en paramettre puis en construit une arborescence de la forme /** le repertoire de base est passé en paramettre puis en construit une arborescence de la forme
<dir>/<user>/<timestamp/ qui contiendra les dossier de dump html et sql <dir>/<user>/<timestamp/ qui contiendra les dossier de dump html et sql
*/ */
function export_data($dir){ function export_data($dir) {
global $hooks, $mem; global $hooks, $mem;
$hooks->invoke('alternc_export_data', Array($dir)); $hooks->invoke('alternc_export_data', Array($dir));
} }
}// export Class end }
// export Class end

View File

@ -1,4 +1,5 @@
<?php <?php
/* /*
---------------------------------------------------------------------- ----------------------------------------------------------------------
AlternC - Web Hosting System AlternC - Web Hosting System
@ -6,483 +7,512 @@
https://alternc.org/ https://alternc.org/
---------------------------------------------------------------------- ----------------------------------------------------------------------
LICENSE LICENSE
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License (GPL) modify it under the terms of the GNU General Public License (GPL)
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
To read the license please visit http://www.gnu.org/copyleft/gpl.html To read the license please visit http://www.gnu.org/copyleft/gpl.html
---------------------------------------------------------------------- ----------------------------------------------------------------------
Purpose of file: Manage FTP accounts Purpose of file: Manage FTP accounts
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** /**
* Classe de gestion des comptes FTP de l'hébergé. * FTP account management class
*/ */
class m_ftp { class m_ftp {
var $srv_name;
var $srv_name; /* ----------------------------------------------------------------- */
/* ----------------------------------------------------------------- */
/**
* Constructeur
*/
function m_ftp() {
global $L_FQDN;
$this->srv_name = variable_get('ftp_human_name', $L_FQDN,'Human name for FTP server', array('desc'=>'Name','type'=>'string'));
}
/**
/* ----------------------------------------------------------------- */ * Constructeur
/** */
* Password kind used in this class (hook for admin class) function m_ftp() {
*/ global $L_FQDN;
function alternc_password_policy() { $this->srv_name = variable_get('ftp_human_name', $L_FQDN, 'Human name for FTP server', array('desc' => 'Name', 'type' => 'string'));
return array("ftp"=>"FTP accounts");
}
function hook_menu() {
global $quota;
$q = $quota->getquota("ftp");
$obj = array(
'title' => _("FTP accounts"),
'ico' => 'images/ftp.png',
'link' => 'toggle',
'pos' => 60,
'links' => array(),
) ;
if ( $quota->cancreate("ftp") ) {
$obj['links'][] =
array (
'ico' => 'images/new.png',
'txt' => _("Create a new ftp account"),
'url' => "ftp_edit.php?create=1",
'class' => '',
);
}
if ( $q['u'] > 0 ) { // if there are some FTP accounts
$obj['links'][] =
array (
'txt' => _("FTP accounts list"),
'url' => "ftp_list.php"
);
}
return $obj;
}
// Return the values needed to activate security access. See get_auth_class()
// in authip for more informations
function authip_class() {
$c = Array();
$c['name']="FTP";
$c['protocol']="ftp";
$c['values']=Array();
$tt = $this->get_list();
if (empty($tt) || !is_array($tt)) return $c;
foreach ($this->get_list() as $v ) {
$c['values'][$v['id']]=$v['login'];
} }
return $c; /* ----------------------------------------------------------------- */
}
// Switch enabled status of an account /**
function switch_enabled($id,$status=null) { * Password kind used in this class (hook for admin class)
global $cuid, $db, $err; */
if (! $jj = $this->get_ftp_details($id)) { function alternc_password_policy() {
$err->raise('ftp', _("This account do not exist or is not of this account")); return array("ftp" => "FTP accounts");
return false;
}
if ( $status == null ){
if ($jj[0]['enabled'] == true ) { $status=0;}
else { $status=1; }
}
// Be sure what is in $status, in case of it was a parameter
$status = ($status?'true':'false');
if ( ! $db->query("UPDATE ftpusers SET enabled = $status WHERE uid = '$cuid' AND id = '$id' ;") ) {
$err->raise('ftp', _("Error during update"));
return false;
} else {
return true ;
}
}
/* ----------------------------------------------------------------- */
/** Retourne la liste des comptes FTP du compte hébergé
* Retourne la liste des comptes FTP sous forme de tableau indexé de
* tableaus associatifs comme suit :
* $a["id"]= ID du compte ftp
* $a["login"]= Nom de login du compte
* $a["dir"]= Dossier relatif à la racine du compte de l'utilisateur
* @return array Retourne le tableau des comptes
*/
function get_list() {
global $db,$err,$cuid, $bro;
$err->log("ftp","get_list");
$r=array();
$db->query("SELECT id, name, homedir, enabled FROM ftpusers WHERE uid='$cuid' ORDER BY name;");
if ($db->num_rows()) {
while ($db->next_record()) {
$r[]=array(
"id"=>$db->f("id"),
"login"=>$db->f("name"),
"enabled"=>$db->f("enabled"),
//"dir"=>$match[1]
"dir"=>$db->f("homedir")
);
}
return $r;
} else {
$err->raise("ftp",_("No FTP account found"));
return array();
}
}
/* ----------------------------------------------------------------- */
/** Retourne les détails d'un compte FTP (voir get_list)
* Le tableau est celui du compte d'id spécifié
* @param integer $id Numéro du compte dont on souhaite obtenir les détails
* @return array Tableau associatif contenant les infos du comptes ftp
*/
function get_ftp_details($id) {
global $db,$err,$cuid;
$err->log("ftp","get_ftp_details",$id);
$r=array();
$db->query("SELECT id, name, homedir, enabled FROM ftpusers WHERE uid='$cuid' AND id='$id';");
if ($db->num_rows()) {
$db->next_record();
$regexp="/^".preg_quote(getuserpath(),"/")."\/(.*)$/";
preg_match($regexp, $db->f("homedir"),$match);
$lg=explode("_",$db->f("name"));
if ((!is_array($lg)) || (count($lg)!=2)) {
$lg[0]=$db->f("name");
$lg[1]="";
}
$r[]=array(
"id"=>$db->f("id"),
"prefixe"=> $lg[0],
"login"=>$lg[1],
"dir"=>$match[1],
"enabled"=>$db->f("enabled")
);
return $r;
} else {
$err->raise("ftp",_("This FTP account does not exist"));
return false;
}
}
/* ----------------------------------------------------------------- */
/** Retourne la liste des prefixes utilisables par le compte courant
* @return array tableau contenant la liste des prefixes (domaines + login)
* du compte actuel.
*/
function prefix_list() {
global $db,$mem,$cuid;
$r=array();
$r[]=$mem->user["login"];
$db->query("SELECT domaine FROM domaines WHERE compte='$cuid' ORDER BY domaine;");
while ($db->next_record()) {
$r[]=$db->f("domaine");
}
return $r;
}
/**
* Check if the login is fine (syntax)
*
* @param string $l
*/
function check_login($l) {
global $err;
// special chars and the max numbers of them allowed
// to be able to give a specific error
$vv = array('_'=>'1', ' '=>0);
foreach ($vv as $k=>$n) {
if (substr_count($l, $k) > $n ) { // if there is more than $n $k
$err->raise('ftp', sprintf(_("FTP login is incorrect: too many '%s'"), $k));
return false;
}
} }
// Explicitly look for only allowed chars function hook_menu() {
if ( ! preg_match("/^[A-Za-z0-9]+[A-Za-z0-9_\.\-]*$/", $l) ) { global $quota;
$err->raise('ftp', _("FTP login is incorrect")); $q = $quota->getquota("ftp");
return false;
}
return true;
}
/* ----------------------------------------------------------------- */ $obj = array(
/** Affiche (ECHO) la liste des prefixes disponibles sous forme de champs d'option 'title' => _("FTP accounts"),
* Les champs sont affichés sous la forme <option>prefixe</option>... 'ico' => 'images/ftp.png',
* La valeur $current se voit affublée de la balise SELECTED. 'link' => 'toggle',
* @param string $current Prefixe sélectionné par défaut 'pos' => 60,
* @return boolean TRUE. 'links' => array(),
*/ );
function select_prefix_list($current) {
$r=$this->prefix_list();
reset($r);
while (list($key,$val)=each($r)) {
if ($current==$val) $c=" selected=\"selected\""; else $c="";
echo "<option$c>$val</option>";
}
return true;
}
/* ----------------------------------------------------------------- */ if ($quota->cancreate("ftp")) {
/** Modifie les paramètres du comptes FTP $id. $obj['links'][] = array(
* @param integer $id Numéro du compte dont on veut modifier les paramètres 'ico' => 'images/new.png',
* @param string $prefixe Prefixe du compte FTP 'txt' => _("Create a new ftp account"),
* @param string $login login ajouté au préfixe ($prefixe_$login) 'url' => "ftp_edit.php?create=1",
* @param string $pass mot de passe 'class' => '',
* @param string $dir Répertoire racine du compte );
* @return boolean TRUE si le compte a été modifié, FALSE si une erreur est survenue.
*/
function put_ftp_details($id,$prefixe,$login,$pass,$dir) {
global $mem,$db,$err,$bro,$cuid,$admin;
$err->log("ftp","put_ftp_details",$id);
$db->query("SELECT count(*) AS cnt FROM ftpusers WHERE id='$id' and uid='$cuid';");
$db->next_record();
if (!$db->f("cnt")) {
$err->raise("ftp",_("This FTP account does not exist"));
return false;
}
$dir=$bro->convertabsolute($dir);
if (substr($dir,0,1)=="/") {
$dir=substr($dir,1);
}
$r=$this->prefix_list();
if (!in_array($prefixe,$r)) {
$err->raise("ftp",_("The chosen prefix is not allowed"));
return false;
}
$full_login=$prefixe;
if ($login) $full_login.="_".$login;
if (! $this->check_login($full_login) ) return false;
$db->query("SELECT COUNT(*) AS cnt FROM ftpusers WHERE id!='$id' AND name='$full_login';");
$db->next_record();
if ($db->f("cnt")) {
$err->raise("ftp",_("This FTP account already exists"));
return false;
}
$absolute=getuserpath()."/$dir";
if (!file_exists($absolute)) {
system("/bin/mkdir -p $absolute");
}
if (!is_dir($absolute)) {
$err->raise("ftp",_("The directory cannot be created"));
return false;
}
if (trim($pass)) {
// Check this password against the password policy using common API :
if (is_callable(array($admin,"checkPolicy"))) {
if (!$admin->checkPolicy("ftp",$full_login,$pass)) {
return false; // The error has been raised by checkPolicy()
} }
}
$encrypted_password = _md5cr($pass,strrev(microtime(true)));
$db->query("UPDATE ftpusers SET name='".$full_login."', password='', encrypted_password='$encrypted_password', homedir='$absolute', uid='$cuid' WHERE id='$id';");
} else {
$db->query("UPDATE ftpusers SET name='".$full_login."', homedir='$absolute', uid='$cuid' WHERE id='$id';");
}
return true;
}
if ($q['u'] > 0) { // if there are some FTP accounts
$obj['links'][] = array(
'txt' => _("FTP accounts list"),
'url' => "ftp_list.php"
);
}
/* ----------------------------------------------------------------- */ return $obj;
/** Efface le compte ftp spécifié.
* @param integer $id Numéro du compte FTP à supprimer.
* @return boolean TRUE si le compte a été effacé, FALSE sinon.
*/
function delete_ftp($id) {
global $db,$err,$cuid;
$err->log("ftp","delete_ftp",$id);
$db->query("SELECT name FROM ftpusers WHERE id='$id' and uid='$cuid';");
$db->next_record();
$name=$db->f("name");
if (!$name) {
$err->raise("ftp",_("This FTP account does not exist"));
return false;
}
$db->query("DELETE FROM ftpusers WHERE id='$id'");
return $name;
}
/* ----------------------------------------------------------------- */
/** Crée un nouveau compte FTP.
* @param string $prefixe Prefixe au login
* @param string $login Login ftp (login=prefixe_login)
* @param string $pass Mot de passe FTP
* @param string $dir Répertoire racine du compte relatif à la racine du membre
* @return boolean TRUE si le compte a été créé, FALSE sinon.
*
*/
function add_ftp($prefixe,$login,$pass,$dir) {
global $mem,$db,$err,$quota,$bro,$cuid,$admin;
$err->log("ftp","add_ftp",$prefixe."_".$login);
$dir=$bro->convertabsolute($dir);
if (substr($dir,0,1)=="/") {
$dir=substr($dir,1);
}
$r=$this->prefix_list();
if (empty($pass)) {
$err->raise("ftp",_("Password can't be empty"));
return false;
}
if (!in_array($prefixe,$r) || $prefixe=="") {
$err->raise("ftp",_("The chosen prefix is not allowed"));
return false;
}
$full_login=$prefixe;
if ($login) $full_login.="_".$login;
if ( !$this->check_login($full_login) ) return false;
$db->query("SELECT count(*) AS cnt FROM ftpusers WHERE name='".$full_login."'");
$db->next_record();
if ($db->f("cnt")) {
$err->raise("ftp",_("This FTP account already exists"));
return false;
}
$db->query("SELECT login FROM membres WHERE uid='$cuid';");
$db->next_record();
$absolute=getuserpath()."/$dir";
if (!file_exists($absolute)) {
system("/bin/mkdir -p $absolute"); // FIXME replace with action
}
if (!is_dir($absolute)) {
$err->raise("ftp",_("The directory cannot be created"));
return false;
} }
// Check this password against the password policy using common API : // Return the values needed to activate security access. See get_auth_class()
if (is_callable(array($admin,"checkPolicy"))) { // in authip for more informations
if (!$admin->checkPolicy("ftp",$full_login,$pass)) { function authip_class() {
return false; // The error has been raised by checkPolicy() $c = Array();
} $c['name'] = "FTP";
$c['protocol'] = "ftp";
$c['values'] = Array();
$tt = $this->get_list();
if (empty($tt) || !is_array($tt)) {
return $c;
}
foreach ($this->get_list() as $v) {
$c['values'][$v['id']] = $v['login'];
}
return $c;
} }
if ($quota->cancreate("ftp")) { // Switch enabled status of an account
$encrypted_password = _md5cr($pass,strrev(microtime(true))); function switch_enabled($id, $status = null) {
$db->query("INSERT INTO ftpusers (name,password, encrypted_password,homedir,uid) VALUES ('".$full_login."', '', '$encrypted_password', '$absolute', '$cuid')"); global $cuid, $db, $err;
return true; if (!$jj = $this->get_ftp_details($id)) {
} else { $err->raise('ftp', _("This account do not exist or is not of this account"));
$err->raise("ftp",_("Your FTP account quota is over. You cannot create more ftp accounts")); return false;
return false; }
if ($status == null) {
if ($jj[0]['enabled'] == true) {
$status = 0;
} else {
$status = 1;
}
}
// Be sure what is in $status, in case of it was a parameter
$status = ($status ? 'true' : 'false');
if (!$db->query("UPDATE ftpusers SET enabled = $status WHERE uid = '$cuid' AND id = '$id' ;")) {
$err->raise('ftp', _("Error during update"));
return false;
} else {
return true;
}
} }
}
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
/** Retourne TRUE si $dir possède un compte FTP
* @param string $dir Dossier à tester, relatif à la racine du compte courant /** Retourne la liste des comptes FTP du compte h<EFBFBD>berg<EFBFBD>
* @return boolean retourne TRUE si $dir à un compte FTP, FALSE sinon. * Retourne la liste des comptes FTP sous forme de tableau index<EFBFBD> de
*/ * tableaus associatifs comme suit :
function is_ftp($dir) { * $a["id"]= ID du compte ftp
global $mem,$db,$err; * $a["login"]= Nom de login du compte
$err->log("ftp","is_ftp",$dir); * $a["dir"]= Dossier relatif <EFBFBD> la racine du compte de l'utilisateur
if (substr($dir,0,1)=="/") $dir=substr($dir,1); * @return array Retourne le tableau des comptes
$db->query("SELECT id FROM ftpusers WHERE homedir='".getuserpath()."/$dir';"); */
if ($db->num_rows()) { function get_list() {
$db->next_record(); global $db, $err, $cuid;
return $db->f("id"); $err->log("ftp", "get_list");
} else { $r = array();
return false; $db->query("SELECT id, name, homedir, enabled FROM ftpusers WHERE uid='$cuid' ORDER BY name;");
if ($db->num_rows()) {
while ($db->next_record()) {
$r[] = array(
"id" => $db->f("id"),
"login" => $db->f("name"),
"enabled" => $db->f("enabled"),
//"dir"=>$match[1]
"dir" => $db->f("homedir")
);
}
return $r;
} else {
$err->raise("ftp", _("No FTP account found"));
return array();
}
} }
}
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
/** Fonction appellée par domains quand un domaine est supprimé pour le membre
* @param string $dom Domaine à détruire.
* @access private
*/
function alternc_del_domain($dom) {
global $db,$err,$cuid;
$err->log("ftp","alternc_del_domain",$dom);
$db->query("DELETE FROM ftpusers WHERE uid='$cuid' AND ( name LIKE '$dom\_%' OR name LIKE '$dom') ");
return true;
}
/* ----------------------------------------------------------------- */ /** Retourne les details d'un compte FTP (voir get_list)
/** Fonction appellée par membres quand un membre est effacé. * Le tableau est celui du compte d'id specifie
* @access private * @param integer $id Numero du compte dont on souhaite obtenir les d<EFBFBD>tails
*/ * @return array Tableau associatif contenant les infos du comptes ftp
function alternc_del_member() { */
global $db,$err,$cuid; function get_ftp_details($id) {
$err->log("ftp","alternc_del_member"); global $db, $err, $cuid;
$db->query("DELETE FROM ftpusers WHERE uid='$cuid'"); $err->log("ftp", "get_ftp_details", $id);
return true; $r = array();
} $db->query("SELECT id, name, homedir, enabled FROM ftpusers WHERE uid='$cuid' AND id='$id';");
if ($db->num_rows()) {
$db->next_record();
/* ----------------------------------------------------------------- */ $regexp = "/^" . preg_quote(getuserpath(), "/") . "\/(.*)$/";
/** $match = array();
* Returns the used quota for the $name service for the current user. preg_match($regexp, $db->f("homedir"), $match);
* @param $name string name of the quota
* @return integer the number of service used or false if an error occured $lg = explode("_", $db->f("name"));
* @access private if ((!is_array($lg)) || (count($lg) != 2)) {
*/ $lg[0] = $db->f("name");
function hook_quota_get() { $lg[1] = "";
global $db,$err,$cuid; }
$err->log("ftp","getquota"); $r[] = array(
$q=Array("name"=>"ftp", "description"=>_("FTP accounts"), "used"=>0); "id" => $db->f("id"),
$db->query("SELECT COUNT(*) AS cnt FROM ftpusers WHERE uid='$cuid'"); "prefixe" => $lg[0],
if ($db->next_record()) { "login" => $lg[1],
$q['used']=$db->f("cnt"); "dir" => $match[1],
"enabled" => $db->f("enabled")
);
return $r;
} else {
$err->raise("ftp", _("This FTP account does not exist"));
return false;
}
} }
return $q;
}
/* ----------------------------------------------------------------- */
/* ----------------------------------------------------------------- */ /** Retourne la liste des prefixes utilisables par le compte courant
/** * @return array tableau contenant la liste des prefixes (domaines + login)
* Exporte toutes les informations ftp du compte AlternC * du compte actuel.
* @access private */
* EXPERIMENTAL 'sid' function ;) function prefix_list() {
*/ global $db, $mem, $cuid;
function alternc_export_conf() { $r = array();
global $db,$err; $r[] = $mem->user["login"];
$err->log("ftp","export"); $db->query("SELECT domaine FROM domaines WHERE compte='$cuid' ORDER BY domaine;");
$f=$this->get_list(); while ($db->next_record()) {
$str=" <ftp>"; $r[] = $db->f("domaine");
foreach ($f as $d=>$v) { }
$str.=" <login>".($v["login"])."</login>\n"; return $r;
$str.=" <password>".($v["encrypted_password"])."</password>\n";
$str.=" <directory>".($v["dir"])."<directory>\n";
} }
$str.=" </ftp>\n";
return $str;
}
/**
* Check if the login is fine (syntax)
*
* @param string $l
*/
function check_login($l) {
global $err;
/* ----------------------------------------------------------------- */ // special chars and the max numbers of them allowed
/** hook function called by AlternC-upnp to know which open // to be able to give a specific error
* tcp or udp ports this class requires or suggests $vv = array('_' => '1', ' ' => 0);
* @return array a key => value list of port protocol name mandatory values foreach ($vv as $k => $n) {
* @access private if (substr_count($l, $k) > $n) { // if there is more than $n $k
*/ $err->raise('ftp', sprintf(_("FTP login is incorrect: too many '%s'"), $k));
function hook_upnp_list() { return false;
return array( }
"ftp" => array("port" => 21, "protocol" => "tcp", "mandatory" => 1), }
);
}
} /* Class m_ftp */
// Explicitly look for only allowed chars
if (!preg_match("/^[A-Za-z0-9]+[A-Za-z0-9_\.\-]*$/", $l)) {
$err->raise('ftp', _("FTP login is incorrect"));
return false;
}
return true;
}
/* ----------------------------------------------------------------- */
/** Affiche (ECHO) la liste des prefixes disponibles sous forme de champs d'option
* Les champs sont affich<EFBFBD>s sous la forme <option>prefixe</option>...
* La valeur $current se voit affubl<EFBFBD>e de la balise SELECTED.
* @param string $current Prefixe s<EFBFBD>lectionn<EFBFBD> par d<EFBFBD>faut
* @return boolean TRUE.
*/
function select_prefix_list($current) {
$r = $this->prefix_list();
reset($r);
while (list($key, $val) = each($r)) {
if ($current == $val) {
$c = " selected=\"selected\"";
} else {
$c = "";
}
echo "<option$c>$val</option>";
}
return true;
}
/* ----------------------------------------------------------------- */
/** Modifie les param<EFBFBD>tres du comptes FTP $id.
* @param integer $id Num<EFBFBD>ro du compte dont on veut modifier les param<EFBFBD>tres
* @param string $prefixe Prefixe du compte FTP
* @param string $login login ajout<EFBFBD> au pr<EFBFBD>fixe ($prefixe_$login)
* @param string $pass mot de passe
* @param string $dir R<EFBFBD>pertoire racine du compte
* @return boolean TRUE si le compte a <EFBFBD>t<EFBFBD> modifi<EFBFBD>, FALSE si une erreur est survenue.
*/
function put_ftp_details($id, $prefixe, $login, $pass, $dir) {
global $db, $err, $bro, $cuid, $admin;
$err->log("ftp", "put_ftp_details", $id);
$db->query("SELECT count(*) AS cnt FROM ftpusers WHERE id='$id' and uid='$cuid';");
$db->next_record();
if (!$db->f("cnt")) {
$err->raise("ftp", _("This FTP account does not exist"));
return false;
}
$dir = $bro->convertabsolute($dir);
if (substr($dir, 0, 1) == "/") {
$dir = substr($dir, 1);
}
$r = $this->prefix_list();
if (!in_array($prefixe, $r)) {
$err->raise("ftp", _("The chosen prefix is not allowed"));
return false;
}
$full_login = $prefixe;
if ($login) {
$full_login.="_" . $login;
}
if (!$this->check_login($full_login)) {
return false;
}
$db->query("SELECT COUNT(*) AS cnt FROM ftpusers WHERE id!='$id' AND name='$full_login';");
$db->next_record();
if ($db->f("cnt")) {
$err->raise("ftp", _("This FTP account already exists"));
return false;
}
$absolute = getuserpath() . "/$dir";
if (!file_exists($absolute)) {
system("/bin/mkdir -p $absolute");
}
if (!is_dir($absolute)) {
$err->raise("ftp", _("The directory cannot be created"));
return false;
}
if (trim($pass)) {
// Check this password against the password policy using common API :
if (is_callable(array($admin, "checkPolicy"))) {
if (!$admin->checkPolicy("ftp", $full_login, $pass)) {
return false; // The error has been raised by checkPolicy()
}
}
$encrypted_password = _md5cr($pass, strrev(microtime(true)));
$db->query("UPDATE ftpusers SET name='" . $full_login . "', password='', encrypted_password='$encrypted_password', homedir='$absolute', uid='$cuid' WHERE id='$id';");
} else {
$db->query("UPDATE ftpusers SET name='" . $full_login . "', homedir='$absolute', uid='$cuid' WHERE id='$id';");
}
return true;
}
/* ----------------------------------------------------------------- */
/** Efface le compte ftp specifie
* @param integer $id Numero du compte FTP a supprimer.
* @return boolean TRUE si le compte a ete efface, FALSE sinon.
*/
function delete_ftp($id) {
global $db, $err, $cuid;
$err->log("ftp", "delete_ftp", $id);
$db->query("SELECT name FROM ftpusers WHERE id='$id' and uid='$cuid';");
$db->next_record();
$name = $db->f("name");
if (!$name) {
$err->raise("ftp", _("This FTP account does not exist"));
return false;
}
$db->query("DELETE FROM ftpusers WHERE id='$id'");
return $name;
}
/* ----------------------------------------------------------------- */
/** Cree un nouveau compte FTP.
* @param string $prefixe Prefixe au login
* @param string $login Login ftp (login=prefixe_login)
* @param string $pass Mot de passe FTP
* @param string $dir Repertoire racine du compte relatif à la racine du membre
* @return boolean TRUE si le compte a ete cree, FALSE sinon.
*
*/
function add_ftp($prefixe, $login, $pass, $dir) {
global $db, $err, $quota, $bro, $cuid, $admin;
$err->log("ftp", "add_ftp", $prefixe . "_" . $login);
$dir = $bro->convertabsolute($dir);
if (substr($dir, 0, 1) == "/") {
$dir = substr($dir, 1);
}
$r = $this->prefix_list();
if (empty($pass)) {
$err->raise("ftp", _("Password can't be empty"));
return false;
}
if (!in_array($prefixe, $r) || $prefixe == "") {
$err->raise("ftp", _("The chosen prefix is not allowed"));
return false;
}
$full_login = $prefixe;
if ($login) {
$full_login.="_" . $login;
}
if (!$this->check_login($full_login)) {
return false;
}
$db->query("SELECT count(*) AS cnt FROM ftpusers WHERE name='" . $full_login . "'");
$db->next_record();
if ($db->f("cnt")) {
$err->raise("ftp", _("This FTP account already exists"));
return false;
}
$db->query("SELECT login FROM membres WHERE uid='$cuid';");
$db->next_record();
$absolute = getuserpath() . "/$dir";
if (!file_exists($absolute)) {
system("/bin/mkdir -p $absolute"); // FIXME replace with action
}
if (!is_dir($absolute)) {
$err->raise("ftp", _("The directory cannot be created"));
return false;
}
// Check this password against the password policy using common API :
if (is_callable(array($admin, "checkPolicy"))) {
if (!$admin->checkPolicy("ftp", $full_login, $pass)) {
return false; // The error has been raised by checkPolicy()
}
}
if ($quota->cancreate("ftp")) {
$encrypted_password = _md5cr($pass, strrev(microtime(true)));
$db->query("INSERT INTO ftpusers (name,password, encrypted_password,homedir,uid) VALUES ('" . $full_login . "', '', '$encrypted_password', '$absolute', '$cuid')");
return true;
} else {
$err->raise("ftp", _("Your FTP account quota is over. You cannot create more ftp accounts"));
return false;
}
}
/* ----------------------------------------------------------------- */
/** Retourne TRUE si $dir possee un compte FTP
* @param string $dir Dossier a tester, relatif a la racine du compte courant
* @return boolean retourne TRUE si $dir a un compte FTP, FALSE sinon.
*/
function is_ftp($dir) {
global $db, $err;
$err->log("ftp", "is_ftp", $dir);
if (substr($dir, 0, 1) == "/") {
$dir = substr($dir, 1);
}
$db->query("SELECT id FROM ftpusers WHERE homedir='" . getuserpath() . "/$dir';");
if ($db->num_rows()) {
$db->next_record();
return $db->f("id");
} else {
return false;
}
}
/* ----------------------------------------------------------------- */
/** Fonction appellee par domains quand un domaine est supprime pour le membre
* @param string $dom Domaine à detruire.
* @access private
*/
function alternc_del_domain($dom) {
global $db, $err, $cuid;
$err->log("ftp", "alternc_del_domain", $dom);
$db->query("DELETE FROM ftpusers WHERE uid='$cuid' AND ( name LIKE '$dom\_%' OR name LIKE '$dom') ");
return true;
}
/* ----------------------------------------------------------------- */
/** Fonction appellee par membres quand un membre est efface
* @access private
*/
function alternc_del_member() {
global $db, $err, $cuid;
$err->log("ftp", "alternc_del_member");
$db->query("DELETE FROM ftpusers WHERE uid='$cuid'");
return true;
}
/* ----------------------------------------------------------------- */
/**
* Returns the used quota for the $name service for the current user.
* @param $name string name of the quota
* @return integer the number of service used or false if an error occured
* @access private
*/
function hook_quota_get() {
global $db, $err, $cuid;
$err->log("ftp", "getquota");
$q = Array("name" => "ftp", "description" => _("FTP accounts"), "used" => 0);
$db->query("SELECT COUNT(*) AS cnt FROM ftpusers WHERE uid='$cuid'");
if ($db->next_record()) {
$q['used'] = $db->f("cnt");
}
return $q;
}
/* ----------------------------------------------------------------- */
/**
* Exporte toutes les informations ftp du compte AlternC
* @access private
* EXPERIMENTAL 'sid' function ;)
*/
function alternc_export_conf() {
global $db, $err;
$err->log("ftp", "export");
$f = $this->get_list();
$str = " <ftp>";
foreach ($f as $d => $v) {
$str.=" <login>" . ($v["login"]) . "</login>\n";
$str.=" <password>" . ($v["encrypted_password"]) . "</password>\n";
$str.=" <directory>" . ($v["dir"]) . "<directory>\n";
}
$str.=" </ftp>\n";
return $str;
}
/* ----------------------------------------------------------------- */
/** hook function called by AlternC-upnp to know which open
* tcp or udp ports this class requires or suggests
* @return array a key => value list of port protocol name mandatory values
* @access private
*/
function hook_upnp_list() {
return array(
"ftp" => array("port" => 21, "protocol" => "tcp", "mandatory" => 1),
);
}
}
/* Class m_ftp */

View File

@ -1,4 +1,5 @@
<?php <?php
/* /*
---------------------------------------------------------------------- ----------------------------------------------------------------------
AlternC - Web Hosting System AlternC - Web Hosting System
@ -21,7 +22,7 @@
---------------------------------------------------------------------- ----------------------------------------------------------------------
Purpose of file: Manage hook system. Purpose of file: Manage hook system.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** /**
* This class manage hooks. * This class manage hooks.
@ -29,91 +30,96 @@
* @copyright AlternC-Team 2002-2005 http://alternc.org/ * @copyright AlternC-Team 2002-2005 http://alternc.org/
*/ */
class m_hooks { class m_hooks {
/* --------------------------------------------------------------------------- */
/*---------------------------------------------------------------------------*/ /** Constructor
/** Constructor * hooks([$mid]) Constructeur de la classe hooks, ne fait rien pour le moment
* hooks([$mid]) Constructeur de la classe hooks, ne fait rien pour le moment */
*/ function m_hooks() {
function m_hooks() {
}
/*---------------------------------------------------------------------------*/
/**
* invoke() permet de lancer une fonction donné en parametre dans toute les classes
* connues de alternc, avec les parametres donnés.
* @param string $hname nom de la fonction "hooks" que l'on cherche dans les classes
* @param array $hparam tableau contenant les parametres
* @param array|string $hclass tableau contenant les classes spécifique qu'on veux appeler (si on veux pas TOUTE les appeler)
* @return array with the return of each classes
*/
function invoke($hname, $hparam = array(), $hclass = null) {
// Si $hclass est defini, on veut appeler le hooks QUE pour UNE
// classe et pas pour toute.
if (is_null($hclass)) {
global $classes;
} else {
if (is_array($hclass)) {
$classes = $hclass;
} else {
$classes = array($hclass);
}
} }
// On parcourt les classes, si la fonction qu'on cherche /* --------------------------------------------------------------------------- */
// existe on l'execute et on rajoute ce qu'elle a retourné dans
// un tableau
$val = array();
foreach ($classes as $c) {
global $$c;
if ( method_exists($$c, $hname) ) {
//$val[$$c]=call_user_func_array(array($$c,$hname), $hparam);
$val[$c]=call_user_func_array(array($$c,$hname), $hparam);
}
}
// On retourne le tout /**
return $val; * invoke() permet de lancer une fonction donné en parametre dans toute les classes
} * connues de alternc, avec les parametres donnés.
* @param string $hname nom de la fonction "hooks" que l'on cherche dans les classes
* @param array $hparam tableau contenant les parametres
* @param array|string $hclass tableau contenant les classes spécifique qu'on veux appeler (si on veux pas TOUTE les appeler)
* @return array with the return of each classes
*/
function invoke($hname, $hparam = array(), $hclass = null) {
/*---------------------------------------------------------------------------*/ // Si $hclass est defini, on veut appeler le hooks QUE pour UNE
/** // classe et pas pour toute.
* invoke each executable script of the directory (or the specified script) if (is_null($hclass)) {
* @param string $scripts a script or a directory global $classes;
* @param array $parameters parameters for the scripts } else {
* @return boolean TRUE if (is_array($hclass)) {
*/ $classes = $hclass;
function invoke_scripts($scripts, $parameters=array()) { } else {
$classes = array($hclass);
// First, build the list of script we want to launch }
$to_launch=array();
if (is_file($scripts)) {
if (is_executable($scripts)) {
$to_launch[]=$scripts;
}
} else if (is_dir($scripts)) {
foreach ( scandir($scripts) as $ccc ) {
if (is_file($ccc) && is_executable($ccc)) {
$to_launch[]=$ccc;
} }
}
} else {
// not a file nor a directory
return false;
}
// Protect each parameters
$parameters = array_map('escapeshellarg', $parameters);
$params = implode(" ", $parameters);
// Launch ! // On parcourt les classes, si la fonction qu'on cherche
foreach($to_launch as $fi) { // existe on l'execute et on rajoute ce qu'elle a retourné dans
system($fi." ".$params); // un tableau
$val = array();
foreach ($classes as $c) {
global $$c;
if (method_exists($$c, $hname)) {
//$val[$$c]=call_user_func_array(array($$c,$hname), $hparam);
$val[$c] = call_user_func_array(array($$c, $hname), $hparam);
}
}
// On retourne le tout
return $val;
} }
// TODO: return something more interesting than true /* --------------------------------------------------------------------------- */
return true;
}
} /* Class hooks */ /**
* invoke each executable script of the directory (or the specified script)
* @param string $scripts a script or a directory
* @param array $parameters parameters for the scripts
* @return boolean TRUE
*/
function invoke_scripts($scripts, $parameters = array()) {
// First, build the list of script we want to launch
$to_launch = array();
if (is_file($scripts)) {
if (is_executable($scripts)) {
$to_launch[] = $scripts;
}
} else if (is_dir($scripts)) {
foreach (scandir($scripts) as $ccc) {
if (is_file($ccc) && is_executable($ccc)) {
$to_launch[] = $ccc;
}
}
} else {
// not a file nor a directory
return false;
}
// Protect each parameters
$parameters = array_map('escapeshellarg', $parameters);
$params = implode(" ", $parameters);
// Launch !
foreach ($to_launch as $fi) {
system($fi . " " . $params);
}
// TODO: return something more interesting than true
return true;
}
}
/* Class hooks */

View File

@ -1,482 +1,463 @@
<?php <?php
/* /*
$Id: m_hta.php,v 1.5 2004/11/29 17:15:37 anonymous Exp $ $Id: m_hta.php,v 1.5 2004/11/29 17:15:37 anonymous Exp $
---------------------------------------------------------------------- ----------------------------------------------------------------------
AlternC - Web Hosting System AlternC - Web Hosting System
Copyright (C) 2002 by the AlternC Development Team. Copyright (C) 2002 by the AlternC Development Team.
http://alternc.org/ http://alternc.org/
---------------------------------------------------------------------- ----------------------------------------------------------------------
Based on: Based on:
Valentin Lacambre's web hosting softwares: http://altern.org/ Valentin Lacambre's web hosting softwares: http://altern.org/
---------------------------------------------------------------------- ----------------------------------------------------------------------
LICENSE LICENSE
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License (GPL) modify it under the terms of the GNU General Public License (GPL)
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
To read the license please visit http://www.gnu.org/copyleft/gpl.html To read the license please visit http://www.gnu.org/copyleft/gpl.html
---------------------------------------------------------------------- ----------------------------------------------------------------------
Original Author of file: Original Author of file:
Purpose of file: Purpose of file:
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** /**
* This class handle folder web restricted access through .htaccess/.htpassword * This class handle folder web restricted access through .htaccess/.htpassword
* files. * files.
* *
* Copyleft {@link http://alternc.net/ AlternC Team} * Copyleft {@link http://alternc.net/ AlternC Team}
* *
* @copyright AlternC-Team 2002-11-01 http://alternc.org/ * @copyright AlternC-Team 2002-11-01 http://alternc.org/
* *
*/ */
class m_hta { class m_hta {
/**
/** * Constructor
* Constructor */
*/ function m_webaccess() {
function m_webaccess() {
} }
/**
* Password kind used in this class (hook for admin class)
*
* @return array
*/
function alternc_password_policy() {
return array("hta"=>"Protected folders passwords");
}
/**
*
* @return array
*/
function hook_menu() {
$obj = array(
'title' => _("Protected folders"),
'ico' => 'images/password.png',
'link' => 'hta_list.php',
'pos' => 50,
) ;
return $obj;
}
/** /**
* Create a protected folder (.htaccess et .htpasswd) * Password kind used in this class (hook for admin class)
* @param string $dir Folder to protect (relative to user root) *
* @return boolean TRUE if the folder has been protected, or FALSE if an error occurred * @return array
* */
* @global m_mem $mem function alternc_password_policy() {
* @global m_bro $bro return array("hta" => "Protected folders passwords");
* @global m_err $err
* @param string $dir
* @return boolean
*/
function CreateDir($dir) {
global $mem,$bro,$err;
$err->log("hta","createdir",$dir);
$absolute = $bro->convertabsolute($dir,0);
if (!$absolute) {
$err->raise("hta",printf(_("The folder '%s' does not exist"),$dir));
return false;
} }
if (!file_exists($absolute)) {
@mkdir($absolute,00777);
}
if (!file_exists("$absolute/.htaccess")) {
if (!@touch("$absolute/.htaccess")) {
$err->raise("hta",_("File already exist"));
return false;
}
$file = @fopen("$absolute/.htaccess","r+");
if (!$file) {
$err->raise("hta",_("File already exist"));
return false;
}
fseek($file,0);
$param = "AuthUserFile \"$absolute/.htpasswd\"\nAuthName \""._("Restricted area")."\"\nAuthType Basic\nrequire valid-user\n";
fwrite($file, $param);
fclose($file);
}
if (!file_exists("$absolute/.htpasswd")) {
if (!touch("$absolute/.htpasswd")) {
$err->raise("hta",_("File already exist"));
return false;
}
return true;
}
return true;
}
/** /**
* Returns the list of all user folder currently protected by a .htpasswd file *
* * @return array
* @global m_err $err */
* @global m_mem $mem function hook_menu() {
* @return array Array containing user folder list $obj = array(
*/ 'title' => _("Protected folders"),
function ListDir(){ 'ico' => 'images/password.png',
global$err,$mem; 'link' => 'hta_list.php',
$err->log("hta","listdir"); 'pos' => 50,
$sortie = array(); );
$absolute = ALTERNC_HTML."/".substr($mem->user["login"],0,1)."/".$mem->user["login"];
exec("find ".escapeshellarg($absolute)." -name .htpasswd|sort",$sortie); return $obj;
if(!count($sortie)){
$err->raise("hta",_("No protected folder"));
return false;
} }
$pattern = "/^".preg_quote(ALTERNC_HTML,"/")."\/.\/[^\/]*\/(.*)\/\.htpasswd/";
$r = array();
for($i = 0;$i<count($sortie);$i++){
preg_match($pattern,$sortie[$i],$matches);
$tmpm = isset($matches[1])?'/'.$matches[1]:'';
$r[$i] = $tmpm."/";
}
return $r;
}
/** /**
* Tells if a folder is protected. * Create a protected folder (.htaccess et .htpasswd)
* * @param string $dir Folder to protect (relative to user root)
* @global m_mem $mem * @return boolean TRUE if the folder has been protected, or FALSE if an error occurred
* @global m_err $err *
* @param string $dir Folder to check * @global m_mem $mem
* @return boolean If the folder is protected, or FALSE if it is not * @global m_bro $bro
*/ * @global m_err $err
function is_protected($dir){ * @param string $dir
global $mem,$err; * @return boolean
$err->log("hta","is_protected",$dir); */
$absolute = ALTERNC_HTML."/".substr($mem->user["login"],0,1)."/".$mem->user["login"]."/$dir"; function CreateDir($dir) {
if (file_exists("$absolute/.htpasswd")){ global $bro, $err;
return true; $err->log("hta", "createdir", $dir);
} else { $absolute = $bro->convertabsolute($dir, 0);
return false; if (!$absolute) {
$err->raise("hta", printf(_("The folder '%s' does not exist"), $dir));
return false;
}
if (!file_exists($absolute)) {
@mkdir($absolute, 00777);
}
if (!file_exists("$absolute/.htaccess")) {
if (!@touch("$absolute/.htaccess")) {
$err->raise("hta", _("File already exist"));
return false;
}
$file = @fopen("$absolute/.htaccess", "r+");
if (!$file) {
$err->raise("hta", _("File already exist"));
return false;
}
fseek($file, 0);
$param = "AuthUserFile \"$absolute/.htpasswd\"\nAuthName \"" . _("Restricted area") . "\"\nAuthType Basic\nrequire valid-user\n";
fwrite($file, $param);
fclose($file);
}
if (!file_exists("$absolute/.htpasswd")) {
if (!touch("$absolute/.htpasswd")) {
$err->raise("hta", _("File already exist"));
return false;
}
return true;
}
return true;
} }
}
/** /**
* Returns the list of login for a protected folder. * Returns the list of all user folder currently protected by a .htpasswd file
* *
* @global m_mem $mem * @global m_err $err
* @global m_err $err * @global m_mem $mem
* @param string $dir The folder to lookup (relative to user root) * @return array Array containing user folder list
* @return array An array containing the list of logins from the .htpasswd file, or FALSE */
*/ function ListDir() {
function get_hta_detail($dir) { global$err, $mem;
global $mem,$err; $err->log("hta", "listdir");
$err->log("hta","get_hta_detail"); $sortie = array();
$absolute = ALTERNC_HTML."/".substr($mem->user["login"],0,1)."/".$mem->user["login"]."/$dir"; $absolute = ALTERNC_HTML . "/" . substr($mem->user["login"], 0, 1) . "/" . $mem->user["login"];
if (file_exists("$absolute/.htaccess")) { exec("find " . escapeshellarg($absolute) . " -name .htpasswd|sort", $sortie);
/* if (!_reading_htaccess($absolute)) { if (!count($sortie)) {
return false; $err->raise("hta", _("No protected folder"));
} return false;
*/ } }
$file = @fopen("$absolute/.htpasswd","r"); $pattern = "/^" . preg_quote(ALTERNC_HTML, "/") . "\/.\/[^\/]*\/(.*)\/\.htpasswd/";
$i = 0;
$res = array();
if (!$file) {
return false;
}
// TODO: Tester la validité du .htpasswd
while (!feof($file)) {
$s = fgets($file,1024);
$t = explode(":",$s);
if ($t[0]!=$s) {
$res[$i] = $t[0];
$i = $i+1;
}
}
fclose($file);
return $res;
}
$r = array();
for ($i = 0; $i < count($sortie); $i++) {
$matches = array();
preg_match($pattern, $sortie[$i], $matches);
$tmpm = isset($matches[1]) ? '/' . $matches[1] : '';
$r[$i] = $tmpm . "/";
}
return $r;
}
/** /**
* Unprotect a folder * Tells if a folder is protected.
* *
* @global m_mem $mem * @global m_mem $mem
* @global m_bro $bro * @global m_err $err
* @global m_err $err * @param string $dir Folder to check
* @param string $dir Folder to unprotect, relative to user root * @return boolean If the folder is protected, or FALSE if it is not
* @param boolean $skip For testing purpose mainly, skips the full user path search */
* @return boolean TRUE if the folder has been unprotected, or FALSE if an error occurred function is_protected($dir) {
*/ global $mem, $err;
function DelDir($dir,$skip = false) { $err->log("hta", "is_protected", $dir);
global $mem,$bro,$err; $absolute = ALTERNC_HTML . "/" . substr($mem->user["login"], 0, 1) . "/" . $mem->user["login"] . "/$dir";
$err->log("hta","deldir",$dir); if (file_exists("$absolute/.htpasswd")) {
$dir = $bro->convertabsolute($dir,$skip); return true;
if (!$dir) { } else {
$err->raise("hta",printf(("The folder '%s' does not exist"),$dir)); return false;
return false; }
} }
$htaccess_file = "$dir/.htaccess";
if( !is_readable($htaccess_file)){ /**
$err->raise("hta",printf(_("I cannot read the file '%s'"),$htaccess_file)); * Returns the list of login for a protected folder.
} *
$fileLines = file($htaccess_file); * @global m_mem $mem
$patternList = array( * @global m_err $err
"AuthUserFile.*$", * @param string $dir The folder to lookup (relative to user root)
"AuthName.*$", * @return array An array containing the list of logins from the .htpasswd file, or FALSE
"AuthType Basic.*$", */
"require valid-user.*$" function get_hta_detail($dir) {
); global $mem, $err;
$count_lines = 0; $err->log("hta", "get_hta_detail");
foreach($fileLines as $key => $line){ $absolute = ALTERNC_HTML . "/" . substr($mem->user["login"], 0, 1) . "/" . $mem->user["login"] . "/$dir";
foreach ($patternList as $pattern) { if (file_exists("$absolute/.htaccess")) {
if(preg_match("/".$pattern."/", $line)){ /* if (!_reading_htaccess($absolute)) {
$count_lines++; return false;
unset($fileLines[$key]); }
*/
}
$file = @fopen("$absolute/.htpasswd", "r");
$i = 0;
$res = array();
if (!$file) {
return false;
}
// TODO: Tester la validité du .htpasswd
while (!feof($file)) {
$s = fgets($file, 1024);
$t = explode(":", $s);
if ($t[0] != $s) {
$res[$i] = $t[0];
$i = $i + 1;
} }
} }
fclose($file);
return $res;
} }
// If no changes
if( ! $count_lines ){ /**
$err->raise("hta",printf(_("Unexpected: No changes made to '%s'"),$htaccess_file)); * Unprotect a folder
} *
// If file is empty, remove it * @global m_mem $mem
if( !count($fileLines)){ * @global m_bro $bro
if( ! unlink( $htaccess_file)){ * @global m_err $err
$err->raise("hta",printf(_("I could not delete the file '%s'"),$htaccess_file)); * @param string $dir Folder to unprotect, relative to user root
* @param boolean $skip For testing purpose mainly, skips the full user path search
* @return boolean TRUE if the folder has been unprotected, or FALSE if an error occurred
*/
function DelDir($dir, $skip = false) {
global $bro, $err;
$err->log("hta", "deldir", $dir);
$dir = $bro->convertabsolute($dir, $skip);
if (!$dir) {
$err->raise("hta", printf(("The folder '%s' does not exist"), $dir));
return false;
}
$htaccess_file = "$dir/.htaccess";
if (!is_readable($htaccess_file)) {
$err->raise("hta", printf(_("I cannot read the file '%s'"), $htaccess_file));
}
$fileLines = file($htaccess_file);
$patternList = array(
"AuthUserFile.*$",
"AuthName.*$",
"AuthType Basic.*$",
"require valid-user.*$"
);
$count_lines = 0;
foreach ($fileLines as $key => $line) {
foreach ($patternList as $pattern) {
if (preg_match("/" . $pattern . "/", $line)) {
$count_lines++;
unset($fileLines[$key]);
}
}
}
// If no changes
if (!$count_lines) {
$err->raise("hta", printf(_("Unexpected: No changes made to '%s'"), $htaccess_file));
}
// If file is empty, remove it
if (!count($fileLines)) {
if (!unlink($htaccess_file)) {
$err->raise("hta", printf(_("I could not delete the file '%s'"), $htaccess_file));
}
} else {
file_put_contents($htaccess_file, implode("\n", $fileLines));
}
$htpasswd_file = "$dir/.htpasswd";
if (!is_writable($htpasswd_file)) {
$err->raise("hta", printf(_("I cannot read the file '%s'"), $htpasswd_file));
} else if (!unlink($htpasswd_file)) {
$err->raise("hta", printf(_("I cannot delete the file '%s/.htpasswd'"), $dir));
return false;
} }
}else{
file_put_contents($htaccess_file, implode("\n",$fileLines));
}
$htpasswd_file = "$dir/.htpasswd";
if( ! is_writable($htpasswd_file)){
$err->raise("hta",printf(_("I cannot read the file '%s'"),$htpasswd_file));
}
else if ( ! unlink($htpasswd_file)) {
$err->raise("hta",printf(_("I cannot delete the file '%s/.htpasswd'"),$dir));
return false;
}
return true;
}
return true;
}
/** /**
* Add a user to a protected folder * Add a user to a protected folder
* *
* @global m_err $err * @global m_err $err
* @global m_bro $bro * @global m_bro $bro
* @global m_admin $admin * @global m_admin $admin
* @param string $user * @param string $user
* @param string $password * @param string $password
* @param string $dir * @param string $dir
* @param string $password The password to add (cleartext) * @param string $password The password to add (cleartext)
* @param string $dir The folder we add it to (relative to user root). * @param string $dir The folder we add it to (relative to user root).
* @return boolean TRUE if the user has been added, or FALSE if an error occurred * @return boolean TRUE if the user has been added, or FALSE if an error occurred
*/ */
function add_user($user,$password,$dir) { function add_user($user, $password, $dir) {
global $err, $bro, $admin; global $err, $bro, $admin;
$err->log("hta","add_user",$user."/".$dir); $err->log("hta", "add_user", $user . "/" . $dir);
if (empty($user)) { if (empty($user)) {
$err->raise('hta',_("Please enter a user")); $err->raise('hta', _("Please enter a user"));
return false; return false;
} }
if (empty($password)) { if (empty($password)) {
$err->raise('hta',_("Please enter a password")); $err->raise('hta', _("Please enter a password"));
return false; return false;
} }
$absolute = $bro->convertabsolute($dir,0); $absolute = $bro->convertabsolute($dir, 0);
if (!file_exists($absolute)) { if (!file_exists($absolute)) {
$err->raise("hta",printf(("The folder '%s' does not exist"),$dir)); $err->raise("hta", printf(("The folder '%s' does not exist"), $dir));
return false; return false;
} }
// @todo delete cf!. functions.php checkloginemail definition // @todo delete cf!. functions.php checkloginemail definition
if (checkloginmail($user)){ if (checkloginmail($user)) {
// Check this password against the password policy using common API : // Check this password against the password policy using common API :
if (is_callable(array($admin,"checkPolicy"))) { if (is_callable(array($admin, "checkPolicy"))) {
if (!$admin->checkPolicy("hta",$user,$password)) { if (!$admin->checkPolicy("hta", $user, $password)) {
return false; // The error has been raised by checkPolicy() return false; // The error has been raised by checkPolicy()
} }
} }
$file = @fopen("$absolute/.htpasswd","a+"); $file = @fopen("$absolute/.htpasswd", "a+");
if (!$file) { if (!$file) {
$err->raise("hta",_("File already exist")); $err->raise("hta", _("File already exist"));
return false; return false;
} }
fseek($file,0); fseek($file, 0);
while (!feof($file)) { while (!feof($file)) {
$s = fgets($file,1024); $s = fgets($file, 1024);
$t = explode(":",$s); $t = explode(":", $s);
if ($t[0]==$user) { if ($t[0] == $user) {
$err->raise("hta",_("The user '%s' already exist for this folder"),$user); $err->raise("hta", _("The user '%s' already exist for this folder"), $user);
return false; return false;
} }
} }
fseek($file,SEEK_END); fseek($file, SEEK_END);
if ( empty($t[1]) || substr($t[1],-1)!="\n") { if (empty($t[1]) || substr($t[1], -1) != "\n") {
fwrite($file,"\n"); fwrite($file, "\n");
} }
fwrite($file, "$user:"._md5cr($password)."\n"); fwrite($file, "$user:" . _md5cr($password) . "\n");
fclose($file); fclose($file);
return true; return true;
} else { } else {
$err->raise("hta",_("Please enter a valid username")); $err->raise("hta", _("Please enter a valid username"));
return false; return false;
}
} }
}
/** /**
*/ * Delete a user from a protected folder.
/** *
* Delete a user from a protected folder. * @global m_bro $bro
* * @global m_err $err
* @global m_bro $bro * @param array $lst An array with login to delete.
* @global m_err $err * @param string $dir The folder, relative to user root, where we want to delete users.
* @param array $lst An array with login to delete. * @return boolean TRUE if users has been deleted, or FALSE if an error occurred.
* @param string $dir The folder, relative to user root, where we want to delete users. */
* @return boolean TRUE if users has been deleted, or FALSE if an error occurred. function del_user($lst, $dir) {
*/ global $bro, $err;
function del_user($lst,$dir) { $err->log("hta", "del_user", $lst . "/" . $dir);
global $bro,$err; $absolute = $bro->convertabsolute($dir, 0);
$err->log("hta","del_user",$lst."/".$dir); if (!file_exists($absolute)) {
$absolute = $bro->convertabsolute($dir,0); $err->raise("hta", printf(_("The folder '%s' does not exist"), $dir));
if (!file_exists($absolute)) { return false;
$err->raise("hta",printf(_("The folder '%s' does not exist"),$dir)); }
return false; touch("$absolute/.htpasswd.new");
$file = fopen("$absolute/.htpasswd", "r");
$newf = fopen("$absolute/.htpasswd.new", "a");
if (!$file || !$newf) {
$err->raise("hta", _("File already exist"));
return false;
}
reset($lst);
fseek($file, 0);
while (!feof($file)) {
$s = fgets($file, 1024);
$t = explode(":", $s);
if (!in_array($t[0], $lst) && ($t[0] != "\n")) {
fseek($newf, 0);
fwrite($newf, "$s");
}
}
fclose($file);
fclose($newf);
unlink("$absolute/.htpasswd");
rename("$absolute/.htpasswd.new", "$absolute/.htpasswd");
return true;
} }
touch("$absolute/.htpasswd.new");
$file = fopen("$absolute/.htpasswd","r");
$newf = fopen("$absolute/.htpasswd.new","a");
if (!$file || !$newf) {
$err->raise("hta",_("File already exist"));
return false;
}
reset($lst);
fseek($file,0);
while (!feof($file)) {
$s = fgets($file,1024);
$t = explode(":",$s);
if (!in_array($t[0],$lst) && ($t[0]!="\n")) {
fseek($newf,0);
fwrite($newf, "$s");
}
}
fclose($file);
fclose($newf);
unlink("$absolute/.htpasswd");
rename("$absolute/.htpasswd.new", "$absolute/.htpasswd");
return true;
}
/** /**
* @param string $user The users whose password should be changed * Change the password of a user in a protected folder
* @param string $newpass The new password of this user * @param string $user The users whose password should be changed
* @param string $dir The folder, relative to user root, in which we will change a password * @param string $newpass The new password of this user
* @return boolean TRUE if the password has been changed, or FALSE if an error occurred * @param string $dir The folder, relative to user root, in which we will change a password
*/ * @return boolean TRUE if the password has been changed, or FALSE if an error occurred
/** */
* Change the password of a user in a protected folder function change_pass($user, $newpass, $dir) {
* global $bro, $err, $admin;
* @global m_bro $bro $err->log("hta", "change_pass", $user . "/" . $dir);
* @global m_err $err $absolute = $bro->convertabsolute($dir, 0);
* @global m_admin $admin if (!file_exists($absolute)) {
* @param string $user $err->raise("hta", printf(_("The folder '%s' does not exist"), $dir));
* @param string $newpass return false;
* @param string $dir }
* @return boolean
*/
function change_pass($user,$newpass,$dir) {
global $bro,$err,$admin;
$err->log("hta","change_pass",$user."/".$dir);
$absolute = $bro->convertabsolute($dir,0);
if (!file_exists($absolute)) {
$err->raise("hta",printf(_("The folder '%s' does not exist"),$dir));
return false;
}
// Check this password against the password policy using common API : // Check this password against the password policy using common API :
if (is_callable(array($admin,"checkPolicy"))) { if (is_callable(array($admin, "checkPolicy"))) {
if (!$admin->checkPolicy("hta",$user,$newpass)) { if (!$admin->checkPolicy("hta", $user, $newpass)) {
return false; // The error has been raised by checkPolicy() return false; // The error has been raised by checkPolicy()
} }
} }
touch("$absolute/.htpasswd.new"); touch("$absolute/.htpasswd.new");
$file = fopen("$absolute/.htpasswd","r"); $file = fopen("$absolute/.htpasswd", "r");
$newf = fopen("$absolute/.htpasswd.new","a"); $newf = fopen("$absolute/.htpasswd.new", "a");
if (!$file || !$newf) { if (!$file || !$newf) {
$err->raise("hta",_("File already exist")); $err->raise("hta", _("File already exist"));
return false; return false;
}
while (!feof($file)) {
$s = fgets($file, 1024);
$t = explode(":", $s);
if ($t[0] != $user) {
fwrite($newf, "$s");
}
}
fwrite($newf, "$user:" . _md5cr($newpass) . "\n");
fclose($file);
fclose($newf);
unlink("$absolute/.htpasswd");
rename("$absolute/.htpasswd.new", "$absolute/.htpasswd");
return true;
} }
while (!feof($file)) {
$s = fgets($file,1024);
$t = explode(":",$s);
if ($t[0]!=$user) {
fwrite($newf, "$s");
}
}
fwrite($newf, "$user:"._md5cr($newpass)."\n");
fclose($file);
fclose($newf);
unlink("$absolute/.htpasswd");
rename("$absolute/.htpasswd.new", "$absolute/.htpasswd");
return true;
}
/** /**
* Check that a .htaccess file is valid (for authentication) * Check that a .htaccess file is valid (for authentication)
* *
* @global m_err $err * @global m_err $err
* @param type $absolute * @param type $absolute
* @param string $absolute Folder we want to check (relative to user root) * @param string $absolute Folder we want to check (relative to user root)
* @return boolean TRUE is the .htaccess is protecting this folder, or FALSE else * @return boolean TRUE is the .htaccess is protecting this folder, or FALSE else
*/ */
private function _reading_htaccess($absolute) { private function _reading_htaccess($absolute) {
global $err; global $err;
$err->log("hta","_reading_htaccess",$absolute); $err->log("hta", "_reading_htaccess", $absolute);
$file = fopen("$absolute/.htaccess","r+"); $file = fopen("$absolute/.htaccess", "r+");
$lignes = array(1,1,1); $lignes = array(1, 1, 1);
$errr = 0; $errr = 0;
if (!$file) { if (!$file) {
return false; return false;
}
while (!feof($file) && !$errr) {
$s = fgets($file, 1024);
if (substr($s, 0, 12) != "RewriteCond " && substr($s, 0, 14) != "ErrorDocument " && substr($s, 0, 12) != "RewriteRule " && substr($s, 0, 14) != "RewriteEngine " && trim($s) != "") {
$errr = 1;
}
if (strtolower(trim($s)) == strtolower("authuserfile $absolute/.htpasswd")) {
$lignes[0] = 0;
$errr = 0;
} // authuserfile
if (strtolower(trim($s)) == "require valid-user") {
$lignes[1] = 0;
$errr = 0;
} //require
if (strtolower(trim($s)) == "authtype basic") {
$lignes[2] = 0;
$errr = 0;
} //authtype
} // Reading config file
fclose($file);
if ($errr || in_array(0, $lignes)) {
$err->raise("hta", _("An incompatible .htaccess file exists in this folder"));
return false;
}
return true;
} }
while (!feof($file) && !$errr) {
$s = fgets($file,1024);
if (substr($s,0,12)!="RewriteCond " && substr($s,0,14)!="ErrorDocument " && substr($s,0,12)!="RewriteRule " && substr($s,0,14)!="RewriteEngine " && trim($s)!="") {
$errr = 1;
}
if (strtolower(trim($s))==strtolower("authuserfile $absolute/.htpasswd")) {
$lignes[0] = 0;
$errr = 0;
} // authuserfile
if (strtolower(trim($s))=="require valid-user") {
$lignes[1] = 0;
$errr = 0;
} //require
if (strtolower(trim($s))=="authtype basic") {
$lignes[2] = 0;
$errr = 0;
} //authtype
} // Reading config file
fclose($file);
if ($errr || in_array(0,$lignes)) {
$err->raise("hta",_("An incompatible .htaccess file exists in this folder"));
return false;
}
return true;
}
} /* CLASS m_hta */
}
/* CLASS m_hta */

View File

@ -1,4 +1,5 @@
<?php <?php
/* /*
---------------------------------------------------------------------- ----------------------------------------------------------------------
AlternC - Web Hosting System AlternC - Web Hosting System
@ -6,117 +7,118 @@
https://alternc.org/ https://alternc.org/
---------------------------------------------------------------------- ----------------------------------------------------------------------
LICENSE LICENSE
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License (GPL) modify it under the terms of the GNU General Public License (GPL)
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
To read the license please visit http://www.gnu.org/copyleft/gpl.html To read the license please visit http://www.gnu.org/copyleft/gpl.html
---------------------------------------------------------------------- ----------------------------------------------------------------------
Purpose of file: Manage Log files for users Purpose of file: Manage Log files for users
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** /**
* Classe de gestion des erreurs apparaissant lors d'appels API. * Classe de gestion des erreurs apparaissant lors d'appels API.
*/ */
class m_log { class m_log {
function m_log(){ function m_log() {
}
function list_logs_directory($dir){
global $cuid,$err;
$err->log("log","list_logs_directory");
$c=array();
foreach( glob("${dir}/*log*") as $absfile) {
$c[]=array("name"=>basename($absfile),
"creation_date"=>date("F d Y H:i:s", filectime($absfile)),
"mtime" => filemtime($absfile),
"filesize"=>filesize($absfile),
"downlink"=>urlencode(basename($absfile)),
);
} }
usort($c,"m_log::compare_logtime");
return $c;
}//list_logs function list_logs_directory($dir) {
global $cuid, $err;
$err->log("log", "list_logs_directory");
// Used by list_logs_directory to sort $c = array();
private function compare_logname($a, $b) { foreach (glob("${dir}/*log*") as $absfile) {
return strcmp($a['name'],$b['name']); $c[] = array("name" => basename($absfile),
} "creation_date" => date("F d Y H:i:s", filectime($absfile)),
"mtime" => filemtime($absfile),
// Used by list_logs_directory to sort "filesize" => filesize($absfile),
private function compare_logtime($a, $b) { "downlink" => urlencode(basename($absfile)),
return $b['mtime']-$a['mtime']; );
} }
usort($c, "m_log::compare_logtime");
return $c;
function hook_menu() {
$obj = array(
'title' => _("Logs"),
'ico' => 'images/logs.png',
'link' => 'logs_list.php',
'pos' => 130,
) ;
return $obj;
}
function list_logs_directory_all($dirs){
global $err;
$err->log("log","get_logs_directory_all");
$c=array();
foreach($dirs as $dir=>$val){
$c[$dir]=$this->list_logs_directory($val);
} }
return $c;
} // Used by list_logs_directory to sort
private function compare_logname($a, $b) {
function get_logs_directory(){ return strcmp($a['name'], $b['name']);
global $cuid,$mem,$err;
$err->log("log","get_logs_directory");
// Return an array to allow multiple directory in the future
if(defined('ALTERNC_LOGS_ARCHIVE')){
$c=array("dir"=>ALTERNC_LOGS_ARCHIVE."/".$cuid."-".$mem->user["login"]);
}else{
$c=array("dir"=>ALTERNC_LOGS."/".$cuid."-".$mem->user["login"]);
} }
return $c;
}
function download_link($file){
global $err,$mem;
$err->log("log","download_link");
header("Content-Disposition: attachment; filename=".$file."");
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: binary");
$f=$this->get_logs_directory();
$ff=$f['dir']."/".basename($file);
set_time_limit(0);
readfile($ff);
}
function tail($file,$lines=20) { // Used by list_logs_directory to sort
global $err,$mem; private function compare_logtime($a, $b) {
$err->log("log","tail"); return $b['mtime'] - $a['mtime'];
$lines=intval($lines); if ($lines<=0) $lines=20; }
$f=$this->get_logs_directory();
$ff=$f['dir']."/".basename($file);
unset($out);
exec("tail -".$lines." ".escapeshellarg($ff),$out);
return implode("\n",$out);
}
function hook_menu() {
$obj = array(
'title' => _("Logs"),
'ico' => 'images/logs.png',
'link' => 'logs_list.php',
'pos' => 130,
);
} // end class return $obj;
}
function list_logs_directory_all($dirs) {
global $err;
$err->log("log", "get_logs_directory_all");
$c = array();
foreach ($dirs as $dir => $val) {
$c[$dir] = $this->list_logs_directory($val);
}
return $c;
}
function get_logs_directory() {
global $cuid, $mem, $err;
$err->log("log", "get_logs_directory");
// Return an array to allow multiple directory in the future
if (defined('ALTERNC_LOGS_ARCHIVE')) {
$c = array("dir" => ALTERNC_LOGS_ARCHIVE . "/" . $cuid . "-" . $mem->user["login"]);
} else {
$c = array("dir" => ALTERNC_LOGS . "/" . $cuid . "-" . $mem->user["login"]);
}
return $c;
}
function download_link($file) {
global $err;
$err->log("log", "download_link");
header("Content-Disposition: attachment; filename=" . $file . "");
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: binary");
$f = $this->get_logs_directory();
$ff = $f['dir'] . "/" . basename($file);
set_time_limit(0);
readfile($ff);
}
function tail($file, $lines = 20) {
global $err;
$err->log("log", "tail");
$lines = intval($lines);
if ($lines <= 0) {
$lines = 20;
}
$f = $this->get_logs_directory();
$ff = $f['dir'] . "/" . basename($file);
$out=array();
exec("tail -" . $lines . " " . escapeshellarg($ff), $out);
return implode("\n", $out);
}
}
// end class

View File

@ -1,197 +1,192 @@
<?php <?php
/* /*
---------------------------------------------------------------------- ----------------------------------------------------------------------
AlternC - Web Hosting System AlternC - Web Hosting System
Copyright (C) 2000-2013 by the AlternC Development Team. Copyright (C) 2000-2013 by the AlternC Development Team.
https://alternc.org/ https://alternc.org/
---------------------------------------------------------------------- ----------------------------------------------------------------------
LICENSE LICENSE
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License (GPL) modify it under the terms of the GNU General Public License (GPL)
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
To read the license please visit http://www.gnu.org/copyleft/gpl.html To read the license please visit http://www.gnu.org/copyleft/gpl.html
---------------------------------------------------------------------- ----------------------------------------------------------------------
Purpose of file: Manage LXC-based virtual machine through an inetd-based protocol Purpose of file: Manage LXC-based virtual machine through an inetd-based protocol
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
include_once(dirname(__FILE__) . '/vm.class.php'); include_once(dirname(__FILE__) . '/vm.class.php');
/** /**
* Manage AlternC's virtual machine start/stop using our own inetd-based protocol. * Manage AlternC's virtual machine start/stop using our own inetd-based protocol.
*/ */
class m_lxc implements vm { class m_lxc implements vm {
public $IP;
public $KEY;
public $PORT;
public $maxtime;
public $TIMEOUT = 5;
public $error = array();
public $IP; /**
public $KEY; * Constructor, initialize the class informations from AlternC's variables
public $PORT; */
public $maxtime; function m_lxc() {
public $TIMEOUT = 5; $this->IP = variable_get('lxc_ip', '', "IP address of the Alternc's LXC server. If empty, no LXC server.", array('desc' => 'IP address', 'type' => 'ip'));
public $error = array(); $this->PORT = variable_get('lxc_port', '6504', "Port of the Alternc's LXC server", array('desc' => 'Port', 'type' => 'integer'));
$this->KEY = variable_get('lxc_key', '', "Shared key with the Alternc's LXC server", array('desc' => 'Shared key', 'type' => 'string'));
$this->maxtime = variable_get('lxc_maxtime', '4', "How many hours do we allow to have a server before shutting it down", array('desc' => 'Max time', 'type' => 'integer'));
/**
* Constructor, initialize the class informations from AlternC's variables
*/
function m_lxc() {
$this->IP = variable_get('lxc_ip', '', "IP address of the Alternc's LXC server. If empty, no LXC server.", array('desc'=>'IP address','type'=>'ip'));
$this->PORT = variable_get('lxc_port', '6504', "Port of the Alternc's LXC server", array('desc'=>'Port','type'=>'integer'));
$this->KEY = variable_get('lxc_key', '', "Shared key with the Alternc's LXC server", array('desc'=>'Shared key','type'=>'string'));
$this->maxtime = variable_get('lxc_maxtime', '4', "How many hours do we allow to have a server before shutting it down", array('desc'=>'Max time','type'=>'integer'));
}
/**
* HOOK: add the "Console Access" to AlternC's main menu
*/
function hook_menu() {
if ( empty($this->IP)) return ; // No menu if no server
$obj = array(
'title' => _("Console access"),
'ico' => 'images/ssh.png',
'link' => 'vm.php',
'pos' => 95,
) ;
return $obj;
}
/**
* HOOK: remove VM history for AlternC account
*/
function hook_admin_del_member() {
global $db,$err,$cuid;
$err->log("lxc","alternc_del_member");
$db->query("DELETE FROM vm_history WHERE uid='$cuid'");
return true;
}
/**
* Send a message to a remote VM manager instance
* $params are the parameters to send as serialized data
* to the listening server.
* Return the unserialized response data, if the message has been sent successfully
* or FALSE if an error occurred. In that case $error[] is set.
*/
private function sendMessage($params) {
global $L_FQDN,$hooks;
$fp = @fsockopen($this->IP, $this->PORT, $errno, $errstr, $this->TIMEOUT);
if (!$fp) {
$this->error[] = 'Unable to connect';
return FALSE;
}
// Authenticate:
$params['server']=$L_FQDN;
$params['key']=$this->KEY;
// MySQL Host for this user ?
$moreparams=$hooks->invoke("lxc_params",array($params));
foreach($moreparams as $p) {
foreach($p as $k=>$v)
$params[$k]=$v;
} }
$msg = serialize($params); /**
if (fwrite ($fp, $msg."\n") < 0) { * HOOK: add the "Console Access" to AlternC's main menu
$this->error[] = 'Unable to send data'; */
return FALSE; function hook_menu() {
if (empty($this->IP))
return; // No menu if no server
$obj = array(
'title' => _("Console access"),
'ico' => 'images/ssh.png',
'link' => 'vm.php',
'pos' => 95,
);
return $obj;
} }
$resp = fgets($fp, 8192);
fclose ($fp);
$data = @unserialize($resp); /**
* HOOK: remove VM history for AlternC account
if (isset($data['error']) && $data['error']>0) { */
$this->error[] = $data['msg']; function hook_admin_del_member() {
return FALSE; global $db, $err, $cuid;
} else { $err->log("lxc", "alternc_del_member");
return $resp; $db->query("DELETE FROM vm_history WHERE uid='$cuid'");
return true;
} }
}
/**
* Send a message to a remote VM manager instance
* $params are the parameters to send as serialized data
* to the listening server.
* Return the unserialized response data, if the message has been sent successfully
* or FALSE if an error occurred. In that case $error[] is set.
*/
private function sendMessage($params) {
global $L_FQDN, $hooks;
$fp = @fsockopen($this->IP, $this->PORT, $errno, $errstr, $this->TIMEOUT);
if (!$fp) {
$this->error[] = 'Unable to connect';
return FALSE;
}
// Authenticate:
$params['server'] = $L_FQDN;
$params['key'] = $this->KEY;
// MySQL Host for this user ?
$moreparams = $hooks->invoke("lxc_params", array($params));
foreach ($moreparams as $p) {
foreach ($p as $k => $v) {
$params[$k] = $v;
}
}
/** $msg = serialize($params);
* START a Virtual Machine on the remote VM manager if (fwrite($fp, $msg . "\n") < 0) {
* for user $login having hashed password $pass and uid $uid $this->error[] = 'Unable to send data';
*/ return FALSE;
public function start($login = FALSE, $pass = FALSE, $uid = FALSE) { }
global $mem, $db, $err, $mysql; $resp = fgets($fp, 8192);
fclose($fp);
if ($this->getvm() !== FALSE) { $data = @unserialize($resp);
$err->raise('lxc', _('VM already started'));
return FALSE; if (isset($data['error']) && $data['error'] > 0) {
$this->error[] = $data['msg'];
return FALSE;
} else {
return $resp;
}
} }
unset($this->error);
$login = $login ? $login : $mem->user['login']; /**
$pass = $pass ? $pass : $mem->user['pass']; * START a Virtual Machine on the remote VM manager
$uid = $uid ? $uid : $mem->user['uid']; * for user $login having hashed password $pass and uid $uid
*/
public function start($login = FALSE, $pass = FALSE, $uid = FALSE) {
global $mem, $db, $err, $mysql;
$msgg = array('action'=>'start', 'login'=>$login, 'pass' => $pass, 'uid'=> $uid); if ($this->getvm() !== FALSE) {
$msgg['mysql_host'] = $mysql->dbus->Host; $err->raise('lxc', _('VM already started'));
return FALSE;
}
unset($this->error);
$res = $this->sendMessage($msgg); $login = $login ? $login : $mem->user['login'];
if ($res === FALSE) { $pass = $pass ? $pass : $mem->user['pass'];
return $this->error; $uid = $uid ? $uid : $mem->user['uid'];
} else {
$data = unserialize($res);
$error = (int)$data['error'];
$hostname = $data['hostname'];
$msg = $data['msg'];
$date_start = 'NOW()';
$uid = $mem->user['uid'];
if ($error != 0) { $msgg = array('action' => 'start', 'login' => $login, 'pass' => $pass, 'uid' => $uid);
$err->raise('lxc', _($msg)); $msgg['mysql_host'] = $mysql->dbus->Host;
return FALSE;
} $res = $this->sendMessage($msgg);
$db->query("INSERT INTO vm_history (ip,date_start,uid,serialized_object) VALUES ('$hostname', $date_start, '$uid', '$res')"); if ($res === FALSE) {
return $res; return $this->error;
} else {
$data = unserialize($res);
$error = (int) $data['error'];
$hostname = $data['hostname'];
$msg = $data['msg'];
$date_start = 'NOW()';
$uid = $mem->user['uid'];
if ($error != 0) {
$err->raise('lxc', _($msg));
return FALSE;
}
$db->query("INSERT INTO vm_history (ip,date_start,uid,serialized_object) VALUES ('$hostname', $date_start, '$uid', '$res')");
return $res;
}
} }
}
/**
*
*/
public function getvm($login = FALSE) {
global $mem;
/** $login = $login ? $login : $mem->user['login'];
* $msgg = array('action' => 'get', 'login' => $login);
*/ $res = $this->sendMessage($msgg);
public function getvm($login = FALSE) { if (!$res) {
global $db, $mem, $cuid; return FALSE;
}
return unserialize($res);
}
$login = $login ? $login : $mem->user['login']; /**
$msgg = array('action'=>'get', 'login'=>$login); * Stop the currently running VM
$res = $this->sendMessage($msgg); */
if (!$res) return FALSE; public function stop() {
return unserialize($res); $vm = $this->getvm();
} if ($vm === FALSE) {
return FALSE;
}
if ($this->sendMessage(array('action' => 'stop', 'vm' => $vm['vm'])) === FALSE) {
return FALSE;
}
return TRUE;
}
}
/** // class m_lxc
* Stop the currently running VM
*/
public function stop() {
global $db, $mem;
$vm = $this->getvm();
if ($vm === FALSE)
return FALSE;
if ($this->sendMessage(array('action' => 'stop', 'vm' => $vm['vm'])) === FALSE)
return FALSE;
return TRUE;
}
} // class m_lxc

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
<?php <?php
/* /*
---------------------------------------------------------------------- ----------------------------------------------------------------------
AlternC - Web Hosting System AlternC - Web Hosting System
@ -21,7 +22,7 @@
---------------------------------------------------------------------- ----------------------------------------------------------------------
Purpose of file: Manage hook system. Purpose of file: Manage hook system.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** /**
* This class manage menu. * This class manage menu.
@ -29,147 +30,126 @@
* @copyright AlternC-Team 2002-2005 http://alternc.org/ * @copyright AlternC-Team 2002-2005 http://alternc.org/
*/ */
class m_menu { class m_menu {
/* --------------------------------------------------------------------------- */
/*---------------------------------------------------------------------------*/ /** Constructor
/** Constructor * menu([$mid]) Constructeur de la classe menu, ne fait rien pour le moment
* menu([$mid]) Constructeur de la classe menu, ne fait rien pour le moment */
*/ function m_menu() {
function m_menu() {
}
function getmenu() {
global $hooks, $quota, $mem;
// Force rebuilding quota, in case of add or edit of the quota and cache not up-to-date
$mesq = $quota->getquota("",true); // rebuild quota
// Get menu objects
$lsto = $hooks->invoke('hook_menu');
// Get system menu
$sm = $this->system_menu();
// Merge it !
$lst = array_merge($sm,$lsto);
// Sort it
uasort($lst, 'm_menu::order_menu');
// Get user specific menu visibility options
$mop = $mem->session_tempo_params_get('menu_toggle') ;
foreach( $lst as $k => $v ) {
if (empty($v)) {
unset($lst[$k]);
continue;
}
// Set the javascript toggle link for menu asking for it
if ($v['link'] == 'toggle') {
$lst[$k]['link'] = 'javascript:menu_toggle(\'menu-'.$k.'\');';
}
// Be sure that the default visibility is true
if (! isset($lst[$k]['visibility'])) $lst[$k]['visibility'] = true;
// Set the user's specific visibility option
if (isset($mop["menu-$k"])) {
if ($mop["menu-$k"] == "hidden") $lst[$k]['visibility'] = false;
if ($mop["menu-$k"] == "visible") $lst[$k]['visibility'] = true;
}
if ( isset($mesq[$k])) { // if there are some quota for this class
// Hide the menu if there are none and not allowed to create
if ( $mesq[$k]['t'] < 1 && $mesq[$k]['u'] < 1 ) {
unset($lst[$k]);
continue;
}
// Set the quota in the menu object
$lst[$k]['quota_used'] = $mesq[$k]['u'] ;
$lst[$k]['quota_total'] = $mesq[$k]['t'] ;
} // end if there are some quota for this class
} }
return $lst; function getmenu() {
} //getmenu global $hooks, $quota, $mem;
function order_menu($a, $b) { // Force rebuilding quota, in case of add or edit of the quota and cache not up-to-date
// Use to order the menu with a usort $mesq = $quota->getquota("", true); // rebuild quota
return $a['pos'] > $b['pos']; // Get menu objects
} $lsto = $hooks->invoke('hook_menu');
function system_menu() { // Get system menu
// Here some needed menu who don't have a class $sm = $this->system_menu();
global $help_baseurl, $lang_translation, $locales;
$m = // Merge it !
array( $lst = array_merge($sm, $lsto);
'home' =>
array(
'title' => _("Home / Information"),
'ico' => 'images/home.png',
'link' => 'main.php',
'pos' => 0,
),
'logout' =>
array(
'title' => _("Logout"),
'ico' => 'images/exit.png',
'link' => 'mem_logout.php',
'pos' => 170,
),
'help' =>
array(
'title' => _("Online help"),
'ico' => 'images/help.png',
'target' => 'help',
'link' => $help_baseurl,
'pos' => 140,
),
'lang' =>
array(
'title' => _("Languages"),
'ico' => '/images/lang.png',
'visibility' => false,
'link' => 'toggle',
'links' => array(),
'pos' => 150,
)
) ;
foreach($locales as $l) {
$m['lang']['links'][] = array ( 'txt' => (isset($lang_translation[$l]))?$lang_translation[$l]:$l, 'url' => "/login.php?setlang=$l");
}
return $m;
// Sort it
uasort($lst, 'm_menu::order_menu');
/* // Get user specific menu visibility options
$mop = $mem->session_tempo_params_get('menu_toggle');
<div class="menu-box"> foreach ($lst as $k => $v) {
<a href="javascript:menu_toggle('menu-lang');">
<div class="menu-title">
<img src="/images/lang.png" alt="<?php __("Languages"); ?>" />&nbsp;<?php __("Languages"); ?>
<img src="/images/menu_moins.png" alt="" style="float:right;" id="menu-lang-img"/>
</div>
</a>
<div class="menu-content" id="menu-lang">
<ul>
<?php foreach($locales as $l) { ?>
<li><a href="/login.php?setlang=<?php echo $l; ?>" target="_top"><?php if (isset($lang_translation[$l])) echo $lang_translation[$l]; else echo $l; ?></a></li>
<?php } ?>
</ul>
</div>
</div>
if (empty($v)) {
unset($lst[$k]);
continue;
}
// Set the javascript toggle link for menu asking for it
if ($v['link'] == 'toggle') {
$lst[$k]['link'] = 'javascript:menu_toggle(\'menu-' . $k . '\');';
}
// Be sure that the default visibility is true
if (!isset($lst[$k]['visibility'])) {
$lst[$k]['visibility'] = true;
}
// Set the user's specific visibility option
if (isset($mop["menu-$k"])) {
if ($mop["menu-$k"] == "hidden") {
$lst[$k]['visibility'] = false;
}
if ($mop["menu-$k"] == "visible") {
$lst[$k]['visibility'] = true;
}
}
*/ if (isset($mesq[$k])) { // if there are some quota for this class
} //system_menu // Hide the menu if there are none and not allowed to create
if ($mesq[$k]['t'] < 1 && $mesq[$k]['u'] < 1) {
unset($lst[$k]);
continue;
}
} /* Class menu */ // Set the quota in the menu object
$lst[$k]['quota_used'] = $mesq[$k]['u'];
$lst[$k]['quota_total'] = $mesq[$k]['t'];
} // end if there are some quota for this class
}
return $lst;
}
function order_menu($a, $b) {
// Use to order the menu with a usort
return $a['pos'] > $b['pos'];
}
function system_menu() {
// Here some needed menu who don't have a class
global $help_baseurl, $lang_translation, $locales;
$m = array(
'home' =>
array(
'title' => _("Home / Information"),
'ico' => 'images/home.png',
'link' => 'main.php',
'pos' => 0,
),
'logout' =>
array(
'title' => _("Logout"),
'ico' => 'images/exit.png',
'link' => 'mem_logout.php',
'pos' => 170,
),
'help' =>
array(
'title' => _("Online help"),
'ico' => 'images/help.png',
'target' => 'help',
'link' => $help_baseurl,
'pos' => 140,
),
'lang' =>
array(
'title' => _("Languages"),
'ico' => '/images/lang.png',
'visibility' => false,
'link' => 'toggle',
'links' => array(),
'pos' => 150,
)
);
foreach ($locales as $l) {
$m['lang']['links'][] = array('txt' => (isset($lang_translation[$l])) ? $lang_translation[$l] : $l, 'url' => "/login.php?setlang=$l");
}
return $m;
}
}
/* Class menu */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff