Przeglądaj źródła

Projektdateien hinzufügen.

Kolja Strohm 7 lat temu
rodzic
commit
4f4c2daf80
11 zmienionych plików z 1766 dodań i 0 usunięć
  1. 28 0
      Update.sln
  2. 9 0
      Update/Einstieg.cpp
  3. 18 0
      Update/Keys.cpp
  4. 43 0
      Update/Keys.h
  5. 655 0
      Update/PSKlient.cpp
  6. 48 0
      Update/PSKlient.h
  7. 184 0
      Update/Update.vcxproj
  8. 42 0
      Update/Update.vcxproj.filters
  9. 704 0
      Update/Updater.cpp
  10. 32 0
      Update/Updater.h
  11. 3 0
      build.bat

+ 28 - 0
Update.sln

@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.22823.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Update", "Update\Update.vcxproj", "{EA9C25EE-2921-4332-A408-B731BA9E4050}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
+		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{EA9C25EE-2921-4332-A408-B731BA9E4050}.Debug|Win32.ActiveCfg = Debug|Win32
+		{EA9C25EE-2921-4332-A408-B731BA9E4050}.Debug|Win32.Build.0 = Debug|Win32
+		{EA9C25EE-2921-4332-A408-B731BA9E4050}.Debug|x64.ActiveCfg = Debug|x64
+		{EA9C25EE-2921-4332-A408-B731BA9E4050}.Debug|x64.Build.0 = Debug|x64
+		{EA9C25EE-2921-4332-A408-B731BA9E4050}.Release|Win32.ActiveCfg = Release|Win32
+		{EA9C25EE-2921-4332-A408-B731BA9E4050}.Release|Win32.Build.0 = Release|Win32
+		{EA9C25EE-2921-4332-A408-B731BA9E4050}.Release|x64.ActiveCfg = Release|x64
+		{EA9C25EE-2921-4332-A408-B731BA9E4050}.Release|x64.Build.0 = Release|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 9 - 0
Update/Einstieg.cpp

@@ -0,0 +1,9 @@
+#include "Updater.h"
+
+extern "C"
+{
+	__declspec( dllexport ) UpdaterV *getUpdater()
+	{
+		return new Updater();
+	}
+}

+ 18 - 0
Update/Keys.cpp

@@ -0,0 +1,18 @@
+#include "Keys.h"
+#include <Datei.h>
+
+using namespace Framework;
+
+// Konstruktor
+Keys::Keys()
+{}
+
+// Gibt den Schlüssel eines Servers zurück
+//  key: Ein Zeiger auf ein array von bytes. Wird als ausgabe verwendet. Enthält nach aufruf den gewünschten Key
+//  length: Enthält nach aufruf die Länge des Schlüssels
+//  sTyp: Der Servertyp, zu dem der Schlüssel ermittelt werden soll
+//  kTyp: Die art des Schlüssels der ermittelt werden soll
+void Keys::getServerKey( char **key, int &length, Server sTyp, Key kTyp )
+{
+    // diese Methode ist nicht open source
+}

+ 43 - 0
Update/Keys.h

@@ -0,0 +1,43 @@
+#pragma once
+
+class Keys
+{
+    // Konstruktor
+    Keys();
+public:
+    enum Server;
+    enum Key;
+
+    // Gibt den Schlüssel eines Servers zurück
+    //  key: Ein Zeiger auf ein array von bytes. Wird als ausgabe verwendet. Enthält nach aufruf den gewünschten Key
+    //  length: Enthält nach aufruf die Länge des Schlüssels
+    //  sTyp: Der Servertyp, zu dem der Schlüssel ermittelt werden soll
+    //  kTyp: Die art des Schlüssels der ermittelt werden soll
+    static void getServerKey( char **key, int &length, Server sTyp, Key kTyp );
+
+    // Servertypen
+    enum Server
+    {
+        MAIN = 0,
+        ANMELDUNG = 1,
+        CHAT = 2,
+        EDITOR = 3,
+        HISTORIE = 4,
+        INFORMATION = 5,
+        KARTEN = 6,
+        LOGIN = 7,
+        NEWS = 8,
+        REGISTER = 9,
+        SHOP = 10,
+        SPIEL = 11,
+        PATCH = 12,
+        ERHALTUNG = 13
+    };
+
+    // Keytypen
+    enum Key
+    {
+        EMPFANGEN = 0,
+        SENDEN = 0
+    };
+};

+ 655 - 0
Update/PSKlient.cpp

