logo
Apache Lounge
Webmasters

 


About

Forum Index Downloads Search Register Log in  RSS Apache Lounge
 



Keep Server Online

If you find the Apache Lounge, the downloads and overall help useful, please express your satisfaction with a donation.

or

Bitcoin

A donation makes a contribution towards the costs, the time and effort that's going in this site and building.

Thank You! Steffen

Apache Lounge is not sponsored.

Your donations will help to keep this site alive and well, and continuing building binaries.



[PHP] .htpasswd manager

 
Post new topic   Reply to topic    Apache Forum Index -> Coding & Scripting Corner



View previous topic :: View next topic  
Author Message
Jorge



Joined: 12 Mar 2006
Posts: 376
Location: Belgium

PostPosted: Mon 31 Jul '06 18:59    Post subject: [PHP] .htpasswd manager Reply with quote

This little class allows you to manage and validate against .htpasswd files.

The class should be fairly self explaining if you look at the code.

Updated: 19/03/2007

Create new file:
Code:

$htpw = new htpasswd(./.htpasswd);
$htpw->create("user", "pass");
$htpw->save();


Update file:
Code:

$htpw = new htpasswd(./.htpasswd);
$htpw->remove('user');
$htpw->create('new_user', 'password');
$htpw->save();


Validate User:
Code:

