2006-04-26 12:28:53 +00:00
< ? php
2015-09-25 15:42:00 +00:00
/*
----------------------------------------------------------------------
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
----------------------------------------------------------------------
2017-10-06 21:42:39 +00:00
*/
2009-11-30 05:02:53 +00:00
2006-04-26 12:28:53 +00:00
/**
2015-09-25 15:42:00 +00:00
* This class handle folder web restricted access through . htaccess /. htpassword
* files .
*
2017-10-08 17:31:34 +00:00
* @ copyright AlternC - Team 2000 - 2017 https :// alternc . com /
2015-09-25 15:42:00 +00:00
*/
2006-04-26 12:28:53 +00:00
class m_hta {
2009-11-30 05:02:53 +00:00
2014-03-27 15:04:21 +00:00
/**
2015-09-25 15:42:00 +00:00
* Password kind used in this class ( hook for admin class )
* @ return array
*/
function alternc_password_policy () {
return array ( " hta " => " Protected folders passwords " );
2013-01-23 13:34:01 +00:00
}
2009-11-30 05:02:53 +00:00
2017-10-06 21:42:39 +00:00
2014-03-27 15:04:21 +00:00
/**
2017-10-06 21:42:39 +00:00
* hook called by menu class to add a menu
* to the left panel
2015-09-25 15:42:00 +00:00
* @ return array
*/
function hook_menu () {
$obj = array (
'title' => _ ( " Protected folders " ),
'link' => 'hta_list.php' ,
'pos' => 50 ,
);
return $obj ;
2006-04-26 12:28:53 +00:00
}
2009-11-30 05:02:53 +00:00
2017-10-06 21:42:39 +00:00
2014-03-27 15:04:21 +00:00
/**
2015-09-25 15:42:00 +00:00
* Create a protected folder ( . htaccess et . htpasswd )
* @ 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
*
* @ global m_mem $mem
* @ global m_bro $bro
2017-08-16 17:34:32 +00:00
* @ global m_messages $msg
2015-09-25 15:42:00 +00:00
* @ param string $dir
* @ return boolean
*/
function CreateDir ( $dir ) {
2017-08-16 17:34:32 +00:00
global $bro , $msg ;
$msg -> log ( " hta " , " createdir " , $dir );
2015-09-25 15:42:00 +00:00
$absolute = $bro -> convertabsolute ( $dir , 0 );
2017-08-16 17:34:32 +00:00
if ( ! is_dir ( $absolute )) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " The folder '%s' does not exist " ), $dir );
2015-09-25 15:42:00 +00:00
return false ;
}
2021-08-20 14:50:08 +00:00
$param = " AuthUserFile \" $absolute /.htpasswd \" \n AuthName \" " . _ ( " Restricted area " ) . " \" \n AuthType Basic \n require valid-user \n " ;
2015-09-25 15:42:00 +00:00
if ( ! file_exists ( " $absolute /.htaccess " )) {
2017-12-29 16:56:03 +00:00
$file = @ fopen ( " $absolute /.htaccess " , " w+ " );
2015-09-25 15:42:00 +00:00
if ( ! $file ) {
2017-12-29 16:56:03 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " Error creating .htaccess file: " ) . error_get_last ()[ 'message' ]);
2015-09-25 15:42:00 +00:00
return false ;
}
fseek ( $file , 0 );
fwrite ( $file , $param );
fclose ( $file );
2021-08-20 14:50:08 +00:00
$msg -> raise ( " INFO " , " hta " , _ ( " Added .htaccess file to restrict '%s' to valid users " ), array ( $dir ));
}
else {
# The .htaccess file already exists, and we don't try to overwrite the existing
# contents, therefore we inform that they need to make the modifications to
# the htaccess file manually.
$msg -> raise ( " ALERT " , " hta " , _ ( " The .htaccess file already existed in '%s', you must add the following lines manually to '%s' \n " ), array ( $dir , $dir . " /.htaccess " ));
$msg -> raise ( " ALERT " , " hta " , $param );
2015-09-25 15:42:00 +00:00
}
if ( ! file_exists ( " $absolute /.htpasswd " )) {
2017-12-29 16:56:03 +00:00
if ( !@ touch ( " $absolute /.htpasswd " )) {
$msg -> raise ( " ERROR " , " hta " , _ ( " Error creating .htpasswd file: " ) . error_get_last ()[ 'message' ]);
2015-09-25 15:42:00 +00:00
return false ;
}
2021-08-20 14:50:08 +00:00
$msg -> raise ( " INFO " , " hta " , _ ( " Added .htpasswd to Folder '%s', you may now add users who will be able to access it. " ), $dir );
2015-09-25 15:42:00 +00:00
return true ;
}
return true ;
2006-04-26 12:28:53 +00:00
}
2009-11-30 05:02:53 +00:00
2017-10-06 21:42:39 +00:00
2014-03-27 15:04:21 +00:00
/**
2015-09-25 15:42:00 +00:00
* Returns the list of all user folder currently protected by a . htpasswd file
*
2017-08-16 17:34:32 +00:00
* @ global m_messages $msg
2015-09-25 15:42:00 +00:00
* @ global m_mem $mem
* @ return array Array containing user folder list
*/
function ListDir () {
2017-08-16 17:34:32 +00:00
global $msg , $mem ;
2018-06-27 22:27:10 +00:00
$msg -> debug ( " hta " , " listdir " );
2015-09-25 15:42:00 +00:00
$sortie = array ();
$absolute = ALTERNC_HTML . " / " . substr ( $mem -> user [ " login " ], 0 , 1 ) . " / " . $mem -> user [ " login " ];
exec ( " find " . escapeshellarg ( $absolute ) . " -name .htpasswd|sort " , $sortie );
if ( ! count ( $sortie )) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " INFO " , " hta " , _ ( " No protected folder " ));
2015-09-25 15:42:00 +00:00
return false ;
}
$pattern = " /^ " . preg_quote ( ALTERNC_HTML , " / " ) . " \ /. \ /[^ \ /]* \ /(.*) \ / \ .htpasswd/ " ;
$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 ;
2006-04-26 12:28:53 +00:00
}
2015-09-25 15:42:00 +00:00
2017-10-06 21:42:39 +00:00
2015-09-25 15:42:00 +00:00
/**
* Tells if a folder is protected .
*
* @ global m_mem $mem
2017-08-16 17:34:32 +00:00
* @ global m_messages $msg
2015-09-25 15:42:00 +00:00
* @ param string $dir Folder to check
* @ return boolean If the folder is protected , or FALSE if it is not
*/
function is_protected ( $dir ) {
2017-08-16 17:34:32 +00:00
global $mem , $msg ;
2018-06-27 22:27:10 +00:00
$msg -> debug ( " hta " , " is_protected " , $dir );
2015-09-25 15:42:00 +00:00
$absolute = ALTERNC_HTML . " / " . substr ( $mem -> user [ " login " ], 0 , 1 ) . " / " . $mem -> user [ " login " ] . " / $dir " ;
if ( file_exists ( " $absolute /.htpasswd " )) {
return true ;
} else {
return false ;
}
2006-04-26 12:28:53 +00:00
}
2015-09-25 15:42:00 +00:00
2017-10-06 21:42:39 +00:00
2015-09-25 15:42:00 +00:00
/**
* Returns the list of login for a protected folder .
*
* @ global m_mem $mem
2017-08-16 17:34:32 +00:00
* @ global m_messages $msg
2015-09-25 15:42:00 +00:00
* @ param string $dir The folder to lookup ( relative to user root )
* @ return array An array containing the list of logins from the . htpasswd file , or FALSE
*/
function get_hta_detail ( $dir ) {
2017-08-16 17:34:32 +00:00
global $mem , $msg ;
2018-06-27 22:27:10 +00:00
$msg -> debug ( " hta " , " get_hta_detail " );
2015-09-25 15:42:00 +00:00
$absolute = ALTERNC_HTML . " / " . substr ( $mem -> user [ " login " ], 0 , 1 ) . " / " . $mem -> user [ " login " ] . " / $dir " ;
if ( file_exists ( " $absolute /.htaccess " )) {
/* if ( ! _reading_htaccess ( $absolute )) {
2017-10-06 21:42:39 +00:00
return false ;
}
*/
2015-09-25 15:42:00 +00:00
}
$file = @ fopen ( " $absolute /.htpasswd " , " r " );
$i = 0 ;
$res = array ();
if ( ! $file ) {
return false ;
}
2017-10-06 21:42:39 +00:00
// TODO: Test the validity of a .htpasswd
2015-09-25 15:42:00 +00:00
while ( ! feof ( $file )) {
$s = fgets ( $file , 1024 );
$t = explode ( " : " , $s );
if ( $t [ 0 ] != $s ) {
$res [ $i ] = $t [ 0 ];
$i = $i + 1 ;
2014-03-27 15:04:21 +00:00
}
}
2015-09-25 15:42:00 +00:00
fclose ( $file );
return $res ;
2014-03-27 15:04:21 +00:00
}
2015-09-25 15:42:00 +00:00
2017-10-06 21:42:39 +00:00
2015-09-25 15:42:00 +00:00
/**
* Unprotect a folder
*
* @ global m_mem $mem
* @ global m_bro $bro
2017-08-16 17:34:32 +00:00
* @ global m_messages $msg
2015-09-25 15:42:00 +00:00
* @ 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 ) {
2017-08-16 17:34:32 +00:00
global $bro , $msg ;
$msg -> log ( " hta " , " deldir " , $dir );
2015-09-25 15:42:00 +00:00
$dir = $bro -> convertabsolute ( $dir , $skip );
if ( ! $dir ) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , ( " The folder '%s' does not exist " ), $dir );
2015-09-25 15:42:00 +00:00
return false ;
}
$htaccess_file = " $dir /.htaccess " ;
if ( ! is_readable ( $htaccess_file )) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " I cannot read the file '%s' " ), $htaccess_file );
2015-09-25 15:42:00 +00:00
}
$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 ) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ALERT " , " hta " , _ ( " Unexpected: No changes made to '%s' " ), $htaccess_file );
2015-09-25 15:42:00 +00:00
}
// If file is empty, remove it
if ( ! count ( $fileLines )) {
if ( ! unlink ( $htaccess_file )) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " I could not delete the file '%s' " ), $htaccess_file );
2015-09-25 15:42:00 +00:00
}
} else {
file_put_contents ( $htaccess_file , implode ( " \n " , $fileLines ));
}
$htpasswd_file = " $dir /.htpasswd " ;
if ( ! is_writable ( $htpasswd_file )) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " I cannot read the file '%s' " ), $htpasswd_file );
2015-09-25 15:42:00 +00:00
} else if ( ! unlink ( $htpasswd_file )) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " I cannot delete the file '%s/.htpasswd' " ), $dir );
2015-09-25 15:42:00 +00:00
return false ;
2014-03-27 15:04:21 +00:00
}
2006-04-26 12:28:53 +00:00
2015-09-25 15:42:00 +00:00
return true ;
}
2009-11-30 05:02:53 +00:00
2017-10-06 21:42:39 +00:00
2014-03-27 15:04:21 +00:00
/**
2015-09-25 15:42:00 +00:00
* Add a user to a protected folder
*
2017-08-16 17:34:32 +00:00
* @ global m_messages $msg
2015-09-25 15:42:00 +00:00
* @ global m_bro $bro
* @ global m_admin $admin
* @ param string $user
* @ param string $password
* @ param string $dir
* @ param string $password The password to add ( cleartext )
* @ 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
*/
function add_user ( $user , $password , $dir ) {
2017-08-16 17:34:32 +00:00
global $msg , $bro , $admin ;
$msg -> log ( " hta " , " add_user " , $user . " / " . $dir );
2015-09-25 15:42:00 +00:00
if ( empty ( $user )) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , 'hta' , _ ( " Please enter a user " ));
2015-09-25 15:42:00 +00:00
return false ;
}
if ( empty ( $password )) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , 'hta' , _ ( " Please enter a password " ));
2015-09-25 15:42:00 +00:00
return false ;
}
$absolute = $bro -> convertabsolute ( $dir , 0 );
if ( ! file_exists ( $absolute )) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " The folder '%s' does not exist " ), $dir );
2015-09-25 15:42:00 +00:00
return false ;
}
// @todo delete cf!. functions.php checkloginemail definition
if ( checkloginmail ( $user )) {
// Check this password against the password policy using common API :
if ( is_callable ( array ( $admin , " checkPolicy " ))) {
if ( ! $admin -> checkPolicy ( " hta " , $user , $password )) {
return false ; // The error has been raised by checkPolicy()
}
}
2009-11-30 06:01:34 +00:00
2015-09-25 15:42:00 +00:00
$file = @ fopen ( " $absolute /.htpasswd " , " a+ " );
if ( ! $file ) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " File already exist " ));
2015-09-25 15:42:00 +00:00
return false ;
}
fseek ( $file , 0 );
while ( ! feof ( $file )) {
$s = fgets ( $file , 1024 );
$t = explode ( " : " , $s );
if ( $t [ 0 ] == $user ) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " The user '%s' already exist for this folder " ), $user );
2015-09-25 15:42:00 +00:00
return false ;
}
}
fseek ( $file , SEEK_END );
if ( empty ( $t [ 1 ]) || substr ( $t [ 1 ], - 1 ) != " \n " ) {
fwrite ( $file , " \n " );
}
fwrite ( $file , " $user : " . _md5cr ( $password ) . " \n " );
fclose ( $file );
return true ;
} else {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " Please enter a valid username " ));
2015-09-25 15:42:00 +00:00
return false ;
}
2006-04-26 12:28:53 +00:00
}
2009-11-30 05:02:53 +00:00
2017-10-06 21:42:39 +00:00
2014-03-27 15:04:21 +00:00
/**
2015-09-25 15:42:00 +00:00
* Delete a user from a protected folder .
*
* @ global m_bro $bro
2017-08-16 17:34:32 +00:00
* @ global m_messages $msg
2015-09-25 15:42:00 +00:00
* @ param array $lst An array with login to delete .
* @ 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 ) {
2017-08-16 17:34:32 +00:00
global $bro , $msg ;
$msg -> log ( " hta " , " del_user " , $lst . " / " . $dir );
2015-09-25 15:42:00 +00:00
$absolute = $bro -> convertabsolute ( $dir , 0 );
if ( ! file_exists ( $absolute )) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " The folder '%s' does not exist " ), $dir );
2015-09-25 15:42:00 +00:00
return false ;
}
touch ( " $absolute /.htpasswd.new " );
$file = fopen ( " $absolute /.htpasswd " , " r " );
$newf = fopen ( " $absolute /.htpasswd.new " , " a " );
if ( ! $file || ! $newf ) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " File already exist " ));
2015-09-25 15:42:00 +00:00
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 ;
2006-04-26 12:28:53 +00:00
}
2009-11-30 05:02:53 +00:00
2017-10-06 21:42:39 +00:00
2014-03-27 15:04:21 +00:00
/**
2015-09-25 15:42:00 +00:00
* Change the password of a user in a protected folder
* @ param string $user The users whose password should be changed
* @ param string $newpass The new password of this user
* @ 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
*/
function change_pass ( $user , $newpass , $dir ) {
2017-08-16 17:34:32 +00:00
global $bro , $msg , $admin ;
$msg -> log ( " hta " , " change_pass " , $user . " / " . $dir );
2015-09-25 15:42:00 +00:00
$absolute = $bro -> convertabsolute ( $dir , 0 );
if ( ! file_exists ( $absolute )) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " The folder '%s' does not exist " ), $dir );
2015-09-25 15:42:00 +00:00
return false ;
}
2009-11-30 06:01:34 +00:00
2015-09-25 15:42:00 +00:00
// Check this password against the password policy using common API :
if ( is_callable ( array ( $admin , " checkPolicy " ))) {
if ( ! $admin -> checkPolicy ( " hta " , $user , $newpass )) {
return false ; // The error has been raised by checkPolicy()
}
}
2009-11-30 06:01:34 +00:00
2015-09-25 15:42:00 +00:00
touch ( " $absolute /.htpasswd.new " );
$file = fopen ( " $absolute /.htpasswd " , " r " );
$newf = fopen ( " $absolute /.htpasswd.new " , " a " );
if ( ! $file || ! $newf ) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " File already exist " ));
2015-09-25 15:42:00 +00:00
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 ;
2006-04-26 12:28:53 +00:00
}
2009-11-30 05:02:53 +00:00
2017-10-06 21:42:39 +00:00
2014-03-27 15:04:21 +00:00
/**
2015-09-25 15:42:00 +00:00
* Check that a . htaccess file is valid ( for authentication )
*
2017-08-16 17:34:32 +00:00
* @ global m_messages $msg
2015-09-25 15:42:00 +00:00
* @ param type $absolute
* @ 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
*/
private function _reading_htaccess ( $absolute ) {
2017-08-16 17:34:32 +00:00
global $msg ;
2018-06-27 22:27:10 +00:00
$msg -> debug ( " hta " , " _reading_htaccess " , $absolute );
2015-09-25 15:42:00 +00:00
$file = fopen ( " $absolute /.htaccess " , " r+ " );
$lignes = array ( 1 , 1 , 1 );
$errr = 0 ;
if ( ! $file ) {
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 )) {
2017-10-06 16:04:36 +00:00
$msg -> raise ( " ERROR " , " hta " , _ ( " An incompatible .htaccess file exists in this folder " ));
2015-09-25 15:42:00 +00:00
return false ;
}
return true ;
2006-04-26 12:28:53 +00:00
}
2009-11-30 05:02:53 +00:00
2017-10-06 21:42:39 +00:00
} /* class m_hta */
2009-11-30 05:02:53 +00:00