#include "RegisterServer.h"
#include <iostream>
#include <Klient.h>
#include <Globals.h>

// Inhalt der RegiserServer Klasse aus RegisterServer.h
// Konstruktor 
RegisterServer::RegisterServer(InitDatei* zIni)
	: Thread()
{
	Network::Start(100);
	std::cout << "RS: Verbindung mit Datenbank wird hergestellt...\n";
	db = new RSDatenbank(zIni);
	klients = new RCArray< RSKlient >();
	empfangen = 0;
	gesendet = 0;
	fehler = new Text();
	ini = dynamic_cast<InitDatei*>(zIni->getThis());
	id = (int)*zIni->zWert("ServerId");
	server = new Server();
	aServer = new SSLServer();
	aServer->setPrivateKeyPassword(zIni->zWert("SSLPasswort")->getText());
	aServer->setCertificateFile(zIni->zWert("SSLCert")->getText());
	aServer->setPrivateKeyFile(zIni->zWert("SSLKey")->getText());
	std::cout << "RS: Starten des Admin Servers...\n";
	if (!aServer->verbinde((unsigned short)TextZuInt(ini->zWert("AdminServerPort")->getText(), 10), 10))
	{
		std::cout << "RS: Der Admin Server konnte nicht gestartet werden. Das Programm wird beendet.\n";
		exit(1);
	}
	db->setServerStatus(id, 2);
	end = 0;
	nichtPausiert = 0;
	InitializeCriticalSection(&cs);
	update = 0;
	if (zIni->zWert("Aktiv")->istGleich("TRUE"))
	{
		serverStarten();
		serverFortsetzen();
	}
}

// Destruktor 
RegisterServer::~RegisterServer()
{
	fehler->release();
	server->trenne();
	server->release();
	aServer->trenne();
	aServer->release();
	if (klients)
		klients->release();
	ini->release();
	db->release();
	DeleteCriticalSection(&cs);
}

// nicht constant 
void RegisterServer::runn()
{
	while (!end && aServer->isConnected())
	{
		SSLSKlient* klient;
		klient = aServer->getKlient();
		if (end && klient)
		{
			klient->trenne();
			klient = (SSLSKlient*)klient->release();
			Sleep(1000);
			return;
		}
		if (!klient)
			continue;
		RSAKlient* clHandle = new RSAKlient(klient, dynamic_cast<RegisterServer*>(getThis()));
		clHandle->start();
	}
}

void RegisterServer::thread()
{
	while (server->isConnected())
	{
		SKlient* klient;
		klient = server->getKlient();
		if (!klient)
			continue;
		Framework::getThreadRegister()->cleanUpClosedThreads();
		RSKlient* clHandle = new RSKlient(klient, dynamic_cast<RegisterServer*>(getThis()));
		EnterCriticalSection(&cs);
		klients->add(clHandle);
		LeaveCriticalSection(&cs);
		clHandle->start();
	}
}

void RegisterServer::close()
{
	db->setServerStatus(id, 1);
	server->trenne();
#ifdef WIN32
	warteAufThread(1000);
#endif
	EnterCriticalSection(&cs);
	for (int i = 0; i < klients->getEintragAnzahl(); i++)
		klients->z(i)->absturz();
	klients = (RCArray<RSKlient>*)klients->release();
	LeaveCriticalSection(&cs);
	ende();
	run = 0;
	end = 1;
	Klient* klient = new Klient();
	klient->verbinde(aServer->getPort(), "127.0.0.1");
	Sleep(500);
	aServer->trenne();
	klient->release();
}

bool RegisterServer::serverStarten()
{
	if (nichtPausiert)
	{
		fehler->setText("Der Server konnte nicht gestartet werden: Der Server läuft bereits.");
		return 0;
	}
	if (server)
		server->release();
	server = new Server();
	if (server->verbinde((unsigned short)TextZuInt(ini->zWert("ServerPort")->getText(), 10), 10))
	{
		nichtPausiert = 1;
		start();
		return 1;
	}
	else
	{
		serverBeenden();
		fehler->setText("Der Server konnte nicht gestartet werden: Eventuell ist der Port in benutzung.");
		return 0;
	}
}

