2006-04-26 12:28:53 +00:00
< ? php
/*
2012-08-28 08:59:05 +00:00
----------------------------------------------------------------------
AlternC - Web Hosting System
Copyright ( C ) 2000 - 2012 by the AlternC Development Team .
https :// alternc . org /
----------------------------------------------------------------------
LICENSE
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License ( GPL )
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
To read the license please visit http :// www . gnu . org / copyleft / gpl . html
----------------------------------------------------------------------
Purpose of file : Manage FTP accounts
----------------------------------------------------------------------
2006-04-26 12:28:53 +00:00
*/
2012-08-28 08:59:05 +00:00
2006-04-26 12:28:53 +00:00
/**
* Classe de gestion des comptes FTP de l ' h<EFBFBD> berg<EFBFBD> .
*/
class m_ftp {
2012-08-28 08:59:05 +00:00
2013-02-26 15:05:10 +00:00
var $srv_name ;
2006-04-26 12:28:53 +00:00
/* ----------------------------------------------------------------- */
/**
* Constructeur
*/
function m_ftp () {
2013-02-26 15:05:10 +00:00
global $L_FQDN ;
2014-11-27 15:15:18 +00:00
$this -> srv_name = variable_get ( 'ftp_human_name' , $L_FQDN , 'Human name for FTP server' , array ( 'desc' => 'Name' , 'type' => 'string' ));
2006-04-26 12:28:53 +00:00
}
2009-11-30 05:02:53 +00:00
/* ----------------------------------------------------------------- */
/**
* Password kind used in this class ( hook for admin class )
*/
function alternc_password_policy () {
return array ( " ftp " => " FTP accounts " );
}
2013-02-18 10:01:28 +00:00
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 ;
}
2009-11-30 05:02:53 +00:00
2011-05-03 07:25:51 +00:00
// 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 ();
2011-05-15 20:38:20 +00:00
$tt = $this -> get_list ();
if ( empty ( $tt ) || ! is_array ( $tt )) return $c ;
2011-05-03 07:25:51 +00:00
foreach ( $this -> get_list () as $v ) {
$c [ 'values' ][ $v [ 'id' ]] = $v [ 'login' ];
}
return $c ;
}
2013-03-01 07:52:50 +00:00
// Switch enabled status of an account
function switch_enabled ( $id , $status = null ) {
global $cuid , $db , $err ;
if ( ! $jj = $this -> get_ftp_details ( $id )) {
$err -> raise ( 'ftp' , _ ( " This account do not exist or is not of this account " ));
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 ;
}
}
2006-04-26 12:28:53 +00:00
/* ----------------------------------------------------------------- */
/** Retourne la liste des comptes FTP du compte h<EFBFBD> berg<EFBFBD>
* Retourne la liste des comptes FTP sous forme de tableau index<EFBFBD> de
* tableaus associatifs comme suit :
* $a [ " id " ] = ID du compte ftp
* $a [ " login " ] = Nom de login du compte
* $a [ " dir " ] = Dossier relatif <EFBFBD> la racine du compte de l ' utilisateur
2014-03-28 09:14:53 +00:00
* @ return array Retourne le tableau des comptes
2006-04-26 12:28:53 +00:00
*/
function get_list () {
2013-02-18 13:48:30 +00:00
global $db , $err , $cuid , $bro ;
2006-04-26 12:28:53 +00:00
$err -> log ( " ftp " , " get_list " );
$r = array ();
2013-10-17 10:33:26 +00:00
$db -> query ( " SELECT id, name, homedir, enabled FROM ftpusers WHERE uid=' $cuid ' ORDER BY name; " );
2006-04-26 12:28:53 +00:00
if ( $db -> num_rows ()) {
while ( $db -> next_record ()) {
2011-05-03 07:25:51 +00:00
$r [] = array (
" id " => $db -> f ( " id " ),
" login " => $db -> f ( " name " ),
2013-03-01 07:52:50 +00:00
" enabled " => $db -> f ( " enabled " ),
2012-02-28 14:48:45 +00:00
//"dir"=>$match[1]
" dir " => $db -> f ( " homedir " )
2006-04-26 12:28:53 +00:00
);
}
return $r ;
} else {
2012-10-18 07:52:54 +00:00
$err -> raise ( " ftp " , _ ( " No FTP account found " ));
2014-03-28 09:14:53 +00:00
return array ();
2006-04-26 12:28:53 +00:00
}
}
/* ----------------------------------------------------------------- */
/** Retourne les d<EFBFBD> tails d ' un compte FTP ( voir get_list )
* Le tableau est celui du compte d ' id sp<EFBFBD> cifi<EFBFBD>
* @ param integer $id Num<EFBFBD> ro du compte dont on souhaite obtenir les d<EFBFBD> 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 ();
2013-03-01 07:52:50 +00:00
$db -> query ( " SELECT id, name, homedir, enabled FROM ftpusers WHERE uid=' $cuid ' AND id=' $id '; " );
2006-04-26 12:28:53 +00:00
if ( $db -> num_rows ()) {
$db -> next_record ();
2013-02-18 13:48:30 +00:00
$regexp = " /^ " . preg_quote ( getuserpath (), " / " ) . " \ /(.*) $ / " ;
2014-03-26 13:31:06 +00:00
preg_match ( $regexp , $db -> f ( " homedir " ), $match );
2013-02-18 13:48:30 +00:00
2006-04-26 12:28:53 +00:00
$lg = explode ( " _ " , $db -> f ( " name " ));
2012-05-16 15:33:04 +00:00
if (( ! is_array ( $lg )) || ( count ( $lg ) != 2 )) {
2011-05-03 07:25:51 +00:00
$lg [ 0 ] = $db -> f ( " name " );
$lg [ 1 ] = " " ;
2006-04-26 12:28:53 +00:00
}
2012-05-16 15:33:04 +00:00
$r [] = array (
2006-04-26 12:28:53 +00:00
" id " => $db -> f ( " id " ),
" prefixe " => $lg [ 0 ],
" login " => $lg [ 1 ],
2013-03-01 07:52:50 +00:00
" dir " => $match [ 1 ],
" enabled " => $db -> f ( " enabled " )
2006-04-26 12:28:53 +00:00
);
2012-05-16 15:33:04 +00:00
return $r ;
2006-04-26 12:28:53 +00:00
} else {
2012-10-18 07:52:54 +00:00
$err -> raise ( " ftp " , _ ( " This FTP account does not exist " ));
2006-04-26 12:28:53 +00:00
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 ;
}
2014-03-28 16:14:32 +00:00
/**
* Check if the login is fine ( syntax )
*
* @ param string $l
*/
2013-01-29 09:13:34 +00:00
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
2014-04-07 16:28:48 +00:00
if ( ! preg_match ( " /^[A-Za-z0-9]+[A-Za-z0-9_ \ . \ -]* $ / " , $l ) ) {
2013-01-29 09:13:34 +00:00
$err -> raise ( 'ftp' , _ ( " FTP login is incorrect " ));
return false ;
}
return true ;
}
2006-04-26 12:28:53 +00:00
/* ----------------------------------------------------------------- */
/** 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 ) {
2009-11-30 06:01:34 +00:00
global $mem , $db , $err , $bro , $cuid , $admin ;
2006-04-26 12:28:53 +00:00
$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 " )) {
2012-10-18 07:52:54 +00:00
$err -> raise ( " ftp " , _ ( " This FTP account does not exist " ));
2006-04-26 12:28:53 +00:00
return false ;
}
$dir = $bro -> convertabsolute ( $dir );
if ( substr ( $dir , 0 , 1 ) == " / " ) {
$dir = substr ( $dir , 1 );
}
$r = $this -> prefix_list ();
if ( ! in_array ( $prefixe , $r )) {
2012-08-26 13:31:38 +00:00
$err -> raise ( " ftp " , _ ( " The chosen prefix is not allowed " ));
2006-04-26 12:28:53 +00:00
return false ;
}
2014-03-26 13:31:06 +00:00
2013-01-29 09:13:34 +00:00
$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 '; " );
2006-04-26 12:28:53 +00:00
$db -> next_record ();
if ( $db -> f ( " cnt " )) {
2012-10-18 07:52:54 +00:00
$err -> raise ( " ftp " , _ ( " This FTP account already exists " ));
2006-04-26 12:28:53 +00:00
return false ;
}
2012-08-21 17:04:24 +00:00
$absolute = getuserpath () . " / $dir " ;
2006-04-26 12:28:53 +00:00
if ( ! file_exists ( $absolute )) {
system ( " /bin/mkdir -p $absolute " );
}
if ( ! is_dir ( $absolute )) {
2012-10-18 07:52:54 +00:00
$err -> raise ( " ftp " , _ ( " The directory cannot be created " ));
2006-04-26 12:28:53 +00:00
return false ;
}
2007-10-26 04:44:53 +00:00
if ( trim ( $pass )) {
2009-11-30 06:01:34 +00:00
// Check this password against the password policy using common API :
if ( is_callable ( array ( $admin , " checkPolicy " ))) {
2011-05-03 07:25:51 +00:00
if ( ! $admin -> checkPolicy ( " ftp " , $prefixe . $login , $pass )) {
return false ; // The error has been raised by checkPolicy()
}
2009-11-30 06:01:34 +00:00
}
2014-01-10 14:02:54 +00:00
$encrypted_password = _md5cr ( $pass , strrev ( microtime ( true )));
2013-01-29 09:13:34 +00:00
$db -> query ( " UPDATE ftpusers SET name=' " . $full_login . " ', password='', encrypted_password=' $encrypted_password ', homedir=' $absolute ', uid=' $cuid ' WHERE id=' $id '; " );
2006-04-26 12:28:53 +00:00
} else {
2013-01-29 09:13:34 +00:00
$db -> query ( " UPDATE ftpusers SET name=' " . $full_login . " ', homedir=' $absolute ', uid=' $cuid ' WHERE id=' $id '; " );
2006-04-26 12:28:53 +00:00
}
return true ;
}
2009-11-30 06:01:34 +00:00
2006-04-26 12:28:53 +00:00
/* ----------------------------------------------------------------- */
/** Efface le compte ftp sp<EFBFBD> cifi<EFBFBD> .
* @ param integer $id Num<EFBFBD> ro du compte FTP <EFBFBD> supprimer .
* @ return boolean TRUE si le compte a <EFBFBD> t<EFBFBD> effac<EFBFBD> , 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 ) {
2012-10-18 07:52:54 +00:00
$err -> raise ( " ftp " , _ ( " This FTP account does not exist " ));
2006-04-26 12:28:53 +00:00
return false ;
}
$db -> query ( " DELETE FROM ftpusers WHERE id=' $id ' " );
return $name ;
}
/* ----------------------------------------------------------------- */
/** Cr<EFBFBD> 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<EFBFBD> pertoire racine du compte relatif <EFBFBD> la racine du membre
* @ return boolean TRUE si le compte a <EFBFBD> t<EFBFBD> cr<EFBFBD> <EFBFBD> , FALSE sinon .
*
*/
function add_ftp ( $prefixe , $login , $pass , $dir ) {
2009-11-30 06:01:34 +00:00
global $mem , $db , $err , $quota , $bro , $cuid , $admin ;
2006-04-26 12:28:53 +00:00
$err -> log ( " ftp " , " add_ftp " , $prefixe . " _ " . $login );
$dir = $bro -> convertabsolute ( $dir );
if ( substr ( $dir , 0 , 1 ) == " / " ) {
$dir = substr ( $dir , 1 );
}
$r = $this -> prefix_list ();
2013-01-29 09:19:31 +00:00
if ( empty ( $pass )) {
$err -> raise ( " ftp " , _ ( " Password can't be empty " ));
return false ;
}
2006-04-26 12:28:53 +00:00
if ( ! in_array ( $prefixe , $r ) || $prefixe == " " ) {
2012-08-26 13:31:38 +00:00
$err -> raise ( " ftp " , _ ( " The chosen prefix is not allowed " ));
2006-04-26 12:28:53 +00:00
return false ;
}
2013-01-29 09:13:34 +00:00
$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 . " ' " );
2006-04-26 12:28:53 +00:00
$db -> next_record ();
if ( $db -> f ( " cnt " )) {
2012-10-18 07:52:54 +00:00
$err -> raise ( " ftp " , _ ( " This FTP account already exists " ));
2006-04-26 12:28:53 +00:00
return false ;
}
$db -> query ( " SELECT login FROM membres WHERE uid=' $cuid '; " );
$db -> next_record ();
2012-08-21 17:04:24 +00:00
$absolute = getuserpath () . " / $dir " ;
2006-04-26 12:28:53 +00:00
if ( ! file_exists ( $absolute )) {
2014-03-26 13:31:06 +00:00
system ( " /bin/mkdir -p $absolute " ); // FIXME replace with action
2006-04-26 12:28:53 +00:00
}
if ( ! is_dir ( $absolute )) {
2012-10-18 07:52:54 +00:00
$err -> raise ( " ftp " , _ ( " The directory cannot be created " ));
2006-04-26 12:28:53 +00:00
return false ;
}
2009-11-30 06:01:34 +00:00
// Check this password against the password policy using common API :
if ( is_callable ( array ( $admin , " checkPolicy " ))) {
2013-01-29 09:13:34 +00:00
if ( ! $admin -> checkPolicy ( " ftp " , $full_login , $pass )) {
2011-05-03 07:25:51 +00:00
return false ; // The error has been raised by checkPolicy()
2009-11-30 06:01:34 +00:00
}
}
2006-04-26 12:28:53 +00:00
if ( $quota -> cancreate ( " ftp " )) {
2014-01-10 14:02:54 +00:00
$encrypted_password = _md5cr ( $pass , strrev ( microtime ( true )));
2013-01-29 09:13:34 +00:00
$db -> query ( " INSERT INTO ftpusers (name,password, encrypted_password,homedir,uid) VALUES (' " . $full_login . " ', '', ' $encrypted_password ', ' $absolute ', ' $cuid ') " );
2006-04-26 12:28:53 +00:00
return true ;
} else {
2012-10-18 07:52:54 +00:00
$err -> raise ( " ftp " , _ ( " Your FTP account quota is over. You cannot create more ftp accounts " ));
2006-04-26 12:28:53 +00:00
return false ;
}
}
/* ----------------------------------------------------------------- */
/** Retourne TRUE si $dir poss<EFBFBD> de un compte FTP
* @ param string $dir Dossier <EFBFBD> tester , relatif <EFBFBD> la racine du compte courant
* @ return boolean retourne TRUE si $dir <EFBFBD> un compte FTP , FALSE sinon .
*/
function is_ftp ( $dir ) {
global $mem , $db , $err ;
$err -> log ( " ftp " , " is_ftp " , $dir );
if ( substr ( $dir , 0 , 1 ) == " / " ) $dir = substr ( $dir , 1 );
2012-08-21 17:04:24 +00:00
$db -> query ( " SELECT id FROM ftpusers WHERE homedir=' " . getuserpath () . " / $dir '; " );
2006-04-26 12:28:53 +00:00
if ( $db -> num_rows ()) {
$db -> next_record ();
return $db -> f ( " id " );
} else {
return false ;
}
}
/* ----------------------------------------------------------------- */
2013-02-18 10:01:28 +00:00
/** Fonction appell<EFBFBD> e par domains quand un domaine est supprim<EFBFBD> pour le membre
2006-04-26 12:28:53 +00:00
* @ param string $dom Domaine <EFBFBD> d<EFBFBD> truire .
* @ access private
*/
function alternc_del_domain ( $dom ) {
global $db , $err , $cuid ;
2013-02-18 10:01:28 +00:00
$err -> log ( " ftp " , " alternc_del_domain " , $dom );
$db -> query ( " DELETE FROM ftpusers WHERE uid=' $cuid ' AND ( name LIKE ' $dom\_ %' OR name LIKE ' $dom ') " );
2006-04-26 12:28:53 +00:00
return true ;
}
/* ----------------------------------------------------------------- */
/** Fonction appell<EFBFBD> e par membres quand un membre est effac<EFBFBD> .
* @ access private
*/
function alternc_del_member () {
global $db , $err , $cuid ;
2013-02-18 10:01:28 +00:00
$err -> log ( " ftp " , " alternc_del_member " );
2006-04-26 12:28:53 +00:00
$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
*/
2012-08-26 16:11:53 +00:00
function hook_quota_get () {
2006-04-26 12:28:53 +00:00
global $db , $err , $cuid ;
2012-08-26 16:11:53 +00:00
$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 ;
2006-04-26 12:28:53 +00:00
}
/* ----------------------------------------------------------------- */
/**
* Exporte toutes les informations ftp du compte AlternC
* @ access private
* EXPERIMENTAL 'sid' function ;)
*/
2012-02-28 14:48:45 +00:00
function alternc_export_conf () {
2006-04-26 12:28:53 +00:00
global $db , $err ;
$err -> log ( " ftp " , " export " );
$f = $this -> get_list ();
2012-05-21 15:58:20 +00:00
$str = " <ftp> " ;
2012-02-28 14:48:45 +00:00
foreach ( $f as $d => $v ) {
2012-05-21 15:58:20 +00:00
$str .= " <login> " . ( $v [ " login " ]) . " </login> \n " ;
$str .= " <password> " . ( $v [ " encrypted_password " ]) . " </password> \n " ;
$str .= " <directory> " . ( $v [ " dir " ]) . " <directory> \n " ;
2006-04-26 12:28:53 +00:00
}
2012-05-21 15:58:20 +00:00
$str .= " </ftp> \n " ;
2006-04-26 12:28:53 +00:00
return $str ;
}
2012-09-03 07:36:00 +00:00
/* ----------------------------------------------------------------- */
/** 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 ),
);
}
2006-04-26 12:28:53 +00:00
} /* Class m_ftp */