$htpw = new htpasswd(./.htpasswd);
if($htpw->validate('user', 'pass'){
     echo 'Welcome';
}else{
     echo 'Get Lost';
}


The class:
Code:

<?php
/*************************************\
| htpasswd class                      |
| By Jorge Schrauwen 2007             |
| http://www.blackdot.be              |
\*************************************/

/*
Requires:
- PHP >= 4.3.0

Usage:
require('htpasswd.php');

$pwmanager = new htpasswd('.htpasswd');
$pwmanager->create('test', 'pass');
$pwmanager->save();

Functions:
create('MyUser', 'Pass')      : create MyUser with password Pass. (true/false)
remove('MyUser')              : remove MyUser. (true/false)
validate('MyUser', 'Pass')    : will validate the user. (true/false)
users()                     : return and array with the usernames.
save()                        : save the password file. (true/false)
save('/server/www/.htpasswd') : save the password file to /server/www/.htpasswd. (true/false)

Error Handling:
when a function returns false you can get more information via
echo $pwmanager->error;
*/

class htpasswd{
   public $users;
   public $error;
   private $_path;   

   function htpasswd($file=false){
      if(!$file){
         die('Please specify a file!');
      }else{   
         //configure
         $this->_path = $file;
         $this->users = '';
         //load database
         if(file_exists($file)){
            $data = array();
            $fcontents = file($file);
            while(list($line_num, $line) = each($fcontents)){
               $user = explode(':',$line);
               //$user = $arraydata[0];
               $data[$user[0]] = rtrim($user[1]);
            }
            $this->users = $data;
         }
      }
   }
         
   function create($user, $passwd, $update=false){
      $this->error = '';
      if(isset($this->users[$user]) && !$update){
         $this->error = 'User <strong>'.$user.'</strong> exists! To update the user set the update parameter to true.';
         return false;
      }
      $this->users[$user] = $this->non_salted_sha1($passwd);
      return true;
   }
   
   function remove($user){
      $this->error = '';
      if(isset($this->users[$user])){
         unset($this->users[$user]);
         return true;
      }else{
         $this->error = 'User <strong>'.$user.'</strong> does not exist!';
         return false;
      }
   }
   
   function users(){
      $this->error = '';
      $rval = Array();
      if(is_array($this->users)){
         foreach(array_keys($this->users) as $uid){
            $rval[count($rval)] = $uid;
         }
      }
      return $rval;
   }
      
   function validate($user, $pass){
      $this->error = '';
      if(!isset($this->users[$user])) return False;
      $crypted = $this->users[$user];
      
      if(substr($crypted, 0, 6) == "{SSHA}"){
         $ohash = base64_decode(substr($crypted, 6));
         return substr($ohash, 0, 20) == pack("H*", sha1($pass . substr($ohash, 20)));
      }elseif(substr($crypted, 0, 5) == "{SHA}"){
         return ($this->non_salted_sha1($pass) == $crypted);
      }else{
         return ($pass == $crypted);
      }
   }

   function save($file=false){
      $fcontents = "";
      if($file == false) $file = $this->_path;
      foreach(array_keys($this->users) as $user){
         $fcontents .= $user.":".$this->users[$user]."\n";
      }
      if(file_put_contents($file, $fcontents)){
         $this->error = '';
         return true;
      }else{
         $this->error = 'Couln\'t save the file!';
         return false;
      }
   }   

   //encryption functions
   function rand_salt_crypt($pass){
      $salt = "";
      mt_srand((double)microtime()*1000000);
      for ($i=0; $i<CRYPT_SALT_LENGTH; $i++)
         $salt .= substr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./", mt_rand() & 63, 1);
      return "$apr1$".crypt($pass, $salt);
   }
   
   function rand_salt_sha1($pass){
      mt_srand((double)microtime()*1000000);
      $salt = pack("CCCC", mt_rand(), mt_rand(), mt_rand(), mt_rand());
      return "{SSHA}".base64_encode(pack("H*", sha1($pass . $salt)) . $salt);
   }
   
   function non_salted_sha1($pass){
      return "{SHA}".base64_encode(pack("H*", sha1($pass)));
   }
}

//php4 work around
if(!function_exists('file_put_contents')){
   function file_put_contents($filename, $content, $flags = null, $resource_context = null){
      if(is_array($content)){
         $content = implode('', $content);
      }
      if(!is_scalar($content)){
         trigger_error('file_put_contents() The 2nd parameter should be either a string or an array', E_USER_WARNING);
         return false;
      }
      $length = strlen($content);
      $mode = ($flags &FILE_APPEND) ? 'a' : 'w';
      $use_inc_path = ($flags &FILE_USE_INCLUDE_PATH) ? true : false;
      if(($fh = @fopen($filename, $mode, $use_inc_path)) === false){
         trigger_error('file_put_contents() failed to open stream: Permission denied', E_USER_WARNING);
         return false;
      }
      $bytes = 0;
      if(($bytes = @fwrite($fh, $content)) === false){
         $errormsg = sprintf('file_put_contents() Failed to write %d bytes to %s',
         $length,
         $filename);
         trigger_error($errormsg, E_USER_WARNING);
         return false;
      }
      @fclose($fh);
      if($bytes != $length){
         $errormsg = sprintf('file_put_contents() Only %d of %d bytes written, possibly out of free disk space.',
         $bytes,
         $length);
         trigger_error($errormsg, E_USER_WARNING);
         return false;
      }
      return $bytes;
   }
}
?>



Last edited by Jorge on Mon 19 Mar '07 10:31; edited 6 times in total
Back to top
James Blond
Moderator


Joined: 19 Jan 2006
Posts: 6255
Location: Germany, Next to Hamburg

PostPosted: Wed 02 Aug '06 16:09    Post subject: Reply with quote

To use this under PHP4 you need file_put_contents (since php 5)
Here the code to emulate that
Code:

<?php
function file_put_contents($filename, $content, $flags = null, $resource_context = null)

{
     if (is_array($content)) {
        $content = implode('', $content);
         }
    if (!is_scalar($content)) {
        user_error('file_put_contents() The 2nd parameter should be either a string or an array',
             E_USER_WARNING);
         return false;
         }
    $length = strlen($content);
     $mode = ($flags &FILE_APPEND) ? 'a' : 'w';
     $use_inc_path = ($flags &FILE_USE_INCLUDE_PATH) ? true : false;
     if (($fh = @fopen($filename, $mode, $use_inc_path)) === false) {
        user_error('file_put_contents() failed to open stream: Permission denied',
             E_USER_WARNING);
         return false;
         }
    $bytes = 0;
     if (($bytes = @fwrite($fh, $content)) === false) {
        $errormsg = sprintf('file_put_contents() Failed to write %d bytes to %s',
             $length,
             $filename);
         user_error($errormsg, E_USER_WARNING);
         return false;
         }
    @fclose($fh);
     if ($bytes != $length) {
        $errormsg = sprintf('file_put_contents() Only %d of %d bytes written, possibly out of free disk space.',
             $bytes,
             $length);
         user_error($errormsg, E_USER_WARNING);
         return false;
         }
    return $bytes;
    }
?>
Back to top
Jorge



Joined: 12 Mar 2006
Posts: 376
Location: Belgium

PostPosted: Wed 14 Feb '07 15:08    Post subject: Reply with quote

Update check first post.

Admin/Mod: maybe clean it up a bit since all problems should be fixed and it should be more user friendly now.

Mod note: clean up Wink
Back to top
condev1972



Joined: 09 Mar 2007
Posts: 1
Location: Germany

PostPosted: Sat 10 Mar '07 0:31    Post subject: Reply with quote

Hello Jorge,

I just found your posts, thanks so much for your work!

Just wanted to provide some feedback:

  • a requirement note at the top of the file saying that the class requires at least PHP >= 4.3.0 (due to the use of "sha1") would be good
  • it might be cleaner to use "trigger_error" instead of "user_error" and "rtrim" instead of "chop" as these are just aliases and could perish. Wink


Thanks,
Tobias
Back to top
Jorge



Joined: 12 Mar 2006
Posts: 376
Location: Belgium

PostPosted: Sat 10 Mar '07 11:55    Post subject: Reply with quote

thanks for the feedback.

Changed it Smile
Back to top


Post new topic   Reply to topic    Apache Forum Index -> Coding & Scripting Corner
Page 1 of 1