#include "../KSGKlient.h"
#include "../KSGServer.h"
#include <Datei.h>
#include "../Keys.h"

// Inhalt der ShopKlient Klasse aus KSGKtient.h
// Konstruktor
ShopKlient::ShopKlient()
{
    verbunden = 0;
    klient = 0;
    fehler = new Text( "" );
    klientId = getKlientId();
    ref = 1;
}

// Destruktor
ShopKlient::~ShopKlient()
{
    cs.lock();
    if( klient )
    {
        char serverReturn = 0;
        if( verbunden )
        {
            klient->sendeEncrypted( "\4", 1 );
            klient->getNachrichtEncrypted( &serverReturn, 1 );
            if( serverReturn == 3 )
            {
                char l�n = 0;
                klient->getNachrichtEncrypted( &l�n, 1 );
                char *nachricht = new char[ l�n + 1 ];
                nachricht[ l�n ] = 0;
                klient->getNachrichtEncrypted( nachricht, l�n );
                delete[]nachricht;
            }
            klient->sendeEncrypted( "\3", 1 );
            klient->getNachrichtEncrypted( &serverReturn, 1 );
            klient->trenne();
        }
        else
        {
            int keyLen = 0;
            char *key = 0;
            Keys::getServerKey( &key, keyLen, Keys::SHOP, Keys::SENDEN );
            klient->setSendeKey( key, keyLen );
            delete[] key;
            Keys::getServerKey( &key, keyLen, Keys::SHOP, Keys::EMPFANGEN );
            klient->setEmpfangKey( key, keyLen );
            delete[] key;
            klient->verbinde( klient->getServerPort(), klient->getServerIp() );
            klient->sendeEncrypted( "\1", 1 );
            klient->sendeEncrypted( (char*)&klientId, 4 );
            klient->getNachrichtEncrypted( &serverReturn, 1 );
            if( serverReturn == 3 )
            {
                char l�n = 0;
                klient->getNachrichtEncrypted( &l�n, 1 );
                char *nachricht = new char[ l�n + 1 ];
                nachricht[ l�n ] = 0;
                klient->getNachrichtEncrypted( nachricht, l�n );
                delete[]nachricht;
            }
            else
            {
                char *sl = 0;
                char slL�n = getSchl�ssel( &sl );
                klient->setSendeKey( sl, slL�n );
                klient->setEmpfangKey( sl, slL�n );
                delete[] sl;
                klient->sendeEncrypted( "\4", 1 );
                klient->getNachrichtEncrypted( &serverReturn, 1 );
                if( serverReturn == 3 )
                {
                    char l�n = 0;
                    klient->getNachrichtEncrypted( &l�n, 1 );
                    char *nachricht = new char[ l�n + 1 ];
                    nachricht[ l�n ] = 0;
                    klient->getNachrichtEncrypted( nachricht, l�n );
                    delete[]nachricht;
                }
            }
            klient->sendeEncrypted( "\3", 1 );
            klient->getNachrichtEncrypted( &serverReturn, 1 );
            klient->trenne();
        }
        klient = klient->release();
    }
    fehler = fehler->release();
    cs.unlock();
}

// privat
bool ShopKlient::verbinde( int port, char *ip ) // verbindet sich mit vorgegebenem Server
{
    int keyLen = 0;
    char *key = 0;
    Keys::getServerKey( &key, keyLen, Keys::SHOP, Keys::SENDEN );
    klient->setSendeKey( key, keyLen );
    delete[] key;
    Keys::getServerKey( &key, keyLen, Keys::SHOP, Keys::EMPFANGEN );
    klient->setEmpfangKey( key, keyLen );
    delete[] key;
    if( klient->verbinde( port, ip ) )
    {
        if( klient->sendeEncrypted( "\1", 1 ) )
        {
            klient->sendeEncrypted( (char*)&klientId, 4 );
            char serverReturn = 0;
            klient->getNachrichtEncrypted( &serverReturn, 1 );
            if( serverReturn == 3 )
            {
                char byte = 0;
                klient->getNachrichtEncrypted( &byte, 1 );
                char *f = new char[ byte + 1 ];
                f[ byte ] = 0;
                klient->getNachrichtEncrypted( f, byte );
                fehler->setText( f );
                delete[]f;
                return 0;
            }
            char *sl = 0;
            char slL�n = getSchl�ssel( &sl );
            klient->setSendeKey( sl, slL�n );
            klient->setEmpfangKey( sl, slL�n );
            delete[] sl;
            return 1;
        }
        else
        {
            fehler->setText( "Der dir zugewiesene Shop Server hat die Verbindung abgebrochen. Bitte versuche es Sp�ter erneut." );
            klient = klient->release();
        }
    }
    else
    {
        fehler->setText( "Der dir zugewiesene Shop Server antwortet nicht. Bitte versuche es Sp�ter erneut." );
        klient = klient->release();
    }
    return 0;
}