bool RegisterServer::serverPause()
{
	if (!nichtPausiert)
	{
		fehler->setText("Der Server konnte nicht pausiert werden: Der Server läuft nicht.");
		return 0;
	}
	if (!db->setServerStatus(id, 2))
	{
		fehler->setText("Der Server konnte nicht pausiert werden: ");
		fehler->append(db->getLetzterFehler());
		return 0;
	}
	return 1;
}

bool RegisterServer::serverFortsetzen()
{
	if (!nichtPausiert)
	{
		fehler->setText("Der Server konnte nicht fortgesetzt werden: Der Server läuft nicht.");
		return 0;
	}
	if (!db->setServerStatus(id, 3))
	{
		fehler->setText("Der Server konnte nicht fortgesetzt werden: ");
		fehler->append(db->getLetzterFehler());
		return 0;
	}
	return 1;
}

bool RegisterServer::serverBeenden()
{
	if (!nichtPausiert)
	{
		fehler->setText("Der Server konnte nicht beendet werden: Der Server läuft nicht.");
		return 0;
	}
	if (db->serverIstNichtPausiert(id))
	{
		fehler->setText("Der Server konnte nicht beendet werden: Der Server muss erst pausiert werden.");
		return 0;
	}
	nichtPausiert = 0;
	ende();
	if (server)
		server->trenne();
	return 1;
}

bool RegisterServer::setMaxKlients(int mc)
{
	if (!db->setMaxClients(id, mc))
	{
		fehler->setText("Die maximale Anzahl der Clients konnte nicht gesetzt werden:\n");
		fehler->append(db->getLetzterFehler());
		return 0;
	}
	ini->setWert("MaxClients", Text() += mc);
	return 1;
}

bool RegisterServer::absturzKlient(int klientId)
{
	bool gefunden = 0;
	EnterCriticalSection(&cs);
	for (int i = 0; i < klients->getEintragAnzahl(); i++)
	{
		if (klients->z(i)->getKlientNummer() == klientId)
		{
			klients->z(i)->absturz();
			klients->remove(i);
			gefunden = 1;
			break;
		}
	}
	LeaveCriticalSection(&cs);
	return gefunden;
}

bool RegisterServer::removeKlient(RSKlient* zKlient)
{
	bool gefunden = 0;
	EnterCriticalSection(&cs);
	for (int i = 0; i < klients->getEintragAnzahl(); i++)
	{
		if (klients->z(i) == zKlient)
		{
			klients->remove(i);
			gefunden = 1;
			break;
		}
	}
	LeaveCriticalSection(&cs);
	return gefunden;
}

void RegisterServer::addGesendet(int bytes)
{
	gesendet += bytes;
}

void RegisterServer::addEmpfangen(int bytes)
{
	empfangen += bytes;
}

// constant
bool RegisterServer::istAn() const
{
	return db->serverIstNichtPausiert(id);
}

Server* RegisterServer::zServer() const
{
	return server;
}

RSDatenbank* RegisterServer::zDB() const
{
	return db;
}

bool RegisterServer::hatClients() const
{
	return klients->hat(0);
}

int RegisterServer::getId() const
{
	return id;
}

const char* RegisterServer::getLetzterFehler() const
{
	return fehler->getText();
}

InitDatei* RegisterServer::zIni() const
{
	return ini;
}


// Inhalt der RSAKlient Klasse aus RegisterServer.h
// Konstruktor 
RSAKlient::RSAKlient(SSLSKlient* klient, RegisterServer* rs)
	: Thread()
{
	this->klient = klient;
	name = new Text("");
	passwort = new Text("");
	adminId = 0;
	version = 0;
	this->rs = rs;
}

// Destruktor 
RSAKlient::~RSAKlient()
{
	klient->trenne();
	klient->release();
	rs->release();
	name->release();
	passwort->release();
}

