<?
class MemberZone
{
var $_createtable="CREATE TABLE IF NOT EXISTS MemberZone
(UserId int(11) NOT NULL auto_increment,
UserLevel int(3) not null default 1,
Name varchar(30) NOT NULL default 'Name',
Vorname varchar(50) NOT NULL default 'Vorname',
UserName varchar(12) NOT NULL default '',
UserPasswd varchar(32) NOT NULL default '',
UserMail varchar(150) NOT NULL default '',
UserSession varchar(32) default NULL,
UserLogin datetime default NULL,
LastAction datetime NOT NULL default 0,
UserLogout datetime NOT NULL default 0,
UserActive varchar(32) NOT NULL default '',
UserRegisteredAt datetime NULL,
FailedLogins int(11) NOT NULL default 0,
PRIMARY KEY (UserId),
UNIQUE KEY UserSession (UserSession),
UNIQUE KEY UserName (UserName),
UNIQUE KEY UserMail (UserMail))
TYPE=INNODB";
var $_addAdmin="INSERT INTO MemberZone
(UserLevel,UserName,UserPasswd,UserMail,UserActive,UserRegisteredAt)
VALUES
(1000,'admin',MD5('admin'),'mail@localhost.de','1',Now())";
var $_db=array
('host' => 'localhost',
'user' => '',
'pass' => '',
'name' => '',
'table' => 'MemberZone',
'link' => NULL);
var $_password=array
('letters' => 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
'numbers' => '0123456789',
'specials' => '!§$%&/()=[]}+*~#-_');
var $init_ok=false;
var $timeout=600;
var $logoutafter=-1;
var $discardafter=2;
var $usecookie=false;
var $MaxFailedLogins=3;
var $_new_pw=NULL;
var $_sql=array();
var $activation_link=NULL;
var $_errors=array();
//***************
//
//Public - Methoden
//
//***************
function MemberZone($sessionname='mz',$timeout=600,$logoutafter=-1,$discardafter=2,$usecookie=false)
//Konstruktor
{
//Name der Session festlegen und Session starten
@session_name($sessionname);
@session_start();
//Zufallsgenerator initialisieren
mt_srand((double)microtime()*1000000);
//DB-Verbindung herstellen
$this->_db['link']=mysql_connect($this->_db['host'],$this->_db['user'],$this->_db['pass']);
@mysql_select_db($this->_db['name'],$this->_db['link']) or $this->_add_error('DB waehlen',mysql_errno(),mysql_error());
//Tabelle erstellen, falls noch nicht vorhanden
$this->_runQuery($this->_createtable);
//Standarduser hinzufügen
$this->_runQuery($this->_addAdmin,false);
//Initialisierung erfolgreich?
$this->init_ok=!(isset($this->_errors) and count($this->_errors)>0);
$this->activation_link=$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?activate=';
if (!preg_match('%^http%siU',$this->activation_link))
$this->activation_link='http://'.$this->activation_link;
$this->set_timeout($timeout);
$this->set_logoutafter($logoutafter);
$this->set_discardafter($discardafter);
if (isset($_COOKIE[$sessionname.'login'])and !$this->logged_in())
$this->_cookie_login($_COOKIE[$sessionname.'login']);
$this->set_usecookie($usecookie);
}
function login($user,$pass,$ignore_already_logged_in=false)
//Login
{
if (!$this->init_ok) //Keine Initialisierung => Abbrechen
{
$this->_add_error('Login',-1000,'Klasse nicht erfolgreich initialisiert.');
return false;
}
$sql="SELECT UserId, UserActive, (Now()-LastAction) as UserIdle, FailedLogins FROM ".$this->_db['table']."
WHERE UserName='$user' AND UserPasswd=MD5('$pass')";
$result=$this->_runQuery($sql,false);
if (@mysql_num_rows($result)!=1) //Kein passender Datensatz gefunden
{
$this->_add_error('Login',-1,'Kombination aus '.$user.' und '.$pass.' ist nicht korrekt.');
if ($this->_password_false($user))
$this->_incFailedLogins($user);
return false;
}
$userinfo=mysql_fetch_array($result,MYSQL_ASSOC);
if ($userinfo['FailedLogins']>=$this->MaxFailedLogins)
{
$this->_add_error('Login',-3,'Zu viel fehlerhafte Logins');
return false;
}
if ($userinfo['UserActive']!=1)
{
$this->_add_error('Login',-12,'User '.$user.' ist bis jetzt noch nicht freigeschalten worden.');
return false;
}
if ($ignore_already_logged_in)
return $this->_login($userinfo['UserId']);
else
if (!empty($userinfo['UserLogin']) and ($userinfo['UserIdle']<$this->timeout or $this->timeout==-1))
{
//User ist bereits eingeloggt, kein weiteres Einloggen erlaubt
$this->_add_error('Login',-2,'User '.$user.' ist bereits eingeloggt.');
return false;
}
else //Alles OK, einloggen
return $this->_login($userinfo['UserId']);
}
function logged_in()
//Ist der User eingeloggt?
{
if (!$this->init_ok) //Keine Initialisierung => Abbrechen
{
$this->_add_error('Login-Check',-1000,'Klasse nicht erfolgreich initialisiert.');
return false;
}
//Steht die aktuelle Session-ID in der DB, ist der User eingeloggt
$sql="SELECT UserId,(Now()-LastAction) as UserIdle FROM ".$this->_db['table']." WHERE UserSession='".session_id()."'";
$result=$this->_runQuery($sql);
if (@mysql_num_rows($result)>0)
{
$user=mysql_fetch_array($result,MYSQL_ASSOC);
if ($user['UserIdle']<$this->logoutafter or $this->logoutafter==-1)
{
$sql='UPDATE '.$this->_db['table']." SET LastAction = NOW() WHERE UserSession = '".session_id()."'";
$this->_runQuery($sql);
$this->logout_idle();
return true;
}
else
{
$this->logout(session_id());
$this->logout_idle();
return false;
}
}
$this->logout_idle();
return false;
}
function logout($sessionid=NULL)
//User ausloggen
{
if (!$this->init_ok) //Keine Initialisierung => Abbrechen
{
$this->_add_error('Logout',-1000,'Klasse nicht erfolgreich initialisiert.');
return false;
}
if (!isset($sessionid))
$sessionid=session_id();
$sql='UPDATE '.$this->_db['table']." SET UserSession = NULL, LastAction=0,UserLogout=NOW() WHERE UserSession = '".$sessionid."'";
$result=$this->_runQuery($sql);
if ($sessionid==session_id())
if ($result)
{
$this->set_usecookie(false);
setcookie(session_name().'login',session_id(),time()-31536000,'/','',0);
$_SESSION=array();
session_destroy();
return true;
}
else
{
$user=$this->return_user();
$this->_add_error('Logout',-11,"User '".$user['UserName']."' konnte nicht ausgeloggt werden.");
return false;
}
else
return false;
}
function activate_user($activation_id)
//User freischalten
{
$sql='UPDATE '.$this->_db['table']." SET UserActive='1', FailedLogins=0 WHERE UserActive='$activation_id'";
$result=$this->_runQuery($sql);
if (!$result)
{
$sql='SELECT UserName FROM '.$this->_db['table']." WHERE UserActive='$activation_id'";
$user=$this->_runQuery($sql,false);
if ($user)
$this->_add_error('Activate',-200,"User '".$user['UserName']."' konnte nicht freigeschalten werden.");
return false;
}
return $this->_update_ok();
}
function has_Access($UserLevel)
//Ist der Benutzer berechtigt, einen bestimmten Bereich zu betreten?
{
if (!$this->logged_in())
return false;
$user=$this->return_user();
return ($user['UserLevel']>=$UserLevel);
}
function return_new_pw()
{
return $this->_new_pw;
$this->_new_pw=NULL;
}
function set_usecookie($usecookie)
//Soll die Session-ID in einem Cookie gespeichert werden
{
$this->usecookie=$usecookie;
if ($usecookie)
{
$user=$this->return_user();
$logindata=$user['UserId'].'|'.$user['UserPasswd'];
if (!isset($_COOKIE[session_name().'login']) or $_COOKIE[session_name().'login']!=$logindata)
setcookie(session_name().'login',$logindata,time()+31536000,'/','',0);
}
}
function return_usecookie()
//Soll die Session-ID in einem Cookie gespeichert werden
{
return $this->usecookie;
}
function set_timeout($timeout)
//Timeout, nachdem ein erneutes einloggen möglich sein soll
{
$this->timeout=$timeout;
}
function return_timeout()
//Timeout, nachdem ein erneutes einloggen möglich sein soll
{
return $this->timeout;
}
function set_logoutafter($logoutafter)
//Timeout für automatischen Logout setzen
{
$this->logoutafter=$logoutafter;
}
function return_logoutafter()
//Timeout für automatischen Logout zurückliefern
{
return $this->logoutafter;
}
function set_discardafter($discardafter)
//Zeitraum zwischen Anmeldung und Freischaltung
{
$this->discardafter=$discardafter;
}
function return_discardafter()
//Zeitraum zwischen Anmeldung und Freischaltung
{
return $this->discardafter;
}
function return_users()
//ID, Username, UserLogin, LastAction und Idletime (in sec.) der momentan eingelogten User ermitteln
{
if (!$this->init_ok) //Keine Initialisierung => Abbrechen
{
$this->_add_error('Users-Info',-1001,'Klasse nicht erfolgreich initialisiert.');
return false;
}
//Inaktive fliegen raus
$this->logout_idle();
$sql="SELECT UserId, UserName, UserRegisteredAt,UserLogin,UserSession, LastAction, (Now()-LastAction) as UserIdle
FROM ".$this->_db['table']." WHERE UserSession IS NOT NULL";
$result=$this->_runQuery($sql,false);
$users=array();
while ($user=mysql_fetch_array($result,MYSQL_ASSOC))
$users[]=$user;
return (count($users)>0) ? $users : false;
}
function return_user($sid=NULL)
//User-Info zurückliefern
{
if (!$this->init_ok) //Keine Initialisierung => Abbrechen
{
$this->_add_error('User-Info',-1000,'Klasse nicht erfolgreich initialisiert.');
return false;
}
if ($sid==NULL)
$sid=session_id();
$sql="SELECT UserId, UserLevel, Name, Vorname, UserName, UserPasswd, UserMail, UserSession,
UserLogin, LastAction, (Now()-LastAction) as UserIdle,UserRegisteredAt
FROM ".$this->_db['table']." WHERE UserSession='".$sid."'";
$result=$this->_runQuery($sql,false);
$user=mysql_fetch_array($result,MYSQL_ASSOC);
return $user;
}
function add_user($Name, $Vorname, $UserName, $UserPasswd, $UserMail, $UserLevel=1)
//User hinzufügen
{
if (!$this->init_ok) //Keine Initialisierung => Abbrechen
{
$this->_add_error('Neuer User',-1000,'Klasse nicht erfolgreich initialisiert.');
return false;
}
$activation_id=$this->_create_password(32,true,false);
$sql='INSERT INTO '.$this->_db['table']."
(UserLevel, Name, Vorname, UserName, UserPasswd, UserMail,UserRegisteredAt,UserActive,LastAction)
VALUES($UserLevel,'$Name','$Vorname','$UserName',MD5('$UserPasswd'),'$UserMail',Now(),'$activation_id',Now())";
if ($this->_runQuery($sql))
{
$newuser=array('UserName' => $UserName,'ActivationLink' => $this->activation_link.$activation_id);
return $newuser;
}
else
return false;
}
function new_password($mail,$length=8,$use_numbers=true,$use_specials=false,$force_reactivate=false)
//Neues Passwort generieren und in DB eintragen
//Mail an registrierte Adresse wird nicht automatisch verschickt
{
if (!$this->init_ok) //Keine Initialisierung => Abbrechen
{
$this->_add_error('Neues Passwort',-1000,'Klasse nicht erfolgreich initialisiert.');
return false;
}
$this->_new_pw=NULL;
$pass=$this->_create_password($length,$use_numbers,$use_specials);
if ($force_reactivate)
//User soll sich neu freischalten mit neuem Passwort
$useractivate=md5('$pass');
else
$useractivate='1';
$sql='UPDATE '.$this->_db['table']." SET UserActive='$useractivate', UserPasswd = MD5('$pass') WHERE UserMail='$mail'";
$result=$this->_runQuery($sql);
if ($result and $this->_update_ok())
{
$this->_new_pw=array('pass' => $pass,'mail' => $mail, 'activate' => $this->activation_link.$useractivate);
return true;
}
$this->_add_error('Neues Passwort',-21,"Das Passwort konnte nicht geaendert werden.");
return false;
}
function change_password($old,$new,$force_reactivate=false)
//Neues Passwort in DB eintragen
{
if (!$this->init_ok) //Keine Initialisierung => Abbrechen
{
$this->_add_error('Passwort ändern',-1000,'Klasse nicht erfolgreich initialisiert.');
return false;
}
if ($force_reactivate)
//User soll sich neu freischalten mit neuem Passwort
$useractivate=md5('$new');
else
$useractivate='1';
$user=$this->return_user();
$sql='UPDATE '.$this->_db['table']." SET UserActive='$useractivate', UserPasswd = MD5('$new') WHERE UserPasswd = MD5('$old') AND UserID=".$user['UserId'];
$result=$this->_runQuery($sql);
if ($result and $this->_update_ok())
{
if ($force_reactivate)
{
$user=$this->return_user();
$newuser=array('UserName' => $user['UserName'],'ActivationLink' => $this->activation_link.$useractivate);
return $newuser;
}
else
return true;
}
$this->_add_error('Passwort aendern',-21,"Das Passwort konnte nicht geaendert werden.");
return false;
}
function has_errors()
{
if (!$this->init_ok) //Keine Initialisierung => Abbrechen
$this->_add_error('Login',-1000,'Klasse nicht erfolgreich initialisiert.');
return (isset($this->_errors)) ? count($this->_errors)>0 : false;
}
function return_errors()
{
if ($this->has_errors())
return $this->_errors;
}
function reset_errors()
{
unset($this->_errors);
}
function return_sql()
{
if (isset($this->_sql))
return $this->_sql;
}
function free($logout=false)
//Destruktor
{
if (!$this->init_ok) //Keine Initialisierung => Abbrechen
{
$this->_add_error('Login',-1000,'Klasse nicht erfolgreich initialisiert.');
return false;
}
if ($this->logged_in() and $logout)
$this->logout();
elseif ($this->logged_in())
session_destroy();
if(isset($this->_db['link']))
@mysql_close($this->_db['link']) or $this->_add_error('DB-Verbindung beenden',mysql_errno(),mysql_error());
unset($this->_db['link']);
return true;
}
//***************
//
//Private Methoden - _Nicht_ von extern aus aufrufen
//
//***************
function _login($userid)
{
$sql='UPDATE '.$this->_db['table']." SET UserSession = '".session_id()."',UserLogin = NOW(),
LastAction=Now() ,UserLogout=0, FailedLogins=0 WHERE UserId = $userid";
if ($this->_runQuery($sql))
{
if ($this->usecookie)
$this->set_usecookie(true);
return true;
}
else
{
$this->_add_error('Login',-3,"User '".$this->_db['UserName']."' (ID: $userid) konnte nicht eingeloogt werden.");
return false;
}
}
function _runQuery($sql,$add_error=true)
{
$result=@mysql_query($sql,$this->_db['link']);
if (!$result and $add_error)
$this->_add_error('SQL: '.$sql,mysql_errno(),mysql_error());
$this->_add_sql($sql);
return $result;
}
function _add_sql($sql)
{
$eintrag=array('Zeitpunkt' => date('Y-m-d H:i:s'), 'SQL' => $sql);
$this->_sql[]=$eintrag;
}
function _add_error($err_at,$err_no=NULL,$err_desc=NULL)
{
$eintrag=array('where' => $err_at,'Zeitpunkt' => date('Y-m-d H:i:s'),'#'=>$err_no,'desc'=>$err_desc);
$this->_errors[]=$eintrag;
}
function _create_password($length,$use_numbers,$use_specials)
{
$pass=$this->_password['letters'];
if ($use_numbers)
$pass.=$this->_password['numbers'];
if ($use_specials)
$pass.=$this->_password['specials'];
$realpass=NULL;
for($i=0;$i<$length;$i++)
$realpass.=$pass[mt_rand(0,strlen($pass)-1)];
return $realpass;
}
function _cookie_login($relogin)
{
if (!$this->init_ok) //Keine Initialisierung => Abbrechen
{
$this->_add_error('Login',-1000,'Klasse nicht erfolgreich initialisiert.');
return false;
}
$logindata=explode('|',$relogin);
$sql="SELECT UserId, UserActive FROM ".$this->_db['table']." WHERE UserId=".$logindata[0]." AND UserPasswd='".$logindata[1]."'";
$result=$this->_runQuery($sql,false);
if (!@mysql_num_rows($result)>0) //Kein passender Datensatz gefunden
{
$this->_add_error('Login',-1,'Login anhand der Cookie-Daten ist nicht möglich.');
return false;
}
$userinfo=mysql_fetch_array($result,MYSQL_ASSOC);
if ($userinfo['UserActive']!=1)
{
$this->_add_error('Login',-12,'User '.$user.' ist bis jetzt noch nicht freigeschalten worden.');
return false;
}
return $this->_login($userinfo['UserId']);
}
function _password_false($user)
{
if (!$this->init_ok) //Keine Initialisierung => Abbrechen
{
$this->_add_error('Login',-1000,'Klasse nicht erfolgreich initialisiert.');
return false;
}
$sql='SELECT UserId FROM '.$this->_db['table']." WHERE UserName='$user'";
return (mysql_num_rows($this->_runQuery($sql,false))>0);
}
function _incFailedLogins($user)
{
if (!$this->init_ok) //Keine Initialisierung => Abbrechen
{
$this->_add_error('Login',-1000,'Klasse nicht erfolgreich initialisiert.');
return false;
}
$sql='UPDATE '.$this->_db['table']." SET FailedLogins=FailedLogins+1 WHERE UserName='$user'";
$this->_runQuery($sql,false);
$sql='SELECT UserMail, FailedLogins FROM '.$this->_db['table']." WHERE UserName='$user'";
$result=$this->_runQuery($sql,false);
if (mysql_num_rows($result)>0)
{
$failedLogins=mysql_fetch_assoc($result);
if ($failedLogins['FailedLogins']==$this->MaxFailedLogins)
$this->new_password($failedLogins['UserMail'],8,true,false,true);
}
}
function logout_idle()
{
if (!$this->init_ok) //Keine Initialisierung => Abbrechen
{
$this->_add_error('Login',-1000,'Klasse nicht erfolgreich initialisiert.');
return false;
}
if ($this->logoutafter!=-1)
{
$sql='UPDATE '.$this->_db['table'].'
SET UserSession = NULL, LastAction=0,UserLogout=NOW()
WHERE (Now()-LastAction)>'.$this->logoutafter;
$this->_runQuery($sql,false);
}
//User, die sich vor mehr als zwei Tagen registriert haben, aber noch nicht freigeschaltet sind, fliegen raus
$sql='DELETE FROM '.$this->_db['table']." WHERE UserActive!='1' AND (UserRegisteredAt + INTERVAL ".$this->discardafter." DAY)<Now() AND (LastAction + INTERVAL ".$this->discardafter." DAY)<Now()";
$this->_runQuery($sql);
}
function _update_ok()
{
return (mysql_affected_rows($this->_db['link'])>0);
}
}
?>