// nicht constant
bool ShopKlient::verbinde() // verbindet ich mit dem Shop Server
{
    cs.lock();
    if( verbunden )
    {
        cs.unlock();
        return 1;
    }
    if( !klient )
    {
        char *msIp = getMainServerIp();
        unsigned short msPort = getMainServerPort();
        klient = new Klient();
        int keyLen = 0;
        char *key = 0;
        Keys::getServerKey( &key, keyLen, Keys::MAIN, Keys::SENDEN );
        klient->setSendeKey( key, keyLen );
        delete[] key;
        Keys::getServerKey( &key, keyLen, Keys::MAIN, Keys::EMPFANGEN );
        klient->setEmpfangKey( key, keyLen );
        delete[] key;
        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;
            cs.unlock();
            return 0;
        }
        delete[]msIp;
        klient->sende( "\0", 1 ); // Verschl�sselung aktivieren
        klient->sendeEncrypted( "\1", 1 );
        klient->sendeEncrypted( (char*)&klientId, 4 );
        char serverReturn = 0;
        klient->getNachrichtEncrypted( &serverReturn, 1 );
        if( serverReturn == 3 )
        {
            char l�n = 0;
            klient->getNachrichtEncrypted( &l�n, 1 );
            char *nachricht = new char[ l�n + 1 ];
            nachricht[ l�n ] = 0;
            klient->getNachrichtEncrypted( nachricht, l�n );
            fehler->setText( nachricht );
            delete[]nachricht;
            klient->sendeEncrypted( "\3", 1 );
            klient->getNachrichtEncrypted( &serverReturn, 1 );
            klient->trenne();
            klient = klient->release();
            cs.unlock();
            return 0;
        }
        char *sl = 0;
        char slL�n = getSchl�ssel( &sl );
        klient->setSendeKey( sl, slL�n );
        klient->setEmpfangKey( sl, slL�n );
        delete[] sl;
        klient->sendeEncrypted( "\6\7", 2 );
        char byte = 0;
        klient->getNachrichtEncrypted( &byte, 1 );
        if( byte == 2 )
        {
            unsigned char lsIp[ 4 ];
            klient->getNachrichtEncrypted( (char *)lsIp, 4 );
            unsigned short lsPort = 0;
            klient->getNachrichtEncrypted( (char*)&lsPort, 2 );
            klient->sendeEncrypted( "\3", 1 );
            klient->getNachrichtEncrypted( &serverReturn, 1 );
            klient->trenne();
            Text *lsIpT = new Text( "" );
            lsIpT->append( (int)lsIp[ 0 ] );
            lsIpT->append( "." );
            lsIpT->append( (int)lsIp[ 1 ] );
            lsIpT->append( "." );
            lsIpT->append( (int)lsIp[ 2 ] );
            lsIpT->append( "." );
            lsIpT->append( (int)lsIp[ 3 ] );
            int keyLen = 0;
            char *key = 0;
            Keys::getServerKey( &key, keyLen, Keys::SHOP, Keys::SENDEN );
            klient->setSendeKey( key, keyLen );
            delete[] key;
            Keys::getServerKey( &key, keyLen, Keys::SHOP, Keys::EMPFANGEN );
            klient->setEmpfangKey( key, keyLen );
            delete[] key;
            klient->verbinde( lsPort, lsIpT->getText() );
            lsIpT = lsIpT->release();
            klient->sendeEncrypted( "\3", 1 );
            klient->getNachrichtEncrypted( &serverReturn, 1 );
            klient->trenne();
        }
        if( byte == 3 )
        {
            klient->getNachrichtEncrypted( &byte, 1 );
            char *f = new char[ byte + 1 ];
            f[ byte ] = 0;
            klient->getNachrichtEncrypted( f, byte );
            fehler->setText( f );
            delete[]f;
            klient->sendeEncrypted( "\3", 1 );
            klient->getNachrichtEncrypted( &serverReturn, 1 );
            klient->trenne();
            klient = klient->release();
            cs.unlock();
            return 0;
        }
    }
    int keyLen = 0;
    char *key = 0;
    Keys::getServerKey( &key, keyLen, Keys::SHOP, Keys::SENDEN );
    klient->setSendeKey( key, keyLen );
    delete[] key;
    Keys::getServerKey( &key, keyLen, Keys::SHOP, Keys::EMPFANGEN );
    klient->setEmpfangKey( key, keyLen );
    delete[] key;
    if( klient->verbinde( klient->getServerPort(), klient->getServerIp() ) )
    {
        if( klient->sendeEncrypted( "\1", 1 ) )
        {
            klient->sendeEncrypted( (char*)&klientId, 4 );
            char serverReturn = 0;
            klient->getNachrichtEncrypted( &serverReturn, 1 );
            if( serverReturn == 3 )
            {
                char byte = 0;
                klient->getNachrichtEncrypted( &byte, 1 );
                char *f = new char[ byte + 1 ];
                f[ byte ] = 0;
                klient->getNachrichtEncrypted( f, byte );
                fehler->setText( f );
                delete[]f;
                klient->sendeEncrypted( "\3", 1 );
                klient->getNachrichtEncrypted( &serverReturn, 1 );
                klient->trenne();
                cs.unlock();
                return 0;
            }
            char *sl = 0;
            char slL�n = getSchl�ssel( &sl );
            klient->setSendeKey( sl, slL�n );
            klient->setEmpfangKey( sl, slL�n );
            delete[] sl;
            verbunden = 1;
            cs.unlock();
            return 1;
        }
        else
        {
            fehler->setText( "Der dir zugewiesene Shop Server hat die Verbindung abgebrochen. Bitte versuche es Sp�ter erneut." );
            klient = klient->release();
        }
    }
    else
    {
        fehler->setText( "Der dir zugewiesene Shop Server antwortet nicht. Bitte versuche es Sp�ter erneut." );
        klient = klient->release();
    }
    cs.unlock();
    return 0;
}

