<?php
// 完成svn修改密码的功能.
error_reporting(0);
ini_set('display_errors', '1');

if($_POST){
   $md5 = reutnrmd5($_POST['UNIQUE_ID']);
   $recode = array();
   $recode['code'] = -1;
   if($md5 !== $_POST['unqid']){
      $recode['msg'] = '无法识别的操作请求!';
      echo json_encode($recode);
      exit();
   }else if($_POST['PHP_AUTH_USER'] !== $_SERVER['PHP_AUTH_USER']){
      $recode['msg'] ='无法识别的用户名请求!';
      echo json_encode($recode);
      exit();
   }else if($_POST['oldpass'] !== $_SERVER['PHP_AUTH_PW']){
      $recode['msg'] ='无法识别的用户旧密码!';
      echo json_encode($recode);
      exit();
   }else if($_POST['newpass'] !== $_POST['newpass2']){
      $recode['msg'] ='不一致的用户新密码!';
      echo json_encode($recode);
      exit();
   }
   
   $updatepass = new Htpasswd(realpath('../users.conf'));
   if($updatepass->updateUser($_SERVER['PHP_AUTH_USER'],$_POST['newpass'],Htpasswd::ENCTYPE_APR_MD5)){  
      $recode['msg'] ='密码修改成功!';
      $recode['code'] = 0;
      echo json_encode($recode);
      exit();
   }else{
     $recode['msg'] ='密码修改失败!';
     echo json_encode($recode);
     exit();
   }
}

header("Content-type: text/javascript;charset=utf-8");
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past

$redata = array();
$redata['AUTH_TYPE'] = $_SERVER['AUTH_TYPE'];
$redata['PHP_AUTH_USER'] = $_SERVER['PHP_AUTH_USER'];

$redata['UNIQUE_ID'] = $_SERVER['UNIQUE_ID'];
$redata['REQUEST_TIME'] = $_SERVER['REQUEST_TIME'];
$redata['SERVER_ADDR'] = $_SERVER['SERVER_ADDR'];
$redata['HTTP_REFERER'] = $_SERVER['HTTP_REFERER'];
!$_SERVER['HTTP_REFERER'] && $_SERVER['HTTP_REFERER'] = $_SERVER['UNIQUE_ID'];
$unqid = reutnrmd5($redata['UNIQUE_ID']);

$data = json_encode($redata);

function reutnrmd5($key){
    return md5(md5($_SERVER['HTTP_REFERER'].$_SERVER['PHP_AUTH_USER'].$_SERVER['PHP_AUTH_PW']).$key);   
}

class Htpasswd{
    /**
     * @var string
     */
    private $_filename;
    private $_users = array();

    const ENCTYPE_CRYPT   = 'crypt';
    const ENCTYPE_APR_MD5 = 'apr_md5';
    const ENCTYPE_SHA1    = 'sha1';

    public function __construct($filename)
    {
        if (!trim($filename)) {
            throw new InvalidArgumentException('File name not sent');
        }

        if (!file_exists($filename)) {
            throw new Exception('File not found');
        }

        $lines = file($filename);

        if (count($lines)) {
            foreach ($lines as $line) {
                $line = trim($line);
                list($user, $pass) = explode(':', $line);
                $this->_users[$user] = $pass;
            }
        }

        /**
         * Filename
         */
        $this->_filename = $filename;
    }

    public function userExists($username)
    {
        return array_key_exists($username, $this->_users);
    }

    public function addUser($username, $password, $encType = self::ENCTYPE_CRYPT)
    {
        if ($this->userExists($username)) {
            return false;
        }

        return $this->updateUser($username, $password, $encType);
    }

    public function deleteUser($username)
    {
        if (!$this->userExists($username)) {
            throw new Exception('User not found');
        }

        unset($this->_users[$username]);

        $this->_saveFile();
    }

    public function updateUser($username, $password, $encType = self::ENCTYPE_CRYPT)
    {
        $this->_validateUserName($username);

        $this->_users[$username] = $this->_encryptPassword($password, $encType);
        $this->_saveFile();

        return true;
    }

    private function _encryptPassword($password, $encType)
    {
        if ($encType == self::ENCTYPE_CRYPT) {
            if (strlen($password) > 8) {
                trigger_error('Only the first 8 characters are taken into account when \'crypt\' algorithm is used.');
            }

            $chars     = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
            $len       = strlen($chars) - 1;
            $salt      = $chars[mt_rand(0, $len)] . $chars[mt_rand(0, $len)];
            $cryptPass = crypt($password, $salt);
        } elseif ($encType == self::ENCTYPE_APR_MD5) {
            $cryptPass = $this->_cryptApr1Md5($password);
        } elseif ($encType == self::ENCTYPE_SHA1) {
            $hash      = base64_encode(sha1($password, true));
            $cryptPass = '{SHA}' . $hash;
        } else {
            throw new Exception('Invalid encryption type');
        }

        return $cryptPass;
    }

    private function _validateUserName($username)
    {
        if (strpos($username, ':')) {
            throw new Exception('Invalid username. Username cannot contain colon (:) character');
        }

        if (strlen($username) > 256) {
            throw new Exception('Usernames cannot be longer than 256 bytes');
        }
    }

    private function _saveFile()
    {
        $data = '';
        foreach ($this->_users as $username => $pass) {
            $data .= "$username:$pass\n";
        }

        file_put_contents($this->_filename, $data, LOCK_EX);
    }

    private function _cryptApr1Md5($plainpasswd)
    {
        $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));
        }

        $tmp = '';
        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;
    }
}

?>
var qsvninfo = <?php echo $data;?>;
var unqid = '<?php echo $unqid;?>';
$('.user').before('User:'+qsvninfo['PHP_AUTH_USER']+', ');