Prechádzať zdrojové kódy

Projektdateien hinzufügen.

Kolja Strohm 7 rokov pred
rodič
commit
dc0eb44eca
42 zmenil súbory, kde vykonal 9607 pridanie a 0 odobranie
  1. 30 0
      Information Server.sln
  2. 175 0
      Information Server/AccountHistorieDaten.cpp
  3. 98 0
      Information Server/AccountHistorieDaten.h
  4. 2062 0
      Information Server/Datenbank.cpp
  5. 101 0
      Information Server/Datenbank.h
  6. 194 0
      Information Server/Information Server.vcxproj
  7. 48 0
      Information Server/Information Server.vcxproj.filters
  8. 1693 0
      Information Server/InformationServer.cpp
  9. 107 0
      Information Server/InformationServer.h
  10. 178 0
      Information Server/KartenLeser.cpp
  11. 32 0
      Information Server/KartenLeser.h
  12. BIN
      Information Server/framework.dll
  13. BIN
      Information Server/libeay32.dll
  14. BIN
      Information Server/libintl-8.dll
  15. BIN
      Information Server/libpq.dll
  16. 55 0
      Information Server/main.cpp
  17. BIN
      Information Server/network.dll
  18. BIN
      Information Server/sql.dll
  19. BIN
      Information Server/ssleay32.dll
  20. 175 0
      InformationServer/AccountHistorieDaten.cpp
  21. 98 0
      InformationServer/AccountHistorieDaten.h
  22. 2061 0
      InformationServer/Datenbank.cpp
  23. 101 0
      InformationServer/Datenbank.h
  24. 1693 0
      InformationServer/InformationServer.cpp
  25. 107 0
      InformationServer/InformationServer.h
  26. 75 0
      InformationServer/InformationServer.vcxproj
  27. 42 0
      InformationServer/InformationServer.vcxproj.filters
  28. 178 0
      InformationServer/KartenLeser.cpp
  29. 32 0
      InformationServer/KartenLeser.h
  30. 55 0
      InformationServer/main.cpp
  31. BIN
      InformationServer/readme/images/ArchOptions.gif
  32. BIN
      InformationServer/readme/images/ChangeRemote.gif
  33. BIN
      InformationServer/readme/images/ManageConnections.gif
  34. BIN
      InformationServer/readme/images/OutputTypes.gif
  35. BIN
      InformationServer/readme/images/debuggerexport.png
  36. BIN
      InformationServer/readme/images/firstconnection.png
  37. BIN
      InformationServer/readme/images/linker.png
  38. BIN
      InformationServer/readme/images/postbuild.png
  39. 85 0
      InformationServer/readme/readme.html
  40. 119 0
      InformationServer/readme/stylesheet.css
  41. 2 0
      build.bat
  42. 11 0
      data/isInit.ini

+ 30 - 0
Information Server.sln

@@ -0,0 +1,30 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26020.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InformationServer", "InformationServer\InformationServer.vcxproj", "{58B97166-96BD-4FE9-A2BA-5C2C5F2F89AF}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|ARM = Debug|ARM
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|ARM = Release|ARM
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{58B97166-96BD-4FE9-A2BA-5C2C5F2F89AF}.Debug|ARM.ActiveCfg = Debug|x64
+		{58B97166-96BD-4FE9-A2BA-5C2C5F2F89AF}.Debug|x64.ActiveCfg = Debug|x64
+		{58B97166-96BD-4FE9-A2BA-5C2C5F2F89AF}.Debug|x64.Build.0 = Debug|x64
+		{58B97166-96BD-4FE9-A2BA-5C2C5F2F89AF}.Debug|x86.ActiveCfg = Debug|x64
+		{58B97166-96BD-4FE9-A2BA-5C2C5F2F89AF}.Release|ARM.ActiveCfg = Release|x64
+		{58B97166-96BD-4FE9-A2BA-5C2C5F2F89AF}.Release|x64.ActiveCfg = Release|x64
+		{58B97166-96BD-4FE9-A2BA-5C2C5F2F89AF}.Release|x64.Build.0 = Release|x64
+		{58B97166-96BD-4FE9-A2BA-5C2C5F2F89AF}.Release|x86.ActiveCfg = Release|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 175 - 0
Information Server/AccountHistorieDaten.cpp

@@ -0,0 +1,175 @@
+#include "AccountHistorieDaten.h"
+
+// Inhalt der AHSpielSpielerDaten Struktur aus AccountHistorieDaten.h
+// Konstruktor
+AHSpielSpielerDaten::AHSpielSpielerDaten()
+	: name( new Text() ),
+	status( new Text() ),
+	ref( 1 )
+{
+}
+
+// Destruktor
+AHSpielSpielerDaten::~AHSpielSpielerDaten()
+{
+	name->release();
+	status->release();
+}
+
+// Reference Counting
+AHSpielSpielerDaten *AHSpielSpielerDaten::getThis()
+{
+	ref++;
+	return this;
+}
+
+AHSpielSpielerDaten *AHSpielSpielerDaten::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der AHSpielTeamDaten Struktur aus AccountHistorieDaten.h
+// Konstruktor
+AHSpielTeamDaten::AHSpielTeamDaten()
+	: name( new Text() ),
+	status( new Text() ),
+	spieler( new RCArray< AHSpielSpielerDaten >() ),
+	ref( 1 )
+{
+}
+
+// Destruktor
+AHSpielTeamDaten::~AHSpielTeamDaten()
+{
+	name->release();
+	status->release();
+	spieler->release();
+}
+
+// Reference Counting
+AHSpielTeamDaten *AHSpielTeamDaten::getThis()
+{
+	ref++;
+	return this;
+}
+
+AHSpielTeamDaten *AHSpielTeamDaten::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der AHSpielDaten Struktur aus AccountHistorieDaten.h
+// Konstruktor
+AHSpielDaten::AHSpielDaten()
+	: spiel( new Text() ),
+	karte( new Text() ),
+	datum( new Text() ),
+	status( new Text() ),
+	dauer( new Text() ),
+	spielStatus( new Text() ),
+	gewinner( new Text() ),
+	teams( new RCArray< AHSpielTeamDaten >() ),
+	ref( 1 )
+{
+}
+
+// Destruktor
+AHSpielDaten::~AHSpielDaten()
+{
+	spiel->release();
+	karte->release();
+	datum->release();
+	status->release();
+	dauer->release();
+	spielStatus->release();
+	gewinner->release();
+	teams->release();
+}
+
+// Reference Counting
+AHSpielDaten *AHSpielDaten::getThis()
+{
+	ref++;
+	return this;
+}
+
+AHSpielDaten *AHSpielDaten::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der AHDaten Struktur aus AccountHistorieDaten.h
+// Konstruktor
+AHDaten::AHDaten()
+	: spiele( new RCArray< AHSpielDaten >() ),
+	ref( 1 )
+{
+}
+
+// Destruktor
+AHDaten::~AHDaten()
+{
+	spiele->release();
+}
+
+// Reference Counting
+AHDaten *AHDaten::getThis()
+{
+	ref++;
+	return this;
+}
+
+AHDaten *AHDaten::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der SpielerTeamStruktur Struktur aus Strukturen.h
+SpielerTeamStruktur::SpielerTeamStruktur()
+{
+	spielerAnzahl = 0;
+	teamAnzahl = 0;
+	spielerFarbe = new Array< int >();
+	teamFarbe = new Array< int >();
+	teamName = new RCArray< Text >();
+	teamGröße = new Array< int >();
+	ref = 1;
+}
+
+SpielerTeamStruktur::~SpielerTeamStruktur()
+{
+	spielerFarbe->release();
+	teamFarbe->release();
+	teamName->release();
+	teamGröße->release();
+}
+
+SpielerTeamStruktur *SpielerTeamStruktur::getThis()
+{
+	ref++;
+	return this;
+}
+
+SpielerTeamStruktur *SpielerTeamStruktur::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 98 - 0
Information Server/AccountHistorieDaten.h

@@ -0,0 +1,98 @@
+#ifndef AccountHistorieDaten_H
+#define AccountHistorieDaten_H
+
+#include <Array.h>
+#include <Text.h>
+
+using namespace Framework;
+
+struct AHSpielSpielerDaten
+{
+	Text *name;
+	int punkte;
+	Text *status;
+	int farbe;
+	int ref;
+
+	// Konstruktor
+	AHSpielSpielerDaten();
+	// Destruktor
+	~AHSpielSpielerDaten();
+	// Reference Counting
+	AHSpielSpielerDaten *getThis();
+	AHSpielSpielerDaten *release();
+};
+
+struct AHSpielTeamDaten
+{
+	int id;
+	Text *name;
+	int sAnzahl;
+	Text *status;
+	int farbe;
+	RCArray< AHSpielSpielerDaten > *spieler;
+	int ref;
+
+	// Konstruktor
+	AHSpielTeamDaten();
+	// Destruktor
+	~AHSpielTeamDaten();
+	// Reference Counting
+	AHSpielTeamDaten *getThis();
+	AHSpielTeamDaten *release();
+};
+
+struct AHSpielDaten
+{
+	int id;
+	int karteId;
+	Text *spiel;
+	Text *karte;
+	Text *datum;
+	Text *status;
+	Text *dauer;
+	Text *spielStatus;
+	Text *gewinner;
+	int sAnzahl;
+	RCArray< AHSpielTeamDaten > *teams;
+	int ref;
+
+	// Konstruktor
+	AHSpielDaten();
+	// Destruktor
+	~AHSpielDaten();
+	// Reference Counting
+	AHSpielDaten *getThis();
+	AHSpielDaten *release();
+};
+
+struct AHDaten
+{
+	RCArray< AHSpielDaten > *spiele;
+	int ref;
+
+	// Konstruktor
+	AHDaten();
+	// Destruktor
+	~AHDaten();
+	// Reference Counting
+	AHDaten *getThis();
+	AHDaten *release();
+};
+
+struct SpielerTeamStruktur
+{
+	SpielerTeamStruktur();
+	~SpielerTeamStruktur();
+	int spielerAnzahl;
+	int teamAnzahl;
+	Array< int > *spielerFarbe;
+	Array< int > *teamFarbe;
+	RCArray< Text > *teamName;
+	Array< int > *teamGröße;
+	int ref;
+	SpielerTeamStruktur *getThis();
+	SpielerTeamStruktur *release();
+};
+
+#endif

+ 2062 - 0
Information Server/Datenbank.cpp