Array< int > *ShopKlient::suchSpiele( const char *suche ) // sucht nach Spielen
{
    char l�n = (char)textLength( suche );
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\5", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( &l�n, 1 );
        if( l�n )
            klient->sendeEncrypted( suche, l�n );
        klient->getNachrichtEncrypted( &ret, 1 );
        if( ret == 1 )
        {
            int anz = 0;
            klient->getNachrichtEncrypted( (char*)&anz, 4 );
            Array< int > *ret = new Array< int >();
            for( int i = 0; i < anz; i++ )
            {
                int w = 0;
                klient->getNachrichtEncrypted( (char*)&w, 4 );
                ret->add( w );
            }
            cs.unlock();
            return ret;
        }
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &l�n, 1 );
        char *err = new char[ l�n + 1 ];
        err[ l�n ] = 0;
        if( l�n )
            klient->getNachrichtEncrypted( err, l�n );
        fehler->setText( err );
        delete[] err;
    }
    cs.unlock();
    return 0;
}

bool ShopKlient::ladeSpielTitel( int id ) // l�d Titelbild des Spieles herunter
{
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\6", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&id, 4 );
        klient->getNachrichtEncrypted( &ret, 1 );
        if( ret == 1 )
        {
            Text *pf = new Text( "data/tmp/shop/kaufen/spiele/" );
            pf->append( id );
            pf->append( "/titelbg.ltdb" );
            Datei *dat = new Datei();
            dat->setDatei( pf );
            dat->erstellen();
            dat->open( Datei::Style::schreiben );
            __int64 gr = 0;
            klient->getNachrichtEncrypted( (char*)&gr, 8 );
            char bytes[ 2048 ];
            while( gr > 0 )
            {
                int l�n = gr > 2048 ? 2048 : (int)gr;
                klient->getNachricht( bytes, l�n );
                dat->schreibe( bytes, l�n );
                gr -= l�n;
            }
            dat->close();
            dat->release();
        }
        if( ret == 2 )
        { // Verweis auf anderen ShopServer
            int port = 0;
            char l�n = 0;
            klient->getNachrichtEncrypted( (char*)&port, 4 );
            klient->getNachrichtEncrypted( &l�n, 1 );
            char *ip = new char[ l�n + 1 ];
            klient->getNachrichtEncrypted( ip, l�n );
            ip[ l�n ] = 0;
            klient->trenne();
            if( !verbinde( port, ip ) )
            {
                delete[] ip;
                trenne();
                cs.unlock();
                return 0;
            }
            delete[] ip;
            cs.unlock();
            return ladeSpielTitel( id );
        }
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &ret, 1 );
        char *err = new char[ ret + 1 ];
        err[ ret ] = 0;
        if( ret )
            klient->getNachrichtEncrypted( err, ret );
        fehler->setText( err );
        delete[] err;
        cs.unlock();
        return 0;
    }
    cs.unlock();
    return 1;
}