@@ -0,0 +1,655 @@
+#include "PSKlient.h"
+#include <Text.h>
+#include <Datei.h>
+#include <Zeit.h>
+#include <InitDatei.h>
+
+// Inhalt der PSKlient Klasse aus PSKlient.h
+// Konstruktor
+PSKlient::PSKlient()
+{
+	Datei *dat = new Datei();
+	dat->setDatei( "data/tmp/k.id" );
+	dat->open( Datei::Style::lesen );
+	dat->lese( (char*)&id, 4 );
+	dat->close();
+	klient = 0;
+	InitializeCriticalSection( &cs );
+	verbunden = 0;
+	dat->setDatei( "data/tmp/schlüssel.netw" );
+	dat->open( Datei::Style::lesen );
+	dat->lese( &schlüsselLän, 1 );
+	schlüssel = new char[ schlüsselLän ];
+	dat->lese( schlüssel, schlüsselLän );
+	dat->close();
+	dat = dat->release();
+	unsigned char tmp[ 20 ] = { 102, 139, 140, 143, 52, 52, 194, 167, 97, 106, 23, 72, 170, 121, 213, 178, 28, 28, 124, 185 };
+	memcpy( stdSchlüssel, tmp, 20 );
+	fehler = new Text();
+	ref = 1;
+}
+
+// Destruktor
+PSKlient::~PSKlient()
+{
+	delete[] schlüssel;
+	if( verbunden )
+		trenne( 1 );
+	if( klient )
+	    klient->release();
+	fehler->release();
+	DeleteCriticalSection( &cs );
+}
+
+// nicht constant
+void PSKlient::lock()
+{
+	EnterCriticalSection( &cs );
+}
+
+void PSKlient::unlock()
+{
+	LeaveCriticalSection( &cs );
+}
+
+bool PSKlient::verbinde()
+{
+	lock();
+	if( verbunden )
+	{
+		unlock();
+		return 1;
+	}
+	if( !klient )
+	{
+		InitDatei *iniDat = new InitDatei( "data/optionen.ini" );
+		iniDat->laden();
+		Text *ipT = iniDat->getWert( "ServerIP" );
+		unsigned short msPort = (unsigned short)TextZuInt( iniDat->zWert( "ServerPort" )->getText(), 10 );
+		iniDat->release();
+		int län = ipT->getLength();
+		char *msIp = new char[ län + 1 ];
+		msIp[ län ] = 0;
+		for( int i = 0; i < län; i++ )
+			msIp[ i ] = ipT->getText()[ i ];
+		ipT->release();
+		klient = new Klient();
+		unsigned char msSchlüssel[ 20 ] = { 199, 164, 172, 55, 246, 16, 155, 8, 151, 176, 250, 181, 227, 133, 30, 41, 200, 26, 7, 151 };
+		klient->setSendeKey( (char*)msSchlüssel, 20 );
+		klient->setEmpfangKey( (char*)msSchlüssel, 20 );
+		if( !klient->verbinde( msPort, msIp ) )
+		{
+			fehler->setText( "Fehler beim verbinden mit dem Main Server. Bitte versuche es Später erneut." );
+			klient = klient->release();
+			delete[] msIp;
+			unlock();
+			return 0;
+		}
+		delete[] msIp;
+		klient->sende( "\0", 1 ); // verschlüsselung aktivieren
+		klient->sendeEncrypted( "\1", 1 );
+		klient->sendeEncrypted( (char*)&id, 4 );
+		char serverReturn = 0;
+		klient->getNachrichtEncrypted( &serverReturn, 1 );
+		if( serverReturn == 3 )
+		{
+			char byte = 0;
+			klient->getNachrichtEncrypted( &byte, 1 );
+			char *err = new char[ byte + 1 ];
+			err[ byte ] = 0;
+			klient->getNachrichtEncrypted( err, byte );
+			fehler->setText( err );
+			delete[] err;
+			klient->sendeEncrypted( "\3", 1 );
+			klient->getNachrichtEncrypted( &serverReturn, 1 );
+			klient->trenne();
+			klient = klient->release();
+			unlock();
+			return 0;
+		}
+		klient->setSendeKey( schlüssel, schlüsselLän );
+		klient->setEmpfangKey( schlüssel, schlüsselLän );
+		klient->sendeEncrypted( "\6\2", 2 );
+		char byte = 0;
+		klient->getNachrichtEncrypted( &byte, 1 );
+		if( byte == 2 )
+		{
+			unsigned char psIp[ 4 ];
+			klient->getNachrichtEncrypted( (char *)psIp, 4 );
+			unsigned short psPort = 0;
+			klient->getNachrichtEncrypted( (char*)&psPort, 2 );
+			klient->sendeEncrypted( "\3", 1 );
+			klient->getNachrichtEncrypted( &serverReturn, 1 );
+			klient->trenne();
+			Text *psIpT = new Text( "" );
+			psIpT->append( (int)psIp[ 0 ] );
+			psIpT->append( "." );
+			psIpT->append( (int)psIp[ 1 ] );
+			psIpT->append( "." );
+			psIpT->append( (int)psIp[ 2 ] );
+			psIpT->append( "." );
+			psIpT->append( (int)psIp[ 3 ] );
+			if( verbinde( psPort, psIpT->getText() ) )
+			{
+				unlock();
+				psIpT->release();
+				return 1;
+			}
+			psIpT->release();
+		}
+		if( byte == 3 )
+		{
+			klient->getNachrichtEncrypted( &byte, 1 );
+			char *err = new char[ byte + 1 ];
+			err[ byte ] = 0;
+			klient->getNachrichtEncrypted( err, byte );
+			fehler->setText( err );
+			delete[] err;
+			klient->sendeEncrypted( "\3", 1 );
+			klient->getNachrichtEncrypted( &serverReturn, 1 );
+			klient->trenne();
+			klient = klient->release();
+			unlock();
+			return 0;
+		}
+	}
+	if( klient && verbinde( klient->getServerPort(), klient->getServerIp() ) )
+	{
+		unlock();
+		return 1;
+	}
+	unlock();
+	return 0;
+}
+
+bool PSKlient::verbinde( int port, const char *ip )
+{
+	lock();
+	if( verbunden )
+		trenne( 1 );
+	if( !klient )
+		klient = new Klient();
+	if( !klient->verbinde( (short)port, ip ) )
+	{
+		unlock();
+		return 0;
+	}
+	klient->setSendeKey( (char*)stdSchlüssel, 20 );
+	klient->setEmpfangKey( (char*)stdSchlüssel, 20 );
+	klient->sende( "\0", 1 ); // Verschlüsselung aktivieren
+	klient->sendeEncrypted( "\1", 1 );
+	klient->sendeEncrypted( (char*)&id, 4 );
+#ifdef _WIN64
+	klient->sendeEncrypted( "\2", 1 ); // 64 Bit Client
+#else
+	klient->sendeEncrypted( "\1", 1 ); // 32 Bit Client
+#endif
+	char ret = 0;
+	klient->getNachrichtEncrypted( &ret, 1 );
+	if( ret == 3 )
+	{ // error
+		klient->getNachrichtEncrypted( &ret, 1 );
+		char *msg = new char[ ret + 1 ];
+		msg[ ret ] = 0;
+		if( ret )
+			klient->getNachrichtEncrypted( msg, ret );
+		fehler->setText( msg );
+		delete[] msg;
+		trenne( 0 );
+		unlock();
+		return 0;
+	}
+	klient->setSendeKey( schlüssel, schlüsselLän );
+	klient->setEmpfangKey( schlüssel, schlüsselLän );
+	verbunden = 1;
+	unlock();
+	return 1;
+}
+
+KSGTDatei *PSKlient::getDateiGruppenListe()
+{
+	lock();
+	if( !verbunden )
+	{
+		unlock();
+		return 0;
+	}
+	klient->sendeEncrypted( "\xC", 1 );
+	char ret = 0;
+	klient->getNachrichtEncrypted( &ret, 1 );
+	if( ret == 3 )
+	{ // error
+		klient->getNachrichtEncrypted( &ret, 1 );
+		char *msg = new char[ ret + 1 ];
+		msg[ ret ] = 0;
+		if( ret )
+			klient->getNachrichtEncrypted( msg, ret );
+		fehler->setText( msg );
+		delete[] msg;
+		unlock();
+		return 0;
+	}
+	KSGTDatei *dgtb = new KSGTDatei();
+	int id = 0;
+	klient->getNachrichtEncrypted( (char*)&id, 4 );
+	while( id )
+	{
+		RCArray< Text > *zeile = new RCArray< Text >();
+		Text *idT = new Text();
+		idT->append( id );
+		zeile->set( idT, 0 );
+		int län = 0;
+		klient->getNachrichtEncrypted( (char*)&län, 4 );
+		char *pfad = new char[ län + 1 ];
+		pfad[ län ] = 0;
+		if( län )
+			klient->getNachrichtEncrypted( pfad, län );
+		zeile->set( new Text( pfad ), 1 );
+		delete[] pfad;
+		int vs = 0;
+		klient->getNachrichtEncrypted( (char*)&vs, 4 );
+		Text *vsT = new Text();
+		vsT->append( vs );
+		zeile->set( vsT, 2 );
+		dgtb->addZeile( 3, zeile );
+		zeile->release();
+		klient->getNachrichtEncrypted( (char*)&id, 4 );
+	}
+	klient->sendeEncrypted( "\1", 1 );
+	unlock();
+	return dgtb;
+}
+
+KSGTDatei *PSKlient::getDateiListe( int gruppe )
+{
+	lock();
+	if( !verbunden )
+	{
+		unlock();
+		return 0;
+	}
+	klient->sendeEncrypted( "\x9", 1 );
+	char ret = 0;
+	klient->getNachrichtEncrypted( &ret, 1 );
+	if( ret == 3 )
+	{ // error
+		klient->getNachrichtEncrypted( &ret, 1 );
+		char *msg = new char[ ret + 1 ];
+		msg[ ret ] = 0;
+		if( ret )
+			klient->getNachrichtEncrypted( msg, ret );
+		fehler->setText( msg );
+		delete[] msg;
+		unlock();
+		return 0;
+	}
+	klient->sendeEncrypted( (char*)&gruppe, 4 );
+	klient->getNachrichtEncrypted( &ret, 1 );
+	if( ret == 3 )
+	{ // error
+		klient->getNachrichtEncrypted( &ret, 1 );
+		char *msg = new char[ ret + 1 ];
+		msg[ ret ] = 0;
+		if( ret )
+			klient->getNachrichtEncrypted( msg, ret );
+		fehler->setText( msg );
+		delete[] msg;
+		unlock();
+		return 0;
+	}
+	KSGTDatei *dtb = new KSGTDatei();
+	int län = 0;
+	klient->getNachrichtEncrypted( (char*)&län, 4 );
+	while( län )
+	{
+		RCArray< Text > *zeile = new RCArray< Text >();
+		zeile->set( new Text( "1" ), 0 );
+		char *pfad = new char[ län + 1 ];
+		pfad[ län ] = 0;
+		klient->getNachrichtEncrypted( pfad, län );
+		zeile->set( new Text( pfad ), 1 );
+		delete[] pfad;
+		int vs = 0;
+		klient->getNachrichtEncrypted( (char*)&vs, 4 );
+		Text *vsT = new Text();
+		vsT->append( vs );
+		zeile->set( vsT, 2 );
+		dtb->addZeile( 3, zeile );
+		zeile->release();
+		klient->getNachrichtEncrypted( (char*)&län, 4 );
+	}
+	klient->getNachrichtEncrypted( (char*)&län, 4 );
+	while( län )
+	{
+		RCArray< Text > *zeile = new RCArray< Text >();
+		zeile->set( new Text( "0" ), 0 );
+		char *pfad = new char[ län + 1 ];
+		pfad[ län ] = 0;
+		klient->getNachrichtEncrypted( pfad, län );
+		zeile->set( new Text( pfad ), 1 );
+		delete[] pfad;
+		dtb->addZeile( 2, zeile );
+		zeile->release();
+		klient->getNachrichtEncrypted( (char*)&län, 4 );
+	}
+	unlock();
+	return dtb;
+}
+
+__int64 PSKlient::getDateiGröße( int gruppe, const char *pfad )
+{
+	lock();
+	if( !verbunden )
+	{
+		unlock();
+		return 0;
+	}
+	klient->sendeEncrypted( "\xA", 1 );
+	char ret = 0;
+	klient->getNachrichtEncrypted( &ret, 1 );
+	if( ret == 3 )
+	{ // error
+		klient->getNachrichtEncrypted( &ret, 1 );
+		char *msg = new char[ ret + 1 ];
+		msg[ ret ] = 0;
+		if( ret )
+			klient->getNachrichtEncrypted( msg, ret );
+		fehler->setText( msg );
+		delete[] msg;
+		unlock();
+		return 0;
+	}
+	klient->sendeEncrypted( (char*)&gruppe, 4 );
+	ret = 0;
+	klient->getNachrichtEncrypted( &ret, 1 );
+	if( ret == 3 )
+	{ // error
+		klient->getNachrichtEncrypted( &ret, 1 );
+		char *msg = new char[ ret + 1 ];
+		msg[ ret ] = 0;
+		if( ret )
+			klient->getNachrichtEncrypted( msg, ret );
+		fehler->setText( msg );
+		delete[] msg;
+		unlock();
+		return 0;
+	}
+	if( ret == 2 )
+	{ // verweis auf anderen Server
+		int port = 0;
+		klient->getNachrichtEncrypted( (char*)&port, 4 );
+		int län = 0;
+		klient->getNachrichtEncrypted( (char*)&län, 4 );
+		char *ip = new char[ län + 1 ];
+		ip[ län ] = 0;
+		klient->getNachrichtEncrypted( ip, län );
+		if( !trenne( 0 ) )
+		{
+			delete[] ip;
+			unlock();
+			return 0;
+		}
+		if( !verbinde( port, ip ) )
+		{
+			delete[] ip;
+			unlock();
+			return 0;
+		}
+		delete[] ip;
+		unlock();
+		return getDateiGröße( gruppe, pfad );
+	}
+	int län = textLength( pfad );
+	klient->sendeEncrypted( (char*)&län, 4 );
+	klient->sendeEncrypted( pfad, län );
+	__int64 größe = 0;
+	klient->getNachrichtEncrypted( (char*)&größe, 8 );
+	unlock();
+	return größe;
+}
+
+bool PSKlient::downloadDatei( int gruppe, __int64 *start, const char *pfad, const char *zielPfad, FBalken *zFb, bool *abbruch, int maxbps )
+{
+	lock();
+	if( !verbunden )
+	{
+		unlock();
+		return 0;
+	}
+	Datei *zielD = new Datei();
+	zielD->setDatei( zielPfad );
+	if( !zielD->existiert() )
+		zielD->erstellen();
+	bool ok = 0;
+	if( !( *start ) ) // datei neu erstellen
+		ok = zielD->open( Datei::Style::schreiben );
+	else // datei weiterschreiben
+		ok = zielD->open( Datei::Style::schreiben | Datei::Style::lesen );
+	if( !ok )
+	{
+		zielD->release();
+		unlock();
+		return 0;
+	}
+	zielD->setSPosition( *start, 0 );
+	klient->sendeEncrypted( "\xB", 1 );
+	char ret = 0;
+	klient->getNachrichtEncrypted( &ret, 1 );
+	if( ret == 3 )
+	{ // error
+		klient->getNachrichtEncrypted( &ret, 1 );
+		char *msg = new char[ ret + 1 ];
+		msg[ ret ] = 0;
+		if( ret )
+			klient->getNachrichtEncrypted( msg, ret );
+		fehler->setText( msg );
+		delete[] msg;
+		zielD->close();
+		zielD->release();
+		unlock();
+		return 0;
+	}
+	klient->sendeEncrypted( (char*)&gruppe, 4 );
+	ret = 0;
+	klient->getNachrichtEncrypted( &ret, 1 );
+	if( ret == 3 )
+	{ // error
+		klient->getNachrichtEncrypted( &ret, 1 );
+		char *msg = new char[ ret + 1 ];
+		msg[ ret ] = 0;
+		if( ret )
+			klient->getNachrichtEncrypted( msg, ret );
+		fehler->setText( msg );
+		delete[] msg;
+		zielD->close();
+		zielD->release();
+		unlock();
+		return 0;
+	}
+	if( ret == 2 )
+	{ // verweis auf anderen Server
+		int port = 0;
+		klient->getNachrichtEncrypted( (char*)&port, 4 );
+		int län = 0;
+		klient->getNachrichtEncrypted( (char*)&län, 4 );
+		char *ip = new char[ län + 1 ];
+		ip[ län ] = 0;
+		klient->getNachrichtEncrypted( ip, län );
+		if( !trenne( 0 ) )
+		{
+			delete[] ip;
+			zielD->close();
+			zielD->release();
+			unlock();
+			return 0;
+		}
+		if( !verbinde( port, ip ) )
+		{
+			delete[] ip;
+			zielD->close();
+			zielD->release();
+			unlock();
+			return 0;
+		}
+		delete[] ip;
+		zielD->close();
+		zielD->release();
+		unlock();
+		return downloadDatei( gruppe, start, pfad, zielPfad, zFb, abbruch, maxbps );
+	}
+	int län = textLength( pfad );
+	klient->sendeEncrypted( (char*)&län, 4 );
+	klient->sendeEncrypted( pfad, län );
+	klient->sendeEncrypted( (char*)start, 8 );
+	char *bytes = new char[ 2048 ];
+	unsigned short byteLän = 0;
+	klient->getNachricht( (char*)&byteLän, 2 );
+	ZeitMesser *zMess = new ZeitMesser();
+	zMess->messungStart();
+	if( byteLän )
+	{
+		int bps = 0;
+		double sec = 0;
+		while( 1 )
+		{
+			klient->getNachricht( bytes, byteLän );
+			zielD->schreibe( bytes, byteLän );
+			if( zFb )
+		    	zFb->aktionPlus( byteLän );
+			( *start ) += byteLän;
+			bps += byteLän;
+			if( byteLän == 2048 )
+			{
+				if( ( *abbruch ) )
+				{
+					zielD->close();
+					zielD->release();
+					klient->trenne();
+					verbunden = 0;
+					delete[] bytes;
+					zMess->release();
+					unlock();
+					return 1;
+				}
+				klient->getNachricht( (char*)&byteLän, 2 ); // sendelänge empfangen
+				if( !byteLän )
+					break;
+			}
+			else
+				break;
+			if( maxbps )
+			{
+				zMess->messungEnde();
+				sec += zMess->getSekunden();
+				zMess->messungStart();
+				if( sec >= 1 )
+				{
+					sec = 0;
+					bps = 0;
+				}
+				while( bps >= maxbps )
+				{
+					Sleep( 10 );
+					zMess->messungEnde();
+					sec += zMess->getSekunden();
+					zMess->messungStart();
+					if( sec >= 1 )
+					{
+						sec = 0;
+						bps = 0;
+					}
+				}
+			}
+		}
+	}
+	zMess->release();
+	delete[] bytes;
+	klient->sendeEncrypted( "\1", 1 );
+	zielD->close();
+	zielD->release();
+	unlock();
+	return 1;
+}
+
+bool PSKlient::trenne( bool abmelden )
+{
+	lock();
+	if( !verbunden )
+	{
+		unlock();
+		return 1;
+	}
+	if( abmelden )
+	{
+		klient->sendeEncrypted( "\4", 1 );
+		char ret = 0;
+		klient->getNachrichtEncrypted( &ret, 1 );
+		if( ret == 3 )
+		{ // error
+			klient->getNachrichtEncrypted( &ret, 1 );
+			char *msg = new char[ ret + 1 ];
+			msg[ ret ] = 0;
+			if( ret )
+				klient->getNachrichtEncrypted( msg, ret );
+			fehler->setText( msg );
+			unlock();
+			delete[] msg;
+		}
+	}
+	klient->sendeEncrypted( "\3", 1 );
+	char ret = 0;
+	klient->getNachrichtEncrypted( &ret, 1 );
+	if( ret == 3 )
+	{ // error
+		klient->getNachrichtEncrypted( &ret, 1 );
+		char *msg = new char[ ret + 1 ];
+		msg[ ret ] = 0;
+		if( ret )
+			klient->getNachrichtEncrypted( msg, ret );
+		unlock();
+		fehler->setText( msg );
+		delete[] msg;
+	}
+	klient->trenne();
+	if( abmelden )
+	    klient = klient->release();
+	verbunden = 0;
+	unlock();
+	return 1;
+}
+
+// constant
+bool PSKlient::istVerbunden() const
+{
+	return verbunden;
+}
+
+bool PSKlient::istRegistriert() const
+{
+	return klient != 0;
+}
+
+int PSKlient::getDownload() const
+{
+	return klient ? (klient->getDownloadBytes( 1 ) + klient->getUploadBytes( 1 ) ) : 0;
+}
+
+Text *PSKlient::zError() const
+{
+	return fehler;
+}
+
+// Reference Counting
+PSKlient *PSKlient::getThis()
+{
+	ref++;
+	return this;
+}
+
+PSKlient *PSKlient::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 48 - 0
Update/PSKlient.h

