#include "DateienEditor.h"
#include <Datei.h>
#include <DateiSystem.h>
#include <Bild.h>
#include <M2Datei.h>
#include <iostream>
#include "GSLDateiV.h"
#include <Model2D.h>
#include <unistd.h>
#define Sleep( x )               usleep( (x) * 1000 )
#include <dlfcn.h>
#define LoadLibrary( x )         dlopen( (x), RTLD_LAZY )
#define GetProcAddress           dlsym
#define FreeLibrary              dlclose
#define HMODULE                  void*

typedef GSL::GSLDateiV *( *GetGSLDatei )( );

class DownloadSound : public GSL::GSLSoundV
{
private:
    bool istM;
    int sample;
    __int64 len;
    SKlient *k;
    int ref;
    bool ok;

public:
    // Konstruktor
    DownloadSound( SKlient *zK )
    {
        k = zK;
        ok = 0;
        ref = 1;
    }
    // nicht constant
    // GSL
    void playSound() override
    {}
    void setPause( bool p ) override
    {}
    void stopSound() override
    {}
    void warteAufSound( int zeit ) override
    {}
    // Lautstärke: 0 - 0xFFFF
    void setVolume( unsigned int links, unsigned int rechts ) override
    {}
    // zum Speichern
    void open() override
    {
        ok = 1;
        k->sendeEncrypted( "\1", 1 );
        char m = 0;
        k->getNachrichtEncrypted( &m, 1 );
        istM = ( m == 1 );
        sample = 0;
        k->getNachrichtEncrypted( (char*)&sample, 4 );
        len = 0;
        k->getNachrichtEncrypted( (char*)&len, 8 );
    }
    int getDaten( char *buffer, int len ) override
    {
        int l = len < this->len ? len : ( int )this->len;
        if( !l )
            return -1;
        k->getNachricht( buffer, l );
        this->len -= l;
        return l;
    }
    void close() override
    {}
    bool istMono() const override
    {
        return istM;
    }
    int getSampleRate() const override
    {
        return sample;
    }
    __int64 getDatLength() const override
    {
        return len;
    }
    bool istOk() const
    {
        return ok;
    }
    // Reference Counting
    GSL::GSLSoundV *getThis() override
    {
        ref++;
        return this;
    }
    GSL::GSLSoundV *release() override
    {
        ref--;
        if( !ref )
            delete this;
        return 0;
    }
};

// Inhalt der DateienEditor Klasse aus DateienEditor.h
// Konstruktor
DateienEditor::DateienEditor( char *pf, InitDatei *zIni )
{
    this->ini = zIni->getThis();
    pfad = pf;
    pfad += "/live/map/client/map/files";
    workPfad = "";
    fehler = "";
    ref = 1;
}

// Destruktor
DateienEditor::~DateienEditor()
{
    ini->release();
}