bool ShopKlient::ladeSpielSeite( int id ) // l�d Seite des Spieles herunter
{
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\7", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&id, 4 );
        klient->getNachrichtEncrypted( &ret, 1 );
        if( ret == 1 )
        {
            Text *pf = new Text( "data/tmp/shop/kaufen/spiele/" );
            pf->append( id );
            pf->append( "/" );
            int anz = 0;
            klient->getNachrichtEncrypted( (char*)&anz, 4 );
            for( int i = 0; i < anz; i++ )
            {
                char l�n = 0;
                klient->getNachrichtEncrypted( &l�n, 1 );
                char *name = new char[ l�n + 1 ];
                name[ l�n ] = 0;
                klient->getNachrichtEncrypted( name, l�n );
                Text *pfad = new Text( pf->getText() );
                pfad->append( name );
                delete[] name;
                Datei *d = new Datei();
                d->setDatei( pfad );
                d->erstellen();
                d->open( Datei::Style::schreiben );
                __int64 gr = 0;
                klient->getNachrichtEncrypted( (char*)&gr, 8 );
                char bytes[ 2048 ];
                while( gr > 0 )
                {
                    int l�n = gr > 2048 ? 2048 : (int)gr;
                    klient->getNachricht( bytes, l�n );
                    d->schreibe( bytes, l�n );
                    gr -= l�n;
                }
                d->close();
                d->release();
            }
            pf->release();
        }
        if( ret == 2 )
        { // Verweis auf anderen ShopServer
            int port = 0;
            char l�n = 0;
            klient->getNachrichtEncrypted( (char*)&port, 4 );
            klient->getNachrichtEncrypted( &l�n, 1 );
            char *ip = new char[ l�n + 1 ];
            klient->getNachrichtEncrypted( ip, l�n );
            ip[ l�n ] = 0;
            klient->trenne();
            if( !verbinde( port, ip ) )
            {
                delete[] ip;
                trenne();
                cs.unlock();
                return 0;
            }
            delete[] ip;
            cs.unlock();
            return ladeSpielSeite( id );
        }
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &ret, 1 );
        char *err = new char[ ret + 1 ];
        err[ ret ] = 0;
        if( ret )
            klient->getNachrichtEncrypted( err, ret );
        fehler->setText( err );
        delete[] err;
        cs.unlock();
        return 0;
    }
    cs.unlock();
    return 1;
}

int ShopKlient::getSpielBesitzStatus( int id ) // 0 = nicht im Besitz, 1 = Testversion, 2 = gekauft
{
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\x8", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&id, 4 );
        int ret = 0;
        klient->getNachrichtEncrypted( (char*)&ret, 4 );
        cs.unlock();
        return ret;
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &ret, 1 );
        char *err = new char[ ret + 1 ];
        err[ ret ] = 0;
        if( ret )
            klient->getNachrichtEncrypted( err, ret );
        fehler->setText( err );
        delete[] err;
    }
    cs.unlock();
    return 0;
}