@@ -0,0 +1,2062 @@
+#include "Datenbank.h"
+#include <Zeit.h>
+#include "AccountHistorieDaten.h"
+#include "KartenLeser.h"
+
+// Inhalt der LSDatenbank Klasse aus Datenbank.h
+// Konstruktor
+ISDatenbank::ISDatenbank( InitDatei *zIni )
+{
+	if( !zIni->wertExistiert( "DBBenutzer" ) )
+		zIni->addWert( "DBBenutzer", "informationserveru" );
+	if( !zIni->wertExistiert( "DBPasswort" ) )
+		zIni->addWert( "DBPasswort", "LTInformationServerPW" );
+	if( !zIni->wertExistiert( "DBName" ) )
+		zIni->addWert( "DBName", "lenck_tech_db" );
+	if( !zIni->wertExistiert( "DBIP" ) )
+		zIni->addWert( "DBIP", "127.0.0.1" );
+	if( !zIni->wertExistiert( "DBPort" ) )
+		zIni->addWert( "DBPort", "5432" );
+	datenbank = new Datenbank( zIni->zWert( "DBBenutzer" )->getText(), zIni->zWert( "DBPasswort" )->getText(),
+							   zIni->zWert( "DBName" )->getText(), zIni->zWert( "DBIP" )->getText(),
+							   (unsigned short)TextZuInt( zIni->zWert( "DBPort" )->getText(), 10 ) );
+	InitializeCriticalSection( &cs );
+	ref = 1;
+}
+
+// Destruktor
+ISDatenbank::~ISDatenbank()
+{
+	datenbank->release();
+	DeleteCriticalSection( &cs );
+}
+
+// nicht constant
+void ISDatenbank::lock()
+{
+	EnterCriticalSection( &cs );
+}
+
+void ISDatenbank::unlock()
+{
+	LeaveCriticalSection( &cs );
+}
+
+int ISDatenbank::istAdministrator( const char *name, const char *passwort )
+{
+	Text *befehl = new Text( "SELECT id FROM benutzer WHERE name = '" );
+	befehl->anhängen( name );
+	befehl->anhängen( "' AND passwort = '" );
+	befehl->anhängen( passwort );
+	befehl->anhängen( "'" );
+	lock();
+	datenbank->befehl( befehl->getText() );
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	int ret = 0;
+	if( res.zeilenAnzahl > 0 )
+		ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+bool ISDatenbank::adminHatRecht( int id, int recht )
+{
+	Text *befehl = new Text( "SELECT * FROM benutzer_rechte WHERE benutzer_id = " );
+	befehl->anhängen( id );
+	befehl->anhängen( " AND rechte_id = " );
+	befehl->anhängen( recht );
+	lock();
+	datenbank->befehl( befehl->getText() );
+	int ret = datenbank->getZeilenAnzahl();
+	unlock();
+	befehl->release();
+	return ret != 0;
+}
+
+bool ISDatenbank::prüfKlient( int num, int sNum )
+{
+	Text *befehl = new Text( "SELECT * FROM server_information_clients WHERE server_information_id = " );
+	befehl->anhängen( sNum );
+	befehl->anhängen( " AND client_id = " );
+	befehl->anhängen( num );
+	lock();
+	datenbank->befehl( befehl->getText() );
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	bool ret = 0;
+	if( res.zeilenAnzahl == 1 )
+		ret = 1;
+	res.destroy();
+	return ret;
+}
+
+Text *ISDatenbank::getKlientSchlüssel( int cId )
+{
+	lock();
+	if( !datenbank->befehl( Text( "SELECT schluessel FROM clients WHERE id = " ) += cId ) )
+	{
+		unlock();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+void ISDatenbank::unregisterKlient( int num, int sNum )
+{
+	Text *befehl = new Text( "DELETE FROM server_information_clients WHERE client_id = " );
+	befehl->anhängen( num );
+	befehl->anhängen( " AND server_information_id = " );
+	befehl->anhängen( sNum );
+	lock();
+	datenbank->befehl( befehl->getText() );
+	int za = datenbank->getZeilenAnzahl();
+	unlock();
+	if( za == 1 )
+	{
+		befehl->setText( "UPDATE server_information SET clients = clients - 1 WHERE id = " );
+		befehl->anhängen( sNum );
+		lock();
+		datenbank->befehl( befehl->getText() );
+		unlock();
+	}
+	befehl->release();
+}
+
+bool ISDatenbank::serverAnmelden( InitDatei *zIni )
+{
+	if( !zIni->wertExistiert( "ServerId" ) )
+		zIni->addWert( "ServerId", "0" );
+	if( !zIni->wertExistiert( "ServerName" ) )
+		zIni->addWert( "ServerName", "Name" );
+	if( !zIni->wertExistiert( "ServerPort" ) )
+		zIni->addWert( "ServerPort", "49144" );
+	if( !zIni->wertExistiert( "ServerIP" ) )
+		zIni->addWert( "ServerIP", "127.0.0.1" );
+	if( !zIni->wertExistiert( "AdminServerPort" ) )
+		zIni->addWert( "AdminServerPort", "49143" );
+	if( !zIni->wertExistiert( "Aktiv" ) )
+		zIni->addWert( "Aktiv", "FALSE" );
+	if( !zIni->wertExistiert( "MaxClients" ) )
+		zIni->addWert( "MaxClients", "50" );
+	bool insert = 0;
+	int id = *zIni->zWert( "ServerId" );
+	if( id )
+	{
+		lock();
+		if( !datenbank->befehl( Text( "SELECT id FROM server_information WHERE id = " ) += id ) )
+		{
+			unlock();
+			return 0;
+		}
+		int anz = datenbank->getZeilenAnzahl();
+		unlock();
+		insert = anz == 0;
+		if( !insert )
+		{
+			lock();
+			if( !datenbank->befehl( Text( "SELECT id FROM server_information WHERE server_status_id = 1 AND id = " ) += id ) )
+			{
+				unlock();
+				return 0;
+			}
+			int anz = datenbank->getZeilenAnzahl();
+			unlock();
+			if( !anz ) // Server läuft bereits
+				return 0;
+		}
+	}
+	if( insert || !id )
+	{ // Neuer Eintrag in Tabelle server_information
+		Text *befehl = new Text( "INSERT INTO server_information( " );
+		if( id )
+			*befehl += "id, ";
+		*befehl += "name, ip, port, admin_port, server_status_id, max_clients ) VALUES( ";
+		if( id )
+		{
+			*befehl += id;
+			*befehl += ", ";
+		}
+		*befehl += "'";
+		*befehl += zIni->zWert( "ServerName" )->getText();
+		*befehl += "', '";
+		*befehl += zIni->zWert( "ServerIP" )->getText();
+		*befehl += "', ";
+		*befehl += zIni->zWert( "ServerPort" )->getText();
+		*befehl += ", ";
+		*befehl += zIni->zWert( "AdminServerPort" )->getText();
+		*befehl += ", 1, ";
+		*befehl += zIni->zWert( "MaxClients" )->getText();
+		*befehl += " ) RETURNING id";
+		lock();
+		if( !datenbank->befehl( *befehl ) )
+		{
+			unlock();
+			befehl->release();
+			return 0;
+		}
+		Result res = datenbank->getResult();
+		unlock();
+		befehl->release();
+		if( !res.zeilenAnzahl )
+		{
+			res.destroy();
+			return 0;
+		}
+		zIni->setWert( "ServerId", res.values[ 0 ] );
+		return 1;
+	}
+	else
+	{ // Alten Eintrag aus Tabelle server_information ändern
+		Text *befehl = new Text( "UPDATE server_information SET name = '" );
+		*befehl += zIni->zWert( "ServerName" )->getText();
+		*befehl += "', port = ";
+		*befehl += zIni->zWert( "ServerPort" )->getText();
+		*befehl += ", ip = '";
+		*befehl += zIni->zWert( "ServerIP" )->getText();
+		*befehl += "', max_clients = ";
+		*befehl += zIni->zWert( "MaxClients" )->getText();
+		*befehl += ", admin_port = ";
+		*befehl += zIni->zWert( "AdminServerPort" )->getText();
+		*befehl += " WHERE id = ";
+		*befehl += id;
+		lock();
+		bool ret = datenbank->befehl( *befehl );
+		unlock();
+		befehl->release();
+		return ret;
+	}
+}
+
+bool ISDatenbank::setServerStatus( int id, int status )
+{
+	Text *befehl = new Text( "UPDATE server_information SET server_status_id = " );
+	*befehl += status;
+	*befehl += "WHERE id = ";
+	*befehl += id;
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	bool ret = datenbank->getZeilenAnzahl() != 0;
+	unlock();
+	befehl->release();
+	return ret;
+}
+
+bool ISDatenbank::setMaxClients( int id, int maxC )
+{
+	Text *befehl = new Text( "UPDATE server_information SET max_clients = " );
+	befehl->anhängen( maxC );
+	befehl->anhängen( " WHERE id = " );
+	befehl->anhängen( id );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	bool ret = datenbank->getZeilenAnzahl() > 0;
+	unlock();
+	befehl->release();
+	return ret;
+}
+
+int ISDatenbank::getAdminPort( int id )
+{
+	Text *befehl = new Text( "SELECT admin_port FROM server_information WHERE id = " );
+	befehl->anhängen( id );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+bool ISDatenbank::serverIstNichtPausiert( int id )
+{
+	Text *befehl = new Text( "SELECT server_status_id FROM server_information WHERE id = " );
+	befehl->anhängen( id );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	bool ret = (int)res.values[ 0 ] == 3;
+	res.destroy();
+	return ret;
+}
+
+Text *ISDatenbank::getInformationsText( char *typ )
+{
+	lock();
+	if( !datenbank->befehl( "SELECT text, typ FROM info_text ORDER BY insert_datum DESC LIMIT 1" ) )
+	{
+		unlock();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		*typ = 0;
+		return 0;
+	}
+	*typ = (char)TextZuInt( res.values[ 1 ].getText(), 10 );
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+bool ISDatenbank::istSpielErlaubt( int spielId )
+{
+	Text *befehl = new Text( "SELECT erlaubt FROM spiel_art WHERE id = " );
+	befehl->anhängen( spielId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	bool ret = 0;
+	if( res.zeilenAnzahl > 0 && res.values[ 0 ].istGleich( "t" ) )
+		ret = 1;
+	res.destroy();
+	return ret;
+}
+
+bool ISDatenbank::istKarteErlaubt( int karteId )
+{
+	Text *befehl = new Text( "SELECT erlaubt FROM karte WHERE id = " );
+	befehl->anhängen( karteId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	bool ret = 0;
+	if( res.zeilenAnzahl > 0 && res.values[ 0 ].istGleich( "t" ) )
+		ret = 1;
+	res.destroy();
+	return ret;
+}
+
+Text *ISDatenbank::getAccountRufName( int accountId )
+{
+	Text *befehl = new Text( "SELECT ruf_name FROM account WHERE id = " );
+	befehl->anhängen( accountId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getAccountId( char *rufName )
+{
+	Text *befehl = new Text( "SELECT id FROM account WHERE ruf_name = '" );
+	befehl->anhängen( rufName );
+	befehl->anhängen( "' LIMIT 1" );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+Array< int > *ISDatenbank::getAccountSpielStatistik( int accountId, int spielId )
+{
+	Text *befehl = new Text( "SELECT gespielt, gewonnen, verloren, punkte, bw0, bw1, bw2, bw3, bw4, bw5 FROM spiel_statistik WHERE account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " AND spiel_art_id = " );
+	befehl->anhängen( spielId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	Array< int > *ret = new Array< int >();
+	if( !res.zeilenAnzahl )
+	{
+		for( int i = 0; i < res.feldAnzahl; i++ )
+			ret->add( 0, i );
+		res.destroy();
+		return ret;
+	}
+	for( int i = 0; i < res.feldAnzahl; i++ )
+		ret->add( TextZuInt( res.values[ i ].getText(), 10 ), i );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getAccountKarteSpiele( int accountId, int karteId )
+{
+	Text *befehl = new Text( "SELECT count( a.id ) FROM spiel a, spiel_spieler b WHERE a.id = b.spiel_id AND b.account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " AND a.karte_id = " );
+	befehl->anhängen( karteId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = res.values[ 0 ];
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getAccountKarteSpieleGewonnen( int accountId, int karteId )
+{
+	Text *befehl = new Text( "SELECT count( a.id ) FROM spiel a, spiel_spieler b WHERE a.id = b.spiel_id "
+							 "AND b.spiel_spieler_status_id = 2 AND b.account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " AND a.karte_id = " );
+	befehl->anhängen( karteId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = res.values[ 0 ];
+	res.destroy();
+	return ret;
+}
+
+Text *ISDatenbank::getKarteName( int karteId )
+{
+	Text *befehl = new Text( "SELECT name FROM karte WHERE id = " );
+	befehl->anhängen( karteId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+Text *ISDatenbank::getSpielName( int spielId )
+{
+	Text *befehl = new Text( "SELECT name FROM spiel_art WHERE id = " );
+	befehl->anhängen( spielId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+Text *ISDatenbank::getChatroomName( int chatroomId )
+{
+	Text *befehl = new Text( "SELECT name FROM chatroom WHERE id = " );
+	befehl->anhängen( chatroomId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getChatroomId( char *name )
+{
+	Text *befehl = new Text( "SELECT id FROM chatroom WHERE name = '" );
+	befehl->anhängen( name );
+	befehl->anhängen( "' LIMIT 1" );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getSpielId( int karteId )
+{
+	Text *befehl = new Text( "SELECT spiel_art_id FROM karte WHERE id = " );
+	befehl->anhängen( karteId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getSpielId( char *name )
+{
+	Text *befehl = new Text( "SELECT id FROM spiel_art WHERE name = '" );
+	befehl->anhängen( name );
+	befehl->anhängen( "'" );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getKarteId( char *name )
+{
+	Text *befehl = new Text( "SELECT id FROM karte WHERE name = '" );
+	befehl->anhängen( name );
+	befehl->anhängen( "'" );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getGruppenKarteId( int gruppeId )
+{
+	Text *befehl = new Text( "SELECT karte_id FROM gruppe WHERE id = " );
+	befehl->anhängen( gruppeId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getGruppeAdminId( int gruppeId )
+{
+	Text *befehl = new Text( "SELECT admin_account_id FROM gruppe WHERE id = " );
+	befehl->anhängen( gruppeId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getSpielerPunkte( int spielId, int accountId )
+{
+	Text *befehl = new Text( "SELECT sum( b.punkte ) FROM spiel a, spiel_spieler b, karte c WHERE a.karte_id = c.id "
+							 "AND a.spiel_status_id = 5 AND c.spiel_art_id = " );
+	befehl->anhängen( spielId );
+	befehl->anhängen( " AND b.spiel_id = a.id AND b.account_id = " );
+	befehl->anhängen( accountId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+Array< int > *ISDatenbank::getAccountSpielArtListe( int cId )
+{
+	Text *befehl = new Text( "SELECT a.spiel_art_id FROM spiel_art_account a, account_clients b "
+							 "WHERE a.account_id = b.account_id AND a.end_dat IS NULL AND b.client_id = " );
+	befehl->anhängen( cId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	Array< int > *ret = new Array< int >();
+	for( int i = 0; i < res.zeilenAnzahl; i++ )
+		ret->add( TextZuInt( res.values[ i ].getText(), 10 ) );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getNeusteSpielVersion( int sId )
+{
+	Text *befehl = new Text( "SELECT a.version FROM datei_gruppe a, spiel_art b WHERE a.id = b.datei_gruppe_id AND b.id = " );
+	befehl->anhängen( sId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getKupfer( int cId )
+{
+	Text *befehl = new Text( "SELECT a.kupfer FROM account a, account_clients b WHERE a.id = b.account_id AND b.client_id = " );
+	befehl->anhängen( cId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getDateiGruppeVonSpiel( int sId )
+{
+	Text *befehl = new Text( "SELECT datei_gruppe_id FROM spiel_art WHERE id = " );
+	befehl->anhängen( sId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+Text *ISDatenbank::getDateiGruppePfad( int dgId )
+{
+	Text *befehl = new Text( "SELECT pfad FROM datei_gruppe WHERE id = " );
+	befehl->anhängen( dgId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+Array< int > *ISDatenbank::getAccountKarteListe( int cId, int sId )
+{
+	Text *befehl = new Text( "SELECT a.karte_id FROM karte_account a, account_clients b, karte c "
+							 "WHERE c.id = a.karte_id AND a.account_id = b.account_id AND a.end_dat IS NULL AND b.client_id = " );
+	befehl->anhängen( cId );
+	befehl->anhängen( " AND c.spiel_art_id = " );
+	befehl->anhängen( sId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	Array< int > *ret = new Array< int >();
+	for( int i = 0; i < res.zeilenAnzahl; i++ )
+		ret->add( TextZuInt( res.values[ i ].getText(), 10 ) );
+	res.destroy();
+	return ret;
+}
+
+bool ISDatenbank::hatAccountKarte( int account, int karte )
+{
+	Text *befehl = new Text( "SELECT karte_id FROM karte_account WHERE end_dat IS NULL AND karte_id = " );
+	befehl->anhängen( karte );
+	befehl->anhängen( " AND account_id = " );
+	befehl->anhängen( account );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	bool ret = datenbank->getZeilenAnzahl() != 0;
+	unlock();
+	befehl->release();
+	return ret;
+}
+
+bool ISDatenbank::hatAccountSpiel( int account, int spiel )
+{
+	Text *befehl = new Text( "SELECT spiel_art_id FROM spiel_art_account WHERE end_dat IS NULL AND spiel_art_id = " );
+	befehl->anhängen( spiel );
+	befehl->anhängen( " AND account_id = " );
+	befehl->anhängen( account );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	bool ret = datenbank->getZeilenAnzahl() != 0;
+	unlock();
+	befehl->release();
+	return ret;
+}
+
+Array< int > *ISDatenbank::getAccountKarteGespieltListe( int accountId, int spielArt )
+{
+	Text *befehl = new Text( "SELECT distinct( c.id ) FROM spiel a, spiel_spieler b, karte c WHERE "
+							 "a.karte_id = c.id AND b.spiel_id = a.id AND b.account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " AND c.spiel_art_id = " );
+	befehl->anhängen( spielArt );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	Array< int > *ret = new Array< int >();
+	for( int i = 0; i < res.zeilenAnzahl; i++ )
+		ret->set( res.values[ i ], i );
+	res.destroy();
+	return ret;
+}
+
+Array< int > *ISDatenbank::getAccountSpielGespieltListe( int accountId )
+{
+	Text *befehl = new Text( "SELECT distinct( c.spiel_art_id ) FROM spiel a, spiel_spieler b, karte c WHERE "
+							 "a.karte_id = c.id AND b.spiel_id = a.id AND b.account_id = " );
+	befehl->anhängen( accountId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	Array< int > *ret = new Array< int >();
+	for( int i = 0; i < res.zeilenAnzahl; i++ )
+		ret->set( res.values[ i ], i );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getDateiGruppeVonPfad( char *pfad )
+{
+	Text *befehl = new Text( "SELECT id FROM datei_gruppe WHERE pfad = '" );
+	befehl->anhängen( pfad );
+	befehl->anhängen( "'" );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getNeusteDateiGruppe( int dg )
+{
+	Text *befehl = new Text( "SELECT version FROM datei_gruppe WHERE id = " );
+	befehl->anhängen( dg );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+bool ISDatenbank::getGruppeSpielerHinzufügen( int gruppeId )
+{
+	Text *befehl = new Text( "SELECT spiel_starten FROM gruppe WHERE id = " );
+	befehl->anhängen( gruppeId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	bool ret = res.values[ 0 ].istGleich( "f" );
+	res.destroy();
+	return ret;
+}
+
+Result ISDatenbank::getSpielerListe( char *suche, int *seite, int *maxSeite, int sortStalte, bool rückwärts )
+{
+	Text *befehl = new Text( "SELECT count( a.id ) FROM account a, "
+							 "( SELECT a.id, max( b.datum ) "
+							 "  FROM account a LEFT JOIN "
+							 "  ( SELECT g.spiel_art_id, i.account_id, max( h.beginn_datum ) "
+							 "    FROM karte g, spiel h, spiel_spieler i "
+							 "    WHERE i.spiel_id = h.id AND h.karte_id = g.id "
+							 "    GROUP BY g.spiel_art_id, i.account_id ) f ON a.id = f.account_id "
+							 "  LEFT JOIN account_online b ON b.account_id = a.id "
+							 "  LEFT JOIN spiel_statistik e ON e.account_id = a.id "
+							 "  LEFT JOIN spiel_art c ON c.id = f.spiel_art_id "
+							 "  LEFT JOIN karte d ON c.id = d.spiel_art_id "
+							 "  WHERE a.name LIKE '" );
+	befehl->anhängen( suche );
+	befehl->anhängen( "' AND d.spiel_art_id = c.id "
+					  "  AND e.spiel_art_id = f.spiel_art_id "
+					  "  GROUP BY a.id ) b "
+					  "WHERE a.id = b.id" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	int einträge = res.values[ 0 ];
+	res.destroy();
+	*maxSeite = einträge / 21;
+	if( einträge % 21 )
+		( *maxSeite )++;
+	if( *seite > *maxSeite )
+		*seite = *maxSeite;
+	if( !( *seite ) )
+	{
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	befehl->setText( "SELECT a.id, a.ruf_name, max( b.datum ), c.name, d.name, e.punkte "
+					 "FROM account a LEFT JOIN "
+					 "( SELECT g.spiel_art_id, i.account_id, max( h.beginn_datum ) "
+					 "  FROM karte g, spiel h, spiel_spieler i "
+					 "  WHERE i.spiel_id = h.id AND h.karte_id = g.id "
+					 "  GROUP BY g.spiel_art_id, i.account_id ) f ON a.id = f.account_id "
+					 "LEFT JOIN account_online b ON b.account_id = a.id "
+					 "LEFT JOIN spiel_statistik e ON e.account_id = a.id "
+					 "LEFT JOIN spiel_art c ON c.id = f.spiel_art_id "
+					 "LEFT JOIN karte d ON c.id = d.spiel_art_id "
+					 "WHERE a.name LIKE '" );
+	befehl->anhängen( suche );
+	befehl->anhängen( "' AND ( d.spiel_art_id = c.id "
+					  "AND e.spiel_art_id = f.spiel_art_id ) "
+					  "OR d.spiel_art_id IS NULL "
+					  "GROUP BY a.id, a.ruf_name, c.name, d.name, e.punkte ORDER BY " );
+	befehl->anhängen( sortStalte + 2 );
+	if( rückwärts )
+		befehl->anhängen( " DESC" );
+	befehl->anhängen( " OFFSET " );
+	befehl->anhängen( ( ( *seite ) - 1 ) * 21 );
+	befehl->anhängen( " LIMIT 21" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	return res;
+}
+
+bool ISDatenbank::getSpielerAktivität( int accountId, RCArray< Text > *datum, Array< double > *stOnline, Array< double > *stGespielt,
+									   Array< int > *anzSpiele, Array< int > *anzGewonnen )
+{
+	Datum *beg = getDatum();
+	Datum *end = getDatum();
+	beg->minusTag( 29 );
+	end->minusTag( 29 );
+	end->plusTag( 1 );
+	for( int i = 0; i < 30; i++ )
+	{ // 30 Tage Rückblick
+		datum->set( beg->getDatum( "d-m-y" ), i );
+		Text *b = beg->getDatum( "y-m-d" );
+		Text *e = end->getDatum( "y-m-d" );
+		stOnline->set( getOnlineSeconds( accountId, *b, *e ) / ( 60.0 * 60 ), i );
+		stGespielt->set( getGespieltSeconds( accountId, *b, *e ) / ( 60.0 * 60 ), i );
+		anzSpiele->set( getGespieltSpiele( accountId, *b, *e ), i );
+		anzGewonnen->set( getGewonnenSpiele( accountId, *b, *e ), i );
+		b->release();
+		e->release();
+		beg->plusTag( 1 );
+		end->plusTag( 1 );
+	}
+	return 1;
+}
+
+int ISDatenbank::getOnlineSeconds( int accountId, char *beg, char *end )
+{
+	int sec = 0;
+	Text *befehl = new Text( "SELECT date_part( 'epoch', ( SELECT sum( now() - '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' ) FROM account_online WHERE datum < '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND now() < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND now() > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND end_datum IS NULL AND account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( now() - datum ) FROM account_online WHERE datum > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND now() < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND end_datum IS NULL AND account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' - datum ) FROM account_online WHERE datum > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND datum < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND now() > '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND end_datum IS NULL AND account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "'::TIMESTAMP WITH TIME ZONE - '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' ) FROM account_online WHERE datum < '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND now() > '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND end_datum IS NULL AND account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( end_datum - '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' ) FROM account_online WHERE datum < '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND end_datum < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND end_datum > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( end_datum - datum ) FROM account_online WHERE datum > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND end_datum < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' - datum ) FROM account_online WHERE datum > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND datum < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND end_datum > '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "'::TIMESTAMP WITH TIME ZONE - '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' ) FROM account_online WHERE datum < '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND end_datum > '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->release();
+	return sec;
+}
+
+int ISDatenbank::getGespieltSeconds( int accountId, char *beg, char *end )
+{
+	int sec = 0;
+	Text *befehl = new Text( "SELECT date_part( 'epoch', ( SELECT sum( now() - '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum < '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND now() < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND now() > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND a.end_datum IS NULL AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( now() - a.beginn_datum ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND now() < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND a.end_datum IS NULL AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' - a.beginn_datum ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND a.beginn_datum < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND now() > '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND a.end_datum IS NULL AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "'::TIMESTAMP WITH TIME ZONE - '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum < '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND now() > '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND a.end_datum IS NULL AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( a.end_datum - '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum < '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND a.end_datum < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND a.end_datum > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( a.end_datum - a.beginn_datum ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND a.end_datum < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' - a.beginn_datum ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND a.beginn_datum < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND a.end_datum > '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND a.id = b.spiel_id AND account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "'::TIMESTAMP WITH TIME ZONE - '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum < '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND a.end_datum > '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND a.id = b.spiel_id AND account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->release();
+	return sec;
+}
+
+int ISDatenbank::getGespieltSpiele( int accountId, char *beg, char *end )
+{
+	int anz = 0;
+	Text *befehl = new Text( "SELECT count( a.id ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum < '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND a.end_datum < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND a.end_datum > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->anhängen( accountId );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		anz += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT count( a.id ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND a.end_datum < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->anhängen( accountId );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		anz += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->release();
+	return anz;
+}
+
+int ISDatenbank::getGewonnenSpiele( int accountId, char *beg, char *end )
+{
+	int anz = 0;
+	Text *befehl = new Text( "SELECT count( a.id ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum < '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND a.end_datum < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND a.end_datum > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND a.id = b.spiel_id AND b.spiel_spieler_status_id = 2 AND b.account_id = " );
+	befehl->anhängen( accountId );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		anz += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT count( a.id ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum > '" );
+	befehl->anhängen( beg );
+	befehl->anhängen( "' AND a.end_datum < '" );
+	befehl->anhängen( end );
+	befehl->anhängen( "' AND a.id = b.spiel_id AND b.spiel_spieler_status_id = 2 AND b.account_id = " );
+	befehl->anhängen( accountId );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		anz += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->release();
+	return anz;
+}
+
+Result ISDatenbank::getSpielPartnerListe( int accountId )
+{
+	Text *befehl = new Text( "SELECT account_id_b, anzahl, karte_id FROM account_mitspieler WHERE account_id_a = " );
+	befehl->anhängen( accountId );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	return res;
+}
+
+Result ISDatenbank::getSpielStatistikListe( int accountId, int *seite, int *maxSeite, int sortStalte, bool rückwärts )
+{
+	Text *befehl = new Text( "SELECT count( spiel_art_id ) FROM spiel_statistik WHERE account_id = " );
+	befehl->anhängen( accountId );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	int einträge = res.values[ 0 ];
+	res.destroy();
+	*maxSeite = einträge / 21;
+	if( einträge % 21 )
+		( *maxSeite )++;
+	if( *seite > *maxSeite )
+		*seite = *maxSeite;
+	if( !( *seite ) )
+	{
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	befehl->setText( "SELECT a.id, a.name, b.gespielt, b.gewonnen, b.verloren, b.punkte, b.bw0, b.bw1, b.bw2, b.bw3, "
+					 "b.bw4, b.bw5 FROM spiel_art a, spiel_statistik b WHERE a.id = b.spiel_art_id AND b.account_id = " );
+	befehl->anhängen( accountId );
+	befehl->anhängen( " ORDER BY " );
+	befehl->anhängen( sortStalte + 2 );
+	if( rückwärts )
+		befehl->anhängen( " DESC" );
+	befehl->anhängen( " OFFSET " );
+	befehl->anhängen( ( ( *seite ) - 1 ) * 18 );
+	befehl->anhängen( " LIMIT 18" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	return res;
+}
+
+AHDaten *ISDatenbank::getSpielHistorie( int accountId, InformationServer *is )
+{
+	Text *befehl = new Text( "SELECT a.id, a.karte_id, c.name, d.name, substring( a.beginn_datum::CHARACTER VARYING FOR 16 ), "
+							 "b.spiel_spieler_status_id, a.spiel_status_id, count( e.spiel_id ) "
+							 "FROM spiel a, spiel_spieler b, spiel_art c, karte d, (SELECT spiel_id FROM spiel_spieler) e "
+							 "WHERE a.id = e.spiel_id AND a.karte_id = d.id AND d.spiel_art_id = c.id "
+							 "AND a.id = b.spiel_id AND b.account_id = " );
+	*befehl += accountId;
+	*befehl += " GROUP BY a.id, a.karte_id, c.name, d.name, a.beginn_datum, b.spiel_spieler_status_id, a.spiel_status_id "
+			   "ORDER BY beginn_datum DESC LIMIT 20";
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result spielListe = datenbank->getResult();
+	unlock();
+	AHDaten *ret = new AHDaten();
+	for( int i = 0; i < spielListe.zeilenAnzahl; i++ )
+	{
+		SpielerTeamStruktur *sts = new SpielerTeamStruktur();
+		bool stsOK = 1;
+		KartenLeser *reader = new KartenLeser( spielListe.values[ 1 + i * spielListe.feldAnzahl ], is );
+		if( !reader->ladeSpielerTeamStruktur( sts ) )
+			stsOK = 0;
+		reader->release();
+		AHSpielDaten *spiel = new AHSpielDaten();
+		spiel->id = spielListe.values[ i * spielListe.feldAnzahl ];
+		spiel->karteId = spielListe.values[ 1 + i * spielListe.feldAnzahl ];
+		spiel->spiel->setText( spielListe.values[ 2 + i * spielListe.feldAnzahl ] );
+		spiel->karte->setText( spielListe.values[ 3 + i * spielListe.feldAnzahl ] );
+		spiel->datum->setText( spielListe.values[ 4 + i * spielListe.feldAnzahl ] );
+		switch( (int)spielListe.values[ 5 + i * spielListe.feldAnzahl ] )
+		{
+		case 1:
+			spiel->status->setText( "Verloren" );
+			break;
+		case 2:
+			spiel->status->setText( "Gewonnen" );
+			break;
+		case 3:
+			spiel->status->setText( "Nicht Anwesend" );
+			break;
+		case 4:
+			spiel->status->setText( "Beobachter" );
+			break;
+		case 5:
+			spiel->status->setText( "Unentschieden" );
+			break;
+		}
+		switch( (int)spielListe.values[ 6 + i * spielListe.feldAnzahl ] )
+		{
+		case 1:
+			spiel->spielStatus->setText( "Beginnt" );
+			break;
+		case 2:
+			spiel->spielStatus->setText( "Läuft" );
+			break;
+		case 3:
+			spiel->spielStatus->setText( "Abgebrochen" );
+			break;
+		case 4:
+			spiel->spielStatus->setText( "Fehlerhaft" );
+			break;
+		case 5:
+			spiel->spielStatus->setText( "Beendet" );
+			break;
+		case 6:
+			spiel->spielStatus->setText( "Unbewertet" );
+			break;
+		}
+		spiel->sAnzahl = spielListe.values[ 7 + i * spielListe.feldAnzahl ];
+		*befehl = "SELECT substring( (end_datum - beginn_datum)::CHARACTER VARYING FOR 8) FROM spiel WHERE id = ";
+		*befehl += spielListe.values[ i * spielListe.feldAnzahl ].getText();
+		lock();
+		if( datenbank->befehl( *befehl ) )
+		{
+			Result dauer = datenbank->getResult();
+			unlock();
+			if( dauer.zeilenAnzahl && dauer.values[ 0 ].getLänge() )
+				spiel->dauer->setText( dauer.values[ 0 ] );
+		}
+		else
+			unlock();
+		int gewinnerTeam = -1;
+		if( stsOK )
+		{
+			*befehl = "SELECT team_id FROM spiel_spieler WHERE spiel_spieler_status_id = 2 AND spiel_id = ";
+			*befehl += spielListe.values[ i * spielListe.feldAnzahl ].getText();
+			lock();
+			if( datenbank->befehl( *befehl ) )
+			{
+				Result team = datenbank->getResult();
+				unlock();
+				if( team.zeilenAnzahl && team.values[ 0 ].getLänge() && sts->teamName->z( team.values[ 0 ] ) )
+				{
+					spiel->gewinner->setText( sts->teamName->z( team.values[ 0 ] )->getText() );
+					gewinnerTeam = team.values[ 0 ];
+				}
+			}
+			else
+				unlock();
+		}
+		*befehl = "SELECT a.ruf_name, b.team_id, b.punkte, b.spiel_spieler_status_id, b.spieler_nummer FROM account a, spiel_spieler b WHERE b.account_id = a.id AND spiel_id = ";
+		*befehl += spielListe.values[ i * spielListe.feldAnzahl ].getText();
+		*befehl += " ORDER BY team_id";
+		lock();
+		if( datenbank->befehl( *befehl ) )
+		{
+			Result spielerListe = datenbank->getResult();
+			unlock();
+			for( int j = 0; j < spielerListe.zeilenAnzahl; j++ )
+			{
+				int tAnz = spiel->teams->getEintragAnzahl();
+				int index = -1;
+				for( int k = 0; k < tAnz; k++ )
+				{
+					if( spiel->teams->z( k )->id == (int)spielerListe.values[ 1 + j * spielerListe.feldAnzahl ] )
+					{
+						index = k;
+						break;
+					}
+				}
+				if( index < 0 )
+				{
+					index = tAnz;
+					AHSpielTeamDaten *team = new AHSpielTeamDaten();
+					team->id = spielerListe.values[ 1 + j * spielerListe.feldAnzahl ];
+					if( sts->teamName->z( team->id ) )
+						team->name->setText( sts->teamName->z( team->id )->getText() );
+					team->sAnzahl = 0;
+					if( team->id == gewinnerTeam )
+						team->status->setText( "Gewonnen" );
+					else
+						team->status->setText( "Verloren" );
+					if( sts->teamFarbe->hat( team->id ) )
+						team->farbe = sts->teamFarbe->get( team->id );
+					else
+						team->farbe = 0;
+					spiel->teams->set( team, index );
+				}
+				AHSpielSpielerDaten *spieler = new AHSpielSpielerDaten();
+				spieler->name->setText( spielerListe.values[ j * spielerListe.feldAnzahl ] );
+				spieler->punkte = spielerListe.values[ 2 + j * spielerListe.feldAnzahl ];
+				if( sts->spielerFarbe->hat( (int)spielerListe.values[ 4 + j * spielerListe.feldAnzahl ] - 1 ) )
+					spieler->farbe = sts->spielerFarbe->get( (int)spielerListe.values[ 4 + j * spielerListe.feldAnzahl ] - 1 );
+				else
+					spieler->farbe = 0;
+				switch( (int)spielerListe.values[ 3 + j * spielerListe.feldAnzahl ] )
+				{
+				case 1:
+					spieler->status->setText( "Verloren" );
+					break;
+				case 2:
+					spieler->status->setText( "Gewonnen" );
+					break;
+				case 3:
+					spieler->status->setText( "Nicht Anwesend" );
+					break;
+				case 4:
+					spieler->status->setText( "Beobachter" );
+					break;
+				case 5:
+					spieler->status->setText( "Unentschieden" );
+					break;
+				}
+				spiel->teams->z( index )->sAnzahl++;
+				spiel->teams->z( index )->spieler->add( spieler );
+			}
+		}
+		else
+			unlock();
+		sts->release();
+		ret->spiele->set( spiel, i );
+	}
+	return ret;
+}
+
+bool ISDatenbank::getHistorieServerPortIp( int clientId, int spielId, int *port, Text *ip )
+{
+	lock();
+	if( !datenbank->befehl( Text( "SELECT a.id, a.port, a.ip FROM server_historie a, server_historie_spiel b "
+								  "WHERE a.id = b.server_historie_id AND a.clients < a.max_clients - 1 AND "
+								  "a.server_status_id = 3 AND b.spiel_id = " ) += spielId ) )
+	{
+		unlock();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int id = res.values[ 0 ];
+	*port = res.values[ 1 ];
+	*ip = res.values[ 2 ].getText();
+	res.destroy();
+	Text *befehl = new Text( "INSERT INTO server_historie_clients( client_id, server_historie_id ) VALUES ( " );
+	befehl->anhängen( clientId );
+	befehl->anhängen( ", " );
+	befehl->anhängen( id );
+	befehl->anhängen( " )" );
+	bool ret = 1;
+	lock();
+	ret &= datenbank->befehl( Text( "SELECT server_historie_id FROM server_historie_clients WHERE client_id = " ) += clientId );
+	res = datenbank->getResult();
+	if( res.zeilenAnzahl )
+		ret &= datenbank->befehl( Text( "UPDATE server_historie SET clients = clients - 1 WHERE id = " ) += res.values[ 0 ] );
+	res.destroy();
+	ret &= datenbank->befehl( Text( "DELETE FROM server_historie_clients WHERE client_id = " ) += clientId );
+	ret &= datenbank->befehl( *befehl );
+	ret &= datenbank->befehl( Text( "UPDATE server_historie SET clients = clients + 1 WHERE id = " ) += id );
+	unlock();
+	befehl->release();
+	return ret;
+}
+
+bool ISDatenbank::hatKlientRecht( int kId, int recht )
+{
+	Text befehl = "SELECT a.* FROM account_user_rechte a, account_clients b WHERE a.account_id = b.account_id AND b.client_id = ";
+	befehl += kId;
+	befehl += " AND a.user_rechte_id = ";
+	befehl += recht;
+	lock();
+	datenbank->befehl( befehl );
+	int num = datenbank->getZeilenAnzahl();
+	unlock();
+	return num == 1;
+}
+
+Result ISDatenbank::getKartenListe( int kId, char *suchFilter, char sortSpalte, char sortRichtung )
+{
+	Text befehl = "SELECT a.id, a.name, b.name, c.kupfer, a.verkauft, a.max_spieler FROM karte a ";
+	befehl += "INNER JOIN spiel_art b ON a.spiel_art_id = b.id ";
+	befehl += "LEFT JOIN karte_kauf_erlaubt c ON a.id = c.karte_id ";
+	befehl += "INNER JOIN account_clients d ON d.account_id = a.account_id ";
+	befehl += "WHERE d.client_id = ";
+	befehl += kId;
+	befehl += " AND a.name LIKE'%";
+	befehl += suchFilter;
+	befehl += "%' ORDER BY ";
+	befehl += sortSpalte + 2;
+	if( sortRichtung ) // absteigend
+		befehl += " DESC";
+	lock();
+	if( !datenbank->befehl( befehl ) )
+	{
+		unlock();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	return res;
+}
+
+bool ISDatenbank::getEditorServerPortIp( int clientId, int karteId, int *port, Text *ip )
+{
+	Text befehl = "SELECT a.port, a.ip, a.id FROM server_editor a, karte b, account_clients c ";
+	befehl += "WHERE a.id = b.server_editor_id AND b.account_id = c.account_id AND a.server_status_id = 3 AND c.client_id = ";
+	befehl += clientId;
+	befehl += " AND b.id = ";
+	befehl += karteId;
+	lock();
+	if( !datenbank->befehl( befehl ) )
+	{
+		unlock();
+		Result res = { 0, 0, 0, 0 };
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	*port = res.values[ 0 ];
+    ip->setText( res.values[ 1 ] );
+    int id = res.values[ 2 ];
+    res.destroy();
+    befehl = "INSERT INTO server_editor_clients( client_id, server_editor_id ) VALUES ( ";
+    befehl += clientId;
+    befehl += ", ";
+    befehl += id;
+    befehl += " )";
+    bool ret = 1;
+    lock();
+    ret &= datenbank->befehl( Text( "SELECT server_editor_id FROM server_editor_clients WHERE client_id = " ) += clientId );
+    ret &= datenbank->befehl( Text( "DELETE FROM server_editor_clients WHERE client_id = " ) += clientId );
+    ret &= datenbank->befehl( befehl );
+    unlock();
+	return 1;
+}
+
+bool ISDatenbank::getKartenServerPortIp( int clientId, int karteId, int *port, Text *ip )
+{
+    Text befehl = "SELECT a.port, a.ip, a.id FROM server_karten a, karte b ";
+    befehl += "WHERE a.id = b.server_karten_id AND a.server_status_id = 3 AND b.id = ";
+    befehl += karteId;
+    if( !karteId )
+        befehl = "SELECT port, ip, a.id FROM server_karten WHERE server_status_id = 3 LIMIT 1";
+    lock();
+    if( !datenbank->befehl( befehl ) )
+    {
+        unlock();
+        return 0;
+    }
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+        return 0;
+    *port = res.values[ 0 ];
+    ip->setText( res.values[ 1 ] );
+    int id = res.values[ 2 ];
+    res.destroy();
+    if( clientId )
+    {
+        befehl = "INSERT INTO server_karten_clients( client_id, server_karten_id ) VALUES ( ";
+        befehl += clientId;
+        befehl += ", ";
+        befehl += id;
+        befehl += " )";
+        bool ret = 1;
+        lock();
+        ret &= datenbank->befehl( Text( "SELECT server_karten_id FROM server_karten_clients WHERE client_id = " ) += clientId );
+        ret &= datenbank->befehl( Text( "DELETE FROM server_karten_clients WHERE client_id = " ) += clientId );
+        ret &= datenbank->befehl( befehl );
+        unlock();
+    }
+    return 1;
+}
+
+// constant
+Text *ISDatenbank::getLetzterFehler() const
+{
+	return datenbank->getLetzterFehler();
+}
+
+// Reference Counting
+ISDatenbank *ISDatenbank::getThis()
+{
+	ref++;
+	return this;
+}
+
+ISDatenbank *ISDatenbank::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 101 - 0
Information Server/Datenbank.h

@@ -0,0 +1,101 @@
+#ifndef Datenbank_H
+#define Datenbank_H
+
+#include <sql.h>
+#include <Text.h>
+#include <Array.h>
+#include <InitDatei.h>
+
+using namespace Framework;
+using namespace sql;
+
+namespace Admin_Recht
+{
+	const int ISStarten = 0x00000014;
+	const int ISBeenden = 0x00000015;
+	const int ISPausieren = 0x00000016;
+	const int ISMCÄndern = 0x00000017;
+}
+
+struct AHDaten;
+class InformationServer;
+
+class ISDatenbank
+{
+private:
+	Datenbank *datenbank;
+	CRITICAL_SECTION cs;
+	int ref;
+
+public:
+	// Konstruktor
+	ISDatenbank( InitDatei *zIni );
+	// Destruktor
+	~ISDatenbank();
+	// nicht constant
+	void lock();
+	void unlock();
+	int istAdministrator( const char *name, const char *passwort );
+	bool adminHatRecht( int id, int recht );
+	bool prüfKlient( int num, int sNum );
+	Text *getKlientSchlüssel( int cId );
+	void unregisterKlient( int num, int sNum );
+	bool serverAnmelden( InitDatei *zIni );
+	bool setServerStatus( int id, int status );
+	bool setMaxClients( int id, int maxC );
+	int getAdminPort( int id );
+	bool serverIstNichtPausiert( int id );
+	Text *getInformationsText( char *typ );
+	bool istSpielErlaubt( int spielId );
+	bool istKarteErlaubt( int karteId );
+	Text *getAccountRufName( int accountId );
+	int getAccountId( char *rufName );
+	Array< int > *getAccountSpielStatistik( int accountId, int spielId );
+	int getAccountKarteSpiele( int accountId, int karteId );
+	int getAccountKarteSpieleGewonnen( int accountId, int karteId );
+	Text *getKarteName( int karteId );
+	Text *getSpielName( int spielId );
+	Text *getChatroomName( int chatroomId );
+	int getChatroomId( char *name );
+	int getSpielId( int karteId );
+	int getSpielId( char *name );
+	int getKarteId( char *name );
+	int getGruppenKarteId( int gruppeId );
+	int getGruppeAdminId( int gruppeId );
+	int getSpielerPunkte( int spielId, int accountId );
+	Array< int > *getAccountSpielArtListe( int cId );
+	int getNeusteSpielVersion( int spielId );
+	int getKupfer( int cId );
+	int getDateiGruppeVonSpiel( int sId );
+	Text *getDateiGruppePfad( int dgId );
+	Array< int > *getAccountKarteListe( int cId, int kId );
+	bool hatAccountKarte( int account, int karte );
+	bool hatAccountSpiel( int account, int spiel );
+	int getDateiGruppeVonPfad( char *pfad );
+	int getNeusteDateiGruppe( int dg );
+	bool getGruppeSpielerHinzufügen( int gruppeId );
+	Result getSpielerListe( char *suche, int *seite, int *maxSeite, int sortStalte, bool rückwärts );
+	bool getSpielerAktivität( int accountId, RCArray< Text > *datum, Array< double > *stOnline, Array< double > *stGespielt,
+							  Array< int > *anzSpiele, Array< int > *anzGewonnen );
+	int getOnlineSeconds( int accountId, char *beg, char *end );
+	int getGespieltSeconds( int accountId, char *beg, char *end );
+	int getGespieltSpiele( int accountId, char *beg, char *end );
+	int getGewonnenSpiele( int accountId, char *beg, char *end );
+	Array< int > *getAccountKarteGespieltListe( int accountId, int spielArt );
+	Array< int > *getAccountSpielGespieltListe( int accountId );
+	Result getSpielPartnerListe( int accountId );
+	Result getSpielStatistikListe( int accountId, int *seite, int *maxSeite, int sortStalte, bool rückwärts );
+    AHDaten *getSpielHistorie( int accountId, InformationServer *is );
+	bool getHistorieServerPortIp( int clientId, int spielId, int *port, Text *ip );
+	bool hatKlientRecht( int kId, int recht );
+	Result getKartenListe( int kId, char *suchFilter, char sortSpalte, char sortRichtung );
+    bool getEditorServerPortIp( int clientId, int karteId, int *port, Text *ip );
+    bool getKartenServerPortIp( int clientId, int karteId, int *port, Text *ip );
+	// constant
+	Text *getLetzterFehler() const;
+	// Reference Counting
+	ISDatenbank *getThis();
+	ISDatenbank *release();
+};
+
+#endif

+ 194 - 0
Information Server/Information Server.vcxproj

@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{41F7BE26-A487-4D75-A978-4F106C12139A}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>InformationServer</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <IncludePath>..\..\..\..\Allgemein\Framework;..\..\..\..\Allgemein\Network\Network;..\..\..\..\Allgemein\sql\sql;$(IncludePath)</IncludePath>
+    <LibraryPath>..\..\..\..\Allgemein\Framework\x64\Debug;..\..\..\..\Allgemein\Network\x64\Debug;..\..\..\..\Allgemein\sql\x64\Debug;$(LibraryPath)</LibraryPath>
+    <CustomBuildBeforeTargets>
+    </CustomBuildBeforeTargets>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>..\..\..\..\Allgemein\Framework;..\..\..\..\Allgemein\Network\Network;..\..\..\..\Allgemein\sql\sql;$(IncludePath)</IncludePath>
+    <LibraryPath>..\..\..\..\Allgemein\Framework\Release;..\..\..\..\Allgemein\Network\Release;..\..\..\..\Allgemein\sql\Release;$(LibraryPath)</LibraryPath>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>..\..\..\..\Allgemein\Framework;..\..\..\..\Allgemein\Network\Network;..\..\..\..\Allgemein\sql\sql;$(IncludePath)</IncludePath>
+    <LibraryPath>..\..\..\..\Allgemein\Framework\x64\Debug;..\..\..\..\Allgemein\Network\x64\Debug;..\..\..\..\Allgemein\sql\x64\Debug;$(LibraryPath)</LibraryPath>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>Framework.lib;Network.lib;sql.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <CustomBuildStep>
+      <Command>
+      </Command>
+    </CustomBuildStep>
+    <CustomBuildStep>
+      <Outputs>
+      </Outputs>
+    </CustomBuildStep>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>Framework.lib;Network.lib;sql.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <CustomBuildStep>
+      <Outputs>Kopieren...;%(Outputs)</Outputs>
+      <Command>copy "..\Release\Information server.exe" "..\..\Fertig\x32\exe\Information server.exe"</Command>
+    </CustomBuildStep>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <BrowseInformation>true</BrowseInformation>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>Framework.lib;Network.lib;sql.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <CustomBuildStep>
+      <Command>copy "..\x64\Release\Information server.exe" "..\..\Fertig\x64\exe\Information server.exe"</Command>
+    </CustomBuildStep>
+    <CustomBuildStep>
+      <Outputs>Kopieren...;%(Outputs)</Outputs>
+    </CustomBuildStep>
+    <Bscmake>
+      <PreserveSbr>true</PreserveSbr>
+    </Bscmake>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="AccountHistorieDaten.cpp" />
+    <ClCompile Include="Datenbank.cpp" />
+    <ClCompile Include="InformationServer.cpp" />
+    <ClCompile Include="KartenLeser.cpp" />
+    <ClCompile Include="main.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="AccountHistorieDaten.h" />
+    <ClInclude Include="Datenbank.h" />
+    <ClInclude Include="InformationServer.h" />
+    <ClInclude Include="KartenLeser.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 48 - 0
Information Server/Information Server.vcxproj.filters

@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Quelldateien">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Headerdateien">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Ressourcendateien">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="main.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Datenbank.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="InformationServer.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="AccountHistorieDaten.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="KartenLeser.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Datenbank.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="InformationServer.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="AccountHistorieDaten.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="KartenLeser.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+  </ItemGroup>
+</Project>

+ 1693 - 0
Information Server/InformationServer.cpp

@@ -0,0 +1,1693 @@
+#include "InformationServer.h"
+#include <iostream>
+#include <Klient.h>
+#include <Globals.h>
+#include "AccountHistorieDaten.h"
+
+// Inhalt der InformationServer Klasse aus InformationServer.h
+// Konstruktor 
+InformationServer::InformationServer( InitDatei *zIni )
+	: Thread()
+{
+	Network::Start( 100 );
+	std::cout << "IS: Verbindung mit Datenbank wird hergestellt...\n";
+	db = new ISDatenbank( zIni );
+	klientAnzahl = 0;
+	klients = new RCArray< ISKlient >();
+	empfangen = 0;
+	gesendet = 0;
+	fehler = new Text();
+	ini = zIni->getThis();
+	if( !db->serverAnmelden( zIni ) )
+	{
+		std::cout << "IS: Der Server konnte nicht in die Datenbank eingetragen werden:\n";
+		Text *txt = db->getLetzterFehler();
+		std::cout << txt->getText() << "\nDas Programm wird beendet.";
+		txt->release();
+		exit( 1 );
+	}
+	id = *zIni->zWert( "ServerId" );
+	server = new Server();
+	aServer = new Server();
+	std::cout << "IS: Starten des Admin Servers...\n";
+	if( !aServer->verbinde( (unsigned short)db->getAdminPort( id ), 10 ) )
+	{
+		std::cout << "IS: Der Admin Server konnte nicht gestartet werden. Das Programm wird beendet.\n";
+		exit( 1 );
+	}
+	db->setServerStatus( id, 2 );
+	end = 0;
+	nichtPausiert = 0;
+	InitializeCriticalSection( &cs );
+	ref = 1;
+	if( zIni->zWert( "Aktiv" )->istGleich( "TRUE" ) )
+	{
+		serverStarten();
+		serverFortsetzen();
+	}
+}
+
+// Destruktor 
+InformationServer::~InformationServer()
+{
+	fehler->release();
+	server->trenne();
+	server->release();
+	aServer->trenne();
+	aServer->release();
+	if( klients )
+		klients->release();
+	ini->release();
+	db->release();
+	DeleteCriticalSection( &cs );
+}
+
+// nicht constant 
+void InformationServer::runn()
+{
+	while( !end )
+	{
+		SKlient *klient;
+		klient = aServer->getKlient();
+		if( end && klient )
+		{
+			klient->trenne();
+			klient = klient->release();
+			Sleep( 1000 );
+			return;
+		}
+		if( !klient )
+			return;
+		ISAKlient *clHandle = new ISAKlient( klient, getThis() );
+		clHandle->start();
+	}
+}
+
+void InformationServer::thread()
+{
+	while( 1 )
+	{
+		SKlient *klient;
+		klient = server->getKlient();
+		if( !klient )
+			break;
+		Framework::getThreadRegister()->cleanUpClosedThreads();
+		ISKlient *clHandle = new ISKlient( klient, getThis() );
+		EnterCriticalSection( &cs );
+		klients->set( clHandle, klientAnzahl );
+		klientAnzahl++;
+		LeaveCriticalSection( &cs );
+		clHandle->start();
+	}
+}
+
+void InformationServer::schließen()
+{
+	db->setServerStatus( id, 1 );
+	server->trenne();
+#ifdef WIN32
+	warteAufThread( 1000 );
+#endif
+	EnterCriticalSection( &cs );
+	for( int i = 0; i < klientAnzahl; i++ )
+		klients->z( i )->absturz();
+	klients = klients->release();
+	klientAnzahl = 0;
+	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 InformationServer::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 InformationServer::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->anhängen( db->getLetzterFehler() );
+		return 0;
+	}
+	return 1;
+}
+
+bool InformationServer::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->anhängen( db->getLetzterFehler() );
+		return 0;
+	}
+	return 1;
+}
+
+bool InformationServer::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 InformationServer::setMaxKlients( int mc )
+{
+	if( !db->setMaxClients( id, mc ) )
+	{
+		fehler->setText( "Die maximale Anzahl der Clients konnte nicht gesetzt werden:\n" );
+		fehler->anhängen( db->getLetzterFehler() );
+		return 0;
+	}
+	ini->setWert( "MaxClients", Text() += mc );
+	return 1;
+}
+
+bool InformationServer::absturzKlient( int klientId )
+{
+	bool gefunden = 0;
+	EnterCriticalSection( &cs );
+	for( int i = 0; i < klientAnzahl; i++ )
+	{
+		if( klients->z( i )->getKlientNummer() == klientId )
+		{
+			klients->z( i )->absturz();
+			klients->lösche( i );
+			klientAnzahl--;
+			gefunden = 1;
+			break;
+		}
+	}
+	LeaveCriticalSection( &cs );
+	return gefunden;
+}
+
+bool InformationServer::removeKlient( ISKlient *zKlient )
+{
+	bool gefunden = 0;
+	EnterCriticalSection( &cs );
+	for( int i = 0; i < klientAnzahl; i++ )
+	{
+		if( klients->z( i ) == zKlient )
+		{
+			klients->lösche( i );
+			klientAnzahl--;
+			gefunden = 1;
+			break;
+		}
+	}
+	LeaveCriticalSection( &cs );
+	return gefunden;
+}
+
+void InformationServer::addGesendet( int bytes )
+{
+	gesendet += bytes;
+}
+
+void InformationServer::addEmpfangen( int bytes )
+{
+	empfangen += bytes;
+}
+
+// constant 
+bool InformationServer::istAn() const
+{
+	return db->serverIstNichtPausiert( id );
+}
+
+Server *InformationServer::zServer() const
+{
+	return server;
+}
+
+ISDatenbank *InformationServer::zDB() const
+{
+	return db;
+}
+
+bool InformationServer::hatClients() const
+{
+	return klientAnzahl > 0;
+}
+
+int InformationServer::getId() const
+{
+	return id;
+}
+
+char *InformationServer::getLetzterFehler() const
+{
+	return fehler->getText();
+}
+
+// Reference Counting
+InformationServer *InformationServer::getThis()
+{
+	ref++;
+	return this;
+}
+
+InformationServer *InformationServer::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der ISAKlient Klasse aus InformationServer.h
+// Konstruktor 
+ISAKlient::ISAKlient( SKlient *klient, InformationServer *is )
+	: Thread()
+{
+	this->klient = klient;
+	unsigned char schlüssel[ 20 ] = { 37, 231, 77, 95, 83, 98, 112, 98, 11, 225, 186, 227, 172, 168, 11, 22, 254, 142, 14, 22 };
+	klient->setSendeSchlüssel( (char*)schlüssel, 20 );
+	klient->setEmpfangSchlüssel( (char*)schlüssel, 20 );
+	name = new Text( "" );
+	passwort = new Text( "" );
+	adminId = 0;
+	this->is = is;
+}
+
+// Destruktor 
+ISAKlient::~ISAKlient()
+{
+	klient->trenne();
+	klient->release();
+	is->release();
+	name->release();
+	passwort->release();
+}
+
+// nicht constant 
+void ISAKlient::thread()
+{
+	while( 1 )
+	{
+		char c = 0;
+		if( !klient->getNachrichtVerschlüsselt( &c, 1 ) )
+			break;
+		else
+		{
+			bool br = 0;
+			switch( c )
+			{
+			case 1: // Login
+				if( 1 )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					char nLän = 0;
+					klient->getNachrichtVerschlüsselt( &nLän, 1 );
+					char *n = new char[ nLän + 1 ];
+					n[ nLän ] = 0;
+					if( nLän )
+						klient->getNachrichtVerschlüsselt( n, nLän );
+					char pLän = 0;
+					klient->getNachrichtVerschlüsselt( &pLän, 1 );
+					char *p = new char[ pLän + 1 ];
+					p[ pLän ] = 0;
+					if( pLän )
+						klient->getNachrichtVerschlüsselt( p, pLän );
+					int adminId = is->zDB()->istAdministrator( n, p );
+					if( adminId )
+					{
+						klient->sendeVerschlüsselt( "\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->sendeVerschlüsselt( "\1", 1 );
+				break;
+			case 3: // Trennen
+				br = 1;
+				klient->sendeVerschlüsselt( "\1", 1 );
+				break;
+			case 4: // Server starten
+				if( !adminId )
+					errorZuKlient( "Du musst dich einloggen." );
+				else
+				{
+					if( is->zDB()->adminHatRecht( adminId, Admin_Recht::ISStarten ) )
+					{
+						if( !is->serverStarten() )
+						{
+							Text *err = new Text();
+							err->anhängen( is->getLetzterFehler() );
+							errorZuKlient( err->getText() );
+							err->release();
+						}
+						else
+							klient->sendeVerschlüsselt( "\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( is->zDB()->adminHatRecht( adminId, Admin_Recht::ISBeenden ) )
+					{
+						if( is->serverBeenden() )
+							klient->sendeVerschlüsselt( "\1", 1 );
+						else
+						{
+							Text *err = new Text();
+							err->anhängen( is->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( is->läuft() )
+					{
+						if( is->zDB()->adminHatRecht( adminId, Admin_Recht::ISBeenden ) )
+						{
+							if( is->serverBeenden() )
+								ok = 1;
+							else
+							{
+								Text *err = new Text();
+								err->anhängen( is->getLetzterFehler() );
+								errorZuKlient( err->getText() );
+								err->release();
+							}
+						}
+						else
+							errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
+					}
+					else
+						ok = 1;
+					if( ok && is->hatClients() )
+					{
+						errorZuKlient( "Es sind noch Klients Online. Bitte versuche es später erneut." );
+						break;
+					}
+					if( ok )
+					{
+						klient->sendeVerschlüsselt( "\1", 1 );
+						std::cout << "IS: Der Server wird von Benutzer " << adminId << " heruntergefahren.\n";
+						is->schließen();
+						br = 1;
+					}
+				}
+				break;
+			case 7: // Progtamm abstürzen
+				if( !adminId )
+					errorZuKlient( "Du musst dich einloggen." );
+				else
+				{
+					bool ok = 0;
+					if( is->läuft() )
+					{
+						if( is->zDB()->adminHatRecht( adminId, Admin_Recht::ISBeenden ) )
+						{
+							is->serverBeenden();
+							ok = 1;
+						}
+						else
+							errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
+					}
+					else
+						ok = 1;
+					if( ok )
+					{
+						klient->sendeVerschlüsselt( "\1", 1 );
+						std::cout << "IS: Der Server wurde von Benutzer " << adminId << " terminiert.\n";
+						is->schließen();
+						br = 1;
+					}
+				}
+				break;
+			case 8: // Status Frage
+				if( 1 )
+				{
+					char status = 0;
+					if( is->läuft() )
+					{
+						status = 1;
+						if( is->istAn() )
+							status = 2;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					klient->sendeVerschlüsselt( &status, 1 );
+				}
+				break;
+			case 9: // Server pausieren
+				if( !adminId )
+					errorZuKlient( "Du musst dich einloggen." );
+				else
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					char pause = 0;
+					klient->getNachrichtVerschlüsselt( &pause, 1 );
+					if( is->zDB()->adminHatRecht( adminId, Admin_Recht::ISPausieren ) )
+					{
+						bool ok = 0;
+						if( pause )
+							ok = is->serverPause();
+						else
+							ok = is->serverFortsetzen();
+						if( ok )
+							klient->sendeVerschlüsselt( "\1", 1 );
+						else
+						{
+							Text *err = new Text();
+							err->anhängen( is->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->sendeVerschlüsselt( "\1", 1 );
+					int maxC = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&maxC, 4 );
+					if( is->zDB()->adminHatRecht( adminId, Admin_Recht::ISMCÄndern ) )
+					{
+						if( is->setMaxKlients( maxC ) )
+							klient->sendeVerschlüsselt( "\1", 1 );
+						else
+						{
+							Text *err = new Text();
+							err->anhängen( is->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->sendeVerschlüsselt( "\1", 1 );
+                    int klientId = 0;
+                    klient->getNachrichtVerschlüsselt( (char*)&klientId, 4 );
+                    if( klientId && is->absturzKlient( klientId ) )
+                        klient->sendeVerschlüsselt( "\1", 1 );
+                    else
+                        klient->sendeVerschlüsselt( "\0", 1 );
+                }
+                break;
+			default:
+				errorZuKlient( "Unbekannte Nachricht!" );
+				break;
+			}
+			if( br )
+				break;
+			is->addEmpfangen( klient->getDownloadBytes( 1 ) );
+			is->addGesendet( klient->getUploadBytes( 1 ) );
+		}
+	}
+	is->addEmpfangen( klient->getDownloadBytes( 1 ) );
+	is->addGesendet( klient->getUploadBytes( 1 ) );
+	delete this;
+}
+
+void ISAKlient::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient
+{
+	klient->sendeVerschlüsselt( "\3", 1 );
+	char län = textLänge( nachricht );
+	klient->sendeVerschlüsselt( &län, 1 );
+	klient->sendeVerschlüsselt( nachricht, län );
+}
+
+
+// Inhalt der ISKlient aus InformationServer.h
+// Konstruktor 
+ISKlient::ISKlient( SKlient *klient, InformationServer *is )
+	: Thread()
+{
+	this->klient = klient;
+	unsigned char schlüssel[ 20 ] = { 231, 246, 125, 32, 88, 172, 229, 223, 246, 138, 74, 64, 142, 245, 217, 218, 162, 62, 103, 50 };
+	klient->setSendeSchlüssel( (char*)schlüssel, 20 );
+	klient->setEmpfangSchlüssel( (char*)schlüssel, 20 );
+	klientNummer = 0;
+	this->is = is;
+	ref = 1;
+}
+
+// Destruktor 
+ISKlient::~ISKlient()
+{
+	klient->release();
+	is->release();
+}
+
+// nicht constant
+void ISKlient::absturz()
+{
+	ende();
+	klient->trenne();
+	is->zDB()->unregisterKlient( klientNummer, is->getId() );
+}
+
+void ISKlient::thread()
+{
+	while( 1 )
+	{
+		char c = 0;
+		if( !klient->getNachrichtVerschlüsselt( &c, 1 ) )
+			break;
+		else
+		{
+			bool br = 0;
+			switch( c )
+			{
+			case 1: // Klient identifikation
+				klient->getNachrichtVerschlüsselt( (char*)&klientNummer, 4 );
+				if( !is->zDB()->prüfKlient( klientNummer, is->getId() ) )
+				{
+					klientNummer = 0;
+					errorZuKlient( "Du bist nicht für diesen Server eingetragen" );
+				}
+				else
+				{
+					Text *schlüssel = is->zDB()->getKlientSchlüssel( klientNummer );
+					if( !schlüssel )
+						errorZuKlient( "Es konnte kein Schlüssel ermittelt werden." );
+					else
+					{
+						klient->sendeVerschlüsselt( "\1", 1 );
+						klient->setEmpfangSchlüssel( *schlüssel, schlüssel->getLänge() );
+						klient->setSendeSchlüssel( *schlüssel, schlüssel->getLänge() );
+						schlüssel->release();
+					}
+				}
+				break;
+			case 2: // Main / Erhaltung Server message
+				if( 1 )
+				{
+					char befehl = 0;
+					klient->getNachrichtVerschlüsselt( &befehl, 1 );
+					switch( befehl )
+					{
+					case 2: // klient absturtz
+						if( 1 )
+						{
+							int klientId = 0;
+							klient->getNachrichtVerschlüsselt( (char*)&klientId, 4 );
+							if( klientId && is->absturzKlient( klientId ) )
+								klient->sendeVerschlüsselt( "\1", 1 );
+							else
+								klient->sendeVerschlüsselt( "\0", 1 );
+						}
+						break;
+					default:
+						errorZuKlient( "Befehl nicht bekannt!" );
+						break;
+					}
+				}
+				break;
+			case 3: // Verbindungsende
+				br = 1;
+				klient->sendeVerschlüsselt( "\1", 1 );
+				break;
+			case 4: // unregister Klient
+				if( !klientNummer )
+				{
+					errorZuKlient( "Du bist nicht Identifiziert." );
+					break;
+				}
+				is->zDB()->unregisterKlient( klientNummer, is->getId() );
+				klient->sendeVerschlüsselt( "\1", 1 );
+				break;
+			case 5: // frage nach Informations Text
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					char typ = 0;
+					Text *info = is->zDB()->getInformationsText( &typ );
+					unsigned short län = info ? (unsigned short)info->getLänge() : 0;
+					klient->sendeVerschlüsselt( (char*)&län, 2 );
+					if( län > 0 )
+						klient->sendeVerschlüsselt( info->getText(), län );
+					klient->sendeVerschlüsselt( &typ, 1 );
+					if( info )
+						info->release();
+				}
+				break;
+			case 6: // frage, ob Spiel erlaubt ist
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int spielId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&spielId, 4 );
+					if( is->zDB()->istSpielErlaubt( spielId ) )
+						klient->sendeVerschlüsselt( "\1", 1 );
+					else
+						klient->sendeVerschlüsselt( "\0", 1 );
+				}
+				break;
+			case 7: // frage, ob Karte erlaubt ist
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int karteId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&karteId, 4 );
+					if( is->zDB()->istKarteErlaubt( karteId ) )
+						klient->sendeVerschlüsselt( "\1", 1 );
+					else
+						klient->sendeVerschlüsselt( "\0", 1 );
+				}
+				break;
+			case 8: // Frage nach Spiel Id
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					char län = 0;
+					klient->getNachrichtVerschlüsselt( &län, 1 );
+					char *name = new char[ län + 1 ];
+					name[ län ] = 0;
+					klient->getNachrichtVerschlüsselt( name, län );
+					int id = is->zDB()->getSpielId( name );
+					klient->sendeVerschlüsselt( (char*)&id, 4 );
+					delete[] name;
+				}
+				break;
+			case 9: // Frage nach Karte Id
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					char län = 0;
+					klient->getNachrichtVerschlüsselt( &län, 1 );
+					char *name = new char[ län + 1 ];
+					name[ län ] = 0;
+					klient->getNachrichtVerschlüsselt( name, län );
+					int id = is->zDB()->getKarteId( name );
+					klient->sendeVerschlüsselt( (char*)&id, 4 );
+					delete[] name;
+				}
+				break;
+			case 0xA: // Frage nach Account rufName
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int accountId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&accountId, 4 );
+					Text *rName = is->zDB()->getAccountRufName( accountId );
+					if( rName )
+					{
+						char län = (char)rName->getLänge();
+						klient->sendeVerschlüsselt( &län, 1 );
+						klient->sendeVerschlüsselt( rName->getText(), län );
+						rName->release();
+					}
+					else
+						klient->sendeVerschlüsselt( "\0", 1 );
+				}
+				break;
+			case 0xB: // Frage nach Spiel Statistik
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int accountId = 0;
+					int spielId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&accountId, 4 );
+					klient->getNachrichtVerschlüsselt( (char*)&spielId, 4 );
+					Array< int > *values = is->zDB()->getAccountSpielStatistik( accountId, spielId );
+					for( int i = 0; i < 10; i++ )
+					{
+						int tmp = values ? values->get( i ) : 0;
+						klient->sendeVerschlüsselt( (char*)&tmp, 4 );
+					}
+					if( values )
+						values->release();
+				}
+				break;
+			case 0xC: // Frage nach Spieler Liste
+				if( !klientNummer )
+				{
+					errorZuKlient( "Du bist nicht Identifiziert." );
+					break;
+				}
+				else
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					char län = 0;
+					klient->getNachrichtVerschlüsselt( &län, 1 );
+					char *suche = new char[ län + 1 ];
+					suche[ län ] = 0;
+					klient->getNachrichtVerschlüsselt( suche, län );
+					int seite = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&seite, 4 );
+					char sortSpalte = 0;
+					char rückwärts = 0;
+					klient->getNachrichtVerschlüsselt( &sortSpalte, 1 );
+					klient->getNachrichtVerschlüsselt( &rückwärts, 1 );
+					int maxSeite = 0;
+					Result list = is->zDB()->getSpielerListe( suche, &seite, &maxSeite, sortSpalte, rückwärts != 0 );
+					delete[] suche;
+					klient->sendeVerschlüsselt( (char*)&seite, 4 );
+					klient->sendeVerschlüsselt( (char*)&maxSeite, 4 );
+					klient->sendeVerschlüsselt( (char*)&list.zeilenAnzahl, 4 );
+					for( int i = 0; i < list.zeilenAnzahl; i++ )
+					{
+						int accId = list.values[ i * 6 ];
+						klient->sendeVerschlüsselt( (char*)&accId, 4 );
+						län = (char)list.values[ i * 6 + 1 ].getLänge();
+						klient->sendeVerschlüsselt( &län, 1 );
+						klient->sendeVerschlüsselt( list.values[ i * 6 + 1 ], län );
+						län = (char)list.values[ i * 6 + 2 ].getLänge();
+						klient->sendeVerschlüsselt( &län, 1 );
+						klient->sendeVerschlüsselt( list.values[ i * 6 + 2 ], län );
+						län = (char)list.values[ i * 6 + 3 ].getLänge();
+						klient->sendeVerschlüsselt( &län, 1 );
+						klient->sendeVerschlüsselt( list.values[ i * 6 + 3 ], län );
+						län = (char)list.values[ i * 6 + 4 ].getLänge();
+						klient->sendeVerschlüsselt( &län, 1 );
+						klient->sendeVerschlüsselt( list.values[ i * 6 + 4 ], län );
+						län = (char)list.values[ i * 6 + 5 ].getLänge();
+						klient->sendeVerschlüsselt( &län, 1 );
+						klient->sendeVerschlüsselt( list.values[ i * 6 + 5 ], län );
+					}
+					list.destroy();
+				}
+				break;
+			case 0xD: // Frage nach Gruppe Karte Id
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int gruppeId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&gruppeId, 4 );
+					int karteId = is->zDB()->getGruppenKarteId( gruppeId );
+					klient->sendeVerschlüsselt( (char*)&karteId, 4 );
+				}
+				break;
+			case 0xE: // Frage nach Karten Name
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int karteId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&karteId, 4 );
+					Text *name = is->zDB()->getKarteName( karteId );
+					if( !name )
+					{
+						klient->sendeVerschlüsselt( "\0", 1 );
+						break;
+					}
+					char län = name->getLänge();
+					klient->sendeVerschlüsselt( &län, 1 );
+					klient->sendeVerschlüsselt( name->getText(), län );
+					name->release();
+				}
+				break;
+			case 0xF: // Frage nach Spiel Name
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int spielId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&spielId, 4 );
+					Text *name = is->zDB()->getSpielName( spielId );
+					if( !name )
+					{
+						klient->sendeVerschlüsselt( "\0", 1 );
+						break;
+					}
+					char län = name->getLänge();
+					klient->sendeVerschlüsselt( &län, 1 );
+					klient->sendeVerschlüsselt( name->getText(), län );
+					name->release();
+				}
+				break;
+			case 0x10: // Frage nach Chatroom Name
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int chatroomId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&chatroomId, 4 );
+					Text *name = is->zDB()->getChatroomName( chatroomId );
+					if( !name )
+					{
+						klient->sendeVerschlüsselt( "\0", 1 );
+						break;
+					}
+					char län = name->getLänge();
+					klient->sendeVerschlüsselt( &län, 1 );
+					klient->sendeVerschlüsselt( name->getText(), län );
+					name->release();
+				}
+				break;
+			case 0x11: // Frage nach Spiel Id
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int karteId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&karteId, 4 );
+					int spielId = is->zDB()->getSpielId( karteId );
+					klient->sendeVerschlüsselt( (char*)&spielId, 4 );
+				}
+				break;
+			case 0x12: // Frage nach Spieler Id
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					char län = 0;
+					klient->getNachrichtVerschlüsselt( &län, 1 );
+					if( län )
+					{
+						char *name = new char[ län + 1 ];
+						name[ län ] = 0;
+						klient->getNachrichtVerschlüsselt( name, län );
+						int id = is->zDB()->getAccountId( name );
+						klient->sendeVerschlüsselt( (char*)&id, 4 );
+						delete[]name;
+					}
+				}
+				break;
+			case 0x13: // Frage nach Chatroom Id
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					char län = 0;
+					klient->getNachrichtVerschlüsselt( &län, 1 );
+					if( län )
+					{
+						char *name = new char[ län + 1 ];
+						name[ län ] = 0;
+						klient->getNachrichtVerschlüsselt( name, län );
+						int id = is->zDB()->getChatroomId( name );
+						klient->sendeVerschlüsselt( (char*)&id, 4 );
+						delete[]name;
+					}
+				}
+				break;
+			case 0x14: // Frage nach Spiel Punkten
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int spielId = 0;
+					int accountId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&spielId, 4 );
+					klient->getNachrichtVerschlüsselt( (char*)&accountId, 4 );
+					int ret = is->zDB()->getSpielerPunkte( spielId, accountId );
+					klient->sendeVerschlüsselt( (char*)&ret, 4 );
+				}
+				break;
+			case 0x15: // Frage nach Gruppe Administrator
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int gruppeId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&gruppeId, 4 );
+					int ret = is->zDB()->getGruppeAdminId( gruppeId );
+					klient->sendeVerschlüsselt( (char*)&ret, 4 );
+				}
+				break;
+			case 0x16: // Frage nach Spiel Liste
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					Array< int > *list = is->zDB()->getAccountSpielArtListe( klientNummer );
+					if( !list )
+					{
+						klient->sendeVerschlüsselt( "\0\0\0\0", 4 );
+						break;
+					}
+					int anz = list->getEintragAnzahl();
+					klient->sendeVerschlüsselt( (char*)&anz, 4 );
+					for( int i = 0; i < anz; i++ )
+					{
+						int id = list->get( i );
+						klient->sendeVerschlüsselt( (char*)&id, 4 );
+					}
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x17: // Frage nach neuster Spiel Version
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int id = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&id, 4 );
+					int v = is->zDB()->getNeusteSpielVersion( id );
+					klient->sendeVerschlüsselt( (char*)&v, 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x18: // Frage nach Kupfer
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int k = is->zDB()->getKupfer( klientNummer );
+					klient->sendeVerschlüsselt( (char*)&k, 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x19: // Frage nach Dateigruppen Id von Spiel
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int spielId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&spielId, 4 );
+					int dgId = is->zDB()->getDateiGruppeVonSpiel( spielId );
+					klient->sendeVerschlüsselt( (char*)&dgId, 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x1A: // Frage nach Dateigruppen Pfad
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int dgId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&dgId, 4 );
+					Text *pf = is->zDB()->getDateiGruppePfad( dgId );
+					if( !pf )
+						errorZuKlient( "Die Dateigruppe wurde nicht gefunden." );
+					else
+					{
+						klient->sendeVerschlüsselt( "\1", 1 );
+						char län = pf->getLänge();
+						klient->sendeVerschlüsselt( &län, 1 );
+						if( län )
+							klient->sendeVerschlüsselt( pf->getText(), län );
+						pf->release();
+					}
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x1B: // Frage nach karte Liste
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int spielId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&spielId, 4 );
+					Array< int > *list = is->zDB()->getAccountKarteListe( klientNummer, spielId );
+					if( !list )
+					{
+						klient->sendeVerschlüsselt( "\0\0\0\0", 4 );
+						break;
+					}
+					int anz = list->getEintragAnzahl();
+					klient->sendeVerschlüsselt( (char*)&anz, 4 );
+					for( int i = 0; i < anz; i++ )
+					{
+						int id = list->get( i );
+						klient->sendeVerschlüsselt( (char*)&id, 4 );
+					}
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x1E: // Frage nach Gruppe Spieler Hinzufügen
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int gruppeId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&gruppeId, 4 );
+					char gSH = (char)is->zDB()->getGruppeSpielerHinzufügen( gruppeId );
+					klient->sendeVerschlüsselt( &gSH, 1 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x1F: // Frage nach Spieler Aktivität
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int acc = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&acc, 4 );
+					RCArray< Text > *datum = new RCArray< Text >();
+					Array< double > *stOnline = new Array< double >();
+					Array< double > *stSpiel = new Array< double >();
+					Array< int > *anzSpiele = new Array< int >();
+					Array< int > *anzGewonnen = new Array< int >();
+					if( is->zDB()->getSpielerAktivität( acc, datum, stOnline, stSpiel, anzSpiele, anzGewonnen ) )
+					{
+						klient->sendeVerschlüsselt( "\1", 1 );
+						int anz = datum->getEintragAnzahl();
+						for( int i = 0; i < anz; i++ )
+						{
+							if( datum->z( i ) )
+							{
+								char län = (char)datum->get( i )->getLänge();
+								if( län )
+								{
+									klient->sendeVerschlüsselt( &län, 1 );
+									klient->sendeVerschlüsselt( datum->z( i )->getText(), län );
+									double sto = stOnline->hat( i ) ? stOnline->get( i ) : 0;
+									klient->sendeVerschlüsselt( (char*)&sto, 8 );
+									double sts = stSpiel->hat( i ) ? stSpiel->get( i ) : 0;
+									klient->sendeVerschlüsselt( (char*)&sts, 8 );
+									int anzs = anzSpiele->hat( i ) ? anzSpiele->get( i ) : 0;
+									klient->sendeVerschlüsselt( (char*)&anzs, 4 );
+									int anzg = anzGewonnen->hat( i ) ? anzGewonnen->get( i ) : 0;
+									klient->sendeVerschlüsselt( (char*)&anzg, 4 );
+								}
+							}
+						}
+						klient->sendeVerschlüsselt( "\0", 1 );
+					}
+					else
+						errorZuKlient( "Keine Daten gefunden." );
+					datum->release();
+					stOnline->release();
+					stSpiel->release();
+					anzSpiele->release();
+					anzGewonnen->release();
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x20: // Frage nach Anzahl der gespielten Spiele von Karte
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int acc = 0;
+					int karte = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&acc, 4 );
+					klient->getNachrichtVerschlüsselt( (char*)&karte, 4 );
+					int anz = is->zDB()->getAccountKarteSpiele( acc, karte );
+					klient->sendeVerschlüsselt( (char*)&anz, 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x21: // Frage nach Anzahl gewonnener Spiele von Karte
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int acc = 0;
+					int karte = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&acc, 4 );
+					klient->getNachrichtVerschlüsselt( (char*)&karte, 4 );
+					int anz = is->zDB()->getAccountKarteSpieleGewonnen( acc, karte );
+					klient->sendeVerschlüsselt( (char*)&anz, 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x22: // Frage nach Besitz Status von Karte
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int acc = 0;
+					int karte = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&acc, 4 );
+					klient->getNachrichtVerschlüsselt( (char*)&karte, 4 );
+					char status = (char)is->zDB()->hatAccountKarte( acc, karte );
+					klient->sendeVerschlüsselt( &status, 1 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x23: // Frage nach Besitz Status von Spiel
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int acc = 0;
+					int spiel = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&acc, 4 );
+					klient->getNachrichtVerschlüsselt( (char*)&spiel, 4 );
+					char status = (char)is->zDB()->hatAccountSpiel( acc, spiel );
+					klient->sendeVerschlüsselt( &status, 1 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x24: // Frage nach Liste mit gespielten Karten
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int acc = 0;
+					int spiel = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&acc, 4 );
+					klient->getNachrichtVerschlüsselt( (char*)&spiel, 4 );
+					Array< int > *res = is->zDB()->getAccountKarteGespieltListe( acc, spiel );
+					if( res )
+					{
+						int anz = res->getEintragAnzahl();
+						klient->sendeVerschlüsselt( (char*)&anz, 4 );
+						for( int i = 0; i < anz; i++ )
+						{
+							int val = res->get( i );
+							klient->sendeVerschlüsselt( (char*)&val, 4 );
+						}
+						res->release();
+					}
+					else
+						klient->sendeVerschlüsselt( "\0\0\0\0", 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x25: // Frage nach Liste mit gespielten Spielen
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int acc = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&acc, 4 );
+					Array< int > *res = is->zDB()->getAccountSpielGespieltListe( acc );
+					if( res )
+					{
+						int anz = res->getEintragAnzahl();
+						klient->sendeVerschlüsselt( (char*)&anz, 4 );
+						for( int i = 0; i < anz; i++ )
+						{
+							int val = res->get( i );
+							klient->sendeVerschlüsselt( (char*)&val, 4 );
+						}
+						res->release();
+					}
+					else
+						klient->sendeVerschlüsselt( "\0\0\0\0", 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x26: // Frage nach Liste mit spiel Partnern
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int acc = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&acc, 4 );
+					Result res = is->zDB()->getSpielPartnerListe( acc );
+					klient->sendeVerschlüsselt( (char*)&res.zeilenAnzahl, 4 );
+					for( int i = 0; i < res.zeilenAnzahl; i++ )
+					{
+						int spieler = res.values[ i * 3 ];
+						int anzahl = res.values[ i * 3 + 1 ];
+						int karte = res.values[ i * 3 + 2 ];
+						klient->sendeVerschlüsselt( (char*)&spieler, 4 );
+						klient->sendeVerschlüsselt( (char*)&karte, 4 );
+						klient->sendeVerschlüsselt( (char*)&anzahl, 4 );
+					}
+					res.destroy();
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x27: // Frage nach Liste mit spiel Statistiken
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int acc = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&acc, 4 );
+					int seite = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&seite, 4 );
+					char sortSpalte = 0;
+					char rückwärts = 0;
+					klient->getNachrichtVerschlüsselt( &sortSpalte, 1 );
+					klient->getNachrichtVerschlüsselt( &rückwärts, 1 );
+					int maxSeite = 0;
+					Result list = is->zDB()->getSpielStatistikListe( acc, &seite, &maxSeite, sortSpalte, rückwärts != 0 );
+					klient->sendeVerschlüsselt( (char*)&seite, 4 );
+					klient->sendeVerschlüsselt( (char*)&maxSeite, 4 );
+					klient->sendeVerschlüsselt( (char*)&list.zeilenAnzahl, 4 );
+					klient->sendeVerschlüsselt( (char*)&list.feldAnzahl, 4 );
+					for( int i = 0; i < list.zeilenAnzahl; i++ )
+					{
+						for( int j = 0; j < list.feldAnzahl; j++ )
+						{
+							if( j != 1 )
+							{
+								int val = list.values[ j + i * list.feldAnzahl ];
+								klient->sendeVerschlüsselt( (char*)&val, 4 );
+							}
+							else
+							{
+								char län = list.values[ j + i * list.feldAnzahl ].getLänge();
+								klient->sendeVerschlüsselt( &län, 1 );
+								if( län )
+									klient->sendeVerschlüsselt( list.values[ j + i * list.feldAnzahl ], län );
+							}
+						}
+					}
+					list.destroy();
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x28: // Spiel Historie Liste
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int acc = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&acc, 4 );
+					AHDaten *daten = is->zDB()->getSpielHistorie( acc, is );
+					if( daten )
+					{
+						char anz = (char)daten->spiele->getEintragAnzahl();
+						klient->sendeVerschlüsselt( &anz, 1 );
+						for( char i = 0; i < anz; i++ )
+						{
+							AHSpielDaten *spiel = daten->spiele->z( i );
+							klient->sendeVerschlüsselt( (char*)&spiel->id, 4 );
+							klient->sendeVerschlüsselt( (char*)&spiel->karteId, 4 );
+							char län = (char)spiel->spiel->getLänge();
+							klient->sendeVerschlüsselt( &län, 1 );
+							if( län )
+								klient->sendeVerschlüsselt( *spiel->spiel, län );
+							län = (char)spiel->karte->getLänge();
+							klient->sendeVerschlüsselt( &län, 1 );
+							if( län )
+								klient->sendeVerschlüsselt( *spiel->karte, län );
+							län = (char)spiel->datum->getLänge();
+							klient->sendeVerschlüsselt( &län, 1 );
+							if( län )
+								klient->sendeVerschlüsselt( *spiel->datum, län );
+							län = (char)spiel->status->getLänge();
+							klient->sendeVerschlüsselt( &län, 1 );
+							if( län )
+								klient->sendeVerschlüsselt( *spiel->status, län );
+							län = (char)spiel->dauer->getLänge();
+							klient->sendeVerschlüsselt( &län, 1 );
+							if( län )
+								klient->sendeVerschlüsselt( *spiel->dauer, län );
+							län = (char)spiel->spielStatus->getLänge();
+							klient->sendeVerschlüsselt( &län, 1 );
+							if( län )
+								klient->sendeVerschlüsselt( *spiel->spielStatus, län );
+							län = (char)spiel->gewinner->getLänge();
+							klient->sendeVerschlüsselt( &län, 1 );
+							if( län )
+								klient->sendeVerschlüsselt( *spiel->gewinner, län );
+							klient->sendeVerschlüsselt( (char*)&spiel->sAnzahl, 4 );
+							char tAnz = (char)spiel->teams->getEintragAnzahl();
+							klient->sendeVerschlüsselt( &tAnz, 1 );
+							for( char j = 0; j < tAnz; j++ )
+							{
+								AHSpielTeamDaten *team = spiel->teams->z( j );
+								char län = (char)team->name->getLänge();
+								klient->sendeVerschlüsselt( &län, 1 );
+								if( län )
+									klient->sendeVerschlüsselt( *team->name, län );
+								klient->sendeVerschlüsselt( (char*)&team->sAnzahl, 4 );
+								län = (char)team->status->getLänge();
+								klient->sendeVerschlüsselt( &län, 1 );
+								if( län )
+									klient->sendeVerschlüsselt( *team->status, län );
+								klient->sendeVerschlüsselt( (char*)&team->farbe, 4 );
+								char sAnz = (char)team->spieler->getEintragAnzahl();
+								klient->sendeVerschlüsselt( &sAnz, 1 );
+								for( char k = 0; k < sAnz; k++ )
+								{
+									AHSpielSpielerDaten *spieler = team->spieler->z( k );
+									char län = (char)spieler->name->getLänge();
+									klient->sendeVerschlüsselt( &län, 1 );
+									if( län )
+										klient->sendeVerschlüsselt( *spieler->name, län );
+									klient->sendeVerschlüsselt( (char*)&spieler->punkte, 4 );
+									län = (char)spieler->status->getLänge();
+									klient->sendeVerschlüsselt( &län, 1 );
+									if( län )
+										klient->sendeVerschlüsselt( *spieler->status, län );
+									klient->sendeVerschlüsselt( (char*)&spieler->farbe, 4 );
+								}
+							}
+						}
+						daten->release();
+					}
+					else
+						klient->sendeVerschlüsselt( "\0", 1 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x29: // Frage nach Historie Server
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int spielId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&spielId, 4 );
+					int port = 0;
+					Text *ip = new Text();
+					if( is->zDB()->getHistorieServerPortIp( klientNummer, spielId, &port, ip ) )
+					{
+						klient->sendeVerschlüsselt( "\1", 1 );
+						klient->sendeVerschlüsselt( (char*)&port, 4 );
+						char län = (char)ip->getLänge();
+						klient->sendeVerschlüsselt( &län, 1 );
+						klient->sendeVerschlüsselt( *ip, län );
+					}
+					else
+						errorZuKlient( "Die Daten für dieses Spiel sind vorrübergehend nicht verfügbar." );
+					ip->release();
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x2A: // Frage nach Dateigruppen Id von Pfad
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					char län = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&län, 1 );
+					char *pf = new char[ län + 1 ];
+					pf[ län ] = 0;
+					klient->getNachrichtVerschlüsselt( (char*)pf, län );
+					int dgId = is->zDB()->getDateiGruppeVonPfad( pf );
+					delete[] pf;
+					klient->sendeVerschlüsselt( (char*)&dgId, 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x2B: // Frage nach neuster Version einer Dateigruppe
+				if( klientNummer )
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int dg = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&dg, 4 );
+					int v = is->zDB()->getNeusteDateiGruppe( dg );
+					klient->sendeVerschlüsselt( (char*)&v, 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x2C: // ping
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+				}
+				break;
+			case 0x2D: // Hat Account Recht
+				if( !klientNummer )
+				{
+					errorZuKlient( "Du bist nicht Identifiziert." );
+					break;
+				}
+				else
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int recht = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&recht, 4 );
+					if( is->zDB()->hatKlientRecht( klientNummer, recht ) )
+						klient->sendeVerschlüsselt( "\1", 1 );
+					else
+						klient->sendeVerschlüsselt( "\0", 1 );
+				}
+				break;
+			case 0x2E: // Karten Liste
+				if( !klientNummer )
+				{
+					errorZuKlient( "Du bist nicht Identifiziert." );
+					break;
+				}
+				else
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					char filterLän = 0;
+					klient->getNachrichtVerschlüsselt( &filterLän, 1 );
+					char *filter = new char[ filterLän + 1 ];
+					filter[ filterLän ] = 0;
+					if( filterLän )
+						klient->getNachrichtVerschlüsselt( filter, filterLän );
+					char sortSpalte = 0;
+					klient->getNachrichtVerschlüsselt( &sortSpalte, 1 );
+					char sortRichtung = 0;
+					klient->getNachrichtVerschlüsselt( &sortRichtung, 1 );
+					Result res = is->zDB()->getKartenListe( klientNummer, filter, sortSpalte, sortRichtung );
+					delete[] filter;
+					klient->sendeVerschlüsselt( (char*)&res.zeilenAnzahl, 4 );
+					for( int i = 0; i < res.zeilenAnzahl; i++ )
+					{
+						int val = res.values[ i * 6 ];
+						klient->sendeVerschlüsselt( (char*)&val, 4 );
+						char län = (char)res.values[ i * 6 + 1 ].getLänge();
+						klient->sendeVerschlüsselt( &län, 1 );
+						if( län )
+							klient->sendeVerschlüsselt( res.values[ i * 6 + 1 ], län );
+						län = (char)res.values[ i * 6 + 2 ].getLänge();
+						klient->sendeVerschlüsselt( &län, 1 );
+						if( län )
+							klient->sendeVerschlüsselt( res.values[ i * 6 + 2 ], län );
+						val = res.values[ i * 6 + 3 ];
+						klient->sendeVerschlüsselt( (char*)&val, 4 );
+						val = res.values[ i * 6 + 4 ];
+						klient->sendeVerschlüsselt( (char*)&val, 4 );
+						val = res.values[ i * 6 + 5 ];
+						klient->sendeVerschlüsselt( (char*)&val, 4 );
+					}
+					res.destroy();
+				}
+				break;
+			case 0x2F: // Editor Server Anfrage
+				if( !klientNummer )
+				{
+					errorZuKlient( "Du bist nicht Identifiziert." );
+					break;
+				}
+				else
+				{
+					klient->sendeVerschlüsselt( "\1", 1 );
+					int karteId = 0;
+					klient->getNachrichtVerschlüsselt( (char*)&karteId, 4 );
+					int port = 0;
+					Text ip;
+					if( !is->zDB()->getEditorServerPortIp( klientNummer, karteId, &port, &ip ) )
+					{
+						errorZuKlient( "Du kannst diese Karte momentan nicht abrufen." );
+						break;
+					}
+					klient->sendeVerschlüsselt( "\1", 1 );
+					klient->sendeVerschlüsselt( (char*)&port, 4 );
+					char län = (char)ip.getLänge();
+					klient->sendeVerschlüsselt( &län, 1 );
+					klient->sendeVerschlüsselt( ip, län );
+				}
+                break;
+            case 0x30: // Karten Server Anfrage
+                if( !klientNummer )
+                {
+                    errorZuKlient( "Du bist nicht Identifiziert." );
+                    break;
+                }
+                else
+                {
+                    klient->sendeVerschlüsselt( "\1", 1 );
+                    int karteId = 0;
+                    klient->getNachrichtVerschlüsselt( (char*)&karteId, 4 );
+                    int port = 0;
+                    Text ip;
+                    if( !is->zDB()->getKartenServerPortIp( klientNummer, karteId, &port, &ip ) )
+                    {
+                        errorZuKlient( "Diese Karte ist vorrübergehend nicht erreichbar." );
+                        break;
+                    }
+                    klient->sendeVerschlüsselt( "\1", 1 );
+                    klient->sendeVerschlüsselt( (char*)&port, 4 );
+                    char län = (char)ip.getLänge();
+                    klient->sendeVerschlüsselt( &län, 1 );
+                    klient->sendeVerschlüsselt( ip, län );
+                }
+                break;
+			default:
+				errorZuKlient( "Unbekannte Nachricht!" );
+				break;
+			}
+			if( br )
+				break;
+			is->addEmpfangen( klient->getDownloadBytes( 1 ) );
+			is->addGesendet( klient->getUploadBytes( 1 ) );
+		}
+	}
+	is->addEmpfangen( klient->getDownloadBytes( 1 ) );
+	is->addGesendet( klient->getUploadBytes( 1 ) );
+	is->removeKlient( this ); // delete this
+}
+
+// constant
+void ISKlient::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient
+{
+	klient->sendeVerschlüsselt( "\3", 1 );
+	char län = textLänge( nachricht );
+	klient->sendeVerschlüsselt( &län, 1 );
+	klient->sendeVerschlüsselt( nachricht, län );
+}
+
+int ISKlient::getKlientNummer() const // gibt die KlientId zurück
+{
+	return klientNummer;
+}
+
+// Reference Counting
+ISKlient *ISKlient::getThis()
+{
+	ref++;
+	return this;
+}
+
+ISKlient *ISKlient::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 107 - 0
Information Server/InformationServer.h

@@ -0,0 +1,107 @@
+#ifndef InformationServer_H
+#define InformationServer_H
+
+#include <Server.h>
+#include <Thread.h>
+#include <Datei.h>
+#include <Text.h>
+#include <InitDatei.h>
+#include "Datenbank.h"
+
+using namespace Framework;
+using namespace Network;
+
+class ISKlient;
+
+class InformationServer : public Thread
+{
+private:
+	Server *server;
+	Server *aServer;
+	InitDatei *ini;
+	ISDatenbank *db;
+	CRITICAL_SECTION cs;
+	RCArray< ISKlient > *klients;
+	Text *fehler;
+	int klientAnzahl;
+	int id;
+	bool nichtPausiert;
+	int empfangen;
+	int gesendet;
+	bool end;
+	int ref;
+
+public:
+	// Konstruktor 
+	InformationServer( InitDatei *zIni );
+	// Destruktor 
+	virtual ~InformationServer();
+	// nicht constant 
+	void runn();
+	void thread();
+	void schließen();
+	bool serverStarten();
+	bool serverPause();
+	bool serverFortsetzen();
+	bool serverBeenden();
+	bool setMaxKlients( int mc );
+	bool absturzKlient( int klientId );
+	bool removeKlient( ISKlient *zKlient );
+	void addGesendet( int bytes );
+	void addEmpfangen( int bytes );
+	// conatant 
+	bool istAn() const;
+	Server *zServer() const;
+	ISDatenbank *zDB() const;
+	bool hatClients() const;
+	int getId() const;
+	char *getLetzterFehler( ) const;
+	// Reference Counting
+	InformationServer *getThis( );
+	InformationServer *release( );
+};
+
+class ISAKlient : public Thread
+{
+private:
+	SKlient *klient;
+	Text *name;
+	Text *passwort;
+	int adminId;
+	InformationServer *is;
+
+public:
+	// Konstruktor 
+	ISAKlient( SKlient *klient, InformationServer *is );
+	// Destruktor 
+	virtual ~ISAKlient( );
+	// nicht constant
+	void thread( );
+	void errorZuKlient( const char *nachricht ) const; // sendet eine Fehlernachricht zum AKlient
+};
+
+class ISKlient : public Thread
+{
+private:
+	SKlient     *klient;
+	unsigned int klientNummer;
+	InformationServer *is;
+	int ref;
+
+public:
+	// Konstruktor 
+	ISKlient( SKlient *klient, InformationServer *is );
+	// Destruktor 
+	virtual ~ISKlient();
+	// nicht constant
+	void absturz();
+	void thread();
+	// constant
+	void errorZuKlient( const char *nachricht ) const; // sendet eine Fehlernachricht zum Klient
+	int getKlientNummer() const;
+	// Reference Counting
+	ISKlient *getThis();
+	ISKlient *release();
+};
+
+#endif

+ 178 - 0
Information Server/KartenLeser.cpp

@@ -0,0 +1,178 @@
+#include "KartenLeser.h"
+#include <Datei.h>
+#include "AccountHistorieDaten.h"
+#include <Klient.h>
+
+// Inhalt der KartenLeser Klasse aus KartenLeser.h
+// Konstruktor 
+KartenLeser::KartenLeser( int karteId, InformationServer *is )
+{
+	pfad = new Text( "" );
+    *pfad += karteId;
+    while( DateiExistiert( pfad->getText() ) )
+        pfad->anhängen( "_" );
+    ref = 1;
+    Text ip;
+    int port;
+    is->zDB()->getKartenServerPortIp( 0, karteId, &port, &ip );
+    Klient *klient = new Klient();
+    unsigned char schlüssel[ 20 ] = { 24, 15, 53, 87, 38, 73, 154, 38, 246, 90, 39, 133, 11, 199, 22, 80, 26, 132, 95, 54 };
+    klient->setSendeSchlüssel( (char*)schlüssel, 20 );
+    klient->setEmpfangSchlüssel( (char*)schlüssel, 20 );
+    if( !klient->verbinde( (unsigned short)port, ip ) )
+    {
+        klient = klient->release();
+        return;
+    }
+    klient->sendeVerschlüsselt( "\x7", 1 );
+    char ret = 0;
+    klient->getNachrichtVerschlüsselt( &ret, 1 );
+    if( ret == 1 )
+    {
+        klient->sendeVerschlüsselt( (char*)&karteId, 4 );
+        klient->getNachrichtVerschlüsselt( &ret, 1 );
+        if( ret == 1 )
+        {
+            int anz = 0;
+            klient->getNachrichtVerschlüsselt( (char*)&anz, 4 );
+            for( int i = 0; i < anz; i++ )
+            {
+                char län = 0;
+                klient->getNachrichtVerschlüsselt( &län, 1 );
+                if( !län )
+                    continue;
+                char *pfa = new char[ län + 1 ];
+                pfa[ län ] = 0;
+                klient->getNachrichtVerschlüsselt( pfa, län );
+                __int64 größe = 0;
+                klient->getNachrichtVerschlüsselt( (char*)&größe, 8 );
+                char *buffer = new char[ 2048 ];
+                Text pf = pfad->getText();
+                pf += "/";
+                pf += pfa;
+                delete[] pfa;
+                Datei d;
+                d.setDatei( pf );
+                d.erstellen();
+                d.öffnen( Datei::Style::schreiben );
+                while( größe )
+                {
+                    int l = größe >= 2048 ? 2048 : (int)größe;
+                    klient->getNachricht( buffer, l );
+                    d.schreibe( buffer, l );
+                    größe -= l;
+                }
+                d.schließen();
+                delete[] buffer;
+            }
+        }
+    }
+    if( ret == 3 )
+    {
+        char byte = 0;
+        klient->getNachrichtVerschlüsselt( &byte, 1 );
+        char *f = new char[ byte + 1 ];
+        f[ byte ] = 0;
+        klient->getNachrichtVerschlüsselt( f, byte );
+        delete[] f;
+    }
+    klient->sendeVerschlüsselt( "\3", 1 );
+    klient->getNachrichtVerschlüsselt( &ret, 1 );
+    klient->trenne();
+    klient->release();
+}
+
+// Destruktor
+KartenLeser::~KartenLeser()
+{
+    DateiLöschen( pfad );
+}
+
+// nicht constant
+bool KartenLeser::ladeSpielerTeamStruktur( SpielerTeamStruktur *sts )
+{
+	if( !pfad->getLänge() )
+		return 0;
+	Text *pf = new Text( pfad->getText() );
+	pf->anhängen( "/sts.ltgd" );
+	Datei *datei = new Datei();
+	datei->setDatei( pf );
+	if( !datei->existiert() || datei->istOrdner() )
+	{
+		datei->release();
+		return 0;
+	}
+	datei->öffnen( Datei::Style::lesen );
+	datei->lese( (char*)&sts->spielerAnzahl, 4 );
+	datei->lese( (char*)&sts->teamAnzahl, 4 );
+	if( sts->spielerFarbe )
+		sts->spielerFarbe->release();
+	sts->spielerFarbe = new Array< int >();
+	for( int i = 0; i < sts->spielerAnzahl; i++ )
+	{
+		int farbe = 0;
+		datei->lese( (char*)&farbe, 4 );
+		sts->spielerFarbe->set( farbe, i );
+	}
+	if( sts->teamFarbe )
+		sts->teamFarbe->release();
+	sts->teamFarbe = new Array< int >();
+	for( int i = 0; i < sts->teamAnzahl; i++ )
+	{
+		int farbe = 0;
+		datei->lese( (char*)&farbe, 4 );
+		sts->teamFarbe->set( farbe, i );
+	}
+	if( sts->teamName )
+		sts->teamName->release();
+	sts->teamName = new RCArray< Text >();
+	for( int i = 0; i < sts->teamAnzahl; i++ )
+	{
+		char län = 0;
+		datei->lese( &län, 1 );
+		char *txt = new char[ län + 1 ];
+		txt[ län ] = 0;
+		datei->lese( txt, län );
+		Text *name = new Text( txt );
+		delete[] txt;
+		sts->teamName->set( name, i );
+	}
+	if( sts->teamGröße )
+		sts->teamGröße->release();
+	sts->teamGröße = new Array< int >();
+	for( int i = 0; i < sts->teamAnzahl; i++ )
+	{
+		int größe = 0;
+		datei->lese( (char*)&größe, 4 );
+		sts->teamGröße->set( größe, i );
+	}
+	datei->schließen();
+	datei->release();
+	return 1;
+}
+
+// constant
+Text *KartenLeser::getPfad() const
+{
+	return pfad ? pfad->getThis() : 0;
+}
+
+Text *KartenLeser::zPfad() const
+{
+	return pfad;
+}
+
+// Reference Counting
+KartenLeser *KartenLeser::getThis()
+{
+	ref++;
+	return this;
+}
+
+KartenLeser *KartenLeser::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 32 - 0
Information Server/KartenLeser.h

@@ -0,0 +1,32 @@
+#ifndef KartenLeser_H
+#define KartenLeser_H
+
+#include <Text.h>
+#include "InformationServer.h"
+
+using namespace Framework;
+
+struct SpielerTeamStruktur;
+
+class KartenLeser
+{
+private:
+	Text *pfad;
+	int ref;
+
+public:
+	// Konstruktor 
+	KartenLeser( int karteId, InformationServer *is );
+	// Destruktor
+	~KartenLeser();
+	// nicht constant
+	bool ladeSpielerTeamStruktur( SpielerTeamStruktur *sts );
+	// constant
+	Text *getPfad() const;
+	Text *zPfad() const;
+	// Reference Counting
+	KartenLeser *getThis();
+	KartenLeser *release();
+};
+
+#endif

BIN
Information Server/framework.dll


BIN
Information Server/libeay32.dll


BIN
Information Server/libintl-8.dll


BIN
Information Server/libpq.dll


+ 55 - 0
Information Server/main.cpp

@@ -0,0 +1,55 @@
+#include "InformationServer.h"
+#ifdef WIN32
+#include <main.h>
+#endif
+#include <Zeit.h>
+#include <iostream>
+#include <fstream>
+#include <Globals.h>
+
+#ifdef WIN32
+int KSGStart Framework::Start( Startparam p )
+{
+#else
+int main()
+{
+    Framework::initFramework();
+#endif
+	Zeit *z = getZeit();
+	Text *pfad = new Text( "../log/information/" );
+	pfad->anhängen( z->getZeit( "y-m-d h-i-s.log" ) );
+	z->release();
+	DateiPfadErstellen( pfad->getThis() );
+	std::ofstream file;
+	file.open( pfad->getText() );
+	std::streambuf* sbuf = std::cout.rdbuf();
+	std::cout.rdbuf( file.rdbuf() );
+	pfad->release();
+
+	std::cout << "IS: Startet...\n";
+	std::cout << "IS: Lese init Datei ../data/isInit.ini ...\n";
+	InitDatei *dat = new InitDatei( "../data/isInit.ini" );
+	if( !dat->laden() )
+	{
+		std::cout << "IS: error: Datei konnte nicht gelesen werden. Das Programm wird geschlossen.\n";
+		dat->release();
+		exit( 1 );
+	}
+
+	InformationServer *iServer = new InformationServer( dat );
+
+	std::cout << "IS: Der Admin Server läuft. Startforgang beendet.\n";
+	iServer->runn();
+
+	iServer->ende();
+	iServer->release();
+	dat->speichern();
+	dat->release();
+	std::cout << "IS: Der Server ist heruntergefahren.\n";
+	file.close();
+	std::cout.rdbuf( sbuf );
+#ifndef WIN32
+    Framework::releaseFramework();
+#endif
+	return 0;
+}

BIN
Information Server/network.dll


BIN
Information Server/sql.dll


BIN
Information Server/ssleay32.dll


+ 175 - 0
InformationServer/AccountHistorieDaten.cpp

@@ -0,0 +1,175 @@
+#include "AccountHistorieDaten.h"
+
+// Inhalt der AHSpielSpielerDaten Struktur aus AccountHistorieDaten.h
+// Konstruktor
+AHSpielSpielerDaten::AHSpielSpielerDaten()
+	: name( new Text() ),
+	status( new Text() ),
+	ref( 1 )
+{
+}
+
+// Destruktor
+AHSpielSpielerDaten::~AHSpielSpielerDaten()
+{
+	name->release();
+	status->release();
+}
+
+// Reference Counting
+AHSpielSpielerDaten *AHSpielSpielerDaten::getThis()
+{
+	ref++;
+	return this;
+}
+
+AHSpielSpielerDaten *AHSpielSpielerDaten::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der AHSpielTeamDaten Struktur aus AccountHistorieDaten.h
+// Konstruktor
+AHSpielTeamDaten::AHSpielTeamDaten()
+	: name( new Text() ),
+	status( new Text() ),
+	spieler( new RCArray< AHSpielSpielerDaten >() ),
+	ref( 1 )
+{
+}
+
+// Destruktor
+AHSpielTeamDaten::~AHSpielTeamDaten()
+{
+	name->release();
+	status->release();
+	spieler->release();
+}
+
+// Reference Counting
+AHSpielTeamDaten *AHSpielTeamDaten::getThis()
+{
+	ref++;
+	return this;
+}
+
+AHSpielTeamDaten *AHSpielTeamDaten::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der AHSpielDaten Struktur aus AccountHistorieDaten.h
+// Konstruktor
+AHSpielDaten::AHSpielDaten()
+	: spiel( new Text() ),
+	karte( new Text() ),
+	datum( new Text() ),
+	status( new Text() ),
+	dauer( new Text() ),
+	spielStatus( new Text() ),
+	gewinner( new Text() ),
+	teams( new RCArray< AHSpielTeamDaten >() ),
+	ref( 1 )
+{
+}
+
+// Destruktor
+AHSpielDaten::~AHSpielDaten()
+{
+	spiel->release();
+	karte->release();
+	datum->release();
+	status->release();
+	dauer->release();
+	spielStatus->release();
+	gewinner->release();
+	teams->release();
+}
+
+// Reference Counting
+AHSpielDaten *AHSpielDaten::getThis()
+{
+	ref++;
+	return this;
+}
+
+AHSpielDaten *AHSpielDaten::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der AHDaten Struktur aus AccountHistorieDaten.h
+// Konstruktor
+AHDaten::AHDaten()
+	: spiele( new RCArray< AHSpielDaten >() ),
+	ref( 1 )
+{
+}
+
+// Destruktor
+AHDaten::~AHDaten()
+{
+	spiele->release();
+}
+
+// Reference Counting
+AHDaten *AHDaten::getThis()
+{
+	ref++;
+	return this;
+}
+
+AHDaten *AHDaten::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der SpielerTeamStruktur Struktur aus Strukturen.h
+SpielerTeamStruktur::SpielerTeamStruktur()
+{
+	spielerAnzahl = 0;
+	teamAnzahl = 0;
+	spielerFarbe = new Array< int >();
+	teamFarbe = new Array< int >();
+	teamName = new RCArray< Text >();
+	teamSize = new Array< int >();
+	ref = 1;
+}
+
+SpielerTeamStruktur::~SpielerTeamStruktur()
+{
+	spielerFarbe->release();
+	teamFarbe->release();
+	teamName->release();
+	teamSize->release();
+}
+
+SpielerTeamStruktur *SpielerTeamStruktur::getThis()
+{
+	ref++;
+	return this;
+}
+
+SpielerTeamStruktur *SpielerTeamStruktur::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 98 - 0
InformationServer/AccountHistorieDaten.h

@@ -0,0 +1,98 @@
+#ifndef AccountHistorieDaten_H
+#define AccountHistorieDaten_H
+
+#include <Array.h>
+#include <Text.h>
+
+using namespace Framework;
+
+struct AHSpielSpielerDaten
+{
+	Text *name;
+	int punkte;
+	Text *status;
+	int farbe;
+	int ref;
+
+	// Konstruktor
+	AHSpielSpielerDaten();
+	// Destruktor
+	~AHSpielSpielerDaten();
+	// Reference Counting
+	AHSpielSpielerDaten *getThis();
+	AHSpielSpielerDaten *release();
+};
+
+struct AHSpielTeamDaten
+{
+	int id;
+	Text *name;
+	int sAnzahl;
+	Text *status;
+	int farbe;
+	RCArray< AHSpielSpielerDaten > *spieler;
+	int ref;
+
+	// Konstruktor
+	AHSpielTeamDaten();
+	// Destruktor
+	~AHSpielTeamDaten();
+	// Reference Counting
+	AHSpielTeamDaten *getThis();
+	AHSpielTeamDaten *release();
+};
+
+struct AHSpielDaten
+{
+	int id;
+	int karteId;
+	Text *spiel;
+	Text *karte;
+	Text *datum;
+	Text *status;
+	Text *dauer;
+	Text *spielStatus;
+	Text *gewinner;
+	int sAnzahl;
+	RCArray< AHSpielTeamDaten > *teams;
+	int ref;
+
+	// Konstruktor
+	AHSpielDaten();
+	// Destruktor
+	~AHSpielDaten();
+	// Reference Counting
+	AHSpielDaten *getThis();
+	AHSpielDaten *release();
+};
+
+struct AHDaten
+{
+	RCArray< AHSpielDaten > *spiele;
+	int ref;
+
+	// Konstruktor
+	AHDaten();
+	// Destruktor
+	~AHDaten();
+	// Reference Counting
+	AHDaten *getThis();
+	AHDaten *release();
+};
+
+struct SpielerTeamStruktur
+{
+	SpielerTeamStruktur();
+	~SpielerTeamStruktur();
+	int spielerAnzahl;
+	int teamAnzahl;
+	Array< int > *spielerFarbe;
+	Array< int > *teamFarbe;
+	RCArray< Text > *teamName;
+	Array< int > *teamSize;
+	int ref;
+	SpielerTeamStruktur *getThis();
+	SpielerTeamStruktur *release();
+};
+
+#endif

+ 2061 - 0
InformationServer/Datenbank.cpp

@@ -0,0 +1,2061 @@
+#include "Datenbank.h"
+#include <Zeit.h>
+#include "AccountHistorieDaten.h"
+#include "KartenLeser.h"
+
+// Inhalt der LSDatenbank Klasse aus Datenbank.h
+// Konstruktor
+ISDatenbank::ISDatenbank( InitDatei *zIni )
+{
+	if( !zIni->wertExistiert( "DBBenutzer" ) )
+		zIni->addWert( "DBBenutzer", "informationserveru" );
+	if( !zIni->wertExistiert( "DBPasswort" ) )
+		zIni->addWert( "DBPasswort", "LTInformationServerPW" );
+	if( !zIni->wertExistiert( "DBName" ) )
+		zIni->addWert( "DBName", "lenck_tech_db" );
+	if( !zIni->wertExistiert( "DBIP" ) )
+		zIni->addWert( "DBIP", "127.0.0.1" );
+	if( !zIni->wertExistiert( "DBPort" ) )
+		zIni->addWert( "DBPort", "5432" );
+	datenbank = new Datenbank( zIni->zWert( "DBBenutzer" )->getText(), zIni->zWert( "DBPasswort" )->getText(),
+							   zIni->zWert( "DBName" )->getText(), zIni->zWert( "DBIP" )->getText(),
+							   (unsigned short)TextZuInt( zIni->zWert( "DBPort" )->getText(), 10 ) );
+	InitializeCriticalSection( &cs );
+	ref = 1;
+}
+
+// Destruktor
+ISDatenbank::~ISDatenbank()
+{
+	datenbank->release();
+	DeleteCriticalSection( &cs );
+}
+
+// nicht constant
+void ISDatenbank::lock()
+{
+	EnterCriticalSection( &cs );
+}
+
+void ISDatenbank::unlock()
+{
+	LeaveCriticalSection( &cs );
+}
+
+int ISDatenbank::istAdministrator( const char *name, const char *passwort )
+{
+	Text *befehl = new Text( "SELECT id FROM benutzer WHERE name = '" );
+	befehl->append( name );
+	befehl->append( "' AND passwort = '" );
+	befehl->append( passwort );
+	befehl->append( "'" );
+	lock();
+	datenbank->befehl( befehl->getText() );
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	int ret = 0;
+	if( res.zeilenAnzahl > 0 )
+		ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+bool ISDatenbank::adminHatRecht( int id, int recht )
+{
+	Text *befehl = new Text( "SELECT * FROM benutzer_rechte WHERE benutzer_id = " );
+	befehl->append( id );
+	befehl->append( " AND rechte_id = " );
+	befehl->append( recht );
+	lock();
+	datenbank->befehl( befehl->getText() );
+	int ret = datenbank->getZeilenAnzahl();
+	unlock();
+	befehl->release();
+	return ret != 0;
+}
+
+bool ISDatenbank::proveKlient( int num, int sNum )
+{
+	Text *befehl = new Text( "SELECT * FROM server_information_clients WHERE server_information_id = " );
+	befehl->append( sNum );
+	befehl->append( " AND client_id = " );
+	befehl->append( num );
+	lock();
+	datenbank->befehl( befehl->getText() );
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	bool ret = 0;
+	if( res.zeilenAnzahl == 1 )
+		ret = 1;
+	res.destroy();
+	return ret;
+}
+
+Text *ISDatenbank::getKlientKey( int cId )
+{
+	lock();
+	if( !datenbank->befehl( Text( "SELECT schluessel FROM clients WHERE id = " ) += cId ) )
+	{
+		unlock();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+void ISDatenbank::unregisterKlient( int num, int sNum )
+{
+	Text *befehl = new Text( "DELETE FROM server_information_clients WHERE client_id = " );
+	befehl->append( num );
+	befehl->append( " AND server_information_id = " );
+	befehl->append( sNum );
+	lock();
+	datenbank->befehl( befehl->getText() );
+	int za = datenbank->getZeilenAnzahl();
+	unlock();
+	if( za == 1 )
+	{
+		befehl->setText( "UPDATE server_information SET clients = clients - 1 WHERE id = " );
+		befehl->append( sNum );
+		lock();
+		datenbank->befehl( befehl->getText() );
+		unlock();
+	}
+	befehl->release();
+}
+
+bool ISDatenbank::serverAnmelden( InitDatei *zIni )
+{
+	if( !zIni->wertExistiert( "ServerId" ) )
+		zIni->addWert( "ServerId", "0" );
+	if( !zIni->wertExistiert( "ServerName" ) )
+		zIni->addWert( "ServerName", "Name" );
+	if( !zIni->wertExistiert( "ServerPort" ) )
+		zIni->addWert( "ServerPort", "49144" );
+	if( !zIni->wertExistiert( "ServerIP" ) )
+		zIni->addWert( "ServerIP", "127.0.0.1" );
+	if( !zIni->wertExistiert( "AdminServerPort" ) )
+		zIni->addWert( "AdminServerPort", "49143" );
+	if( !zIni->wertExistiert( "Aktiv" ) )
+		zIni->addWert( "Aktiv", "FALSE" );
+	if( !zIni->wertExistiert( "MaxClients" ) )
+		zIni->addWert( "MaxClients", "50" );
+	bool insert = 0;
+	int id = *zIni->zWert( "ServerId" );
+	if( id )
+	{
+		lock();
+		if( !datenbank->befehl( Text( "SELECT id FROM server_information WHERE id = " ) += id ) )
+		{
+			unlock();
+			return 0;
+		}
+		int anz = datenbank->getZeilenAnzahl();
+		unlock();
+		insert = anz == 0;
+		if( !insert )
+		{
+			lock();
+			if( !datenbank->befehl( Text( "SELECT id FROM server_information WHERE server_status_id = 1 AND id = " ) += id ) )
+			{
+				unlock();
+				return 0;
+			}
+			int anz = datenbank->getZeilenAnzahl();
+			unlock();
+			if( !anz ) // Server läuft bereits
+				return 0;
+		}
+	}
+	if( insert || !id )
+	{ // Neuer Eintrag in Tabelle server_information
+		Text *befehl = new Text( "INSERT INTO server_information( " );
+		if( id )
+			*befehl += "id, ";
+		*befehl += "name, ip, port, admin_port, server_status_id, max_clients ) VALUES( ";
+		if( id )
+		{
+			*befehl += id;
+			*befehl += ", ";
+		}
+		*befehl += "'";
+		*befehl += zIni->zWert( "ServerName" )->getText();
+		*befehl += "', '";
+		*befehl += zIni->zWert( "ServerIP" )->getText();
+		*befehl += "', ";
+		*befehl += zIni->zWert( "ServerPort" )->getText();
+		*befehl += ", ";
+		*befehl += zIni->zWert( "AdminServerPort" )->getText();
+		*befehl += ", 1, ";
+		*befehl += zIni->zWert( "MaxClients" )->getText();
+		*befehl += " ) RETURNING id";
+		lock();
+		if( !datenbank->befehl( *befehl ) )
+		{
+			unlock();
+			befehl->release();
+			return 0;
+		}
+		Result res = datenbank->getResult();
+		unlock();
+		befehl->release();
+		if( !res.zeilenAnzahl )
+		{
+			res.destroy();
+			return 0;
+		}
+		zIni->setWert( "ServerId", res.values[ 0 ] );
+		return 1;
+	}
+	else
+	{ // Alten Eintrag aus Tabelle server_information ändern
+		Text *befehl = new Text( "UPDATE server_information SET name = '" );
+		*befehl += zIni->zWert( "ServerName" )->getText();
+		*befehl += "', port = ";
+		*befehl += zIni->zWert( "ServerPort" )->getText();
+		*befehl += ", ip = '";
+		*befehl += zIni->zWert( "ServerIP" )->getText();
+		*befehl += "', max_clients = ";
+		*befehl += zIni->zWert( "MaxClients" )->getText();
+		*befehl += ", admin_port = ";
+		*befehl += zIni->zWert( "AdminServerPort" )->getText();
+		*befehl += " WHERE id = ";
+		*befehl += id;
+		lock();
+		bool ret = datenbank->befehl( *befehl );
+		unlock();
+		befehl->release();
+		return ret;
+	}
+}
+
+bool ISDatenbank::setServerStatus( int id, int status )
+{
+	Text *befehl = new Text( "UPDATE server_information SET server_status_id = " );
+	*befehl += status;
+	*befehl += "WHERE id = ";
+	*befehl += id;
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	bool ret = datenbank->getZeilenAnzahl() != 0;
+	unlock();
+	befehl->release();
+	return ret;
+}
+
+bool ISDatenbank::setMaxClients( int id, int maxC )
+{
+	Text *befehl = new Text( "UPDATE server_information SET max_clients = " );
+	befehl->append( maxC );
+	befehl->append( " WHERE id = " );
+	befehl->append( id );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	bool ret = datenbank->getZeilenAnzahl() > 0;
+	unlock();
+	befehl->release();
+	return ret;
+}
+
+int ISDatenbank::getAdminPort( int id )
+{
+	Text *befehl = new Text( "SELECT admin_port FROM server_information WHERE id = " );
+	befehl->append( id );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+bool ISDatenbank::serverIstNichtPausiert( int id )
+{
+	Text *befehl = new Text( "SELECT server_status_id FROM server_information WHERE id = " );
+	befehl->append( id );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	bool ret = (int)res.values[ 0 ] == 3;
+	res.destroy();
+	return ret;
+}
+
+Text *ISDatenbank::getInformationsText( char *typ )
+{
+	lock();
+	if( !datenbank->befehl( "SELECT text, typ FROM info_text ORDER BY insert_datum DESC LIMIT 1" ) )
+	{
+		unlock();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		*typ = 0;
+		return 0;
+	}
+	*typ = (char)TextZuInt( res.values[ 1 ].getText(), 10 );
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+bool ISDatenbank::istSpielErlaubt( int spielId )
+{
+	Text *befehl = new Text( "SELECT erlaubt FROM spiel_art WHERE id = " );
+	befehl->append( spielId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	bool ret = 0;
+	if( res.zeilenAnzahl > 0 && res.values[ 0 ].istGleich( "t" ) )
+		ret = 1;
+	res.destroy();
+	return ret;
+}
+
+bool ISDatenbank::istKarteErlaubt( int karteId )
+{
+	Text *befehl = new Text( "SELECT erlaubt FROM karte WHERE id = " );
+	befehl->append( karteId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	bool ret = 0;
+	if( res.zeilenAnzahl > 0 && res.values[ 0 ].istGleich( "t" ) )
+		ret = 1;
+	res.destroy();
+	return ret;
+}
+
+Text *ISDatenbank::getAccountRufName( int accountId )
+{
+	Text *befehl = new Text( "SELECT ruf_name FROM account WHERE id = " );
+	befehl->append( accountId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getAccountId( char *rufName )
+{
+	Text *befehl = new Text( "SELECT id FROM account WHERE ruf_name = '" );
+	befehl->append( rufName );
+	befehl->append( "' LIMIT 1" );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+Array< int > *ISDatenbank::getAccountSpielStatistik( int accountId, int spielId )
+{
+	Text *befehl = new Text( "SELECT gespielt, gewonnen, verloren, punkte, bw0, bw1, bw2, bw3, bw4, bw5 FROM spiel_statistik WHERE account_id = " );
+	befehl->append( accountId );
+	befehl->append( " AND spiel_art_id = " );
+	befehl->append( spielId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	Array< int > *ret = new Array< int >();
+	if( !res.zeilenAnzahl )
+	{
+		for( int i = 0; i < res.feldAnzahl; i++ )
+			ret->add( 0, i );
+		res.destroy();
+		return ret;
+	}
+	for( int i = 0; i < res.feldAnzahl; i++ )
+		ret->add( TextZuInt( res.values[ i ].getText(), 10 ), i );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getAccountKarteSpiele( int accountId, int karteId )
+{
+	Text *befehl = new Text( "SELECT count( a.id ) FROM spiel a, spiel_spieler b WHERE a.id = b.spiel_id AND b.account_id = " );
+	befehl->append( accountId );
+	befehl->append( " AND a.karte_id = " );
+	befehl->append( karteId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = res.values[ 0 ];
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getAccountKarteSpieleGewonnen( int accountId, int karteId )
+{
+	Text *befehl = new Text( "SELECT count( a.id ) FROM spiel a, spiel_spieler b WHERE a.id = b.spiel_id "
+							 "AND b.spiel_spieler_status_id = 2 AND b.account_id = " );
+	befehl->append( accountId );
+	befehl->append( " AND a.karte_id = " );
+	befehl->append( karteId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = res.values[ 0 ];
+	res.destroy();
+	return ret;
+}
+
+Text *ISDatenbank::getKarteName( int karteId )
+{
+	Text *befehl = new Text( "SELECT name FROM karte WHERE id = " );
+	befehl->append( karteId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+Text *ISDatenbank::getSpielName( int spielId )
+{
+	Text *befehl = new Text( "SELECT name FROM spiel_art WHERE id = " );
+	befehl->append( spielId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+Text *ISDatenbank::getChatroomName( int chatroomId )
+{
+	Text *befehl = new Text( "SELECT name FROM chatroom WHERE id = " );
+	befehl->append( chatroomId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getChatroomId( char *name )
+{
+	Text *befehl = new Text( "SELECT id FROM chatroom WHERE name = '" );
+	befehl->append( name );
+	befehl->append( "' LIMIT 1" );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getSpielId( int karteId )
+{
+	Text *befehl = new Text( "SELECT spiel_art_id FROM karte WHERE id = " );
+	befehl->append( karteId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getSpielId( char *name )
+{
+	Text *befehl = new Text( "SELECT id FROM spiel_art WHERE name = '" );
+	befehl->append( name );
+	befehl->append( "'" );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getKarteId( char *name )
+{
+	Text *befehl = new Text( "SELECT id FROM karte WHERE name = '" );
+	befehl->append( name );
+	befehl->append( "'" );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getGruppenKarteId( int gruppeId )
+{
+	Text *befehl = new Text( "SELECT karte_id FROM gruppe WHERE id = " );
+	befehl->append( gruppeId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getGruppeAdminId( int gruppeId )
+{
+	Text *befehl = new Text( "SELECT admin_account_id FROM gruppe WHERE id = " );
+	befehl->append( gruppeId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getSpielerPunkte( int spielId, int accountId )
+{
+	Text *befehl = new Text( "SELECT sum( b.punkte ) FROM spiel a, spiel_spieler b, karte c WHERE a.karte_id = c.id "
+							 "AND a.spiel_status_id = 5 AND c.spiel_art_id = " );
+	befehl->append( spielId );
+	befehl->append( " AND b.spiel_id = a.id AND b.account_id = " );
+	befehl->append( accountId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+Array< int > *ISDatenbank::getAccountSpielArtListe( int cId )
+{
+	Text *befehl = new Text( "SELECT a.spiel_art_id FROM spiel_art_account a, account_clients b "
+							 "WHERE a.account_id = b.account_id AND a.end_dat IS NULL AND b.client_id = " );
+	befehl->append( cId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	Array< int > *ret = new Array< int >();
+	for( int i = 0; i < res.zeilenAnzahl; i++ )
+		ret->add( TextZuInt( res.values[ i ].getText(), 10 ) );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getNeusteSpielVersion( int sId )
+{
+	Text *befehl = new Text( "SELECT a.version FROM datei_gruppe a, spiel_art b WHERE a.id = b.datei_gruppe_id AND b.id = " );
+	befehl->append( sId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getKupfer( int cId )
+{
+	Text *befehl = new Text( "SELECT a.kupfer FROM account a, account_clients b WHERE a.id = b.account_id AND b.client_id = " );
+	befehl->append( cId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getDateiGruppeVonSpiel( int sId )
+{
+	Text *befehl = new Text( "SELECT datei_gruppe_id FROM spiel_art WHERE id = " );
+	befehl->append( sId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+Text *ISDatenbank::getDateiGruppePfad( int dgId )
+{
+	Text *befehl = new Text( "SELECT pfad FROM datei_gruppe WHERE id = " );
+	befehl->append( dgId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	Text *ret = new Text( res.values[ 0 ].getText() );
+	res.destroy();
+	return ret;
+}
+
+Array< int > *ISDatenbank::getAccountKarteListe( int cId, int sId )
+{
+	Text *befehl = new Text( "SELECT a.karte_id FROM karte_account a, account_clients b, karte c "
+							 "WHERE c.id = a.karte_id AND a.account_id = b.account_id AND a.end_dat IS NULL AND b.client_id = " );
+	befehl->append( cId );
+	befehl->append( " AND c.spiel_art_id = " );
+	befehl->append( sId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	Array< int > *ret = new Array< int >();
+	for( int i = 0; i < res.zeilenAnzahl; i++ )
+		ret->add( TextZuInt( res.values[ i ].getText(), 10 ) );
+	res.destroy();
+	return ret;
+}
+
+bool ISDatenbank::hatAccountKarte( int account, int karte )
+{
+	Text *befehl = new Text( "SELECT karte_id FROM karte_account WHERE end_dat IS NULL AND karte_id = " );
+	befehl->append( karte );
+	befehl->append( " AND account_id = " );
+	befehl->append( account );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	bool ret = datenbank->getZeilenAnzahl() != 0;
+	unlock();
+	befehl->release();
+	return ret;
+}
+
+bool ISDatenbank::hatAccountSpiel( int account, int spiel )
+{
+	Text *befehl = new Text( "SELECT spiel_art_id FROM spiel_art_account WHERE end_dat IS NULL AND spiel_art_id = " );
+	befehl->append( spiel );
+	befehl->append( " AND account_id = " );
+	befehl->append( account );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	bool ret = datenbank->getZeilenAnzahl() != 0;
+	unlock();
+	befehl->release();
+	return ret;
+}
+
+Array< int > *ISDatenbank::getAccountKarteGespieltListe( int accountId, int spielArt )
+{
+	Text *befehl = new Text( "SELECT distinct( c.id ) FROM spiel a, spiel_spieler b, karte c WHERE "
+							 "a.karte_id = c.id AND b.spiel_id = a.id AND b.account_id = " );
+	befehl->append( accountId );
+	befehl->append( " AND c.spiel_art_id = " );
+	befehl->append( spielArt );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	Array< int > *ret = new Array< int >();
+	for( int i = 0; i < res.zeilenAnzahl; i++ )
+		ret->set( res.values[ i ], i );
+	res.destroy();
+	return ret;
+}
+
+Array< int > *ISDatenbank::getAccountSpielGespieltListe( int accountId )
+{
+	Text *befehl = new Text( "SELECT distinct( c.spiel_art_id ) FROM spiel a, spiel_spieler b, karte c WHERE "
+							 "a.karte_id = c.id AND b.spiel_id = a.id AND b.account_id = " );
+	befehl->append( accountId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	Array< int > *ret = new Array< int >();
+	for( int i = 0; i < res.zeilenAnzahl; i++ )
+		ret->set( res.values[ i ], i );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getDateiGruppeVonPfad( char *pfad )
+{
+	Text *befehl = new Text( "SELECT id FROM datei_gruppe WHERE pfad = '" );
+	befehl->append( pfad );
+	befehl->append( "'" );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+int ISDatenbank::getNeusteDateiGruppe( int dg )
+{
+	Text *befehl = new Text( "SELECT version FROM datei_gruppe WHERE id = " );
+	befehl->append( dg );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+	res.destroy();
+	return ret;
+}
+
+bool ISDatenbank::getGruppeSpielerAdd( int gruppeId )
+{
+	Text *befehl = new Text( "SELECT spiel_starten FROM gruppe WHERE id = " );
+	befehl->append( gruppeId );
+	lock();
+	if( !datenbank->befehl( befehl->getText() ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	bool ret = res.values[ 0 ].istGleich( "f" );
+	res.destroy();
+	return ret;
+}
+
+Result ISDatenbank::getSpielerListe( char *suche, int *seite, int *maxSeite, int sortStalte, bool backwords )
+{
+	Text *befehl = new Text( "SELECT count( a.id ) FROM account a, "
+							 "( SELECT a.id, max( b.datum ) "
+							 "  FROM account a LEFT JOIN "
+							 "  ( SELECT g.spiel_art_id, i.account_id, max( h.beginn_datum ) "
+							 "    FROM karte g, spiel h, spiel_spieler i "
+							 "    WHERE i.spiel_id = h.id AND h.karte_id = g.id "
+							 "    GROUP BY g.spiel_art_id, i.account_id ) f ON a.id = f.account_id "
+							 "  LEFT JOIN account_online b ON b.account_id = a.id "
+							 "  LEFT JOIN spiel_statistik e ON e.account_id = a.id "
+							 "  LEFT JOIN spiel_art c ON c.id = f.spiel_art_id "
+							 "  LEFT JOIN karte d ON c.id = d.spiel_art_id "
+							 "  WHERE a.name LIKE '" );
+	befehl->append( suche );
+	befehl->append( "' AND d.spiel_art_id = c.id "
+					  "  AND e.spiel_art_id = f.spiel_art_id "
+					  "  GROUP BY a.id ) b "
+					  "WHERE a.id = b.id" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	int entrys = res.values[ 0 ];
+	res.destroy();
+	*maxSeite = entrys / 21;
+	if( entrys % 21 )
+		( *maxSeite )++;
+	if( *seite > *maxSeite )
+		*seite = *maxSeite;
+	if( !( *seite ) )
+	{
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	befehl->setText( "SELECT a.id, a.ruf_name, max( b.datum ), c.name, d.name, e.punkte "
+					 "FROM account a LEFT JOIN "
+					 "( SELECT g.spiel_art_id, i.account_id, max( h.beginn_datum ) "
+					 "  FROM karte g, spiel h, spiel_spieler i "
+					 "  WHERE i.spiel_id = h.id AND h.karte_id = g.id "
+					 "  GROUP BY g.spiel_art_id, i.account_id ) f ON a.id = f.account_id "
+					 "LEFT JOIN account_online b ON b.account_id = a.id "
+					 "LEFT JOIN spiel_statistik e ON e.account_id = a.id "
+					 "LEFT JOIN spiel_art c ON c.id = f.spiel_art_id "
+					 "LEFT JOIN karte d ON c.id = d.spiel_art_id "
+					 "WHERE a.name LIKE '" );
+	befehl->append( suche );
+	befehl->append( "' AND ( d.spiel_art_id = c.id "
+					  "AND e.spiel_art_id = f.spiel_art_id ) "
+					  "OR d.spiel_art_id IS NULL "
+					  "GROUP BY a.id, a.ruf_name, c.name, d.name, e.punkte ORDER BY " );
+	befehl->append( sortStalte + 2 );
+	if( backwords )
+		befehl->append( " DESC" );
+	befehl->append( " OFFSET " );
+	befehl->append( ( ( *seite ) - 1 ) * 21 );
+	befehl->append( " LIMIT 21" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	return res;
+}
+
+bool ISDatenbank::getSpielerAktivity( int accountId, RCArray< Text > *datum, Array< double > *stOnline, Array< double > *stGespielt,
+									   Array< int > *anzSpiele, Array< int > *anzGewonnen )
+{
+	Datum *beg = getDatum();
+	Datum *end = getDatum();
+	beg->minusTag( 29 );
+	end->minusTag( 29 );
+	end->plusTag( 1 );
+	for( int i = 0; i < 30; i++ )
+	{ // 30 Tage Rückblick
+		datum->set( beg->getDatum( "d-m-y" ), i );
+		Text *b = beg->getDatum( "y-m-d" );
+		Text *e = end->getDatum( "y-m-d" );
+		stOnline->set( getOnlineSeconds( accountId, *b, *e ) / ( 60.0 * 60 ), i );
+		stGespielt->set( getGespieltSeconds( accountId, *b, *e ) / ( 60.0 * 60 ), i );
+		anzSpiele->set( getGespieltSpiele( accountId, *b, *e ), i );
+		anzGewonnen->set( getGewonnenSpiele( accountId, *b, *e ), i );
+		b->release();
+		e->release();
+		beg->plusTag( 1 );
+		end->plusTag( 1 );
+	}
+	return 1;
+}
+
+int ISDatenbank::getOnlineSeconds( int accountId, char *beg, char *end )
+{
+	int sec = 0;
+	Text *befehl = new Text( "SELECT date_part( 'epoch', ( SELECT sum( now() - '" );
+	befehl->append( beg );
+	befehl->append( "' ) FROM account_online WHERE datum < '" );
+	befehl->append( beg );
+	befehl->append( "' AND now() < '" );
+	befehl->append( end );
+	befehl->append( "' AND now() > '" );
+	befehl->append( beg );
+	befehl->append( "' AND end_datum IS NULL AND account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( now() - datum ) FROM account_online WHERE datum > '" );
+	befehl->append( beg );
+	befehl->append( "' AND now() < '" );
+	befehl->append( end );
+	befehl->append( "' AND end_datum IS NULL AND account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->append( end );
+	befehl->append( "' - datum ) FROM account_online WHERE datum > '" );
+	befehl->append( beg );
+	befehl->append( "' AND datum < '" );
+	befehl->append( end );
+	befehl->append( "' AND now() > '" );
+	befehl->append( end );
+	befehl->append( "' AND end_datum IS NULL AND account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->append( end );
+	befehl->append( "'::TIMESTAMP WITH TIME ZONE - '" );
+	befehl->append( beg );
+	befehl->append( "' ) FROM account_online WHERE datum < '" );
+	befehl->append( beg );
+	befehl->append( "' AND now() > '" );
+	befehl->append( end );
+	befehl->append( "' AND end_datum IS NULL AND account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( end_datum - '" );
+	befehl->append( beg );
+	befehl->append( "' ) FROM account_online WHERE datum < '" );
+	befehl->append( beg );
+	befehl->append( "' AND end_datum < '" );
+	befehl->append( end );
+	befehl->append( "' AND end_datum > '" );
+	befehl->append( beg );
+	befehl->append( "' AND account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( end_datum - datum ) FROM account_online WHERE datum > '" );
+	befehl->append( beg );
+	befehl->append( "' AND end_datum < '" );
+	befehl->append( end );
+	befehl->append( "' AND account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->append( end );
+	befehl->append( "' - datum ) FROM account_online WHERE datum > '" );
+	befehl->append( beg );
+	befehl->append( "' AND datum < '" );
+	befehl->append( end );
+	befehl->append( "' AND end_datum > '" );
+	befehl->append( end );
+	befehl->append( "' AND account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->append( end );
+	befehl->append( "'::TIMESTAMP WITH TIME ZONE - '" );
+	befehl->append( beg );
+	befehl->append( "' ) FROM account_online WHERE datum < '" );
+	befehl->append( beg );
+	befehl->append( "' AND end_datum > '" );
+	befehl->append( end );
+	befehl->append( "' AND account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->release();
+	return sec;
+}
+
+int ISDatenbank::getGespieltSeconds( int accountId, char *beg, char *end )
+{
+	int sec = 0;
+	Text *befehl = new Text( "SELECT date_part( 'epoch', ( SELECT sum( now() - '" );
+	befehl->append( beg );
+	befehl->append( "' ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum < '" );
+	befehl->append( beg );
+	befehl->append( "' AND now() < '" );
+	befehl->append( end );
+	befehl->append( "' AND now() > '" );
+	befehl->append( beg );
+	befehl->append( "' AND a.end_datum IS NULL AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( now() - a.beginn_datum ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum > '" );
+	befehl->append( beg );
+	befehl->append( "' AND now() < '" );
+	befehl->append( end );
+	befehl->append( "' AND a.end_datum IS NULL AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->append( end );
+	befehl->append( "' - a.beginn_datum ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum > '" );
+	befehl->append( beg );
+	befehl->append( "' AND a.beginn_datum < '" );
+	befehl->append( end );
+	befehl->append( "' AND now() > '" );
+	befehl->append( end );
+	befehl->append( "' AND a.end_datum IS NULL AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->append( end );
+	befehl->append( "'::TIMESTAMP WITH TIME ZONE - '" );
+	befehl->append( beg );
+	befehl->append( "' ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum < '" );
+	befehl->append( beg );
+	befehl->append( "' AND now() > '" );
+	befehl->append( end );
+	befehl->append( "' AND a.end_datum IS NULL AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( a.end_datum - '" );
+	befehl->append( beg );
+	befehl->append( "' ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum < '" );
+	befehl->append( beg );
+	befehl->append( "' AND a.end_datum < '" );
+	befehl->append( end );
+	befehl->append( "' AND a.end_datum > '" );
+	befehl->append( beg );
+	befehl->append( "' AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( a.end_datum - a.beginn_datum ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum > '" );
+	befehl->append( beg );
+	befehl->append( "' AND a.end_datum < '" );
+	befehl->append( end );
+	befehl->append( "' AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->append( end );
+	befehl->append( "' - a.beginn_datum ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum > '" );
+	befehl->append( beg );
+	befehl->append( "' AND a.beginn_datum < '" );
+	befehl->append( end );
+	befehl->append( "' AND a.end_datum > '" );
+	befehl->append( end );
+	befehl->append( "' AND a.id = b.spiel_id AND account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT date_part( 'epoch', ( SELECT sum( '" );
+	befehl->append( end );
+	befehl->append( "'::TIMESTAMP WITH TIME ZONE - '" );
+	befehl->append( beg );
+	befehl->append( "' ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum < '" );
+	befehl->append( beg );
+	befehl->append( "' AND a.end_datum > '" );
+	befehl->append( end );
+	befehl->append( "' AND a.id = b.spiel_id AND account_id = " );
+	befehl->append( accountId );
+	befehl->append( " )::INTERVAL )" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		sec += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->release();
+	return sec;
+}
+
+int ISDatenbank::getGespieltSpiele( int accountId, char *beg, char *end )
+{
+	int anz = 0;
+	Text *befehl = new Text( "SELECT count( a.id ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum < '" );
+	befehl->append( beg );
+	befehl->append( "' AND a.end_datum < '" );
+	befehl->append( end );
+	befehl->append( "' AND a.end_datum > '" );
+	befehl->append( beg );
+	befehl->append( "' AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->append( accountId );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		anz += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT count( a.id ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum > '" );
+	befehl->append( beg );
+	befehl->append( "' AND a.end_datum < '" );
+	befehl->append( end );
+	befehl->append( "' AND a.id = b.spiel_id AND b.account_id = " );
+	befehl->append( accountId );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		anz += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->release();
+	return anz;
+}
+
+int ISDatenbank::getGewonnenSpiele( int accountId, char *beg, char *end )
+{
+	int anz = 0;
+	Text *befehl = new Text( "SELECT count( a.id ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum < '" );
+	befehl->append( beg );
+	befehl->append( "' AND a.end_datum < '" );
+	befehl->append( end );
+	befehl->append( "' AND a.end_datum > '" );
+	befehl->append( beg );
+	befehl->append( "' AND a.id = b.spiel_id AND b.spiel_spieler_status_id = 2 AND b.account_id = " );
+	befehl->append( accountId );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		anz += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->setText( "SELECT count( a.id ) FROM spiel a, spiel_spieler b WHERE a.beginn_datum > '" );
+	befehl->append( beg );
+	befehl->append( "' AND a.end_datum < '" );
+	befehl->append( end );
+	befehl->append( "' AND a.id = b.spiel_id AND b.spiel_spieler_status_id = 2 AND b.account_id = " );
+	befehl->append( accountId );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	res = datenbank->getResult();
+	unlock();
+	if( res.zeilenAnzahl )
+		anz += (int)res.values[ 0 ];
+	res.destroy();
+	befehl->release();
+	return anz;
+}
+
+Result ISDatenbank::getSpielPartnerListe( int accountId )
+{
+	Text *befehl = new Text( "SELECT account_id_b, anzahl, karte_id FROM account_mitspieler WHERE account_id_a = " );
+	befehl->append( accountId );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	return res;
+}
+
+Result ISDatenbank::getSpielStatistikListe( int accountId, int *seite, int *maxSeite, int sortStalte, bool backwords )
+{
+	Text *befehl = new Text( "SELECT count( spiel_art_id ) FROM spiel_statistik WHERE account_id = " );
+	befehl->append( accountId );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	int entrys = res.values[ 0 ];
+	res.destroy();
+	*maxSeite = entrys / 21;
+	if( entrys % 21 )
+		( *maxSeite )++;
+	if( *seite > *maxSeite )
+		*seite = *maxSeite;
+	if( !( *seite ) )
+	{
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	befehl->setText( "SELECT a.id, a.name, b.gespielt, b.gewonnen, b.verloren, b.punkte, b.bw0, b.bw1, b.bw2, b.bw3, "
+					 "b.bw4, b.bw5 FROM spiel_art a, spiel_statistik b WHERE a.id = b.spiel_art_id AND b.account_id = " );
+	befehl->append( accountId );
+	befehl->append( " ORDER BY " );
+	befehl->append( sortStalte + 2 );
+	if( backwords )
+		befehl->append( " DESC" );
+	befehl->append( " OFFSET " );
+	befehl->append( ( ( *seite ) - 1 ) * 18 );
+	befehl->append( " LIMIT 18" );
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	res = datenbank->getResult();
+	unlock();
+	befehl->release();
+	return res;
+}
+
+AHDaten *ISDatenbank::getSpielHistorie( int accountId, InformationServer *is )
+{
+	Text *befehl = new Text( "SELECT a.id, a.karte_id, c.name, d.name, substring( a.beginn_datum::CHARACTER VARYING FOR 16 ), "
+							 "b.spiel_spieler_status_id, a.spiel_status_id, count( e.spiel_id ) "
+							 "FROM spiel a, spiel_spieler b, spiel_art c, karte d, (SELECT spiel_id FROM spiel_spieler) e "
+							 "WHERE a.id = e.spiel_id AND a.karte_id = d.id AND d.spiel_art_id = c.id "
+							 "AND a.id = b.spiel_id AND b.account_id = " );
+	*befehl += accountId;
+	*befehl += " GROUP BY a.id, a.karte_id, c.name, d.name, a.beginn_datum, b.spiel_spieler_status_id, a.spiel_status_id "
+			   "ORDER BY beginn_datum DESC LIMIT 20";
+	lock();
+	if( !datenbank->befehl( *befehl ) )
+	{
+		unlock();
+		befehl->release();
+		return 0;
+	}
+	Result spielListe = datenbank->getResult();
+	unlock();
+	AHDaten *ret = new AHDaten();
+	for( int i = 0; i < spielListe.zeilenAnzahl; i++ )
+	{
+		SpielerTeamStruktur *sts = new SpielerTeamStruktur();
+		bool stsOK = 1;
+		KartenLeser *reader = new KartenLeser( spielListe.values[ 1 + i * spielListe.feldAnzahl ], is );
+		if( !reader->ladeSpielerTeamStruktur( sts ) )
+			stsOK = 0;
+		reader->release();
+		AHSpielDaten *spiel = new AHSpielDaten();
+		spiel->id = spielListe.values[ i * spielListe.feldAnzahl ];
+		spiel->karteId = spielListe.values[ 1 + i * spielListe.feldAnzahl ];
+		spiel->spiel->setText( spielListe.values[ 2 + i * spielListe.feldAnzahl ] );
+		spiel->karte->setText( spielListe.values[ 3 + i * spielListe.feldAnzahl ] );
+		spiel->datum->setText( spielListe.values[ 4 + i * spielListe.feldAnzahl ] );
+		switch( (int)spielListe.values[ 5 + i * spielListe.feldAnzahl ] )
+		{
+		case 1:
+			spiel->status->setText( "Verloren" );
+			break;
+		case 2:
+			spiel->status->setText( "Gewonnen" );
+			break;
+		case 3:
+			spiel->status->setText( "Nicht Anwesend" );
+			break;
+		case 4:
+			spiel->status->setText( "Beobachter" );
+			break;
+		case 5:
+			spiel->status->setText( "Unentschieden" );
+			break;
+		}
+		switch( (int)spielListe.values[ 6 + i * spielListe.feldAnzahl ] )
+		{
+		case 1:
+			spiel->spielStatus->setText( "Beginnt" );
+			break;
+		case 2:
+			spiel->spielStatus->setText( "Läuft" );
+			break;
+		case 3:
+			spiel->spielStatus->setText( "Abgebrochen" );
+			break;
+		case 4:
+			spiel->spielStatus->setText( "Fehlerhaft" );
+			break;
+		case 5:
+			spiel->spielStatus->setText( "Beendet" );
+			break;
+		case 6:
+			spiel->spielStatus->setText( "Unbewertet" );
+			break;
+		}
+		spiel->sAnzahl = spielListe.values[ 7 + i * spielListe.feldAnzahl ];
+		*befehl = "SELECT substring( (end_datum - beginn_datum)::CHARACTER VARYING FOR 8) FROM spiel WHERE id = ";
+		*befehl += spielListe.values[ i * spielListe.feldAnzahl ].getText();
+		lock();
+		if( datenbank->befehl( *befehl ) )
+		{
+			Result dauer = datenbank->getResult();
+			unlock();
+			if( dauer.zeilenAnzahl && dauer.values[ 0 ].getLength() )
+				spiel->dauer->setText( dauer.values[ 0 ] );
+		}
+		else
+			unlock();
+		int gewinnerTeam = -1;
+		if( stsOK )
+		{
+			*befehl = "SELECT team_id FROM spiel_spieler WHERE spiel_spieler_status_id = 2 AND spiel_id = ";
+			*befehl += spielListe.values[ i * spielListe.feldAnzahl ].getText();
+			lock();
+			if( datenbank->befehl( *befehl ) )
+			{
+				Result team = datenbank->getResult();
+				unlock();
+				if( team.zeilenAnzahl && team.values[ 0 ].getLength() && sts->teamName->z( team.values[ 0 ] ) )
+				{
+					spiel->gewinner->setText( sts->teamName->z( team.values[ 0 ] )->getText() );
+					gewinnerTeam = team.values[ 0 ];
+				}
+			}
+			else
+				unlock();
+		}
+		*befehl = "SELECT a.ruf_name, b.team_id, b.punkte, b.spiel_spieler_status_id, b.spieler_nummer FROM account a, spiel_spieler b WHERE b.account_id = a.id AND spiel_id = ";
+		*befehl += spielListe.values[ i * spielListe.feldAnzahl ].getText();
+		*befehl += " ORDER BY team_id";
+		lock();
+		if( datenbank->befehl( *befehl ) )
+		{
+			Result spielerListe = datenbank->getResult();
+			unlock();
+			for( int j = 0; j < spielerListe.zeilenAnzahl; j++ )
+			{
+				int tAnz = spiel->teams->getEintragAnzahl();
+				int index = -1;
+				for( int k = 0; k < tAnz; k++ )
+				{
+					if( spiel->teams->z( k )->id == (int)spielerListe.values[ 1 + j * spielerListe.feldAnzahl ] )
+					{
+						index = k;
+						break;
+					}
+				}
+				if( index < 0 )
+				{
+					index = tAnz;
+					AHSpielTeamDaten *team = new AHSpielTeamDaten();
+					team->id = spielerListe.values[ 1 + j * spielerListe.feldAnzahl ];
+					if( sts->teamName->z( team->id ) )
+						team->name->setText( sts->teamName->z( team->id )->getText() );
+					team->sAnzahl = 0;
+					if( team->id == gewinnerTeam )
+						team->status->setText( "Gewonnen" );
+					else
+						team->status->setText( "Verloren" );
+					if( sts->teamFarbe->hat( team->id ) )
+						team->farbe = sts->teamFarbe->get( team->id );
+					else
+						team->farbe = 0;
+					spiel->teams->set( team, index );
+				}
+				AHSpielSpielerDaten *spieler = new AHSpielSpielerDaten();
+				spieler->name->setText( spielerListe.values[ j * spielerListe.feldAnzahl ] );
+				spieler->punkte = spielerListe.values[ 2 + j * spielerListe.feldAnzahl ];
+				if( sts->spielerFarbe->hat( (int)spielerListe.values[ 4 + j * spielerListe.feldAnzahl ] - 1 ) )
+					spieler->farbe = sts->spielerFarbe->get( (int)spielerListe.values[ 4 + j * spielerListe.feldAnzahl ] - 1 );
+				else
+					spieler->farbe = 0;
+				switch( (int)spielerListe.values[ 3 + j * spielerListe.feldAnzahl ] )
+				{
+				case 1:
+					spieler->status->setText( "Verloren" );
+					break;
+				case 2:
+					spieler->status->setText( "Gewonnen" );
+					break;
+				case 3:
+					spieler->status->setText( "Nicht Anwesend" );
+					break;
+				case 4:
+					spieler->status->setText( "Beobachter" );
+					break;
+				case 5:
+					spieler->status->setText( "Unentschieden" );
+					break;
+				}
+				spiel->teams->z( index )->sAnzahl++;
+				spiel->teams->z( index )->spieler->add( spieler );
+			}
+		}
+		else
+			unlock();
+		sts->release();
+		ret->spiele->set( spiel, i );
+	}
+	return ret;
+}
+
+bool ISDatenbank::getHistorieServerPortIp( int clientId, int spielId, int *port, Text *ip )
+{
+	lock();
+	if( !datenbank->befehl( Text( "SELECT a.id, a.port, a.ip FROM server_historie a, server_historie_spiel b "
+								  "WHERE a.id = b.server_historie_id AND a.clients < a.max_clients - 1 AND "
+								  "a.server_status_id = 3 AND b.spiel_id = " ) += spielId ) )
+	{
+		unlock();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	if( !res.zeilenAnzahl )
+	{
+		res.destroy();
+		return 0;
+	}
+	int id = res.values[ 0 ];
+	*port = res.values[ 1 ];
+	*ip = res.values[ 2 ].getText();
+	res.destroy();
+	Text *befehl = new Text( "INSERT INTO server_historie_clients( client_id, server_historie_id ) VALUES ( " );
+	befehl->append( clientId );
+	befehl->append( ", " );
+	befehl->append( id );
+	befehl->append( " )" );
+	bool ret = 1;
+	lock();
+	ret &= datenbank->befehl( Text( "SELECT server_historie_id FROM server_historie_clients WHERE client_id = " ) += clientId );
+	res = datenbank->getResult();
+	if( res.zeilenAnzahl )
+		ret &= datenbank->befehl( Text( "UPDATE server_historie SET clients = clients - 1 WHERE id = " ) += res.values[ 0 ] );
+	res.destroy();
+	ret &= datenbank->befehl( Text( "DELETE FROM server_historie_clients WHERE client_id = " ) += clientId );
+	ret &= datenbank->befehl( *befehl );
+	ret &= datenbank->befehl( Text( "UPDATE server_historie SET clients = clients + 1 WHERE id = " ) += id );
+	unlock();
+	befehl->release();
+	return ret;
+}
+
+bool ISDatenbank::hatKlientRecht( int kId, int recht )
+{
+	Text befehl = "SELECT a.* FROM account_user_rechte a, account_clients b WHERE a.account_id = b.account_id AND b.client_id = ";
+	befehl += kId;
+	befehl += " AND a.user_rechte_id = ";
+	befehl += recht;
+	lock();
+	datenbank->befehl( befehl );
+	int num = datenbank->getZeilenAnzahl();
+	unlock();
+	return num == 1;
+}
+
+Result ISDatenbank::getKartenListe( int kId, char *suchFilter, char sortSpalte, char sortRichtung )
+{
+	Text befehl = "SELECT a.id, a.name, b.name, c.kupfer, a.verkauft, a.max_spieler FROM karte a ";
+	befehl += "INNER JOIN spiel_art b ON a.spiel_art_id = b.id ";
+	befehl += "LEFT JOIN karte_kauf_erlaubt c ON a.id = c.karte_id ";
+	befehl += "INNER JOIN account_clients d ON d.account_id = a.account_id ";
+	befehl += "WHERE d.client_id = ";
+	befehl += kId;
+	befehl += " AND a.name LIKE'%";
+	befehl += suchFilter;
+	befehl += "%' ORDER BY ";
+	befehl += sortSpalte + 2;
+	if( sortRichtung ) // absteigend
+		befehl += " DESC";
+	lock();
+	if( !datenbank->befehl( befehl ) )
+	{
+		unlock();
+		Result res = { 0, 0, 0, 0 };
+		return res;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	return res;
+}
+
+bool ISDatenbank::getEditorServerPortIp( int clientId, int karteId, int *port, Text *ip )
+{
+	Text befehl = "SELECT a.port, a.ip, a.id FROM server_editor a, karte b, account_clients c ";
+	befehl += "WHERE a.id = b.server_editor_id AND b.account_id = c.account_id AND a.server_status_id = 3 AND c.client_id = ";
+	befehl += clientId;
+	befehl += " AND b.id = ";
+	befehl += karteId;
+	lock();
+	if( !datenbank->befehl( befehl ) )
+	{
+		unlock();
+		return 0;
+	}
+	Result res = datenbank->getResult();
+	unlock();
+	*port = res.values[ 0 ];
+    ip->setText( res.values[ 1 ] );
+    int id = res.values[ 2 ];
+    res.destroy();
+    befehl = "INSERT INTO server_editor_clients( client_id, server_editor_id ) VALUES ( ";
+    befehl += clientId;
+    befehl += ", ";
+    befehl += id;
+    befehl += " )";
+    bool ret = 1;
+    lock();
+    ret &= datenbank->befehl( Text( "SELECT server_editor_id FROM server_editor_clients WHERE client_id = " ) += clientId );
+    ret &= datenbank->befehl( Text( "DELETE FROM server_editor_clients WHERE client_id = " ) += clientId );
+    ret &= datenbank->befehl( befehl );
+    unlock();
+	return 1;
+}
+
+bool ISDatenbank::getKartenServerPortIp( int clientId, int karteId, int *port, Text *ip )
+{
+    Text befehl = "SELECT a.port, a.ip, a.id FROM server_karten a, karte b ";
+    befehl += "WHERE a.id = b.server_karten_id AND a.server_status_id = 3 AND b.id = ";
+    befehl += karteId;
+    if( !karteId )
+        befehl = "SELECT port, ip, a.id FROM server_karten WHERE server_status_id = 3 LIMIT 1";
+    lock();
+    if( !datenbank->befehl( befehl ) )
+    {
+        unlock();
+        return 0;
+    }
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+        return 0;
+    *port = res.values[ 0 ];
+    ip->setText( res.values[ 1 ] );
+    int id = res.values[ 2 ];
+    res.destroy();
+    if( clientId )
+    {
+        befehl = "INSERT INTO server_karten_clients( client_id, server_karten_id ) VALUES ( ";
+        befehl += clientId;
+        befehl += ", ";
+        befehl += id;
+        befehl += " )";
+        bool ret = 1;
+        lock();
+        ret &= datenbank->befehl( Text( "SELECT server_karten_id FROM server_karten_clients WHERE client_id = " ) += clientId );
+        ret &= datenbank->befehl( Text( "DELETE FROM server_karten_clients WHERE client_id = " ) += clientId );
+        ret &= datenbank->befehl( befehl );
+        unlock();
+    }
+    return 1;
+}
+
+// constant
+Text *ISDatenbank::getLetzterFehler() const
+{
+	return datenbank->getLetzterFehler();
+}
+
+// Reference Counting
+ISDatenbank *ISDatenbank::getThis()
+{
+	ref++;
+	return this;
+}
+
+ISDatenbank *ISDatenbank::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 101 - 0
InformationServer/Datenbank.h

@@ -0,0 +1,101 @@
+#ifndef Datenbank_H
+#define Datenbank_H
+
+#include <sql.h>
+#include <Text.h>
+#include <Array.h>
+#include <InitDatei.h>
+
+using namespace Framework;
+using namespace sql;
+
+namespace Admin_Recht
+{
+	const int ISStarten = 0x00000014;
+	const int ISBeenden = 0x00000015;
+	const int ISPausieren = 0x00000016;
+	const int ISMCChange = 0x00000017;
+}
+
+struct AHDaten;
+class InformationServer;
+
+class ISDatenbank
+{
+private:
+	Datenbank *datenbank;
+	CRITICAL_SECTION cs;
+	int ref;
+
+public:
+	// Konstruktor
+	ISDatenbank( InitDatei *zIni );
+	// Destruktor
+	~ISDatenbank();
+	// nicht constant
+	void lock();
+	void unlock();
+	int istAdministrator( const char *name, const char *passwort );
+	bool adminHatRecht( int id, int recht );
+	bool proveKlient( int num, int sNum );
+	Text *getKlientKey( int cId );
+	void unregisterKlient( int num, int sNum );
+	bool serverAnmelden( InitDatei *zIni );
+	bool setServerStatus( int id, int status );
+	bool setMaxClients( int id, int maxC );
+	int getAdminPort( int id );
+	bool serverIstNichtPausiert( int id );
+	Text *getInformationsText( char *typ );
+	bool istSpielErlaubt( int spielId );
+	bool istKarteErlaubt( int karteId );
+	Text *getAccountRufName( int accountId );
+	int getAccountId( char *rufName );
+	Array< int > *getAccountSpielStatistik( int accountId, int spielId );
+	int getAccountKarteSpiele( int accountId, int karteId );
+	int getAccountKarteSpieleGewonnen( int accountId, int karteId );
+	Text *getKarteName( int karteId );
+	Text *getSpielName( int spielId );
+	Text *getChatroomName( int chatroomId );
+	int getChatroomId( char *name );
+	int getSpielId( int karteId );
+	int getSpielId( char *name );
+	int getKarteId( char *name );
+	int getGruppenKarteId( int gruppeId );
+	int getGruppeAdminId( int gruppeId );
+	int getSpielerPunkte( int spielId, int accountId );
+	Array< int > *getAccountSpielArtListe( int cId );
+	int getNeusteSpielVersion( int spielId );
+	int getKupfer( int cId );
+	int getDateiGruppeVonSpiel( int sId );
+	Text *getDateiGruppePfad( int dgId );
+	Array< int > *getAccountKarteListe( int cId, int kId );
+	bool hatAccountKarte( int account, int karte );
+	bool hatAccountSpiel( int account, int spiel );
+	int getDateiGruppeVonPfad( char *pfad );
+	int getNeusteDateiGruppe( int dg );
+	bool getGruppeSpielerAdd( int gruppeId );
+	Result getSpielerListe( char *suche, int *seite, int *maxSeite, int sortStalte, bool backwords );
+	bool getSpielerAktivity( int accountId, RCArray< Text > *datum, Array< double > *stOnline, Array< double > *stGespielt,
+							  Array< int > *anzSpiele, Array< int > *anzGewonnen );
+	int getOnlineSeconds( int accountId, char *beg, char *end );
+	int getGespieltSeconds( int accountId, char *beg, char *end );
+	int getGespieltSpiele( int accountId, char *beg, char *end );
+	int getGewonnenSpiele( int accountId, char *beg, char *end );
+	Array< int > *getAccountKarteGespieltListe( int accountId, int spielArt );
+	Array< int > *getAccountSpielGespieltListe( int accountId );
+	Result getSpielPartnerListe( int accountId );
+	Result getSpielStatistikListe( int accountId, int *seite, int *maxSeite, int sortStalte, bool backwords );
+    AHDaten *getSpielHistorie( int accountId, InformationServer *is );
+	bool getHistorieServerPortIp( int clientId, int spielId, int *port, Text *ip );
+	bool hatKlientRecht( int kId, int recht );
+	Result getKartenListe( int kId, char *suchFilter, char sortSpalte, char sortRichtung );
+    bool getEditorServerPortIp( int clientId, int karteId, int *port, Text *ip );
+    bool getKartenServerPortIp( int clientId, int karteId, int *port, Text *ip );
+	// constant
+	Text *getLetzterFehler() const;
+	// Reference Counting
+	ISDatenbank *getThis();
+	ISDatenbank *release();
+};
+
+#endif

+ 1693 - 0
InformationServer/InformationServer.cpp

@@ -0,0 +1,1693 @@
+#include "InformationServer.h"
+#include <iostream>
+#include <Klient.h>
+#include <Globals.h>
+#include "AccountHistorieDaten.h"
+
+// Inhalt der InformationServer Klasse aus InformationServer.h
+// Konstruktor 
+InformationServer::InformationServer( InitDatei *zIni )
+	: Thread()
+{
+	Network::Start( 100 );
+	std::cout << "IS: Verbindung mit Datenbank wird hergestellt...\n";
+	db = new ISDatenbank( zIni );
+	klientAnzahl = 0;
+	klients = new RCArray< ISKlient >();
+	empfangen = 0;
+	gesendet = 0;
+	fehler = new Text();
+	ini = zIni->getThis();
+	if( !db->serverAnmelden( zIni ) )
+	{
+		std::cout << "IS: Der Server konnte nicht in die Datenbank eingetragen werden:\n";
+		Text *txt = db->getLetzterFehler();
+		std::cout << txt->getText() << "\nDas Programm wird beendet.";
+		txt->release();
+		exit( 1 );
+	}
+	id = *zIni->zWert( "ServerId" );
+	server = new Server();
+	aServer = new Server();
+	std::cout << "IS: Starten des Admin Servers...\n";
+	if( !aServer->verbinde( (unsigned short)db->getAdminPort( id ), 10 ) )
+	{
+		std::cout << "IS: Der Admin Server konnte nicht gestartet werden. Das Programm wird beendet.\n";
+		exit( 1 );
+	}
+	db->setServerStatus( id, 2 );
+	end = 0;
+	nichtPausiert = 0;
+	InitializeCriticalSection( &cs );
+	ref = 1;
+	if( zIni->zWert( "Aktiv" )->istGleich( "TRUE" ) )
+	{
+		serverStarten();
+		serverFortsetzen();
+	}
+}
+
+// Destruktor 
+InformationServer::~InformationServer()
+{
+	fehler->release();
+	server->trenne();
+	server->release();
+	aServer->trenne();
+	aServer->release();
+	if( klients )
+		klients->release();
+	ini->release();
+	db->release();
+	DeleteCriticalSection( &cs );
+}
+
+// nicht constant 
+void InformationServer::runn()
+{
+	while( !end )
+	{
+		SKlient *klient;
+		klient = aServer->getKlient();
+		if( end && klient )
+		{
+			klient->trenne();
+			klient = klient->release();
+			Sleep( 1000 );
+			return;
+		}
+		if( !klient )
+			return;
+		ISAKlient *clHandle = new ISAKlient( klient, getThis() );
+		clHandle->start();
+	}
+}
+
+void InformationServer::thread()
+{
+	while( 1 )
+	{
+		SKlient *klient;
+		klient = server->getKlient();
+		if( !klient )
+			break;
+		Framework::getThreadRegister()->cleanUpClosedThreads();
+		ISKlient *clHandle = new ISKlient( klient, getThis() );
+		EnterCriticalSection( &cs );
+		klients->set( clHandle, klientAnzahl );
+		klientAnzahl++;
+		LeaveCriticalSection( &cs );
+		clHandle->start();
+	}
+}
+
+void InformationServer::close()
+{
+	db->setServerStatus( id, 1 );
+	server->trenne();
+#ifdef WIN32
+	warteAufThread( 1000 );
+#endif
+	EnterCriticalSection( &cs );
+	for( int i = 0; i < klientAnzahl; i++ )
+		klients->z( i )->absturz();
+	klients = klients->release();
+	klientAnzahl = 0;
+	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 InformationServer::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 InformationServer::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 InformationServer::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 InformationServer::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 InformationServer::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 InformationServer::absturzKlient( int klientId )
+{
+	bool gefunden = 0;
+	EnterCriticalSection( &cs );
+	for( int i = 0; i < klientAnzahl; i++ )
+	{
+		if( klients->z( i )->getKlientNummer() == klientId )
+		{
+			klients->z( i )->absturz();
+			klients->remove( i );
+			klientAnzahl--;
+			gefunden = 1;
+			break;
+		}
+	}
+	LeaveCriticalSection( &cs );
+	return gefunden;
+}
+
+bool InformationServer::removeKlient( ISKlient *zKlient )
+{
+	bool gefunden = 0;
+	EnterCriticalSection( &cs );
+	for( int i = 0; i < klientAnzahl; i++ )
+	{
+		if( klients->z( i ) == zKlient )
+		{
+			klients->remove( i );
+			klientAnzahl--;
+			gefunden = 1;
+			break;
+		}
+	}
+	LeaveCriticalSection( &cs );
+	return gefunden;
+}
+
+void InformationServer::addGesendet( int bytes )
+{
+	gesendet += bytes;
+}
+
+void InformationServer::addEmpfangen( int bytes )
+{
+	empfangen += bytes;
+}
+
+// constant 
+bool InformationServer::istAn() const
+{
+	return db->serverIstNichtPausiert( id );
+}
+
+Server *InformationServer::zServer() const
+{
+	return server;
+}
+
+ISDatenbank *InformationServer::zDB() const
+{
+	return db;
+}
+
+bool InformationServer::hatClients() const
+{
+	return klientAnzahl > 0;
+}
+
+int InformationServer::getId() const
+{
+	return id;
+}
+
+char *InformationServer::getLetzterFehler() const
+{
+	return fehler->getText();
+}
+
+// Reference Counting
+InformationServer *InformationServer::getThis()
+{
+	ref++;
+	return this;
+}
+
+InformationServer *InformationServer::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der ISAKlient Klasse aus InformationServer.h
+// Konstruktor 
+ISAKlient::ISAKlient( SKlient *klient, InformationServer *is )
+	: Thread()
+{
+	this->klient = klient;
+	unsigned char key[ 20 ] = { 37, 231, 77, 95, 83, 98, 112, 98, 11, 225, 186, 227, 172, 168, 11, 22, 254, 142, 14, 22 };
+	klient->setSendeKey( (char*)key, 20 );
+	klient->setEmpfangKey( (char*)key, 20 );
+	name = new Text( "" );
+	passwort = new Text( "" );
+	adminId = 0;
+	this->is = is;
+}
+
+// Destruktor 
+ISAKlient::~ISAKlient()
+{
+	klient->trenne();
+	klient->release();
+	is->release();
+	name->release();
+	passwort->release();
+}
+
+// nicht constant 
+void ISAKlient::thread()
+{
+	while( 1 )
+	{
+		char c = 0;
+		if( !klient->getNachrichtEncrypted( &c, 1 ) )
+			break;
+		else
+		{
+			bool br = 0;
+			switch( c )
+			{
+			case 1: // Login
+				if( 1 )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					char nLen = 0;
+					klient->getNachrichtEncrypted( &nLen, 1 );
+					char *n = new char[ nLen + 1 ];
+					n[ (int)nLen ] = 0;
+					if( nLen )
+						klient->getNachrichtEncrypted( n, nLen );
+					char pLen = 0;
+					klient->getNachrichtEncrypted( &pLen, 1 );
+					char *p = new char[ pLen + 1 ];
+					p[ (int)pLen ] = 0;
+					if( pLen )
+						klient->getNachrichtEncrypted( p, pLen );
+					int adminId = is->zDB()->istAdministrator( n, p );
+					if( adminId )
+					{
+						klient->sendeEncrypted( "\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->sendeEncrypted( "\1", 1 );
+				break;
+			case 3: // Trennen
+				br = 1;
+				klient->sendeEncrypted( "\1", 1 );
+				break;
+			case 4: // Server starten
+				if( !adminId )
+					errorZuKlient( "Du musst dich einloggen." );
+				else
+				{
+					if( is->zDB()->adminHatRecht( adminId, Admin_Recht::ISStarten ) )
+					{
+						if( !is->serverStarten() )
+						{
+							Text *err = new Text();
+							err->append( is->getLetzterFehler() );
+							errorZuKlient( err->getText() );
+							err->release();
+						}
+						else
+							klient->sendeEncrypted( "\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( is->zDB()->adminHatRecht( adminId, Admin_Recht::ISBeenden ) )
+					{
+						if( is->serverBeenden() )
+							klient->sendeEncrypted( "\1", 1 );
+						else
+						{
+							Text *err = new Text();
+							err->append( is->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( is->isRunning() )
+					{
+						if( is->zDB()->adminHatRecht( adminId, Admin_Recht::ISBeenden ) )
+						{
+							if( is->serverBeenden() )
+								ok = 1;
+							else
+							{
+								Text *err = new Text();
+								err->append( is->getLetzterFehler() );
+								errorZuKlient( err->getText() );
+								err->release();
+							}
+						}
+						else
+							errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
+					}
+					else
+						ok = 1;
+					if( ok && is->hatClients() )
+					{
+						errorZuKlient( "Es sind noch Klients Online. Bitte versuche es später erneut." );
+						break;
+					}
+					if( ok )
+					{
+						klient->sendeEncrypted( "\1", 1 );
+						std::cout << "IS: Der Server wird von Benutzer " << adminId << " heruntergefahren.\n";
+						is->close();
+						br = 1;
+					}
+				}
+				break;
+			case 7: // Progtamm abstürzen
+				if( !adminId )
+					errorZuKlient( "Du musst dich einloggen." );
+				else
+				{
+					bool ok = 0;
+					if( is->isRunning() )
+					{
+						if( is->zDB()->adminHatRecht( adminId, Admin_Recht::ISBeenden ) )
+						{
+							is->serverBeenden();
+							ok = 1;
+						}
+						else
+							errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
+					}
+					else
+						ok = 1;
+					if( ok )
+					{
+						klient->sendeEncrypted( "\1", 1 );
+						std::cout << "IS: Der Server wurde von Benutzer " << adminId << " terminiert.\n";
+						is->close();
+						br = 1;
+					}
+				}
+				break;
+			case 8: // Status Frage
+				if( 1 )
+				{
+					char status = 0;
+					if( is->isRunning() )
+					{
+						status = 1;
+						if( is->istAn() )
+							status = 2;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					klient->sendeEncrypted( &status, 1 );
+				}
+				break;
+			case 9: // Server pausieren
+				if( !adminId )
+					errorZuKlient( "Du musst dich einloggen." );
+				else
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					char pause = 0;
+					klient->getNachrichtEncrypted( &pause, 1 );
+					if( is->zDB()->adminHatRecht( adminId, Admin_Recht::ISPausieren ) )
+					{
+						bool ok = 0;
+						if( pause )
+							ok = is->serverPause();
+						else
+							ok = is->serverFortsetzen();
+						if( ok )
+							klient->sendeEncrypted( "\1", 1 );
+						else
+						{
+							Text *err = new Text();
+							err->append( is->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->sendeEncrypted( "\1", 1 );
+					int maxC = 0;
+					klient->getNachrichtEncrypted( (char*)&maxC, 4 );
+					if( is->zDB()->adminHatRecht( adminId, Admin_Recht::ISMCChange ) )
+					{
+						if( is->setMaxKlients( maxC ) )
+							klient->sendeEncrypted( "\1", 1 );
+						else
+						{
+							Text *err = new Text();
+							err->append( is->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->sendeEncrypted( "\1", 1 );
+                    int klientId = 0;
+                    klient->getNachrichtEncrypted( (char*)&klientId, 4 );
+                    if( klientId && is->absturzKlient( klientId ) )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                        klient->sendeEncrypted( "\0", 1 );
+                }
+                break;
+			default:
+				errorZuKlient( "Unbekannte Nachricht!" );
+				break;
+			}
+			if( br )
+				break;
+			is->addEmpfangen( klient->getDownloadBytes( 1 ) );
+			is->addGesendet( klient->getUploadBytes( 1 ) );
+		}
+	}
+	is->addEmpfangen( klient->getDownloadBytes( 1 ) );
+	is->addGesendet( klient->getUploadBytes( 1 ) );
+	delete this;
+}
+
+void ISAKlient::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 );
+}
+
+
+// Inhalt der ISKlient aus InformationServer.h
+// Konstruktor 
+ISKlient::ISKlient( SKlient *klient, InformationServer *is )
+	: Thread()
+{
+	this->klient = klient;
+	unsigned char key[ 20 ] = { 231, 246, 125, 32, 88, 172, 229, 223, 246, 138, 74, 64, 142, 245, 217, 218, 162, 62, 103, 50 };
+	klient->setSendeKey( (char*)key, 20 );
+	klient->setEmpfangKey( (char*)key, 20 );
+	klientNummer = 0;
+	this->is = is;
+	ref = 1;
+}
+
+// Destruktor 
+ISKlient::~ISKlient()
+{
+	klient->release();
+	is->release();
+}
+
+// nicht constant
+void ISKlient::absturz()
+{
+	ende();
+	klient->trenne();
+	is->zDB()->unregisterKlient( klientNummer, is->getId() );
+}
+
+void ISKlient::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( !is->zDB()->proveKlient( klientNummer, is->getId() ) )
+				{
+					klientNummer = 0;
+					errorZuKlient( "Du bist nicht für diesen Server eingetragen" );
+				}
+				else
+				{
+					Text *key = is->zDB()->getKlientKey( klientNummer );
+					if( !key )
+						errorZuKlient( "Es konnte kein Schlüssel 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 && is->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;
+				}
+				is->zDB()->unregisterKlient( klientNummer, is->getId() );
+				klient->sendeEncrypted( "\1", 1 );
+				break;
+			case 5: // frage nach Informations Text
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					char typ = 0;
+					Text *info = is->zDB()->getInformationsText( &typ );
+					unsigned short len = info ? (unsigned short)info->getLength() : 0;
+					klient->sendeEncrypted( (char*)&len, 2 );
+					if( len > 0 )
+						klient->sendeEncrypted( info->getText(), len );
+					klient->sendeEncrypted( &typ, 1 );
+					if( info )
+						info->release();
+				}
+				break;
+			case 6: // frage, ob Spiel erlaubt ist
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					int spielId = 0;
+					klient->getNachrichtEncrypted( (char*)&spielId, 4 );
+					if( is->zDB()->istSpielErlaubt( spielId ) )
+						klient->sendeEncrypted( "\1", 1 );
+					else
+						klient->sendeEncrypted( "\0", 1 );
+				}
+				break;
+			case 7: // frage, ob Karte erlaubt ist
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					int karteId = 0;
+					klient->getNachrichtEncrypted( (char*)&karteId, 4 );
+					if( is->zDB()->istKarteErlaubt( karteId ) )
+						klient->sendeEncrypted( "\1", 1 );
+					else
+						klient->sendeEncrypted( "\0", 1 );
+				}
+				break;
+			case 8: // Frage nach Spiel Id
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					char len = 0;
+					klient->getNachrichtEncrypted( &len, 1 );
+					char *name = new char[ len + 1 ];
+					name[ (int)len ] = 0;
+					klient->getNachrichtEncrypted( name, len );
+					int id = is->zDB()->getSpielId( name );
+					klient->sendeEncrypted( (char*)&id, 4 );
+					delete[] name;
+				}
+				break;
+			case 9: // Frage nach Karte Id
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					char len = 0;
+					klient->getNachrichtEncrypted( &len, 1 );
+					char *name = new char[ len + 1 ];
+					name[ (int)len ] = 0;
+					klient->getNachrichtEncrypted( name, len );
+					int id = is->zDB()->getKarteId( name );
+					klient->sendeEncrypted( (char*)&id, 4 );
+					delete[] name;
+				}
+				break;
+			case 0xA: // Frage nach Account rufName
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					int accountId = 0;
+					klient->getNachrichtEncrypted( (char*)&accountId, 4 );
+					Text *rName = is->zDB()->getAccountRufName( accountId );
+					if( rName )
+					{
+						char len = (char)rName->getLength();
+						klient->sendeEncrypted( &len, 1 );
+						klient->sendeEncrypted( rName->getText(), len );
+						rName->release();
+					}
+					else
+						klient->sendeEncrypted( "\0", 1 );
+				}
+				break;
+			case 0xB: // Frage nach Spiel Statistik
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					int accountId = 0;
+					int spielId = 0;
+					klient->getNachrichtEncrypted( (char*)&accountId, 4 );
+					klient->getNachrichtEncrypted( (char*)&spielId, 4 );
+					Array< int > *values = is->zDB()->getAccountSpielStatistik( accountId, spielId );
+					for( int i = 0; i < 10; i++ )
+					{
+						int tmp = values ? values->get( i ) : 0;
+						klient->sendeEncrypted( (char*)&tmp, 4 );
+					}
+					if( values )
+						values->release();
+				}
+				break;
+			case 0xC: // Frage nach Spieler Liste
+				if( !klientNummer )
+				{
+					errorZuKlient( "Du bist nicht Identifiziert." );
+					break;
+				}
+				else
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					char len = 0;
+					klient->getNachrichtEncrypted( &len, 1 );
+					char *suche = new char[ len + 1 ];
+					suche[ (int)len ] = 0;
+					klient->getNachrichtEncrypted( suche, len );
+					int seite = 0;
+					klient->getNachrichtEncrypted( (char*)&seite, 4 );
+					char sortSpalte = 0;
+					char backwords = 0;
+					klient->getNachrichtEncrypted( &sortSpalte, 1 );
+					klient->getNachrichtEncrypted( &backwords, 1 );
+					int maxSeite = 0;
+					Result list = is->zDB()->getSpielerListe( suche, &seite, &maxSeite, sortSpalte, backwords != 0 );
+					delete[] suche;
+					klient->sendeEncrypted( (char*)&seite, 4 );
+					klient->sendeEncrypted( (char*)&maxSeite, 4 );
+					klient->sendeEncrypted( (char*)&list.zeilenAnzahl, 4 );
+					for( int i = 0; i < list.zeilenAnzahl; i++ )
+					{
+						int accId = list.values[ i * 6 ];
+						klient->sendeEncrypted( (char*)&accId, 4 );
+						len = (char)list.values[ i * 6 + 1 ].getLength();
+						klient->sendeEncrypted( &len, 1 );
+						klient->sendeEncrypted( list.values[ i * 6 + 1 ], len );
+						len = (char)list.values[ i * 6 + 2 ].getLength();
+						klient->sendeEncrypted( &len, 1 );
+						klient->sendeEncrypted( list.values[ i * 6 + 2 ], len );
+						len = (char)list.values[ i * 6 + 3 ].getLength();
+						klient->sendeEncrypted( &len, 1 );
+						klient->sendeEncrypted( list.values[ i * 6 + 3 ], len );
+						len = (char)list.values[ i * 6 + 4 ].getLength();
+						klient->sendeEncrypted( &len, 1 );
+						klient->sendeEncrypted( list.values[ i * 6 + 4 ], len );
+						len = (char)list.values[ i * 6 + 5 ].getLength();
+						klient->sendeEncrypted( &len, 1 );
+						klient->sendeEncrypted( list.values[ i * 6 + 5 ], len );
+					}
+					list.destroy();
+				}
+				break;
+			case 0xD: // Frage nach Gruppe Karte Id
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					int gruppeId = 0;
+					klient->getNachrichtEncrypted( (char*)&gruppeId, 4 );
+					int karteId = is->zDB()->getGruppenKarteId( gruppeId );
+					klient->sendeEncrypted( (char*)&karteId, 4 );
+				}
+				break;
+			case 0xE: // Frage nach Karten Name
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					int karteId = 0;
+					klient->getNachrichtEncrypted( (char*)&karteId, 4 );
+					Text *name = is->zDB()->getKarteName( karteId );
+					if( !name )
+					{
+						klient->sendeEncrypted( "\0", 1 );
+						break;
+					}
+					char len = (char)name->getLength();
+					klient->sendeEncrypted( &len, 1 );
+					klient->sendeEncrypted( name->getText(), len );
+					name->release();
+				}
+				break;
+			case 0xF: // Frage nach Spiel Name
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					int spielId = 0;
+					klient->getNachrichtEncrypted( (char*)&spielId, 4 );
+					Text *name = is->zDB()->getSpielName( spielId );
+					if( !name )
+					{
+						klient->sendeEncrypted( "\0", 1 );
+						break;
+					}
+					char len = (char)name->getLength();
+					klient->sendeEncrypted( &len, 1 );
+					klient->sendeEncrypted( name->getText(), len );
+					name->release();
+				}
+				break;
+			case 0x10: // Frage nach Chatroom Name
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					int chatroomId = 0;
+					klient->getNachrichtEncrypted( (char*)&chatroomId, 4 );
+					Text *name = is->zDB()->getChatroomName( chatroomId );
+					if( !name )
+					{
+						klient->sendeEncrypted( "\0", 1 );
+						break;
+					}
+					char len = (char)name->getLength();
+					klient->sendeEncrypted( &len, 1 );
+					klient->sendeEncrypted( name->getText(), len );
+					name->release();
+				}
+				break;
+			case 0x11: // Frage nach Spiel Id
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					int karteId = 0;
+					klient->getNachrichtEncrypted( (char*)&karteId, 4 );
+					int spielId = is->zDB()->getSpielId( karteId );
+					klient->sendeEncrypted( (char*)&spielId, 4 );
+				}
+				break;
+			case 0x12: // Frage nach Spieler Id
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					char len = 0;
+					klient->getNachrichtEncrypted( &len, 1 );
+					if( len )
+					{
+						char *name = new char[ len + 1 ];
+						name[ (int)len ] = 0;
+						klient->getNachrichtEncrypted( name, len );
+						int id = is->zDB()->getAccountId( name );
+						klient->sendeEncrypted( (char*)&id, 4 );
+						delete[]name;
+					}
+				}
+				break;
+			case 0x13: // Frage nach Chatroom Id
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					char len = 0;
+					klient->getNachrichtEncrypted( &len, 1 );
+					if( len )
+					{
+						char *name = new char[ len + 1 ];
+						name[ (int)len ] = 0;
+						klient->getNachrichtEncrypted( name, len );
+						int id = is->zDB()->getChatroomId( name );
+						klient->sendeEncrypted( (char*)&id, 4 );
+						delete[]name;
+					}
+				}
+				break;
+			case 0x14: // Frage nach Spiel Punkten
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					int spielId = 0;
+					int accountId = 0;
+					klient->getNachrichtEncrypted( (char*)&spielId, 4 );
+					klient->getNachrichtEncrypted( (char*)&accountId, 4 );
+					int ret = is->zDB()->getSpielerPunkte( spielId, accountId );
+					klient->sendeEncrypted( (char*)&ret, 4 );
+				}
+				break;
+			case 0x15: // Frage nach Gruppe Administrator
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					int gruppeId = 0;
+					klient->getNachrichtEncrypted( (char*)&gruppeId, 4 );
+					int ret = is->zDB()->getGruppeAdminId( gruppeId );
+					klient->sendeEncrypted( (char*)&ret, 4 );
+				}
+				break;
+			case 0x16: // Frage nach Spiel Liste
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					Array< int > *list = is->zDB()->getAccountSpielArtListe( klientNummer );
+					if( !list )
+					{
+						klient->sendeEncrypted( "\0\0\0\0", 4 );
+						break;
+					}
+					int anz = list->getEintragAnzahl();
+					klient->sendeEncrypted( (char*)&anz, 4 );
+					for( int i = 0; i < anz; i++ )
+					{
+						int id = list->get( i );
+						klient->sendeEncrypted( (char*)&id, 4 );
+					}
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x17: // Frage nach neuster Spiel Version
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int id = 0;
+					klient->getNachrichtEncrypted( (char*)&id, 4 );
+					int v = is->zDB()->getNeusteSpielVersion( id );
+					klient->sendeEncrypted( (char*)&v, 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x18: // Frage nach Kupfer
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int k = is->zDB()->getKupfer( klientNummer );
+					klient->sendeEncrypted( (char*)&k, 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x19: // Frage nach Dateigruppen Id von Spiel
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int spielId = 0;
+					klient->getNachrichtEncrypted( (char*)&spielId, 4 );
+					int dgId = is->zDB()->getDateiGruppeVonSpiel( spielId );
+					klient->sendeEncrypted( (char*)&dgId, 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x1A: // Frage nach Dateigruppen Pfad
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int dgId = 0;
+					klient->getNachrichtEncrypted( (char*)&dgId, 4 );
+					Text *pf = is->zDB()->getDateiGruppePfad( dgId );
+					if( !pf )
+						errorZuKlient( "Die Dateigruppe wurde nicht gefunden." );
+					else
+					{
+						klient->sendeEncrypted( "\1", 1 );
+						char len = (char)pf->getLength();
+						klient->sendeEncrypted( &len, 1 );
+						if( len )
+							klient->sendeEncrypted( pf->getText(), len );
+						pf->release();
+					}
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x1B: // Frage nach karte Liste
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int spielId = 0;
+					klient->getNachrichtEncrypted( (char*)&spielId, 4 );
+					Array< int > *list = is->zDB()->getAccountKarteListe( klientNummer, spielId );
+					if( !list )
+					{
+						klient->sendeEncrypted( "\0\0\0\0", 4 );
+						break;
+					}
+					int anz = list->getEintragAnzahl();
+					klient->sendeEncrypted( (char*)&anz, 4 );
+					for( int i = 0; i < anz; i++ )
+					{
+						int id = list->get( i );
+						klient->sendeEncrypted( (char*)&id, 4 );
+					}
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x1E: // Frage nach Gruppe Spieler Hinzufügen
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int gruppeId = 0;
+					klient->getNachrichtEncrypted( (char*)&gruppeId, 4 );
+					char gSH = (char)is->zDB()->getGruppeSpielerAdd( gruppeId );
+					klient->sendeEncrypted( &gSH, 1 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x1F: // Frage nach Spieler Aktivität
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int acc = 0;
+					klient->getNachrichtEncrypted( (char*)&acc, 4 );
+					RCArray< Text > *datum = new RCArray< Text >();
+					Array< double > *stOnline = new Array< double >();
+					Array< double > *stSpiel = new Array< double >();
+					Array< int > *anzSpiele = new Array< int >();
+					Array< int > *anzGewonnen = new Array< int >();
+					if( is->zDB()->getSpielerAktivity( acc, datum, stOnline, stSpiel, anzSpiele, anzGewonnen ) )
+					{
+						klient->sendeEncrypted( "\1", 1 );
+						int anz = datum->getEintragAnzahl();
+						for( int i = 0; i < anz; i++ )
+						{
+							if( datum->z( i ) )
+							{
+								char len = (char)datum->get( i )->getLength();
+								if( len )
+								{
+									klient->sendeEncrypted( &len, 1 );
+									klient->sendeEncrypted( datum->z( i )->getText(), len );
+									double sto = stOnline->hat( i ) ? stOnline->get( i ) : 0;
+									klient->sendeEncrypted( (char*)&sto, 8 );
+									double sts = stSpiel->hat( i ) ? stSpiel->get( i ) : 0;
+									klient->sendeEncrypted( (char*)&sts, 8 );
+									int anzs = anzSpiele->hat( i ) ? anzSpiele->get( i ) : 0;
+									klient->sendeEncrypted( (char*)&anzs, 4 );
+									int anzg = anzGewonnen->hat( i ) ? anzGewonnen->get( i ) : 0;
+									klient->sendeEncrypted( (char*)&anzg, 4 );
+								}
+							}
+						}
+						klient->sendeEncrypted( "\0", 1 );
+					}
+					else
+						errorZuKlient( "Keine Daten gefunden." );
+					datum->release();
+					stOnline->release();
+					stSpiel->release();
+					anzSpiele->release();
+					anzGewonnen->release();
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x20: // Frage nach Anzahl der gespielten Spiele von Karte
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int acc = 0;
+					int karte = 0;
+					klient->getNachrichtEncrypted( (char*)&acc, 4 );
+					klient->getNachrichtEncrypted( (char*)&karte, 4 );
+					int anz = is->zDB()->getAccountKarteSpiele( acc, karte );
+					klient->sendeEncrypted( (char*)&anz, 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x21: // Frage nach Anzahl gewonnener Spiele von Karte
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int acc = 0;
+					int karte = 0;
+					klient->getNachrichtEncrypted( (char*)&acc, 4 );
+					klient->getNachrichtEncrypted( (char*)&karte, 4 );
+					int anz = is->zDB()->getAccountKarteSpieleGewonnen( acc, karte );
+					klient->sendeEncrypted( (char*)&anz, 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x22: // Frage nach Besitz Status von Karte
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int acc = 0;
+					int karte = 0;
+					klient->getNachrichtEncrypted( (char*)&acc, 4 );
+					klient->getNachrichtEncrypted( (char*)&karte, 4 );
+					char status = (char)is->zDB()->hatAccountKarte( acc, karte );
+					klient->sendeEncrypted( &status, 1 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x23: // Frage nach Besitz Status von Spiel
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int acc = 0;
+					int spiel = 0;
+					klient->getNachrichtEncrypted( (char*)&acc, 4 );
+					klient->getNachrichtEncrypted( (char*)&spiel, 4 );
+					char status = (char)is->zDB()->hatAccountSpiel( acc, spiel );
+					klient->sendeEncrypted( &status, 1 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x24: // Frage nach Liste mit gespielten Karten
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int acc = 0;
+					int spiel = 0;
+					klient->getNachrichtEncrypted( (char*)&acc, 4 );
+					klient->getNachrichtEncrypted( (char*)&spiel, 4 );
+					Array< int > *res = is->zDB()->getAccountKarteGespieltListe( acc, spiel );
+					if( res )
+					{
+						int anz = res->getEintragAnzahl();
+						klient->sendeEncrypted( (char*)&anz, 4 );
+						for( int i = 0; i < anz; i++ )
+						{
+							int val = res->get( i );
+							klient->sendeEncrypted( (char*)&val, 4 );
+						}
+						res->release();
+					}
+					else
+						klient->sendeEncrypted( "\0\0\0\0", 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x25: // Frage nach Liste mit gespielten Spielen
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int acc = 0;
+					klient->getNachrichtEncrypted( (char*)&acc, 4 );
+					Array< int > *res = is->zDB()->getAccountSpielGespieltListe( acc );
+					if( res )
+					{
+						int anz = res->getEintragAnzahl();
+						klient->sendeEncrypted( (char*)&anz, 4 );
+						for( int i = 0; i < anz; i++ )
+						{
+							int val = res->get( i );
+							klient->sendeEncrypted( (char*)&val, 4 );
+						}
+						res->release();
+					}
+					else
+						klient->sendeEncrypted( "\0\0\0\0", 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x26: // Frage nach Liste mit spiel Partnern
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int acc = 0;
+					klient->getNachrichtEncrypted( (char*)&acc, 4 );
+					Result res = is->zDB()->getSpielPartnerListe( acc );
+					klient->sendeEncrypted( (char*)&res.zeilenAnzahl, 4 );
+					for( int i = 0; i < res.zeilenAnzahl; i++ )
+					{
+						int spieler = res.values[ i * 3 ];
+						int anzahl = res.values[ i * 3 + 1 ];
+						int karte = res.values[ i * 3 + 2 ];
+						klient->sendeEncrypted( (char*)&spieler, 4 );
+						klient->sendeEncrypted( (char*)&karte, 4 );
+						klient->sendeEncrypted( (char*)&anzahl, 4 );
+					}
+					res.destroy();
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x27: // Frage nach Liste mit spiel Statistiken
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int acc = 0;
+					klient->getNachrichtEncrypted( (char*)&acc, 4 );
+					int seite = 0;
+					klient->getNachrichtEncrypted( (char*)&seite, 4 );
+					char sortSpalte = 0;
+					char backwords = 0;
+					klient->getNachrichtEncrypted( &sortSpalte, 1 );
+					klient->getNachrichtEncrypted( &backwords, 1 );
+					int maxSeite = 0;
+					Result list = is->zDB()->getSpielStatistikListe( acc, &seite, &maxSeite, sortSpalte, backwords != 0 );
+					klient->sendeEncrypted( (char*)&seite, 4 );
+					klient->sendeEncrypted( (char*)&maxSeite, 4 );
+					klient->sendeEncrypted( (char*)&list.zeilenAnzahl, 4 );
+					klient->sendeEncrypted( (char*)&list.feldAnzahl, 4 );
+					for( int i = 0; i < list.zeilenAnzahl; i++ )
+					{
+						for( int j = 0; j < list.feldAnzahl; j++ )
+						{
+							if( j != 1 )
+							{
+								int val = list.values[ j + i * list.feldAnzahl ];
+								klient->sendeEncrypted( (char*)&val, 4 );
+							}
+							else
+							{
+								char len = (char)( list.values[ j + i * list.feldAnzahl ].getLength() );
+								klient->sendeEncrypted( &len, 1 );
+								if( len )
+									klient->sendeEncrypted( list.values[ j + i * list.feldAnzahl ], len );
+							}
+						}
+					}
+					list.destroy();
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x28: // Spiel Historie Liste
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int acc = 0;
+					klient->getNachrichtEncrypted( (char*)&acc, 4 );
+					AHDaten *daten = is->zDB()->getSpielHistorie( acc, is );
+					if( daten )
+					{
+						char anz = (char)daten->spiele->getEintragAnzahl();
+						klient->sendeEncrypted( &anz, 1 );
+						for( char i = 0; i < anz; i++ )
+						{
+							AHSpielDaten *spiel = daten->spiele->z( i );
+							klient->sendeEncrypted( (char*)&spiel->id, 4 );
+							klient->sendeEncrypted( (char*)&spiel->karteId, 4 );
+							char len = (char)spiel->spiel->getLength();
+							klient->sendeEncrypted( &len, 1 );
+							if( len )
+								klient->sendeEncrypted( *spiel->spiel, len );
+							len = (char)spiel->karte->getLength();
+							klient->sendeEncrypted( &len, 1 );
+							if( len )
+								klient->sendeEncrypted( *spiel->karte, len );
+							len = (char)spiel->datum->getLength();
+							klient->sendeEncrypted( &len, 1 );
+							if( len )
+								klient->sendeEncrypted( *spiel->datum, len );
+							len = (char)spiel->status->getLength();
+							klient->sendeEncrypted( &len, 1 );
+							if( len )
+								klient->sendeEncrypted( *spiel->status, len );
+							len = (char)spiel->dauer->getLength();
+							klient->sendeEncrypted( &len, 1 );
+							if( len )
+								klient->sendeEncrypted( *spiel->dauer, len );
+							len = (char)spiel->spielStatus->getLength();
+							klient->sendeEncrypted( &len, 1 );
+							if( len )
+								klient->sendeEncrypted( *spiel->spielStatus, len );
+							len = (char)spiel->gewinner->getLength();
+							klient->sendeEncrypted( &len, 1 );
+							if( len )
+								klient->sendeEncrypted( *spiel->gewinner, len );
+							klient->sendeEncrypted( (char*)&spiel->sAnzahl, 4 );
+							char tAnz = (char)spiel->teams->getEintragAnzahl();
+							klient->sendeEncrypted( &tAnz, 1 );
+							for( char j = 0; j < tAnz; j++ )
+							{
+								AHSpielTeamDaten *team = spiel->teams->z( j );
+								char len = (char)team->name->getLength();
+								klient->sendeEncrypted( &len, 1 );
+								if( len )
+									klient->sendeEncrypted( *team->name, len );
+								klient->sendeEncrypted( (char*)&team->sAnzahl, 4 );
+								len = (char)team->status->getLength();
+								klient->sendeEncrypted( &len, 1 );
+								if( len )
+									klient->sendeEncrypted( *team->status, len );
+								klient->sendeEncrypted( (char*)&team->farbe, 4 );
+								char sAnz = (char)team->spieler->getEintragAnzahl();
+								klient->sendeEncrypted( &sAnz, 1 );
+								for( char k = 0; k < sAnz; k++ )
+								{
+									AHSpielSpielerDaten *spieler = team->spieler->z( k );
+									char len = (char)spieler->name->getLength();
+									klient->sendeEncrypted( &len, 1 );
+									if( len )
+										klient->sendeEncrypted( *spieler->name, len );
+									klient->sendeEncrypted( (char*)&spieler->punkte, 4 );
+									len = (char)spieler->status->getLength();
+									klient->sendeEncrypted( &len, 1 );
+									if( len )
+										klient->sendeEncrypted( *spieler->status, len );
+									klient->sendeEncrypted( (char*)&spieler->farbe, 4 );
+								}
+							}
+						}
+						daten->release();
+					}
+					else
+						klient->sendeEncrypted( "\0", 1 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x29: // Frage nach Historie Server
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int spielId = 0;
+					klient->getNachrichtEncrypted( (char*)&spielId, 4 );
+					int port = 0;
+					Text *ip = new Text();
+					if( is->zDB()->getHistorieServerPortIp( klientNummer, spielId, &port, ip ) )
+					{
+						klient->sendeEncrypted( "\1", 1 );
+						klient->sendeEncrypted( (char*)&port, 4 );
+						char len = (char)ip->getLength();
+						klient->sendeEncrypted( &len, 1 );
+						klient->sendeEncrypted( *ip, len );
+					}
+					else
+						errorZuKlient( "Die Daten für dieses Spiel sind vorrübergehend nicht verfügbar." );
+					ip->release();
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x2A: // Frage nach Dateigruppen Id von Pfad
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					char len = 0;
+					klient->getNachrichtEncrypted( (char*)&len, 1 );
+					char *pf = new char[ len + 1 ];
+					pf[ (int)len ] = 0;
+					klient->getNachrichtEncrypted( (char*)pf, len );
+					int dgId = is->zDB()->getDateiGruppeVonPfad( pf );
+					delete[] pf;
+					klient->sendeEncrypted( (char*)&dgId, 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x2B: // Frage nach neuster Version einer Dateigruppe
+				if( klientNummer )
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int dg = 0;
+					klient->getNachrichtEncrypted( (char*)&dg, 4 );
+					int v = is->zDB()->getNeusteDateiGruppe( dg );
+					klient->sendeEncrypted( (char*)&v, 4 );
+				}
+				else
+					errorZuKlient( "Du bist nicht Identifiziert." );
+				break;
+			case 0x2C: // ping
+				if( 1 )
+				{
+					if( !klientNummer )
+					{
+						errorZuKlient( "Du bist nicht Identifiziert." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+				}
+				break;
+			case 0x2D: // Hat Account Recht
+				if( !klientNummer )
+				{
+					errorZuKlient( "Du bist nicht Identifiziert." );
+					break;
+				}
+				else
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int recht = 0;
+					klient->getNachrichtEncrypted( (char*)&recht, 4 );
+					if( is->zDB()->hatKlientRecht( klientNummer, recht ) )
+						klient->sendeEncrypted( "\1", 1 );
+					else
+						klient->sendeEncrypted( "\0", 1 );
+				}
+				break;
+			case 0x2E: // Karten Liste
+				if( !klientNummer )
+				{
+					errorZuKlient( "Du bist nicht Identifiziert." );
+					break;
+				}
+				else
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					char filterLen = 0;
+					klient->getNachrichtEncrypted( &filterLen, 1 );
+					char *filter = new char[ filterLen + 1 ];
+					filter[ (int)filterLen ] = 0;
+					if( filterLen )
+						klient->getNachrichtEncrypted( filter, filterLen );
+					char sortSpalte = 0;
+					klient->getNachrichtEncrypted( &sortSpalte, 1 );
+					char sortRichtung = 0;
+					klient->getNachrichtEncrypted( &sortRichtung, 1 );
+					Result res = is->zDB()->getKartenListe( klientNummer, filter, sortSpalte, sortRichtung );
+					delete[] filter;
+					klient->sendeEncrypted( (char*)&res.zeilenAnzahl, 4 );
+					for( int i = 0; i < res.zeilenAnzahl; i++ )
+					{
+						int val = res.values[ i * 6 ];
+						klient->sendeEncrypted( (char*)&val, 4 );
+						char len = (char)res.values[ i * 6 + 1 ].getLength();
+						klient->sendeEncrypted( &len, 1 );
+						if( len )
+							klient->sendeEncrypted( res.values[ i * 6 + 1 ], len );
+						len = (char)res.values[ i * 6 + 2 ].getLength();
+						klient->sendeEncrypted( &len, 1 );
+						if( len )
+							klient->sendeEncrypted( res.values[ i * 6 + 2 ], len );
+						val = res.values[ i * 6 + 3 ];
+						klient->sendeEncrypted( (char*)&val, 4 );
+						val = res.values[ i * 6 + 4 ];
+						klient->sendeEncrypted( (char*)&val, 4 );
+						val = res.values[ i * 6 + 5 ];
+						klient->sendeEncrypted( (char*)&val, 4 );
+					}
+					res.destroy();
+				}
+				break;
+			case 0x2F: // Editor Server Anfrage
+				if( !klientNummer )
+				{
+					errorZuKlient( "Du bist nicht Identifiziert." );
+					break;
+				}
+				else
+				{
+					klient->sendeEncrypted( "\1", 1 );
+					int karteId = 0;
+					klient->getNachrichtEncrypted( (char*)&karteId, 4 );
+					int port = 0;
+					Text ip;
+					if( !is->zDB()->getEditorServerPortIp( klientNummer, karteId, &port, &ip ) )
+					{
+						errorZuKlient( "Du kannst diese Karte momentan nicht abrufen." );
+						break;
+					}
+					klient->sendeEncrypted( "\1", 1 );
+					klient->sendeEncrypted( (char*)&port, 4 );
+					char len = (char)ip.getLength();
+					klient->sendeEncrypted( &len, 1 );
+					klient->sendeEncrypted( ip, len );
+				}
+                break;
+            case 0x30: // Karten Server Anfrage
+                if( !klientNummer )
+                {
+                    errorZuKlient( "Du bist nicht Identifiziert." );
+                    break;
+                }
+                else
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    int karteId = 0;
+                    klient->getNachrichtEncrypted( (char*)&karteId, 4 );
+                    int port = 0;
+                    Text ip;
+                    if( !is->zDB()->getKartenServerPortIp( klientNummer, karteId, &port, &ip ) )
+                    {
+                        errorZuKlient( "Diese Karte ist vorrübergehend nicht erreichbar." );
+                        break;
+                    }
+                    klient->sendeEncrypted( "\1", 1 );
+                    klient->sendeEncrypted( (char*)&port, 4 );
+                    char len = (char)ip.getLength();
+                    klient->sendeEncrypted( &len, 1 );
+                    klient->sendeEncrypted( ip, len );
+                }
+                break;
+			default:
+				errorZuKlient( "Unbekannte Nachricht!" );
+				break;
+			}
+			if( br )
+				break;
+			is->addEmpfangen( klient->getDownloadBytes( 1 ) );
+			is->addGesendet( klient->getUploadBytes( 1 ) );
+		}
+	}
+	is->addEmpfangen( klient->getDownloadBytes( 1 ) );
+	is->addGesendet( klient->getUploadBytes( 1 ) );
+	is->removeKlient( this ); // delete this
+}
+
+// constant
+void ISKlient::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 ISKlient::getKlientNummer() const // gibt die KlientId zurück
+{
+	return klientNummer;
+}
+
+// Reference Counting
+ISKlient *ISKlient::getThis()
+{
+	ref++;
+	return this;
+}
+
+ISKlient *ISKlient::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 107 - 0
InformationServer/InformationServer.h

@@ -0,0 +1,107 @@
+#ifndef InformationServer_H
+#define InformationServer_H
+
+#include <Server.h>
+#include <Thread.h>
+#include <Datei.h>
+#include <Text.h>
+#include <InitDatei.h>
+#include "Datenbank.h"
+
+using namespace Framework;
+using namespace Network;
+
+class ISKlient;
+
+class InformationServer : public Thread
+{
+private:
+	Server *server;
+	Server *aServer;
+	InitDatei *ini;
+	ISDatenbank *db;
+	CRITICAL_SECTION cs;
+	RCArray< ISKlient > *klients;
+	Text *fehler;
+	int klientAnzahl;
+	int id;
+	bool nichtPausiert;
+	int empfangen;
+	int gesendet;
+	bool end;
+	int ref;
+
+public:
+	// Konstruktor 
+	InformationServer( InitDatei *zIni );
+	// Destruktor 
+	virtual ~InformationServer();
+	// nicht constant 
+	void runn();
+	void thread();
+	void close();
+	bool serverStarten();
+	bool serverPause();
+	bool serverFortsetzen();
+	bool serverBeenden();
+	bool setMaxKlients( int mc );
+	bool absturzKlient( int klientId );
+	bool removeKlient( ISKlient *zKlient );
+	void addGesendet( int bytes );
+	void addEmpfangen( int bytes );
+	// conatant 
+	bool istAn() const;
+	Server *zServer() const;
+	ISDatenbank *zDB() const;
+	bool hatClients() const;
+	int getId() const;
+	char *getLetzterFehler( ) const;
+	// Reference Counting
+	InformationServer *getThis( );
+	InformationServer *release( );
+};
+
+class ISAKlient : public Thread
+{
+private:
+	SKlient *klient;
+	Text *name;
+	Text *passwort;
+	int adminId;
+	InformationServer *is;
+
+public:
+	// Konstruktor 
+	ISAKlient( SKlient *klient, InformationServer *is );
+	// Destruktor 
+	virtual ~ISAKlient( );
+	// nicht constant
+	void thread( );
+	void errorZuKlient( const char *nachricht ) const; // sendet eine Fehlernachricht zum AKlient
+};
+
+class ISKlient : public Thread
+{
+private:
+	SKlient     *klient;
+	unsigned int klientNummer;
+	InformationServer *is;
+	int ref;
+
+public:
+	// Konstruktor 
+	ISKlient( SKlient *klient, InformationServer *is );
+	// Destruktor 
+	virtual ~ISKlient();
+	// nicht constant
+	void absturz();
+	void thread();
+	// constant
+	void errorZuKlient( const char *nachricht ) const; // sendet eine Fehlernachricht zum Klient
+	int getKlientNummer() const;
+	// Reference Counting
+	ISKlient *getThis();
+	ISKlient *release();
+};
+
+#endif

+ 75 - 0
InformationServer/InformationServer.vcxproj

@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{58b97166-96bd-4fe9-a2ba-5c2c5f2f89af}</ProjectGuid>
+    <Keyword>Linux</Keyword>
+    <RootNamespace>InformationServer</RootNamespace>
+    <MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>
+    <ApplicationType>Linux</ApplicationType>
+    <ApplicationTypeRevision>1.0</ApplicationTypeRevision>
+    <TargetLinuxPlatform>Generic</TargetLinuxPlatform>
+    <LinuxProjectType>{D51BCBC9-82E9-4017-911E-C93873C4EA2B}</LinuxProjectType>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <RemoteRootDir>/home/kolja/projects</RemoteRootDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <RemoteRootDir>/home/kolja/projects</RemoteRootDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings" />
+  <ImportGroup Label="Shared" />
+  <ImportGroup Label="PropertySheets" />
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <RemoteProjectDir>$(RemoteRootDir)/Server/$(ProjectName)/Release</RemoteProjectDir>
+    <IncludePath>..\..\..\..\Allgemein\Framework;../../../Framework/Release;..\..\..\..\Allgemein\Network\Network;../../../Network/Release;..\..\..\..\Allgemein\sql\sql;../../../sql/Release;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <RemoteProjectDir>$(RemoteRootDir)/Server/$(ProjectName)/Debug</RemoteProjectDir>
+    <TargetExt />
+    <IncludePath>..\..\..\..\Allgemein\Framework;../../../Framework/Debug;..\..\..\..\Allgemein\Network\Network;../../../Network/Debug;..\..\..\..\Allgemein\sql\sql;../../../sql/Debug;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <ItemGroup>
+    <ClInclude Include="AccountHistorieDaten.h" />
+    <ClInclude Include="Datenbank.h" />
+    <ClInclude Include="InformationServer.h" />
+    <ClInclude Include="KartenLeser.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="AccountHistorieDaten.cpp" />
+    <ClCompile Include="Datenbank.cpp" />
+    <ClCompile Include="InformationServer.cpp" />
+    <ClCompile Include="KartenLeser.cpp" />
+    <ClCompile Include="main.cpp" />
+  </ItemGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Link>
+      <AdditionalLibraryDirectories>$(RemoteRootDir)/sql/Debug/bin/x64/debug;$(RemoteRootDir)/Network/Debug/bin/x64/debug;$(RemoteRootDir)/Framework/Debug/bin/x64/debug;/usr/lib/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <LibraryDependencies>dbgFramework;dbgNetwork;dbgSQL;pq;pthread</LibraryDependencies>
+      <AdditionalOptions>-Wl,-rpath,../lib %(AdditionalOptions)</AdditionalOptions>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Link>
+      <AdditionalLibraryDirectories>$(RemoteRootDir)/sql/Release/bin/x64/release;$(RemoteRootDir)/Network/Release/bin/x64/release;$(RemoteRootDir)/Framework/Release/bin/x64/release;/usr/lib/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <LibraryDependencies>Framework;Network;SQL;pq;pthread</LibraryDependencies>
+      <AdditionalOptions>-Wl,-rpath,../lib %(AdditionalOptions)</AdditionalOptions>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets" />
+</Project>

+ 42 - 0
InformationServer/InformationServer.vcxproj.filters

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Quelldateien">
+      <UniqueIdentifier>{a56615ed-7aa4-41e7-8cf9-d2762876c752}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Headerdateien">
+      <UniqueIdentifier>{af4fdaa3-1212-453d-8633-5b5feba94f91}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="AccountHistorieDaten.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Datenbank.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="InformationServer.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="KartenLeser.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="AccountHistorieDaten.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Datenbank.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="InformationServer.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="KartenLeser.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="main.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>

+ 178 - 0
InformationServer/KartenLeser.cpp

@@ -0,0 +1,178 @@
+#include "KartenLeser.h"
+#include <Datei.h>
+#include "AccountHistorieDaten.h"
+#include <Klient.h>
+
+// Inhalt der KartenLeser Klasse aus KartenLeser.h
+// Konstruktor 
+KartenLeser::KartenLeser( int karteId, InformationServer *is )
+{
+	pfad = new Text( "" );
+    *pfad += karteId;
+    while( DateiExistiert( pfad->getText() ) )
+        pfad->append( "_" );
+    ref = 1;
+    Text ip;
+    int port;
+    is->zDB()->getKartenServerPortIp( 0, karteId, &port, &ip );
+    Klient *klient = new Klient();
+    unsigned char key[ 20 ] = { 24, 15, 53, 87, 38, 73, 154, 38, 246, 90, 39, 133, 11, 199, 22, 80, 26, 132, 95, 54 };
+    klient->setSendeKey( (char*)key, 20 );
+    klient->setEmpfangKey( (char*)key, 20 );
+    if( !klient->verbinde( (unsigned short)port, ip ) )
+    {
+        klient = klient->release();
+        return;
+    }
+    klient->sendeEncrypted( "\x7", 1 );
+    char ret = 0;
+    klient->getNachrichtEncrypted( &ret, 1 );
+    if( ret == 1 )
+    {
+        klient->sendeEncrypted( (char*)&karteId, 4 );
+        klient->getNachrichtEncrypted( &ret, 1 );
+        if( ret == 1 )
+        {
+            int anz = 0;
+            klient->getNachrichtEncrypted( (char*)&anz, 4 );
+            for( int i = 0; i < anz; i++ )
+            {
+                char len = 0;
+                klient->getNachrichtEncrypted( &len, 1 );
+                if( !len )
+                    continue;
+                char *pfa = new char[ len + 1 ];
+                pfa[ (int)len ] = 0;
+                klient->getNachrichtEncrypted( pfa, len );
+                __int64 size = 0;
+                klient->getNachrichtEncrypted( (char*)&size, 8 );
+                char *buffer = new char[ 2048 ];
+                Text pf = pfad->getText();
+                pf += "/";
+                pf += pfa;
+                delete[] pfa;
+                Datei d;
+                d.setDatei( pf );
+                d.erstellen();
+                d.open( Datei::Style::schreiben );
+                while( size )
+                {
+                    int l = size >= 2048 ? 2048 : (int)size;
+                    klient->getNachricht( buffer, l );
+                    d.schreibe( buffer, l );
+                    size -= l;
+                }
+                d.close();
+                delete[] buffer;
+            }
+        }
+    }
+    if( ret == 3 )
+    {
+        char byte = 0;
+        klient->getNachrichtEncrypted( &byte, 1 );
+        char *f = new char[ byte + 1 ];
+        f[ (int)byte ] = 0;
+        klient->getNachrichtEncrypted( f, byte );
+        delete[] f;
+    }
+    klient->sendeEncrypted( "\3", 1 );
+    klient->getNachrichtEncrypted( &ret, 1 );
+    klient->trenne();
+    klient->release();
+}
+
+// Destruktor
+KartenLeser::~KartenLeser()
+{
+    DateiRemove( pfad );
+}
+
+// nicht constant
+bool KartenLeser::ladeSpielerTeamStruktur( SpielerTeamStruktur *sts )
+{
+	if( !pfad->getLength() )
+		return 0;
+	Text *pf = new Text( pfad->getText() );
+	pf->append( "/sts.ltgd" );
+	Datei *datei = new Datei();
+	datei->setDatei( pf );
+	if( !datei->existiert() || datei->istOrdner() )
+	{
+		datei->release();
+		return 0;
+	}
+	datei->open( Datei::Style::lesen );
+	datei->lese( (char*)&sts->spielerAnzahl, 4 );
+	datei->lese( (char*)&sts->teamAnzahl, 4 );
+	if( sts->spielerFarbe )
+		sts->spielerFarbe->release();
+	sts->spielerFarbe = new Array< int >();
+	for( int i = 0; i < sts->spielerAnzahl; i++ )
+	{
+		int farbe = 0;
+		datei->lese( (char*)&farbe, 4 );
+		sts->spielerFarbe->set( farbe, i );
+	}
+	if( sts->teamFarbe )
+		sts->teamFarbe->release();
+	sts->teamFarbe = new Array< int >();
+	for( int i = 0; i < sts->teamAnzahl; i++ )
+	{
+		int farbe = 0;
+		datei->lese( (char*)&farbe, 4 );
+		sts->teamFarbe->set( farbe, i );
+	}
+	if( sts->teamName )
+		sts->teamName->release();
+	sts->teamName = new RCArray< Text >();
+	for( int i = 0; i < sts->teamAnzahl; i++ )
+	{
+		char len = 0;
+		datei->lese( &len, 1 );
+		char *txt = new char[ len + 1 ];
+		txt[ (int)len ] = 0;
+		datei->lese( txt, len );
+		Text *name = new Text( txt );
+		delete[] txt;
+		sts->teamName->set( name, i );
+	}
+	if( sts->teamSize )
+		sts->teamSize->release();
+	sts->teamSize = new Array< int >();
+	for( int i = 0; i < sts->teamAnzahl; i++ )
+	{
+		int size = 0;
+		datei->lese( (char*)&size, 4 );
+		sts->teamSize->set( size, i );
+	}
+	datei->close();
+	datei->release();
+	return 1;
+}
+
+// constant
+Text *KartenLeser::getPfad() const
+{
+	return pfad ? pfad->getThis() : 0;
+}
+
+Text *KartenLeser::zPfad() const
+{
+	return pfad;
+}
+
+// Reference Counting
+KartenLeser *KartenLeser::getThis()
+{
+	ref++;
+	return this;
+}
+
+KartenLeser *KartenLeser::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 32 - 0
InformationServer/KartenLeser.h

@@ -0,0 +1,32 @@
+#ifndef KartenLeser_H
+#define KartenLeser_H
+
+#include <Text.h>
+#include "InformationServer.h"
+
+using namespace Framework;
+
+struct SpielerTeamStruktur;
+
+class KartenLeser
+{
+private:
+	Text *pfad;
+	int ref;
+
+public:
+	// Konstruktor 
+	KartenLeser( int karteId, InformationServer *is );
+	// Destruktor
+	~KartenLeser();
+	// nicht constant
+	bool ladeSpielerTeamStruktur( SpielerTeamStruktur *sts );
+	// constant
+	Text *getPfad() const;
+	Text *zPfad() const;
+	// Reference Counting
+	KartenLeser *getThis();
+	KartenLeser *release();
+};
+
+#endif

+ 55 - 0
InformationServer/main.cpp

@@ -0,0 +1,55 @@
+#include "InformationServer.h"
+#ifdef WIN32
+#include <main.h>
+#endif
+#include <Zeit.h>
+#include <iostream>
+#include <fstream>
+#include <Globals.h>
+
+#ifdef WIN32
+int KSGStart Framework::Start( Startparam p )
+{
+#else
+int main()
+{
+    Framework::initFramework();
+#endif
+	Zeit *z = getZeit();
+	Text *pfad = new Text( "../log/information/" );
+	pfad->append( z->getZeit( "y-m-d h-i-s.log" ) );
+	z->release();
+	DateiPfadErstellen( pfad->getThis() );
+	std::ofstream file;
+	file.open( pfad->getText() );
+	std::streambuf* sbuf = std::cout.rdbuf();
+	std::cout.rdbuf( file.rdbuf() );
+	pfad->release();
+
+	std::cout << "IS: Startet...\n";
+	std::cout << "IS: Lese init Datei ../data/isInit.ini ...\n";
+	InitDatei *dat = new InitDatei( "../data/isInit.ini" );
+	if( !dat->laden() )
+	{
+		std::cout << "IS: error: Datei konnte nicht gelesen werden. Das Programm wird geschlossen.\n";
+		dat->release();
+		exit( 1 );
+	}
+
+	InformationServer *iServer = new InformationServer( dat );
+
+	std::cout << "IS: Der Admin Server läuft. Startforgang beendet.\n";
+	iServer->runn();
+
+	iServer->ende();
+	iServer->release();
+	dat->speichern();
+	dat->release();
+	std::cout << "IS: Der Server ist heruntergefahren.\n";
+	file.close();
+	std::cout.rdbuf( sbuf );
+#ifndef WIN32
+    Framework::releaseFramework();
+#endif
+	return 0;
+}

BIN
InformationServer/readme/images/ArchOptions.gif


BIN
InformationServer/readme/images/ChangeRemote.gif


BIN
InformationServer/readme/images/ManageConnections.gif


BIN
InformationServer/readme/images/OutputTypes.gif


BIN
InformationServer/readme/images/debuggerexport.png


BIN
InformationServer/readme/images/firstconnection.png


BIN
InformationServer/readme/images/linker.png


BIN
InformationServer/readme/images/postbuild.png


+ 85 - 0
InformationServer/readme/readme.html

@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset='utf-8'>
+
+    <link rel="stylesheet" type="text/css" href="stylesheet.css" media="screen">
+
+    <title>Getting Started</title>
+  </head>
+
+<body>
+
+    <div class="container">
+        <div id="header">
+            <h1>Getting Started</h1>
+            <h2>Visual C++ for Linux Development extension</h2>
+        </div>
+    
+    <table>
+    <tr>    
+    <div id="main_content">
+        
+        <td>
+        <div id="lpanel">
+            <h1>Setting up your project for Linux Development</h1>
+
+            <p>With this extension you can author C++ code for Linux servers, desktops and devices. You can manage your connections to these machines from within VS. VS will automatically copy and remote build your sources and can launch your application with the debugger. Our project system supports targeting specific architectures, including ARM.</p>
+            <img src="images\ArchOptions.gif"/>
+            
+            <h1>Connecting to Linux</h1>
+            <h2>Prerequisites</h2>
+            <p>Today we only support building remotely on the Linux target machine. We are not limited by specific Linux distros but we do have dependencies on the presence of some tools. Specifically, we need openssh-server, g++, gdb and gdbserver. Use your favorite package manager to install them, e.g. on Debian based systems: sudo apt-get install openssh-server g++ gdb gdbserver</p>
+            
+            <h2>First connection</h2>
+            <p>The first time you target a Linux machine you will be prompted for connection information.  This is triggered by building the project.</p>
+            <img src="images\firstconnection.png"/>
+                
+            <h2>Adding and removing connections</h2>
+            <p>To add a new connection, go to Tools > Options and search for Linux. From here you can add and remove connections.</p>
+            <img src="images\ManageConnections.gif"/>
+            
+            <p>To change which connection a project is using go to the project properties remote settings and update the target machine.</p>
+            <img src="images\ChangeRemote.gif"/>
+            
+            <h1>Project Properties</h1>
+            <p>All of the options necessary to control C++ compilation are exposed on the project properies pages. We'll cover a few specific to how things work for Linux. First under remote settings, you will see the remote root is set to ~/projects/ by default and that we are setting the remote project directory to match our project name in that location. </p>
+            <img src="images\OutputTypes.gif"/>
+            
+            <p>Looking at the General settings for the project, you can see how our output and intermediate directories were configured. Additionally, you’ll see that this project was configured as an application – thus our executable is under bin/x64/Debug/ as ConsoleApplication1.out. Notice that for configuration types we also support static and dynamic libraries.</p>
+            
+            <p>Add additional library dependencies on the Linker > Input property page.</p>
+            <img src="images\linker.png"/>
+            
+            <p>You can pass additional pre launch commands to the debugger to do things like launch graphical apps on the remote linux machine.</p>
+            <img src="images\debuggerexport.png"/>
+            
+            <p>You can also send post build events to control remote behavior, as in this example that exports a gpio pin for use without requiring the executable run as super user.</p>
+            <img src="images\postbuild.png"/>
+            
+        </div>
+        </td>
+        <td>
+        <div id="rpanel">
+
+            <h1>Resources</h1>
+
+            <p>Check out the <a href="http://aka.ms/vslinuxext">VS Gallery VC++ for Linux Development page</a> where we will keep updates posted. You can also check out our <a href="https://blogs.msdn.microsoft.com/vcblog/2016/03/30/visual-c-for-linux-development">announcment blog post</a> for more in depth details on configuring the project properties.</p>
+            
+            <p>Here are other utilities you will find useful in connection with this extension.</p>
+            <ul>
+                <li>Learn more about <a href="http://aka.ms/vsiot">IoT Development</a></li>
+                <li><a href="http://aka.ms/vsiotext">VC++ for IoT Development Tools</a></li>
+                <li><a href="https://github.com/Azure/azure-iot-sdks">Azure IoT SDK</a>, includes a C API for connecting small devices to the Azure IoT Hub</li>
+            </ul>
+
+            <h1>Give us feedback</h1>
+            <p><a href="http://aka.ms/vslinux-feedback">UserVoice</a></p>
+        </div>
+        </td>   
+    </div>
+    </tr>
+    </table>
+    </div>
+</body>
+</html>

+ 119 - 0
InformationServer/readme/stylesheet.css

@@ -0,0 +1,119 @@
+body {
+  margin: 0;
+  padding: 0;
+  border: 0;
+  color: #1E1E1E;
+  font-size: 13px;
+  font-family: "Segoe UI", Helvetica, Arial, sans-serif;
+  line-height: 1.45;
+  word-wrap: break-word;
+}
+
+/* General & 'Reset' Stuff */
+
+
+.container {
+  width: 1100px;
+  margin: 0 auto;
+}
+
+section {
+  display: block;
+  margin: 0;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  margin: 0;
+}
+
+table, tr {
+    width: 1100px;
+    padding: 0px;
+    vertical-align: top;
+  }
+
+/* Header, <header>
+   header   - container
+   h1       - project name
+   h2       - project description
+*/
+
+#header {
+  color: #FFF;
+  background: #68217a;
+  position:relative;
+}
+h1, h2 {
+  font-family: "Segoe UI Light", "Segoe UI", Helvetica, Arial, sans-serif;
+  line-height: 1;
+  margin: 0 18px;;
+  padding: 0;
+}
+#header h1 {
+  font-size: 3.4em;
+  padding-top: 18px;
+  font-weight: normal;
+  margin-left: 15px;
+}
+
+#header h2 {
+  font-size: 1.5em;
+  margin-top: 10px;
+  padding-bottom: 18px;
+  font-weight: normal;
+}
+
+#main_content {
+  width: 100%;
+  display: flex;
+  flex-direction: row;
+}
+
+
+h1, h2, h3, h4, h5, h6 {
+  font-weight: bolder;
+}
+
+#main_content h1 {
+  font-size: 1.8em;
+  margin-top: 34px;
+}
+
+    #main_content h1:first-child {
+        margin-top: 30px;
+    }
+
+#main_content h2 {
+  font-size: 1.8em;
+}
+p, ul {
+    margin: 11px 18px;
+}
+
+#main_content a {
+    color: #06C;
+    text-decoration: none;
+}
+ul {
+        margin-top: 13px;
+    margin-left: 18px;
+    padding-left: 0;
+}
+    ul li {
+        margin-left: 18px;
+        padding-left: 0;
+    }
+#lpanel {
+    width: 870px;
+    float: left;
+}
+#rpanel ul {
+    list-style-type: none;
+}
+    #rpanel ul li {
+        line-height: 1.8em;
+    }
+#rpanel {
+    background: #e7e7e7;
+    width: 230px;
+}

+ 2 - 0
build.bat

@@ -0,0 +1,2 @@
+"D:\Visual Studio 2017\MSBuild\15.0\Bin\MSBuild.exe" "Information Server.sln" /t:rebuild /p:configuration=debug /p:platform=x64
+"D:\Visual Studio 2017\MSBuild\15.0\Bin\MSBuild.exe" "Information Server.sln" /t:rebuild /p:configuration=release /p:platform=x64

+ 11 - 0
data/isInit.ini

@@ -0,0 +1,11 @@
+DBBenutzer=informationserveru
+DBPasswort=LTInformationServerPW
+DBName=koljadb
+DBIP=127.0.0.1
+DBPort=5432
+ServerName=Test
+ServerPort=49112
+ServerIP=127.0.0.1
+AdminServerPort=49111
+Aktiv=FALSE
+MaxClients=50