<?php
define("USER_USERNAME_UNKNOWN", -1);
define("USER_INVALID_PASSWORD", -2);
define("USER_USERNAME_EMPTY", -3);
define("USER_PASSWORD_EMPTY", -4);
define("USER_ABO_FAILURE", -5);
define("USER_ALL_SESSIONS_OCCUPIED", -6);
define("USER_LOGIN_VALID", 1);
define("USER_ACCOUNT_CLOSED", -7);
define("USER_ACCOUNT_NEW", -8);
define("USER_ACCOUNT_OK", "USER_ACCOUNT_OK");
define("USER_USER_NOT_FOUND", -9);
define("SESSION_SESSION_NOT_FOUND", -10);
define("SESSION_TIMEOUT", -11);
define("ABOCHANGE_IBRABO_LOWER", -12);
define("SESSION_TERMINATE_TIMEOUT", -13);
define("SESSION_NOT_VALID_ANYMORE", -14);

// bekannte Module
define("ROLES_IDVERLAG", 1);
define("ROLES_IBR", 4);
define("ROLES_URTEILSPFLEGE", 11);
define("ROLES_IK", 10);
define("ROLES_SCHADIS_FULL", 14);
define("ROLES_BECK_VOB_A_B", 15);
define("ROLES_BECK_VHB_priv_BauR", 16);
define("ROLES_BECK_VOB_B", 17);
define("ROLES_BECK_Komp_BauR", 18);
define("ROLES_BECK_VOB_C", 19);
define("ROLES_BECK_Praxis_HOAI", 20);
define("ROLES_BECK_NZBau", 21);
define("ROLES_BECK_BNV", 22);
define("ROLES_BECK_BauGB", 23);
define("ROLES_BECK_K_WEG", 24);
define("ROLES_BECK_Miete", 25);
define("ROLES_BECK_GewrMr", 26);

// {{{ User
/**
 * Hier werden alle einen Benutzer betreffenden Informationen verarbeitet
 *
 * @access public
 * @static
 */
class User
{
	// {{{ Eigenschaften
  /**
   * Die ID eines Benutzers
   *
   * Mögliche Werte: 0 (unbekannter Benutzer) oder die ID aus der Datenbank
   *
   * @var int
   */
	var $ID = 0;

  /**
   * Alle Basisdaten zu einem Benutzer (ausreichend für Login)
   *
   * @var array
   */
	var $data = array();

  /**
   * Erweiterte Daten zu einem Benutzer (Personendaten, etc)
   *
   * @var array
   */
	var $dataExt = array();

  /**
   * Daten zum letzten Login (aus Stat_Sessiondata)
   *
   * @var mixed/array
   */
	var $lastLoginData = false;

  /**
   * Speichert, ob bereits eine Session gestartet wurde
   *
   * @var bool
   */
	var $_SessionStarted = false;

  /**
   * Speichert, ob das Passwort geprüft werden soll
   *
   * @var bool
   */
	var $_checkPass = true;

  /**
   * Speichert, ob ein Benutzer eingeloggt ist
   *
   * @var bool
   */
	var $_loggedIn = false;

  /**
   * Zum Speichern von Debug-Informationen
   *
   * @var array
   */
	var $_debugInfo = array();

  /**
   * Speichert die Session ID
   *
   * @var string
   */
	var $SessionID = "";

  /**
   * Speichert die Session-Daten
   *
   * @var array
   */
	var $Session = false;

  /**
   * Sekunden bis eine Session den Timeout erreicht
   *
   * @var int
   */
	var $sessionTimeout = 86400;

  /**
   * Array mit allen bekannten Rollen
   *
   * @var array
   */
	var $_arrRoles = array();

  /**
   * Lange Benutzernamen korrigieren?
   *
   * @var boolean
   */
	var $fixUserName = false;

  /**
   * Gehört der eingeloggte Benutzer zur Redaktion (RolleID = 9)
   *
   * @var boolean
   */
	var $isEditor = false;
	var $zurRedaktion = false;

  /**
   * Ist der Account noch im Probeabo-Status
   *
   * @var boolean
   */
	var $IstProbeabonnent = true;

  /**
   * Ist der Account ein Freiabo
   *
   * @var boolean
   */
	var $IstFreiabonnent = false;

  /**
   * findet der Login in einem Fenster statt
   *
   * @var boolean
   */
	var $loginInWindow = false;

  /**
   * speichert das Ergebnis der letzten Dubletten-Prüfung
   *
   * @var mixed
   */
	var $arrDoublets = false;

  /**
   * Timeout für zuletzt aufgerufene Dokumente in Minuten
   *
   * @var long
   */
	var $documents_viewed_timeout = 5;

  /**
   * Maximale Anzahl an aufgerufenen Dokumenten in $documents_viewed_timeout Minuten
   *
   * @var long
   */
	var $max_count_documents_viewed = 50;

  /**
   * Array für Abwärtskompatibilität (kann mit Variablen gefüllt werden die sonst unter 'global $variable' verwendet wurden
   *
   * @var array
   */
	var $oldvar = array();

  /**
   * Verweis auf die Funktionssammlung
   *
   * @var object
   */
	var $func = null;
	// }}}

  /**
   * Default Einstellungen
   *
   * @var array
   */
	var $arrEinstellungenDefault = array(
    "CSS" => 1,
    "VerlaufEin" => 1,
    "VerlaufHaekchen" => 1,
    "KommentarVerlauf" => 10,
    "SuchtrefferZusammenfassung" => 1,
    "NeuesBei" => 0,
    "Suche_Treffervorschau" => 1,
    "Suche_Positionsanzeige" => 1,
    "show_Beenden_in_main_menu" => 0,
    "show_Archiv_in_main_menu" => 0,
    "Zielgruppe" => 0,
    "show_Beenden_in_commentary" => 0,
    "confirm_Beenden_in_commentary" => 0,
    "auto_login_to_zg" => 1);
	// }}}

  /**
   * Neuer Krams seit dem letzten Login
   *
   * @var array
   */
	var $arrNewStuffSinceLastLogin = array();
	// }}}

  /**
   * bereits validierte SessionIDs
   *
   * @var array
   */
	var $_checkedSessions = array();
	// }}}

  /**
   * benötigte Rollen für eine Seite
   *
   * @var array
   */
	var $arr_require_roles = array();
	// }}}

  /**
   * fehlende Rollen für eine Seite
   *
   * @var array
   */
	var $arr_missing_roles = array();
	// }}}

  /**
   * Array für Änderungen in Stat_Sessiondata
   *
   * @var array
   */
	var $arr_set_login_stats = array();
	// }}}

  /**
   * Array für Änderungen in ibr_login_stats
   *
   * @var array
   */
	var $arr_set_ibr_login_stats = array();
	// }}}

  /**
   * automatisch versuchen einzuloggen falls Session gefunden wird
   *
   * @var array
   */
	var $auto_login_after_http_auth = true;
	// }}}

  /**
   * dient für das Unterdrücken von User-Funktionen
   *
   * @var array
   */
	var $surpress = array();
	// }}}

  /**
   * speichert die UserID die versucht einzuloggen
   *
   * @var array
   */
	var $ID_before_login_complete = false;
	// }}}

  /**
   * speichert die Default-Probezeit für eine Rolle, sofern nicht in der DB gesetzt
   *
   * @var array
   */
	var $default_trial_period = 7;
	// }}}

  /**
   * Debug an/aus
   *
   * @var array
   */
	var $_debugging = false;
	// }}}

	// {{{ User
	/**
	 * Konstruktor der Klasse
	 *
   * @return void
	 */
	function User($dummy_1 = "", $dummy_2 = "", $SessionID = "", $pbo = array())
	{
		global $env, $clsZG;

		$this->_debugInfo[] = "function User";
		$this->_debugInfo[] = "User -> SessionID:".$SessionID;
		$this->_debugInfo[] = "User -> clsZG->zg:".$clsZG->id;
		$this->SessionID = $SessionID;

		$this->_regularLogin = true;
		isset($pbo['_regularLogin']) ? $this->_regularLogin = $pbo['_regularLogin'] : 0;
		$this->_debugInfo[] = "User -> _regularLogin:".$this->_regularLogin;

		$this->_checkAbonnementsAvailability = true;
		isset($pbo['_checkAbonnementsAvailability']) ? $this->_checkAbonnementsAvailability = $pbo['_checkAbonnementsAvailability'] : 0;
		$this->_debugInfo[] = "User -> _checkAbonnementsAvailability:".$this->_checkAbonnementsAvailability;

		$this->_arrRoles = $this->_getAllRoles();
		$this->_arrRolesAdmin = $this->_getAllRolesAdmin();

		$env->query['loginInWindow'] ? $this->loginInWindow = $env->query['loginInWindow'] : 0;

		$env->query['user']['surpress'] ? $this->surpress = $env->query['user']['surpress'] : 0;

		isset($pbo['require_roles_by_textnr']) ? $this->require_roles_by_textnr($pbo['require_roles_by_textnr']) : 0;
		isset($pbo['require_roles']) ? $this->require_roles($pbo['require_roles']) : 0;
		isset($pbo['arr_set_login_stats']) ? $this->arr_set_login_stats = $pbo['arr_set_login_stats'] : 0;
		isset($pbo['arr_set_ibr_login_stats']) ? $this->arr_set_ibr_login_stats = $pbo['arr_set_ibr_login_stats'] : 0;

		$this->auto_login_after_http_auth = $pbo['auto_login_after_http_auth'];
		//$this->auto_login_after_http_auth = $_POST['Kennung'] && $_POST['Passwort'] ? $this->auto_login_after_http_auth = false : 0;

		if (!$this->auto_login_after_http_auth) {
			return $this->auto_login();
		}
	}
	// }}}

	// {{{ query
	/**
	 * Führt ein SQL-Statement aus
	 *
   * @param string	$sQuery		das Query
   *
   * @return array
	 */
	function sql($sQuery, $indexResult = "", $indexResult2 = "", $bSurpressArray = false)
	{
		global $sql;

		if (is_object($sql))
			return $sql->query($sQuery, $indexResult, $indexResult2, $bSurpressArray);
		else
			return false;
	}
	// }}}

	// {{{ _clear_data
	/**
	 * Leert den data-Array und setzt diverse Variablen die mit dem Login zu tun haben zurück
	 *
   * @param array		$arr		Schlüssel, die nicht geleert werden sollen
   *
   * @return void
	 */
	function _clear_data($arr = array())
	{
		$this->_debugInfo[] = "function _clear_data";
		if (is_array($arr)) {
			foreach ($arr as $val) {
				isset($this->data[$val]) ? $keep->data[$val] = $this->data[$val] : 0;
				isset($this->$val) ? $keep->$val = $this->$val : 0;
			}
		}
		unset($this->data);
		unset($this->ID);
		unset($this->SessionID);
		unset($this->Kennung);
		$this->isEditor = false;
		$this->zurRedaktion = false;
		if (is_object($keep)) {
			foreach ($keep as $key => $val) {
				$this->_debugInfo[] = "_clear_data -> keeping: ".$key;
				$this->$key = $val;
			}
		}
	}
	// }}}

	// {{{ login
	/**
	 * Führt einen Login aus
	 *
   * @param string	$sUserName		der Name des Benutzers
   * @param string	$sUserPass		das Passwort des Benutzers
   * @param bool		$bCheckPass		Passwort prüfen (true/false)
   *
   * @return string
	 */
	function loginFailed()
	{
		$this->_debugInfo[] = "function loginFailed";
		$tmp = $this->arrPassToUserOutput->data;
		unset($this->data);
		unset($this->ID);
		unset($this->SessionID);
		unset($this->Kennung);
		$this->isEditor = false;
		$this->zurRedaktion = false;
		$this->_loggedIn = 0;
		$this->_loginFailed = 1;
		$this->deleteCookie(true);
		$tmp ? $this->arrPassToUserOutput->data = $tmp : 0;
	}
	// }}}

	// {{{ auto_login
	/**
	 * Führt einen Auto-Login aus, falls die Session gefunden wird
	 *
   * @return string
	 */
	function auto_login()
	{
		$this->_debugInfo[] = "function auto_login";
		$this->_debugInfo[] = "auto_login -> _regularLogin: ".$this->_regularLogin;
		if ($this->_regularLogin) {
			$this->require_roles(ROLES_IBR);
    	$this->getCookie();
			if ($this->SessionID != "") {
				$this->_debugInfo[] = "auto_login -> SessionID: ".$this->SessionID;
				$retVal = $this->checkSession(array("SessionID" => $this->SessionID));
				if (is_array($retVal)) {
					$this->Session = $retVal;
					$this->_SessionStarted = true;
				  $retVal = $this->loginBySessionID($this->SessionID);
					return $retVal;
				} else {
					$this->clear_SessionID();
	  			/*
	  			$result = $this->getSessionBy(array("SessionID" => $this->SessionID));
	  			if (!is_array($result)) {
			      $this->logDB("login -> result: ".$result.", ".$_SERVER['PHP_SELF']);
				    return $result;
	  			}
	  			*/
	      }
			} else {
			  $this->logDB("auto_login -> no SessionID, ".$_SERVER['PHP_SELF']);
				return SESSION_SESSION_NOT_FOUND;
			}
		}
	}
	// }}}

	// {{{ login
	/**
	 * Führt einen Login aus
	 *
   * @param string	$sUserName		der Name des Benutzers
   * @param string	$sUserPass		das Passwort des Benutzers
   * @param bool		$bCheckPass		Passwort prüfen (true/false)
   *
   * @return string
	 */
	function login($sUserName = false, $sUserPass = false, $bCheckPass = true)
	{
		global $env;

		$this->_debugInfo[] = "function login(".$sUserName.", ".$sUserPass.", ".$bCheckPass.")";

		$result = $this->executeLogin($sUserName, $sUserPass, $bCheckPass);
	
		if ($result != USER_ACCOUNT_OK && $result != USER_LOGIN_VALID) {
			$this->_debugging_next = true;
			$this->logDB("login -> failure (".$result.")\n\nScript: ".$_SERVER['PHP_SELF']."\n\n".$this->debug(false, true));
		  $this->loginFailed();
			$this->closeSession();
		} else {
			if ($env->query['Login'] == "Yes") {
				$this->_debugging_next = true;
				$this->logDB("login -> success");
			}
			$this->getUserSettings();
		}
		$this->deprecatedAdjustments();
		return $result;
	}
	// }}}

	// {{{ executeLogin
	/**
	 * Führt einen Login aus
	 *
   * @param string	$sUserName		der Name des Benutzers
   * @param string	$sUserPass		das Passwort des Benutzers
   * @param bool		$bCheckPass		Passwort prüfen (true/false)
   *
   * @return string
	 */
	function executeLogin($sUserName, $sUserPass, $bCheckPass = true)
	{
		global $env;
		
		$this->_debugInfo[] = "function executeLogin(".$sUserName.", ".$sUserPass.", ".$bCheckPass.")";
		$this->_loggedIn = false;
		$this->ID = 0;
		$sUserName = trim($sUserName);
		if (empty($sUserName)) {
      $this->_debugInfo[] = "executeLogin -> USER_USERNAME_EMPTY";
		  $this->loginFailed();
			return USER_USERNAME_EMPTY;
		}
		if ($bCheckPass) {
			$sUserPass = trim($sUserPass);
			if (empty($sUserPass)) {
  	    $this->_debugInfo[] = "executeLogin -> USER_PASSWORD_EMPTY";
			  $this->loginFailed();
				return USER_PASSWORD_EMPTY;
			}
		} else
			$sUserPass = "";
		$result = $this->getUserData($sUserName);
		if (!is_array($result)) {
	    $this->_debugInfo[] = "executeLogin -> USER_USERNAME_UNKNOWN";
		  $this->loginFailed();
			return USER_USERNAME_UNKNOWN;
		} else {
			if ($sUserPass != "") {
				if (!$this->_comparePassword($sUserPass, $result['Passwort'])) {
    	    $this->_debugInfo[] = "executeLogin -> USER_INVALID_PASSWORD";
				  $this->loginFailed();
   				return USER_INVALID_PASSWORD;
   		  }
   		}

			$this->data = $result;
			$this->ID_before_login_complete = $this->data['PersonID'];
			$this->data['::Roles::'] = $this->getRoles($this->data['PersonID']);
			$this->data['::AllowLogin::'] = $this->checkRole(ROLES_IBR, 1, true);
			if ($this->data['::AllowLogin::'] < 1 && $this->data['::AllowLogin::'] != USER_ACCOUNT_OK)
				return $this->data['::AllowLogin::'];

			$this->data['Abonnements'] = $this->getAbonnements($this->data['PersonID']);
			if (!is_array($this->data['Abonnements'])) {
	  	  $this->_debugInfo[] = "executeLogin -> USER_ABO_FAILURE";
			  $this->loginFailed();
				return USER_ABO_FAILURE;
			}
			if ($this->_checkAbonnementsAvailability) {
				$this->checkAbonnementsAvailability();
				if ($this->data['::AuthData::']['availableSessionsBeforeLogin'] <= 0) {
					$this->data['AbonnementsRunning'] = $this->getAbonnementsRunning($this->data['PersonID']);
		  	  $this->arrPassToUserOutput = $this;
		  	  $this->_debugInfo[] = "executeLogin -> USER_ALL_SESSIONS_OCCUPIED";
				  $this->loginFailed();
					return USER_ALL_SESSIONS_OCCUPIED;
				}
			}
			$this->startSession();
			$this->_loggedIn = true;
			$this->_checkPass = true;
			$this->ID = $this->data['PersonID'];
			$this->hasRole("Dev-Zugang") ? $this->logDB("INFO: Dev-Zugang for ID:".$this->ID) : 0;
			$this->getStatusProbeabonnent();
			$this->getStatusFreiabo();
			$this->getViewedDocs();
			if ($this->fixUserName) {
			  if ($this->updateUserAuthInDB($this->ID, $this->data['Kennung'], array("Kennung" => $this->fixUserName))) {
			    $this->_debugging_next = true;
			    $this->logDB("INFO: fixed: ".$this->data['Kennung']." to: ".$this->fixUserName);
			    $this->data['Kennung'] = $this->fixUserName;
			    $this->fixUserName = false;
			  }
			}
			$this->Kennung = $this->data['Kennung'];

			$this->setCookie();
			$this->_debugInfo[] = "executeLogin -> USER_LOGIN_VALID";
			$this->data['stat_document_types'] = $this->get_stat_document_types($this->ID);
			$this->get_login_stats($this->ID);
			if ($env->query['Login']) {
				!count($this->arr_set_login_stats) && $this->_regularLogin ? $this->set_login_stats(array("LastAccess" => "NOW()", "LastUpdate" => "NOW()", "Session_Anzahl" => "Session_Anzahl+1"), $this->ID, true) : 0;
				!count($this->arr_set_ibr_login_stats) && $this->_regularLogin ? $this->set_ibr_login_stats(array("last_access" => "NOW()", "last_update" => "NOW()", "logins_total" => "logins_total+1"), $this->ID, true) : 0;
			} else {
				!count($this->arr_set_login_stats) && $this->_regularLogin ? $this->set_login_stats(array("LastAccess" => "NOW()", "LastUpdate" => "NOW()"), $this->ID, true) : 0;
				!count($this->arr_set_ibr_login_stats) && $this->_regularLogin ? $this->set_ibr_login_stats(array("last_access" => "NOW()", "last_update" => "NOW()"), $this->ID, true) : 0;
			}
			count($this->arr_set_login_stats) && $this->_regularLogin ? $this->set_login_stats() : 0;
			count($this->arr_set_ibr_login_stats) && $this->_regularLogin ? $this->set_ibr_login_stats() : 0;
			return USER_LOGIN_VALID;
		}
	}
	// }}}


	// {{{ ip_check
	/**
	 * Führt einen Login nach IP-Prüfung aus
	 *
   * @param string	$lPersonID		die Person ID des Benutzers
   *
   * @return void
	 */
	function ip_check($sUseIP = false)
	{
		$this->_debugInfo[] = "function ip_check(".$sUseIP.")";
		!$sUseIP ? $sUseIP = $_SERVER['REMOTE_ADDR'] : 0;
		$arr = $this->sql("SELECT * FROM `IPPruefung` WHERE (`IP`='".$sUseIP."' OR `IP` LIKE '%-%') AND `Freigeschaltet`='Ja'", "");
		$arrUser = false;
		if (is_array($arr)) {
			foreach ($arr as $val) {
				if ($val['IP'] == $sUseIP) {
					$arrUser = $val;
					break;
				} else {
					$cnt_match = 0;
					$arrIP = explode(".", $val['IP']);
					$arrREMOTE_ADDR = explode(".", $sUseIP);
					for ($i = 0; $i < 4; $i++) {
						if (!preg_match("/\-/", $arrIP[$i])) {
							$arrIP[$i] == $arrREMOTE_ADDR[$i] ? $cnt_match++ : 0;
						} else {
							list ($low, $high) = explode("-", $arrIP[$i]);
							$arrREMOTE_ADDR[$i] >= $low && $arrREMOTE_ADDR[$i] <= $high ? $cnt_match++ : 0;
						}
					}
					if ($cnt_match == 4) {
						$arrUser = $val;
						break;
					}
				}
			}
			if (is_array($arrUser)) {
				$this->_debugInfo[] = "ip_check -> success";
				$this->_ip_check_success = true;
			} else {
				$this->_debugInfo[] = "ip_check -> failed";
				$this->_ip_check_success = false;
			}
			return $arrUser;
		} else {
			$this->_debugInfo[] = "ip_check -> not found";
			$this->_ip_check_success = false;
		}
	}
	// }}}
	
	// {{{ login_with_ip_check
	/**
	 * Führt einen Login nach IP-Prüfung aus
	 *
   * @param string	$lPersonID		die Person ID des Benutzers
   *
   * @return void
	 */
	function login_with_ip_check($lPersonID = 0)
	{
		$this->_debugInfo[] = "function login_with_ip_check(".$lPersonID.")";
		
		if($lPersonID == 0 || $lPersonID == "") {
			$arrUser = $this->ip_check();
			is_array($arrUser) ? $lPersonID = $arrUser['PersonID'] : 0;
			$this->_arr_login_with_ip_check = $arrUser;
		}
		if ($lPersonID) { 
			$this->_checkAbonnementsAvailability = true;
			$result = $this->getUserAuthById($lPersonID);
			if (is_array($result)) {
				$this->_debugInfo[] = "login_with_ip_check -> success";
				$this->_login_with_ip_check = 1;
				$result = $this->login($result['Kennung'], "", false);
				$this->_login_with_ip_check = $result;
				$result == USER_LOGIN_VALID ? $this->_login_with_ip_check_success = true : 0;
				return $result;
			} else
				$this->_debugInfo[] = "login_with_ip_check -> failed";
		} else
			unset($this->_arr_login_with_ip_check);
	}
	// }}}

	// {{{ http_auth
	/**
	 * Anmeldung per HTTP_AUTH
	 *
   * @param array/string	$arrRoles		Mindestens benötigte Rollen
   *
   * @return string
	 */
	function http_auth($arrRoles = "", $bSetID = false)
	{
		if (!is_array($arrRoles) && $arrRoles != "")
			$arrRoles = array($arrRoles);
		$this->_debugInfo[] = "function http_auth(".implode(", ", $arrRoles).", ".$bSetID.")";
		count($arrRoles) == 0 ? $arrRoles = false : 0;
		$arr = $this->getUserData($_SERVER['PHP_AUTH_USER']);
		if (!is_array($arr)) {
			$this->_debugInfo[] = "http_auth -> unknown user";
			$sError = "Unbekannter Benutzer";
		} else {
			if (!$this->_comparePassword($_SERVER['PHP_AUTH_PW'], $arr['Passwort'])) {
				$this->_debugInfo[] = "http_auth -> password mismatch";
				$sError = "Unbekannter Benutzer oder falsches Passwort";
			} else {
				if (is_array($arrRoles)) {
					!is_array($this->data['::Roles::']) ? $this->data['::Roles::'] = $this->getRoles($arr['PersonID']) : 0;
					if (!$this->hasRole($arrRoles)) {
						$this->_debugInfo[] = "http_auth-> no rights";
						$sError = "Unzureichende Berechtigungen für diesen Bereich";
						//$this->debug();
					}
				}
			}
		}
		if ($sError) {
			$this->http_authorized = false;
			header("WWW-Authenticate: Basic realm=\"id Verlag - Intranet\"");
			header("HTTP/1.0 401 Unauthorized");
			echo $sError;
			$this->surpress['ScriptInfo'];
			exit;
		} else {
			$this->data['http_auth']['ID'] = $arr['PersonID'];
			$this->data['http_auth']['Kennung'] = $arr['Kennung'];
			if ($bSetID) {
				!$this->ID ? $this->ID = $this->data['http_auth']['ID'] : 0;
				!$this->Kennung ? $this->Kennung = $this->data['http_auth']['Kennung'] : 0;
			}
			if (!$bSetID || $this->_loginFailed) {
				$this->isEditor = false;
				$this->zurRedaktion = false;
				$this->data['http_auth']['::Roles::'] = $this->data['::Roles::'];
				if ($this->_loginFailed)
					$this->loginFailed();
				else
					$this->_clear_data(array("http_auth", "SessionID", "Großkunde"));
			}
			$this->http_authorized = true;
			$this->_debugInfo[] = "http_auth -> success";
			$this->_debugInfo[] = "**************************";
			$this->_debugInfo[] = ">>>>> http_auth DONE <<<<<";
			if ($this->auto_login_after_http_auth) {
				$this->_regularLogin = true;
				$this->auto_login();
			}
		}
	}
	// }}}

	// {{{ getUser
	/**
	 * Holt Daten aus der Datenbank als würde ein User einloggen
	 *
   * @param string	$sUserName		der Name des Benutzers
   * @param string	$sUserPass		das Passwort des Benutzers
   * @param bool	$bCheckPass		Passwort prüfen (true/false)
   *
   * @return string
	 */
	function getUser($sUserName, $sUserPass, $bCheckPass = true)
	{
		$this->_debugInfo[] = "function getUser";
		$this->_loggedIn = false;
		$this->ID = 0;
		$sUserName = trim($sUserName);
		if (empty($sUserName)) {
			$this->_debugInfo[] = "USER_USERNAME_EMPTY";
		  $this->loginFailed();
			return USER_USERNAME_EMPTY;
		}
		if ($bCheckPass) {
			$sUserPass = trim($sUserPass);
			if (empty($sUserPass)) {
  	    $this->_debugInfo[] = "USER_PASSWORD_EMPTY";
			  $this->loginFailed();
				return USER_PASSWORD_EMPTY;
			}
		} else
			$sUserPass = "";
		$result = $this->getUserData($sUserName);
		if (!is_array($result)) {
	    $this->_debugInfo[] = "USER_USERNAME_UNKNOWN";
		  $this->loginFailed();
			return USER_USERNAME_UNKNOWN;
		} else {
			if ($sUserPass != "") {
				if (!$this->_comparePassword($sUserPass, $result['Passwort'])) {
    	    $this->_debugInfo[] = "USER_INVALID_PASSWORD";
				  $this->loginFailed();
   				return USER_INVALID_PASSWORD;
   		  }
   		}

			$this->data = $result;
			$this->data['::Roles::'] = $this->getRoles($this->data['PersonID']);
			$this->data['Abonnements'] = $this->getAbonnements($this->data['PersonID']);
			if (!is_array($this->data['Abonnements'])) {
  	  	$this->_debugInfo[] = "USER_ABO_FAILURE";
			  $this->loginFailed();
				return USER_ABO_FAILURE;
			}
			if ($this->_checkAbonnementsAvailability) {
				$this->checkAbonnementsAvailability();
				if ($this->data['::AuthData::']['availableSessionsBeforeLogin'] <= 0) {
					$this->data['AbonnementsRunning'] = $this->getAbonnementsRunning($this->data['PersonID']);
    			$this->arrPassToUserOutput = $this;
    			$this->_debugInfo[] = "USER_ALL_SESSIONS_OCCUPIED";
				  $this->loginFailed();
					return USER_ALL_SESSIONS_OCCUPIED;
				}
			}
			$this->startSession();
			$this->_loggedIn = true;
			$this->_checkPass = true;
			$this->ID = $this->data['PersonID'];
			$this->getStatusProbeabonnent();
			$this->getStatusFreiabo();
			$this->getViewedDocs();
			if ($this->fixUserName) {
			  if ($this->updateUserAuthInDB($this->ID, $this->data['Kennung'], array("Kennung" => $this->fixUserName))) {
					$this->_debugging_next = true;
			    $this->logDB("INFO: fixed: ".$this->data['Kennung']." to: ".$this->fixUserName);
			    $this->data['Kennung'] = $this->fixUserName;
			    $this->fixUserName = false;
			  }
			}
			$this->Kennung = $this->data['Kennung'];
			$this->_debugInfo[] = "USER_LOGIN_VALID";
			return USER_LOGIN_VALID;
		}
	}
	// }}}

	// {{{ getUserById
	/**
	 * Holt einen Benutzer per ID aus der Datenbank
	 *
   * @param long	$lID		die ID des Benutzers
   *
   * @return string
	 */
	function getUserById($lID)
	{
		$this->_debugInfo[] = "function getUserById";
		if ($lID) {
			$result = $this->sql("SELECT * FROM Person WHERE PersonID='".$lID."'");
			if ($result) {
				$this->data = $result[0];
				$this->data['::Roles::'] = $this->getRoles($this->data['PersonID']);
				$this->data['Abonnements'] = $this->getAbonnements($this->data['PersonID']);
				if ($this->_regularLogin) {
					if (!is_array($this->data['Abonnements'])) {
		    	  $this->_debugInfo[] = "USER_ABO_FAILURE";
					  $this->loginFailed();
						return USER_ABO_FAILURE;
					}
					if ($this->_checkAbonnementsAvailability) {
						$this->checkAbonnementsAvailability();
						if ($this->data['::AuthData::']['availableSessionsBeforeLogin'] <= 0) {
							$this->data['AbonnementsRunning'] = $this->getAbonnementsRunning($this->data['PersonID']);
			    	  $this->arrPassToUserOutput = $this;
			    	  $this->_debugInfo[] = "USER_ALL_SESSIONS_OCCUPIED";
						  $this->loginFailed();
							return USER_ALL_SESSIONS_OCCUPIED;
						}
					}
					$this->startSession();
					$this->_loggedIn = true;
					$this->_checkPass = true;
					$this->ID = $this->data['PersonID'];
					$this->getStatusProbeabonnent();
					$this->getStatusFreiabo();
					$this->getViewedDocs();
					if ($this->fixUserName) {
					  if ($this->updateUserAuthInDB($this->ID, $this->data['Kennung'], array("Kennung" => $this->fixUserName))) {
							$this->_debugging_next = true;
					    $this->logDB("INFO: fixed: ".$this->data['Kennung']." to: ".$this->fixUserName);
					    $this->data['Kennung'] = $this->fixUserName;
					    $this->fixUserName = false;
					  }
					}
					$this->Kennung = $this->data['Kennung'];
		    	$this->_debugInfo[] = "USER_LOGIN_VALID";
					return USER_LOGIN_VALID;
				} else {
					$this->_loggedIn = true;
					$this->_checkPass = true;
					$this->ID = $this->data['PersonID'];
					$this->getStatusProbeabonnent();
					$this->getStatusFreiabo();
					$this->getViewedDocs();
		    	$this->_debugInfo[] = "USER_LOGIN_VALID";
					return USER_LOGIN_VALID;
				}
			}
		}
	}
	// }}}

	// {{{ getUserAuthById
	/**
	 * Holt einen Benutzer mit AuthData per ID aus der Datenbank
	 *
   * @param long	$lID		die ID des Benutzers
   *
   * @return array/false
	 */
	function getUserAuthById($lID)
	{
		$this->_debugInfo[] = "function getUserAuthById";
		if ($lID) {
			$result = $this->sql("SELECT A.Kennung, A.Passwort, P.* FROM Person AS P LEFT JOIN AuthData AS A ON A.PersonID=P.PersonID WHERE P.PersonID='".$lID."'");
			if ($result)
				return $result[0];
			else
				return false;
		} else
			return false;
	}
	// }}}