@@ -0,0 +1,48 @@
+#ifndef PSKlient_H
+#define PSKlient_H
+
+#include <Klient.h>
+#include <KSGTDatei.h>
+#include <Fortschritt.h>
+
+using namespace Network;
+using namespace Framework;
+
+class PSKlient
+{
+private:
+	int id;
+	Klient *klient;
+	CRITICAL_SECTION cs;
+	char *schlüssel;
+	char schlüsselLän;
+	bool verbunden;
+	Text *fehler;
+	int ref;
+
+public:
+	// Konstruktor
+	PSKlient();
+	// Destruktor
+	~PSKlient();
+	// nicht constant
+	void lock();
+	void unlock();
+	bool verbinde();
+	bool verbinde( int port, const char *ip );
+	KSGTDatei *getDateiGruppenListe();
+	KSGTDatei *getDateiListe( int gruppe );
+	__int64 getDateiGröße( int gruppe, const char *pfad );
+	bool downloadDatei( int gruppe, __int64 *start, const char *pfad, const char *zielPfad, FBalken *zFb, bool *abbruch, int maxbps );
+	bool trenne( bool abmelden );
+	// constant
+	bool istVerbunden() const;
+	bool istRegistriert() const;
+	int getDownload() const;
+	Text *zError() const;
+	// Reference Counting
+	PSKlient *getThis();
+	PSKlient *release();
+};
+
+#endif