// nicht constant
bool DateienEditor::prozessMessage( SKlient *zKlient )
{
    char message = 0;
    zKlient->getNachrichtEncrypted( &message, 1 );
    switch( message )
    {
    case 0x1: // Neue Datei erstellen
    {
        zKlient->sendeEncrypted( "\1", 1 );
        char typ = 0;
        zKlient->getNachrichtEncrypted( &typ, 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        name[ (int)len ] = 0;
        if( !len )
        {
            delete[] name;
            fehler = "Du musst einen Dateinamen angeben.";
            return 0;
        }
        Text n = name;
        delete[] name;
        if( n.hat( "/" ) || n.hat( "." ) )
        {
            fehler = "Du musst einen gültigen Dateinamen angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += n;
        if( typ == 0 )
        {
            p += "/tmp";
            if( !DateiPfadErstellen( p ) )
            {
                fehler = "Fehler beim erstellen der Datei.";
                return 0;
            }
            DateiRemove( p );
            p.remove( p.getLength() - 4, p.getLength() );
            p.ersetzen( p.positionVon( "map/client" ), p.positionVon( "map/client" ) + textLength( "map/client" ), "map/server" );
            if( !DateiPfadErstellen( p ) )
            {
                fehler = "Fehler beim erstellen der Datei.";
                return 0;
            }
            DateiRemove( p );
            p.remove( p.getLength() - 4, p.getLength() );
            zKlient->sendeEncrypted( "\1", 1 );
            return 1;
        }
        if( typ == 1 )
        {
            p += ".ltdb";
            if( !DateiPfadErstellen( p ) )
            {
                fehler = "Fehler beim erstellen der Datei.";
                return 0;
            }
            zKlient->sendeEncrypted( "\1", 1 );
            return 1;
        }
        if( typ == 2 )
        {
            p += ".m2";
            if( !DateiPfadErstellen( p ) )
            {
                fehler = "Fehler beim erstellen der Datei.";
                return 0;
            }
            p.ersetzen( p.positionVon( "map/client" ), p.positionVon( "map/client" ) + textLength( "map/client" ), "map/server" );
            if( !DateiPfadErstellen( p ) )
            {
                fehler = "Fehler beim erstellen der Datei.";
                return 0;
            }
            zKlient->sendeEncrypted( "\1", 1 );
            return 1;
        }
        if( typ == 3 )
        {
            p += ".gsl";
            if( !DateiPfadErstellen( p ) )
            {
                fehler = "Fehler beim erstellen der Datei.";
                return 0;
            }
            zKlient->sendeEncrypted( "\1", 1 );
            return 1;
        }
        fehler = "Ungültiger Dateityp.";
        return 0;
    }
    case 0x2: // Ordner open
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( Text( ".." ).istGleich( name ) )
        {
            if( workPfad.getLength() )
            {
                int anz = workPfad.anzahlVon( "/" );
                if( anz )
                    workPfad.remove( workPfad.positionVon( "/", anz - 1 ), workPfad.getLength() );
                else
                    workPfad = "";
            }
            delete[] name;
            zKlient->sendeEncrypted( "\1", 1 );
            return 1;
        }
        else
        {
            Text p = pfad.getText();
            p += workPfad.getText();
            p += "/";
            p += name;
            Datei d;
            d.setDatei( p );
            if( !d.existiert() )
            {
                delete[] name;
                fehler = "Die Datei konnte nicht gefunden werden.";
                return 0;
            }
            else
            {
                if( d.istOrdner() )
                {
                    workPfad += "/";
                    workPfad += name;
                }
                delete[] name;
                zKlient->sendeEncrypted( "\1", 1 );
                return 1;
            }
        }
    }
    case 0x3: // Bild laden
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *dName = new char[ len + 1 ];
        dName[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( dName, len );
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *bName = new char[ len + 1 ];
        bName[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( bName, len );
        if( !textLength( dName ) || !textLength( bName ) )
        {
            delete[] dName;
            delete[] bName;
            fehler = "Du musst ein Bild und eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += dName;
        delete[] dName;
        if( !DateiExistiert( p ) )
        {
            delete[] bName;
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        LTDBDatei dat;
        dat.setDatei( p.getThis() );
        dat.leseDaten( 0 );
        Bild *b = dat.laden( 0, new Text( bName ) );
        delete[] bName;
        if( !b )
        {
            fehler = "Das Bild wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        int br = b->getBreite();
        int hi = b->getHeight();
        zKlient->sendeEncrypted( (char*)&br, 4 );
        zKlient->sendeEncrypted( (char*)&hi, 4 );
        char *buffer = (char*)b->getBuffer();
        __int64 gr = br * hi * 4;
        for( int i = 0, l = gr > 2048 ? 2048 : (int)gr; gr > 0; i += l, gr -= l, l = gr > 2048 ? 2048 : (int)gr )
            zKlient->sende( &( buffer[ i ] ), l );
        b->release();
        return 1;
    }
    case 0x4: // Datei remove
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( Text( name ).istGleich( ".." ) )
        {
            fehler = "Du kannst diese Datei nicht remove.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        if( !Text( "." ).istGleich( name ) )
        {
            p += "/";
            p += name;
        }
        else
        {
            int anz = workPfad.anzahlVon( "/" );
            if( anz )
                workPfad.remove( workPfad.positionVon( "/", anz - 1 ), workPfad.getLength() );
            else
                workPfad = "";
        }
        delete[] name;
        if( !DateiExistiert( p ) )
        {
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        if( !DateiRemove( p ) )
        {
            fehler = "Fehler beim remove der Datei.";
            return 0;
        }
        p.ersetzen( p.positionVon( "map/client" ), p.positionVon( "map/client" ) + textLength( "map/client" ), "map/server" );
        if( !DateiRemove( p ) )
        {
            fehler = "Fehler beim remove der Datei.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        return 1;
    }
    case 0x5: // Bild remove
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *dName = new char[ len + 1 ];
        dName[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( dName, len );
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *bName = new char[ len + 1 ];
        bName[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( bName, len );
        if( !textLength( dName ) || !textLength( bName ) )
        {
            delete[] dName;
            delete[] bName;
            fehler = "Du musst ein Bild und eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += dName;
        delete[] dName;
        if( !DateiExistiert( p ) )
        {
            delete[] bName;
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        LTDBDatei dat;
        dat.setDatei( p.getThis() );
        dat.leseDaten( 0 );
        dat.remove( 0, new Text( bName ) );
        delete[] bName;
        zKlient->sendeEncrypted( "\1", 1 );
        return 1;
    }
    case 0x6: // Bild erstellen
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *dName = new char[ len + 1 ];
        dName[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( dName, len );
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *bName = new char[ len + 1 ];
        bName[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( bName, len );
        if( !textLength( dName ) || !textLength( bName ) )
        {
            delete[] dName;
            delete[] bName;
            fehler = "Du musst ein Bild und eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += dName;
        delete[] dName;
        if( !DateiExistiert( p ) )
        {
            delete[] bName;
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        int br = 0;
        int hi = 0;
        zKlient->getNachrichtEncrypted( (char*)&br, 4 );
        zKlient->getNachrichtEncrypted( (char*)&hi, 4 );
        __int64 gr = br * hi * 4;
        Bild *b = new Bild();
        b->neuBild( br, hi, 0 );
        char *buffer = (char*)b->getBuffer();
        for( int i = 0, l = gr > 2048 ? 2048 : (int)gr; gr > 0; i += l, gr -= l, l = gr > 2048 ? 2048 : (int)gr )
            zKlient->getNachricht( &( buffer[ i ] ), l );
        LTDBDatei dat;
        dat.setDatei( p.getThis() );
        dat.leseDaten( 0 );
        dat.remove( 0, new Text( bName ) );
        if( dat.speichern( 0, b, new Text( bName ) ) < 0 )
        {
            delete[] bName;
            fehler = "Fehler beim speichern des Bildes.";
            return 0;
        }
        delete[] bName;
        zKlient->sendeEncrypted( "\1", 1 );
        return 1;
    }
    case 0x7: // Datei Liste herunterladen
    {
        Datei d;
        d.setDatei( Text( pfad.getText() ) += workPfad.getText() );
        RCArray< Text > *list = d.getDateiListe();
        zKlient->sendeEncrypted( "\1", 1 );
        int anz = list ? list->getEintragAnzahl() : 0;
        if( workPfad.getLength() )
            anz++;
        zKlient->sendeEncrypted( (char*)&anz, 4 );
        if( workPfad.getLength() )
        {
            zKlient->sendeEncrypted( "\2", 1 );
            zKlient->sendeEncrypted( "..", 2 );
            anz--;
        }
        for( int i = 0; i < anz; i++ )
        {
            char len = (char)list->z( i )->getLength();
            zKlient->sendeEncrypted( &len, 1 );
            zKlient->sendeEncrypted( list->z( i )->getText(), len );
        }
        if( list )
            list->release();
        return 1;
    }
    case 0x8: // Bild Liste herunterladen
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( !textLength( name ) )
        {
            delete[] name;
            fehler = "Du musst eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += name;
        delete[] name;
        if( !DateiExistiert( p ) )
        {
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        LTDBDatei dat;
        dat.setDatei( p.getThis() );
        dat.leseDaten( 0 );
        int anz = dat.getBildAnzahl();
        zKlient->sendeEncrypted( (char*)&anz, 4 );
        for( int i = 0; i < anz; i++ )
        {
            char len = (char)dat.zBildListe()->z( i )->getLength();
            zKlient->sendeEncrypted( &len, 1 );
            zKlient->sendeEncrypted( dat.zBildListe()->z( i )->getText(), len );
        }
        return 1;
    }
    case 0x9: // Modell Liste herunterladen
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( !textLength( name ) )
        {
            delete[] name;
            fehler = "Du musst eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += name;
        delete[] name;
        if( !DateiExistiert( p ) )
        {
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        M2Datei dat;
        dat.setPfad( p );
        dat.leseDaten();
        int anz = dat.getModelAnzahl();
        zKlient->sendeEncrypted( (char*)&anz, 4 );
        for( int i = 0; i < anz; i++ )
        {
            char len = (char)dat.zModelName( i )->getLength();
            zKlient->sendeEncrypted( &len, 1 );
            zKlient->sendeEncrypted( dat.zModelName( i )->getText(), len );
        }
        return 1;
    }
    case 0xA: // Sound Liste herunterlaen
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( !textLength( name ) )
        {
            delete[] name;
            fehler = "Du musst eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += name;
        delete[] name;
        if( !DateiExistiert( p ) )
        {
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        HMODULE gslDLL = LoadLibrary( ini->zWert( "gslPfad" )->getText() );
        if( !gslDLL )
        {
            fehler = "Interner Server Fehler.";
            std::cout << "EdS: Fehler beim laden von '" << ini->zWert( "gslPfad" )->getText() << "'.\n";
            return 0;
        }
        GetGSLDatei getGSLDatei = (GetGSLDatei)GetProcAddress( gslDLL, "getGSLDatei" );
        if( !getGSLDatei )
        {
            fehler = "Interner Server Fehler.";
            std::cout << "EdS: Der Einstiegspunkt 'getGSLDatei' wurde in der Datei '" << ini->zWert( "gslPfad" )->getText() << "' nicht gefunden.\n";
            return 0;
        }
        GSL::GSLDateiV *gslDatei = getGSLDatei();
        zKlient->sendeEncrypted( "\1", 1 );
        gslDatei->setDatei( p );
        gslDatei->leseDaten();
        int anz = gslDatei->getSoundAnzahl();
        zKlient->sendeEncrypted( (char*)&anz, 4 );
        for( int i = 0; i < anz; i++ )
        {
            Text *n = gslDatei->getSoundName( i );
            char len = (char)n->getLength();
            zKlient->sendeEncrypted( &len, 1 );
            zKlient->sendeEncrypted( n->getText(), len );
            n->release();
        }
        gslDatei->release();
        FreeLibrary( gslDLL );
        return 1;
    }
    case 0xB: // Modell remove
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( !textLength( name ) )
        {
            delete[] name;
            fehler = "Du musst eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += name;
        delete[] name;
        if( !DateiExistiert( p ) )
        {
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        M2Datei dat;
        dat.setPfad( p );
        dat.leseDaten();
        if( !textLength( name ) || !dat.removeModel( name ) )
        {
            delete[] name;
            fehler = "Das Modell wurde nicht gefunden.";
            return 0;
        }
        p.ersetzen( p.positionVon( "map/client" ), p.positionVon( "map/client" ) + textLength( "map/client" ), "map/server" );
        dat.setPfad( p );
        dat.leseDaten();
        if( !textLength( name ) || !dat.removeModel( name ) )
        {
            delete[] name;
            fehler = "Das Modell wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        delete[] name;
        return 1;
    }
    case 0xC: // Sound remove
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( !textLength( name ) )
        {
            delete[] name;
            fehler = "Du musst eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += name;
        delete[] name;
        if( !DateiExistiert( p ) )
        {
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        HMODULE gslDLL = LoadLibrary( ini->zWert( "gslPfad" )->getText() );
        if( !gslDLL )
        {
            fehler = "Interner Server Fehler.";
            std::cout << "EdS: Fehler beim laden von '" << ini->zWert( "gslPfad" )->getText() << "'.\n";
            return 0;
        }
        GetGSLDatei getGSLDatei = (GetGSLDatei)GetProcAddress( gslDLL, "getGSLDatei" );
        if( !getGSLDatei )
        {
            fehler = "Interner Server Fehler.";
            std::cout << "EdS: Der Einstiegspunkt 'getGSLDatei' wurde in der Datei '" << ini->zWert( "gslPfad" )->getText() << "' nicht gefunden.\n";
            return 0;
        }
        GSL::GSLDateiV *gslDatei = getGSLDatei();
        gslDatei->setDatei( p );
        gslDatei->leseDaten();
        if( !textLength( name ) || !gslDatei->removeSound( name ) )
        {
            fehler = "Das Modell wurde nicht gefunden.";
            delete[] name;
            gslDatei->release();
            FreeLibrary( gslDLL );
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        delete[] name;
        gslDatei->release();
        FreeLibrary( gslDLL );
        return 1;
    }
    case 0xD: // Modell laden
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( !textLength( name ) )
        {
            delete[] name;
            fehler = "Du musst eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += name;
        delete[] name;
        if( !DateiExistiert( p ) )
        {
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        M2Datei dat;
        dat.setPfad( p );
        dat.leseDaten();
        Model2DData *mdl;
        if( !textLength( name ) || !( mdl = dat.ladeModel( name ) ) )
        {
            delete[] name;
            fehler = "Das Modell wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        int anz = mdl->polygons ? mdl->polygons->getEintragAnzahl() : 0;
        zKlient->sendeEncrypted( (char*)&anz, 4 );
        for( int i = 0; i < anz; i++ )
        {
            Polygon2D pol = mdl->polygons->get( i );
            zKlient->sendeEncrypted( (char*)&pol.transparent, 1 );
            char nLen = (char)pol.name->getLength();
            zKlient->sendeEncrypted( &nLen, 1 );
            if( nLen )
                zKlient->sendeEncrypted( pol.name->getText(), nLen );
            int anz2 = pol.vertex ? pol.vertex->getEintragAnzahl() : 0;
            zKlient->sendeEncrypted( (char*)&anz2, 4 );
            for( int j = 0; j < anz2; j++ )
            {
                float var = pol.vertex->get( j ).x;
                zKlient->sendeEncrypted( (char*)&var, 4 );
                var = pol.vertex->get( j ).y;
                zKlient->sendeEncrypted( (char*)&var, 4 );
                var = ( pol.tKordinaten && pol.tKordinaten->hat( j ) ) ? pol.tKordinaten->get( j ).x : 0;
                zKlient->sendeEncrypted( (char*)&var, 4 );
                var = ( pol.tKordinaten && pol.tKordinaten->hat( j ) ) ? pol.tKordinaten->get( j ).y : 0;
                zKlient->sendeEncrypted( (char*)&var, 4 );
            }
        }
        mdl->release();
        delete[] name;
        return 1;
    }
    case 0xE: // Sound laden
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( !textLength( name ) )
        {
            delete[] name;
            fehler = "Du musst eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += name;
        delete[] name;
        if( !DateiExistiert( p ) )
        {
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        HMODULE gslDLL = LoadLibrary( ini->zWert( "gslPfad" )->getText() );
        if( !gslDLL )
        {
            fehler = "Interner Server Fehler.";
            std::cout << "EdS: Fehler beim laden von '" << ini->zWert( "gslPfad" )->getText() << "'.\n";
            return 0;
        }
        GetGSLDatei getGSLDatei = (GetGSLDatei)GetProcAddress( gslDLL, "getGSLDatei" );
        if( !getGSLDatei )
        {
            fehler = "Interner Server Fehler.";
            std::cout << "EdS: Der Einstiegspunkt 'getGSLDatei' wurde in der Datei '" << ini->zWert( "gslPfad" )->getText() << "' nicht gefunden.\n";
            return 0;
        }
        GSL::GSLDateiV *gslDatei = getGSLDatei();
        gslDatei->setDatei( p );
        gslDatei->leseDaten();
        GSL::GSLSoundV *sound;
        if( !textLength( name ) || !( sound = gslDatei->getSound( name ) ) )
        {
            delete[] name;
            gslDatei->release();
            FreeLibrary( gslDLL );
            fehler = "Das Modell wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        char channels = sound->istMono() ? 1 : 2;
        zKlient->sendeEncrypted( &channels, 1 );
        int sample = sound->getSampleRate();
        zKlient->sendeEncrypted( (char*)&sample, 4 );
        __int64 length = sound->getDatLength();
        zKlient->sendeEncrypted( (char*)&length, 8 );
        sound->open();
        char *buffer = new char[ 2048 ];
        while( length > 0 )
        {
            int l = length > 2048 ? 2048 : (int)length;
            sound->getDaten( buffer, l );
            zKlient->sende( buffer, l );
			length -= l;
        }
        delete[] buffer;
        sound->close();
        sound->release();
        gslDatei->release();
        FreeLibrary( gslDLL );
        delete[] name;
        return 1;
    }
    case 0xF: // Modell erstellen
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( !textLength( name ) )
        {
            delete[] name;
            fehler = "Du musst eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += name;
        delete[] name;
        if( !DateiExistiert( p ) )
        {
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        M2Datei dat;
        dat.setPfad( p );
        dat.leseDaten();
        dat.removeModel( name );
        if( !textLength( name ) )
        {
            delete[] name;
            fehler = "Du musst einen Namen eingeben.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        Model2DData *mdl = new Model2DData();
        Array< Polygon2D > *data = new Array< Polygon2D >();
        int anz = 0;
        zKlient->getNachrichtEncrypted( (char*)&anz, 4 );
        for( int i = 0; i < anz; i++ )
        {
            Polygon2D pol;
            pol.schwerpunkt = 0;
            pol.vertex = new Array< Vertex >();
            pol.tKordinaten = new Array< Vertex >();
            zKlient->getNachrichtEncrypted( (char*)&pol.transparent, 1 );
            unsigned char nLen = 0;
            zKlient->getNachrichtEncrypted( (char*)&nLen, 1 );
            char *txt = new char[ nLen + 1 ];
            if( nLen )
                zKlient->getNachrichtEncrypted( txt, nLen );
            txt[ (int)nLen ] = 0;
            pol.name = new Text( txt );
            delete[] txt;
            int anz2 = 0;
            zKlient->getNachrichtEncrypted( (char*)&anz2, 4 );
            for( int j = 0; j < anz2; j++ )
            {
                Vertex v;
                Vertex p;
                zKlient->getNachrichtEncrypted( (char*)&v.x, 4 );
                zKlient->getNachrichtEncrypted( (char*)&v.y, 4 );
                zKlient->getNachrichtEncrypted( (char*)&p.x, 4 );
                zKlient->getNachrichtEncrypted( (char*)&p.y, 4 );
                pol.vertex->add( v );
                pol.tKordinaten->add( p );
            }
            data->add( pol );
        }
        if( !mdl->erstelleModell( data ) || !dat.saveModel( mdl, name ) )
        {
            mdl->release();
            delete[] name;
            fehler = "Fehler beim speichern des Modells.";
            return 0;
        }
        p.ersetzen( p.positionVon( "map/client" ), p.positionVon( "map/client" ) + textLength( "map/client" ), "map/server" );
        dat.setPfad( p );
        dat.leseDaten();
        dat.removeModel( name );
        if( !dat.saveModel( mdl, name ) )
        {
            mdl->release();
            delete[] name;
            fehler = "Fehler beim speichern des Modells.";
            return 0;
        }
        mdl->release();
        zKlient->sendeEncrypted( "\1", 1 );
        delete[] name;
        return 1;
    }
    case 0x10: // Sound erstellen
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( !textLength( name ) )
        {
            delete[] name;
            fehler = "Du musst eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += name;
        delete[] name;
        if( !DateiExistiert( p ) )
        {
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        HMODULE gslDLL = LoadLibrary( ini->zWert( "gslPfad" )->getText() );
        if( !gslDLL )
        {
            fehler = "Interner Server Fehler.";
            std::cout << "EdS: Fehler beim laden von '" << ini->zWert( "gslPfad" )->getText() << "'.\n";
            return 0;
        }
        GetGSLDatei getGSLDatei = (GetGSLDatei)GetProcAddress( gslDLL, "getGSLDatei" );
        if( !getGSLDatei )
        {
            fehler = "Interner Server Fehler.";
            std::cout << "EdS: Der Einstiegspunkt 'getGSLDatei' wurde in der Datei '" << ini->zWert( "gslPfad" )->getText() << "' nicht gefunden.\n";
            return 0;
        }
        GSL::GSLDateiV *gslDatei = getGSLDatei();
        gslDatei->setDatei( p );
        gslDatei->leseDaten();
        gslDatei->removeSound( name );
        if( !textLength( name ) )
        {
            delete[] name;
            gslDatei->release();
            FreeLibrary( gslDLL );
            fehler = "Du musst einen Namen eingeben.";
            return 0;
        }
        DownloadSound dws( zKlient );
        gslDatei->speicherSound( &dws, name );
        if( !dws.istOk() )
        {
            delete[] name;
            gslDatei->release();
            FreeLibrary( gslDLL );
            fehler = "Es ist ein Fehler beim speichern aufgetreten.";
            return 0;
        }
        gslDatei->release();
        FreeLibrary( gslDLL );
        delete[] name;
        return 1;
    }
    case 0x11: // reset work path
        workPfad = "";
        zKlient->sendeEncrypted( "\1", 1 );
        return 1;
    default:
        fehler = "Unbekannte Nachricht. Eventuell ist der Client nicht auf dem neusten Stand.";
    }
    return 0;
}

// constant
char *DateienEditor::getLetzterFehler() const
{
    return fehler;
}

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

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