<?php
/*
	GenPWD
	A tool to generate .htpasswd files
	Made by Jefrey S. Santos - jefrey[at]jefrey.ml
*/

/* Set this to true before using this tool.
	This is just a security measure to prevent
	people from accessing this file. */
$Enabled = true;

/* Specify the users and their passwords in the
	following format:
	user => pass
	Be'ware with the comma. The first item does not
	need a comma at its starting. */
$Users = array(
	// user => pass
	 'user' => 'pass'
	,'user2' => 'pass2'
);

/* The method used to encrypt the password.
	Edit only if you really know what you're doing.
	Available methods:
	 'md5' (APR1-MD5): base64 encoded, salted and 1000-times encoded MD5
	 'sha' (SHA1): base64 encoded SHA1 hash
	 'crypt' (not recommended): Unix Standard DES-based encryption */
$Method = "md5";

/* File name to save in. Default is .htpasswd
	You can use relative paths here.
	You can also write 'PHPOUT' if you want the result
	to be echoed. */
$Filename = ".htpasswd";

/* What to do if $Filename already exists?
	Available options:
	 'add' = will just append the new users to the file
	 'replace' = will replace the file contents */
$OnFileExists = 'add';

/* Will this script also generate the .htaccess needed file? */
$GenerateHtaccess = True;

/* Where do you want it to be saved? */
$HtaccessFileName = ".htaccess";

/* What text will it show in the require password window? */
$AuthName = "Test";

/* Where will .htpasswd be on the server? Full path please.
	You can also use <autodetect> to get "genpwd.php" (this file) path. */
$AuthUserFile = '<autodetect>/.htpasswd';
	
echo 'done';

/**********************************************\
|	YOU DO NOT NEED TO EDIT THE LINES BELOW    |
\**********************************************/
 
 if(!$Enabled) die('not enabled');
 
 switch($Method) {
	case "md5":
		savefile($Filename, gen_md5($Users), $OnFileExists);
		break;
		
	case "sha":
		savefile($Filename, gen_sha($Users), $OnFileExists);
		break;
		
	case "crypt":
		savefile($Filename, gen_crypt($Users), $OnFileExists);
		break;
 }
 
 if($GenerateHtaccess) {
	$AuthUserFile = str_replace("<autodetect>", dirname(__FILE__), $AuthUserFile);
	$content = 'AuthType Basic'."\n"
		.'AuthName "'.$AuthName.'"'."\n"
		.'AuthUserFile '.$AuthUserFile."\n"
		.'Require valid-user';
	savefile($HtaccessFileName, $content, "add");
 }
 
 function savefile($fname, $content, $ifexists) {
	if($ifexists=='add') {
		$mode = "a+";
		if(file_exists($fname) AND @filesize($fname)) $content = "\n".$content;
	} else
		$mode = "w";
	$handle = fopen($fname, $mode);
	fwrite($handle, $content);
	fclose($handle);
 }
 
 function gen_md5($usr) {
	$ret = array();
	foreach($usr as $user=>$pass) {
		$ret[] = $user.":".crypt_apr1_md5($pass);
	}
	return implode("\n", $ret);
 }
 
 function gen_sha($usr) {
	$ret = array();
	foreach($usr as $user=>$pass) {
		$ret[] = $user.":".base64_encode(sha1($pass));
	}
	return implode("\n", $ret);
 }
 
 function gen_crypt($usr) {
	$ret = array();
	foreach($usr as $user=>$pass) {
		$ret[] = $user.":".crypt($pass, base64_encode($pass));
	}
 }
 
 
 function crypt_apr1_md5($plainpasswd)
{	// taken from http://stackoverflow.com/questions/1038791/how-to-programmaticaly-build-an-apr1-md5-using-php
	$tmp = null;
    $salt = substr(str_shuffle("abcdefghijklmnopqrstuvwxyz0123456789"), 0, 8);
    $len = strlen($plainpasswd);
    $text = $plainpasswd.'$apr1$'.$salt;
    $bin = pack("H32", md5($plainpasswd.$salt.$plainpasswd));
    for($i = $len; $i > 0; $i -= 16) { $text .= substr($bin, 0, min(16, $i)); }
    for($i = $len; $i > 0; $i >>= 1) { $text .= ($i & 1) ? chr(0) : $plainpasswd{0}; }
    $bin = pack("H32", md5($text));
    for($i = 0; $i < 1000; $i++)
    {
        $new = ($i & 1) ? $plainpasswd : $bin;
        if ($i % 3) $new .= $salt;
        if ($i % 7) $new .= $plainpasswd;
        $new .= ($i & 1) ? $bin : $plainpasswd;
        $bin = pack("H32", md5($new));
    }
    for ($i = 0; $i < 5; $i++)
    {
        $k = $i + 6;
        $j = $i + 12;
        if ($j == 16) $j = 5;
        $tmp = $bin[$i].$bin[$k].$bin[$j].$tmp;
    }
    $tmp = chr(0).chr(0).$bin[11].$tmp;
    $tmp = strtr(strrev(substr(base64_encode($tmp), 2)),
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
 
    return "$"."apr1"."$".$salt."$".$tmp;
}