login/pass: error messages below page title
[minimedit.git] / auth.inc.php
old mode 100755 (executable)
new mode 100644 (file)
index ecd29b5..34c83db
 <?php
-global $User, $Admin;
+date_default_timezone_set('Europe/Amsterdam');
 
-call_user_func(function () {
-       if (isset($_SERVER['PHP_AUTH_USER'])) {
-               $authinfo = [ $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ];
+class User
+{
+       public $dir, $login;
+
+       function __construct($dir = NULL, $existing = TRUE)
+       {
+               if (empty($dir)) {
+                       return;
+               }
+               if (!file_exists($dir) and $existing) {
+                       throw new Exception("Gebruiker niet gevonden in $dir");
+               }
+               $this->dir = $dir;
+               $this->login = preg_replace('{.*/}', '', $dir);
        }
-       elseif (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
-               // cgi compatibility
-               $authinfo = explode(':' , base64_decode(substr($_SERVER['REDIRECT_HTTP_AUTHORIZATION'], 6)));
+
+       function __get($col)
+       {
+               return $this->$col = $this->$col();  # run method and cache
        }
-       else {
-               return;
+
+       function rawname()
+       {
+               return rtrim(@file_get_contents("{$this->dir}/name.txt"));
+       }
+
+       function name()
+       {
+               return htmlspecialchars(implode(' & ', explode("\n", $this->rawname)));
+       }
+
+       function html()
+       {
+               $name = htmlspecialchars($this->login);
+               if ($this->name and $this->name != $name) {
+                       $name = "{$this->name}<small> @$name</small>";
+               }
+               return $name;
+       }
+
+       function email()
+       {
+               return rtrim(@file_get_contents("{$this->dir}/email.txt"));
+       }
+
+       function admin($permission = NULL)
+       {
+               if (isset($permission)) {
+                       if (!$this->admin) {
+                               return FALSE;  # empty results
+                       }
+                       preg_match_all('{[ /]}', $permission, $parts, PREG_OFFSET_CAPTURE);
+                       foreach ($parts[0] as $part) {
+                               if (isset($this->admin[substr($permission, 0, $part[1])])) {
+                                       return TRUE;  # partial match
+                               }
+                       }
+                       return isset($this->admin[$permission]);  # check level
+               }
+               if (!$this->dir or !@file_exists("{$this->dir}/.admin")) {
+                       return FALSE;  # not an admin
+               }
+               return array_fill_keys(explode("\n", file_get_contents("{$this->dir}/.admin")), TRUE);
        }
 
-       $pwdata = file_get_contents(__DIR__.'/.htpasswd');
-       $pwlist = [];
-       foreach (explode("\n", $pwdata) as $line) {
-               if (!$line) continue;
-               list ($username, $pass) = explode(':', $line);
-               $pwlist[$username] = $pass;
+       function seen()
+       {
+               return @filemtime("{$this->dir}/last.log");
        }
 
-       list ($authname, $authpass) = $authinfo;
-       $usertest = $pwlist[ strtolower($authname) ];
+       function logclient()
+       {
+               if ($log = @fopen("{$this->dir}/last.log", 'w')) {
+                       $line = $_SERVER['REMOTE_ADDR'].' '.$_SERVER['HTTP_USER_AGENT'];
+                       fwrite($log, $line."\n");
+               }
+       }
+}
+
+function login_password_verify($input, $test)
+{
+       if (substr($test, 0, 1) != '$') {
+               # plaintext match for uncrypted passwords
+               return $input === $test;
+       }
+       return password_verify($input, $test);
+}
+
+function login_setcookie()
+{
+       global $User;
+       return setcookie('login', $User->auth, 0, '/');
+}
+
+function login($inuser, $inpass = NULL)
+{
+       if (empty($inuser)) return;
+       if (!isset($inpass)) {
+               @list ($inuser, $inauth) = explode(':', $inuser, 2);
+       }
+
+       # find password data by user name
+       $userdir = 'profile/'.preg_replace('/[^a-z0-9]+/', '-', strtolower($inuser));
+       $pwfile = "$userdir/.passwd";
+       if (!file_exists($pwfile)) return;
+       $usertest = trim(file_get_contents($pwfile));
        if (!$usertest) return;
 
-       $salt = substr($usertest, 0, 2);
-       if (crypt($authpass, $salt) != $usertest) return;
+       # verify password
+       $authhash = md5($usertest);
+       if (isset($inpass)) {
+               if (!login_password_verify($inpass, $usertest)) return;
+       }
+       else {
+               if ($inauth !== $authhash) return;
+       }
+
+       if (function_exists('apache_note')) apache_note('user', $inuser);
+
+       $user = new User($userdir);
+       $user->logclient();
+       $user->pass = $usertest;
+       $user->auth = "$inuser:$authhash";
+       return $user;
+}
 
-       global $User, $Admin;
-       $User = $authname;
-       $Admin = !empty($User) && $User != 'lid' ? $User : FALSE;
-});
+global $User;
+if (isset($_COOKIE['login'])) {
+       $User = login($_COOKIE['login']);
+}
+if (!$User) {
+       $User = new User;
+}