[PHP] Gérer un .htaccess et un .htpasswd

Titre: Gérer un .htaccess et un .htpasswd
Date: Juillet 2009
Language: PHP
Description: Le but est de gérer un fichier .htpasswd de manière à ce que seuls les utilisateurs d’un site aient accès aux fichiers d’un répertoire.

Je travaille en supposant qu’une connexion à une base de données existe et qu’une table users existe avec les champs suivants:
* actif: si 1, l’utilisateur peut se loger
* psw_htpasswd: champ qui contient le mot de passe pour le fichier .htpasswd
* pseudo: 3 caractères qui désigne l’utilisateur

Voici un exemple d’utilisation:

<?
$htaccess = new htaccess( );
$htaccess->set_folder( 'folder/' ); // dossier contenant le .htpasswd

// si vous voulez ajouter un user à votre base de données:
$psw_sha = $htaccess->non_salted_sha1( $psw ); // retourne le passord encodé que vous pouvez sauver

// si vous voulez créer le fichier à partir de la base de données
if( !$htaccess->create_htpasswd_from_bdd( ) )
	die( 'Erreur' );
if( !$htaccess->write_files( ) )
	die( 'Erreur' );

// si vous voulez ajouter un utilisateur
if( !$htaccess->load_htpasswd( ) )
	die( 'Erreur' );
$htaccess->add_user( $pseudo, $psw );
if( !$htaccess->write_files( ) )
	die( 'Erreur' );

// si vous voulez supprimer un user
if( !$htaccess->load_htpasswd( ) )
	$htaccess->remove_user_from_htpasswd( $pseudo );
if( !$htaccess->write_files( ) )
	die( 'Erreur' );
?>

Code principal

<?php
/*
	htaccess.class.php
	Classe de gestion des fichiers .htaccess et .htpasswd
	Rafael GUGLIELMETTI
	Début: 28.02.2009, derniere modif 28.02.2009
*/
class htaccess
{
	public $error = NULL;
	
	private $htpasswd_content = NULL;
	private $htpasswd_rows = 0;
	
	private $folder = 'data/';
	
	/*
		load_htpasswd
		Lit le fichier des mots de passe
		Retour: bool
	*/
	
	public function load_htpasswd( )
	{
		if( !file_exists( $this->folder . '.htpasswd' ) )
		{
			$this->htpasswd_rows = 0;
			$this->htpasswd_content = array( );
			return true;
		}
		
		if( ( $this->htpasswd_content = file( $this->folder . '.htpasswd' ) ) === false )
		{
			$this->error = 'LOAD_HTPASSWD';
			return false;
		}
		
		$this->htpasswd_content = array_map( 'rtrim', $this->htpasswd_content );
		
		$this->htpasswd_rows = count( $this->htpasswd_content );
	
	return true;
	}
	
	/*
		write_files
		Ecrit les fichiers
		Retour: bool
	*/
	public function write_files( )
	{
		// ------------------------------------------------------------------
		// .htpasswd
		if( !$this->htpasswd_rows )
		{
			if( @file_put_contents( $this->folder . '.htpasswd', ' ' ) === false )
			return false;
		}
		else
		{
			if( @file_put_contents( $this->folder . '.htpasswd', implode( "\n", $this->htpasswd_content ) ) === false )
				return false;
		}
	
		// ------------------------------------------------------------------
		// .htaccess
		if( !file_exists( $this->folder . '.htaccess' ) )
		{
			$data = 'AuthName "Veuillez entrer votre visa et votre mot de passe"' . "\n";
			$data .= "AuthType Basic\n";
			$data .= 'AuthUserFile "' . realpath( $this->folder . '.htpasswd' ) . '"' . "\n";
			$data .= "Require valid-user\n";
			
			if( @file_put_contents( $this->folder . '/.htaccess', $data ) === false )
				return false;
		}
	
		return true;
	}
	
	/*
		add_user
		Ajoute un utilisateur
	*/
	public function add_user( $visa, $psw )
	{
		if( isset( $this->htpasswd_content ) )
			$this->remove_user_from_htpasswd( $visa ); // suppression des anciennes occurences
		else
			$this->htpasswd_content[ ] = array( );
		
		$visa = strtoupper( $visa );
		$psw = $this->non_salted_sha1( $psw );
		
		$this->htpasswd_rows = count( $this->htpasswd_content );
		
		$this->htpasswd_content[ ] = $visa . ':' . $psw;
		$this->htpasswd_content[ ] = strtolower( $visa ) . ':' . $psw;
		
		$this->htpasswd_rows += 2;
		return $psw;
	}
	
	/*
		create_htpasswd_from_bdd
		Crée le fichier depuis la bdd
		Retour: bool
	*/
	public function create_htpasswd_from_bdd( )
	{
		if( !( $ret = mysql_query( 'SELECT pseudo, psw_htpasswd FROM users WHERE actif=1' ) ) )
		{
			$this->error = 'GET_DATA';
			return false;
		}
		
		$this->htpasswd_content = array( );
		while( $row = mysql_fetch_row( $ret ) )
		{
			if( empty( $row[1] ) )
				continue ;
			
			$this->htpasswd_content[ ] = $row[0] . ':' . $row[1];
			$this->htpasswd_content[ ] = strtolower( $row[0] ) . ':' . $row[1];
		}
		
		$this->htpasswd_rows = count( $this->htpasswd_content );
		
		return true;
	}
		
	public function remove_user_from_htpasswd( $visa )
	{
		$find = $this->find_visa_in_array( $visa );
		$find_ = count( $find );
		
		$j = 0;
		for( $i = 0; $i < $find_; $i++ )
			{
			array_splice( $this->htpasswd_content, $find[$i] - $j, 1 );
			$j++;
		}
		
		$this->htpasswd_rows = count( $this->htpasswd_content );
	}
	
	/*
	find_visa_in_array
	Cherche les occurences d'un visa (insensible à la casse)
	*/
	private function find_visa_in_array( $visa )
	{
		$find = array( );
		$visa = strtolower( $visa );
	
		for( $i = 0; $i < $this->htpasswd_rows; $i++ )
		{
			if( strlen( $this->htpasswd_content[$i] ) < 4 )
			continue ;
		
			if( strtolower( substr( $this->htpasswd_content[$i], 0, 3 ) ) == $visa )
				$find[ ] = $i;
		}
		
		return $find;
	}
	
	public function set_folder( $folder )
	{
		if( ( $len = strlen( $folder ) ) > 0 )
		{
			if( $folder[$len - 1] != '/' )
			$folder .= '/';
		}
	
		$this->folder = $folder;
	}
	
	// .htpasswd file functions
	// Copyright (C) 2004,2005 Jarno Elonen <elonen@iki.fi>
	//
	// Redistribution and use in source and binary forms, with or without modification,
	// are permitted provided that the following conditions are met:
	//
	// * Redistributions of source code must retain the above copyright notice, this
	//   list of conditions and the following disclaimer.
	// * Redistributions in binary form must reproduce the above copyright notice,
	//   this list of conditions and the following disclaimer in the documentation
	//   and/or other materials provided with the distribution.
	// * The name of the author may not be used to endorse or promote products derived
	//   from this software without specific prior written permission.
	//
	// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
	// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
	// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
	// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
	// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
	// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
	// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
	// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	//
	// Thanks to Jonas Wagner for SHA1 support.
	
	// Generate a SHA1 password hash *without* salt
	public function non_salted_sha1( $pass )
	{
		return "{SHA}" . base64_encode(pack("H*", sha1($pass)));
	}
}

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *