<?php
# Konfiguration:
## Freier String:
$config['authname']= 'private area';

## Diese Einstellungen ist auf einem Apache Webserver
## eine "gute Idee" - Nicht ändern.
$config['userfile']='.htpasswd';

## Die folgende Einstellung ist auf einem Apache Webserver
## normalerweise so vorkonfiguriert. Ändern sie diese,
## dann wird das Skript zwar funktionieren, aber der
## Webserver wird Ihre Einstellungen nicht einmal
## Ignorieren, sondern nicht einmal zur Kenntnis nehmen.
$config['htaccessfile']='.htaccess';

# soll die Konfiguration angezeigt werden? (true / false)
# Spielzeug/Debug/Lernen ... muss man nicht haben, kann man aber:
$config['showconfig']=true;


# Ende der Konfiguration
global $config;


error_reporting(E_ALL);
$warnung='';

if (
get_magic_quotes_gpc()) {
    if ( isset(
$_REQUEST ) ) {
        
$_REQUEST=StripSlashesDeepInHash($_REQUEST);
    }
    
    if ( isset(
$_POST) ) {
        
$_POST=StripSlashesDeepInHash($_POST);
    }
    
    if ( isset(
$_GET) ) {
        
$_GET=StripSlashesDeepInHash($_GET);
    }
}


if (! 
file_exists($config['userfile'])) {
    
touch ($config['userfile']);
}

if (! 
file_exists($config['htaccessfile'])) {
    
touch ($config['htaccessfile']);
}

if (! 
file_exists($config['userfile'])) {
    die(
'Fatal: Die Datei "'.$config['userfile'].'" konnte nicht angelegt werden. Überprüfen Sie, ob der Webserver Schreibrechte am Verzeichnis "'.dirname($_SERVER['SCRIPT_FILENAME']).'" hat.');
}

if (! 
file_exists($config['htaccessfile'])) {
    die(
'Fatal: Die Datei "'.$config['htaccessfile'].'" konnte nicht angelegt werden. Überprüfen Sie, ob der Webserver Schreibrechte am Verzeichnis "'.dirname($_SERVER['SCRIPT_FILENAME']).'" hat.');
}

if (! 
is_readable($config['userfile'])) {
    die(
'Fatal: Die Datei "'.$config['userfile'].'" existiert, der Webserver hat aber keine Leserechte. (Lösung: Setzen mit "chmod 666 '.$config['userfile'].'"' );
}

if (! 
is_readable($config['htaccessfile'])) {
    die(
'Fatal: Die Datei "'.$config['htaccessfile'].'" existiert, der Webserver hat aber keine Leserechte. (Lösung: Setzen mit "chmod 666 '.$config['htaccessfile'].'"' );
}

if (! 
is_writable($config['userfile'])) {
    die(
'Fatal: Die Datei "'.$config['userfile'].'" existiert, der Webserver hat aber keine Schreibrechte. (Lösung: Setzen mit "chmod 666 '.$config['userfile'].'"' );
}

if (! 
is_writable($config['htaccessfile'])) {
    die(
'Fatal: Die Datei "'.$config['htaccessfile'].'" existiert, der Webserver hat aber keine Schreibrechte. (Lösung: Setzen mit "chmod 666 '.$config['htaccessfile'].'"' );
}


if (isset(
$_POST['user']) && $_POST['user'] && isset($_POST['pass']) && ($_POST['pass'])) {
    
#Benutzer anlegen
    
$user=trim($_POST['user']);
    
$pass=trim($_POST['pass']);
    if (! 
AddUser($config['userfile'], $user$pass)) {
        
$warnung='<script type="text/javascript">
        alert("Der Benutzer wurde nicht angelegt. (Enthält der Benutzername unzulässige Zeichen?)")
        </script>'
;
    }
}


if (isset(
$_GET['kill']) && $_GET['kill']) {    
    
$user=trim($_GET['kill']);
    if (
        ! 
CheckHtaccess($GLOBALS['config']['htaccessfile']) 
        || (
            isset(
$_SERVER["PHP_AUTH_USER"]) 
            && 
$strUser != $_SERVER["PHP_AUTH_USER"]
        )
    ) {
        
KillUser ($config['userfile'],$user);
    } else {
        
$warnung.='<script type="text/javascript">
        alert("Sie können sich selbst nicht löschen! Sie können aber Ihr Passwort ändern.")
        </script>'
;
    }
}

if (isset(
$_POST['Ein']) && $_POST['Ein']) {
    
$arUsers=GetUserArray($config['userfile']);
    if ( (isset(
$arUsers[0])) && ($arUsers[0]) ) {
        
AddToHtaccess($config['htaccessfile'], $config['userfile'], $config['authname']);
        
header('Location: http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?tw='.md5(microtime()));
        exit;
    } else {
        
$warnung.='<script type="text/javascript">
        alert("Der Schutz kann nicht aktiviert werden, weil (noch) keine Benutzer existieren. Legen Sie mindestens einen Benutzer an.")
        </script>'
;

    }
}

if (isset(
$_POST['Aus']) && $_POST['Aus']) {
    
DelFromHtaccess($config['htaccessfile']);
}

if (
CheckHtaccess($config['htaccessfile'])) {
    
$strSchutz="Der Verzeichnisschutz ist eingeschaltet.";
    
$strShowEinbutton="none";
    
$strShowAusbutton="inline";
} else {
    
$strSchutz="Der Verzeichnisschutz ist ausgeschaltet.";
    
$strShowEinbutton="inline";
    
$strShowAusbutton="none";
}

/* 
    Funktionen

*/
    
function StripSlashesDeepInHash($hash) {
        if (! isset(
$hash)) { 
            die (
"Fatal: kein Wert an Funktion 'TrimAndStripSlashesDeepInHash' uebergeben. Datei: ".$_SERVER['SCRIPT_NAME']); 
        }
        if (
is_array($hash)) {
            
$arKeys=array_keys($hash);
            foreach (
$arKeys as $strKey) {
                if (
is_array($hash[$strKey])) {
                    
$hash[$strKey]=StripSlashesDeepInHash($hash[$strKey]);
                } else {
                    
$hash[$strKey]=stripslashes($hash[$strKey]);
                }
            }
        } else {
            
$hash=stripslashes($hash);
        }
        return 
$hash;
}

    function 
GetUserArray($userfile) {
        
$users=array();
        
$arLines=file($userfile);
        foreach (
$arLines as $strLine) {
            
$parts=array();
            
$parts=explode(':'$strLine,2);
            
$parts[0]=trim($parts[0]);
            if (
'' != $parts[0]) {
                
$users[]=$parts[0];
            }
        }
        
$dummy=sort($users);
        return 
$users;
    }

    function 
PrintUserList($userfile) {
        
$arUsers=GetUserArray($userfile);
        print 
"        <ul type=\"none\">\n";
            foreach (
$arUsers as $strUser) {
                
$strUser=trim($strUser);
                if (
                    ! 
CheckHtaccess($GLOBALS['config']['htaccessfile']) 
                    || (
                        isset(
$_SERVER["PHP_AUTH_USER"]) 
                        && 
$strUser != $_SERVER["PHP_AUTH_USER"]
                    )
                ) {
                    print 
'            <li class="t2" title="Diesen Benutzer löschen ..." onmouseover="this.style.backgroundColor=\'#ffa\'"onmouseout="this.style.backgroundColor=\'#fff\'" onclick="Ask(\''.urlencode($strUser).'\')">'.htmlentities($strUser)."</li>\n";
                } else {
                    print 
'            <li title="Aktueller Benutzer ist nicht löschbar." class="t2i">'.htmlentities($strUser)."</li>\n";
                }
            }
        print 
"        </ul>\n";
    }


    function 
PrintFile($file) {    
        
$ar=file($file);
        
$str=htmlentities(implode("",$ar));
        print 
"<pre>$str</pre>";
    }

    function 
KillUser($userfile$user) {
        
$newFile='';
        
$arFile=file($userfile);
        foreach (
$arFile as $strLine) {
            
$arLine=explode(':',$strLine,2);
            if (
$arLine[0] != $user && $arLine[0] != '' && isset($arLine[1])) {
                
$newFile.=$arLine[0].':'.trim($arLine[1])."\n";
            }
        }
        
$FH=fopen($userfile,'w');
        
fwrite ($FH$newFile);
        
fclose($FH);
    }

    function 
AddUser($userfile$user$password) {
        
KillUser($userfile$user);
        if (
strpos(':',$user)) {
            return 
false;
        }
        
$apachepassword  md5crypt_apache($password);
        
$newline=$user.':'.$apachepassword ;

        
$FH=fopen($userfile,'a');
        
fwrite ($FH$newline);
        
fclose($FH);
        return 
true;
    }    
        

    

    function 
AddToHtaccess($htaccessfile$userfile$authname) {
        
$text='
AuthType basic
AuthName "'
.$authname.'"
AuthUserFile '
.dirname($_SERVER['SCRIPT_FILENAME']).'/'.$userfile.'
Require valid-user
'
;
        
$FH=fopen($htaccessfile,'a');
        
fwrite ($FH$text);
        
fclose($FH);
    }

    function 
DelFromHtaccess($htaccessfile) {
        
$write=true;
        
$text='';
        
$arFile=array();
        
$arFile=file($htaccessfile);
        
#print_r($arFile);exit;
        
foreach ($arFile as $strLine) {
            
$strLine=trim($strLine);
            if (
$strLine !='') {
            if (! 
strpos($strLine'uth')) {
            if (! 
strpos($strLine'valid-user')) {
                
$text.=$strLine."\n";
            }
            }
            }
        }
        
$FH=fopen($htaccessfile,'w');
        
fwrite ($FH$text);
        
fclose($FH);
    }

    function 
CheckHtaccess($htaccessfile) {
        
$arFile=file($htaccessfile);
        
$bol=false;
            foreach (
$arFile as $strLine) {
            
$strLine=trim($strLine);
            if (
$strLine !='') {
            if (
strpos($strLine'uth')) {$bol=true;}
            if (
strpos($strLine'valid-user')) {$bol=true;}
            }
            
        }
        return 
$bol;
    }
    



/**
    This part is based on a script written by
    
    - Dennis Riehle <selfhtml@riehle-web.com>
    
    Based on
    
    - perl's Crypt::PasswdMD5 by Luis Munoz (lem@cantv.net)
    - phyton's md5crypt.py by Michal Wallace http://www.sabren.com/
    - /usr/src/libcrypt/crypt.c from FreeBSD 2.2.5-RELEASE
    
    Many thanks to
    
    - Fabian Steiner <info@fabis-site.net>
    without him this script would not work!!
    
    Version:   1.0 stable
    
    Last edit: Tue, 13 September 2005 13:49:28 GMT
    
    
    
    USAGE
    
    
    $cryptedpassword = md5crypt_unix   ($password [, $salt [, $magicstring ]);
    
    $apachepassword  = md5crypt_apache ($password [, $salt]);
    
    
    DESCRIPTION
    
    unix_md5_crypt() provides a crypt()-compatible interface to the
    rather new MD5-based crypt() function found in modern operating systems.
    It's based on the implementation found on FreeBSD 2.2.[56]-RELEASE and
    contains the following license in it:
    "THE BEER-WARE LICENSE" (Revision 42):
    <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
    can do whatever you want with this stuff. If we meet some day, and you think
    this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
    apache_md5_crypt() provides a function compatible with Apache's
    .htpasswd files. This was contributed by Bryan Hart <bryan@eai.com>.
*/
    
    
function get_itoa64() {
        return 
'./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    }
    

    function 
md5crypt_to64($v$n) {
        
$itoa64 get_itoa64();
        
$ret '';
        while(--
$n >= 0) {
            
$ret .= $itoa64{$v 0x3f};   
            
$v $v >> 6;
        }
    return 
$ret;
    }
    
    function 
md5crypt_apache($pw$salt NULL) {
        
$Magic '$apr1$';
        return 
md5crypt_unix($pw$salt$Magic);
    }
    
    
    function 
md5crypt_unix($pw$salt NULL$Magic '$1$') {
        
$itoa64 get_itoa64();
        if(
$salt !== NULL) {
            
// Take care of the magic string if present
            
if(substr($salt0strlen($Magic)) == $Magic) {
                
$salt substr($saltstrlen($Magic), strlen($salt));
            }
            
// Salt can have up to 8 characters
            
$parts explode('$'$salt1);
            
$salt substr($parts[0], 08);
        } else {
            
$salt '';
            
mt_srand((double)(microtime() * 10000000));
            while(
strlen($salt) < 8) {
                
$salt .= $itoa64{mt_rand(0strlen($itoa64)-1)}; # Jörg Reinholz: origin was strlen($itoa64) bit this generate one notice- index 64 not set.
            
}
        }
        
$ctx $pw $Magic $salt;
        
$final pack('H*'md5($pw $salt $pw));
        for (
$pl strlen($pw); $pl 0$pl -= 16) {
            
$ctx .= substr($final0, ($pl 16) ? 16 $pl);
        }
        
// Now the 'weird' xform
        
for($i strlen($pw); $i$i >>= 1) {   
            if(
$i 1) {                    // This comes from the original version,
                
$ctx .= pack("C"0);   // where a memset() is done to $final
            
} else {                        // before this loop
                
$ctx .= $pw{0};
            }
        }
        
$final pack('H*'md5($ctx));         // The following is supposed to make
                            // things run slower
        
for($i 0$i 1000$i++) {
            
$ctx1 '';
            if(
$i 1) {
                
$ctx1 .= $pw;
            } else {
                
$ctx1 .= substr($final016);
            }
            if(
$i 3) { $ctx1 .= $salt; }
            if(
$i 7) { $ctx1 .= $pw; }
            if(
$i 1) {
                
$ctx1 .= substr($final016);
            } else {
                
$ctx1 .= $pw;
            }
            
$final pack('H*'md5($ctx1));
        }
        
// Final xform
        
$passwd '';
        
$passwd .= md5crypt_to64((intval(ord($final{0})) << 16)
                    |(
intval(ord($final{6})) << 8)
                    |(
intval(ord($final{12}))),4);
        
$passwd .= md5crypt_to64((intval(ord($final{1})) << 16)
                    |(
intval(ord($final{7})) << 8)
                    |(
intval(ord($final{13}))), 4);
        
$passwd .= md5crypt_to64((intval(ord($final{2})) << 16)
                    |(
intval(ord($final{8})) << 8)
                    |(
intval(ord($final{14}))), 4);
        
$passwd .= md5crypt_to64((intval(ord($final{3})) << 16)
                    |(
intval(ord($final{9})) << 8)
                    |(
intval(ord($final{15}))), 4);
        
$passwd .= md5crypt_to64((intval(ord($final{4}) << 16)
                    |(
intval(ord($final{10})) << 8)                       
                    |(
intval(ord($final{5})))), 4);
        
$passwd .= md5crypt_to64((intval(ord($final{11}))), 2);
        
// Return the final string
        
return $Magic $salt '$' $passwd;
    }
# end of the helpful script from Dennis Riehle
 



    
    
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
       "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <TITLE>Passwortverwaltung</TITLE>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15">
        <meta name="Author" content="Jörg Reinholz, fastix Webdesign &amp; Consult">
        <meta name="Publisher" content="Jörg Reinholz, fastix Webdesign &amp; Consult">
        <meta name="Copyright" content="Jörg Reinholz, fastix Webdesign &amp; Consult">
        <meta name="Robots" content="NOINDEX,NOFOLLOW">
        <style type="text/css">
            body, html, form {
                padding:0;
                margin:0;
                font-family:helvetica, arial, sans-serif;
                background-color:#ddd;
                font-size:1.0001em;
            }
            h1 {
                margin-top:0;
                font-size:2em;
                padding:.7em;
                padding-left:1em;
                background-color:#006;
                color:#fff;
                border-bottom:2px solid #000;
                font-family: times, serif;
            }
            #inhalt {
                position:absolute;
                top:6em;
                left:2em;
                bottom:4em;
                width:25em;
                padding:1em;
                overflow:auto;
            }

            #inhalt2 {
                position:absolute;
                top:6em;
                left:30em;
                bottom:4em;
                padding:1em;
                overflow:auto;
            }
            .t1 {
                display:block;
                width:6em;
                float:left;
            }
            .t2 {
                background-color:#fff;
                padding:.3em;
                border:1px solid #cc0;
                margin-top:-1px;
                cursor:pointer;
            }
            .t2i {
                background-color:#ddd;
                color:888;
                padding:.3em;
                border:1px solid #cc0;
                margin-top:-1px;
            }
            .t3 {
                text-align:center;
                font-weight:bold;
                color:red;
            }
            legend {
                font-weight:bold;
                font-size:.8em;
                font-family:times, serif;
            }
            fieldset {
                margin-bottom:2em;
            }
            #fastix {
                position:absolute;
                top:100%;
                left:0;
                right:0;
                margin-top:-3.2em;
                font-size:.8em;
                padding:.7em;
                padding-left:1em;
                background-color:#006;
                color:#fff;
                border-top:.2em solid #000;    
            }
            #fastix a:link, #fastix a:visited , #fastix a:hover , #fastix a:focus {
                color: #fff;
            }
            .subline {
                font-size:50%;
            }
            input {
                font-family:helvetica, arial, sans-serif;
            }
            #Ein {
                width:10em;
                display:<?php print $strShowEinbutton?>
            }
            #Aus {
                width:10em;
                display:<?php print $strShowAusbutton?>
            }
        </style>
        <script type="text/javascript">
            function Ask(user) {
                if (confirm('Wollen Sie den Benutzer "'+user+'" wirklich löschen?')) {
                    this.location.href="<?php echo $_SERVER['PHP_SELF'];?>?kill="+user;
                } else {            
                    return 0;
                }
            }
        </script>
        <?php echo $warnung?>
    </head>
    <body onload="document.getElementById('user').focus();">

        <h1 id="js_on" style="display:none">Benutzerverwaltung<span class="subline"><br>für das Verzeichnis: <?php print htmlentities(dirname($_SERVER['SCRIPT_FILENAME']));?></span></h1>
        <script type="text/javascript">
            document.getElementById('js_on').style.display='block';
        </script>

        <noscript><h1 style="postion:absolute;top:0;left:0;z-index:99">Bitte aktivieren Sie Java-Script!<span class="subline"><br>(Sonst wird hier nicht alles funktionieren...)</span></h1></noscript>

        <div id="inhalt">
        <p><strong>Hinweis:</strong> Um einem Benutzer ein neues Passwort zuzuweisen legen Sie diesen neu an. Vorheriges Löschen ist <em>nicht</em> notwendig.</p>
        <form action="<?php echo $_SERVER['PHP_SELF'];?>?tw=<?php echo md5(microtime()); ?>" method="post">
            <fieldset><legend>Verzeichnisschutz:</legend>
            <div class='t3'><?php echo $strSchutz?><br>
            <input id="Ein" type="submit" name="Ein" value="Einschalten">&nbsp;<input id="Aus" type="submit" name="Aus" value="Ausschalten"></div>
            </fieldset>
        </form>
        <form action="<?php echo $_SERVER['PHP_SELF'];?>?tw=<?php echo md5(microtime()); ?>" method="post">
            <fieldset><legend>Neuen Benutzer anlegen:</legend>
                 <label class="t1">Benutzer:</label><input type="text" id='user' name="user"><br clear="all">
                 <label class="t1">Passwort:</label><input type="text" name="pass"><br clear="all">
                <label class="t1">&nbsp;</label><input type="submit" name="neu" value="Eintragen">
                <br clear="all">
            </fieldset>
        </form>
        <fieldset><legend>Benutzer löschen:</legend>
        <?php PrintUserList($config['userfile'],'htpasswd-kill.php?kill=ELEMENT''Ask()'); ?>
        </fieldset>
        </div>

<?php if ($config['showconfig']) { ?>
        <div id="inhalt2">
        <p>Hier sehen Sie Dateien, die mit diesem Skript bearbeitet werden.<br>
        Welche das sind bestimmen Sie im Konfigurationsteil.</p>
        <fieldset><legend>Inhalt der Datei <?php echo $config['userfile']; ?>:</legend>
<?php PrintFile($config['userfile']); ?>
        </fieldset>        

        <fieldset><legend>Inhalt der Datei <?php echo $config['htaccessfile']; ?>:</legend>
<?php PrintFile($config['htaccessfile']); ?>
        </fieldset>    

        </div>
<?php ?>
        <p id="fastix">Version 2.5.2 von Jörg Reinholz (<a href="http://www.fastix.de">http://www.fastix.de</a>) - MD5 Passwortgenerator von Dennis Riehle (<a href="http://riehle-web.com">http://riehle-web.com</a>)</p>

    </body>
</html>