	// {{{ loginBySessionID
	/**
	 * loggt einen Benutzer basierend auf den aus einer Session ermittelten PersonID ein
	 *
   * @return string
	 */
	function loginBySessionID()
	{
		$this->_debugInfo[] = "function loginBySessionID";
    if (!$this->SessionID) {
		  $this->_debugInfo[] = "loginBySessionID -> !this->SessionID";
      ob_start();
      $this->debug();
			$sDebug = ob_get_contents();
			ob_end_clean();
      $this->logDB("INFO: user->loginBySessionID SessionID:".$this->SessionID." deleteCookie is next >>> ".$sDebug." <<<, Datei: ".$_SERVER['PHP_SELF']);
      $this->deleteCookie();
      return SESSION_SESSION_NOT_FOUND;
    }
    if (!$this->_SessionStarted) {
      $retVal = $this->checkSession(array("SessionID" => $this->SessionID));
			if (is_array($retVal)) {
				$this->Session = $retVal;
				$this->_SessionStarted = true;
			  $result[0] = $this->Session;
			} else {
  			$result = $this->getSessionBy(array("SessionID" => $this->SessionID));
  			if (!is_array($result)) {
		  		$this->_debugInfo[] = "loginBySessionID -> !is_array(result) [getSessionBy]";
			    return $result;
			  } else
			  	$result[0] = $result;
      }
		} else
		  $result[0] = $this->Session;
		if (is_array($result) && count($result)) {
  		$this->_debugInfo[] = "loginBySessionID -> is_array(result)";
	    $sessionTimedOut = $this->sessionTimedOut($result[0]);
			if (!$sessionTimedOut) {
				$result = $this->getLoginValuesByID($result[0]);
				if (is_array($result))
					return $this->login($result['Kennung'], $result['Passwort'], false);
				else
					return USER_USER_NOT_FOUND;
			} else {
		  	$this->clear_SessionID();
	      ob_start();
	      $this->debug();
				$sDebug = ob_get_contents();
				ob_end_clean();
	      $this->logDB("INFO: user->loginBySessionID SessionID:".$this->SessionID." deleteCookie is next >>> ".$sDebug." <<<, Datei: ".$_SERVER['PHP_SELF']);
				$this->logDB("INFO: user->loginBySessionID sessionTimedOut=true deleteCookie is next, Datei: ".$_SERVER['PHP_SELF']);
				$this->deleteCookie();
				return SESSION_TIMEOUT;
		  }
		} else {
		  $this->_debugInfo[] = "loginBySessionID -> !is_array(result)";
			$this->logDB(var_dump($this->_debugInfo).", Datei: ".$_SERVER['PHP_SELF']);
		  $this->clear_SessionID();
			$this->deleteCookie();
			return SESSION_SESSION_NOT_FOUND;
	  }
	}
	// }}}