// nicht constant 
void RSAKlient::thread()
{
	while (1)
	{
		char c = 0;
		if (!klient->getNachricht(&c, 1))
			break;
		else
		{
			bool br = 0;
			switch (c)
			{
			case 1: // Login
				if (1)
				{
					klient->sende("\1", 1);
					unsigned char nLen = 0;
					klient->getNachricht((char*)&nLen, 1);
					char* n = new char[nLen + 1];
					n[(int)nLen] = 0;
					if (nLen)
						klient->getNachricht(n, nLen);
					unsigned char pLen = 0;
					klient->getNachricht((char*)&pLen, 1);
					char* p = new char[pLen + 1];
					p[(int)pLen] = 0;
					if (pLen)
						klient->getNachricht(p, pLen);
					int adminId = rs->zDB()->istAdministrator(n, p);
					if (adminId)
					{
						klient->sende("\1", 1);
						name->setText(n);
						passwort->setText(p);
						this->adminId = adminId;
					}
					else
						errorZuKlient("Falsche Kombination aus Name und Passwort.");
					delete[] n;
					delete[] p;
				}
				break;
			case 2: // Logout
				adminId = 0;
				name->setText("");
				passwort->setText("");
				klient->sende("\1", 1);
				break;
			case 3: // Trennen
				br = 1;
				klient->sende("\1", 1);
				break;
			case 4: // Server starten
				if (!adminId)
					errorZuKlient("Du musst dich einloggen.");
				else
				{
					if (rs->zDB()->adminHatRecht(adminId, Admin_Recht::RSStarten))
					{
						if (!rs->serverStarten())
						{
							Text* err = new Text();
							err->append(rs->getLetzterFehler());
							errorZuKlient(err->getText());
							err->release();
						}
						else
							klient->sende("\1", 1);
					}
					else
						errorZuKlient("Du bist nicht berechtigt den Server zu starten.");
				}
				break;
			case 5: // Server beenden
				if (!adminId)
					errorZuKlient("Du musst dich einloggen.");
				else
				{
					if (rs->zDB()->adminHatRecht(adminId, Admin_Recht::RSBeenden))
					{
						if (rs->serverBeenden())
							klient->sende("\1", 1);
						else
						{
							Text* err = new Text();
							err->append(rs->getLetzterFehler());
							errorZuKlient(err->getText());
							err->release();
						}
					}
					else
						errorZuKlient("Du bist nicht berechtigt den Server zu beenden.");
				}
				break;
			case 6: // Programm Schließen
				if (!adminId)
					errorZuKlient("Du musst dich einloggen.");
				else
				{
					bool ok = 0;
					if (rs->isRunning())
					{
						if (rs->zDB()->adminHatRecht(adminId, Admin_Recht::RSBeenden))
						{
							if (rs->serverBeenden())
								ok = 1;
							else
							{
								Text* err = new Text();
								err->append(rs->getLetzterFehler());
								errorZuKlient(err->getText());
								err->release();
							}
						}
						else
							errorZuKlient("Du bist nicht berechtigt den Server zu beenden.");
					}
					else
						ok = 1;
					if (ok && rs->hatClients())
					{
						errorZuKlient("Es sind noch Klients Online. Bitte versuche es später erneut.");
						break;
					}
					if (ok)
					{
						klient->sende("\1", 1);
						std::cout << "RS: Der Server wird von Benutzer " << adminId << " heruntergefahren.\n";
						rs->close();
						br = 1;
					}
				}
				break;
			case 7: // Progtamm abstürzen
				if (!adminId)
					errorZuKlient("Du musst dich einloggen.");
				else
				{
					bool ok = 0;
					if (rs->isRunning())
					{
						if (rs->zDB()->adminHatRecht(adminId, Admin_Recht::RSBeenden))
						{
							rs->serverBeenden();
							ok = 1;
						}
						else
							errorZuKlient("Du bist nicht berechtigt den Server zu beenden.");
					}
					else
						ok = 1;
					if (ok)
					{
						klient->sende("\1", 1);
						std::cout << "RS: Der Server wurde von Benutzer " << adminId << " terminiert.\n";
						rs->close();
						br = 1;
					}
				}
				break;
			case 8: // Status Frage
				if (1)
				{
					char status = 0;
					if (rs->isRunning())
					{
						status = 1;
						if (rs->istAn())
							status = 2;
					}
					klient->sende("\1", 1);
					klient->sende(&status, 1);
				}
				break;
			case 9: // Server pausieren
				if (!adminId)
					errorZuKlient("Du musst dich einloggen.");
				else
				{
					klient->sende("\1", 1);
					char pause = 0;
					klient->getNachricht(&pause, 1);
					if (rs->zDB()->adminHatRecht(adminId, Admin_Recht::RSPausieren))
					{
						bool ok = 0;
						if (pause)
							ok = rs->serverPause();
						else
							ok = rs->serverFortsetzen();
						if (ok)
							klient->sende("\1", 1);
						else
						{
							Text* err = new Text();
							err->append(rs->getLetzterFehler());
							errorZuKlient(err->getText());
							err->release();
						}
					}
					else
					{
						if (pause)
							errorZuKlient("Du bist nicht berechtigt den Server zu pausieren.");
						else
							errorZuKlient("Du bist nicht berechtigt den Server fortzusetzen.");
					}
				}
				break;
			case 0xA: // maximale Anzahl der Clients setzen
				if (!adminId)
					errorZuKlient("Du musst dich einloggen.");
				else
				{
					klient->sende("\1", 1);
					int maxC = 0;
					klient->getNachricht((char*)&maxC, 4);
					if (rs->zDB()->adminHatRecht(adminId, Admin_Recht::RSMCChange))
					{
						if (rs->setMaxKlients(maxC))
							klient->sende("\1", 1);
						else
						{
							Text* err = new Text();
							err->append(rs->getLetzterFehler());
							errorZuKlient(err->getText());
							err->release();
						}
					}
					else
						errorZuKlient("Du bist nicht berechtigt die maximale Anzahl der Clients zu verändern.");
				}
				break;
			case 0xC: // klient absturtz
				if (1)
				{
					klient->sende("\1", 1);
					int klientId = 0;
					klient->getNachricht((char*)&klientId, 4);
					if (klientId && rs->absturzKlient(klientId))
						klient->sende("\1", 1);
					else
						klient->sende("\0", 1);
				}
				break;
			default:
				errorZuKlient("Unbekannte Nachricht!");
				break;
			}
			if (br)
				break;
			rs->addEmpfangen(klient->getDownloadBytes(1));
			rs->addGesendet(klient->getUploadBytes(1));
		}
	}
	rs->addEmpfangen(klient->getDownloadBytes(1));
	rs->addGesendet(klient->getUploadBytes(1));
	delete this;
}