int ShopKlient::getSpielTestversion( int id ) // gibt die Anzahl der verbleibenden Spiele zur�ck
{
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\x9", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&id, 4 );
        int ret = 0;
        klient->getNachrichtEncrypted( (char*)&ret, 4 );
        cs.unlock();
        return ret;
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &ret, 1 );
        char *err = new char[ ret + 1 ];
        err[ ret ] = 0;
        if( ret )
            klient->getNachrichtEncrypted( err, ret );
        fehler->setText( err );
        delete[] err;
    }
    cs.unlock();
    return 0;
}

int ShopKlient::istSpielErwerbbar( int id ) // pr�ft, ob das Spiel erworben werden kann
{
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\xA", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&id, 4 );
        int ret = 0;
        klient->getNachrichtEncrypted( (char*)&ret, 4 );
        cs.unlock();
        return ret;
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &ret, 1 );
        char *err = new char[ ret + 1 ];
        err[ ret ] = 0;
        if( ret )
            klient->getNachrichtEncrypted( err, ret );
        fehler->setText( err );
        delete[] err;
    }
    cs.unlock();
    return 0;
}

int ShopKlient::getSpielPreis( int id, bool testVersion ) // gibt den Preis eines Spieles zur�ck
{
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\xB", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&id, 4 );
        klient->sendeEncrypted( (char*)&testVersion, 1 );
        int ret = 0;
        klient->getNachrichtEncrypted( (char*)&ret, 4 );
        cs.unlock();
        return ret;
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &ret, 1 );
        char *err = new char[ ret + 1 ];
        err[ ret ] = 0;
        if( ret )
            klient->getNachrichtEncrypted( err, ret );
        fehler->setText( err );
        delete[] err;
    }
    cs.unlock();
    return 0;
}

bool ShopKlient::spielErwerben( int spielId, bool testVersion ) // Spiel kaufen
{
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\xC", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&spielId, 4 );
        klient->sendeEncrypted( (char*)&testVersion, 1 );
        klient->getNachrichtEncrypted( &ret, 1 );
        if( ret == 1 )
        {
            cs.unlock();
            return 1;
        }
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &ret, 1 );
        char *err = new char[ ret + 1 ];
        err[ ret ] = 0;
        if( ret )
            klient->getNachrichtEncrypted( err, ret );
        fehler->setText( err );
        delete[] err;
    }
    cs.unlock();
    return 0;
}

Array< int > *ShopKlient::suchKarten( const char *suche, int spielId ) // sucht nach Karten
{
    char l�n = (char)textLength( suche );
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\xD", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&spielId, 4 );
        klient->sendeEncrypted( &l�n, 1 );
        if( l�n )
            klient->sendeEncrypted( suche, l�n );
        klient->getNachrichtEncrypted( &ret, 1 );
        if( ret == 1 )
        {
            int anz = 0;
            klient->getNachrichtEncrypted( (char*)&anz, 4 );
            Array< int > *ret = new Array< int >();
            for( int i = 0; i < anz; i++ )
            {
                int w = 0;
                klient->getNachrichtEncrypted( (char*)&w, 4 );
                ret->add( w );
            }
            cs.unlock();
            return ret;
        }
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &l�n, 1 );
        char *err = new char[ l�n + 1 ];
        err[ l�n ] = 0;
        if( l�n )
            klient->getNachrichtEncrypted( err, l�n );
        fehler->setText( err );
        delete[] err;
    }
    cs.unlock();
    return 0;
}