	// {{{ getLoginValuesByID
	/**
	 * Liefert Benutzerdaten basierend auf PersonID oder MID
	 *
   * @param array		$arrUser		ein Array der PersonID und/oder MID als Schlüssel mit entsprechendem Wert enthalten muss
   *
   * @return array
	 */
	function getLoginValuesByID($arrUser)
	{
		$this->_debugInfo[] = "function getLoginValuesByID";

		if (!is_array($arrUser))
			return array();
		if (array_key_exists("PersonID", $arrUser)) {
			if ($arrUser['MID'] != 0)
				$result = $this->sql("
					SELECT
						a.`maxAllowedSessions`,
						a.`maxAllowedSessions` AS `availableSessionsBeforeLogin`,
						m.*,
						p.`Großkunde`
					FROM
						`Mitbenutzerkennung`  AS m
					LEFT JOIN
						`AuthData` AS a
					ON a.`PersonID`=m.`PersonID`
				  LEFT JOIN
				  	`Person` AS p
				  ON p.`PersonID`=a.`PersonID`
					WHERE
						m.`MID`='".$arrUser['MID']."'");
			else {
				$result = $this->sql("
				  SELECT
				    a.*,
				    a.`maxAllowedSessions` AS `availableSessionsBeforeLogin`,
				    p.`Großkunde`
				  FROM
				    `AuthData` AS a
				  LEFT JOIN
				  	`Person` AS p
				  ON p.`PersonID`=a.`PersonID`
				  WHERE
						a.`PersonID`='".$arrUser['PersonID']."'");
				$this->data['::AuthData::'] = $result[0];
			}
			if (is_array($result))
				return $result[0];
		}
		return array();
	}
	// }}}

	// {{{ isUsernameAvailable
	/**
	 * Prüft, ob ein Benutzername noch frei ist
	 *
   * @param string	$sUserName		der Name des Benutzers
   *
   * @return int
	 */
	function isUsernameAvailable($sUserName)
	{
		$this->_debugInfo[] = "function isUsernameAvailable (".$sUserName.")";
	  $sKENNUNGAuth = "`Kennung`='".$sUserName."'";
		if (strlen($sUserName) > 20)
		  $sKENNUNGAuth = "(".$sKENNUNGAuth." OR `Kennung`='".substr($sUserName, 0, 20)."')";
		$result = $this->sql("
		  SELECT
		    *
		  FROM
		    `AuthData`
		  WHERE
		    ".$sKENNUNGAuth
		);
		if (!is_array($result)) {
			$retVal = 1;
			$result = $this->sql("
			  SELECT
			    *
			  FROM
			    `FreigeschalteteProbeabos`
			  WHERE
			    ".$sKENNUNGAuth
			);
			is_array($result) ? $retVal = 0 : 0;
		} else
			$retVal = -1;
		return $retVal;
	}
	// }}}

	// {{{ getUserData
	/**
	 * Holt die Basis-Benutzerdaten zu einem Benutzer oder Mitbenutzer
	 *
   * @param string	$sUserName		der Name des Benutzers
   * @param string	$sUserPass		optional das Passwort des Benutzers
   *
   * @return array
	 */
	function getUserData($sUserName, $sUserPass = "")
	{
		$this->_debugInfo[] = "function getUserData(".$sUserName.", ".$sUserPass.")";
		$sKENNUNGAuth = "a.`Kennung`='".$sUserName."'";
		$sKENNUNGMit = "m.`Kennung`='".$sUserName."'";
		if (strlen($sUserName) > 20) {
			$this->fixUserName = $sUserName;
			$sKENNUNGAuth = "(".$sKENNUNGAuth." OR a.`Kennung`='".substr($sUserName, 0, 20)."')";
			$sKENNUNGMit = "(".$sKENNUNGMit." OR m.`Kennung`='".substr($sUserName, 0, 20)."')";
		} elseif (strpos($sUserName, " ") !== false) {
			$sKENNUNGAuth = "(".$sKENNUNGAuth." OR a.`Kennung`='".str_replace(" ", "+", $sUserName)."')";
			$sKENNUNGMit = "(".$sKENNUNGMit." OR m.`Kennung`='".str_replace(" ", "+", $sUserName)."')";
		}
		$WHERE = $sUserPass != "" ? " AND a.`Passwort`='".$sUserPass."'" : "";
		if (!is_array($this->data['::AuthData::'])) {
			$this->_debugInfo[] = "getUserData -> !is_array(this->data[::AuthData::])";
			$result = $this->sql("
			  SELECT
			    a.*,
			    a.`maxAllowedSessions` AS `availableSessionsBeforeLogin`,
			    p.`Großkunde`
			  FROM
			    `AuthData` AS a
			  LEFT JOIN
			  	`Person` AS p
			  ON p.`PersonID`=a.`PersonID`
			  WHERE
			    ".$sKENNUNGAuth.$WHERE, true);
			is_array($result) ? $this->_debugInfo[] = "getUserData -> found Kennung in AuthData" : 0;
		} else {
			$this->_debugInfo[] = "getUserData -> ::AuthData:: exists - using";
			$result[0] = $this->data['::AuthData::'];
			$result[0]['::AuthData::'] = $this->data['::AuthData::'];
			$result[0]['Großkunde'] = $this->data['::AuthData::']['Großkunde'];
		}
		if (!is_array($result)) {
		  $WHERE = $sUserPass != "" ? " AND m.`Passwort`='".$sUserPass."'" : "";
			$result = $this->sql("
				SELECT
					a.`maxAllowedSessions`,
					a.`maxAllowedSessions` AS `availableSessionsBeforeLogin`,
					m.*,
					p.`Großkunde`
				FROM
					`Mitbenutzerkennung`  AS m
				LEFT JOIN
					`AuthData` AS a
				ON a.`PersonID`=m.`PersonID`
			  LEFT JOIN
			  	`Person` AS p
			  ON p.`PersonID`=a.`PersonID`
				WHERE
					".$sKENNUNGMit.$WHERE, true);
			is_array($result) ? $this->_debugInfo[] = "getUserData -> found Kennung in Mitbenutzerkennung" : 0;
		}
		if (!is_array($this->data['::AuthData::']) && is_array($result)) {
			$this->data['::AuthData::'] = $result[0];
			$result[0]['::AuthData::'] = $result[0];
		}
		$this->data['Großkunde'] = $result[0]['Großkunde'];
		$this->data['maxAllowedSessions'] = $result[0]['availableSessionsBeforeLogin'];
		return $result[0];
	}
	// }}}

	// {{{ getUserDataExt
	/**
	 * Holt alle Benutzerdaten zu einem Benutzer oder Mitbenutzer
	 *
   * @param boolean	$bReturnAsArray		Rückgabe als Array?
   * @param string	$sKennung					Kennung (optional)
   * @param string	$lPersonID				PersonID (optional)
   *
   * @return void
	 */
	function getUserDataExt($bReturnAsArray = false, $sKennung = false, $lPersonID = false)
	{
		$this->_debugInfo[] = "function getUserDataExt(".$bReturnAsArray.", ".$sKennung.", ".$lPersonID.")";
		!$sKennung && !$lPersonID ? $sKennung = $this->Kennung : 0;
		!$lPersonID ? $lPersonID = $this->ID : 0;
		$retVal = array();
		if ($lPersonID) {
			$result = $this->sql("
				SELECT
					*
				FROM
					Person
				WHERE
					PersonID='".$lPersonID."'");
			is_array($result) ? $retVal = $retVal + $result[0] : 0;
			$retVal['Strasse'] = trim($retVal['Strasse']);
			$retVal['Hausnummer'] = trim($retVal['Hausnummer']);
			$retVal['Strasse_complete'] = substr($retVal['Strasse'], strlen($retVal['Strasse']) - strlen($retVal['Hausnummer'])) != $retVal['Hausnummer'] ? $retVal['Strasse']." ".$retVal['Hausnummer'] : $retVal['Strasse'];
			$result = $this->sql("
			  SELECT
			    `KundennummerThull`
			  FROM
			    `KonkordanzAbonnentenDaten`
			  WHERE
			  	`PersonID`='".$lPersonID."'
			  ".$myWHERE
			);
			is_array($result) ? $retVal = $retVal + $result[0] : 0;
		}
		if (count($retVal)) {
			$result = $this->sql("
				SELECT
					*
				FROM
					RedNotizenZuAbonnenten
				WHERE
					PersonID='".$lPersonID."'
				ORDER BY
					Eingetragen DESC");
			is_array($result) ? $retVal['Notizen'] = $result : 0;

		  if (!$bReturnAsArray)
		  	$this->dataExt = $retVal;
		  else
		  	return $retVal;
		} else {
		  if ($bReturnAsArray)
		  	return false;
		}
  }
	// }}}

	// {{{ _comparePassword
	/**
	 * vergleicht ein Klartext-Passwort mit einem verschlüsselten Passwort
	 *
   * @param string	$sPasswordClear			Passwort im Klartext
   * @param string	$sPasswordCrypted		Passwort aus der Datenbank
   *
   * @return bool		true wenn die Passwörter gleich sind, false wenn sie unterschiedlich sind
	 */
	function _comparePassword($sPasswordClear, $sPasswordCrypted = "")
	{
		$this->_debugInfo[] = "function _comparePassword (".$sPasswordClear.", ".$sPasswordCrypted.")";
		$sPasswordCrypted == "" ? $sPasswordCrypted = $this->data['Passwort'] : 0;
		if ($sPasswordCrypted == "")
			return false;
		if (substr($sPasswordCrypted, 0, 2) != "@@") {
			if ($sPasswordCrypted{0} == "$")
				$salt = substr($sPasswordCrypted, 0, 12); // MD5-Verschl., 12-stelliges salt
			else
				$salt = substr($sPasswordCrypted, 0, 2);  // Std-Verschl., 2-stelliges salt
			$sCrypt = crypt($sPasswordClear, $salt);
			if ($sCrypt == $sPasswordCrypted) {
				$this->_debugInfo[] = "_comparePassword -> (1) ".$sCrypt.", ".$sPasswordCrypted;
				return true;
			} else {
				if ($sPasswordClear == $sPasswordCrypted) {
					$this->_debugInfo[] = "_comparePassword -> (2) ".$sPasswordClear.", ".$sPasswordCrypted;
				  return true;
				} else
				  return false;
	    }
	  } else {
	  	if ($sPasswordClear == substr($sPasswordCrypted, 2)) {
				$this->_debugInfo[] = "_comparePassword -> (3) ".$sPasswordClear.", ".substr($sPasswordCrypted, 2);
	  		return true;
	  	} else
	  		return false;
	  }
	}
	// }}}

	// {{{ getRoles
	/**
	 * liefert die Rollen eines Benutzers
	 *
   * @param long	$lID		ID des Benutzers
   *
   * @return array		Array mit den Rollen
	 */
	function getRoles($lID = 0)
	{
		$this->_debugInfo[] = "function getRoles(".$lID.")";
		if ($lID == 0) return array();
		$result = $this->sql("
			SELECT
				*
			FROM
				`Person_Rolle`
			WHERE
				`PersonID`='".$lID."'");
		if (is_array($result)) {
			foreach ($result as $val) {
				$val['Bezeichnung'] = $this->_arrRoles[$val['RolleID']]['Bezeichnung'];
				$val['Kurzbeschreibung'] = $this->_arrRoles[$val['RolleID']]['Kurzbeschreibung'];
				$val['Textnr'] = $this->_arrRoles[$val['RolleID']]['Textnr'];
				/*
				$val['RolleID'] == ROLES_IBR && $this->data['maxAllowedSessions'] && $this->data['maxAllowedSessions'] != $val['Arbeitsplaetze'] ? $val['Arbeitsplaetze'] = $this->data['maxAllowedSessions'] : 0;
				$val['RolleID'] == ROLES_IBR && $this->data['maxAllowedSessions'] ? $val['Frei'] = $this->data['maxAllowedSessions'] : 0;
				*/
				$val['Frei'] = $val['Arbeitsplaetze'];
				$val['Freigeschaltet'] == "Ja" ? $val['Freigeschaltet'] = USER_ACCOUNT_OK : 0;
				$val['Freigeschaltet'] == "Nein" ? $val['Freigeschaltet'] = USER_ACCOUNT_CLOSED : 0;
				$val['Freigeschaltet'] == "Neu" ? $val['Freigeschaltet'] = USER_ACCOUNT_NEW : 0;
				$retVal[$val['RolleID']] = $val;
				$val['RolleID'] == ROLES_URTEILSPFLEGE ? $this->isEditor = true : 0;
				$val['RolleID'] == ROLES_IDVERLAG ? $this->isEditor = true : 0;
				$this->zurRedaktion = $this->isEditor;
			}
			return $retVal;
		} else
			return array();
	}
	// }}}

	// {{{ getRoles4MID
	/**
	 * liefert die zugewiesenen Rollen eines Mit-/Benutzers (Großkunden)
	 *
   * @param long	$lID		ID des Benutzers
   * @param long	$lMID		ID des Mitbenutzers
   *
   * @return array		Array mit den Rollen
	 */
	function getRoles4MID($lID = 0, $lMID = 0)
	{
		$this->_debugInfo[] = "function getRoles4MID(".$lID.", ".$lMID.")";
		if ($lID == 0) return array();
		$result = $this->sql("
			SELECT
				*
			FROM
				`Mitbenutzer_Rollen`
			WHERE
				`PersonID`='".$lID."'
			AND
				`MID`='".$lMID."'", "id");
		return $result;
	}
	// }}}

	// {{{ checkRoles4MID
	/**
	 * prüft die zugewiesenen Rollen eines Mit-/Benutzers (Großkunden)
	 * und löscht ggf. ungültige Rollen
	 *
   * @param long	$lID		ID des Benutzers
   * @param long	$lMID		ID des Mitbenutzers
   *
   * @return void
	 */
	function checkRoles4MID($lID = 0, $lMID = 0, $bDeleteInvalid = true)
	{
		$this->_debugInfo[] = "function checkRoles4MID(".$lID.", ".$lMID.", ".$bDeleteInvalid.")";
		!$lID ? $lID = $this->ID : 0;
		!$lID ? $lID = $this->data['PersonID'] : 0;
		if ($lID == 0) return;
		$this->_debugInfo[] = "checkRoles4MID > lID: ".$lID;
		$result = $this->getRoles4MID($lID, $lMID);
		$result[] = array("id_role" => ROLES_IBR);
		foreach ($result as $key => $val) {
			if ($this->data['::Roles::'][$val['id_role']]['Freigeschaltet'] == USER_ACCOUNT_OK)
				$arr[] = $val['id_role'];
			else
				$key != 0 ? $arrDelete[] = $key : 0;
		}
		!is_array($arr) ? $arr = array() : 0;
		is_array($arrDelete) ? $sql->query("DELETE FROM `Mitbenutzer_Rollen` WHERE `id` IN ('".implode("', '", $arrDelete)."')") : 0;
		$this->_debugInfo[] = "checkRoles4MID -> ".implode(", ", $arr);
		return $arr;
	}
	// }}}
		
	// {{{ getRoleStatusBy
	/**
	 * liefert für eine Rolle des Benutzers den Status
	 *
   * @param long	$lID		ID des Benutzers
   * @param long	$arr		Array mit dem Schlüssel/Wert den die Rolle haben muss
   *
   * @return array		Array mit den Rollen
	 */
	function getRoleStatusBy($lID, $arr = false)
	{
		$this->_debugInfo[] = "function getRoleBy";
		if (!is_array($arr)) return false;
		if (!is_array($this->data['::Roles::']))
			$this->data['::Roles::'] = $this->getRoles($lID);
		if (!is_array($this->data['::Roles::']))
			return false;
		else {
			$retVal = false;
			foreach ($this->data['::Roles::'] as $key => $val) {
				if (is_array($val)) {
					foreach ($val as $k => $v) {
						if (array_key_exists($k, $arr)) {
							if ($v == $arr[$k]) {
								if ($val['Freigeschaltet'] == USER_ACCOUNT_OK)
									$retVal = true;
								else
									$retVal = false;
							}
						}
					}
				}
			}
			return $retVal;
		}
	}
	// }}}

	// {{{ hasRole
	/**
	 * liefert für eine oder mehrere Rollen den Status
	 *
   * @param array	$arrRoles		Array mit den Rollennamen die zu prüfen sind
   *
   * @return array		Array mit den Rollen und deren Status
	 */
	function hasRole($roles = array())
	{
		!is_array($roles) ? $arrRoles[] = $roles : $arrRoles = $roles;
		if (count($arrRoles) == 0) return false;

		$this->_debugInfo[] = "function hasRole(".implode(", ", $arrRoles).")";

    if ($this->_regularLogin && !$this->_loggedIn && $this->SessionID) {
    	$this->loginBySessionID();
    }
    if (is_array($this->data['::Roles::'])) {
      foreach ($this->data['::Roles::'] as $id_role => $arr) {
        if (in_array($arr['Bezeichnung'], $arrRoles)) {
          $retVal[$arr['Bezeichnung']] = $arr;
        } elseif (in_array($arr['RolleID'], $arrRoles)) {
          $retVal[$arr['RolleID']] = $arr;
        }
      }
      foreach ($arrRoles as $val)
				!is_array($retVal[$val]) ? $this->_debugInfo[] = "hasRole -> missing role: ".$val : 0;
      if (is_array($retVal))
        return $retVal;
      else
        return false;
    } else
      return false;
	}
	// }}}

	// {{{ checkRole
	/**
	 * prüft, ob ein Benutzer eine Rolle mit einem bestimmten Status hat
	 *
   * @param array	$sRole		Name oder ID der Rolle
   * @param mixed $mStatus  Prüfung auf Status
   *
   * @return bool           true oder false
	 */
	function checkRole($sRole = "", $mStatus = "", $bReturnStatus = false)
	{
		$this->_debugInfo[] = "function checkRole(".$sRole.", ".$mStatus.", ".$bReturnStatus.")";
		if (!$sRole)
		  return false;
    if (is_array($this->data['::Roles::'])) {
      $retVal = false;
      $mStatus == "" ? $mStatus = USER_ACCOUNT_OK : 0;
      foreach ($this->data['::Roles::'] as $arr) {
        if ($sRole == $arr['Bezeichnung'] || $sRole == $arr['RolleID']) {
          $this->_debugInfo[] = "checkRole -> Role: ".$arr['Bezeichnung'];
          if (!$this->data['Großkunde'] || !$arr['istBuchbaresAbo']) {
	          if ($bReturnStatus)
	          	$retVal = $arr['Freigeschaltet'];
	          else
	          	$retVal = $arr['Freigeschaltet'] == $mStatus ? true : false;
        	} else {
		        $this->_debugInfo[] = "checkRole -> Großkunde";
						$lMID = $this->data['MID'] ? $this->data['MID'] : 0;
						$arrMID = $this->checkRoles4MID($this->ID, $lMID);
        		if (in_array($arr['RolleID'], $arrMID)) {
		          if ($bReturnStatus)
		          	$retVal = $arr['Freigeschaltet'];
		          else
		          	$retVal = $arr['Freigeschaltet'] == $mStatus ? true : false;
        		} else
        			$retVal = false;
        	}
          break;
        }
      }
			$this->_debugInfo[] = "checkRole -> returning: ".$retVal;
      return $retVal;
    } else {
      $this->_debugInfo[] = "checkRole -> !is_array(data[::Roles::])";
      return false;
		}
	}
	// }}}

	// {{{ checkRole_http_auth
	/**
	 * prüft, ob ein Benutzer eine Rolle mit einem bestimmten Status hat
	 *
   * @param array	$sRole		Name oder ID der Rolle
   * @param mixed $mStatus  Prüfung auf Status
   *
   * @return bool           true oder false
	 */
	function checkRole_http_auth($sRole = "", $mStatus = "", $bReturnStatus = false)
	{
		$this->_debugInfo[] = "function checkRole_http_auth(".$sRole.", ".$mStatus.", ".$bReturnStatus.")";
		if (!$sRole)
		  return false;
    if (is_array($this->data['http_auth']['::Roles::'])) {
      $retVal = false;
      $mStatus == "" ? $mStatus = USER_ACCOUNT_OK : 0;
      foreach ($this->data['http_auth']['::Roles::'] as $arr) {
        if ($sRole == $arr['Bezeichnung'] || $sRole == $arr['RolleID']) {
          $this->_debugInfo[] = "checkRole -> Role: ".$arr['Bezeichnung'];
          if (!$this->data['http_auth']['Großkunde'] || !$arr['istBuchbaresAbo']) {
	          if ($bReturnStatus)
	          	$retVal = $arr['Freigeschaltet'];
	          else
	          	$retVal = $arr['Freigeschaltet'] == $mStatus ? true : false;
        	} else {
		        $this->_debugInfo[] = "checkRole_http_auth -> Großkunde";
						$lMID = $this->data['http_auth']['MID'] ? $this->data['MID'] : 0;
						$arrMID = $this->checkRoles4MID($this->ID, $lMID);
        		if (in_array($arr['RolleID'], $arrMID)) {
		          if ($bReturnStatus)
		          	$retVal = $arr['Freigeschaltet'];
		          else
		          	$retVal = $arr['Freigeschaltet'] == $mStatus ? true : false;
        		} else
        			$retVal = false;
        	}
          break;
        }
      }
			$this->_debugInfo[] = "checkRole_http_auth -> returning: ".$retVal;
      return $retVal;
    } else {
      $this->_debugInfo[] = "checkRole_http_auth -> !is_array(data[::Roles::])";
      return false;
		}
	}
	// }}}

	// {{{ validateRole
	/**
	 * prüft, ob ein Benutzer für eine Rolle freigeschaltet ist
	 *
   * @param array	$sRole		Name oder ID der Rolle
   *
   * @return bool           true oder false
	 */
	function validateRole($sRole = "", $mStatus)
	{
		$this->_debugInfo[] = "function validateRole";
		if (!$sRole)
		  return false;
    if (is_array($this->data['::Roles::'])) {
      $retVal = false;
      foreach ($this->data['::Roles::'] as $arr) {
        if ($sRole == $arr['Bezeichnung'] || $sRole == $arr['RolleID']) {
          $retVal = $arr['Freigeschaltet'] == $mStatus ? true : false;
          break;
        }
      }
      return $retVal;
    } else
      return false;
	}
	// }}}

	// {{ getAbonnements
  /**
   * Liefert die aktuellen Abonnements eines Benutzers
   *
   * @param int   $lID    ID des Benutzers
   *
   * @return array
   */
  function getAbonnements($lID, $bGetForAdmin = false)
  {
		$this->_debugInfo[] = "function getAbonnements(".$lID.", ".$bGetForAdmin.")";
    if ($lID == 0) return array();
    if (!is_array($this->data['::Roles::']) || $bGetForAdmin) {
    	$this->_debugInfo[] = "getAbonnements -> query DB";
    	$myAND = $bGetForAdmin ? "AND r.`show_in_admin`='1'" : "";
	    $result = $this->sql("
	      SELECT
	        r.`Bezeichnung`,
	        r.`RolleID`,
	        r.`Kurzbeschreibung`,
	        pr.`FreiAbo`,
	        pr.`Anmeldedatum`,
	        pr.`Sperrdatum`,
	        pr.`Freischaltdatum`,
	        pr.`Freigeschaltet`,
	        pr.`Arbeitsplaetze`,
	        pr.`Arbeitsplaetze` AS `Frei`,
	        pr.`Bearbeitet`,
	        pr.`Bearbeitet_am`,
	        pr.`Ablauf_Probezeit`
	      FROM
	        `Person_Rolle` AS pr
	      LEFT JOIN
	        `Rolle` AS r
	      ON r.`RolleID`=pr.`RolleID`
	      WHERE
	        pr.`PersonID`='".$lID."'
	      ".$myAND."
	    ");
			if (is_array($result)) {
				foreach ($result as $val) {
				  if ($val['RolleID'] == ROLES_IBR && $this->data['PersonID'] == $lID) {
				    //$val['Arbeitsplaetze'] = $this->data['maxAllowedSessions'];
				    $val['Frei'] = $this->data['maxAllowedSessions'];
				  }
					$val['Freigeschaltet'] == "Ja" ? $val['Freigeschaltet'] = USER_ACCOUNT_OK : 0;
					$val['Freigeschaltet'] == "Nein" ? $val['Freigeschaltet'] = USER_ACCOUNT_CLOSED : 0;
					$val['Freigeschaltet'] == "Neu" ? $val['Freigeschaltet'] = USER_ACCOUNT_NEW : 0;
					$retVal[$val['RolleID']] = $val;
				}
				$this->data['::Roles::'] = $retVal;
				return $retVal;
			} else
				return array();
  	} elseif (is_array($this->data['::Roles::'])) {
    	$this->_debugInfo[] = "getAbonnements -> using this->data[::Roles::]";
  		return $this->data['::Roles::'];
  	}
  }
  // }}}

	// {{ checkAbonnementsTerminated
  /**
   * Liefert eventuell terminierte Änderungen an Abos
   *
   * @param string   $sKennung    Kennung des Benutzers
   *
   * @return array
   */
  function checkAbonnementsTerminated($sKennung = "")
  {
		$this->_debugInfo[] = "function checkAbonnementsTerminated(".$sKennung.")";
		$this->_debugInfo[] = "checkAbonnementsTerminated -> !deprecated! (called from Script: ".$_SERVER['PHP_SELF'];
		$this->_debugInfo[] = "checkAbonnementsTerminated -> redirecting parameters to function get_logged_changes";
		$this->_debugging_next = true;
		$this->logDB($this->_debugInfo[count($this->_debugInfo)-3]."\n".$this->_debugInfo[count($this->_debugInfo)-2]."\n".$this->_debugInfo[count($this->_debugInfo)-1]);

		$retVal = $this->get_logged_changes($sKennung);
		return $retVal;
	}
  // }}}

	// {{ get_logged_changes
  /**
   * Liefert eventuell terminierte Änderungen an Feldern
   *
   * @param string   $sID    PersonID
   *
   * @return array
   */
  function get_logged_changes($sID = "")
  {
		$this->_debugInfo[] = "function get_logged_changes(".$sID.")";

    if ($sID == "") return false;
		if (!is_numeric($sID) || strlen(intval($sID)) != strlen(strval($sID))) {
			$arr = $this->_getUser($sID);
			$sID = $arr['PersonID'];
		}
    if ($sID == "") return false;

    $result = $this->sql("
      SELECT
        *
      FROM
        `ibr_log_changes`
      WHERE
        `id_Person`='".$sID."'
      AND
      	`execute_date`>=NOW()
      AND
      	`executed`!='1'", "id");

		if (is_array($result))
			$retVal = $result;
		else
			$retVal = false;
		return $retVal;
  }
  // }}}

	// {{{ require_roles
	/**
	 * führt den Array der für eine Seite benötigten Rollen
	 *
   * @return void
	 */
	function require_roles($val = false)
	{
		$this->_debugInfo[] = "function require_roles(".$val.")";

		if ($val == false) {
			unset($this->arr_require_roles);
			return;
		}
		!is_array($val) ? $arr[] = $val : $arr = $val;
		foreach ($arr as $id_role) {
			if (!is_numeric($id_role)) {
				foreach ($this->_arrRoles as $id => $val) {
					if ($val['Bezeichnung'] == $id_role) {
						$id_role = $id;
						break;
					}
				}
			}
			$this->arr_require_roles[$id_role] = $this->arr_require_roles[$id_role] ? false : true;
			$this->arr_require_roles[$id_role] ? $this->_debugInfo[] = "require_roles -> id_role: ".$id_role." required" : 0;
		}
	}
	// }}}

	// {{{ require_roles_by_textnr
	/**
	 * führt den Array der für eine Seite benötigten Rollen
	 *
   * @return void
	 */
	function require_roles_by_textnr($val = false)
	{
		if ($val == false) {
			$this->_debugInfo[] = "function require_roles_by_textnr()";
			unset($this->arr_require_roles);
			return;
		}
		!is_array($val) ? $arr[] = $val : $arr = $val;
		$this->_debugInfo[] = "function require_roles_by_textnr(".implode(", ", $val).")";
  	foreach ($arr as $textnr) {
  		foreach ($this->_arrRoles as $id_role => $val) {
  			if ($textnr == $val['Textnr']) {
  				$this->arr_require_roles[$id_role] = $this->arr_require_roles[$id_role] ? false : true;
					$this->arr_require_roles[$id_role] ? $this->_debugInfo[] = "require_roles_by_textnr -> id_role: ".$id_role." required" : 0;
					break;
				}
			}
		}
	}
	// }}}

	// {{{ checkAbonnementsAvailability
	/**
	 * liefert für die Abonnements eines Benutzers die aktuell zur Verfügung stehenden freien Plätze
	 *
   * @return void
	 */
	function checkAbonnementsAvailability()
	{
		$this->_debugInfo[] = "function checkAbonnementsAvailability";
		$this->_debugInfo[] = "checkAbonnementsAvailability -> _checkAbonnementsAvailability:".$this->_checkAbonnementsAvailability;
		if (!is_array($this->data))
			return 0;

		if ($this->_regularLogin) {
			$this->_debugInfo[] = "checkAbonnementsAvailability -> pre-checking availableSessionsBeforeLogin: ".$this->data['::AuthData::']['availableSessionsBeforeLogin'];
			$this->data['::AuthData::']['availableSessionsBeforeLogin'] != $this->data['::AuthData::']['maxAllowedSessions'] ? $this->data['::AuthData::']['availableSessionsBeforeLogin'] = $this->data['::AuthData::']['maxAllowedSessions'] : 0;
			$this->_debugInfo[] = "checkAbonnementsAvailability -> post-checking availableSessionsBeforeLogin: ".$this->data['::AuthData::']['availableSessionsBeforeLogin'];
			if (!$this->data['Großkunde']) {
				$result = $this->sql("SELECT * FROM `Session` WHERE `LoginTime`>=DATE_SUB(NOW(), INTERVAL 1 DAY) AND `SessionID`<>'".$this->SessionID."' AND `PersonID`='".$this->data['PersonID']."' AND `Valid`='Y'");
				if (is_array($result)) {
					foreach($result as $val) {
						$this->_debugInfo[] = "checkAbonnementsAvailability -> found other valid SessionID: ".$val['SessionID'];
						$this->_debugInfo[] = "checkAbonnementsAvailability -> other session Login Time: ".$val['LoginTime'];
						$this->_debugInfo[] = "checkAbonnementsAvailability -> other session Last Access: ".$val['LastAccess'];
						$this->_debugInfo[] = "checkAbonnementsAvailability -> other session Logout Time: ".$val['LogoutTime'];
						$this->_debugInfo[] = "checkAbonnementsAvailability -> other session Valid: ".$val['Valid'];
						$this->data['::AuthData::']['availableSessionsBeforeLogin'] -= 1;
						foreach ($this->arr_require_roles as $id_role => $v) {
							if (($val['SessionType'] >> $id_role) % 2 == 1) {
								if (is_array($this->data['Abonnements'][$id_role])) {
									$this->data['Abonnements'][$id_role]['Frei']--;
									$this->_debugInfo[] = "checkAbonnementsAvailability -> other session running role_id: ".$id_role." (".$this->_arrRoles[$id_role]['Bezeichnung'].") leaving free slots: ".$this->data['Abonnements'][$id_role]['Frei'];
									if ($this->data['Abonnements'][$id_role]['Frei'] <= 0) {
										$this->arr_missing_roles[$id_role] = true;
										$this->data['AbonnementsNeeded'] = true;
										$this->_debugInfo[] = "checkAbonnementsAvailability -> id_role: ".$id_role." (".$this->_arrRoles[$id_role]['Bezeichnung'].") - no slots available";
									}
								} else {
									if ($this->data['PersonID'] == 9737) {
									  echo "DEBUG<hr>";
									  print_r($this->data['Abonnements']);
									}
									$this->arr_missing_roles[$id_role] = true;
									$this->data['AbonnementsNeeded'] = true;
									$this->_debugInfo[] = "checkAbonnementsAvailability -> id_role: ".$id_role." (".$this->_arrRoles[$id_role]['Bezeichnung'].") - not available";
								}
							}
						}
					}
				} else {
					$this->_debugInfo[] = "checkAbonnementsAvailability -> check arr_require_roles";
					foreach ($this->arr_require_roles as $id_role => $v) {
						if (is_array($this->data['Abonnements'][$id_role])) {
							$this->data['Abonnements'][$id_role]['Frei']--;
							$this->_debugInfo[] = "checkAbonnementsAvailability -> check arr_require_roles, role_id: ".$id_role.", ".$this->_arrRoles[$id_role]['Bezeichnung'].": ".$this->data['Abonnements'][$id_role]['Frei'];
							if ($this->data['Abonnements'][$id_role]['Frei'] < 0) {
								$this->arr_missing_roles[$id_role] = true;
								$this->data['AbonnementsNeeded'] = true;
								$this->_debugInfo[] = "checkAbonnementsAvailability -> check arr_require_roles, id_role: ".$id_role." (".$this->_arrRoles[$id_role]['Bezeichnung'].") - no slots available";
							}
						} else {
							$this->arr_missing_roles[$id_role] = true;
							$this->data['AbonnementsNeeded'] = true;
							$this->_debugInfo[] = "checkAbonnementsAvailability -> id_role: ".$id_role." (".$this->_arrRoles[$id_role]['Bezeichnung'].") - not available";
						}
					}
				}
			} else {
				$this->_debugInfo[] = "checkAbonnementsAvailability -> Großkunde";
				$lMID = $this->data['MID'] ? $this->data['MID'] : 0;
				$this->data['::MID-Roles::'] = $this->checkRoles4MID($this->data['PersonID'], $lMID);
				if (is_array($this->data['::MID-Roles::'])) {
					foreach ($this->arr_require_roles as $id_role => $v) {
						if (!in_array($id_role, $this->data['::MID-Roles::'])) {
							$this->arr_missing_roles[$id_role] = true;
							$this->data['AbonnementsNeeded'] = true;
							$this->_debugInfo[] = "checkAbonnementsAvailability -> id_role: ".$id_role." (".$this->_arrRoles[$id_role]['Bezeichnung'].") - not available";
							//$this->data['::AuthData::']['availableSessionsBeforeLogin'] = 0;
							break;
						}
					}
					if ($this->data['::AuthData::']['availableSessionsBeforeLogin'] > 0) {
						$this->_debugInfo[] = "checkAbonnementsAvailability -> checking other active sessions";
						$result = $this->sql("SELECT * FROM `Session` WHERE `LoginTime`>=DATE_SUB(NOW(), INTERVAL 1 DAY) AND `SessionID`<>'".$this->SessionID."' AND `PersonID`='".$this->data['PersonID']."' AND `Valid`='Y'");
						if (is_array($result)) {
							foreach($result as $val) {
								if ($val['MID'] == $lMID) {
									$this->_debugInfo[] = "checkAbonnementsAvailability -> found other active session with same MID";
									$this->data['AbonnementsNeeded'] = true;
									$this->data['::AuthData::']['availableSessionsBeforeLogin'] = 0;
									break;
								}
							}
						}
						$this->data['::AuthData::']['availableSessionsBeforeLogin'] > 0 ? $this->data['::AuthData::']['availableSessionsBeforeLogin'] = 1 : 0;
					}
				} else {
					$this->data['AbonnementsNeeded'] = true;
					$this->_debugInfo[] = "checkAbonnementsAvailability -> no roles found for MID";
					$this->data['::AuthData::']['availableSessionsBeforeLogin'] = 0;
				}
			}
		}
		$this->_debugInfo[] = "checkAbonnementsAvailability -> availableSessionsBeforeLogin: ".$this->data['::AuthData::']['availableSessionsBeforeLogin'];
	}
	// }}}

	// {{{ abo_available
	/**
	 * liefert für ein Abonnement des Benutzers, ob eine Erweiterung nötig ist
	 *
   * @param array	$lID		die ID des zu prüfenden Abos
   *
   * @return boolean
	 */
	function abo_available($lID = 0)
	{
		$this->_debugInfo[] = "function abo_available(".$lID.")";

		if (!$lID || !is_array($this->data))
      $retVal = false;
    else {
      if (!is_array($this->data['Abonnements'])) {
      	$this->data['Abonnements'] = $this->getAbonnements($this->ID);
      	$this->checkAbonnementsAvailability();
      }
      $retVal = $this->data['Abonnements'][$lID]['Freigeschaltet'] == USER_ACCOUNT_OK ? true : false;
		  $this->_debugInfo[] = "Freigeschaltet: ".$retVal;
      $retVal = $retVal && $this->data['Abonnements'][$lID]['Frei'] >= 0 ? true : false;
		  $this->_debugInfo[] = "Frei: ".$retVal;
      $retVal && is_array($this->arr_missing_roles) && in_array($lID, $this->arr_missing_roles) ? $retVal = false : 0;
		  $this->_debugInfo[] = "arr_missing: ".$retVal;
    }
		$this->_debugInfo[] = "retVal: ".$retVal;
    return $retVal;
	}
	// }}}


	// {{{ getAbonnementsRunning
	/**
	 * liefert alle derzeit eingeloggten Abonnements zu einer PersonID
	 *
	 * @param int   $iPersonID
	 *
	 * return array
	 */
	function getAbonnementsRunning($iPersonID)
	{
		$this->_debugInfo[] = "function getAbonnementsRunning(".$iPersonID.")";
    $result = $this->sql("
      SELECT
        `SessionID`,
        DATE_FORMAT(`LoginTime`, '%H:%i') AS `LoginTime`,
        DATE_FORMAT(`LastAccess`, '%H:%i') AS `LastAccess`,
        `SessionType`
      FROM
        `Session`
      WHERE
        `PersonID`='".$iPersonID."'
      AND
        `Valid`='Y'
    ", "");
    if (is_array($result))
      return $result;
    else
      return array();
	}
	// }}}

	// {{{ logout
	/**
	 * loggt den Benutzer aus
	 *
   * @return void
	 */
	function logout()
	{
		$this->_debugInfo[] = "function logout";
		$this->ID ? $this->set_login_stats(array("LastAccess" => "NOW()", "LastLogout" => "NOW()", "Anzahl_Logout_User" => "Anzahl_Logout_User+1"), $this->ID, true) : 0;
		$this->ID ? $this->set_ibr_login_stats(array("last_access" => "NOW()", "last_logout" => "NOW()", "logouts_user_total" => "logouts_user_total+1"), $this->ID, true) : 0;
		if (strpos($_SERVER['PHP_SELF'], "Logout.php") === false) {
			$this->_debugging_next = true;
			$this->logDB("logout -> logout ".$this->SessionID.", Datei: ".$_SERVER['PHP_SELF']);
		}
		$this->closeSession();
		$this->deleteCookie();
		$this->data = array();
		$this->dataExt = array();
	}
	// }}}

	// {{{ startSession
	/**
	 * startet die Session für den Benutzer
	 *
   * @return void
	 */
	function startSession()
	{
		$this->_debugInfo[] = "function startSession";
		if ($this->_regularLogin) {
			if ($this->_SessionStarted) {
				$this->_debugInfo[] = "startSession -> already started";
				$this->refreshSession();
			} else {
		    if (is_array($this->data)) {
		    	$result = $this->SessionID ? $this->checkSession(array("SessionID" => $this->SessionID, "PersonID" => $this->data['PersonID'], "MID" => $this->data['MID'])) : false;
		    	if (!is_array($result) || !count($result))
		    		$this->createSession();
		    	else {
		    		$this->_debugInfo[] = "startSession -> SessionID: ".$result[0]['SessionID'];
		    		$this->SessionID = $result['SessionID'];
		    		$this->_SessionStarted = true;
		    	 	$this->updateSessionData();
		    	}
		    }
		  }
		} else
			$this->_debugInfo[] = "startSession -> _regularLogin: ".$this->_regularLogin;
	}
	// }}}

	// {{{ checkSession
	/**
	 * prüft ob es für eine Session noch aktive/reaktivierbare Sessiondaten gibt
	 *
	 * @param array	$arrWHERE		Array (Schlüssel = Spalte in DB, Wert = Wert in DB)
	 *
   * @return array/false
	 */
	function checkSession($arrWHERE)
	{
		global $func;

		if ($this->_regularLogin) {
			if (!is_array($arrWHERE)) {
				$this->_debugInfo[] = "function checkSession()";
			  $this->_debugInfo[] = "checkSession -> !is_array(arrWHERE)";
				return false;
			}
			$this->_debugInfo[] = "function checkSession(".$func->implode_assoc($arrWHERE, " => ", ", ").")";
			if (is_array($this->_checkedSessions) && $arrWHERE['SessionID'] && !array_key_exists($arrWHERE['SessionID'], $this->_checkedSessions)) {
				$sWHERE_DayValidation = date("G") < 3 ? "(`LoginTime`>=CURDATE() OR `LoginTime`>=DATE_SUB(NOW(), INTERVAL 1 DAY))" : "`LoginTime`>=CURDATE()";
				$WHERE = $func->implode_assoc($arrWHERE, "=", " AND ", "`", "'");
				$func->str_add("`LogoutTime`='00-00-00 00:00:00'", $WHERE, " AND ");
				$WHERE != "" ? $WHERE = " AND ".$WHERE." ORDER BY `LastAccess` DESC LIMIT 1" : 0;
				$SQL = "SELECT * FROM `Session` WHERE ".$sWHERE_DayValidation.$WHERE;
				//$this->_debugInfo[] = "checkSession -> SQL: ".addslashes($SQL;
				$result = $this->sql($SQL, true);
				if (is_array($result)) {
					if ($result[0]['Valid'] == "N") {
						$this->_debugInfo[] = "checkSession -> N";
						$this->_checkAbonnementsAvailability = true;
						if (array_key_exists("SessionID", $arrWHERE))
							$this->_checkedSessions[$arrWHERE['SessionID']] = false;
					} else {
						$this->_debugInfo[] = "checkSession -> Y";
						if (array_key_exists("SessionID", $arrWHERE))
							$this->_checkedSessions[$arrWHERE['SessionID']] = true;
				  }
				  $this->_debugInfo[] = "checkSession -> is_array(result)";
				  $this->data['::session::'] = $result[0];
				  $this->_login_with_ip_check = $this->data['::session::']['login_with_ip_check'];
				  if ($this->_login_with_ip_check) {
				  	$this->_debugInfo[] = "checkSession -> login_with_ip_check = 1";
				  	$this->_arr_login_with_ip_check = $this->ip_check();
				  	if (!is_array($this->_arr_login_with_ip_check)) {
				  		$this->_login_with_ip_check = false;
				  		$this->_SessionStarted = true;
				  		$this->SessionID = $this->data['::session::']['SessionID'];
				  		unset($this->data['::session::']);
				  		$this->closeSession();
				  	} else {
							$this->_login_with_ip_check_success = true;
				  		return $result[0];
				  	}
				  } else {
						/*
						if ($result[0]['Valid'] == "N") {
				  		$this->_debugInfo[] = "checkSession -> not valid anymore";
							return SESSION_NOT_VALID_ANYMORE;
				  	} else
				  	*/
				  		return $result[0];
					}
				} else {
					if (array_key_exists("SessionID", $arrWHERE))
						$this->_checkedSessions[$arrWHERE['SessionID']] = false;
				  $this->_debugging_next = true;
				  $this->_debugInfo[] = "checkSession -> !is_array(result), DB: ".$sql->db['database'];
				  $this->logDB[] = "checkSession -> !is_array(result)";
				  unset($this->data['::session::']);
					return SESSION_SESSION_NOT_FOUND;
				}
			} else {
				if ($arrWHERE['SessionID'])
					return $this->_checkedSessions[$arrWHERE['SessionID']];
			}
		} else
			$this->_debugInfo[] = "checkSession -> _regularLogin:".$this->_regularLogin;
  }
	// }}}

	// {{{ SessionValid
	/**
	 * prüft ob eine Session ID gültig ist
	 *
	 * @param string	$sSessionID   die zu prüfende Session ID
	 *
   * @return bool
	 */
	function SessionValid($sSessionID)
	{
		$this->_debugInfo[] = "function SessionValid(".$sSessionID.")";
		if ($sSessionID) {
			if (!array_key_exists($sSessionID, $this->_checkedSessions)) {
				$this->_debugInfo[] = "SessionValid -> check new";
				$retVal = false;
				if ($sSessionID != "") {
					$result = $this->checkSession(array("SessionID" => $sSessionID));
					$retVal = is_array($result);
				}
			} else {
				$this->_debugInfo[] = "SessionValid -> already checked";
				$retVal = $this->_checkedSessions[$sSessionID];
			}
		} else
			$this->_debugInfo[] = "SessionValid -> no SessionID";
		$retVal == false ? $this->clear_SessionID() : 0;
		$this->_debugInfo[] = "SessionValid -> retVal:".$retVal;
		return $retVal;
  }
	// }}}

	// {{{ createSession
	/**
	 * erzeugt eine neue Session
	 *
   * @return array
	 */
	function createSession()
	{
		if ($this->_regularLogin) {
			$this->_debugInfo[] = "function createSession";

	    $this->data['::session::']['SessionType'] = 0;
	    if (is_array($this->arr_require_roles)) {
	    	foreach ($this->arr_require_roles as $id_role => $required) {
		  		if ($required && !$this->arr_missing_roles[$id_role]) {
		  			$this->data['::session::']['SessionType'] += (1 << $id_role);
		  			$this->_debugInfo[] = "createSession -> adding id_role: ".$id_role;
		  		}
	    	}
	    }

	    srand((double)microtime()*1000000);
	    $rand = rand();
	    $this->SessionID = md5(date("His").$rand);
	    $this->BauNord ? $this->SessionID = "baun".substr($this->SessionID, 4) : 0;
	    $this->data['::session::']['SessionID'] = $this->SessionID;
			$lLoginWithIPCheck = $this->_login_with_ip_check ? 1 : 0;
			$result = $this->sql("
				INSERT
				INTO
					`Session`
				(
					`SessionID`,
				 	`PersonID`,
				 	`Valid`,
				 	`LoginTime`,
				 	`LastAccess`,
				 	`SessionType`,
				 	`MID`,
				 	`login_with_ip_check`
				)
				VALUES
				(
					'".$this->data['::session::']['SessionID']."',
					'".$this->data['PersonID']."',
					'Y',
					NOW(),
					NOW(),
					'".$this->data['::session::']['SessionType']."',
					'".$this->data['MID']."',
					'".$lLoginWithIPCheck."'
				)");
	 		if ($result)
	 			$this->_SessionStarted = true;
	 		else {
	   		$this->_SessionStarted = false;
	   		$this->clear_SessionID;
	   	}
		} else
			$this->_debugInfo[] = "! function createSession";
	}
	// }}}

	// {{{ getSessionBy
	/**
	 * liest eine Session je nach übergebenem Array
	 *
	 * @param array	$arrWHERE		Array (Schlüssel = Spalte in DB, Wert = Wert in DB)
	 *
   * @return array
	 */
	function getSessionBy($arrWHERE)
	{
		global $func;
		
		$this->_debugInfo[] = "function getSessionBy";
		$retVal = array();
		if (!is_array($arrWHERE)) {
		  $this->_debugInfo[] = "getSessionBy -> !is_array(arrWHERE)";
			return $retVal;
		}
		$WHERE = $func->implode_assoc($arrWHERE, "=", " AND ", "`", "'");
		$WHERE = $WHERE != "" ? "WHERE ".$WHERE : "";
		$result = $this->sql("SELECT * FROM `Session` ".$WHERE);
		if (is_array($result)) {
	  	$retVal = $result[0];
		  if (substr($retVal['LoginTime'], 0, 10) == date("Y-m-d") || (date("G") < 3 && substr($retVal['LoginTime'], 0, 10) == date("Y-m-d", (date("U") - 86000)))) {
		    $this->_debugInfo[] = "getSessionBy -> refreshing possible";
		    !$this->SessionID ? $this->SessionID = $retVal['SessionID'] : 0;
		    $this->refreshSession();
		    $this->data['::session::'] = $retVal;
		    return $retVal;
		  } else {
		    $this->_debugInfo[] = "getSessionBy -> refreshing NOT possible > SESSION_TIMEOUT";
		    unset($this->data['::session::']);
		  	return SESSION_TIMEOUT;
      }
		} else {
	    $this->_debugInfo[] = "getSessionBy -> SESSION_SESSION_NOT_FOUND";
	    unset($this->data['::session::']);
      return SESSION_SESSION_NOT_FOUND;
		}
	}
	// }}}

	// {{{ refreshSession
	/**
	 * erneuert die Lifetime einer SessionID
	 *
   * @return void
	 */
	function refreshSession()
	{
		$this->_debugInfo[] = "function refreshSession";
		if (!$this->_Session_refreshed) {
			$this->_debugInfo[] = "refreshSession -> SessionID: ".$this->SessionID;
	    $this->data['::session::']['SessionType'] = 0;
	    if (is_array($this->arr_require_roles)) {
	    	foreach ($this->arr_require_roles as $id_role => $required) {
		  		if ($required && !$this->arr_missing_roles[$id_role]) {
		  			$this->data['::session::']['SessionType'] += (1 << $id_role);
		  			$this->_debugInfo[] = "refreshSession -> adding id_role: ".$id_role;
		  		}
	    	}
	    }
			$this->_debugInfo[] = "refreshSession -> SessionType: ".$this->data['::session::']['SessionType'];
			$result = $this->sql("UPDATE `Session` SET `Valid`='Y', `SessionType`='".$this->data['::session::']['SessionType']."', `LastAccess`='".date("Y-m-d H:i:s")."' WHERE `SessionID`='".$this->SessionID."'");
			if ($result < 0) {
				$this->_debugInfo[] = "refreshSession -> UPDATE failed (".$this->SessionID.")";
				$this->_clear_SessionID();
				$this->_SessionStarted = false;
			} else {
				$this->_debugInfo[] = "refreshSession -> refreshed";
    		$this->_checkedSessions[$this->SessionID] = true;
    		$this->_SessionStarted = true;
				$this->_Session_refreshed = true;
			}
		} else {
			$this->_SessionStarted = true;
			$this->_debugInfo[] = "refreshSession -> already refreshed";
  		$this->_checkedSessions[$this->SessionID] = true;
		}
	}
	// }}}

	// {{{ updateSessionData
	/**
	 * schreibt neue Werte in die laufende Session
	 *
   * @return void
	 */
	function updateSessionData()
	{
		$this->_debugInfo[] = "function updateSessionData";
    $this->data['::session::']['SessionType'] = 0;
    if (is_array($this->data['Abonnements'])) {
    	foreach ($this->data['Abonnements'] as $val)
	  		$this->data['::session::']['SessionType'] += (1 << $val['RolleID']);
    }
		$this->logDB("INFO: user->updateSessionData ".$this->ID." ".$this->data['http_auth']['ID']." ".$this->data['http_auth']['Kennung']." (".$this->SessionID."), ".$_SERVER['PHP_SELF']);
		$lLoginWithIPCheck = $this->_login_with_ip_check ? 1 : 0;
		$result = $this->sql("
			UPDATE
				`Session`
			SET
				`SessionType`='".$this->data['::session::']['SessionType']."',
				`login_with_ip_check`='".$lLoginWithIPCheck."'
				`LastAccess`=NOW()
			WHERE
				`SessionID`='".$this->SessionID."'
		");
		if (!$result) {
			$this->clear_SessionID();
			$this->_SessionStarted = false;
		}
	}
	// }}}

	// {{{ sessionTimedOut
	/**
	 * prüft, ob eine Session den Timeout erreicht hat
	 *
	 * @param array		$arrSession		der Session-Array
	 *
   * @return bool
	 */
	function sessionTimedOut($arrSession)
	{
		$this->_debugInfo[] = "function sessionTimedOut()";
		if (!is_array($arrSession) || date("U") - strtotime($arrSession['LastAccess']) > $this->sessionTimeout)
			return true;
		else
			return false;
	}
	// }}}

	// {{{ getSessionData
	/**
	 * liefert relevante Sessiondaten
	 *
	 * @param string		$SessionID		eine Session ID
	 *
   * @return array
	 */
  function getSessionData($SessionID)
  {
  	global $func;
  	
		$this->_debugInfo[] = "function getSessionData(".$SessionID.")";
    if ($SessionID == "")
      return array();
    $result = $this->sql("
      SELECT
        s.*,
        p.`Name`,
        p.`Vorname`
      FROM
        `Session` AS s
      LEFT JOIN
        `Person` AS p
      ON
        s.`PersonID`=p.`PersonID`
      WHERE
        s.`SessionID`='".$SessionID."'
    ");
    if (is_array($result) && count($result)) {
      $currSession = $result[0];
      $result = $this->sql("
        SELECT
          *
        FROM
          `Session`
        WHERE
          `PersonID`='".$currSession['PersonID']."'
        AND
          `SessionID`<>'".$SessionID."'
        AND
          `Valid`='N'
        ORDER BY
          `LoginTime` DESC
        LIMIT 1
      ");
      if (is_array($result))
        $lastSession = $result[0];
      else {
        $result = $this->sql("
          SELECT
            `LastLogin`,
            `LastAccess`,
            `LastLogout`
          FROM
            `Stat_Sessiondata`
          WHERE
            `PersonID`='".$currSession['PersonID']."'
        ");
        if (is_array($result))
          $lastSession = $result[0];
        else
          $lastSession = array();
      }
      $result = $this->sql("
        SELECT
          SUM(IF(`Valid`='Y', 1, 0)) AS lSessionsValid,
          SUM(IF(`Valid`='N', 1, 0)) AS lSessionsInvalid
        FROM
          `Session`
        WHERE
          `PersonID`='".$currSession['PersonID']."'
      ");
      if (is_array($result))
        $arrSessionsValid = $result[0];
      else
        $arrSessionsValid = array();
      $result = $this->sql("
        SELECT
          `Session_Anzahl`
        FROM
          `Stat_Sessiondata`
        WHERE
          `PersonID`='".$currSession['PersonID']."'
      ");
      if (is_array($result))
        $arrSessionsValid['lSessionsInvalid'] += $result[0]['Session_Anzahl'];

      $logoutBy = $lastSession['LastAccess'] == $lastSession['LogoutTime'] ? "User" : "System";

      $retVal = array(
        "PersonID"          => $currSession['PersonID'],
        "Name"              => $currSession['Name'],
        "Vorname"           => $currSession['Vorname'],
        "currentLoginTime"  => $func->mysql2date($currSession['LoginTime']),
        "currentAccessTime" => $func->mysql2date($currSession['LastAccess']),
        "currentLogoutTime" => $func->mysql2date($currSession['LogoutTime']),
        "lastLoginTime"     => $func->mysql2date($lastSession['LoginTime']),
        "lastAccessTime"    => $func->mysql2date($lastSession['LastAccess']),
        "lastLogoutTime"    => $func->mysql2date($lastSession['LogoutTime']),
        "lastLogoutBy"      => $logoutBy,
        "ValidSessions"     => $arrSessionsValid['lSessionsValid'],
        "InvalidSessions"   => $arrSessionsValid['lSessionsInvalid']
      );
      return $retVal;
    } else
      return array();
  }
  // }}}

	// {{{ closeSession
	/**
	 * beendet die Session des Benutzers
	 *
   * @return void
	 */
	function closeSession()
	{
		global $env;

		$this->_debugInfo[] = "function closeSession";
		if ($this->_SessionStarted && $this->SessionID) {
			$this->_debugInfo[] = "closeSession -> SessionID: ".$this->SessionID.", ".$_SERVER['PHP_SELF'];
			$this->_debugging_next = true;
			$this->logDB("closeSession -> user->ID:".$this->ID." http_auth-ID: ".$this->data['http_auth']['ID']." http_auth-Kennung: ".$this->data['http_auth']['Kennung']." SessionID: ".$this->SessionID.", ".$_SERVER['PHP_SELF']);
			$this->sql("UPDATE `Session` SET `Valid`='N', `LastAccess`=NOW(), `LogoutTime`=NOW() WHERE `SessionID`='".$this->SessionID."'");
		} else {
			$this->_debugging_next = true;
			if (!$this->SessionID)
				$this->logDB("closeSession -> no SessionID, ".$_SERVER['PHP_SELF']);
			else
				$this->logDB("closeSession -> session not started, ".$_SERVER['PHP_SELF']);
		}
		$this->_SessionStarted = false;
		$this->clear_SessionID();
	  $this->deprecatedAdjustments();
	}
	// }}}

	// {{{ terminateSession
	/**
	 * Fremde Sitzung beenden
	 *
	 * @param string  $sUserName    Kennung des Benutzers der terminieren möchte
	 * @param string  $sTimestamp   unixdate|crypt(Passwort, unixdate)|SessionID
	 *
	 * @return bool
	 */
	function terminateSession($sUserName, $sTimestamp)
	{
		$this->_debugInfo[] = "function terminateSession";
	  $arrTimestamp = explode("|", $sTimestamp);
	  if ($arrTimestamp[0] + $this->sessionTimeout < date("U"))
	    return SESSION_TERMINATE_TIMEOUT;

	  $result = $this->getUserData($sUserName);
		!$this->ID_before_login_complete ? $this->ID_before_login_complete = $result['PersonID'] : 0;
	  if ($arrTimestamp[1] != crypt($result['Passwort'], $arrTimestamp[0])) {
    	$this->_debugging_next = true;
      $this->logDB("terminateSession-> invalid password: ".$arrTimestamp[0]." (".$result['Passwort'].")");
	    return USER_INVALID_PASSWORD;
	  } else {
	    $this->_checkPass = false;
	    $result = $this->checkSession(array("SessionID" => $arrTimestamp[2]));
	    if (!count($result)) {
    		$this->_debugging_next = true;
	      $this->logDB("terminateSession-> session not found SessionID: ".$arrTimestamp[2]);
	      return SESSION_SESSION_NOT_FOUND;
      } else {
			  $this->_debugInfo[] = "terminateSession -> SessionID: ".$arrTimestamp[2];
    		$this->_debugging_next = true;
	      $this->logDB("terminateSession-> terminating SessionID: ".$arrTimestamp[2]);
	      return $this->sql("UPDATE `Session` SET `Valid`='N' WHERE `SessionID`='".$arrTimestamp[2]."'");
      }
	  }
	}
	// }}}

	// {{{ get_role_title
	/**
	 * liefert den Titel einer Rolle
	 *
	 * @param long/array  $lID	ID der Rolle
	 *
   * @return string
	 */
  function get_role_title($lID, $bHTML = false, $bPersonalMenu = false)
  {
		$retVal = "";
		if (!is_array($lID) && is_array($this->_arrRoles[$lID]))
			$arr = $this->_arrRoles[$lID];
		elseif (is_array($lID))
			$arr = $lID;
		$sType = $bHTML ? "_HTML" : "";
		if (is_array($arr)) {
			if (!$bPersonalMenu) {
		    $arr['info_array']['Autor'.$sType] != "" ? $retVal = "<i>".$arr['info_array']['Autor'.$sType]."</i>" : 0;
		    $retVal != "" && $arr['info_array']['Titel'.$sType] ? $retVal .= "<br />".$arr['info_array']['Titel'.$sType] : 0;
			} else
		    $retVal = $arr['info_array']['Titel_personal_menu'];
	    $retVal == "" ? $retVal = $arr['Kurzbeschreibung'] : 0;
	    $retVal == "" ? $retVal = $arr['Bezeichnung'] : 0;
	    $retVal == "" ? $retVal = "RolleID: ".$arr['RolleID'] : 0;
			!$bHTML ? $retVal = strip_tags(str_replace("<br />", " - ", $retVal)) : 0;
		}
		return $retVal;
	}
	// }}}

	// {{{ _getUser
	/**
	 * holt Daten eines Benutzers
	 *
	 * @param string  $sUser		Kennung oder ID Benutzers
	 *
   * @return false/array
	 */
  function _getUser($sUser)
  {
		$this->_debugInfo[] = "function _getUser(".$sUser.")";
		$bForceKennung = $this->data['Kennung'] && $this->data['Kennung'] == $sUser ? true : false;
		$this->_debugInfo[] = "_getUser -> bForceKennung: ".$bForceKennung;
		if (is_numeric($sUser) && strlen(intval($sUser)) == strlen(strval($sUser)) && !$bForceKennung)
			$mySQL = "SELECT P.*, A.`Kennung` FROM `Person` AS P LEFT JOIN `AuthData` AS A ON A.`PersonID`=P.`PersonID` WHERE P.`PersonID`='".$sUser."'";
		else
			$mySQL = "SELECT P.*, A.`Kennung` FROM `AuthData` AS A LEFT JOIN `Person` AS P ON P.`PersonID`=A.`PersonID` WHERE A.`Kennung`='".$sUser."'";
		$result = $this->sql($mySQL);
		if (is_array($result)) {
			if (is_numeric($sUser) && strlen(intval($result[0]['PersonID'])) != strlen(strval($sUser)) && !$bForceKennung)
				return false;
			else
				return $result[0];
		} else
			return false;
	}
	// }}}

	// {{{ updateAbonnement
	/**
	 * ändert die Abonnements eines Benutzers
	 *
	 * @param string  $sUser		Kennung oder ID Benutzers
	 * @param array   $arrAbo		Array mit den Abo-IDs als Schlüssel
	 *														Variante a) und der neuen Anzahl an Abos als Wert << DEFAULT
	 *														Variante b) und einem Array der Form
	 *															"Arbeitsplaetze" => 1, <<<<< MUSS-Angabe
	 *															"Freigeschaltet" => "Ja",
	 *															"Anmeldedatum" => "YYYY-MM-DDD",
	 *															"Freischaltdatum" => "YYYY-MM-DD",
	 *															"FreiAbo" => "Ja"/"Nein"
	 *														Sollte der Array Variante a) sein, wird er in Variante b) umgeformt
	 *
   * @return int/array  int wenn ein Fehler aufgetreten ist oder Array mit den Abo-IDs als Schlüssel und dem Ergebnis der Änderung als int
	 */

  function updateAbonnement($sUser, $arrAbo)
  {
  	global $Abopreise, $func, $env;

		$this->_debugInfo[] = "function updateAbonnement(".$sUser.", ".serialize($arrAbo).")";
    $retVal = false;
		if (is_array($arrAbo)) {
			$arrUser = $this->_getUser($sUser);
			if (is_array($arrUser)) {
				!is_array($this->data['::Roles::']) ? $this->data['::Roles::'] = $this->getRoles($arrUser['PersonID']) : 0;
				$arrUser['Abonnements'] = $this->getAbonnements($arrUser['PersonID']);
				!array_key_exists(ROLES_IBR, $arrAbo) ? $arrAbo[ROLES_IBR] = $arrUser['Abonnements'][ROLES_IBR] : 0;
				$max_value = is_array($arrAbo[ROLES_IBR]) && array_key_exists("Arbeitsplaetze", $arrAbo[ROLES_IBR]) ? $arrAbo[ROLES_IBR]['Arbeitsplaetze'] : $arrAbo[ROLES_IBR];
				$this->arrUpdateAbonnement['updated_by'] == "" && $this->admin ? $this->arrUpdateAbonnement['updated_by'] = "Verlag" : 0;
				$this->arrUpdateAbonnement['updated_by'] == "" ? $this->arrUpdateAbonnement['updated_by'] = $arrUser['Kennung'] : 0;
        foreach ($arrAbo as $id_role => $val) {
					if (!array_key_exists($id_role, $this->_arrRoles))
						continue;
					!is_array($val) ? $val = array("Arbeitsplaetze" => $val) : 0;

					$bNeedChange = false;
					$bRoleFound = false;
					$mail_content = 0;
					$retVal[$id_role] = array(
						"id_role" => $id_role,
						"sRole" => $this->get_role_title($id_role),
						"Bezeichnung" => $this->_arrRoles[$id_role]['Bezeichnung'],
						"Kurzbeschreibung" => $this->_arrRoles[$id_role]['Kurzbeschreibung'],
						"Titel" => $this->_arrRoles[$id_role]['info_array']['Titel'],
						"Titel_HTML" => $this->_arrRoles[$id_role]['info_array']['Titel_HTML'],
						"Autor" => $this->_arrRoles[$id_role]['info_array']['Autor'],
						"Autor_HTML" => $this->_arrRoles[$id_role]['info_array']['Autor_HTML'],
						"updates" => array());
					$this->_debugInfo[] = "updateAbonnement -> checking role ".$retVal[$id_role]['sRole']." (".$id_role.")";
					if (is_array($arrUser['Abonnements'][$id_role])) {
						$this->arrUpdateAbonnement['has_roles'] = true;
						foreach ($arrUser['Abonnements'][$id_role] as $k => $v) {
							if (is_array($val) && array_key_exists($k, $val) && $v != $val[$k]) {
								$this->_debugInfo[] = "updateAbonnement -> need change: ".$k.":".$v.":".$val[$k];
								$bNeedChange = true;
								break;
							}
						}
					} else {
						if ($val['Arbeitsplaetze']) {
				  		$val['Freigeschaltet'] = "Ja";
					  	$val['Freischaltdatum'] = "NOW()";
					  	$bNeedChange = true;
						}
					}
					if ($val['delete_delay']) {
						$arrDeleteDelay[$id_role] = $val['delete_delay'];
						$retVal[$id_role]['delete_delay'] = true;
						$bNeedChange = true;
					}

					if (!$bNeedChange)
						continue;

					$retVal[$id_role]['offer_as_trial'] = $this->role_offer_as_trial($id_role);
					$retVal[$id_role]['is_trial'] = $this->role_is_trial($id_role);
					$bChangesMade = true;

					$useDelay = $val['delay'] ? $val['delay'] : 0;
					$useDelay == date("d.m.Y") ? $useDelay = false : 0;

					$retVal[$id_role]['terminate_result'] = $this->sql("
						DELETE FROM
							`ibr_log_changes`
						WHERE
							`id_Person`='".$arrUser['PersonID']."'
						AND
							`id_role`='".$id_role."'
						AND
							`execute_date`>=NOW()");
					if (!$useDelay) {
						if (is_array($arrUser['Abonnements'][$id_role])) {
							$mySET = "";
							$arr = "";
							if ($val['Arbeitsplaetze'] != $arrUser['Abonnements'][$id_role]['Arbeitsplaetze'] && $val['Arbeitsplaetze'] <= $max_value) {
								if ($val['Arbeitsplaetze'] != $arrUser['Abonnements'][$id_role]['Arbeitsplaetze']) {
									$mySET != "" ? $mySET .= ", " : 0;
									$mySET .= "`Arbeitsplaetze`='".$val['Arbeitsplaetze']."'";
									if ($val['Arbeitsplaetze'] == 0) {
										$this->arrUpdateAbonnement['close_roles'][] = $id_role;
										$val['Freigeschaltet'] = USER_ACCOUNT_CLOSED;
										$val['Sperrdatum'] = "NOW()";
									}
									if (!$arrUser['Abonnements'][$id_role]['Arbeitsplaetze']) {
										$val['Freischaltdatum'] = "NOW()";
										$val['Freigeschaltet'] = USER_ACCOUNT_OK;
									}
									$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Arbeitsplaetze", "old_value" => $arrUser['Abonnements'][$id_role]['Arbeitsplaetze'], "new_value" => $val['Arbeitsplaetze']);
									$mail_content = 1;
									$retVal[$id_role]['updates'][] = $arr;
									$this->arrLogChanges[] = $arr;
								}
							} else
	            	$retVal[$id_role]['update_result'] = ABOCHANGE_IBRABO_LOWER;
              if (is_array($val) && array_key_exists("Freigeschaltet", $val) && $val['Freigeschaltet'] != $arrUser['Abonnements'][$id_role]['Freigeschaltet']) {
              	$mySET != "" ? $mySET .= ", " : 0;
              	$val['Freigeschaltet'] == USER_ACCOUNT_OK ? $sFreigeschaltet_new = "Ja" : 0;
              	$val['Freigeschaltet'] == USER_ACCOUNT_CLOSED ? $sFreigeschaltet_new = "Nein" : 0;
              	$val['Freigeschaltet'] == USER_ACCOUNT_NEW ? $sFreigeschaltet_new = "Neu" : 0;
              	if ($sFreigeschaltet_new == "Ja") {
              		!$val['Freischaltdatum'] ? $val['Freischaltdatum'] = "NOW()" : 0;
              	} elseif ($sFreigeschaltet_new == "Nein")  {
									$this->arrUpdateAbonnement['close_roles'][] = $id_role;
              		!$val['Sperrdatum'] ? $val['Sperrdatum'] = "NOW()" : 0;
              	}
              	$mySET .= "`Freigeschaltet`='".$sFreigeschaltet_new."'";
              	$sFreigeschaltet_old = $arrUser['Abonnements'][$id_role]['Freigeschaltet'] == USER_ACCOUNT_OK ? "Ja" : "Nein";
              	$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Freigeschaltet", "old_value" => $sFreigeschaltet_old, "new_value" => $sFreigeschaltet_new);
								$retVal[$id_role]['updates'][] = $arr;
								$retVal[$id_role]['mail_content'] = 1;
								$this->arrLogChanges[] = $arr;
              }
              if (is_array($val) && array_key_exists("Anmeldedatum", $val) && $val['Anmeldedatum'] != $arrUser['Abonnements'][$id_role]['Anmeldedatum']) {
              	$mySET != "" ? $mySET .= ", " : 0;
              	$mySET .= "`Anmeldedatum`='".$val['Anmeldedatum']."'";
              	$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Anmeldedatum", "old_value" => $arrAbo[$id_role]['Anmeldedatum'], "new_value" => $val['Anmeldedatum']);
								$retVal[$id_role]['updates'][] = $arr;
								$this->arrLogChanges[] = $arr;
							}
              if (is_array($val) && array_key_exists("Freischaltdatum", $val) && $val['Freischaltdatum'] != $arrUser['Abonnements'][$id_role]['Freischaltdatum']) {
              	$mySET != "" ? $mySET .= ", " : 0;
              	$mySET .= "`Freischaltdatum`=".$val['Freischaltdatum'];
              	$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Freischaltdatum", "old_value" => $arrUser['Abonnements'][$id_role]['Freischaltdatum'], "new_value" => $val['Freischaltdatum']);
								$retVal[$id_role]['updates'][] = $arr;
								$this->arrLogChanges[] = $arr;
							}
              if (is_array($val) && array_key_exists("Sperrdatum", $val) && $val['Sperrdatum'] != $arrUser['Abonnements'][$id_role]['Sperrdatum']) {
              	$mySET != "" ? $mySET .= ", " : 0;
              	$mySET .= "`Sperrdatum`=".$val['Sperrdatum'];
              	$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Sperrdatum", "old_value" => $arrUser['Abonnements'][$id_role]['Sperrdatum'], "new_value" => $val['Sperrdatum']);
								$retVal[$id_role]['updates'][] = $arr;
								$this->arrLogChanges[] = $arr;
							}
              if (is_array($val) && array_key_exists("Bearbeitet", $val) && $val['Bearbeitet'] != $arrUser['Abonnements'][$id_role]['Bearbeitet']) {
              	$mySET != "" ? $mySET .= ", " : 0;
              	$mySET .= "`Bearbeitet`='".$val['Bearbeitet']."'";
              	$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Bearbeitet", "old_value" => $arrUser['Abonnements'][$id_role]['Bearbeitet'], "new_value" => $val['Bearbeitet']);
								$retVal[$id_role]['updates'][] = $arr;
								$this->arrLogChanges[] = $arr;
							}
              if (is_array($val) && array_key_exists("Bearbeitet_am", $val) && $val['Bearbeitet_am'] != $arrUser['Abonnements'][$id_role]['Bearbeitet_am']) {
              	$mySET != "" ? $mySET .= ", " : 0;
              	$mySET .= "`Bearbeitet_am`='".$val['Bearbeitet_am']."'";
              	$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Bearbeitet_am", "old_value" => $arrUser['Abonnements'][$id_role]['Bearbeitet_am'], "new_value" => $val['Bearbeitet_am']);
								$retVal[$id_role]['updates'][] = $arr;
								$this->arrLogChanges[] = $arr;
							}
              if (is_array($val) && array_key_exists("FreiAbo", $val) && $val['FreiAbo'] != $arrUser['Abonnements'][$id_role]['FreiAbo']) {
              	$mySET != "" ? $mySET .= ", " : 0;
              	$mySET .= "`FreiAbo`='".$val['FreiAbo']."'";
              	$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "FreiAbo", "old_value" => $arrUser['Abonnements'][$id_role]['FreiAbo'], "new_value" => $val['FreiAbo']);
								$retVal[$id_role]['updates'][] = $arr;
								$this->arrLogChanges[] = $arr;
							}
              if ($val['Arbeitsplaetze'] > 0 && $val['Freigeschaltet'] == "Ja") {
	              if ($val['Ablauf_Probezeit'] && ($val['FreiAbo'] == "Nein" || $val['FreiAbo'] != $arrUser['Abonnements'][$id_role]['FreiAbo'])) {
	              	$mySET != "" ? $mySET .= ", " : 0;
	              	$mySET .= "`Ablauf_Probezeit`='".$val['Ablauf_Probezeit']."'";
	              	$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Ablauf_Probezeit", "old_value" => $arrUser['Abonnements'][$id_role]['Ablauf_Probezeit'], "new_value" => $val['Ablauf_Probezeit']);
									$retVal[$id_role]['updates'][] = $arr;
									$this->arrLogChanges[] = $arr;
								} elseif (!$val['Ablauf_Probezeit']) {
	              	if ((!$arrUser['Abonnements'][$id_role]['Ablauf_Probezeit'] || $arrUser['Abonnements'][$id_role]['Ablauf_Probezeit'] == "0000-00-00") && $arrUser['Abonnements'][$id_role]['Anmeldedatum'] > "2006-01-01") {
	              		!$this->_arrRoles[$id_role]['Probezeit'] || $this->_arrRoles[$id_role]['Probezeit'] < 1 ? $this->_arrRoles[$id_role]['Probezeit'] = 14 : 0;
	              		$val['Ablauf_Probezeit'] = date("Y-m-d", strtotime("+".$this->_arrRoles[$id_role]['Probezeit']." days"));
		              	$mySET != "" ? $mySET .= ", " : 0;
		              	$mySET .= "`Ablauf_Probezeit`=DATE_ADD(NOW(), INTERVAL ".$this->_arrRoles[$id_role]['Probezeit']." DAY)";
		              	$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Ablauf_Probezeit", "old_value" => $arrUser['Abonnements'][$id_role]['Ablauf_Probezeit'], "new_value" => $val['Ablauf_Probezeit']);
										$retVal[$id_role]['updates'][] = $arr;
										$this->arrLogChanges[] = $arr;
									}
								}
							}
							if ($mySET) {
                $retVal[$id_role]['update_result'] = $this->sql("
                  UPDATE
                    `Person_Rolle`
                  SET
                  	".$mySET."
                  WHERE
                    `PersonID`='".$arrUser['PersonID']."'
                  AND
                    `RolleID`='".$id_role."'
                ");
              	if ($retVal[$id_role]['update_result']) {
									if (!is_array($this->arrUpdateAbonnement['close_roles']) || (is_array($this->arrUpdateAbonnement['close_roles']) && !in_array($id_role, $this->arrUpdateAbonnement['close_roles']))) {
										$this->arrUpdateAbonnement['update_roles'][] = $id_role;
              			$this->_debugInfo[] = "updateAbonnement -> updated role: ".$id_role;
	              		if ($id_role != ROLES_IBR && $val['Arbeitsplaetze'] > 0)
											$mail['include_abobedingung_zusatzabo'] = true;
										elseif ($id_role == ROLES_IBR && $val['Arbeitsplaetze'] > 0)
											$mail['include_abobedingung_ibr-online'] = true;
              		}
              		$mail_content == 1 ? $retVal[$id_role]['mail_content'] = $mail_content : 0;
                }
            	}
						} else {
							if ($val['Arbeitsplaetze'] > 0) {
								if (!count($arrUser['Abonnements']) || $arrUser['Abonnements'][ROLES_IBR]['Arbeitsplaetze'] == "" || $val['Arbeitsplaetze'] <= $arrUser['Abonnements'][ROLES_IBR]['Arbeitsplaetze'] || !$this->_arrRoles[$id_role]['istBuchbaresAbo']) {
		              $arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Arbeitsplaetze", "old_value" => 0, "new_value" => $val['Arbeitsplaetze']);;
									$retVal[$id_role]['updates'][] = $arr;
		              $this->arrLogChanges[] = $arr;
		              $Freigeschaltet = is_array($val) && array_key_exists('Freigeschaltet', $val) ? $val['Freigeschaltet'] : "Ja";
		            	$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Freigeschaltet", "new_value" => $Freigeschaltet);
									$retVal[$id_role]['updates'][] = $arr;
		              $this->arrLogChanges[] = $arr;
		              $Anmeldedatum = is_array($val) && array_key_exists('Anmeldedatum', $val) ? $val['Anmeldedatum'] : "NOW()";
		            	$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Anmeldedatum", "new_value" => $Anmeldedatum);
									$retVal[$id_role]['updates'][] = $arr;
		              $this->arrLogChanges[] = $arr;
		              $Freischaltdatum = is_array($val) && array_key_exists('Freischaltdatum', $val) ? $val['Freischaltdatum'] : "NOW()";
		            	$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Freischaltdatum", "new_value" => $Freischaltdatum);
									$retVal[$id_role]['updates'][] = $arr;
		              $this->arrLogChanges[] = $arr;
		              if (is_array($val) && array_key_exists("FreiAbo", $val)) {
		              	$FreiAbo = $val['FreiAbo'];
		              	$id_role == ROLES_IBR && $val['FreiAbo'] == "Ja" ? $this->arrUpdateAbonnement['FreiAbo'] = true : 0;
		              } else
		              	$FreiAbo = "Nein";
		            	$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "FreiAbo", "new_value" => $FreiAbo);
									$retVal[$id_role]['updates'][] = $arr;
		              $this->arrLogChanges[] = $arr;
		              if (is_array($val) && array_key_exists("Ablauf_Probezeit", $val)) {
	              		!$this->_arrRoles[$id_role]['Probezeit'] || $this->_arrRoles[$id_role]['Probezeit'] < 1 ? $this->_arrRoles[$id_role]['Probezeit'] = 14 : 0;
		              	$val['Ablauf_Probezeit'] == "" || $val['Ablauf_Probezeit'] == "0000-00-00" ? $val['Ablauf_Probezeit'] = date("Y-m-d", strtotime("+".$this->_arrRoles[$id_role]['Probezeit']." days")) : 0;
		              	$Ablauf_Probezeit = "'".$val['Ablauf_Probezeit']."'";
										$this->arrUpdateAbonnement['Abobedingungen_Laufzeit_Probeabo'] = "Das Probeabo hat eine Laufzeit bis zum ".$func->mysql2date($val['Ablauf_Probezeit']).".";
		            		$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Ablauf_Probezeit", "new_value" => $val['Ablauf_Probezeit']);
		             	} else {
	              		!$this->_arrRoles[$id_role]['Probezeit'] || $this->_arrRoles[$id_role]['Probezeit'] < 1 ? $this->_arrRoles[$id_role]['Probezeit'] = 14 : 0;
		             		$Ablauf_Probezeit = "DATE_ADD(NOW(), INTERVAL ".$this->_arrRoles[$id_role]['Probezeit']." DAY)";
										$this->arrUpdateAbonnement['Abobedingungen_Laufzeit_Probeabo'] = "Das Probeabo hat eine Laufzeit von ".$this->_arrRoles[$id_role]['Probezeit']." Tagen.";
		            		$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "Ablauf_Probezeit", "new_value" => $Ablauf_Probezeit);
		            	}
									$retVal[$id_role]['updates'][] = $arr;
		              $this->arrLogChanges[] = $arr;
		              $retVal[$id_role]['update_result'] = $this->sql("
		                INSERT INTO
		                  `Person_Rolle`
		                	(`PersonID`,
		                	`RolleID`,
		                	`Arbeitsplaetze`,
											`Freigeschaltet`,
											`Anmeldedatum`,
											`Freischaltdatum`,
											`AnmeldeArt`,
											`FreiAbo`,
											`Ablauf_Probezeit`)
		                VALUES
		                  ('".$arrUser['PersonID']."',
		                  '".$id_role."',
		                  '".$val['Arbeitsplaetze']."',
		                  '".$Freigeschaltet."',
		                  ".$Anmeldedatum.",
		                  ".$Freischaltdatum.",
		                  'papier',
		                  '".$FreiAbo."',
		                  ".$Ablauf_Probezeit.")
		              ");
		              if ($retVal[$id_role]['update_result']) {
              			$this->_debugInfo[] = "updateAbonnement -> insert role: ".$id_role;
										$this->arrUpdateAbonnement['insert_roles'][] = $id_role;
										$retVal[$id_role]['mail_content'] = 1;
		              	if ($id_role != ROLES_IBR && $val['Arbeitsplaetze'] > 0) {
											!$mail['include_probeabo_zusatzabo'] ? $mail['include_probeabo_zusatzabo'] = $retVal[$id_role]['offer_as_trial'] : 0;
											if (!$arrUser['Großkunde'])
												$mail['include_abobedingung_zusatzabo'] = true;
											else
												$mail['include_abobedingung_zusatzabo_Großkunde'] = true;
										} elseif ($id_role == ROLES_IBR && $val['Arbeitsplaetze'] > 0) {
											!$mail['include_probeabo_ibr-online'] ? $mail['include_probeabo_ibr-online'] = $retVal[$id_role]['offer_as_trial'] : 0;
											$mail['include_abobedingung_ibr-online'] = true;
										}
									}
								} else
									$retVal[$id_role]['update_result'] = ABOCHANGE_IBRABO_LOWER;
							}
						}
						if ($id_role == ROLES_IBR) {
							if ($val['Arbeitsplaetze'] != $arrUser['Abonnements'][ROLES_IBR]['Arbeitsplaetze']) {
	            	$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "maxAllowedSessions", "old_value" => $arrUser[ROLES_IBR]['Arbeitsplaetze'], "new_value" => $val['Arbeitsplaetze']);
	              $this->arrLogChanges[] = $arr;
	              $retVal[$id_role]['update_result_auth'] = $this->sql("
	                UPDATE
	                  `AuthData`
	                SET
	                  `maxAllowedSessions`='".$val['Arbeitsplaetze']."'
	                WHERE
	                  `PersonID`='".$arrUser['PersonID']."'
	              ");
	              if ($retVal[$id_role]['update_result_auth']) {
              		$this->_debugInfo[] = "updateAbonnement -> updated AuthData";
              		$this->data['maxAllowedSessions'] = $val['Arbeitsplaetze'];
              	}
              	if ($val['Arbeitsplaetze'] < $arrUser['Abonnements'][ROLES_IBR]['Arbeitsplaetze']) {
              		$arrMIDs = $this->getMIDs($arrUser['PersonID'], array("MID" => "DESC"));
              		if (count($arrMIDs) >= $val['Arbeitsplaetze']) {
										global $NeSe, $sql;
										include_once $env->root."include/classes/class.favoriten.inc.php";
              			unset($arr);
              			foreach ($arrMIDs as $key => $val) {
              				if (count($arrMIDs) - count($arr) < $val['Arbeitsplaetze']) {
              					break;
              				}
              				$arr[] = $key;
              				$user_tmp = new User($sql, $func, "");
											$user_tmp->data['Kennung'] = $val['Kennung'];
											$user_tmp->ID = $arrUser['PersonID'];
											$user_tmp->MID = $key;
											$fav = new Favoriten($user_tmp);
              				if ($fav->rootNode) {
              					$node = $NeSe->pickNode($fav->rootNode, true);
              					$NeSe->deleteNode($fav->rootNode);
              				}
              			}
              			if (count($arr)) {
              				$retVal[$id_role]['update_result_MIDs'] = $this->sql("DELETE FROM `Mitbenutzerkennung` WHERE `PersonID`='".$arrUser['PersonID']."' AND `MID` IN ('".implode("', '", $arr)."')");
              				if ($retVal[$id_role]['update_result_MIDs']) {
              					$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "change_value" => "MIDs", "old_value" => implode(", ", $arr), "new_value" => "DELETE");
					              $this->arrLogChanges[] = $arr;
			              		$this->_debugInfo[] = "updateAbonnement -> MIDs deleted";
              				}
              			}
              		}
              	}
	          	}
	          }
          } else {
						$this->_debugInfo[] = "updateAbonnement -> change role with delay (".$useDelay."): ".$id_role;
						if ($val['Arbeitsplaetze'] != $arrUser['Abonnements'][$id_role]['Arbeitsplaetze']) {
							$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "id_role" => $id_role, "change_value" => "Arbeitsplaetze", "old_value" => $arrUser['Abonnements'][$id_role]['Arbeitsplaetze'], "new_value" => $val['Arbeitsplaetze'], "execute_date" => $func->date2mysql($useDelay), "delay" => $useDelay);
							$this->arrLogChanges[] = $arr;
							$retVal[$id_role]['updates'][] = $arr;
							$this->_debugInfo[] = "updateAbonnement -> Arbeitsplaetze/".$arr['old_value']."/".$arr['new_value'];
						}
						if ($val['Freigeschaltet'] != $arrUser['Abonnements'][$id_role]['Freigeschaltet']) {
            	$val['Freigeschaltet'] == USER_ACCOUNT_OK ? $sFreigeschaltet_new = "Ja" : 0;
            	$val['Freigeschaltet'] == USER_ACCOUNT_CLOSED ? $sFreigeschaltet_new = "Nein" : 0;
            	$val['Freigeschaltet'] == USER_ACCOUNT_NEW ? $sFreigeschaltet_new = "Neu" : 0;
            	$sFreigeschaltet_old = $arrUser['Abonnements'][$id_role]['Freigeschaltet'] == USER_ACCOUNT_OK ? "Ja" : "Nein";
							$arr = array("id_role" => $id_role, "id_Person" => $arrUser['PersonID'], "id_role" => $id_role, "change_value" => "Freigeschaltet", "old_value" => $sFreigeschaltet_old, "new_value" => $sFreigeschaltet_new, "execute_date" => $func->date2mysql($useDelay), "delay" => $useDelay);
							$this->arrLogChanges[] = $arr;
							$retVal[$id_role]['updates'][] = $arr;
							$this->_debugInfo[] = "updateAbonnement -> Freigeschaltet/".$arr['old_value']."/".$arr['new_value'];
						}
						$retVal[$id_role]['update_result'] = 1;
						$retVal[$id_role]['mail_content'] = 1;

						if ($val['Arbeitsplaetze'] == 0 || $val["Freigeschaltet"] == USER_ACCOUNT_CLOSED) {
							$this->_debugInfo[] = "updateAbonnement -> close_roles[] = ".$id_role;
							$this->arrUpdateAbonnement['close_roles'][] = $id_role;
						} else {
							$this->arrUpdateAbonnement['insert_roles'][] = $id_role;

							if (is_array($arrUser['Abonnements'][$id_role])) {
            		if ($id_role != ROLES_IBR && $val['Arbeitsplaetze'] > 0) {
									if (!$arrUser['Großkunde'])
										$mail['include_abobedingung_zusatzabo'] = true;
									else
										$mail['include_abobedingung_zusatzabo_Großkunde'] = true;
								} elseif ($id_role == ROLES_IBR && $val['Arbeitsplaetze'] > 0)
									$mail['include_abobedingung_ibr-online'] = true;
							} else {
	            	if ($id_role != ROLES_IBR && $val['Arbeitsplaetze'] > 0) {
									!$mail['include_probeabo_zusatzabo'] ? $mail['include_probeabo_zusatzabo'] = $retVal[$id_role]['offer_as_trial'] : 0;
									if (!$arrUser['Großkunde'])
										$mail['include_abobedingung_zusatzabo'] = true;
									else
										$mail['include_abobedingung_zusatzabo_Großkunde'] = true;
								} elseif ($id_role == ROLES_IBR && $val['Arbeitsplaetze'] > 0) {
									!$mail['include_probeabo_ibr-online'] ? $mail['include_probeabo_ibr-online'] = $retVal[$id_role]['offer_as_trial'] : 0;
									$mail['include_abobedingung_ibr-online'] = true;
								}
							}
						}
          }
          if ($retVal[$id_role]['update_result'] > 0) {
						if ($retVal[$id_role]['mail_content']) {
	            $arr = $retVal[$id_role];
	            $sRole = $arr['sRole'];
	            $sRole = str_pad($sRole, strlen($sRole) + 2, " ", STR_PAD_BOTH);
	            $sAutor = $arr['Autor'];
	            $sAutor != "" ? $sAutor = str_pad($sAutor, strlen($sAutor) + 2, " ", STR_PAD_BOTH) : 0;
	            $arrMailBody[$id_role] = array(
	            	"lRole" => $id_role,
	            	"sRole" => $sRole,
	            	"sAutor" => $sAutor,
	            	"delay" => $useDelay,
	            	"Arbeitsplaetze" => array (
	            		"old_value" => $arrUser['Abonnements'][$id_role]['Arbeitsplaetze'],
	            		"new_value" => $val['Arbeitsplaetze']),
	            	"Freigeschaltet" => array(
	            		"old_value" => $arrUser['Abonnements'][$id_role]['Freigeschaltet'],
	            		"new_value" => $val['Freigeschaltet']),
	            	"offer_as_trial" => $retVal[$id_role]['offer_as_trial'],
	            	"trial_end_date" => $retVal[$id_role]['Ablauf_Probezeit'],
	            	"is_trial" => $retVal[$id_role]['is_trial']
	            );
	            strlen($sRole) > $lRoleStringLength ? $lRoleStringLength = strlen($sRole) : 0;
	            strlen($sAutor) > $lRoleStringLength ? $lRoleStringLength = strlen($sAutor) : 0;
          	}
          }
				}
				$this->_debugInfo[] = "updateAbonnement -> done checking roles";
				if (is_array($arrDeleteDelay)) {
					$myWHERE = "";
					foreach ($arrDeleteDelay as $id_role => $val) {
						$myWHERE != "" ? $myWHERE .= " OR " : 0;
						$myWHERE .= "`id`='".$val."'";
					}
					if ($myWHERE) {
						$this->sql("DELETE FROM `ibr_log_changes`WHERE ".$myWHERE);
					}
				}
				if ($bChangesMade) {
					$retVal['changes_made'] = true;
					if (is_array($arrSetBearbeitetJa)) {
						$this->sql("UPDATE `Person_Rolle` SET `Bearbeitet`='Ja', `Bearbeitet_am`=NOW() WHERE `Bearbeitet`='Nein' AND `PersonID` IN (".implode(", ", $arrSetBearbeitetJa).")");
					}
					$this->logChanges($this->admin);
					if (is_array($arrMailBody)) {
						$retVal['mail'] = $this->updateAbonnement_createEMail($arrMailBody, $arrUser, $mail);
					} else
					  $this->_debugInfo[] = "updateAbonnement -> !is_array(MailBody)";
				} else {
					$retVal = false;
					$this->_debugInfo[] = "updateAbonnement -> !bChangesMade";
				}
			} else
				$this->_debugInfo[] = "updateAbonnement -> !is_array(arrUser)";
		} else
			$this->_debugInfo[] = "updateAbonnement -> !is_array(arrAbo)";
		return $retVal;
	}
	// }}}

	// {{{ updateAbonnement_createEMail
	/**
	 * erstellt den E-Mail Text für Änderungen an Abos
	 *
	 * @param array   $arrAbo     Array mit den Abo-IDs als Schlüssel
	 *															Variante a) und der neuen Anzahl an Abos als Wert << DEFAULT
	 *															Variante b) und einem Array der Form
	 *																						"Arbeitsplaetze" => 1, <<<<< MUSS-Angabe
	 *																						"Freigeschaltet" => "Ja",
	 *																						"Anmeldedatum" => "YYYY-MM-DDD",
	 *																						"Freischaltdatum" => "YYYY-MM-DD"
	 *														Sollte der Array Variante a) sein, wird er in Variante b) umgeformt
	 *
   * @return int/array  int wenn ein Fehler aufgetreten ist oder Array mit den Abo-IDs als Schlüssel und dem Ergebnis der Änderung als int
	 */
  function updateAbonnement_createEMail($arrMailBody = array(), $arrUser = array(), $mail = array())
  {
  	global $env, $func, $clsDienst;

		$this->_debugInfo[] = "function updateAbonnement_createEMail";

		$mail['recipient'] = $arrUser['Email'];
		if (!count($this->dataExt))
			$this->getUserDataExt(false, $arrUser['Kennung'], $arrUser['PersonID']);

		$bForLetter = true;
		$mail['salutation'] = $func->createSalutation($this->dataExt, $bForLetter)."\n";
		$mail['customer'] = $mail['salutation'];
    $mail['customer'] .= "\n";
  	if (!is_array($this->arrUpdateAbonnement['insert_roles'])) { // nur ein Update (keine neuen Abos)
			$this->arrUpdateAbonnement['exclude_all_additional_texts'] = true;
  		if (is_array($this->arrUpdateAbonnement['update_roles'])) {
	  		if (in_array(ROLES_IBR, $this->arrUpdateAbonnement['update_roles'])) { // ibr-online wurde (mit) erweitert
	  			if (!$this->arrUpdateAbonnement['doublet']) {
		  			$mail['subject'] = $clsDienst->data['abo.short_name'].": Änderungen an Ihrem Abonnement";
		  			$mail['customer'] .= "vielen Dank für die Erweiterung Ihres Abonnements auf ".$clsDienst->data['abo.short_name']."!\n";
		  			$mail['customer'] .= "Hiermit bestätigen wir Ihnen Ihre Änderungen wie folgt:\n";
		  		} else {
  					$mail['subject'] = $clsDienst->data['abo.short_name'].": Ihr kostenloses Probeabo";
	    			$mail['customer'] .= "vielen Dank für Ihre Anmeldung zu einem Probeabonnement von ".$clsDienst->data['abo.short_name'].".\n";
	    			//$this->arrUpdateAbonnement['trial'] = true;
	    			//$this->arrUpdateAbonnement['exclude_details_4_customer'] = true;
	    			//$this->arrUpdateAbonnement['exclude_all_additional_texts'] = true;
		  		}
		  	} else {
	  			$mail['subject'] = $clsDienst->data['abo.short_name'].": Änderungen an Ihrem Abonnement";
	  			$mail['customer'] .= "vielen Dank für die Erweiterung ";
	  			$mail['customer'] .= count($this->arrUpdateAbonnement['update_roles']) == 1 ? "Ihres" : "Ihrer";
	  			$mail['customer'] .= " Zusatzabonnements auf ".$clsDienst->data['abo.short_name'].".\n";
	  			$mail['customer'] .= "Hiermit bestätigen wir Ihnen die durchgeführten Erweiterungen wie folgt:\n";
	  		}
	  	} elseif (is_array($this->arrUpdateAbonnement['close_roles'])) {
	  		if (in_array(ROLES_IBR, $this->arrUpdateAbonnement['close_roles'])) {
					if ($arrMailBody[ROLES_IBR]['is_trial']) {
	  				$mail['subject'] = $clsDienst->data['abo.short_name'].": Kündigung Ihres Probeabonnements";
						$mail['customer'] .= "nochmals herzlichen Dank für Ihre Anmeldung zu einem kostenlosen Probe-Abo von ".$clsDienst->data['abo.short_name'].".\n\n";
						$mail['customer'] .= "Nach Ablauf der Probezeit möchten Sie das Abo jedoch nicht fortsetzen.\n\n";
	    			$this->arrUpdateAbonnement['close_account'] = true;
					} else {
	  				$mail['subject'] = $clsDienst->data['abo.short_name'].": Kündigung Ihres Abonnements";
						$mail['customer'] .= "nochmals herzlichen Dank für Ihre Anmeldung bei ".$clsDienst->data['abo.short_name'].".\n\n";
						$mail['customer'] .= "Sie möchten Ihr Abonnement jedoch nicht mehr fortsetzen.\n\n";
	    			$this->arrUpdateAbonnement['close_account'] = true;
					}
					$mail['customer'] .= "Wir bestätigen hiermit Ihre Kündigung wie folgt:\n";
	  		} else {
					$mail['subject'] = $clsDienst->data['abo.short_name'].": Änderungen an Ihrem Abonnement";
    			$mail['customer'] .= "vielen Dank für Ihre Anmeldung zu unserem Online-Dienst ".$clsDienst->data['abo.short_name']."!\n";
    			$mail['customer'] .= "Hiermit bestätigen wir Ihnen Ihre Änderungen wie folgt:\n";
	  		}
	  	}
  	} else { // neue Abos
  		if (!is_array($this->arrUpdateAbonnement['update_roles'])) { // nur neue Abos
    		if (in_array(ROLES_IBR, $this->arrUpdateAbonnement['insert_roles'])) { // ibr-online wurde (mit) bestellt
					if (!$this->arrUpdateAbonnement['doublet']) {
  					if (!$this->arrUpdateAbonnement['FreiAbo']) {
	  					$mail['subject'] = $clsDienst->data['abo.short_name'].": Ihr kostenloses Probeabo";
		    			$mail['customer'] .= "vielen Dank für Ihre Anmeldung zu unserem Online-Dienst ".$clsDienst->data['abo.short_name']."!\n";
		    			$mail['customer'] .= "Hiermit bestätigen wir Ihnen Ihre Anmeldung wie folgt:\n";
		    			$this->arrUpdateAbonnement['trial'] = true;
	    			} else {
	  					$mail['subject'] = $clsDienst->data['abo.short_name']." Freiabo";
		    			$mail['customer'] .= "wir haben für Sie ein Freiabo zu unserem Online-Dienst ".$clsDienst->data['abo.short_name']." mit folgenden Angaben angelegt:\n";
	    			}
	    		} else {
  					$mail['subject'] = $clsDienst->data['abo.short_name'].": Ihr kostenloses Probeabo";
	    			$mail['customer'] .= "vielen Dank für Ihre Anmeldung zu einem Probeabonnement von ".$clsDienst->data['abo.short_name'].".\n";
	    			//$this->arrUpdateAbonnement['trial'] = true;
	    			//$this->arrUpdateAbonnement['exclude_details_4_customer'] = true;
	    			//$this->arrUpdateAbonnement['exclude_all_additional_texts'] = true;
    			}
    		} else {
					$mail['subject'] = $clsDienst->data['abo.short_name'].": Änderungen an Ihrem Abonnement";
    			$mail['customer'] .= "vielen Dank für die Bestellung ";
    			$mail['customer'] .= count($this->arrUpdateAbonnement['insert_roles']) == 1 ? "eines" : "mehrerer";
    			$mail['customer'] .= " Zusatzabonnements auf ".$clsDienst->data['abo.short_name']."!\n";
    			$mail['customer'] .= "Hiermit bestätigen wir Ihnen Ihre Anmeldung wie folgt:\n";
    		}
    	} else { // auch Updates bei alten Abos
				$mail['subject'] = $clsDienst->data['abo.short_name'].": Änderungen an Ihrem Abonnement";
  			$mail['customer'] .= "vielen Dank für die Erweiterung Ihres Abonnements auf ".$clsDienst->data['abo.short_name']."!\n";
  			$mail['customer'] .= "Hiermit bestätigen wir Ihnen Ihre Anmeldung wie folgt:\n";
    	}
  	}

		if (!$this->arrUpdateAbonnement['new_user']) {
	    $mail['admin'] .= "Hallo id Verlag!\n";
	    $mail['admin'] .= "\n";
	  	$mail['admin'] .= "es gibt Änderungen an folgendem Abonnement:\n";
	    $mail['admin'] .= "\n";
	    $mail['admin'] .= str_pad("", 72, "-")."\n";
	    $mail['admin'] .= "Kd.Nr.(Thull): ".$this->dataExt['KundennummerThull']."\n";
	    $mail['admin'] .= "PersonID     : ".$this->dataExt['PersonID']."\n";
	  }
	  if (!$this->arrUpdateAbonnement['new_user'] || $this->arrUpdateAbonnement['FreiAbo']) {
	  	$sRecipient = $this->arrUpdateAbonnement['FreiAbo'] ? "customer" : "admin";
			if ($this->arrUpdateAbonnement['FreiAbo']) {
	    	$mail['include_probeabo_ibr-online'] = false;
	    	$mail['include_abobedingung_ibr-online'] = false;
	    	$mail['include_probeabo_zusatzabo'] = false;
	    	$mail['include_abobedingung_zusatzabo'] = false;
	    	$mail['include_abobedingung_zusatzabo_Großkunde'] = false;
	    	$mail[$sRecipient] .= "\n";
	    	$mail[$sRecipient] .= str_pad("", 72, "-")."\n";
	    	$mail[$sRecipient] .= "\n";
			}
	    $mail[$sRecipient] .= "Name         : ".$this->dataExt['Name']."\n";
	    $mail[$sRecipient] .= "Vorname      : ".$this->dataExt['Vorname']."\n";
	    $mail[$sRecipient] .= "Firma        : ".$this->dataExt['Firma']."\n";
	    $mail[$sRecipient] .= "Strasse      : ".$this->dataExt['Strasse']."\n";
	    $mail[$sRecipient] .= "Hausnummer   : ".$this->dataExt['Hausnummer']."\n";
	    $mail[$sRecipient] .= "PLZ          : ".$this->dataExt['PLZ']."\n";
	    $mail[$sRecipient] .= "Ort          : ".$this->dataExt['Ort']."\n";
	    $mail[$sRecipient] .= "Telefon      : ".$this->dataExt['Telefon']."\n";
	    $mail[$sRecipient] .= "Fax          : ".$this->dataExt['Fax']."\n";
	    $mail[$sRecipient] .= "E-Mail       : ".$this->dataExt['Email']."\n";
	    $mail['all'] .= "\n";
		}
		if (!$this->arrUpdateAbonnement['new_user']) {
	    $mail['all'] .= str_pad("", 72, "-")."\n";
			foreach ($arrMailBody as $val) {
				$sRoleBody .= "\n";
	      $sRoleBody .= trim($val['sRole'])."\n\n";
	      !$val['delay'] ? $val['delay'] = date("d.m.Y") : 0;
	      if ($val['Arbeitsplaetze']['new_value'] != $val['Arbeitsplaetze']['old_value']) {
					!$val['Arbeitsplaetze']['new_value'] ? $val['Arbeitsplaetze']['new_value'] = 0 : 0;
					!$val['Arbeitsplaetze']['old_value'] ? $val['Arbeitsplaetze']['old_value'] = 0 : 0;
					if ($val['Arbeitsplaetze']['new_value'] == 0) {
						$sRoleBody .= $val['is_trial'] ? "Probeabonnement" : "Abonnement";
						$sRoleBody .= " gekündigt";
					} else {
						$sRoleBody .= "Anzahl Zugänge: ".$val['Arbeitsplaetze']['new_value'];
						$val['Arbeitsplaetze']['old_value'] > 0 ? $sRoleBody .= " (bisher: ".$val['Arbeitsplaetze']['old_value'].")" : 0;
						if ($val['Arbeitsplaetze']['old_value'] == 0 && $val['offer_as_trial']) {
						  $val['trial_end_date'] ? $sRoleBody .= " (Probeabonnement bis zum: ".$func->mysql2date($val['trial_end_date']).")" : 0;
						}
					}
				} elseif ($val['Freigeschaltet']['new_value'] != $val['Freigeschaltet']['old_value']) {
					$sRoleBody .= "Zugang ";
					$sRoleBody .= $val['Freigeschaltet']['new_value'] != USER_ACCOUNT_OK ? "sperren" : "freischalten";
				}
				$sRoleBody .= "\n";
				$sRoleBody .= "zum ".$val['delay']."\n";
				$sRoleBody .= "\n";
				$sRoleBody .= str_pad("", 72, "-")."\n";
			}
	    $mail['all'] .= $sRoleBody;
	    $mail['all'] .= "\n";
	    $mail['admin'] .= $mail['all'];
	    if (!$this->arrUpdateAbonnement['exclude_details_4_customer'])
	    	$mail['customer'] .= $mail['all'];
    } else {
			$mail['admin'] .= "\n".$this->arrUpdateAbonnement['admin_body']."\n";
    	if (!$this->arrUpdateAbonnement['exclude_details_4_customer'])
				$mail['customer'] .= "\n".$this->arrUpdateAbonnement['customer_body']."\n";
    }
  	if (!$this->arrUpdateAbonnement['admin_body_is_html'])
    	$mail['admin'] .= "Zeitpunkt der Änderung: ".date("d.m.Y, H:i:s")." Uhr\n";
    else
    	$mail['admin'] .= "Zeitpunkt der Änderung: ".date("d.m.Y, H:i:s")." Uhr<br />\n";
    if (!$this->arrUpdateAbonnement['admin_body_is_html']) {
    	$mail['admin'] .= "\n";
    	$mail['admin'] .= "\n";
    	$mail['admin'] .= "Mit freundlichen Grüßen,\n";
    	$mail['admin'] .= "\n";
    	$mail['admin'] .= "Ihr ".$clsDienst->data['abo.short_name']."-Server\n";
		} else {
    	$mail['admin'] .= "<br />\n";
    	$mail['admin'] .= "<br />\n";
    	$mail['admin'] .= "Mit freundlichen Grüßen,<br />\n";
    	$mail['admin'] .= "<br />\n";
    	$mail['admin'] .= "Ihr ".$clsDienst->data['abo.short_name']."-Server<br />\n";
		}
		if (!$this->arrUpdateAbonnement['new_user']) {
			if ($this->dataExt['Firma']) {
				$mail['customer'] .= "\nAbonnent: ".$this->dataExt['Firma'];
				$this->dataExt['Ort'] ? $mail['customer'] .= " (".$this->dataExt['Ort'].")" : 0;
				$mail['customer'] .= "\n\n";
			}
		}
		if ($this->arrUpdateAbonnement['has_roles']) {
			if (!$this->arrUpdateAbonnement['close_account']) {
				if (!$this->arrUpdateAbonnement['doublet']) {
					if (!$this->arrUpdateAbonnement['delay']) {
						//if (is_array($this->arrUpdateAbonnement['update_roles']) || is_array($this->arrUpdateAbonnement['insert_roles'])) {
						if (is_array($this->arrUpdateAbonnement['insert_roles'])) {
							$mail['customer'] .= "Ihr Zugang ist bereits freigeschaltet; Sie können sich mit Ihren Zugangsdaten\n";
							if ((is_array($this->arrUpdateAbonnement['insert_roles']) && in_array(ROLES_IBR, $this->arrUpdateAbonnement['insert_roles'])) || $this->arrUpdateAbonnement['FreiAbo']) {
								if ($this->data['from_form']['Kennung'] && $this->data['from_form']['Passwort'])
									$mail['customer'] .= "\nBenutzerkennung: ".$this->data['from_form']['Kennung']."\n       Passwort:	".$this->data['from_form']['Passwort']."\n\n";
							}
							$mail['customer'] .= "unter ".$env->root_web." einloggen und unsere Online-Dienste nutzen.\n\n";
						}
					} else {
						$mail['customer'] .= "Ihr Zugang wird zum ".$this->arrUpdateAbonnement['delay']." freigeschaltet.\n\n";
					}
				} else {
					if (!$this->arrUpdateAbonnement['new_user']) {
						if (is_array($this->arrUpdateAbonnement['update_roles']) || is_array($this->arrUpdateAbonnement['insert_roles'])) {
							$mail['customer'] .= "Ihr Zugang ist nun freigeschaltet. Sie können Sich von nun an mit der ";
							$mail['customer'] .= "von Ihnen gewählten Benutzerkennung (".$arrUser['Kennung'].") und dem von Ihnen gewählten Passwort ";
							$mail['customer'] .= "unter ".$env->root_web." einloggen und unser Online-Angebot nutzen.\n";
						}
					} else {
						$this->arrUpdateAbonnement['trial_closed'] = true;
						$mail['customer'] .= "Ihr Zugang wird schnellstmöglich freigeschaltet; Sie können sich\n";
						$mail['customer'] .= "dann mit den von Ihnen gewählten Zugangsdaten unter\n";
						$mail['customer'] .= $env->root_web." einloggen und unsere Online-Dienste nutzen.\n";
						$mail['customer'] .= "Die Freischaltung wird Ihnen mit einer separaten E-Mail bestätigt.\n";
					}
				}
				$mail['customer'] .= "\n".strip_tags($func->echoHotline("", ""))."\n\n";
			} else {
				$mail['customer'] .= "Sollten Sie sich zu einem späteren Zeitpunkt wieder für ein Abonnement\n";
				$mail['customer'] .= "interessieren, stehen wir Ihnen gerne zur Verfügung.\n\n";
				$mail['customer'] .= "Bitte melden Sie sich in diesem Fall telefonisch (".$func->arrHotline['Böttger']['phone'].")\n";
				$mail['customer'] .= "oder per E-Mail (".$func->arrHotline['Böttger']['email'].") bei ".$func->arrHotline['Böttger']['name']." von unserer Abo-Abteilung.\n\n";
			}
		} else {
			$mail['customer'] .= "Ihr Zugang ist bereits freigeschaltet; Sie können sich mit Ihren Zugangsdaten\n";
			if ((is_array($this->arrUpdateAbonnement['insert_roles']) && in_array(ROLES_IBR, $this->arrUpdateAbonnement['insert_roles'])) || $this->arrUpdateAbonnement['FreiAbo']) {
				if ($this->data['from_form']['Kennung'] && $this->data['from_form']['Passwort'])
					$mail['customer'] .= "\nBenutzerkennung: ".$this->data['from_form']['Kennung']."\n       Passwort: ".$this->data['from_form']['Passwort']."\n\n";
			}
			$mail['customer'] .= "unter ".$env->root_web." einloggen und unsere Online-Dienste nutzen.\n\n";
			$mail['customer'] .= "\n".strip_tags($func->echoHotline("", ""))."\n\n";
		}

		if ($this->arrUpdateAbonnement['trial']) {
			if (!$this->arrUpdateAbonnement['trial_closed']) {
			  if (!$this->arrUpdateAbonnement['trial_text'])
				  $mail['customer'] .= "Falls wir von Ihnen innerhalb der nächsten ".$this->_arrRoles[ROLES_IBR]['Probezeit']." Tage keine Kündigung erhalten, setzt sich das Probeabo automatisch als reguläres Abonnement fort.\n\n";
			  else
				  $mail['customer'] .= $this->arrUpdateAbonnement['trial_text'];
			  $mail['customer'] .= "Wir wünschen Ihnen bei der Nutzung von ".$clsDienst->data['abo.short_name']." viel Erfolg!\n\n";
			}
		} else {
			if (!$this->arrUpdateAbonnement['close_account'])
				$mail['customer'] .= "Wir wünschen Ihnen weiterhin viel Erfolg bei der Arbeit mit ".$clsDienst->data['abo.short_name']."!\n\n";
		}
		$mail['customer'] .= $func->echo_email_signature("Böttger")."\n\n";

		!$this->arrUpdateAbonnement['Abobedingungen_Laufzeit_Probeabo'] ? $this->arrUpdateAbonnement['Abobedingungen_Laufzeit_Probeabo'] = "Das Probeabo hat eine Laufzeit von ".$this->_arrRoles[ROLES_IBR]['Probezeit']." Tagen." : 0;
		$mail['text_probeabo_ibr-online'] = "
-----------------------------------------------------------------

Abonnementbedingungen für das kostenlose Probeabo ".$clsDienst->data['abo.short_name'].":

1. Das Probeabo bietet Ihnen kostenlosen und unbeschränkten
   Zugang zu allen Leistungen von ".$clsDienst->data['abo.short_name'].", ausgenommen Inhalten,
   die in Zusammenarbeit mit anderen Verlagen angeboten werden und
   von Ihnen gesondert bestellt werden.

2. ".$this->arrUpdateAbonnement['Abobedingungen_Laufzeit_Probeabo']."

3. Es setzt sich, wenn es nicht innerhalb der Probezeit gekündigt wird,
   automatisch als reguläres Abonnement (siehe unten) fort.

4. Die Kündigung kann per Email, Telefax oder Brief erfolgen.

5. Im übrigen gelten die Allgemeinen Geschäftsbedingungen
   (".$env->root_web."/ID-Verlag/agb.php)

";
		if (is_object($Abopreise)) {
			$lPreisAbonnent = $Abopreise->arrPreise['Abonnent']['IBR-Abonnenten'];
			$lPreisNichtAbonnent = $Abopreise->arrPreise['Abonnent']['Nicht-Abonnenten'];
		} else {
			$lPreisAbonnent = 189;
			$lPreisNichtAbonnent = 189;
		}
		$lPreisAbonnent = 189; // Provisorisch, OG
		$mail['text_abobedingung_ibr-online'] = "
-----------------------------------------------------------------

Abonnementbedingungen für das reguläre Abo ".$clsDienst->data['abo.short_name']."##Probezeit##:


1. Das Abonnement hat eine Laufzeit von 6 Monaten und verlängert sich
   jeweils um die gleiche Zeit, sofern es nicht mit einer Frist von 4
   Wochen zum Ende der Laufzeit gekündigt wird (die Kündigung kann per
   Email, Telefax oder Brief erfolgen).

2. Der Abo-Preis für einen Arbeitsplatz beträgt halbjährlich ".$lPreisAbonnent." Euro
   zzgl. ges. MwSt., z.Zt. ".$env->MwSt().".

3. Sollen mehrere Kollegen innerhalb eines lokalen Netzwerkes parallel
   mit ".$clsDienst->data['abo.short_name']." arbeiten können, so setzt dies die Freischaltung mehrerer
   Arbeitsplätze voraus. Sie können diese mit Rabatten gemäß der unter
   ".$env->root_web."/ID-Verlag/impressum-online.php abrufbaren
   Preisstaffel bestellen.

4. Mitglieder unserer Kooperationspartner (eine Auflistung findet sich
   unter ".$env->root_web."/ID-Verlag/kooperationen.php)
   erhalten 12 Euro Nachlass pro Halbjahr.

5. Der Abo-Preis wird jeweils zum Beginn der Laufzeit in Rechnung
   gestellt.

6. Im übrigen gelten die Allgemeinen Geschäftsbedingungen
   (".$env->root_web."/ID-Verlag/agb.php)

";

		$mail['text_probeabo_zusatzabo'] = "
-----------------------------------------------------------------
Bedingungen für das kostenlose Probeabo eines Zusatzmoduls:

1. Das Probeabo hat eine Laufzeit von 7 Tagen. Falls das ".$clsDienst->data['abo.short_name']."-
   Grundabo zuvor endet, endet auch das Probeabo für das Zusatzmodul.

2. Es setzt sich automatisch als reguläres Halbjahresabo (s.u.) fort,
   wenn es nicht innerhalb der Probezeit gekündigt wird.

3. Die Kündigung kann per Email, Telefax oder Brief erfolgen.
   Die genauen Kontaktdaten stehen unter
   ".$env->root_web."/ID-Verlag/kontakt.php bereit.

4. Im übrigen gelten die Allgemeinen Geschäftsbedingungen
   (".$env->root_web."/ID-Verlag/agb.php)

";
		$mail['text_abobedingung_zusatzabo'] = "
-----------------------------------------------------------------
Abonnementbedingungen für Zusatzmodule##Probezeit##:

1. Das Zusatzabonnement setzt ein Abonnement von ".$clsDienst->data['abo.short_name']." voraus.

2. Das Abonnement hat die gleiche Laufzeit wie das ".$clsDienst->data['abo.short_name']."-
   Abonnement, auf dem es aufsetzt. Es kann zusammen mit diesem oder
   auch gesondert (mit einer Frist von 4 Wochen zum Ende der
   Laufzeit) gekündigt werden.

3. Sollen mehrere Kollegen innerhalb eines lokalen Netzwerkes
   parallel mit diesem Abonnement arbeiten können, so setzt dies die
   Freischaltung mehrerer Arbeitsplätze voraus. Der Abopreis für
   jeden zusätzlichen Arbeitsplatz beträgt 20% des Grundpreises.

4. Die Anzahl der Arbeitsplätze kann für das ".$clsDienst->data['abo.short_name']."-Abo und das
   Zusatzabo separat festgelegt werden.

5. Der Abo-Preis wird jeweils zum Beginn der Laufzeit in Rechnung
   gestellt.

6. Nach Ablauf der Probezeit erhalten Sie eine Rechnung über Ihr
   neues Zusatzabonnement für die Zeit bis zum Ablauf des
   derzeitigen 6-Monats-Zeitraumes Ihres ".$clsDienst->data['abo.short_name']."-Grundabonnements.

7. Sonderkonditionen für den Bezug von ".$clsDienst->data['abo.short_name']." - z.B. für
   ".$clsDienst->data['abo.short_name']."-Kooperationspartner - gelten nicht für das Zusatzabo.

8. Es gelten im übrigen die Allgemeinen Geschäftsbedingungen des
   Grundabonnements ".$clsDienst->data['abo.short_name'].".

";
		$mail['text_abobedingung_zusatzabo_Großkunde'] = "
-----------------------------------------------------------------
Abonnementbedingungen für Zusatzmodule##Probezeit##:

1. Das Zusatzabonnement setzt ein Abonnement von ".$clsDienst->data['abo.short_name']." voraus.

2. Das Abonnement hat die gleiche Laufzeit wie das ".$clsDienst->data['abo.short_name']."-
   Abonnement, auf dem es aufsetzt. Es kann zusammen mit diesem oder
   auch gesondert (mit einer Frist von 4 Wochen zum Ende der
   Laufzeit) gekündigt werden.

3. Sollen mehrere Kollegen innerhalb eines lokalen Netzwerkes
   parallel mit diesem Abonnement arbeiten können, so setzt dies die
   Freischaltung mehrerer Arbeitsplätze voraus.

4. Die Anzahl der Arbeitsplätze kann für das ".$clsDienst->data['abo.short_name']."-Abo und das
   Zusatzabo separat festgelegt werden.

5. Der Abo-Preis wird jeweils zum Beginn der Laufzeit in Rechnung
   gestellt.

6. Nach Ablauf der Probezeit erhalten Sie eine Rechnung über Ihr
   neues Zusatzabonnement für die Zeit bis zum Ablauf des
   derzeitigen 6-Monats-Zeitraumes Ihres ".$clsDienst->data['abo.short_name']."-Grundabonnements.

7. Sonderkonditionen für den Bezug von ".$clsDienst->data['abo.short_name']." - z.B. für
   ".$clsDienst->data['abo.short_name']."-Kooperationspartner - gelten nicht für das Zusatzabo.

8. Es gelten im übrigen die Allgemeinen Geschäftsbedingungen des
   Grundabonnements ".$clsDienst->data['abo.short_name'].".

";
		if (!$this->arrUpdateAbonnement['exclude_all_additional_texts']) {
			if ($mail['include_probeabo_ibr-online']) {
				$mail['customer'] .= $mail['text_probeabo_ibr-online'];
			}
			if ($mail['include_abobedingung_ibr-online']) {
				if ($mail['include_probeabo_ibr-online'])
					$mail['text_abobedingung_ibr-online'] = str_replace("##Probezeit##", "\n(nach Ablauf der Probezeit)", $mail['text_abobedingung_ibr-online']);
				else
					$mail['text_abobedingung_ibr-online'] = str_replace("##Probezeit##", "", $mail['text_abobedingung_ibr-online']);
				$mail['customer'] .= $mail['text_abobedingung_ibr-online'];
			}
			if ($mail['include_probeabo_zusatzabo']) {
				$mail['customer'] .= $mail['text_probeabo_zusatzabo'];
			}
			if ($mail['include_abobedingung_zusatzabo']) {
				if ($mail['include_probeabo_zusatzabo'])
					$mail['text_abobedingung_zusatzabo'] = str_replace("##Probezeit##", " (nach Ablauf der Probezeit)", $mail['text_abobedingung_zusatzabo']);
				else
					$mail['text_abobedingung_zusatzabo'] = str_replace("##Probezeit##", "", $mail['text_abobedingung_zusatzabo']);
				$mail['customer'] .= $mail['text_abobedingung_zusatzabo'];
			}
			if ($mail['include_abobedingung_zusatzabo_Großkunde']) {
				if ($mail['include_probeabo_zusatzabo'])
					$mail['text_abobedingung_zusatzabo_Großkunde'] = str_replace("##Probezeit##", " (nach Ablauf der Probezeit)", $mail['text_abobedingung_zusatzabo']);
				else
					$mail['text_abobedingung_zusatzabo_Großkunde'] = str_replace("##Probezeit##", "", $mail['text_abobedingung_zusatzabo']);
				$mail['customer'] .= $mail['text_abobedingung_zusatzabo_Großkunde'];
			}
		}
		return $mail;
	}
	// }}}

	// {{{ changeMaxAllowedSessions
	/**
	 * ändert die Anzahl von Abonnements
	 *
	 * @param string  $sUserName  Kennung des Benutzers der erweitern möchte
	 * @param array   $arrAbo     Array mit den Abo-IDs als Schlüssel
	 *															Variante a) und der neuen Anzahl an Abos als Wert << DEFAULT
	 *															Variante b) und einem Array der Form
	 *																						"Arbeitsplaetze" => 1, <<<<< MUSS-Angabe
	 *																						"Freigeschaltet" => "Ja",
	 *																						"Anmeldedatum" => "YYYY-MM-DDD",
	 *																						"Freischaltdatum" => "YYYY-MM-DD"
	 *														Sollte der Array Variante a) sein, wird er in Variante b) umgeformt
	 *
   * @return int/array  int wenn ein Fehler aufgetreten ist oder Array mit den Abo-IDs als Schlüssel und dem Ergebnis der Änderung als int
	 */
  function changeMaxAllowedSessions($sUserName, $sPassword, $arrAbo, $bChangeAsAdmin = false)
  {
  	global $func, $clsDienst;
		/*
		$this->_debugInfo[] = "function changeMaxAllowedSessions";
		$this->_debugInfo[] = "changeMaxAllowedSessions -> !deprecated! (called from Script: ".$_SERVER['PHP_SELF'];
		$this->_debugInfo[] = "changeMaxAllowedSessions -> redirecting parameters to function updateAbonnement";
		$this->_debugging_next = true;
		$this->logDB($this->_debugInfo[count($this->_debugInfo)-3]."\n".$this->_debugInfo[count($this->_debugInfo)-2]."\n".$this->_debugInfo[count($this->_debugInfo)-1]);
		*/
		
    $retVal = array();
    $result = $this->getUserData($sUserName);
    if (is_array($result)) {
      if ($this->_comparePassword($sPassword, $result['Passwort'])) {
				$arr = $this->updateAbonnement($sUserName, $arrAbo);
				if (is_array($arr)) {
					foreach ($arr as $id_role => $val) {
						if (is_int($id_role)) {
							if (is_array($val) && array_key_exists("update_result", $val))
								$arr[$id_role]['result'] = $val['update_result'];
      			}
      		}
					mail($func->arrHotline['Abo']['email'], $clsDienst->data['abo.short_name'].": Änderungen an einem Abonnement", $arr['mail']['admin'], "From: ".$func->arrHotline['Abo']['email']."\nBCC: g@rcia.de\n");
					mail($arr['mail']['recipient'], $clsDienst->data['abo.short_name'].": Änderungen an Ihrem Abonnement", $arr['mail']['customer'], "From: ".$func->arrHotline['Abo']['email']."\nBCC: g@rcia.de\n");
      		$retVal = $arr;
      	}
      } else {
        $retVal = USER_INVALID_PASSWORD;
        $this->_checkPass = false;
      }
    } else
      $retVal = USER_USERNAME_UNKNOWN;
  	return $retVal;
  }
	// }}}

	// {{{ getMIDs
	/**
	 * Liefert einen Array mit allen bekannten Mitbenutzern zu einer Kennung/PersonID
	 *
	 * @param int/string  $mixedFetch   PersonID oder Kennung
	 * @param string      $aOrder       Array mit den Schlüsseln als Spalten und den Werten als ASC/DESC
	 * @param bool        $mixedIndex   für Indizierung des Array
	 *
	 * @return array/false  Array mit den Mitbenutzerdaten falls vorhanden, sonst false
	 */
	function getMIDs($mixedFetch, $aOrder = array(), $mixedIndex = "MID")
	{
		global $func;
		
		$this->_debugInfo[] = "function getMIDs";
  	$sCol = !is_numeric($mixedFetch) ? "Kennung" : "PersonID";
    is_array($aOrder) && count($aOrder) ? $sOrder = "ORDER BY ".$func->implode_assoc($aOrder, " ", ", ", "`", "") : 0;
    $result = $this->sql("
      SELECT
        m.*,
        mr.id_role
      FROM
        `AuthData` AS a
      LEFT JOIN
        `Mitbenutzerkennung` AS m
      ON
        m.`PersonID` = a.`PersonID`
      LEFT JOIN
      	`Mitbenutzer_Rollen` AS mr
      ON
      	mr.`MID`=m.`MID`
      WHERE
        a.`".$sCol."`='".$mixedFetch."'
      AND
        m.`MID` <> 0
      ".$sOrder, $mixedIndex);
	  if (is_array($result)) {
			$retVal = array();
			foreach ($result as $val) {
				$key = is_array($val) && array_key_exists(strval($mixedIndex), $val) ? $val[$mixedIndex] : $val['MID'];
				!is_array($retVal[$key]) ? $retVal[$key] = $val : 0;
				unset($retVal[$key]['id_role']);
				$val['id_role'] ? $retVal[$key]['::Roles::'][] = $val['id_role'] : 0;
			}
		} else
	  	$retVal = array();
	  return $retVal;
	}
	// }}}

	// {{{ _getAllRoles
	/**
	 * Liefert einen Array mit allen bekannten Rollen zurück
	 *
	 * @return array
	 */
	function _getAllRoles()
	{
		global $env;

		$this->_debugInfo[] = "function _getAllRoles";
	  if (!$env->IBRValues['_Roles']['str'])
	  	$result = $this->sql("SELECT * FROM `Rolle` ORDER BY `pos`, `Bezeichnung`", "RolleID");
	  else
	  	$result = unserialize($env->IBRValues['_Roles']['str']);
	  if (is_array($result)) {
			foreach ($result as $id_role => $val) {
				$result[$id_role]['info_array'] = unserialize($val['info_array']);
				$val['info_array'] = $result[$id_role]['info_array'];
				$result[$id_role]['role_title'] = $this->get_role_title($val);
				$result[$id_role]['role_title_html'] = $this->get_role_title($val, true);
				$result[$id_role]['role_title_personal_menu'] = $this->get_role_title($val, false, true);
			}
	    return $result;
	  } else
	    return array();
	}
	// }}}

	// {{{ _getPossibleMenubarItems
	/**
	 * Liefert einen Array der alle für das personalisierte Menü möglichen Einträge listet
	 * Sofern ein Eintrag eine Rolle voraussetzt, wird er hier bereits ausgefiltert
	 * Durch den Benutzer für sein persönliches Menu gesetzte Einträge werden gesondert markiert
	 *
	 * @return array
	 */
	function _getPossibleMenubarItems()
	{
		global $env;

		$this->_debugInfo[] = "function _getPossibleMenubarItems";
		$arrItems = $this->_getKommentareMustertexte("ORDER BY `Titel`");
		$arrPersonalMenu = array();
		!is_array($this->data['Einstellungen']['personal_menu']) ? $this->getUserSettings() : 0;
		$retVal['has_personal_menu'] = is_array($this->data['Einstellungen']['personal_menu']);
		if (is_array($arrItems)) {
			foreach ($arrItems as $val) {
				//$this->_debugInfo[] = "_getPossibleMenubarItems -> found ".$val['Textnr']." (".$val['Typ'].")";
				!is_array($val['info_array']) ? $val['info_array'] = unserialize($val['info_array']) : 0;
				if (!$val['info_array']['href']) {
					$href = "";
					$val['Typ'] == "Beck" ? $href = $env->root."Beck-Verlag/index.php" : 0;
					$val['Typ'] == "Kommentar" ? $href = $env->root."IBRKommentare/index.php" : 0;
					$val['Typ'] == "Reihe" ? $href = $env->root."IBR-Reihe/index.php" : 0;
					$val['Typ'] == "Mustertexte" ? $href = $env->root."IBRMustertexte/index.php" : 0;
					$val['info_array']['href'] = $href;
				}
				if ($val['RolleID'] != -1)
					$val['user_has_role'] = $this->checkRole($val['RolleID']) ? true : false;
				else
					$val['user_has_role'] = true;
				if ($this->data['Einstellungen']['personal_menu'][$val['Textnr']] == 1) {
					$val['show_in_personal_menu'] = true;
					$arr_show_in_personal_menu[] = $val['Textnr'];
				} elseif ($this->data['Einstellungen']['personal_menu'][$val['Textnr']] == -1)
					$val['show_in_personal_menu'] = false;
				$retVal[$val['Textnr']] = $val;
			}
			!is_array($arr_show_in_personal_menu) ? $arr_show_in_personal_menu = array() : 0;
			$retVal['show_in_personal_menu'] = $arr_show_in_personal_menu;
	    return $retVal;
		}
	}
	// }}}

	// {{{ _getLesesaalItems
	/**
	 * Liefert einen Array der alle im Lesesaal verfügbaren Einträge beinhaltet
	 *
	 * @return array
	 */
	function _getLesesaalItems($sColPos = "pos", $bExcludeIK = false) {
		global $env, $func, $clsZG;
		
		/*
		if (!$bExcludeIK)
		  $arr = $this->sql("SELECT * FROM `Rolle` WHERE (`Bezeichnung` LIKE 'BECK_%' OR `RolleID`='".ROLES_IK."') ORDER BY `online_since` DESC, `istBuchbaresAbo` DESC, `pos`", true);
		else
		  $arr = $this->sql("SELECT * FROM `Rolle` WHERE `Bezeichnung` LIKE 'BECK_%' ORDER BY `online_since` DESC, `istBuchbaresAbo` DESC, `pos`", true);
		*/
	  $arr = $this->sql("SELECT * FROM `Rolle` WHERE `Bezeichnung` LIKE 'BECK_%' ORDER BY `online_since` DESC, `istBuchbaresAbo` DESC, `pos`", true);
		if (is_array($arr)) {
			foreach ($arr as $val)
				$dataRoles[$val['RolleID']] = $val;
		}
	  if (is_array($dataRoles)) {
			$arr = $this->sql("
			    SELECT
			      ka.*,
			      kzp.".$sColPos."
			    FROM
			      idvKommentar_Angaben AS ka
			    LEFT JOIN
			    	ibr_kommentare_zielgruppe_pos AS kzp
			    ON
			    	kzp.KommentarID=ka.KommentarID
			    WHERE
			      kzp.ZielgruppeID='".$clsZG->id."'
			    AND
			    (
			      	ka.Typ='Reihe'
			    	OR
			    		ka.Typ='Kommentar'
			    	OR
			    		(ka.Typ='Beck' AND ka.id_role IN ('".implode("', '", array_keys($dataRoles))."'))
			    )
			    ORDER BY
			      kzp.".$sColPos.", ka.Stand DESC", true);
			if (is_array($arr)) {
				foreach ($arr as $val) {
			    empty($val['Kurztitel']) ? $val['Kurztitel'] = $val['Titel'] : 0;
			    $info_array = is_array($val['info_array']) ? unserialize($val['info_array']) : array();
			    !$val['Autor'] ? $val['Autor'] = $info_array['Autor'] : 0;
			    !$val['Titel'] ? $val['Titel'] = $info_array['Titel'] : 0;
			    if (!$val['Autor'] && !$val['Titel'])
						continue;
					if ($val['Typ'] == "Beck" || $val['id_role'] == ROLES_IK) {
						!$dataRoles[$val['id_role']]['Autor'] ? $dataRoles[$val['id_role']]['Autor'] = $val['Autor'] : 0;
						!$dataRoles[$val['id_role']]['Titel'] ? $dataRoles[$val['id_role']]['Titel'] = $val['Titel'] : 0;
						$data[$val[$sColPos]] = $dataRoles[$val['id_role']];
					} else {
						$id_role = -1;
						//$sLetzteAktualisierung = $val['KommentarID'] != 10 ? "Letzte Aktualisierung: ".$func->mysql2date($val['Stand'])."<br /><br />" : "";
						$lIstBuchbaresAbo = 0;
						$val['Typ'] == "Kommentar" ? $href = $env->root."IBRKommentare/index.php" : 0;
						$val['Typ'] == "Reihe" ? $href = $env->root."IBR-Reihe/index.php" : 0;
						if ($val['Einstelldatum'] != "0000-00-00" || $val['Stand'] != "0000-00-00") {
							$sLetzteAktualisierung = $val['Einstelldatum'] != $val['Stand'] ? "Letzte Aktualisierung: " : "Online seit: ";
							$sLetzteAktualisierung .= $func->mysql2date($val['Stand'])."<br /><br />";
						}
						$val['Einstelldatum'] == "0000-00-00" && $val['Stand'] != "0000-00-00" ? $val['Einstelldatum'] = $val['Stand'] : 0;
						$data[$val[$sColPos]] = array(
							"RolleID" => $id_role,
							"Bezeichnung" => $val['Titel'],
							"Beschreibung" => $val['Titel'],
							"Kurzbeschreibung" => $val['Kurztitel'],
							"istBuchbaresAbo" => $lIstBuchbaresAbo,
							"Textnr" => $val['KommentarID'],
							"info_array" => serialize(array(
								"Titel" => $val['Titel'],
								"Titel_HTML" => $val['Titel'],
								"Autor" => $val['Autor'],
								"Autor_HTML" => $val['Autor'],
								"Preis" => 0.00,
								"Zusatztext_HTML" => $sLetzteAktualisierung.nl2br($val['Kurzangaben']),
								"img_small" => $val['thumb_image'],
								"href" => $href)),
							"online_since" => $val['Einstelldatum']);
					}
				}
				unset($arr);
				unset($dataRoles);
				ksort($data);
			}
		}
		return $data;
	}
	// }}}

	// {{{ _textnr2role
	/**
	 * Liefert eine oder mehrere Rollen basierend auf der Textnr
	 *
	 * @return array
	 */
	function _textnr2role($arrTextnr = array())
	{
		global $env;

		$this->_debugInfo[] = "function _textnr2role";
	  if (!$arrTextnr)
	  	return;
	  !is_array($arrTextnr) ? $arrTextnr = array($arrTextnr) : 0;
		$this->_debugInfo[] = "_textnr2role -> ".implode(", ", $arrTextnr);
	  !count($this->_arrRoles) ? $this->_arrRoles = $this->_getAllRoles() : 0;
	  if (is_array($this->_arrRoles)) {
			foreach ($this->_arrRoles as $val) {
				//echo $val['Textnr']."<br>";
				if (in_array($val['Textnr'], $arrTextnr)) {
					$this->_debugInfo[] = "_textnr2role -> found ".$val['Textnr'];
					!is_array($val['info_array']) ? $val['info_array'] = unserialize($val['info_array']) : 0;
					$retVal[$val['Textnr']] = $val;
				}
			}
	    return $retVal;
	  }
	}
	// }}}

	// {{{ _getAllRolesAdmin
	/**
	 * Liefert einen Array mit allen bekannten Rollen für den Adminbereich zurück
	 *
	 * @return array
	 */
	function _getAllRolesAdmin()
	{
		$this->_debugInfo[] = "function _getAllRolesAdmin";
	  !count($this->_arrRoles) ? $this->_arrRoles = $this->_getAllRoles() : 0;

	  if (is_array($this->_arrRoles)) {
	  	foreach ($this->_arrRoles as $id_role => $val)
	  		$arrSort[$id_role] = $val['pos_admin'];
	  	if (is_array($arrSort)) {
	  		asort($arrSort);
	  		foreach ($arrSort as $id_role => $val)
	  			$result[$id_role] = $this->_arrRoles[$id_role];
			}
			return $result;
		} else
			return array();
	}
	// }}}

	// {{{ _getKommentarPosition
	/**
	 * Liefert einen Array mit den Positionen der zusätzlich buchbaren Rollen
	 *
	 * @return array
	 */
	function _getKommentarPosition($bWithMustertexte = false)
	{
		global $clsZG, $sql, $func;

		$this->_debugInfo[] = "function _getKommentarPosition";
		$bWithMustertexte ? $mySQL = "OR ka.Typ='Mustertexte'" : 0;
		$arr = $this->sql("
	    SELECT
	      ka.*,
	      kzp.pos,
	      kzp.pos_logged_in
	    FROM
	      idvKommentar_Angaben AS ka
	    LEFT JOIN
	    	ibr_kommentare_zielgruppe_pos AS kzp
	    ON
	    	kzp.KommentarID=ka.KommentarID
	    WHERE
	      kzp.ZielgruppeID='".$clsZG->id."'
	    AND
	    (
	      	ka.Typ='Reihe'
	    	OR
	    		ka.Typ='Kommentar'
	    	OR
	    		(ka.Typ='Beck' AND ka.id_role IN ('".implode("', '", array_keys($this->_arrRoles))."'))
	    	".$mySQL."
	    )", true);
		if (is_array($arr)) {
			foreach ($arr as $val) {
		    empty($val['Kurztitel']) ? $val['Kurztitel'] = $val['Titel'] : 0;
		    if (!$val['Autor'] && !$val['Titel'])
					continue;
				if ($val['Typ'] == "Beck" || $val['id_role'] == ROLES_IK)
					$use_val = $this->_arrRoles[$val['id_role']];
				else
					$use_val = array(
						"RolleID" => -1,
						"Bezeichnung" => $val['Titel'],
						"Beschreibung" => $val['Titel'],
						"Kurzbeschreibung" => $val['Kurztitel'],
						"istBuchbaresAbo" => 0,
						"Typ" => $val['Typ'],
						"Textnr" => $val['KommentarID'],
						"info_array" => serialize(array(
							"Titel" => $val['Titel'],
							"Titel_HTML" => $val['Titel'],
							"Autor" => $val['Autor'],
							"Autor_HTML" => $val['Autor'],
							"Preis" => 0.00,
							"Zusatztext_HTML" => "Letzte Aktualisierung: ".$func->mysql2date($val['Stand'])."<br /><br />".$val['Kurzangaben'],
							"img_small" => $val['thumb_image'],
							"href" => "lesesaal.php")),
						"online_since" => $val['Einstelldatum']);
				$arrSorted['logged_in'][$val['pos_logged_in']] = $use_val;
				$arrSorted['not_logged_in'][$val['pos']] = $use_val;
				$val['pos_logged_in'] > $max_pos_logged_in ? $max_pos_logged_in = $val['pos_logged_in'] : 0;
				$val['pos'] > $max_pos ? $max_pos = $val['pos'] : 0;
			}

			$max_pos_logged_in++;
			$max_pos++;
			$use_val = array(
				"RolleID" => -1,
				"Bezeichnung" => "Mustertexte",
				"Beschreibung" => "Mustertexte",
				"Kurzbeschreibung" => "Mustertexte",
				"istBuchbaresAbo" => 0,
				"Textnr" => "mustertexte",
				"info_array" => serialize(array(
					"Titel" => "Mustertexte",
					"Titel_HTML" => "Mustertexte",
					"Autor" => "",
					"Autor_HTML" => "",
					"Preis" => 0.00,
					"Zusatztext_HTML" => "",
					"img_small" => "",
					"href" => "")),
				"online_since" => "");
			$arrSorted['logged_in'][$max_pos_logged_in] = $use_val;
			$arrSorted['not_logged_in'][$max_pos] = $use_val;

			$max_pos_logged_in++;
			$max_pos++;
			$use_val = array(
				"RolleID" => -1,
				"Bezeichnung" => "Vergabehandbuch",
				"Beschreibung" => "Vergabehandbuch",
				"Kurzbeschreibung" => "Vergabehandbuch",
				"istBuchbaresAbo" => 0,
				"Textnr" => "pdf",
				"info_array" => serialize(array(
					"Titel" => "Vergabehandbuch",
					"Titel_HTML" => "Vergabehandbuch",
					"Autor" => "",
					"Autor_HTML" => "",
					"Preis" => 0.00,
					"Zusatztext_HTML" => "",
					"img_small" => "",
					"href" => "")),
				"online_since" => "");
			$arrSorted['logged_in'][$max_pos_logged_in] = $use_val;
			$arrSorted['not_logged_in'][$max_pos] = $use_val;
			if (is_array($arrSorted['logged_in']))
				ksort($arrSorted['logged_in']);
			if (is_array($arrSorted['not_logged_in']))
				ksort($arrSorted['not_logged_in']);
		} else
			$arrSorted = array();
		return $arrSorted;
	}
	// }}}

	// {{{ _getKommentareMustertexte
	/**
	 * Liefert einen Array mit den Kommentaren / Mustertexten
	 *
	 * @return array
	 */
	function _getKommentareMustertexte($myORDER = "")
	{
		global $sql, $func;

		$this->_debugInfo[] = "function _getKommentareMustertexte(".$myORDER.")";
		$arr = $this->sql("
	    SELECT
	      ka.*
	    FROM
	      idvKommentar_Angaben AS ka
	    WHERE
	      	ka.Typ='Reihe'
	    	OR
	    		ka.Typ='Kommentar'
	    	OR
	    		ka.Typ='Mustertexte'
	    	OR
	    		(ka.Typ='Beck' AND ka.id_role IN ('".implode("', '", array_keys($this->_arrRoles))."'))
	    	".$myORDER, true);
		if (is_array($arr)) {
			foreach ($arr as $val) {
		    empty($val['Kurztitel']) ? $val['Kurztitel'] = $val['Titel'] : 0;
				if ($val['Typ'] == "Beck" || $val['id_role'] == ROLES_IK) {
					$use_val = $this->_arrRoles[$val['id_role']];
					$use_val['Typ'] = $val['Typ'];
					if ($val['Typ'] == "Beck") {
						$val['Titel_personal_menu'] ? $title_personal_menu = $val['Titel_personal_menu'] : 0;
						!$title_personal_menu ? $title_personal_menu = $use_val['role_title_personal_menu'] : 0;
						$use_val['info_array'] = serialize(array(
							"Titel" => $use_val['role_title'],
							"Titel_HTML" => $use_val['role_title_html'],
							"Titel_personal_menu" => $title_personal_menu,
							"Autor" => $use_val['info_array']['Autor']));
					}
				} else {
					!$val['Titel_personal_menu'] ? $val['Titel_personal_menu'] = $val['Titel'] : 0;
					$use_val = array(
						"RolleID" => -1,
						"Bezeichnung" => $val['Titel'],
						"Beschreibung" => $val['Titel'],
						"Kurzbeschreibung" => $val['Kurztitel'],
						"istBuchbaresAbo" => 0,
						"Typ" => $val['Typ'],
						"Textnr" => $val['KommentarID'],
						"info_array" => serialize(array(
							"Titel" => $val['Titel'],
							"Titel_HTML" => $val['Titel'],
							"Titel_personal_menu" => $val['Titel_personal_menu'],
							"Autor" => $val['Autor'],
							"Autor_HTML" => $val['Autor'],
							"Preis" => 0.00,
							"Zusatztext_HTML" => "Letzte Aktualisierung: ".$func->mysql2date($val['Stand'])."<br /><br />".$val['Kurzangaben'],
							"img_small" => $val['thumb_image'])),
						"online_since" => $val['Einstelldatum']);
				}
				$retVal[] = $use_val;
			}
		}
		return $retVal;
	}
	// }}}

	// {{{ _getPublicRoles
	/**
	 * Liefert einen Array mit allen bekannten extern verfügbaren Rollen zurück
	 *
	 * @return array
	 */
	function _getPublicRoles()
	{
		$this->_debugInfo[] = "function _getPublicRoles";
	  $result = $this->sql("SELECT * FROM `Rolle` WHERE `istBuchbaresAbo`='1' OR `istBuchbaresAbo`='-1'  ORDER BY `pos`, `Bezeichnung`", "RolleID");
	  if (is_array($result)) {
			foreach ($result as $id_role => $val) {
				$result[$id_role]['info_array'] = unserialize($val['info_array']);
				$val['info_array'] = $result[$id_role]['info_array'];
				$result[$id_role]['role_title'] = $this->get_role_title($val);
				$result[$id_role]['role_title_html'] = $this->get_role_title($val, true);
			}
	    return $result;
	  } else
	    return array();
	}
	// }}}

	// {{{ get_groups_roles
	/**
	 * Liefert einen Array mit allen bekannten Rollen sortiert nach Gruppen zurück
	 *
	 * @return array
	 */
	function get_groups_roles($pos = "pos")
	{
		$this->_debugInfo[] = "function get_groups_roles";
	  $result = $this->sql("SELECT R.*, g.`id`, g.`name_short`, g.`name_long`, g.`name_extern` FROM `Rolle` AS R LEFT JOIN `ibr_auth_groups_roles` AS gr ON gr.`id_role`=R.`RolleID` LEFT JOIN `ibr_auth_groups` AS g on g.`id`=gr.`id_group` ORDER BY g.`pos`, R.`".$pos."`, R.`Bezeichnung`", "id", "RolleID");
	  if (is_array($result)) {
			foreach ($result as $id_group => $val) {
				$retVal[$id_group] = array();
				if (is_array($val)) {
					foreach ($val as $id_role => $v) {
						!$retVal[$id_group]['name_short'] ? $retVal[$id_group]['name_short'] = $v['name_short'] : 0;
						!$retVal[$id_group]['name_long'] ? $retVal[$id_group]['name_long'] = $v['name_long'] : 0;
						!$retVal[$id_group]['name_extern'] ? $retVal[$id_group]['name_extern'] = $v['name_extern'] : 0;
						unset($v['id']);
						unset($v['name_short']);
						unset($v['name_long']);
						unset($v['name_extern']);
						$retVal[$id_group]['::roles::'][$id_role] = $v;
						$retVal[$id_group]['::roles::'][$id_role]['info_array'] = unserialize($v['info_array']);
						$v['info_array'] = $retVal[$id_group]['::roles::'][$id_role]['info_array'];
						$retVal[$id_group]['::roles::'][$id_role]['role_title'] = $this->get_role_title($v);
						$retVal[$id_group]['::roles::'][$id_role]['role_title_html'] = $this->get_role_title($v, true);
					}
				}
			}
	    return $retVal;
	  } else
	    return array();
	}
	// }}}

	// {{{ updateUserAuthInDB
	/**
	 * Updatet den Datensatz eines Benutzers oder Mitbenutzers in der Tabelle AuthData in der Datenbank
	 *
   * @param long	  $lPersonID		die ID des Benutzers
   * @param string  $sKennung     die Kennung des Benutzers
   * @param array	  $aSET   		  der Array mit den Schlüsseln (Spaltenname) und Werten die zu updaten sind
   *
   * @return true bei Erfolg, false im Fehlerfall
	 */
	function updateUserAuthInDB($lPersonID = 0, $sKennung = "", $aSET = array())
	{
		global $func;
		
		$this->_debugInfo[] = "function updateUserAuthInDB";
		if (!$lPersonID || $sKennung == "" || count($aSET) == 0)
		  return false;
		$sSET = $func->implode_assoc($aSET, "=", ", ", "`", "'");
		if (!$this->SuperPIN_is_MID) {
			$result = $this->sql("
			  UPDATE
			    `AuthData`
			  SET
			    ".$sSET."
			  WHERE
			    `PersonID`='".$lPersonID."'
			  AND
			    `Kennung`='".$sKennung."'"
			);
		} else {
			if ($sSET != "") {
				$result = $this->sql("
				  UPDATE
				    `Mitbenutzerkennung`
				  SET
				    ".$sSET."
				  WHERE
				    `PersonID`='".$lPersonID."'
				  AND
				    `Kennung`='".$sKennung."'"
				);
			}
		}
		return $result;
	}
	// }}}

	// {{{ updateUserPersonInDB
	/**
	 * Updatet den Datensatz eines Benutzers in der Tabelle Person in der Datenbank
	 *
   * @param long	  $lPersonID		die ID des Benutzers
   * @param array	  $aSET   		  der Array mit den Schlüsseln (Spaltenname) und Werten die zu updaten sind
   *
   * @return true bei Erfolg, false im Fehlerfall
	 */
	function updateUserPersonInDB($lPersonID = 0, $aSET = array())
	{
		global $func;
		
		$this->_debugInfo[] = "function updateUserPersonInDB";
		if (!$lPersonID || count($aSET) == 0)
		  return false;
		foreach ($aSET as $key => $val)
		  $aSET[$key] = addslashes($val);
		$sSET = $func->implode_assoc($aSET, "=", ", ", "`", "'");
		$result = $this->sql("
		  UPDATE
		    `Person`
		  SET
		    ".$sSET."
		  WHERE
		    `PersonID`='".$lPersonID."'"
		);
		return $result;
	}
	// }}}

	// {{{ insertMIDInDB
	/**
	 * Legt einen Mitbenutzer für einen Benutzer an
	 *
   * @param array	  $aCols  der Array mit den Schlüsseln (Spaltenname) und Werten die angelegt werden sollen
   *
   * @return true bei Erfolg, false im Fehlerfall
	 */
	function insertMIDInDB($aCols = array())
	{
		$this->_debugInfo[] = "function insertMIDInDB";
		if (count($aCols) == 0)
		  return false;
		foreach ($aCols as $key => $val) {
		  $sSET != "" ? $sSET .= ", " : 0;
		  $sVALUES != "" ? $sVALUES .= ", " : 0;
		  $sSET .= "`".$key."`";
		  $sVALUES .= "'".$val."'";
		}
		$result = $this->sql("
		  INSERT INTO
		    `Mitbenutzerkennung`
		    (".$sSET.")
		  VALUES
		    (".$sVALUES.")"
		);
		return $result;
	}
	// }}}

	// {{{ updateMIDInDB
	/**
	 * Updatet den Datensatz eines Benutzers oder Mitbenutzers in der Datenbank
	 *
   * @param long	  $lMID		die MID des Benutzers
   * @param array	  $aSET   der Array mit den Schlüsseln (Spaltenname) und Werten die zu updaten sind
   *
   * @return true bei Erfolg, false im Fehlerfall
	 */
	function updateMIDInDB($lMID, $aSET = array())
	{
		global $func;
		
		$this->_debugInfo[] = "function updateMIDInDB(".$lMID.", ".serialize($aSET).")";
		if (!$lMID || count($aSET) == 0)
		  return false;
		$sSET = $func->implode_assoc($aSET, "=", ", ", "`", "'");
		if ($sSET != "") {
			$result = $this->sql("
			  UPDATE
			    `Mitbenutzerkennung`
			  SET
			    ".$sSET."
			  WHERE
			    `MID`='".$lMID."'"
			);
			return $result;
		} else
			return false;
	}
	// }}}

	// {{{ updateMIDRoles
	/**
	 * Updatet die zugewiesenen Rollen eines Mitbenutzers in der Datenbank
	 *
   * @param long	  $lMID		die MID des Benutzers
   * @param array	  $aSET   der Array mit den Rollen die für den MID gesetzt werden sollen
   *
   * @return true bei Erfolg, false im Fehlerfall
	 */
	function updateMIDRoles($lMID, $aSET = array())
	{
		global $func;
		
		$this->_debugInfo[] = "function updateMIDRoles(".$lMID.", ".serialize($aSET).")";
		$sWHERE = count($aSET) ? "AND `id_role` NOT IN ('".implode("', '", $aSET)."')" : "";
		$this->sql("
			DELETE
			FROM
				`Mitbenutzer_Rollen`
			WHERE
				`PersonID`='".$this->ID."'
			AND
				`MID`='".$lMID."'
			".$sWHERE);
		$arr = $this->sql("
			SELECT
				id_role
			FROM
				`Mitbenutzer_Rollen`
			WHERE
				`PersonID`='".$this->ID."'
			AND
				`MID`='".$lMID."'", "id_role");
		$arrDiff = is_array($arr) ? array_diff($aSET, array_keys($arr)) : $aSET;
		if (count($arrDiff)) {
			$arr = $this->sql("
				SELECT
					`id_role`, COUNT(*) AS `used`
				FROM
					`Mitbenutzer_Rollen`
				WHERE
					`PersonID`='".$this->ID."'
				AND
					`id_role` IN ('".implode("', '", $arrDiff)."')
				GROUP BY
					`id_role`", "id_role");
			if (is_array($arr)) {
				unset($arrDiff);
				foreach ($arr as $key => $val) {
					$this->data['::Roles::'][$key]['Arbeitsplaetze'] > $val['used'] ? $arrDiff[] = $key : 0;
				}
			}
			if (is_array($arrDiff)) {
				$sVALUES = "";
				foreach ($arrDiff as $val)
					$func->str_add("('".$this->ID."', '".$lMID."', '".$val."')", $sVALUES);
				$retVal = $this->sql("
					INSERT
					INTO
						`Mitbenutzer_Rollen`
						(`PersonID`, `MID`, `id_role`)
					VALUES
						".$sVALUES);
			}
		} else
			$retVal = true;
		return $retVal;
	}
	// }}}

	// {{{ deleteMID
	/**
	 * Löscht einen Mitbenutzer in der Datenbank
	 *
   * @param long	  $lMID		die MID des Benutzers
   *
   * @return true bei Erfolg, false im Fehlerfall
	 */
	function deleteMID($lMID, $bDeleteRoles = false)
	{
		global $env;
		
		$this->_debugInfo[] = "function deleteMID";
		if (!$lMID)
		  return false;
		if ($bDeleteRoles)
			$this->deleteMIDRoles($lMID);
		$arr = $this->sql("
			SELECT
				*
			FROM
				`Mitbenutzerkennung`
			WHERE
				`MID`='".$lMID."'", "MID");
		if ($arr) {
			$result = $this->sql("
			  DELETE FROM
			    `Mitbenutzerkennung`
			  WHERE
			    `MID`='".$lMID."'"
			);
			if ($result) {
			  global $sql, $NeSe;
      	$arrLog = array("id_Person" => $arr['PersonID'], "change_value" => "MID", "old_value" => $arr[$lMID]['Kennung'], "new_value" => "DELETE");
        $this->arrLogChanges[] = $arrLog;
			  include_once $env->root."include/classes/class.favoriten.inc.php";
			  $fav = new Favoriten($arr[$lMID]);
			  if ($fav->rootNode) {
			  	$NeSe->deleteNode($fav->rootNode);
			  }
			}
		}
		return $result;
	}
	// }}}

	// {{{ deleteMIDRoles
	/**
	 * Löscht alle zugewiesenen Rollen eines Mitbenutzer in der Datenbank
	 *
   * @param long	  $lMID		die MID des Benutzers
   *
   * @return true bei Erfolg, false im Fehlerfall
	 */
	function deleteMIDRoles($lMID)
	{
		$this->_debugInfo[] = "function deleteMIDRoles(".$lMID.")";
		if (!$lMID)
		  return false;
		$result = $this->sql("
			DELETE FROM
				`Mitbenutzer_Rollen`
			WHERE
				`MID`='".$lMID."'");
		return $result;
	}
	// }}}

	// {{{ clearMIDs
	/**
	 * Löscht alle Mitbenutzer eines Benutzers
	 *
   * @param long	  $lPersonID		die ID des Benutzers
   *
   * @return true bei Erfolg, false im Fehlerfall
	 */
	function clearMIDs($lPersonID = 0)
	{
		$this->_debugInfo[] = "function clearMIDs";
		if (!$lPersonID)
		  return false;
		$result = $this->sql("
		  DELETE FROM
		    `Mitbenutzerkennung`
		  WHERE
		    `PersonID`='".$lPersonID."'"
		);
		$this->sql("
		  DELETE FROM
		    `Mitbenutzer_Rollen`
		  WHERE
		    `PersonID`='".$lPersonID."'"
		);
  	$arrLog = array("id_Person" => $lPersonID, "change_value" => "MIDs", "old_value" => "", "new_value" => "DELETE");
    $this->arrLogChanges[] = $arrLog;
		return $result;
	}
	// }}}

	// {{{ encryptPassword
	/**
	 * Funktion, um ein Passwort zu verschlüsseln
	 *
	 * @param string  $sPassword  Das zu verschlüsselnde Passwort im Klartext
	 *
	 * @return string   das verschlüsselte Passwort
	 */
	function encryptPassword($sPassword = "")
	{
		$this->_debugInfo[] = "function encryptPassword";
    $retVal = crypt($sPassword, substr($sPassword, 0, 2));
    return $retVal;
	}
	// }}}

	// {{{ getCookie
	/**
	 * Cookie prüfen
	 *
	 * @return void
	 */
	function getCookie()
	{
		$this->_debugInfo[] = "function getCookie";
		if ($_COOKIE['IBRCookieSessionID']) {
		  $this->SessionID = $_COOKIE['IBRCookieSessionID'];
			$this->_debugInfo[] = "getCookie -> SessionID:".$this->SessionID;
		} else {
			//$this->SessionID = false;
			$this->_debugInfo[] = "getCookie -> no cookie";
		}
	}
	// }}}

	// {{{ setCookie
	/**
	 * Cookie setzen
	 *
	 * @return void
	 */
	function setCookie()
	{
		$this->_debugInfo[] = "function setCookie";
		if ($this->_regularLogin) {
    	if ($_SERVER['PHP_SELF'] == "/SessionMgr/Login.php") {
	    	if (!setcookie("IBRCookieSessionID", $this->SessionID, mktime(3, 0, 0, date("m"), date("d") + 1, date("Y")), "/")) {
					$this->_debugInfo[] = "setCookie -> setcookie failed";
	    		$this->logDB("INFO: user->setCookie SessionID:".$this->SessionID." setcookie failed, Datei: ".$_SERVER['PHP_SELF']);
	    	} else
					$this->_debugInfo[] = "setCookie -> setcookie success";
			} else
				$this->_debugInfo[] = "setCookie -> invalid page to set cookie";
		} else
			$this->_debugInfo[] = "setCookie -> _regularLogin:".$this->_regularLogin;
	}
	// }}}

	// {{{ deleteCookie
	/**
	 * Cookie löschen
	 *
	 * @return void
	 */
	function deleteCookie($bForceDelete = false)
	{
		if ($this->_regularLogin || $bForceDelete) {
		  $this->_debugInfo[] = "function deleteCookie";
      if (!setcookie("IBRCookieSessionID", "", mktime(23, 59, 59, date("m"), date("d")-1, date("Y")), "/")) {
    		$this->logDB("INFO: user->deleteCookie setcookie failed, Datei: ".$_SERVER['PHP_SELF']);
      }
	  } else
		  $this->_debugInfo[] = "! function deleteCookie";
	}
	// }}}

	// {{{ getLastLoginData
	/**
	 * Holt Werte des letzten Logins
	 *
	 * @return void
	 */
	function getLastLoginData()
	{
		$this->_debugInfo[] = "function getLastLoginData";
		$this->_debugInfo[] = "getLastLoginData -> !deprecated! (called from Script: ".$_SERVER['PHP_SELF'];
		$this->_debugInfo[] = "getLastLoginData -> redirecting parameters to function get_login_stats";
		$this->_debugging_next = true;
		$this->logDB($this->_debugInfo[count($this->_debugInfo)-3]."\n".$this->_debugInfo[count($this->_debugInfo)-2]."\n".$this->_debugInfo[count($this->_debugInfo)-1]);

    $this->get_login_stats();
    $this->lastLoginData = $this->data['stat_sessiondata']['SessionsInfo'];
	}
	// }}}

	// {{{ setLastLoginData
	/**
	 * Setzt Werte für den letzten Login
	 *
	 * @param long  $arr        Array mit den Schlüssel als Spaltennamen und den Werten als den zu setzenden Werten
	 *
	 * @return void
	 */
	function setLastLoginData($arr, $bForceUpdate = false)
	{
		$this->_debugInfo[] = "function setLastLoginData";
		$this->_debugInfo[] = "setLastLoginData -> !deprecated! (called from Script: ".$_SERVER['PHP_SELF'];
		$this->_debugInfo[] = "setLastLoginData -> redirecting parameters to function set_login_stats";
		$this->_debugging_next = true;
		$this->logDB($this->_debugInfo[count($this->_debugInfo)-3]."\n".$this->_debugInfo[count($this->_debugInfo)-2]."\n".$this->_debugInfo[count($this->_debugInfo)-1]);

		$this->set_login_stats($arr, $this->ID, $bForceUpdate);
	}
	// }}}

	// {{{ newStuffSinceLastLogin
	/**
	 * Findet alle neuen Dinge seit dem letzten Login und gibt sie als Array zurück
	 *
	 * @return den neu zu schreibenden String für die Stat_Sessiondata Tabelle
	 */
	function newStuffSinceLastLogin()
	{
		global $env;

	  if (is_array($this->data['stat_sessiondata']['SessionsInfo'])) {
	    $arrCnt = explode(";", $this->data['stat_sessiondata']['SessionsInfo']);
	    if (is_array($arrCnt)) {
	      foreach ($arrCnt as $arr) {
	        list($key, $val) = explode(":", $arr);
	        $arrCntOld[$key] = $val;
	      }
			}
		}
		$arrGrabKeys = array(
	  	"_idvDokument" => array(
	  		"single" => "neuer veröffentlichter Beitrag",
	  		"multi" => "neue veröffentlichte Beiträge",
	  		"link" => "/IBRZeitschrift/inhalt.php",
	  		"pos" => 1),
	  	"_idvDokument_Werkstatt" => array(
	  		"single" => "neuer Werkstatt-Beitrag",
	  		"multi" => "neue Werkstatt-Beiträge",
	  		"link" => "/IBRZeitschrift/werkstatt.php",
	  		"pos" => 2),
	    "_idvUrteil_kurz" => array(
	  		"single" => "Volltexturteil",
	  		"multi" => "Volltexturteile",
	  		"link" => "/IBRUrteile/index.php",
	  		"pos" => 3),
	    "_idvMaterialien" => array(
	  		"single" => "neue Materialien",
	  		"multi" => "neue Materialien",
	  		"link" => "/IBRMaterialien/index.php",
	  		"pos" => 4),
	    "_Gesetzesangaben" => array(
	  		"single" => "weiteres Gesetz",
	  		"multi" => "weitere Gesetze",
	  		"link" => "/IBRNormen/index.php",
	  		"pos" => 5),
	    "_idvNews" => array(
	  		"single" => "News",
	  		"multi" => "News",
	  		"link" => "/IBRNews/index.php",
	  		"pos" => 6));
	  $retVal = $this->sql("
	    SELECT
	      *
	    FROM
	      ibr_values
	    WHERE
	      _key IN ('".implode("', '", array_keys($arrGrabKeys))."')");
	  if (is_array($retVal)) {
	    foreach ($retVal as $val) {
	      $arrCntNew[$val['_key']] = $val['_value_long'];
	      $SessionsInfo != "" ? $SessionsInfo .= ";" : 0;
	      $SessionsInfo .= $val['_key'].":".$val['_value_long'];
				if (is_array($this->data['stat_sessiondata']['SessionsInfo'])) {
					if (array_key_exists($val['_key'], $arrCntOld)) {
						$num = $val['_value_long'] - $arrCntOld[$val['_key']];
		      	if ($num > 0) {
							$sLink = $num > 1 ? $arrGrabKeys[$val['_key']]['multi'] : $arrGrabKeys[$val['_key']]['single'];
		      		$this->arrNewStuffSinceLastLogin[$arrGrabKeys[$val['_key']]['pos']] = "<p><b>".$num."</b> ".$env->link($sLink, $arrGrabKeys[$val['_key']]['link'])."</p>";
		      	}
		    	}
	    	}
	    }
		}
		return $SessionsInfo;
	}
	// }}}

	// {{{ get_new_stuff_since_last_login
	/**
	 * Findet alle neuen Dinge seit dem letzten Login und gibt sie als Array zurück
	 *
	 * @return den neu zu schreibenden String für die Stat_Sessiondata Tabelle
	 */
	function get_new_stuff_since_last_login()
	{
		global $env;

		$this->_debugInfo[] = "function get_new_stuff_since_last_login";
	  if (is_array($this->data['ibr_login_stats']['ibr_values'])) {
	    $arrCnt = explode(";", $this->data['ibr_login_stats']['ibr_values']);
	    if (is_array($arrCnt)) {
	      foreach ($arrCnt as $arr) {
	        list($key, $val) = explode(":", $arr);
	        $arrCntOld[$key] = $val;
	      }
			}
		}
		$arrGrabKeys = array(
	  	"_idvDokument" => array(
	  		"single" => "neuer veröffentlichter Beitrag",
	  		"multi" => "neue veröffentlichte Beiträge",
	  		"link" => "/IBRZeitschrift/inhalt.php",
	  		"pos" => 1),
	  	"_idvDokument_Werkstatt" => array(
	  		"single" => "neuer Werkstatt-Beitrag",
	  		"multi" => "neue Werkstatt-Beiträge",
	  		"link" => "/IBRZeitschrift/werkstatt.php",
	  		"pos" => 2),
	    "_idvUrteil_kurz" => array(
	  		"single" => "Volltexturteil",
	  		"multi" => "Volltexturteile",
	  		"link" => "/IBRUrteile/index.php",
	  		"pos" => 3),
	    "_idvMaterialien" => array(
	  		"single" => "neue Materialien",
	  		"multi" => "neue Materialien",
	  		"link" => "/IBRMaterialien/index.php",
	  		"pos" => 4),
	    "_Gesetzesangaben" => array(
	  		"single" => "weiteres Gesetz",
	  		"multi" => "weitere Gesetze",
	  		"link" => "/IBRNormen/index.php",
	  		"pos" => 5),
	    "_idvNews" => array(
	  		"single" => "News",
	  		"multi" => "News",
	  		"link" => "/IBRNews/index.php",
	  		"pos" => 6));
	  $retVal = $this->sql("
	    SELECT
	      *
	    FROM
	      ibr_values
	    WHERE
	      _key IN ('".implode("', '", array_keys($arrGrabKeys))."')");
	  if (is_array($retVal)) {
	    foreach ($retVal as $val) {
	      $arrCntNew[$val['_key']] = $val['_value_long'];
	      $SessionsInfo != "" ? $SessionsInfo .= ";" : 0;
	      $SessionsInfo .= $val['_key'].":".$val['_value_long'];
				if (is_array($this->data['ibr_login_stats']['ibr_values'])) {
					if (array_key_exists($val['_key'], $arrCntOld)) {
						$num = $val['_value_long'] - $arrCntOld[$val['_key']];
		      	if ($num > 0) {
							$sLink = $num > 1 ? $arrGrabKeys[$val['_key']]['multi'] : $arrGrabKeys[$val['_key']]['single'];
		      		$this->arrNewStuffSinceLastLogin[$arrGrabKeys[$val['_key']]['pos']] = "<p><b>".$num."</b> ".$env->link($sLink, $arrGrabKeys[$val['_key']]['link'])."</p>";
		      	}
		    	}
	    	}
	    }
		}
		return $SessionsInfo;
	}
	// }}}
	
	// {{{ validateUser
	/**
	 * Prüft eine eingegebene Kennung/Passwort Kombination mit dem eingeloggten Benutzer ab
	 *
	 * @param string  $sUsername  Der Benutzername
	 * @param string  $sPassword  Das Passwort
	 *
	 * @return void
	 */
	function validateUser($sUsername, $sPassword)
	{
		$this->_debugInfo[] = "function validateUser";
    if (!$sUsername || !$sPassword)
      return false;
    else {
      if ($sUsername != $this->data['Kennung'])
        return false;
      else
        return $this->_comparePassword($sPassword, $this->data['Passwort']);
    }
	}
	// }}}

	// {{{ role_is_trial
	/**
	 * Prüft ob eine Rolle Probeabo ist
	 *
	 * @param int/array		$lID	die ID der Rolle oder ein Array mit den Daten der Rolle
	 *
	 * @return boolean
	 */
  function role_is_trial($lID)
  {
		$this->_debugInfo[] = "function role_is_trial(".$lID.")";
    !is_array($lID) ? $arrRole = $this->hasRole($lID) : 0;
    $arrRole = is_array($arrRole) ? $arrRole[$lID] : $lID;
    $retVal = false;
    if (is_array($arrRole)) {
      if ($arrRole['Ablauf_Probezeit'] > 0) {
      	$sDate = $arrRole['Ablauf_Probezeit'];
      	$days_passed = floor((time() - strtotime($sDate)) / 86400);
      	$retVal = $days_passed < 0 ? true : false;
      } else {
      	if ($arrRole['Freischaltdatum'] > 0)
      		$sDate = $arrRole['Freischaltdatum'];
       	elseif ($arrRole['Anmeldedatum'] > 0)
      		$sDate = $arrRole['Anmeldedatum'];
      	$days_passed = floor((time() - strtotime($sDate)) / 86400);
      	!$this->_arrRoles[$lID]['Probezeit'] ? $this->_arrRoles[$lID]['Probezeit'] = $this->default_trial_period : 0;
      	$retVal = $days_passed <= $this->_arrRoles[$lID]['Probezeit'] ? true : false;
    	}
    } else
      $retVal = true;
		$this->_debugInfo[] = "role_is_trial -> ".$retVal;
    return $retVal;
  }
	// }}}

	// {{{ role_offer_as_trial
	/**
	 * Prüft für eine Rolle, ob diese bereits einmal abonniert war
	 *
	 * @param int		$lID	die ID der Rolle
	 *
	 * @return boolean
	 */
  function role_offer_as_trial($lID)
  {
		$this->_debugInfo[] = "function role_offer_as_trial(".$lID.")";
    $arrRole = $this->hasRole($lID);
    $retVal = false;
    if (is_array($arrRole))
      $retVal = $arrRole[$lID]['Sperrdatum'] > 0 ? false : true;
   	else
      $retVal = true;
		$this->_debugInfo[] = "role_offer_as_trial -> retVal: ".$retVal;
    return $retVal;
  }
	// }}}


	// {{{ getStatusProbeabonnent
	/**
	 * Prüft ob ein Benutzer noch Probeabonnent ist
	 *
	 * @return void
	 */
  function getStatusProbeabonnent()
  {
		$this->_debugInfo[] = "function getStatusProbeabonnent";
    if ($this->data['Abonnements'][ROLES_IBR]['Ablauf_Probezeit'] && $this->data['Abonnements'][ROLES_IBR]['Ablauf_Probezeit'] > 0)
    	$this->IstProbeabonnent = $this->data['Abonnements'][ROLES_IBR]['Ablauf_Probezeit'] > date("Y-m-d") ? true : false;
		else
      $this->IstProbeabonnent = date("z") - date("z", strtotime($this->data['Abonnements'][ROLES_IBR]['Anmeldedatum'])) < 15 ? 1 : 0;
		$this->_debugInfo[] = "getStatusProbeabonnent -> IstProbeabonnent:".$this->IstProbeabonnent;
  }
	// }}}

	// {{{ getStatusFreiabo
	/**
	 * Prüft ob ein Benutzer ein Freiabo hat
	 *
	 * @return void
	 */
  function getStatusFreiabo()
  {
		$this->_debugInfo[] = "function getStatusFreiabo";
    $this->IstFreiabonnent = $this->data['Abonnements'][ROLES_IBR]['FreiAbo'] == "Ja" ? 1 : 0;
		$this->_debugInfo[] = "getStatusFreiabo -> IstFreiabonnent:".$this->IstFreiabonnent;
  }
	// }}}

	// {{{ getViewedDocs
	/**
	 * Holt die gesehenen Dokumente für den Benutzer
	 *
	 * @return void
	 */
	function getViewedDocs() {
		$this->_debugInfo[] = "function getViewedDocs";
		if ($this->ID) {
			if (!is_array($this->data['Einstellungen']))
				$this->getUserSettings();

			if ($this->data['Einstellungen']['VerlaufHaekchen'] && !preg_match("/^baun/", $this->SessionID)) {
				$this->data['ViewedDocs'] = $this->sql("
					SELECT
						DISTINCT
						CONCAT(UPPER(LEFT(`Dokumenttyp`, 1)), SUBSTRING(`Dokumenttyp`, 2), ', ', `DokumentID`) AS k,
						1 as v
					FROM
						`SitzungsVerlaufNeu`
					WHERE
						`SessionID`='".$this->SessionID."'", array("k" => "v"));
			}
		}
	}
	// }}}

	// {{{ getUserSettings
	/**
	 * Holt Einstellungen des Benutzers
	 *
	 * @return void
	 */
	function getUserSettings() {
		$this->_debugInfo[] = "function getUserSettings";

		if ($this->ID) {
		  !$this->MID ? $this->MID = $this->data['MID'] : 0;
			$arr = $this->sql("
				SELECT
					`EinstellungFuer`, `Einstellung`
				FROM
					`Benutzereinstellungen`
				WHERE
					`PersonID`='".$this->ID."'
				AND
					`MID`='".$this->MID."'", "EinstellungFuer");
			if (is_array($arr)) {
				foreach ($arr as $key => $val) {
					$key == "personal_menu" ? $val['Einstellung'] = unserialize($val['Einstellung']) : 0;
					$this->data['Einstellungen'][$key] = $val['Einstellung'];
				}
			}

			$myVALUES = "";
			if (!is_array($this->data['Einstellungen']) || !array_key_exists("Zielgruppe", $this->data['Einstellungen'])) {
				$this->getUserDataExt();
				if ($this->dataExt['Zielgruppe'] != "") {
					$this->data['Einstellungen']['Zielgruppe'] = $this->dataExt['Zielgruppe'];
					$myVALUES != "" ? $myVALUES .= ", " : 0;
        	$myVALUES .= "('".$this->ID."', '".$this->MID."', 'Zielgruppe', '".$this->dataExt['Zielgruppe']."', NOW())";
				}
			}
			foreach ($this->arrEinstellungenDefault as $key => $val) {
				if (!array_key_exists($key, $this->data['Einstellungen'])) {
					$key == "show_Beenden_in_commentary" && array_key_exists("show_Beenden_in_main_menu", $this->data['Einstellungen']) ? $val = $this->data['Einstellungen']['show_Beenden_in_main_menu'] : 0;
					$key == "confirm_Beenden_in_commentary" && array_key_exists("show_Beenden_in_main_menu", $this->data['Einstellungen']) ? $val = $this->data['Einstellungen']['show_Beenden_in_main_menu'] : 0;
					$key == "auto_login_to_zg" && array_key_exists("Zielgruppe", $this->data['Einstellungen']) ? $val = 0 : 0;
					$this->data['Einstellungen'][$key] = $val;
					$myVALUES != "" ? $myVALUES .= ", " : 0;
        	$myVALUES .= "('".$this->ID."', '".$this->MID."', '".$key."', '".$val."', NOW())";
				}
			}
			$myVALUES ? $this->sql("REPLACE INTO `Benutzereinstellungen` (`PersonID`, `MID`, `EinstellungFuer`,  `Einstellung`, `Eingetragen`) VALUES ".$myVALUES) : 0;
		} else
			$this->data['Einstellungen'] = $this->arrEinstellungenDefault;
	}
	// }}}

	// {{{ deleteUserSettings
	/**
	 * Löscht Benutzer-Einstellungen
	 *
	 * @return void
	 */
	function deleteUserSetting($sKey = "") {
		if ($sKey) {
			$this->sql("
				DELETE
				FROM
					`Benutzereinstellungen`
				WHERE
					`EinstellungFuer`='".$sKey."'
				AND
					`PersonID`='".$this->ID."'
				AND
					`MID`='".$this->MID."'");
			unset($this->data['Einstellungen'][$sKey]);
		}
	}
	// }}}

	// {{{ getVerlauf
	/**
	 * Holt die Einstellung für den Verlauf
	 *
	 * @return void
	 */
	function getVerlauf() {
		$this->_debugInfo[] = "function getVerlauf";
		if (!is_array($this->data['Einstellungen']))
		  $this->getUserSettings();

		$retVal = $this->data['Einstellungen']['VerlaufEin'] || $this->data['Einstellungen']['VerlaufHaekchen'] ? true : false;
		return $retVal;
	}
	// }}}
	// {{{ getNewRegistrations
	/**
	 * Holt Benutzer die noch nicht freigeschaltet sind aus der DB
	 *
	 * @return array
	 */
	function getNewRegistrations() {
		$this->_debugInfo[] = "function getNewRegistrations";
		$retVal = $this->sql("
			SELECT
				P.*
			FROM
				Person AS P
			LEFT JOIN
				Person_Rolle AS PR
			ON
				PR.PersonID=P.PersonID
			LEFT JOIN
				AuthData AS A
			ON
				A.PersonID=P.PersonID
			WHERE
				PR.RolleID='".ROLES_IBR."'
			AND
				PR.Freigeschaltet='Neu'
			AND
				P.Name<>''
			ORDER BY
				P.PersonID", "PersonID");
		return $retVal;
	}
	// }}}

	// {{{ checkDoublets
	/**
	 * Prüft auf mögliche Doubletten bei Anmeldungen
	 *
	 * @param string  $sName  		der Nachname
	 * @param string  $sVorname		der Vorname
	 * @param string  $sOrt				der Ort mit PLZ
	 * @param string  $sStrasse		die Strasse mit Hausnummer
	 * @param string  $sEmail			die E-Mail Adresse
	 *
	 * @return boolean
	 */
	function checkDoublets($sName, $sVorname, $sStrasse, $sOrt, $sEmail = "", $bReturnDoublets = false, $bReturnSingleHit = false) {
		global $sql;

		$this->_debugInfo[] = "function checkDoublets";

		$this->arrDoublets = false;
		$this->doublets_found = false;
		$retVal = false;
		$mySQL = "
			SELECT DISTINCT
				P.PersonID,
				P.Name,
				P.Vorname,
				P.Ort,
				P.Strasse,
				P.Email,
				PR.*
			FROM
				Person AS P
			LEFT JOIN
				Person_Rolle AS PR
			ON
				PR.PersonID=P.PersonID
			WHERE
				PR.RolleID='".ROLES_IBR."'"; // IN (".implode(array_keys($this->_getPublicRoles()), ", ").")";
		$sANDVorname = $sVorname != "" ? "AND SOUNDEX(P.Vorname)=SOUNDEX('".$sVorname."')" : "";
		$arr = $this->sql($mySQL."
			AND
				SOUNDEX(P.Name)=SOUNDEX('".$sName."')
			".$sANDVorname, "PersonID");
		if (is_array($arr)) {
			$this->_debugInfo[] = "checkDoublets -> found ".count($arr)." possible match(es)";
			$sANDEmail = $sEmail != "" ? "OR SOUNDEX(P.Email)=SOUNDEX('".$sEmail."')" : "";
			$arrDoubleCheck = $this->sql($mySQL."
				AND
					P.PersonID IN (".implode(array_keys($arr), ", ").")
				AND
					(
						SOUNDEX(P.Strasse)=SOUNDEX('".$sStrasse."')
					OR
						SOUNDEX(P.Ort)=SOUNDEX('".$sOrt."')
					".$sANDEmail."
					)");
			if (is_array($arrDoubleCheck)) {
				$this->_debugInfo[] = "checkDoublets -> found ".count($arrDoubleCheck)." match(es) after double check";
				$this->doublets_found = true;
				if (count($arrDoubleCheck) > 1) {
					$this->arrDoublets = $arrDoubleCheck;
					$retVal = !$bReturnDoublets ? true : $arrDoubleCheck;
   			} elseif (count($arrDoubleCheck) == 1 && $bReturnSingleHit) {
					$retVal = $arrDoubleCheck;
				}
   		} else
				$this->_debugInfo[] = "checkDoublets -> found no match(es) after double check";
   	} else
			$this->_debugInfo[] = "checkDoublets -> found no match(es)";
		$this->_debugInfo[] = "checkDoublets -> returning: ".$retVal;
   	return $retVal;
	}
	// }}}

	// {{{ isUniqueSession
	/**
	 * Rausfinden, ob für eine Kennung mehrere Sessions offen sind
	 *
	 * @param string  $SessionID   die zu suchende Session ID
	 *
	 * @return boolean
	 */
	function isSessionUnique($SessionID = "") {
		$SessionID == "" ? $SessionID = $this->SessionID : 0;
		$arr = $this->sql("
			SELECT
				S2.SessionID
			FROM
				Session S1,
				Session S2
			WHERE
				S1.SessionID='".$SessionID."'
			AND
				S1.Valid='Y'
			AND
				S1.PersonID=S2.PersonID
			AND
				S2.Valid='Y'
			AND
				S1.SessionID!=S2.SessionID");
		return !is_array($arr);
	}
	// }}}

	// {{{ sendSuperPIN
	/**
	 * Versendet eine SuperPIN an die angegebene Kennung
	 *
	 * @param string  $sKennung   die Kennung an die gesendet werden soll
	 *
	 * @return long / array
	 */
	function sendSuperPIN($sKennung)
	{
	  global $env, $func, $clsDienst;

	  if ($sKennung == "")
	  	return -1;

		$sKENNUNGAuth = "A.`Kennung`='".$sKennung."'";
		$sKENNUNGMit = "M.`Kennung`='".$sKennung."'";
		if (strpos($sKennung, " ") !== false) {
			$sKENNUNGAuth = "(".$sKENNUNGAuth." OR A.`Kennung`='".str_replace(" ", "+", $sKennung)."')";
			$sKENNUNGMit = "(".$sKENNUNGMit." OR M.`Kennung`='".str_replace(" ", "+", $sKennung)."')";
		}
	  $arr = $this->sql("
	    SELECT
	      A.Kennung,
	      A.PersonID,
	      P.Email,
	      P.Name,
	      P.Vorname,
	      P.Anrede,
	      P.Titel
	    FROM
	      AuthData AS A, Person AS P
	    WHERE
	      A.PersonID=P.PersonID
	    AND
	      ".$sKENNUNGAuth);
		if (!is_array($arr)) {
			$arr = $this->sql("
				SELECT
		      M.Kennung,
		      M.PersonID,
		      M.Email,
		      P.Name,
		      P.Vorname,
		      P.Anrede,
		      P.Titel
				FROM
					`Mitbenutzerkennung` AS M
				LEFT JOIN
					`Person` AS P
				ON P.`PersonID` = M.`PersonID`
				WHERE
					".$sKENNUNGMit);
			if (!is_array($arr))
	    	return -1;
	    else
	    	$bMID = true;
		}
		$arr = $arr[0];

	  $arrTmp = $this->data['::Roles::'];
	  $this->data['::Roles::'] = $this->getRoles($arr['PersonID']);
	  $retVal = $this->checkRole(ROLES_IBR);
	  if ($retVal) {
		  srand((double)microtime() * 1000000);
		  $sSuperPIN = substr(md5(date("YmdHis", time()).$arr['Email'].$arr['PersonID'].$arr['Kennung']), rand(0, 23), 8);
		  if (!$bMID) {
			  $this->sql("
			    UPDATE
			      AuthData
			    SET
			      PasswortPIN='".$sSuperPIN."'
			    WHERE
			      PersonID='".$arr['PersonID']."'");
			} else {
			  $this->sql("
			    UPDATE
			      Mitbenutzerkennung
			    SET
			      PasswortPIN='".$sSuperPIN."'
			    WHERE
			      PersonID='".$arr['PersonID']."'");
			}

			include_once $env->root."include/classes/class.email.inc.php";
			$email = new Email();
			$email->use_pear = true;

		  $body = $func->createSalutation($arr, true)."\n";
		  $body .= "\n";
		  if (!$bMID)
		  	$body .= "Sie haben soeben auf unseren Internetseiten eine \"Super-PIN\" zur Neubestimmung Ihres Passwortes angefordert.\n";
		  else
		  	$body .= "Sie haben soeben auf unseren Internetseiten eine \"Super-PIN\" zur Neubestimmung Ihres Mitbenutzer-Passwortes angefordert.\n";
		  $body .= "\n";

		  $body .= "Sie können nun die Seite\n";
		  $body .= "\n";
		  $body .= $env->root_web."/IBRRegistrierung/PasswortPIN.php?SPIN=".$sSuperPIN."\n";
		  $body .= "\n";
		  $body .= "aufrufen und dort ein neues Passwort festlegen. Die erforderliche\n";
		  $body .= "\"Super-PIN\" ist auf dieser Seite schon für Sie eingetragen.\n";
		  $body .= "\n";
	  	$body .= "Bitte denken Sie daran, nach der Änderung etwaigen Mitbenutzern Ihrer\n";
	  	$body .= "Benutzerkennung das neue Passwort mitzuteilen.\n";
		  $body .= "\n";

		  $body .= "Falls Sie diese E-Mail nicht angefordert haben sollten, können Sie\n";
		  $body .= "sie ohne weiteres ignorieren.\n";
		  $body .= "\n";
		  $body .= "Ihr ".$clsDienst->data['abo.short_name']."-Team";

		  $email->send($arr['Email'], $clsDienst->data['abo.short_name'].": neues Passwort festlegen", $body, $func->get_mail_string("Mayer"));
		  $email->send($func->get_mail_string("Garcia"), "Super-PIN angefordert", "Für Nutzer\n\n".$sKennung."\n\n wurde gerade eine Super-PIN angefordert.\n\n".date("d.m.Y H:i:s")." Uhr", "g@arcia.de");
			return $arr;
		} else
			return -2;
	}
	// }}}

	// {{{ checkSuperPIN
	/**
	 * Prüft eine Super-PIN auf Gültigkeit
	 *
	 * @param string  $sSuperPIN  	die Super-PIN die geprüft werden soll
	 * @param string  $sKennung   	die Kennung die geprüft werden soll
	 *
	 * @return boolean / array
	 */
	function checkSuperPIN($sSuperPIN, $sKennung)
	{
	  $arr = $this->sql("
	    SELECT
	      Kennung,
	      PersonID,
	      PasswortPIN
	    FROM
	      AuthData
	    WHERE
	      Kennung='".$sKennung."'
	    AND
	      PasswortPIN='".$sSuperPIN."'", "Kennung");
		if (!is_array($arr)) {
		  $arr = $this->sql("
		    SELECT
		      Kennung,
		      PersonID,
		      PasswortPIN
		    FROM
		      Mitbenutzerkennung
		    WHERE
		      Kennung='".$sKennung."'
		    AND
		      PasswortPIN='".$sSuperPIN."'", "Kennung");
			is_array($arr) ? $this->SuperPIN_is_MID = true : 0;
		}
		if (is_array($arr))
			return $arr[$sKennung];
		else
			return false;
	}
	// }}}

	// {{{ createUser
	/**
	 * Legt einen neuen Benutzer an
	 *
	 * @param array  $arrCols  	Array mit den Schlüssel-Wertepaaren die dem Benutzer in der DB zugeordnet werden sollen
	 * @param array  $arrRoles 	Array mit den Schlüssel-Wertepaaren für die Rollen und deren Anzahl für den Benutzer
	 * @param array  $sKennung  Die anzulegende Kennung des Benutzers
	 * @param array  $sPasswort	Das anzulegende Passwort des Benutzers
	 *
	 * @return boolean / array
	 */
	function createUser($arrCols = array(), $arrRoles = array(), $sKennung = "", $sPasswort = "")
	{
		global $sql;

		$this->_debugInfo[] = "function createUser()";

		if (preg_match("/^([0-9]{1,5})(.*)/", $arrCols['Ort'], $arrMatch)) {
			$arrCols['PLZ'] = $arrMatch[1];
			$arrCols['Ort'] = trim($arrMatch[2]);
		}
		$retVal = $this->checkDoublets($arrCols['Name'], $arrCols['Vorname'], $arrCols['Strasse'], $arrCols['Ort'], $arrCols['Email'], true, true);
		if (!is_array($retVal) && !$this->doublets_found)
			$sFreigeschaltet = "Ja";
		else
			$sFreigeschaltet = "Neu";
		$arrCols['Kennung'] != $sKennung ? $sKennung = $arrCols['Kennung'] : 0;
		$mySQL = $sql->insert_by_array($arrCols, "Person");
		$insert_id = $this->sql($mySQL);
		if ($insert_id) {
			$maxAllowedSessions = 0;
			if (count($arrRoles)) {
				foreach ($arrRoles as $key => $val) {
					if (!$val)
						continue;
					$key == ROLES_IBR ? $maxAllowedSessions = $val : 0;
					$Ablauf_Probezeit = !$this->_arrRoles[$key]['Ablauf_Probezeit'] ? date("Y-m-d", strtotime("+".$this->_arrRoles[$key]['Probezeit']." days")) : $this->_arrRoles[$key]['Ablauf_Probezeit'];
					$myVALUES != "" ? $myVALUES .= ", " : 0;
					$myVALUES .= "('".$insert_id."', '".$key."', '".$sFreigeschaltet."', NOW(), NOW(), '".$val."', '".$Ablauf_Probezeit."')";
					$arr = array("id_role" => $key, "id_Person" => $insert_id, "change_value" => "Freigeschaltet", "old_value" => "Neuanmeldung", "new_value" => $sFreigeschaltet);
					$this->arrLogChanges[] = $arr;
				}
				if ($myVALUES) {
					$this->sql("
						INSERT INTO
							`Person_Rolle`
						(
							`PersonID`,
							`RolleID`,
							`Freigeschaltet`,
							`Anmeldedatum`,
							`Freischaltdatum`,
							`Arbeitsplaetze`,
							`Ablauf_Probezeit`
						)
						VALUES
						".$myVALUES);
					$temp = $this->data['Kennung'];
					$this->data['Kennung'] = $sKennung;
					$this->logChanges();
					$this->data['Kennung'] = $temp;
				}
			}
			if ($sKennung && $sPasswort) {
      	$this->sql("
      		INSERT INTO
      			`AuthData`
      		(
      			`Kennung`,
      			`PersonID`,
      			`Passwort`,
      			`maxAllowedSessions`
      		)
					VALUES
					(
						'".trim($sKennung)."',
						'".$insert_id."',
						'".$this->encryptPassword($sPasswort)."',
						'".$maxAllowedSessions."'
					)");
			}
		}
		return $insert_id;
	}
	// }}}

	// {{{ deleteRole
	/**
	 * Löscht die Rolle eines Benutzers
	 *
	 * @param string  $lUserID  	die ID des Bentuzers
	 * @param string  $lRoleID		die ID der Rolle
	 *
	 * @return boolean
	 */
	function deleteRole($lUserID = false, $lRoleID = false)
	{
	  if ($lUserID && $lRoleID) {
			if ($lRoleID == ROLE_IBR) {
			  $retVal = $this->sql("
			    DELETE
			    FROM
			      `AuthData`
			    WHERE
			      `PersonID`='".$lUserID."'");
			} else {
			  $retVal = $this->sql("
			    DELETE
			    FROM
			      `Person_Rolle`
			    WHERE
			    	`PersonID`='".$lUserID."'
			    AND
			    	`RolleID`='".$lRoleID."'");
			}
		} else
			$retVal = false;
		return $retVal;
	}
	// }}}

	// {{{ logChanges
	/**
	 * Speichert Änderungen an den Abonnbements eines Benutzers
	 *
	 * @param boolean  $bChangeAsAdmin		gibt an, ob die Änderungen durch den User oder den Admin gemacht werden
	 *
	 * @return void
	 */
	function logChanges($bChangeAsAdmin = false)
	{
	  if (is_array($this->arrLogChanges) && count($this->arrLogChanges)) {
	  	$sChangeAs = $bChangeAsAdmin ? "Admin" : $this->data['Kennung'];
	  	foreach ($this->arrLogChanges as $val) {
	  		$id_person = $val['id_Person'] ? $val['id_Person'] : $this->ID;
	  		$create_date = $val['create_date'] ? "'".$val['create_date']."'" : "NOW()";
	  		$execute_date = $val['execute_date'] ? "'".$val['execute_date']."'" : "''";
	  		$executed = $val['executed'] ? $val['executed'] : "";
	  		$myVALUES != "" ? $myVALUES .= ", " : 0;
	  		$myVALUES .= "('".$id_person."', '".$val['id_role']."', '".$val['change_value']."', '".$val['old_value']."', '".$val['new_value']."', ".$create_date.", '".$sChangeAs."', ".$execute_date.", '".$executed."')";
			}
  		$this->sql("
  			INSERT INTO
  				`ibr_log_changes`
  			(
  				`id_Person`,
  				`id_role`,
  				`change_value`,
  				`old_value`,
  				`new_value`,
  				`create_date`,
  				`created_by`,
  				`execute_date`,
  				`executed`
  			)
  			VALUES
  			".$myVALUES);
	  }
	  $this->arrLogChanges = array();
	}
	// }}}

	// {{{ get_login_stats
	/**
	 * Holt Zugriffsdaten für eine Person aus der Datenbank
	 *
	 * @param long  $lID		ID des Benutzers
	 *
	 * @return void
	 */
	function get_login_stats($lID = 0)
	{
		global $env, $clsZG;

		$this->_debugInfo[] = "function get_login_stats(".$lID.")";
		$lID == 0 ? $lID = $this->ID : 0;
		if (!$lID)
			return;
		if ($this->ID == $lID)
			$result = $this->sql("
				SELECT
					*
				FROM
					`Stat_Sessiondata`
				WHERE
					`PersonID`='".$lID."'");
		else
			$result = $this->sql("
				SELECT
					P.`Name`,
					P.`Vorname`,
					S.*
				FROM
					`Person` AS P
				LEFT JOIN
					`Stat_Sessiondata` AS S
				ON
					S.`PersonID`=P.`PersonID`
				WHERE
					P.`PersonID`='".$lID."'
				AND
					S.`PersonID` IS NOT NULL");
		if (is_array($result)) {
			$this->_debugInfo[] = "get_login_stats -> found stats";
			$this->data['stat_sessiondata'] = $result[0];
		  $LastLogin4User = $this->data['stat_sessiondata']['LastLogin'];
		  if ($this->data['::session::']['LoginTime'] > $this->data['stat_sessiondata']['LastLogin']) {
		  	$this->data['stat_sessiondata']['LastLogin'] = $this->data['::session::']['LoginTime'];
		  	$this->set_login_stats(array("LastLogin" => "'".$this->data['stat_sessiondata']['LastLogin']."'"), $lID);
			}
			$retVal = $this->get_login_stats_all($lID, 2);
			$retVal['stat_sessiondata']['LastLogin'] > $this->data['stat_sessiondata']['LastLogin'] ? $this->data['stat_sessiondata']['LastLogin'] = $retVal['stat_sessiondata']['LastLogin'] : 0;
  		$this->data['stat_sessiondata']['LastLogin4User'] = $LastLogin4User;
  	} else {
			$this->_debugInfo[] = "get_login_stats -> no stats found";
  		if ($env->query['Login'] == "yes") {
				$this->_debugInfo[] = "get_login_stats -> assuming first login, setting zg to: ".$this->data['Einstellungen']['Zielgruppe'];
  			$clsZG->id = $this->data['Einstellungen']['Zielgruppe'];
  			$env->query['zg'] = $clsZG->id;
  		} else {
				$retVal = $this->get_login_stats_all($lID, 2);
				$this->data['stat_sessiondata'] = array();
				is_array($retVal['set_login_stats']) ? $this->set_login_stats($retVal['set_login_stats'], $lID) : 0;
				is_array($retVal['stat_sessiondata']) ? $this->data['stat_sessiondata'] = $retVal['stat_sessiondata'] : 0;
		  	count($this->data['stat_sessiondata']) ? $this->data['stat_sessiondata']['LastLogin4User'] = $this->data['stat_sessiondata']['LastLogin'] : 0;
  		}
  	}
		$this->_debugInfo[] = "get_login_stats -> LastLogin4User: ".$this->data['stat_sessiondata']['LastLogin4User'];
  }
	// }}}

	// {{{ get_ibr_login_stats
	/**
	 * Holt Zugriffsdaten für eine Person aus der Datenbank
	 *
	 * @param long  $lID		ID des Benutzers
	 *
	 * @return void
	 */
	function get_ibr_login_stats($lID = 0)
	{
		global $env, $clsZG;

		$this->_debugInfo[] = "function get_ibr_login_stats(".$lID.")";
		$lID == 0 ? $lID = $this->ID : 0;
		if (!$lID)
			return;

		if ($this->ID == $lID)
			$result = $this->sql("
				SELECT
					*
				FROM
					`ibr_login_stats`
				WHERE
					`PersonID`='".$lID."'");
		else
			$result = $this->sql("
				SELECT
					P.`Name`,
					P.`Vorname`,
					S.*
				FROM
					`Person` AS P
				LEFT JOIN
					`ibr_login_stats` AS S
				ON
					S.`PersonID`=P.`PersonID`
				WHERE
					P.`PersonID`='".$lID."'
				AND
					S.`PersonID` IS NOT NULL");
		if (is_array($result)) {
			$this->_debugInfo[] = "get_ibr_login_stats -> found stats";
  		$this->_ibr_login_stats_missing = false;
			$this->data['ibr_login_stats'] = $result[0];
		  $LastLogin4User = $this->data['ibr_login_stats']['last_login'];
		  if ($this->data['::session::']['LoginTime'] > $this->data['ibr_login_stats']['last_login']) {
		  	$this->data['ibr_login_stats']['last_login'] = $this->data['::session::']['LoginTime'];
		  	$this->set_ibr_login_stats(array("last_login" => "'".$this->data['ibr_login_stats']['last_login']."'"), $lID);
			}
			$retVal = $this->get_ibr_login_stats_all($lID, 2);
			$retVal['ibr_login_stats']['last_login'] > $this->data['ibr_login_stats']['last_login'] ? $this->data['ibr_login_stats']['last_login'] = $retVal['ibr_login_stats']['last_login'] : 0;
  		$this->data['ibr_login_stats']['LastLogin4User'] = $LastLogin4User;
  	} else {
			$this->_debugInfo[] = "get_ibr_login_stats -> no stats found";
			$this->_ibr_login_stats_missing = true;
			$retVal = $this->get_ibr_login_stats_all($lID, 2);
  		if ($env->query['Login'] == "yes") {
				$this->_debugInfo[] = "get_ibr_login_stats -> assuming first login, setting zg to: ".$this->data['Einstellungen']['Zielgruppe'];
  			$clsZG->id = $this->data['Einstellungen']['Zielgruppe'];
  			$env->query['zg'] = $clsZG->id;
  		} else
				$this->data['ibr_login_stats'] = array();
			is_array($retVal['set_ibr_login_stats']) ? $this->set_ibr_login_stats($retVal['set_ibr_login_stats'], $lID) : 0;
			is_array($retVal['ibr_login_stats']) ? $this->data['ibr_login_stats'] = $retVal['ibr_login_stats'] : 0;
  		count($this->data['ibr_login_stats']) ? $this->data['ibr_login_stats']['LastLogin4User'] = $this->data['ibr_login_stats']['last_login'] : 0;
  	}
		$this->_debugInfo[] = "get_ibr_login_stats -> LastLogin4User: ".$this->data['ibr_login_stats']['LastLogin4User'];
  }
	// }}}

	// {{{ get_login_stats_all
	/**
	 * Holt zusätzliche Zugriffsdaten für eine Person aus der Datenbank
	 *
	 * @param long  $lID		ID des Benutzers
	 *
	 * @return array
	 */
	function get_login_stats_all($lID = 0, $lGetItem = 1)
	{
		global $env, $clsZG;

		$this->_debugInfo[] = "get_login_stats_all(".$lID.", ".$lGetItem.")";

		$lID == 0 ? $lID = $this->ID : 0;
		if (!$lID)
			return;

		$retVal = false;

		if ($this->ID == $lID) {
			$result = $this->sql("
				SELECT
					`PersonID`,
					`SessionID`,
					`LoginTime`,
					`LastAccess`,
					`LogoutTime`
				FROM
					`Session`
				WHERE
					`PersonID`='".$lID."'
				ORDER BY
					`LastAccess` DESC,
					`LoginTime` DESC", "PersonID", "SessionID");
		} else {
			$result = $this->sql("
				SELECT
					P.`Name`,
					P.`Vorname`,
					S.`PersonID`,
					S.`SessionID`,
					S.`LoginTime`,
					S.`LastAccess`,
					S.`LogoutTime`
				FROM
					`Person` AS P
				LEFT JOIN
					`Session` AS S
				ON
					S.`PersonID`=P.`PersonID`
				WHERE
					P.`PersonID`='".$lID."'
				AND
					S.`PersonID` IS NOT NULL
				ORDER BY
					S.`LastAccess` DESC,
					S.`LoginTime` DESC", "PersonID", "SessionID");
		}
		if (is_array($result)) {
			$this->_debugInfo[] = "get_login_stats_all -> found stats in Session table";
			$cnt = 0;
			foreach ($result[$lID] as $val) {
				$cnt++;
				$retVal['stat_sessiondata'] = array(
					"Name" => $val['Name'],
					"Vorname" => $val['Vorname'],
					"PersonID" => $lID,
					"Session_Anzahl" => count($result[$lID]),
					"LastLogin" => $val['LoginTime'],
					"LastLogout" => $val['LogoutTime'],
					"LastAccess" => $val['LastAccess']);
				$retval['set_login_stats'] = array(
					"Session_Anzahl" => "'".count($result[$lID])."'",
					"LastLogin" => "'".$val['LoginTime']."'",
					"LastLogout" => "'".$val['LogoutTime']."'",
					"LastAccess" => "'".$val['LastAccess']."'");
				if ($lGetItem == $cnt)
					break;
			}
		}
		return $retVal;
	}
	// }}}

	// {{{ get_ibr_login_stats_all
	/**
	 * Holt zusätzliche Zugriffsdaten für eine Person aus der Datenbank
	 *
	 * @param long  $lID		ID des Benutzers
	 *
	 * @return array
	 */
	function get_ibr_login_stats_all($lID = 0, $lGetItem = 1)
	{
		global $env, $clsZG;

		$this->_debugInfo[] = "get_ibr_login_stats_all(".$lID.", ".$lGetItem.")";

		$lID == 0 ? $lID = $this->ID : 0;
		if (!$lID)
			return;

		$retVal = false;
		if ($this->ID == $lID)
			$result = $this->sql("
				SELECT
					`PersonID`,
					`SessionID`,
					`LoginTime`,
					`LastAccess`,
					`LogoutTime`
				FROM
					`Session`
				WHERE
					`PersonID`='".$lID."'
				ORDER BY
					`LastAccess` DESC,
					`LoginTime` DESC", "PersonID", "SessionID");
		else
			$result = $this->sql("
				SELECT
					P.`Name`,
					P.`Vorname`,
					S.`PersonID`,
					S.`SessionID`,
					S.`LoginTime`,
					S.`LastAccess`,
					S.`LogoutTime`
				FROM
					`Person` AS P
				LEFT JOIN
					`Session` AS S
				ON
					S.`PersonID`=P.`PersonID`
				WHERE
					P.`PersonID`='".$lID."'
				AND
					S.`PersonID` IS NOT NULL
				ORDER BY
					S.`LastAccess` DESC,
					S.`LoginTime` DESC", "PersonID", "SessionID");
		if (is_array($result)) {
			$this->_debugInfo[] = "get_ibr_login_stats -> found stats in Session table";
			$cnt = 0;
			foreach ($result[$lID] as $val) {
				$cnt++;
				$retVal['ibr_login_stats'] = array(
					"Name" => $val['Name'],
					"Vorname" => $val['Vorname'],
					"PersonID" => $lID,
					"logins_total" => count($result[$lID]),
					"last_login" => $val['LoginTime'],
					"last_logout" => $val['LogoutTime'],
					"last_access" => $val['LastAccess']);
				$retval['set_ibr_login_stats'] = array(
					"logins_total" => "'".count($result[$lID])."'",
					"last_login" => "'".$val['LoginTime']."'",
					"last_logout" => "'".$val['LogoutTime']."'",
					"last_access" => "'".$val['LastAccess']."'");
				if ($lGetItem == $cnt)
					break;
			}
		}
		return $retVal;
	}
	// }}}
	
	// {{{ set_login_stats
	/**
	 * Speichert Zugriffsdaten für eine Person in der Datenbank
	 *
	 * @param long  	$lID						ID des Benutzers, Default ist die aktuelle user->ID
	 * @param array  	$arr						Array mit den Schlüssel als Spaltennamen und den Werten als den zu setzenden Werten
	 * @param bool		$bForceUpdate		Wenn true, dann auf jeden Fall ein Update schreiben
	 *
	 * @return void
	 */
	function set_login_stats($arr = array(), $lID = 0, $bForceUpdate = false)
	{
		global $func;

		$lID == 0 ? $lID = $this->ID : 0;
		!count($arr) && count($this->arr_set_login_stats) ? $arr = $this->arr_set_login_stats : 0;
		if ((!$lID || !count($arr) || $this->surpress_set_login_stats) && !$bForceUpdate)
			return;
		$this->_debugInfo[] = "function set_login_stats(array(".$func->implode_assoc($arr, " => ", ", ")."), ".$lID.", ".$bForceUpdate.")";
		!is_array($this->data['stat_sessiondata']) ? $this->get_login_stats($lID) : 0;
		if (is_array($this->data['stat_sessiondata']) && count($this->data['stat_sessiondata'])) {
			$result = $this->sql("
				UPDATE
					`Stat_Sessiondata`
				SET
					".$func->implode_assoc($arr, "=", ", ", "`", "")."
				WHERE
					`PersonID`='".$lID."'");
		} else {
			$mySET = "`PersonID`";
			$myVALUES = "'".$lID."'";
			foreach ($arr as $key => $val) {
				$mySET != "" ? $mySET .= ", " : 0;
				$myVALUES != "" ? $myVALUES .= ", " : 0;
				$mySET .= "`".$key."`";
				$myVALUES .= $val;
			}
			$result = $this->sql("
				INSERT INTO
					`Stat_Sessiondata`
					(".$mySET.")
				VALUES
					(".$myVALUES.")");
		}
		$this->arr_set_login_stats = array();
	}
	// }}}

	// {{{ set_ibr_login_stats
	/**
	 * Speichert Zugriffsdaten für eine Person in der Datenbank
	 *
	 * @param long  	$lID						ID des Benutzers, Default ist die aktuelle user->ID
	 * @param array  	$arr						Array mit den Schlüssel als Spaltennamen und den Werten als den zu setzenden Werten
	 * @param bool		$bForceUpdate		Wenn true, dann auf jeden Fall ein Update schreiben
	 *
	 * @return void
	 */
	function set_ibr_login_stats($arr = array(), $lID = 0, $bForceUpdate = false)
	{
		global $func;

		$lID == 0 ? $lID = $this->ID : 0;
		!count($arr) && count($this->arr_set_ibr_login_stats) ? $arr = $this->arr_set_ibr_login_stats : 0;
		if ((!$lID || !count($arr) || $this->surpress_set_login_stats) && !$bForceUpdate)
			return;
		$this->_debugInfo[] = "function set_ibr_login_stats(array(".$func->implode_assoc($arr, " => ", ", ")."), ".$lID.", ".$bForceUpdate.")";
		!is_array($this->data['ibr_login_stats']) ? $this->get_ibr_login_stats($lID) : 0;
		if (!$this->_ibr_login_stats_missing && is_array($this->data['ibr_login_stats']) && count($this->data['ibr_login_stats'])) {
			$result = $this->sql("
				UPDATE
					`ibr_login_stats`
				SET
					".$func->implode_assoc($arr, "=", ", ", "`", "")."
				WHERE
					`PersonID`='".$lID."'");
		} else {
			$this->_ibr_login_stats_missing = false;
			$mySET = "`PersonID`";
			$myVALUES = "'".$lID."'";
			foreach ($arr as $key => $val) {
				$mySET != "" ? $mySET .= ", " : 0;
				$myVALUES != "" ? $myVALUES .= ", " : 0;
				$mySET .= "`".$key."`";
				$myVALUES .= $val;
			}
			$result = $this->sql("
				REPLACE INTO
					`ibr_login_stats`
					(".$mySET.")
				VALUES
					(".$myVALUES.")");
		}
		$this->arr_set_ibr_login_stats = array();
	}
	// }}}
	
	// {{{ get_stat_document_types
	/**
	 * Daten für Statistiken
	 *
	 * @param long  $lID		ID des Benutzers
	 *
	 * @return array
	 */
  function get_stat_document_types($lID) {
		$this->_debugInfo[] = "function get_stat_document_types(".$lID.")";
		$result = $this->sql("
			SELECT
				*
			FROM
				`Stat_Dokumenttyp`
			WHERE
				`PersonID`='".$lID."'", "Dokumenttyp");
		return $result;
  }
  // }}}

	// {{{ count_documents_viewed
	/**
	 * Zähler für aufgerufene Dokumente durch den Benutzer
	 *
	 * @param string  $sDokumentTyp		Art des Dokuments
	 * @param long  	$lDokumentID		ID des Dokuments
	 * @param long  	$lID						ID des Benutzers
	 *
	 * @return boolean (true wenn das Dokument angezeigt werden soll, false wenn der Zähler überschritten wurde)
	 */
  function count_documents_viewed($sDokumentTyp, $lDokumentID, $lID = false) {
		global $sql;

		$this->_debugInfo[] = "function count_documents_viewed(".$sDokumentTyp.", ".$lDokumentID.", ".$lID.")";
		!$lID ? $lID = $this->ID : 0;
		if (!$lID)
			return;
		$sql->query("
			DELETE FROM
				`ibr_count_documents_viewed`
			WHERE
				`PersonID`='".$lID."'
			AND
				`viewed`<DATE_SUB(NOW(), INTERVAL ".$this->documents_viewed_timeout." MINUTE)");
  	$arr = $sql->query("
  		SELECT
  			COUNT(*) AS `cnt`
  		FROM
  			`ibr_count_documents_viewed`
  		WHERE
  			`PersonID`='".$lID."'");
  	$this->count_documents_viewed = !is_array($arr) ? 0 : $arr[0]['cnt'];
		if ($this->count_documents_viewed < $this->max_count_documents_viewed) {
			$this->count_documents_viewed++;
			$sql->query("
				REPLACE INTO
					`ibr_count_documents_viewed`
					(`PersonID`, `DokumentTyp`, `DokumentID`, `viewed`)
				VALUES
					('".$lID."', '".$sDokumentTyp."', '".$lDokumentID."', NOW())");
  		return true;
  	} else
  		return false;
  }
  // }}}

	// {{{ is_leecher
	/**
	 * Gibt zurück, ob ein Benutzer massenhaft Dokumente abruft
	 *
	 * @return boolean (true falls zu viele Dokumente abgerufen wurden, false wenn der Zähler noch ok ist)
	 */
  function is_leecher() {

		$this->_debugInfo[] = "function is_leecher()";
		if (!$this->ID)
			return false;
		$this->_debugInfo[] = "is_leecher -> max_count_documents_viewed: ".$this->max_count_documents_viewed;
		$this->_debugInfo[] = "is_leecher -> count_documents_viewed: ".$this->count_documents_viewed;
		return $this->count_documents_viewed >= $this->max_count_documents_viewed;
  }
  // }}}

	// {{{ clear_SessionID
	/**
	 * setzt die SessionIDs in diversen Klassen auf false
	 *
	 * @return void
	 */
  function clear_SessionID() {

		global $env;

		$this->_debugInfo[] = "function clear_SessionID()";
		$this->SessionID = false;
		$env->SessionID = false;
		unset($env->query['SessionID']);
  }
  // }}}

	// {{{ logDB
	/**
	 * Logfile schreiben
	 *
	 * @param string  $sLog   der Text der geloggt werden soll
	 *
	 * @return void
	 */
	function logDB($sLog = "")
	{
		$this->_debugInfo[] = "function logDB()";
		if ($sLog && ($this->_debugging || $this->_debugging_next)) {
			$sLog = addslashes($sLog); // OG, 16.9.06
    	$this->_debugInfo[] = "logDB -> ".$sLog;
    	$lID = $this->ID ? $this->ID : 0;
    	!$lID && $this->data['PersonID'] ? $lID = $this->data['PersonID'] : 0;
    	!$lID && $this->ID_before_login_complete ? $lID = $this->ID_before_login_complete : 0;
    	$result = $this->sql("
    	  INSERT INTO
    	    `Logfile`
    	    (`creation`, `PersonID`, `logtext`)
    	  VALUES
    	    (NOW(), '".$lID."', '".$sLog."')"
    	);
    	$this->_debugging_next = false;
		}
	}
	// }}}

	// {{{ deprecatedAdjustments
	/**
	 * Funktion, um die neue Login-Funktionalität abwärtskompatibel zu halten
	 *
	 * @return void
	 */
	function deprecatedAdjustments()
	{
	  global $fehlernummer, $SessionID, $PersonID, $IBRCookieSessionID, $DokumentGesehen;

		$this->_debugInfo[] = "function deprecatedAdjustments()";
	  $fehlernummer = $this->resultLogin;
		$this->_debugInfo[] = "deprecatedAdjustments -> global fehlernummer:".$fehlernummer;
	  $SessionID = $this->SessionID;
		$this->_debugInfo[] = "deprecatedAdjustments -> global SessionID:".$SessionID;
		if ($this->SessionID == "") {
		  $IBRCookieSessionID = "";
		  $this->_debugInfo[] = "deprecatedAdjustments -> global IBRCookieSessionID:".$IBRCookieSessionID;
		}
	  $PersonID = $this->ID;
	  $DokumentGesehen = $this->data['ViewedDocs'];
		$this->_debugInfo[] = "deprecatedAdjustments -> global PersonID:".$PersonID;
	}
	// }}}

	// {{{ debug
	/**
	 * gibt Debug-Infos aus
	 *
	 * @return void
	 */
	function debug($die = false, $bBufferOutput = false)
	{
		global $clsZG;

		if (!$bBufferOutput) {
			echo "<pre>\n";
			echo date("Y-m-d H:i:s")."<br>\n";
			echo $_SERVER['PHP_SELF']."<br>\n";
			echo "user->debug()<br>\n";
		} else {
			ob_start();
			echo date("Y-m-d H:i:s")."\n";
		}
		$this->_debugInfo[] = "function debug";
		$this->_debugInfo[] = "debug -> this->_loggedIn:".$this->_loggedIn;
		$this->_debugInfo[] = "debug -> this->SessionID:".$this->SessionID;
		$this->_debugInfo[] = "debug -> this->ID:".$this->ID;
		$this->_debugInfo[] = "debug -> this->Kennung:".$this->Kennung;
		$this->_debugInfo[] = "debug -> this->Großkunde:".$this->data['Großkunde'];
		$this->_debugInfo[] = "debug -> clsZG->zg:".$clsZG->id;
		foreach ($this->arr_require_roles as $id_role => $require) {
			$require ? $this->_debugInfo[] = "debug -> page requires role: ".$id_role." (".$this->_arrRoles[$id_role]['Bezeichnung'].")" : 0;
		}
		foreach ($this->arr_missing_roles as $id_role => $missing) {
			$missing ? $this->_debugInfo[] = "debug -> user missing role: ".$id_role." (".$this->_arrRoles[$id_role]['Bezeichnung'].") ***** GAME OVER ***** PLEASE INSERT NEW COIN *****" : 0;
		}
		print_r($this->_debugInfo);
		if (!$bBufferOutput)
			echo "</pre>";
		if ($die)
		  die();
		if ($bBufferOutput) {
			$retVal = ob_get_contents();
			ob_end_clean();
			return $retVal;
		}
	}
	// }}}

	// {{{ ScriptInfo
	/**
	 * gibt verschiedene Infos während der Laufzeit aus
	 *
	 * @return void
	 */
	function ScriptInfo($bResetValues = false)
	{
		global $sql, $func;

		$this->_debugInfo[] = "function ScriptInfo";
		if (!$this->surpress['ScriptInfo'] && ($this->checkRole("Dev-Zugang") || $_SERVER['HTTP_HOST'] == "dev2.ibr-online.de")) {
			$this->cntScriptInfo++;
?>
<br style="clear: both;" />
<div class="box-head dark">Script-Info (<? echo $this->cntScriptInfo; ?>)</div>
<div class="box-sub darkborder">
	<table cellpadding="2">
		<tr>
			<th width="100%" class="dark">Infos der User-Klasse</th>
			<td><a href="javascript:void(0);" onClick="document.getElementById('ScriptInfo[user_info][<? echo $this->cntScriptInfo; ?>]').style.display='none';"><img src="/bilder/_intern/images/up.gif"></a>&nbsp;<a href="#ScriptInfo_user_info<? echo $this->cntScriptInfo; ?>" onClick="document.getElementById('ScriptInfo[user_info][<? echo $this->cntScriptInfo; ?>]').style.display='';"><img src="/bilder/_intern/images/down.gif"></a></td>
		</tr>
		<tr id="ScriptInfo[user_info][<? echo $this->cntScriptInfo; ?>]" style="display: none;">
			<td colspan="2">
<?
			$this->debug();
?>
			</td>
		</tr>
	</table>
	<br />
<?
			if (is_array($sql->info)) {
?>
	<a name="ScriptInfo_sql_info<? echo $this->cntScriptInfo; ?>"></a>
	<table cellpadding="2">
		<tr>
			<th width="100%" class="dark">SQL-Infos</th>
			<td><a href="javascript:void(0);" onClick="document.getElementById('ScriptInfo[sql_info][<? echo $this->cntScriptInfo; ?>]').style.display='none';"><img src="/bilder/_intern/images/up.gif"></a>&nbsp;<a href="#ScriptInfo_sql_info<? echo $this->cntScriptInfo; ?>" onClick="document.getElementById('ScriptInfo[sql_info][<? echo $this->cntScriptInfo; ?>]').style.display='';"><img src="/bilder/_intern/images/down.gif"></a></td>
		</tr>
		<tr>
			<td colspan="2">
				<table cellpadding="2" align="center" class="darkborder">
					<tr>
						<th class="dark">Ausgeführte SQL-Statements</th>
					</tr>
					<tr>
						<td align="center">
							<table cellpadding="2" cellspacing="1">
								<tr>
<?
				foreach ($sql->info as $key => $val) {
					if (substr($key, 0, 2) == "::")
						continue;
?>
									<th class="bright"><? echo $key; ?></th>
<?
				}
?>
								</tr>
								<tr>
<?
				foreach ($sql->info as $key => $val) {
					if (substr($key, 0, 2) == "::")
						continue;
?>
									<td align="center"><? echo $val['count']; if ($val['failed']) echo " (".$val['success']."/".$val['failed'].")"; ?></td>
<?
				}
?>
								</tr>
							</table>
						</td>
					</tr>
				</table>
			</td>
		</tr>
		<tr id="ScriptInfo[sql_info][<? echo $this->cntScriptInfo; ?>]" style="display: none;">
			<td colspan="2">
<?
				if (is_array($sql->info['::queries::'])) {
?>
				<table cellpadding="5">
					<tr>
						<th class="dark">Nr.</th>
						<th class="dark">Query</th>
						<th class="dark">Laufzeit</th>
						<th class="dark">&nbsp;</th>
					</tr>
<?
					foreach ($sql->info['::queries::'] as $key => $val)
						$arrRuntime[$key] = $val['runtime'];
					arsort($arrRuntime);
					foreach ($arrRuntime as $key => $val) {
						$val = $sql->info['::queries::'][$key];
						$cls = !$val['success'] ? "bg_red darkborder" : "darkborder";
						floatval($val['runtime']) >= 0.1 ? $cls = "bg_yellow darkborder" : 0;
						floatval($val['runtime']) >= 0.2 ? $cls = "bg_orange darkborder" : 0;
?>
					<tr>
						<th align="right" class="<? echo $cls; ?>"><? echo ($key + 1); ?>:</th>
						<td class="<? echo $cls; ?>"><? echo htmlentities($val['query']); ?></td>
						<td class="<? echo $cls; ?>"><? echo $val['runtime']; ?></td>
						<td class="<? echo $cls; ?>"><? if ($val['success']) echo "&nbsp;"; else echo "<b>FEHLER</b>"; ?></td>
					</tr>
<?
						break;
					}
					foreach ($sql->info['::queries::'] as $key => $val) {
						$cls = !$val['success'] ? "bg_red darkborder" : "darkborder";
						floatval($val['runtime']) >= 0.1 ? $cls = "bg_yellow darkborder" : 0;
						floatval($val['runtime']) >= 0.2 ? $cls = "bg_orange darkborder" : 0;
?>
					<tr>
						<th align="right" class="<? echo $cls; ?>"><? echo ($key + 1); ?>:</th>
						<td class="<? echo $cls; ?>"><? echo htmlentities($val['query']); ?></td>
						<td style="vertical-align: middle;" class="<? echo $cls; ?>"><? echo $val['runtime']; ?></td>
						<td style="vertical-align: middle;" class="<? echo $cls; ?>"><? if ($val['success']) echo "&nbsp;"; else echo "<b>FEHLER</b>"; ?></td>
					</tr>
<?
					}
?>
				</table>
			</td>
		</tr>
	</table>
<?
					$bResetValues ? $sql->info = array() : 0;
				}
			}
			if ($bResetValues) {
?>
	<p>Werte zurückgesetzt</p>
<?

			}
?>
</div>
<?
		}
	}
	// }}}
}
// }}}