void RSAKlient::errorZuKlient(const char* nachricht) const // sendet eine Fehlernachricht zum Klient
{
	klient->sende("\3", 1);
	char len = (char)textLength(nachricht);
	klient->sende(&len, 1);
	klient->sende(nachricht, len);
}


// Inhalt der RSKlasse aus RegisterServer.h
// Konstruktor 
RSKlient::RSKlient(SKlient* klient, RegisterServer* rs)
	: Thread()
{
	this->klient = klient;
	unsigned char key[20] = { 186, 186, 179, 126, 216, 207, 123, 154, 168, 149, 51, 221, 6, 193, 160, 141, 164, 126, 44, 242 };
	klient->setSendeKey((char*)key, 20);
	klient->setEmpfangKey((char*)key, 20);
	klientNummer = 0;
	this->rs = rs;
}

// Destruktor 
RSKlient::~RSKlient()
{
	klient->release();
	rs->release();
}

// nicht constant
void RSKlient::absturz()
{
	ende();
	klient->trenne();
	rs->zDB()->unregisterKlient(klientNummer, rs->getId());
}

void RSKlient::thread()
{
	while (1)
	{
		char c = 0;
		if (!klient->getNachrichtEncrypted(&c, 1))
			break;
		else
		{
			bool br = 0;
			switch (c)
			{
			case 1: // Klient identifikation
				klient->getNachrichtEncrypted((char*)&klientNummer, 4);
				if (!rs->zDB()->proveKlient(klientNummer, rs->getId()))
				{
					klientNummer = 0;
					errorZuKlient("Du bist nicht für diesen Server eingetragen");
				}
				else
				{
					Text* key = rs->zDB()->getKlientKey(klientNummer);
					if (!key)
						errorZuKlient("Es konnte kein Key ermittelt werden.");
					else
					{
						klient->sendeEncrypted("\1", 1);
						klient->setEmpfangKey(*key, key->getLength());
						klient->setSendeKey(*key, key->getLength());
						key->release();
					}
				}
				break;
			case 2: // Main / Erhaltung Server message
				if (1)
				{
					char befehl = 0;
					klient->getNachrichtEncrypted(&befehl, 1);
					switch (befehl)
					{
					case 2: // klient absturtz
						if (1)
						{
							int klientId = 0;
							klient->getNachrichtEncrypted((char*)&klientId, 4);
							if (klientId && rs->absturzKlient(klientId))
								klient->sendeEncrypted("\1", 1);
							else
								klient->sendeEncrypted("\0", 1);
						}
						break;
					default:
						errorZuKlient("Befehl nicht bekannt!");
						break;
					}
				}
				break;
			case 3: // Verbindungsende
				br = 1;
				klient->sendeEncrypted("\1", 1);
				break;
			case 4: // unregister Klient
				if (!klientNummer)
				{
					errorZuKlient("Du bist nicht Identifiziert.");
					break;
				}
				rs->zDB()->unregisterKlient(klientNummer, rs->getId());
				klient->sendeEncrypted("\1", 1);
				break;
			case 5: // Account erstellen
				if (1)
				{
					if (!klientNummer)
					{
						errorZuKlient("Du bist nicht Identifiziert.");
						break;
					}
					klient->sendeEncrypted("\1", 1);
					unsigned char len[4] = { 0, 0, 0, 0 };
					klient->getNachrichtEncrypted((char*)len, 4);
					char* acc_name = new char[len[0] + 1];
					acc_name[len[0]] = 0;
					klient->getNachrichtEncrypted(acc_name, len[0]);
					char* acc_pass = new char[len[1] + 1];
					acc_pass[len[1]] = 0;
					klient->getNachrichtEncrypted(acc_pass, len[1]);
					char* acc_geheim = new char[len[2] + 1];
					acc_geheim[len[2]] = 0;
					klient->getNachrichtEncrypted(acc_geheim, len[2]);
					char* acc_mail = new char[len[3] + 1];
					acc_mail[len[3]] = 0;
					klient->getNachrichtEncrypted(acc_mail, len[3]);
					unsigned short acc_geb_jahr = 0;
					klient->getNachrichtEncrypted((char*)&acc_geb_jahr, 2);
					char acc_geb_monat = 0;
					klient->getNachrichtEncrypted(&acc_geb_monat, 1);
					char acc_geb_tag = 0;
					klient->getNachrichtEncrypted(&acc_geb_tag, 1);
					int pres = rs->zDB()->proveNeuAccount(acc_name, acc_mail);
					if (!pres)
					{
						Text* gebDatum = new Text("");
						gebDatum->append((int)acc_geb_jahr);
						gebDatum->append("-");
						gebDatum->append((int)acc_geb_monat);
						gebDatum->append("-");
						gebDatum->append((int)acc_geb_tag);
						if (!rs->zDB()->neuAccount(acc_name, acc_pass, acc_geheim, acc_mail, gebDatum->getText(), rs->zIni()))
						{
							Text* err = new Text("Das Datum '");
							err->append(gebDatum->getText());
							err->append("' ist kein gültiges Datum.");
							errorZuKlient(err->getText());
							err->release();
						}
						else
							klient->sendeEncrypted("\1", 1);
						gebDatum->release();
					}
					else
					{
						if (pres == 1)
							errorZuKlient("Der Name wird bereits verwendet.");
						else if (pres == 2)
							errorZuKlient("Die E-Mail Adresse wird bereits verwendet.");
					}
					delete[]acc_name;
					delete[]acc_pass;
					delete[]acc_geheim;
					delete[]acc_mail;
				}
				break;
			case 6: // Account removen
				if (1)
				{
					if (!klientNummer)
					{
						errorZuKlient("Du bist nicht Identifiziert.");
						break;
					}
					klient->sendeEncrypted("\1", 1);
					unsigned char len[3];
					klient->getNachrichtEncrypted((char*)len, 3);
					char* acc_name = new char[len[0] + 1];
					acc_name[(int)len[0]] = 0;
					klient->getNachrichtEncrypted(acc_name, len[0]);
					char* acc_pass = new char[len[1] + 1];
					acc_pass[(int)len[1]] = 0;
					klient->getNachrichtEncrypted(acc_pass, len[1]);
					char* acc_geheim = new char[len[2] + 1];
					acc_geheim[(int)len[2]] = 0;
					klient->getNachrichtEncrypted(acc_geheim, len[2]);
					int res = rs->zDB()->removeAccount(acc_name, acc_pass, acc_geheim, rs->zIni());
					if (!res)
					{
						klient->sendeEncrypted("\1", 1);
						while (1)
						{
							char len = 0;
							klient->getNachrichtEncrypted(&len, 1);
							if (!len)
							{
								rs->zDB()->removeAccountAbbruch(acc_name);
								break;
							}
							if (len == -1)
								break;
							char* key = new char[len + 1];
							key[(int)len] = 0;
							klient->getNachrichtEncrypted(key, len);
							if (rs->zDB()->removeConfirmation(acc_name, key))
							{
								klient->sendeEncrypted("\1", 1);
								delete[]key;
								break;
							}
							else
								klient->sendeEncrypted("\0", 1);
							delete[]key;
						}
					}
					else if (res == 1)
						errorZuKlient("Der Account wurde nicht gefunden.");
					else if (res == 2)
						errorZuKlient("Falsches Passwort.");
					else if (res == 3)
						errorZuKlient("Falsches Geheimnis.");
					delete[]acc_name;
					delete[]acc_pass;
					delete[]acc_geheim;
				}
				break;
			case 7: // Passwort ändern
				if (1)
				{
					if (!klientNummer)
					{
						errorZuKlient("Du bist nicht Identifiziert.");
						break;
					}
					klient->sendeEncrypted("\1", 1);
					unsigned char len[4];
					klient->getNachrichtEncrypted((char*)len, 4);
					char* accName = new char[len[0] + 1];
					accName[len[0]] = 0;
					klient->getNachrichtEncrypted(accName, len[0]);
					char* accPasswort = new char[len[1] + 1];
					accPasswort[len[1]] = 0;
					klient->getNachrichtEncrypted(accPasswort, len[1]);
					char* neuPasswort = new char[len[2] + 1];
					neuPasswort[len[2]] = 0;
					klient->getNachrichtEncrypted(neuPasswort, len[2]);
					char* accGeheimnis = new char[len[3] + 1];
					accGeheimnis[len[3]] = 0;
					klient->getNachrichtEncrypted(accGeheimnis, len[3]);
					int res = rs->zDB()->passwortChange(accName, accPasswort, neuPasswort, accGeheimnis);
					if (!res)
						klient->sendeEncrypted("\1", 1);
					else if (res == 1)
						errorZuKlient("Account nicht gefunden.");
					else if (res == 2)
						errorZuKlient("Falsches Passwort.");
					else if (res == 3)
						errorZuKlient("Falsches Geheimnis.");
					delete[]accName;
					delete[]accPasswort;
					delete[]neuPasswort;
					delete[]accGeheimnis;
				}
				break;
			case 8: // E-Mail ändern
				if (1)
				{
					if (!klientNummer)
					{
						errorZuKlient("Du bist nicht Identifiziert.");
						break;
					}
					klient->sendeEncrypted("\1", 1);
					unsigned char len[4];
					klient->getNachrichtEncrypted((char*)len, 4);
					char* accName = new char[len[0] + 1];
					accName[len[0]] = 0;
					klient->getNachrichtEncrypted(accName, len[0]);
					char* accPasswort = new char[len[1] + 1];
					accPasswort[len[1]] = 0;
					klient->getNachrichtEncrypted(accPasswort, len[1]);
					char* accGeheimnis = new char[len[2] + 1];
					accGeheimnis[len[2]] = 0;
					klient->getNachrichtEncrypted(accGeheimnis, len[2]);
					char* neuEMail = new char[len[3] + 1];
					neuEMail[len[3]] = 0;
					klient->getNachrichtEncrypted(neuEMail, len[3]);
					int res = rs->zDB()->eMailChange(accName, accPasswort, accGeheimnis, neuEMail);
					if (!res)
						klient->sendeEncrypted("\1", 1);
					else if (res == 1)
						errorZuKlient("Account nicht gefunden.");
					else if (res == 2)
						errorZuKlient("Falsches Passwort.");
					else if (res == 3)
						errorZuKlient("Falsches Geheimnis.");
					else if (res == 4)
						errorZuKlient("Diese E-Mail Addresse wird bereits verwendet.");
					delete[]accName;
					delete[]accPasswort;
					delete[]accGeheimnis;
					delete[]neuEMail;
				}
				break;
			case 9: // Geheimnis Ändern
				if (1)
				{
					if (!klientNummer)
					{
						errorZuKlient("Du bist nicht Identifiziert.");
						break;
					}
					klient->sendeEncrypted("\1", 1);
					unsigned char len[4];
					klient->getNachrichtEncrypted((char*)len, 4);
					char* accName = new char[len[0] + 1];
					accName[len[0]] = 0;
					klient->getNachrichtEncrypted(accName, len[0]);
					char* accPasswort = new char[len[1] + 1];
					accPasswort[len[1]] = 0;
					klient->getNachrichtEncrypted(accPasswort, len[1]);
					char* accGeheimnis = new char[len[2] + 1];
					accGeheimnis[len[2]] = 0;
					klient->getNachrichtEncrypted(accGeheimnis, len[2]);
					char* neuGeheimnis = new char[len[3] + 1];
					neuGeheimnis[len[3]] = 0;
					klient->getNachrichtEncrypted(neuGeheimnis, len[3]);
					int res = rs->zDB()->geheimnisChange(accName, accPasswort, accGeheimnis, neuGeheimnis);
					if (!res)
						klient->sendeEncrypted("\1", 1);
					else if (res == 1)
						errorZuKlient("Account nicht gefunden.");
					else if (res == 2)
						errorZuKlient("Falsches Passwort.");
					else if (res == 3)
						errorZuKlient("Falsches Geheimnis.");
					delete[]accName;
					delete[]accPasswort;
					delete[]accGeheimnis;
					delete[]neuGeheimnis;
				}
				break;
			case 0xA: // Name Vergessen
				if (1)
				{
					if (!klientNummer)
					{
						errorZuKlient("Du bist nicht Identifiziert.");
						break;
					}
					klient->sendeEncrypted("\1", 1);
					unsigned char len[2];
					klient->getNachrichtEncrypted((char*)len, 2);
					char* accPasswort = new char[len[0] + 1];
					accPasswort[len[0]] = 0;
					klient->getNachrichtEncrypted(accPasswort, len[0]);
					char* accGeheimnis = new char[len[1] + 1];
					accGeheimnis[len[1]] = 0;
					klient->getNachrichtEncrypted(accGeheimnis, len[1]);
					if (rs->zDB()->nameVergessen(accPasswort, accGeheimnis, rs->zIni()))
						klient->sendeEncrypted("\1", 1);
					else
						errorZuKlient("Account nicht gefunden.");
					delete[]accPasswort;
					delete[]accGeheimnis;
				}
				break;
			case 0xB: // Passwort Vergessen
				if (1)
				{
					if (!klientNummer)
					{
						errorZuKlient("Du bist nicht Identifiziert.");
						break;
					}
					klient->sendeEncrypted("\1", 1);
					unsigned char len[2];
					klient->getNachrichtEncrypted((char*)len, 2);
					char* accName = new char[len[0] + 1];
					accName[len[0]] = 0;
					klient->getNachrichtEncrypted(accName, len[0]);
					char* accGeheimnis = new char[len[1] + 1];
					accGeheimnis[len[1]] = 0;
					klient->getNachrichtEncrypted(accGeheimnis, len[1]);
					if (rs->zDB()->passwortVergessen(accName, accGeheimnis, rs->zIni()))
						klient->sendeEncrypted("\1", 1);
					else
						errorZuKlient("Account nicht gefunden.");
					delete[]accName;
					delete[]accGeheimnis;
				}
				break;
			case 0xC: // Geheimnis Vergessen
				if (1)
				{
					if (!klientNummer)
					{
						errorZuKlient("Du bist nicht Identifiziert.");
						break;
					}
					klient->sendeEncrypted("\1", 1);
					unsigned char len[2];
					klient->getNachrichtEncrypted((char*)len, 2);
					char* accName = new char[len[0] + 1];
					accName[len[0]] = 0;
					klient->getNachrichtEncrypted(accName, len[0]);
					char* accPasswort = new char[len[1] + 1];
					accPasswort[len[1]] = 0;
					klient->getNachrichtEncrypted(accPasswort, len[1]);
					if (rs->zDB()->geheimnisVergessen(accName, accPasswort, rs->zIni()))
						klient->sendeEncrypted("\1", 1);
					else
						errorZuKlient("Account nicht gefunden.");
					delete[]accName;
					delete[]accPasswort;
				}
				break;
			case 0xD: // E-Mail Vergessen
				if (1)
				{
					if (!klientNummer)
					{
						errorZuKlient("Du bist nicht Identifiziert.");
						break;
					}
					klient->sendeEncrypted("\1", 1);
					unsigned char len[3];
					klient->getNachrichtEncrypted((char*)len, 3);
					char* accName = new char[len[0] + 1];
					accName[len[0]] = 0;
					klient->getNachrichtEncrypted(accName, len[0]);
					char* accPasswort = new char[len[1] + 1];
					accPasswort[len[1]] = 0;
					klient->getNachrichtEncrypted(accPasswort, len[1]);
					char* accGeheimnis = new char[len[2] + 1];
					accGeheimnis[len[2]] = 0;
					klient->getNachrichtEncrypted(accGeheimnis, len[2]);
					Text* eMail = rs->zDB()->eMailVergessen(accName, accPasswort, accGeheimnis);
					if (eMail)
					{
						klient->sendeEncrypted("\1", 1);
						unsigned char len = (unsigned char)eMail->getLength();
						klient->sendeEncrypted((char*)&len, 1);
						klient->sendeEncrypted(eMail->getText(), len);
						eMail->release();
					}
					else
						errorZuKlient("Account nicht gefunden.");
					delete[]accName;
					delete[]accPasswort;
					delete[]accGeheimnis;
				}
				break;
			case 0xF: // ping
				if (1)
				{
					if (!klientNummer)
					{
						errorZuKlient("Du bist nicht Identifiziert.");
						break;
					}
					klient->sendeEncrypted("\1", 1);
				}
				break;
			default:
				errorZuKlient("Unbekannte Nachricht!");
				break;
			}
			if (br)
				break;
		}
		rs->addEmpfangen(klient->getDownloadBytes(1));
		rs->addGesendet(klient->getUploadBytes(1));
	}
	rs->addEmpfangen(klient->getDownloadBytes(1));
	rs->addGesendet(klient->getUploadBytes(1));
	rs->removeKlient(this); // delete this
}

// constant
void RSKlient::errorZuKlient(const char* nachricht) const // sendet eine Fehlernachricht zum Klient
{
	klient->sendeEncrypted("\3", 1);
	char len = (char)textLength(nachricht);
	klient->sendeEncrypted(&len, 1);
	klient->sendeEncrypted(nachricht, len);
}

int RSKlient::getKlientNummer() const // gibt die KlientId zurück
{
	return klientNummer;
}