bool ShopKlient::ladeKarteTitel( int id ) // l�d Titelbild der Karte herunter
{
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\xE", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&id, 4 );
        klient->getNachrichtEncrypted( &ret, 1 );
        if( ret == 1 )
        {
            Text *pf = new Text( "data/tmp/shop/kaufen/karten/" );
            pf->append( id );
            pf->append( "/titelbg.ltdb" );
            Datei *dat = new Datei();
            dat->setDatei( pf );
            dat->erstellen();
            dat->open( Datei::Style::schreiben );
            __int64 gr = 0;
            klient->getNachrichtEncrypted( (char*)&gr, 8 );
            char bytes[ 2048 ];
            while( gr > 0 )
            {
                int l�n = gr > 2048 ? 2048 : (int)gr;
                klient->getNachricht( bytes, l�n );
                dat->schreibe( bytes, l�n );
                gr -= l�n;
            }
            dat->close();
            dat->release();
        }
        if( ret == 2 )
        { // Verweis auf anderen ShopServer
            int port = 0;
            char l�n = 0;
            klient->getNachrichtEncrypted( (char*)&port, 4 );
            klient->getNachrichtEncrypted( &l�n, 1 );
            char *ip = new char[ l�n + 1 ];
            klient->getNachrichtEncrypted( ip, l�n );
            ip[ l�n ] = 0;
            klient->trenne();
            if( !verbinde( port, ip ) )
            {
                delete[] ip;
                trenne();
                cs.unlock();
                return 0;
            }
            delete[] ip;
            cs.unlock();
            return ladeKarteTitel( id );
        }
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &ret, 1 );
        char *err = new char[ ret + 1 ];
        err[ ret ] = 0;
        if( ret )
            klient->getNachrichtEncrypted( err, ret );
        fehler->setText( err );
        delete[] err;
        cs.unlock();
        return 0;
    }
    cs.unlock();
    return 1;
}

bool ShopKlient::ladeKarteSeite( int id ) // l�d Seite der Karte herunter
{
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\xF", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&id, 4 );
        klient->getNachrichtEncrypted( &ret, 1 );
        if( ret == 1 )
        {
            Text *pf = new Text( "data/tmp/shop/kaufen/karten/" );
            pf->append( id );
            pf->append( "/" );
            int anz = 0;
            klient->getNachrichtEncrypted( (char*)&anz, 4 );
            for( int i = 0; i < anz; i++ )
            {
                char l�n = 0;
                klient->getNachrichtEncrypted( &l�n, 1 );
                char *name = new char[ l�n + 1 ];
                name[ l�n ] = 0;
                klient->getNachrichtEncrypted( name, l�n );
                Text *pfad = new Text( pf->getText() );
                pfad->append( name );
                delete[] name;
                Datei *d = new Datei();
                d->setDatei( pfad );
                d->erstellen();
                d->open( Datei::Style::schreiben );
                __int64 gr = 0;
                klient->getNachrichtEncrypted( (char*)&gr, 8 );
                char bytes[ 2048 ];
                while( gr > 0 )
                {
                    int l�n = gr > 2048 ? 2048 : (int)gr;
                    klient->getNachricht( bytes, l�n );
                    d->schreibe( bytes, l�n );
                    gr -= l�n;
                }
                d->close();
                d->release();
            }
            pf->release();
        }
        if( ret == 2 )
        { // Verweis auf anderen ShopServer
            int port = 0;
            char l�n = 0;
            klient->getNachrichtEncrypted( (char*)&port, 4 );
            klient->getNachrichtEncrypted( &l�n, 1 );
            char *ip = new char[ l�n + 1 ];
            klient->getNachrichtEncrypted( ip, l�n );
            ip[ l�n ] = 0;
            klient->trenne();
            if( !verbinde( port, ip ) )
            {
                delete[] ip;
                trenne();
                cs.unlock();
                return 0;
            }
            delete[] ip;
            cs.unlock();
            return ladeKarteSeite( id );
        }
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &ret, 1 );
        char *err = new char[ ret + 1 ];
        err[ ret ] = 0;
        if( ret )
            klient->getNachrichtEncrypted( err, ret );
        fehler->setText( err );
        delete[] err;
        cs.unlock();
        return 0;
    }
    cs.unlock();
    return 1;
}

int ShopKlient::getKarteBesitzStatus( int id ) // 0 = nicht im Besitz, 1 = Testversion, 2 = gekauft
{
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\x10", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&id, 4 );
        int ret = 0;
        klient->getNachrichtEncrypted( (char*)&ret, 4 );
        cs.unlock();
        return ret;
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &ret, 1 );
        char *err = new char[ ret + 1 ];
        err[ ret ] = 0;
        if( ret )
            klient->getNachrichtEncrypted( err, ret );
        fehler->setText( err );
        delete[] err;
    }
    cs.unlock();
    return 0;
}