+ 184 - 0
Update/Update.vcxproj

@@ -0,0 +1,184 @@
+<?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>{EA9C25EE-2921-4332-A408-B731BA9E4050}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>Update</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</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;..\..\Include;$(IncludePath)</IncludePath>
+    <LibraryPath>..\..\..\..\Allgemein\Framework\x64\Debug;..\..\..\..\Allgemein\Network\x64\Debug;$(LibraryPath)</LibraryPath>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>..\..\..\..\Allgemein\Framework;..\..\..\..\Allgemein\Network\Network;..\..\Include;$(IncludePath)</IncludePath>
+    <LibraryPath>..\..\..\..\Allgemein\Framework\Release;..\..\..\..\Allgemein\Network\Release;$(LibraryPath)</LibraryPath>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>..\..\..\..\Allgemein\Framework;..\..\..\..\Allgemein\Network\Network;..\..\Include;$(IncludePath)</IncludePath>
+    <LibraryPath>..\..\..\..\Allgemein\Framework\x64\Release;..\..\..\..\Allgemein\Network\x64\Release;$(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;_USRDLL;UPDATE_EXPORTS;%(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;_USRDLL;UPDATE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>Framework.lib;Network.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <CustomBuildStep>
+      <Outputs>kopieren...;%(Outputs)</Outputs>
+      <Command>copy "..\x64\Debug\Update.dll" "..\..\patcher\patcher\data\bin\Update.dll"
+copy "..\x64\Debug\Update.dll" "..\..\Fertig\Debug\x64\data\bin\Update.dll"</Command>
+    </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;_USRDLL;UPDATE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>Framework.lib;Network.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <CustomBuildStep>
+      <Command>copy "..\Release\Update.dll" "..\..\Fertig\x32\data\bin\Update.dll"</Command>
+    </CustomBuildStep>
+    <CustomBuildStep>
+      <Outputs>kopieren...;%(Outputs)</Outputs>
+    </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;_USRDLL;UPDATE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>Framework.lib;Network.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <CustomBuildStep>
+      <Outputs>kopieren...;%(Outputs)</Outputs>
+      <Command>copy "..\x64\Release\Update.dll" "..\..\Fertig\x64\data\bin\Update.dll"</Command>
+    </CustomBuildStep>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="Keys.h" />
+    <ClInclude Include="PSKlient.h" />
+    <ClInclude Include="Updater.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="Einstieg.cpp" />
+    <ClCompile Include="Keys.cpp" />
+    <ClCompile Include="PSKlient.cpp" />
+    <ClCompile Include="Updater.cpp" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 42 - 0
Update/Update.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>{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;hh;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>
+    <ClInclude Include="PSKlient.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Updater.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Keys.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="PSKlient.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Updater.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Einstieg.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Keys.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>

+ 704 - 0
Update/Updater.cpp

@@ -0,0 +1,704 @@
+#include "Updater.h"
+#include <Text.h>
+#include <InitDatei.h>
+#include <Datei.h>
+
+// Inhalt der Updater Klasse aus Updater.h
+// Konstruktor
+Updater::Updater()
+{
+	client = new PSKlient();
+	fehler = new Text();
+	ref = 1;
+}
+
+// Destruktor
+Updater::~Updater()
+{
+	if( client->istRegistriert() )
+	{
+		if( !client->istVerbunden() )
+			client->verbinde();
+		client->trenne( 1 );
+	}
+	client->release();
+	fehler->release();
+}
+
+// nicht constant
+int Updater::getNextDateiGruppe( Text *zDgPfad )
+{
+	client->lock();
+	if( !client->istVerbunden() && !client->verbinde() )
+	{
+		fehler->setText( client->zError()->getText() );
+		client->unlock();
+		return -1;
+	}
+	KSGTDatei *sDgTb = client->getDateiGruppenListe();
+	if( !sDgTb )
+	{
+		fehler->setText( client->zError()->getText() );
+		client->trenne( 0 );
+		client->unlock();
+		return -1;
+	}
+	client->trenne( 0 );
+	client->unlock();
+	KSGTDatei *lDgTb = new KSGTDatei( "data/dg.ksgt" ); // Tabellen Spalten: Id, Pfad, Version, Priorität
+	lDgTb->laden();
+	InitDatei *ur = new InitDatei();
+	for( int i = 0; i < sDgTb->getZeilenAnzahl(); i++ )
+	{
+		int id = TextZuInt( sDgTb->zFeld( i, 0 )->getText(), 10 );
+		int vs = TextZuInt( sDgTb->zFeld( i, 2 )->getText(), 10 );
+		bool gefunden = 0;
+		for( int j = 0; j < lDgTb->getZeilenAnzahl(); j++ )
+		{
+			if( id == TextZuInt( lDgTb->zFeld( j, 0 )->getText(), 10 ) )
+			{
+				if( vs != TextZuInt( lDgTb->zFeld( j, 2 )->getText(), 10 ) )
+				{
+					if( !sDgTb->zFeld( i, 1 )->getLength() )
+						ur->addWert( sDgTb->zFeld( i, 0 )->getText(), "SOFORT" );
+					else if( !lDgTb->zFeld( j, 3 )->istGleich( "NICHT" ) )
+						ur->addWert( sDgTb->zFeld( i, 0 )->getText(), lDgTb->zFeld( j, 3 )->getText() );
+				}
+				gefunden = 1;
+				break;
+			}
+		}
+		if( gefunden )
+			continue;
+		if( !sDgTb->zFeld( i, 1 )->getLength() )
+			ur->addWert( sDgTb->zFeld( i, 0 )->getText(), "SOFORT" );
+		else if( DateiExistiert( sDgTb->getFeld( i, 1 ) ) )
+			ur->addWert( sDgTb->zFeld( i, 0 )->getText(), "SPÄTER" );
+	}
+	lDgTb->release();
+	if( !ur->getWertAnzahl() )
+	{
+		ur->release();
+		sDgTb->release();
+		return 0;
+	}
+	int gruppe = 0;
+	for( int i = 0; i < ur->getWertAnzahl(); i++ )
+	{
+		if( ur->zWert( i )->istGleich( "SOFORT" ) )
+		{
+			gruppe = TextZuInt( ur->zName( i )->getText(), 10 );
+			break;
+		}
+	}
+	if( !gruppe )
+	{
+		unsigned int klein = 0xFFFFFFFF;
+		for( int i = 0; i < ur->getWertAnzahl(); i++ )
+		{
+			if( !ur->zWert( i )->istGleich( "SPÄTER" ) )
+			{
+				unsigned int num = TextZuInt( ur->zWert( i )->getText(), 10 );
+				if( num < klein )
+				{
+					klein = num;
+					gruppe = TextZuInt( ur->zName( i )->getText(), 10 );
+				}
+			}
+		}
+		if( !gruppe )
+		{
+			for( int i = 0; i < ur->getWertAnzahl(); i++ )
+			{
+				if( ur->zWert( i )->istGleich( "SPÄTER" ) )
+				{
+					gruppe = TextZuInt( ur->zName( i )->getText(), 10 );
+					break;
+				}
+			}
+		}
+	}
+	ur->release();
+	if( zDgPfad )
+	{ // Pfad der Dateigruppe ermitteln
+		for( int i = 0; i < sDgTb->getZeilenAnzahl(); i++ )
+		{
+			if( gruppe == TextZuInt( sDgTb->zFeld( i, 0 )->getText(), 10 ) )
+			{
+				zDgPfad->setText( sDgTb->zFeld( i, 1 )->getText() );
+				break;
+			}
+		}
+	}
+	sDgTb->release();
+	return gruppe;
+}
+
+int Updater::update( UpdateParams *zParams )
+{
+	if( zParams->zStatus )
+	{
+		zParams->zStatus->lockZeichnung();
+		zParams->zStatus->setText( "Warte auf Update . . ." );
+		zParams->zStatus->unlockZeichnung();
+	}
+	client->lock();
+	if( zParams->zStatus )
+	{
+		zParams->zStatus->lockZeichnung();
+		zParams->zStatus->setText( "Verbinden . . ." );
+		zParams->zStatus->unlockZeichnung();
+	}
+	if( !client->istVerbunden() && !client->verbinde() )
+	{
+		fehler->setText( client->zError()->getText() );
+		client->unlock();
+		return 1;
+	}
+	bool clientGruppe = 0;
+	KSGTDatei *dgL = client->getDateiGruppenListe();
+	if( !dgL )
+	{
+		fehler->setText( client->zError()->getText() );
+		client->trenne( 0 );
+		client->unlock();
+		return 1;
+	}
+	Text *pfad = new Text( "" );
+	for( int i = 0; i < dgL->getZeilenAnzahl(); i++ )
+	{ // Pfad der Dateigruppe ermitteln
+		if( zParams->dateiGruppe == TextZuInt( dgL->zFeld( i, 0 )->getText(), 10 ) )
+		{
+			pfad->setText( dgL->zFeld( i, 1 )->getText() );
+			if( !pfad->getLength() )
+				clientGruppe = 1;
+			break;
+		}
+	}
+	if( !clientGruppe )
+		pfad->append( "/" );
+	Text *dlPf = new Text( pfad->getText() );
+	dlPf->append( "data/update/datei_versionen.ini" );
+	InitDatei *dateiListe = new InitDatei( dlPf );
+	dateiListe->laden();
+	Text *dsPf = new Text( pfad->getText() );
+	dsPf->append( "data/update/datei_status.ini" );
+	InitDatei *dateiStatus = new InitDatei( dsPf );
+	dateiStatus->laden();
+	Text *llPf = new Text( pfad->getText() );
+	llPf->append( "data/update/datei_remove.patch" );
+	Datei *removeListe = new Datei();
+	removeListe->setDatei( llPf );
+	if( !removeListe->existiert() )
+		removeListe->erstellen();
+	removeListe->open( Datei::Style::schreiben );
+	KSGTDatei *dl = client->getDateiListe( zParams->dateiGruppe ); // Liste mit Dateien aus der Gruppe
+	if( !dl )
+	{ // error
+		dgL->release();
+		pfad->release();
+		dateiListe->release();
+		dateiStatus->release();
+		removeListe->release();
+		fehler->setText( client->zError()->getText() );
+		client->trenne( 0 );
+		client->unlock();
+		return 1;
+	}
+	for( int i = 0; i < dl->getZeilenAnzahl(); i++ )
+	{
+		if( dl->zFeld( i, 0 )->istGleich( "1" ) )
+		{ // existierende Datei
+			if( !dateiListe->wertExistiert( dl->zFeld( i, 1 )->getText() ) )
+			{
+				dateiListe->addWert( dl->zFeld( i, 1 )->getText(), dl->zFeld( i, 2 )->getText() );
+				dateiStatus->addWert( dl->zFeld( i, 1 )->getText(), "Ausstehend" );
+			}
+			else
+			{
+				if( !dateiListe->zWert( dl->zFeld( i, 1 )->getText() )->istGleich( dl->zFeld( i, 2 )->getText() ) )
+				{
+					dateiListe->setWert( dl->zFeld( i, 1 )->getText(), dl->zFeld( i, 2 )->getText() );
+					dateiStatus->setWert( dl->zFeld( i, 1 )->getText(), "Ausstehend" );
+				}
+			}
+		}
+		else
+		{ // gelöschte Datei
+			removeListe->schreibe( dl->zFeld( i, 1 )->getText(), dl->zFeld( i, 1 )->getLength() );
+			removeListe->schreibe( "\n", 1 );
+			dateiListe->removeWert( dl->zFeld( i, 1 )->getText() );
+			dateiStatus->removeWert( dl->zFeld( i, 1 )->getText() );
+		}
+	}
+	removeListe->close();
+	removeListe->release();
+	dateiListe->speichern();
+	dateiStatus->speichern();
+	dl->release();
+	Text *ldPf = new Text( pfad->getText() );
+	ldPf->append( "data/versionen.ini" );
+	InitDatei *lokaleDateien = new InitDatei( ldPf );
+	if( !lokaleDateien->laden() )
+		DateiPfadErstellen( lokaleDateien->zPfad()->getText() );
+	__int64 maxAktionen = 0;
+	for( int i = 0; i < dateiListe->getWertAnzahl(); i++ )
+	{
+		bool geändert = 0;
+		if( !lokaleDateien->wertExistiert( dateiListe->zName( i )->getText() ) )
+		{
+			geändert = 1;
+			if( dateiStatus->zWert( dateiListe->zName( i )->getText() ) &&
+				dateiStatus->zWert( dateiListe->zName( i )->getText() )->istGleich( "Fertig" ) )
+				geändert = 0;
+		}
+		else
+		{
+			if( !lokaleDateien->zWert( dateiListe->zName( i )->getText() )->istGleich( dateiListe->zWert( i )->getText() ) )
+				geändert = 1;
+			else
+				dateiStatus->setWert( dateiListe->zName( i )->getText(), "Fertig" );
+		}
+		if( geändert && !dateiStatus->zWert( dateiListe->zName( i )->getText() )->istGleich( "Fertig" ) )
+		{
+			maxAktionen += client->getDateiGröße( zParams->dateiGruppe, dateiListe->zName( i )->getText() );
+			if( dateiStatus->zWert( dateiListe->zName( i )->getText() )->istGleich( "InBearbeitung" ) )
+			{
+				Text *jPf = new Text( pfad->getText() );
+				jPf->append( "data/update/jetzt_position.patch" );
+				Datei *jetzt = new Datei();
+				jetzt->setDatei( jPf );
+				if( jetzt->open( Datei::Style::lesen ) )
+				{
+					__int64 pos = 0;
+					jetzt->lese( (char*)&pos, 8 );
+					maxAktionen -= pos;
+					jetzt->close();
+				}
+				jetzt->release();
+			}
+		}
+	}
+	dateiStatus->speichern();
+	if( zParams->zFortschritt )
+	{
+		zParams->zFortschritt->reset();
+		zParams->zFortschritt->setAktionAnzahl( maxAktionen );
+	}
+	for( int i = 0; i < dateiStatus->getWertAnzahl(); i++ )
+	{
+		if( dateiStatus->zWert( i )->istGleich( "InBearbeitung" ) )
+		{
+			Text *jPf = new Text( pfad->getText() );
+			jPf->append( "data/update/jetzt_position.patch" );
+			Datei *jetzt = new Datei();
+			jetzt->setDatei( jPf );
+			__int64 pos = 0;
+			if( jetzt->open( Datei::Style::lesen ) )
+			{
+				jetzt->lese( (char*)&pos, 8 );
+				jetzt->close();
+			}
+			jetzt->release();
+			Text *zielPf = new Text( pfad->getText() );
+			zielPf->append( "data/update/download/" );
+			zielPf->append( dateiStatus->zName( i )->getText() );
+			InitDatei *poIni = new InitDatei( "data/patch/po.ini" );
+			poIni->laden();
+			int maxbps = 0;
+			if( poIni->wertExistiert( "ülps" ) && poIni->zWert( "ülps" )->getLength() && poIni->wertExistiert( "üle" ) )
+			{
+				if( poIni->zWert( "üle" )->istGleich( "kb/s" ) )
+					maxbps = (int)TextZuInt( poIni->zWert( "ülps" )->getText(), 10 ) * 1024;
+				if( poIni->zWert( "üle" )->istGleich( "mb/s" ) )
+					maxbps = (int)TextZuInt( poIni->zWert( "ülps" )->getText(), 10 ) * 1024 * 1024;
+			}
+			poIni->release();
+			if( zParams->zStatus )
+			{
+				zParams->zStatus->lockZeichnung();
+				zParams->zStatus->setText( dateiStatus->zName( i )->getText() );
+				zParams->zStatus->unlockZeichnung();
+			}
+			if( client->downloadDatei( zParams->dateiGruppe, &pos, dateiStatus->zName( i )->getText(), zielPf->getText(), zParams->zFortschritt, zParams->abbruch, maxbps ) )
+			{
+				if( ( *zParams->abbruch ) )
+				{ // übertragung unterbrochen
+					jPf = new Text( pfad->getText() );
+					jPf->append( "data/update/jetzt_position.patch" );
+					jetzt = new Datei();
+					jetzt->setDatei( jPf );
+					if( jetzt->open( Datei::Style::schreiben ) )
+					{
+						jetzt->schreibe( (char*)&pos, 8 );
+						jetzt->close();
+					}
+					jetzt->release();
+					dgL->release();
+					pfad->release();
+					dateiListe->release();
+					dateiStatus->release();
+					zielPf->release();
+					lokaleDateien->release();
+					fehler->setText( "" );
+					client->trenne( 0 );
+					client->unlock();
+					return 2;
+				}
+				else
+				{
+					dateiStatus->setWert( i, "Fertig" );
+					dateiStatus->speichern();
+				}
+			}
+			else
+			{ // error
+				dgL->release();
+				pfad->release();
+				dateiListe->release();
+				dateiStatus->release();
+				zielPf->release();
+				lokaleDateien->release();
+				fehler->setText( client->zError()->getText() );
+				client->trenne( 0 );
+				client->unlock();
+				return 1;
+			}
+			zielPf->release();
+			break;
+		}
+	}
+	for( int i = 0; i < dateiStatus->getWertAnzahl(); i++ )
+	{
+		if( dateiStatus->zWert( i )->istGleich( "Ausstehend" ) )
+		{
+			dateiStatus->setWert( i, "InBearbeitung" );
+			Text *jPf = new Text( pfad->getText() );
+			jPf->append( "data/update/jetzt_position.patch" );
+			Datei *jetzt = new Datei();
+			jetzt->setDatei( jPf );
+			__int64 pos = 0;
+			jetzt->open( Datei::Style::schreiben );
+			jetzt->schreibe( (char*)&pos, 8 );
+			jetzt->close();
+			jetzt->release();
+			dateiStatus->speichern();
+			Text *zielPf = new Text( pfad->getText() );
+			zielPf->append( "data/update/download/" );
+			zielPf->append( dateiStatus->zName( i )->getText() );
+			InitDatei *poIni = new InitDatei( "data/patch/po.ini" );
+			poIni->laden();
+			int maxbps = 0;
+			if( poIni->wertExistiert( "ülps" ) && poIni->zWert( "ülps" )->getLength() && poIni->wertExistiert( "üle" ) )
+			{
+				if( poIni->zWert( "üle" )->istGleich( "kb/s" ) )
+					maxbps = (int)TextZuInt( poIni->zWert( "ülps" )->getText(), 10 ) * 1024;
+				if( poIni->zWert( "üle" )->istGleich( "mb/s" ) )
+					maxbps = (int)TextZuInt( poIni->zWert( "ülps" )->getText(), 10 ) * 1024 * 1024;
+			}
+			poIni->release();
+			if( zParams->zStatus )
+			{
+				zParams->zStatus->lockZeichnung();
+				zParams->zStatus->setText( dateiStatus->zName( i )->getText() );
+				zParams->zStatus->unlockZeichnung();
+			}
+			if( client->downloadDatei( zParams->dateiGruppe, &pos, dateiStatus->zName( i )->getText(), zielPf->getText(), zParams->zFortschritt, zParams->abbruch, maxbps ) )
+			{
+				if( ( *zParams->abbruch ) )
+				{ // übertragung unterbrochen
+					jPf = new Text( pfad->getText() );
+					jPf->append( "data/update/jetzt_position.patch" );
+					jetzt = new Datei();
+					jetzt->setDatei( jPf );
+					if( jetzt->open( Datei::Style::schreiben ) )
+					{
+						jetzt->schreibe( (char*)&pos, 8 );
+						jetzt->close();
+					}
+					jetzt->release();
+					dgL->release();
+					pfad->release();
+					dateiListe->release();
+					dateiStatus->release();
+					zielPf->release();
+					lokaleDateien->release();
+					fehler->setText( "" );
+					client->trenne( 0 );
+					client->unlock();
+					return 2;
+				}
+				else
+				{
+					dateiStatus->setWert( i, "Fertig" );
+					dateiStatus->speichern();
+				}
+			}
+			else
+			{ // error
+				dgL->release();
+				pfad->release();
+				dateiListe->release();
+				dateiStatus->release();
+				zielPf->release();
+				lokaleDateien->release();
+				fehler->setText( client->zError()->getText() );
+				client->trenne( 0 );
+				client->unlock();
+				return 1;
+			}
+			zielPf->release();
+		}
+	}
+	if( zParams->zStatus )
+	{
+		zParams->zStatus->lockZeichnung();
+		zParams->zStatus->setText( "Übernehme Änderungen..." );
+		zParams->zStatus->unlockZeichnung();
+	}
+    removeListe = new Datei();
+    llPf = new Text( pfad->getText() );
+    llPf->append( "data/update/datei_remove.patch" );
+    removeListe->setDatei( llPf );
+	removeListe->open( Datei::Style::lesen );
+	Text *zeile = removeListe->leseZeile();
+	while( zeile )
+	{
+        zeile->remove( "\r\n" );
+        zeile->remove( "\n" );
+		if( !zeile->getLength() )
+			break;
+        Text pf = pfad->getText();
+        pf += zeile->getText();
+		lokaleDateien->removeWert( zeile->getText() );
+        DateiRemove( pf );
+        zeile->release();
+		zeile = removeListe->leseZeile();
+	}
+	lokaleDateien->speichern();
+	removeListe->close();
+	removeListe->remove();
+	removeListe->release();
+	if( clientGruppe )
+	{ // Es wird der Patcher selbst geupdatet
+		Text *uPf = new Text( pfad->getText() );
+		uPf->append( "data/update/unable/list.patch" );
+		Datei *unable = new Datei();
+		unable->setDatei( uPf );
+		unable->erstellen();
+		unable->open( Datei::Style::schreiben );
+		bool fertig = 1;
+		for( int i = 0; i < dateiStatus->getWertAnzahl(); i++ )
+		{
+			Text *altPfad = new Text( pfad->getText() );
+			altPfad->append( "data/update/download/" );
+			altPfad->append( dateiStatus->zName( i )->getText() );
+			Text *neuPfad = new Text( pfad->getText() );
+			neuPfad->append( dateiStatus->zName( i )->getText() );
+			if( DateiExistiert( altPfad->getThis() ) )
+			{
+				bool b = 0;
+				if( !DateiExistiert( neuPfad->getText() ) )
+					DateiPfadErstellen( neuPfad->getText() );
+				if( DateiExistiert( neuPfad->getText() ) )
+				{
+					if( DateiRemove( neuPfad->getText() ) )
+					{
+						if( !DateiUmbenennen( altPfad->getText(), neuPfad->getText() ) )
+							b = 1;
+					}
+					else
+						b = 1;
+				}
+				else
+				{
+					if( !DateiUmbenennen( altPfad->getText(), neuPfad->getText() ) )
+						b = 1;
+				}
+				if( b )
+				{
+					unable->schreibe( "\2", 1 );
+					unable->schreibe( neuPfad->getText(), neuPfad->getLength() );
+					unable->schreibe( "=>", 2 );
+					unable->schreibe( altPfad->getText(), altPfad->getLength() );
+					unable->schreibe( "\n", 1 );
+					fertig = 0;
+				}
+			}
+			altPfad->release();
+			neuPfad->release();
+			if( !lokaleDateien->wertExistiert( dateiStatus->zName( i )->getText() ) )
+				lokaleDateien->addWert( dateiStatus->zName( i )->getText(), dateiListe->zWert( dateiStatus->zName( i )->getText() )->getText() );
+			else
+				lokaleDateien->setWert( dateiStatus->zName( i )->getText(), dateiListe->zWert( dateiStatus->zName( i )->getText() )->getText() );
+		}
+		unable->close();
+		if( fertig )
+			unable->remove();
+		unable->release();
+	}
+	else
+	{ // Es werden Spiele und Karten geupdatet
+		for( int i = 0; i < dateiStatus->getWertAnzahl(); i++ )
+		{
+			Text *altPfad = new Text( pfad->getText() );
+			altPfad->append( "data/update/download/" );
+			altPfad->append( dateiStatus->zName( i )->getText() );
+			Text *neuPfad = new Text( pfad->getText() );
+			neuPfad->append( dateiStatus->zName( i )->getText() );
+			if( DateiExistiert( altPfad->getThis() ) )
+			{
+				bool b = 0;
+				if( !DateiExistiert( neuPfad->getText() ) )
+					DateiPfadErstellen( neuPfad->getText() );
+				if( DateiExistiert( neuPfad->getText() ) )
+				{
+					if( DateiRemove( neuPfad->getText() ) )
+					{
+						if( !DateiUmbenennen( altPfad->getText(), neuPfad->getText() ) )
+							b = 1;
+					}
+					else
+						b = 1;
+				}
+				else
+				{
+					if( !DateiUmbenennen( altPfad->getText(), neuPfad->getText() ) )
+						b = 1;
+				}
+				if( b )
+				{ // error
+					dgL->release();
+					pfad->release();
+					lokaleDateien->speichern();
+					lokaleDateien->release();
+					dateiListe->release();
+					dateiStatus->release();
+					fehler->setText( client->zError()->getText() );
+					client->trenne( 0 );
+					client->unlock();
+					return 1;
+				}
+			}
+			altPfad->release();
+			neuPfad->release();
+			if( !lokaleDateien->wertExistiert( dateiStatus->zName( i )->getText() ) )
+				lokaleDateien->addWert( dateiStatus->zName( i )->getText(), dateiListe->zWert( dateiStatus->zName( i )->getText() )->getText() );
+			else
+				lokaleDateien->setWert( dateiStatus->zName( i )->getText(), dateiListe->zWert( dateiStatus->zName( i )->getText() )->getText() );
+		}
+	}
+	lokaleDateien->speichern();
+	lokaleDateien->release();
+	dateiListe->release();
+	dateiStatus->release();
+	Text *jpPf = new Text( pfad->getText() );
+	jpPf->append( "data/update/jetzt_position.patch" );
+	DateiRemove( jpPf );
+	Text *dvPf = new Text( pfad->getText() );
+	dvPf->append( "data/update/datei_versionen.ini" );
+	DateiRemove( dvPf );
+	dsPf = new Text( pfad->getText() );
+	dsPf->append( "data/update/datei_status.ini" );
+	DateiRemove( dsPf );
+	if( clientGruppe )
+	{
+		Text *ulPf = new Text( pfad->getText() );
+		ulPf->append( "data/update/unable/list.patch" );
+		if( DateiExistiert( ulPf ) )
+		{ // es gibt Dateien, die der Patcher (wegen momentaner Benutzung) nicht pätchen konnte
+			dgL->release();
+			pfad->release();
+			fehler->setText( "" );
+			client->trenne( 0 );
+			client->unlock();
+			return 3;
+		}
+	}
+	pfad->release();
+	KSGTDatei *lDgL = new KSGTDatei( "data/dg.ksgt" );
+	lDgL->laden();
+	bool gefunden = 0;
+	for( int i = 0; i < lDgL->getZeilenAnzahl(); i++ )
+	{
+		if( zParams->dateiGruppe == TextZuInt( lDgL->zFeld( i, 0 )->getText(), 10 ) )
+		{
+			for( int j = 0; j < dgL->getZeilenAnzahl(); j++ )
+			{
+				if( zParams->dateiGruppe == TextZuInt( dgL->zFeld( j, 0 )->getText(), 10 ) )
+				{
+					lDgL->setFeld( i, 2, dgL->zFeld( j, 2 )->getText() );
+					break;
+				}
+			}
+			gefunden = 1;
+			break;
+		}
+	}
+	if( !gefunden )
+	{
+		unsigned int rfPos = 0;
+		for( int i = 0; i < lDgL->getZeilenAnzahl(); i++ )
+		{
+			if( rfPos <= TextZuInt( lDgL->zFeld( i, 3 )->getText(), 10 ) )
+				rfPos = TextZuInt( lDgL->zFeld( i, 3 )->getText(), 10 ) + 1;
+		}
+		rfPos++;
+		for( int i = 0; i < dgL->getZeilenAnzahl(); i++ )
+		{
+			if( zParams->dateiGruppe == TextZuInt( dgL->zFeld( i, 0 )->getText(), 10 ) )
+			{
+				RCArray< Text > *zeile = new RCArray< Text >();
+				zeile->set( new Text( dgL->zFeld( i, 0 )->getText() ), 0 );
+				zeile->set( new Text( dgL->zFeld( i, 1 )->getText() ), 1 );
+				zeile->set( new Text( dgL->zFeld( i, 2 )->getText() ), 2 );
+				Text *rfPosT = new Text();
+				rfPosT->append( rfPos );
+				zeile->set( rfPosT, 3 );
+				lDgL->addZeile( 4, zeile );
+				zeile->release();
+				break;
+			}
+		}
+	}
+	dgL->release();
+	lDgL->speichern();
+	lDgL->release();
+	if( ( *zParams->abbruch ) )
+	{
+		fehler->setText( "" );
+		client->trenne( 0 );
+		client->unlock();
+		return 2;
+	}
+	client->trenne( 0 );
+	client->unlock();
+	fehler->setText( "" );
+	return 0;
+}
+
+// constant
+char *Updater::getError() const
+{
+	return fehler->getText();
+}
+
+int Updater::getDownload() const
+{
+	return client->getDownload();
+}
+
+// Reference Counting
+UpdaterV *Updater::getThis()
+{
+	ref++;
+	return this;
+}
+
+UpdaterV *Updater::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 32 - 0
Update/Updater.h

@@ -0,0 +1,32 @@
+#ifndef Updater_H
+#define Updater_H
+
+#include <Update.h>
+#include "PSKlient.h"
+
+using namespace Framework;
+
+class Updater : public UpdaterV
+{
+private:
+	PSKlient *client;
+	Text *fehler;
+	int ref;
+
+public:
+	// Konstruktor
+	Updater();
+	// Destruktor
+	~Updater();
+	// nicht constant
+	virtual int getNextDateiGruppe( Text *zDgPfad );
+	virtual int update( UpdateParams *zParams );
+	// constant
+	virtual char *getError() const;
+	virtual int getDownload() const;
+	// Reference Counting
+	virtual UpdaterV *getThis();
+	virtual UpdaterV *release();
+};
+
+#endif

+ 3 - 0
build.bat

@@ -0,0 +1,3 @@
+"D:\Visual Studio 2017\MSBuild\15.0\Bin\MSBuild.exe" "Update.sln" /p:configuration=release /p:platform=win32
+"D:\Visual Studio 2017\MSBuild\15.0\Bin\MSBuild.exe" "Update.sln" /p:configuration=release /p:platform=x64
+"D:\Visual Studio 2017\MSBuild\15.0\Bin\MSBuild.exe" "Update.sln" /p:configuration=debug /p:platform=x64