int ShopKlient::getKarteTestversion( int id ) // gibt die Anzahl der verbleibenden Spiele zur�ck
{
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\x11", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&id, 4 );
        int ret = 0;
        klient->getNachrichtEncrypted( (char*)&ret, 4 );
        cs.unlock();
        return ret;
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &ret, 1 );
        char *err = new char[ ret + 1 ];
        err[ ret ] = 0;
        if( ret )
            klient->getNachrichtEncrypted( err, ret );
        fehler->setText( err );
        delete[] err;
    }
    cs.unlock();
    return 0;
}

int ShopKlient::istKarteErwerbbar( int id ) // pr�ft, ob die Karte erworben werden kann
{
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\x12", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&id, 4 );
        int ret = 0;
        klient->getNachrichtEncrypted( (char*)&ret, 4 );
        cs.unlock();
        return ret;
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &ret, 1 );
        char *err = new char[ ret + 1 ];
        err[ ret ] = 0;
        if( ret )
            klient->getNachrichtEncrypted( err, ret );
        fehler->setText( err );
        delete[] err;
    }
    cs.unlock();
    return 0;
}

int ShopKlient::getKartePreis( int id, bool testVersion ) // gibt den Preis einer Karte zur�ck
{
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\x13", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&id, 4 );
        klient->sendeEncrypted( (char*)&testVersion, 1 );
        int ret = 0;
        klient->getNachrichtEncrypted( (char*)&ret, 4 );
        cs.unlock();
        return ret;
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &ret, 1 );
        char *err = new char[ ret + 1 ];
        err[ ret ] = 0;
        if( ret )
            klient->getNachrichtEncrypted( err, ret );
        fehler->setText( err );
        delete[] err;
    }
    cs.unlock();
    return 0;
}

bool ShopKlient::karteErwerben( int karteId, bool testVersion ) // Karte kaufen
{
    char ret = 0;
    cs.lock();
    if( !verbunden )
        verbinde();
    if( !verbunden )
    {
        cs.unlock();
        return 0;
    }
    klient->sendeEncrypted( "\x14", 1 );
    klient->getNachrichtEncrypted( &ret, 1 );
    if( ret == 1 )
    {
        klient->sendeEncrypted( (char*)&karteId, 4 );
        klient->sendeEncrypted( (char*)&testVersion, 1 );
        klient->getNachrichtEncrypted( &ret, 1 );
        if( ret == 1 )
        {
            cs.unlock();
            return 1;
        }
    }
    if( ret == 3 )
    {
        klient->getNachrichtEncrypted( &ret, 1 );
        char *err = new char[ ret + 1 ];
        err[ ret ] = 0;
        if( ret )
            klient->getNachrichtEncrypted( err, ret );
        fehler->setText( err );
        delete[] err;
    }
    cs.unlock();
    return 0;
}

bool ShopKlient::keepAlive() // Erh�lt die Verbindung aufrecht
{
    if( !verbunden )
        return 0;
    char res = 0;
    if( !cs.tryLock() )
        return 1;
    klient->sendeEncrypted( "\x15", 1 );
    klient->getNachrichtEncrypted( &res, 1 );
    cs.unlock();
    if( res != 1 )
        trenne();
    return res == 1;
}

bool ShopKlient::trenne() // trennt sich von dem Shop Server
{
    if( !verbunden )
        return 1;
    cs.lock();
    klient->sendeEncrypted( "\3", 1 );
    char serverReturn = 0;
    klient->getNachrichtEncrypted( &serverReturn, 1 );
    klient->trenne();
    verbunden = 0;
    cs.unlock();
    return 1;
}

// constant
bool ShopKlient::istVerbunden() const // pr�ft, ob mit Shop Server verbunden
{
    return verbunden;
}

char *ShopKlient::getLetzterFehler() const // gibt den Letzten Fehlertext zu�ck
{
    return fehler->getText();
}

// Reference Counting
ShopKlient *ShopKlient::getThis()
{
    ref++;
    return this;
}

ShopKlient *ShopKlient::release()
{
    ref--;
    if( !ref )
        delete this;
    return 0;
}