Переглянути джерело

Projektdateien hinzufügen.

Kolja Strohm 7 роки тому
батько
коміт
d2df97b803

+ 84 - 0
AppServer Linux/AppServer Linux.vcxproj

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

+ 30 - 0
AppServer Linux/AppServer Linux.vcxproj.filters

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Headerdateien">
+      <UniqueIdentifier>{fa1e2f63-6040-4500-a553-ca59c21622b7}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Quelldateien">
+      <UniqueIdentifier>{4eb89c3b-e5eb-485c-8632-5856c9a29ab0}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\AppServer\AppServer.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="..\AppServer\Datenbank.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\AppServer\AppServer.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="..\AppServer\Datenbank.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="..\AppServer\main.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>

BIN
AppServer Linux/readme/images/ArchOptions.gif


BIN
AppServer Linux/readme/images/ChangeRemote.gif


BIN
AppServer Linux/readme/images/ManageConnections.gif


BIN
AppServer Linux/readme/images/OutputTypes.gif


BIN
AppServer Linux/readme/images/debuggerexport.png


BIN
AppServer Linux/readme/images/firstconnection.png


BIN
AppServer Linux/readme/images/linker.png


BIN
AppServer Linux/readme/images/postbuild.png


+ 85 - 0
AppServer Linux/readme/readme.html

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

+ 119 - 0
AppServer Linux/readme/stylesheet.css

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

+ 30 - 0
AppServer.sln

@@ -0,0 +1,30 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26020.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppServer Linux", "AppServer Linux\AppServer Linux.vcxproj", "{CFD616B5-30F8-4BD1-AEB1-BD8809294805}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|ARM = Debug|ARM
+		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
+		Release|ARM = Release|ARM
+		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CFD616B5-30F8-4BD1-AEB1-BD8809294805}.Debug|ARM.ActiveCfg = Debug|x64
+		{CFD616B5-30F8-4BD1-AEB1-BD8809294805}.Debug|Win32.ActiveCfg = Debug|x64
+		{CFD616B5-30F8-4BD1-AEB1-BD8809294805}.Debug|x64.ActiveCfg = Debug|x64
+		{CFD616B5-30F8-4BD1-AEB1-BD8809294805}.Debug|x64.Build.0 = Debug|x64
+		{CFD616B5-30F8-4BD1-AEB1-BD8809294805}.Release|ARM.ActiveCfg = Release|x64
+		{CFD616B5-30F8-4BD1-AEB1-BD8809294805}.Release|Win32.ActiveCfg = Release|x64
+		{CFD616B5-30F8-4BD1-AEB1-BD8809294805}.Release|x64.ActiveCfg = Release|x64
+		{CFD616B5-30F8-4BD1-AEB1-BD8809294805}.Release|x64.Build.0 = Release|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 1285 - 0
AppServer/AppServer.cpp

@@ -0,0 +1,1285 @@
+#include "AppServer.h"
+#include "Datenbank.h"
+#include <Text.h>
+#include <iostream>
+#include <Klient.h>
+#include <Globals.h>
+
+// Inhalt der AppServer Klasse aus AppServer.h
+// Konstruktor 
+AppServer::AppServer( InitDatei *zDat )
+    : Thread()
+{
+    Network::Start( 100 );
+    std::cout << "AppS: Verbindung mit Datenbank wird hergestellt...\n";
+    db = new AppSDatenbank( zDat );
+    clients = 0;
+    empfangen = 0;
+    gesendet = 0;
+    dat = zDat->getThis();
+    server = new Server();
+    aServer = new Server();
+    std::cout << "AppS: Starten des Admin Servers...\n";
+    if( !aServer->verbinde( (unsigned short)TextZuInt( zDat->zWert( "AppSAPort" )->getText(), 10 ), 10 ) )
+    {
+        std::cout << "AppS: Der Admin Server konnte nicht gestartet werden. Das Programm wird beendet.\n";
+        exit( 1 );
+    }
+    end = 0;
+    InitializeCriticalSection( &cs );
+    ref = 1;
+    if( zDat->wertExistiert( "Aktiv" ) && zDat->zWert( "Aktiv" )->istGleich( "TRUE" ) )
+        serverStarten();
+}
+
+// Destruktor 
+AppServer::~AppServer()
+{
+    ende();
+    server->trenne();
+    server->release();
+    aServer->trenne();
+    aServer->release();
+    dat->release();
+    db->release();
+    Network::Exit();
+    DeleteCriticalSection( &cs );
+}
+
+// nicht constant 
+void AppServer::runn()
+{
+    while( !end )
+    {
+        SKlient *klient;
+        klient = aServer->getKlient();
+        if( end && klient )
+        {
+            klient->trenne();
+            klient = klient->release();
+            Sleep( 1000 );
+            return;
+        }
+        if( !klient )
+            return;
+        AppSAKlient *clHandle = new AppSAKlient( klient, getThis() );
+        clHandle->start();
+    }
+}
+
+void AppServer::thread()
+{
+    while( 1 )
+    {
+        SKlient *klient;
+        klient = server->getKlient();
+        if( !klient )
+            break;
+        Framework::getThreadRegister()->cleanUpClosedThreads();
+        AppSKlient *clHandle = new AppSKlient( klient, getThis() );
+        clHandle->start();
+        clients++;
+    }
+    run = 0;
+}
+
+void AppServer::close()
+{
+    server->trenne();
+#ifdef WIN32
+    warteAufThread( 1000 );
+#endif
+    ende();
+    run = 0;
+    end = 1;
+    Klient *klient = new Klient();
+    klient->verbinde( aServer->getPort(), "127.0.0.1" );
+    Sleep( 500 );
+    aServer->trenne();
+    klient->release();
+}
+
+bool AppServer::serverStarten()
+{
+    if( run )
+        return 1;
+    bool ret = server->verbinde( (unsigned short)TextZuInt( dat->zWert( "AppSPort" )->getText(), 10 ), 10 );
+    start();
+    return ret;
+}
+
+void AppServer::serverBeenden()
+{
+    if( !run )
+        return;
+    server->trenne();
+#ifdef WIN32
+    warteAufThread( 1000 );
+#endif
+    ende();
+    server->release();
+    server = new Server();
+    run = 0;
+}
+
+void AppServer::addGesendet( int bytes )
+{
+    gesendet += bytes;
+}
+
+void AppServer::addEmpfangen( int bytes )
+{
+    empfangen += empfangen;
+}
+
+void AppServer::clientTrennung()
+{
+    clients--;
+}
+
+// constant 
+InitDatei *AppServer::zIni() const
+{
+    return dat;
+}
+
+Server *AppServer::zServer() const
+{
+    return server;
+}
+
+AppSDatenbank *AppServer::zDB() const
+{
+    return db;
+}
+
+int AppServer::getClients() const
+{
+    return clients;
+}
+
+bool AppServer::hatClients() const
+{
+    return clients > 0;
+}
+
+// Reference Counting
+AppServer *AppServer::getThis()
+{
+    EnterCriticalSection( &cs );
+    ref++;
+    LeaveCriticalSection( &cs );
+    return this;
+}
+
+AppServer *AppServer::release()
+{
+    EnterCriticalSection( &cs );
+    ref--;
+    LeaveCriticalSection( &cs );
+    if( !ref )
+        delete this;
+    return 0;
+}
+
+
+// Inhalt der AppSKlient Klasse aus AppServer.h
+// Konstruktor 
+AppSAKlient::AppSAKlient( SKlient *klient, AppServer *appS )
+    : Thread()
+{
+    this->klient = klient;
+    unsigned char key[ 20 ] = { 14, 143, 241, 74, 52, 68, 158, 32, 83, 67, 205, 80, 206, 243, 151, 156, 46, 72, 120, 161 };
+    klient->setSendeKey( (char*)key, 20 );
+    klient->setEmpfangKey( (char*)key, 20 );
+    name = new Text( "" );
+    passwort = new Text( "" );
+    adminId = 0;
+    this->appS = appS;
+}
+
+// Destruktor 
+AppSAKlient::~AppSAKlient()
+{
+    klient->trenne();
+    klient->release();
+    appS->release();
+    name->release();
+    passwort->release();
+}
+
+// nicht constant 
+void AppSAKlient::thread()
+{
+    while( 1 )
+    {
+        char c = 0;
+        if( !klient->getNachrichtEncrypted( &c, 1 ) )
+            break;
+        else
+        {
+            bool br = 0;
+            switch( c )
+            {
+            case 1: // Login
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    char nLen = 0;
+                    klient->getNachrichtEncrypted( &nLen, 1 );
+                    char *n = new char[ nLen + 1 ];
+                    n[ (int)nLen ] = 0;
+                    if( nLen )
+                        klient->getNachrichtEncrypted( n, nLen );
+                    char pLen = 0;
+                    klient->getNachrichtEncrypted( &pLen, 1 );
+                    char *p = new char[ pLen + 1 ];
+                    p[ (int)pLen ] = 0;
+                    if( pLen )
+                        klient->getNachrichtEncrypted( p, pLen );
+                    int adminId = appS->zDB()->istAdministrator( n, p );
+                    if( adminId )
+                    {
+                        klient->sendeEncrypted( "\1", 1 );
+                        name->setText( n );
+                        passwort->setText( p );
+                        this->adminId = adminId;
+                    }
+                    else
+                        errorZuKlient( "Falsche Kombination aus Name und Passwort." );
+                    delete[] n;
+                    delete[] p;
+                }
+                break;
+            case 2: // Logout
+                adminId = 0;
+                name->setText( "" );
+                passwort->setText( "" );
+                klient->sendeEncrypted( "\1", 1 );
+                break;
+            case 3: // Trennen
+                br = 1;
+                klient->sendeEncrypted( "\1", 1 );
+                break;
+            case 4: // Server starten
+                if( !adminId )
+                    errorZuKlient( "Du musst dich einloggen." );
+                else
+                {
+                    if( appS->zDB()->adminHatRecht( adminId, Admin_Recht::AppSStarten ) )
+                    {
+                        if( !appS->serverStarten() )
+                            errorZuKlient( "Beim starten des Servers ist ein Fehler aufgetreten." );
+                        else
+                            klient->sendeEncrypted( "\1", 1 );
+                    }
+                    else
+                        errorZuKlient( "Du bist nicht berechtigt den Server zu starten." );
+                }
+                break;
+            case 5: // Server beenden
+                if( !adminId )
+                    errorZuKlient( "Du musst dich einloggen." );
+                else
+                {
+                    if( appS->zDB()->adminHatRecht( adminId, Admin_Recht::AppSBeenden ) )
+                    {
+                        appS->serverBeenden();
+                        klient->sendeEncrypted( "\1", 1 );
+                    }
+                    else
+                        errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
+                }
+                break;
+            case 6: // Programm Schließen
+                if( !adminId )
+                    errorZuKlient( "Du musst dich einloggen." );
+                else
+                {
+                    bool ok = 0;
+                    if( appS->isRunning() )
+                    {
+                        if( appS->zDB()->adminHatRecht( adminId, Admin_Recht::AppSBeenden ) )
+                        {
+                            appS->serverBeenden();
+                            ok = 1;
+                        }
+                        else
+                            errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
+                    }
+                    else
+                        ok = 1;
+                    if( ok && appS->hatClients() )
+                    {
+                        errorZuKlient( "Es sind noch Klients Online. Bitte versuche es später erneut." );
+                        break;
+                    }
+                    if( ok )
+                    {
+                        klient->sendeEncrypted( "\1", 1 );
+                        std::cout << "AppS: Der Server wird von Benutzer " << adminId << " heruntergefahren.\n";
+                        appS->close();
+                        br = 1;
+                    }
+                }
+                break;
+            case 7: // Progtamm abstürzen
+                if( !adminId )
+                    errorZuKlient( "Du musst dich einloggen." );
+                else
+                {
+                    bool ok = 0;
+                    if( appS->isRunning() )
+                    {
+                        if( appS->zDB()->adminHatRecht( adminId, Admin_Recht::AppSBeenden ) )
+                        {
+                            appS->serverBeenden();
+                            ok = 1;
+                        }
+                        else
+                            errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
+                    }
+                    else
+                        ok = 1;
+                    if( ok )
+                    {
+                        klient->sendeEncrypted( "\1", 1 );
+                        std::cout << "AppS: Der Server wurde von Benutzer " << adminId << " terminiert.\n";
+                        appS->close();
+                        br = 1;
+                    }
+                }
+                break;
+            case 8: // Status Frage
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    char status = (int)appS->isRunning();
+                    klient->sendeEncrypted( &status, 1 );
+                }
+                break;
+            default:
+                errorZuKlient( "Unbekannte Nachricht!" );
+                br = true;
+                break;
+            }
+            if( br )
+                break;
+            appS->addEmpfangen( klient->getDownloadBytes( 1 ) );
+            appS->addGesendet( klient->getUploadBytes( 1 ) );
+        }
+    }
+    appS->addEmpfangen( klient->getDownloadBytes( 1 ) );
+    appS->addGesendet( klient->getUploadBytes( 1 ) );
+    delete this;
+}
+
+void AppSAKlient::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient
+{
+    klient->sendeEncrypted( "\3", 1 );
+    char len = (char)textLength( nachricht );
+    klient->sendeEncrypted( &len, 1 );
+    klient->sendeEncrypted( nachricht, len );
+}
+
+
+// Inhalt der AppSKlient Klasse aus AppServer.h
+// Konstruktor 
+AppSKlient::AppSKlient( SKlient *klient, AppServer *appS )
+    : Thread()
+{
+    std::cout << "New Client aktuell:" << appS->getClients() << "\n";
+    this->klient = klient;
+    unsigned char key[ 20 ] = { 74, 103, 6, 115, 185, 240, 35, 53, 108, 55, 120, 253, 1, 232, 78, 254, 183, 223, 101, 9 };
+    klient->setSendeKey( (char*)key, 20 );
+    klient->setEmpfangKey( (char*)key, 20 );
+    this->appS = appS;
+    accountId = 0;
+    tmo = new AppSKTimeOut( this );
+}
+
+// Destruktor 
+AppSKlient::~AppSKlient()
+{
+    tmo->stop();
+    tmo->warteAufThread( 1000 );
+    delete tmo;
+    appS->clientTrennung();
+    appS->release();
+    klient->release();
+    std::cout << "Client Deleted aktuell:" << appS->getClients() << "\n";
+}
+
+// nicht constant 
+void AppSKlient::thread()
+{
+    while( 1 )
+    {
+        char c = 0;
+        if( !klient->getNachrichtEncrypted( &c, 1 ) )
+            break;
+        else
+        {
+            tmo->addConnect();
+            bool br = 0;
+            switch( c )
+            {
+            case 0: // Schlüssel Anfrage
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    Text *s = appS->zDB()->getKey();
+                    char l = (char)s->getLength();
+                    klient->sendeEncrypted( &l, 1 );
+                    klient->sendeEncrypted( s->getText(), l );
+                    klient->setSendeKey( s->getText(), s->getLength() );
+                    klient->setEmpfangKey( s->getText(), s->getLength() );
+                    s->release();
+                    break;
+                }
+            case 1: // Login 5 Minigames
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    char l = 0;
+                    klient->getNachrichtEncrypted( &l, 1 );
+                    char *name = new char[ l + 1 ];
+                    name[ (int)l ] = 0;
+                    if( l )
+                        klient->getNachrichtEncrypted( name, l );
+                    klient->getNachrichtEncrypted( &l, 1 );
+                    char *passwort = new char[ l + 1 ];
+                    passwort[ (int)l ] = 0;
+                    if( l )
+                        klient->getNachrichtEncrypted( passwort, l );
+                    accountId = appS->zDB()->login( name, passwort );
+                    delete[] name;
+                    delete[] passwort;
+                    if( accountId > 0 )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                        klient->sende( "\0", 1 );
+                    if( accountId && appS->zDB()->istNeu( accountId ) )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else if( accountId )
+                        klient->sendeEncrypted( "\0", 1 );
+                    break;
+                }
+            case 2: // Frage nach Welt Blöcke Score
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    int num = 0;
+                    klient->getNachrichtEncrypted( (char*)&num, 4 );
+                    Array< int > *score = new Array< int >();
+                    RCArray< Text > *namen = new RCArray< Text >();
+                    num = appS->zDB()->getWeltBloeckeScore( num, score, namen );
+                    klient->sendeEncrypted( (char*)&num, 4 );
+                    for( int i = 0; i < num; i++ )
+                    {
+                        int s = score->get( i );
+                        klient->sendeEncrypted( (char*)&s, 4 );
+                        char l = (char)namen->z( i )->getLength();
+                        klient->sendeEncrypted( &l, 1 );
+                        klient->sendeEncrypted( namen->z( i )->getText(), l );
+                    }
+                    score->release();
+                    namen->release();
+                    break;
+                }
+            case 3: // Frage nach Welt Mauer Score
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    int num = 0;
+                    klient->getNachrichtEncrypted( (char*)&num, 4 );
+                    Array< int > *score = new Array< int >();
+                    RCArray< Text > *namen = new RCArray< Text >();
+                    num = appS->zDB()->getWeltMauerScore( num, score, namen );
+                    klient->sendeEncrypted( (char*)&num, 4 );
+                    for( int i = 0; i < num; i++ )
+                    {
+                        int s = score->get( i );
+                        klient->sendeEncrypted( (char*)&s, 4 );
+                        char l = (char)namen->z( i )->getLength();
+                        klient->sendeEncrypted( &l, 1 );
+                        klient->sendeEncrypted( namen->z( i )->getText(), l );
+                    }
+                    score->release();
+                    namen->release();
+                    break;
+                }
+            case 4: // Frage nach Welt Farben Score
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    int num = 0;
+                    klient->getNachrichtEncrypted( (char*)&num, 4 );
+                    Array< int > *score = new Array< int >();
+                    RCArray< Text > *namen = new RCArray< Text >();
+                    num = appS->zDB()->getWeltFarbenScore( num, score, namen );
+                    klient->sendeEncrypted( (char*)&num, 4 );
+                    for( int i = 0; i < num; i++ )
+                    {
+                        int s = score->get( i );
+                        klient->sendeEncrypted( (char*)&s, 4 );
+                        char l = (char)namen->z( i )->getLength();
+                        klient->sendeEncrypted( &l, 1 );
+                        klient->sendeEncrypted( namen->z( i )->getText(), l );
+                    }
+                    score->release();
+                    namen->release();
+                    break;
+                }
+            case 5: // Frage nach Welt Fangen Score
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    int num = 0;
+                    klient->getNachrichtEncrypted( (char*)&num, 4 );
+                    Array< int > *score = new Array< int >();
+                    RCArray< Text > *namen = new RCArray< Text >();
+                    num = appS->zDB()->getWeltFangenScore( num, score, namen );
+                    klient->sendeEncrypted( (char*)&num, 4 );
+                    for( int i = 0; i < num; i++ )
+                    {
+                        int s = score->get( i );
+                        klient->sendeEncrypted( (char*)&s, 4 );
+                        char l = (char)namen->z( i )->getLength();
+                        klient->sendeEncrypted( &l, 1 );
+                        klient->sendeEncrypted( namen->z( i )->getText(), l );
+                    }
+                    score->release();
+                    namen->release();
+                    break;
+                }
+            case 6: // Frage nach Welt Rennen Score
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    int num = 0;
+                    klient->getNachrichtEncrypted( (char*)&num, 4 );
+                    Array< int > *score = new Array< int >();
+                    RCArray< Text > *namen = new RCArray< Text >();
+                    num = appS->zDB()->getWeltRennenScore( num, score, namen );
+                    klient->sendeEncrypted( (char*)&num, 4 );
+                    for( int i = 0; i < num; i++ )
+                    {
+                        int s = score->get( i );
+                        klient->sendeEncrypted( (char*)&s, 4 );
+                        char l = (char)namen->z( i )->getLength();
+                        klient->sendeEncrypted( &l, 1 );
+                        klient->sendeEncrypted( namen->z( i )->getText(), l );
+                    }
+                    score->release();
+                    namen->release();
+                    break;
+                }
+            case 7: // Frage nach Welt Gesamt Score
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    int num = 0;
+                    klient->getNachrichtEncrypted( (char*)&num, 4 );
+                    Array< int > *score = new Array< int >();
+                    RCArray< Text > *namen = new RCArray< Text >();
+                    num = appS->zDB()->getWeltGesamtScore( num, score, namen );
+                    klient->sendeEncrypted( (char*)&num, 4 );
+                    for( int i = 0; i < num; i++ )
+                    {
+                        int s = score->get( i );
+                        klient->sendeEncrypted( (char*)&s, 4 );
+                        char l = (char)namen->z( i )->getLength();
+                        klient->sendeEncrypted( &l, 1 );
+                        klient->sendeEncrypted( namen->z( i )->getText(), l );
+                    }
+                    score->release();
+                    namen->release();
+                    break;
+                }
+            case 8: // Frage nach Blöcke Score
+                if( 1 )
+                {
+                    if( accountId )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                    {
+                        klient->sendeEncrypted( "\0", 1 );
+                        break;
+                    }
+                    int score = appS->zDB()->getBloeckeScore( accountId );
+                    klient->sendeEncrypted( (char*)&score, 4 );
+                    break;
+                }
+            case 9: // Frage nach Mauer Score
+                if( 1 )
+                {
+                    if( accountId )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                    {
+                        klient->sendeEncrypted( "\0", 1 );
+                        break;
+                    }
+                    int score = appS->zDB()->getMauerScore( accountId );
+                    klient->sendeEncrypted( (char*)&score, 4 );
+                    break;
+                }
+            case 10: // Frage nach Farben Score
+                if( 1 )
+                {
+                    if( accountId )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                    {
+                        klient->sendeEncrypted( "\0", 1 );
+                        break;
+                    }
+                    int score = appS->zDB()->getFarbenScore( accountId );
+                    klient->sendeEncrypted( (char*)&score, 4 );
+                    break;
+                }
+            case 11: // Frage nach Fangen Score
+                if( 1 )
+                {
+                    if( accountId )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                    {
+                        klient->sendeEncrypted( "\0", 1 );
+                        break;
+                    }
+                    int score = appS->zDB()->getFangenScore( accountId );
+                    klient->sendeEncrypted( (char*)&score, 4 );
+                    break;
+                }
+            case 12: // Frage nach Rennen Score
+                if( 1 )
+                {
+                    if( accountId )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                    {
+                        klient->sendeEncrypted( "\0", 1 );
+                        break;
+                    }
+                    int score = appS->zDB()->getRennenScore( accountId );
+                    klient->sendeEncrypted( (char*)&score, 4 );
+                    break;
+                }
+            case 13: // Frage nach Gesamt Score
+                if( 1 )
+                {
+                    if( accountId )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                    {
+                        klient->sendeEncrypted( "\0", 1 );
+                        break;
+                    }
+                    int score = appS->zDB()->getGesamtScore( accountId );
+                    klient->sendeEncrypted( (char*)&score, 4 );
+                    break;
+                }
+            case 14: // Frage nach Mauer Zeit
+                if( 1 )
+                {
+                    if( accountId )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                    {
+                        klient->sendeEncrypted( "\0", 1 );
+                        break;
+                    }
+                    int level = 0;
+                    klient->getNachrichtEncrypted( (char*)&level, 4 );
+                    int sek = appS->zDB()->getMauerZeit( accountId, level );
+                    klient->sendeEncrypted( (char*)&sek, 4 );
+                    break;
+                }
+            case 15: // Set Blöcke Score
+                if( 1 )
+                {
+                    if( accountId )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                    {
+                        klient->sendeEncrypted( "\0", 1 );
+                        break;
+                    }
+                    int score = 0;
+                    klient->getNachrichtEncrypted( (char*)&score, 4 );
+                    appS->zDB()->setBloeckeScore( accountId, score );
+                    klient->sendeEncrypted( "\1", 1 );
+                    break;
+                }
+            case 16: // Set Farben Score
+                if( 1 )
+                {
+                    if( accountId )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                    {
+                        klient->sendeEncrypted( "\0", 1 );
+                        break;
+                    }
+                    int score = 0;
+                    klient->getNachrichtEncrypted( (char*)&score, 4 );
+                    appS->zDB()->setFarbenScore( accountId, score );
+                    klient->sendeEncrypted( "\1", 1 );
+                    break;
+                }
+            case 17: // Set Fangen Score
+                if( 1 )
+                {
+                    if( accountId )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                    {
+                        klient->sendeEncrypted( "\0", 1 );
+                        break;
+                    }
+                    int score = 0;
+                    klient->getNachrichtEncrypted( (char*)&score, 4 );
+                    appS->zDB()->setFangenScore( accountId, score );
+                    klient->sendeEncrypted( "\1", 1 );
+                    break;
+                }
+            case 18: // Set Rennen Score
+                if( 1 )
+                {
+                    if( accountId )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                    {
+                        klient->sendeEncrypted( "\0", 1 );
+                        break;
+                    }
+                    int score = 0;
+                    klient->getNachrichtEncrypted( (char*)&score, 4 );
+                    appS->zDB()->setRennenScore( accountId, score );
+                    klient->sendeEncrypted( "\1", 1 );
+                    break;
+                }
+            case 19: // Set Mauer Zeit
+                if( 1 )
+                {
+                    if( accountId )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                    {
+                        klient->sendeEncrypted( "\0", 1 );
+                        break;
+                    }
+                    int level = 0;
+                    klient->getNachrichtEncrypted( (char*)&level, 4 );
+                    int zeit = 0;
+                    klient->getNachrichtEncrypted( (char*)&zeit, 4 );
+                    appS->zDB()->setMauerZeit( accountId, level, zeit );
+                    klient->sendeEncrypted( "\1", 1 );
+                    break;
+                }
+            case 20: // Account erstellen
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    unsigned char len[ 4 ] = { 0, 0, 0, 0 };
+                    klient->getNachrichtEncrypted( (char*)len, 4 );
+                    char *acc_name = new char[ len[ 0 ] + 1 ];
+                    acc_name[ len[ 0 ] ] = 0;
+                    klient->getNachrichtEncrypted( acc_name, len[ 0 ] );
+                    char *acc_pass = new char[ len[ 1 ] + 1 ];
+                    acc_pass[ len[ 1 ] ] = 0;
+                    klient->getNachrichtEncrypted( acc_pass, len[ 1 ] );
+                    char *acc_geheim = new char[ len[ 2 ] + 1 ];
+                    acc_geheim[ len[ 2 ] ] = 0;
+                    klient->getNachrichtEncrypted( acc_geheim, len[ 2 ] );
+                    char *acc_mail = new char[ len[ 3 ] + 1 ];
+                    acc_mail[ len[ 3 ] ] = 0;
+                    klient->getNachrichtEncrypted( acc_mail, len[ 3 ] );
+                    unsigned short acc_geb_jahr = 0;
+                    klient->getNachrichtEncrypted( (char*)&acc_geb_jahr, 2 );
+                    char acc_geb_monat = 0;
+                    klient->getNachrichtEncrypted( &acc_geb_monat, 1 );
+                    char acc_geb_tag = 0;
+                    klient->getNachrichtEncrypted( &acc_geb_tag, 1 );
+                    int pres = appS->zDB()->pruefNeuAccount( acc_name, acc_mail );
+                    if( !pres )
+                    {
+                        Text *gebDatum = new Text( "" );
+                        gebDatum->append( (int)acc_geb_jahr );
+                        gebDatum->append( "-" );
+                        gebDatum->append( (int)acc_geb_monat );
+                        gebDatum->append( "-" );
+                        gebDatum->append( (int)acc_geb_tag );
+                        if( !appS->zDB()->neuAccount( acc_name, acc_pass, acc_geheim, acc_mail, gebDatum->getText(), appS->zIni() ) )
+                            klient->sendeEncrypted( "\0", 1 );
+                        else
+                            klient->sendeEncrypted( "\1", 1 );
+                        gebDatum->release();
+                    }
+                    else
+                        klient->sendeEncrypted( "\0", 1 );
+                    delete[]acc_name;
+                    delete[]acc_pass;
+                    delete[]acc_geheim;
+                    delete[]acc_mail;
+                }
+                break;
+            case 21: // Account bestätigen
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    unsigned char len[ 2 ];
+                    klient->getNachrichtEncrypted( (char*)len, 2 );
+                    char *accName = new char[ len[ 0 ] + 1 ];
+                    accName[ len[ 0 ] ] = 0;
+                    klient->getNachrichtEncrypted( accName, len[ 0 ] );
+                    char *accPasswort = new char[ len[ 1 ] + 1 ];
+                    accPasswort[ len[ 1 ] ] = 0;
+                    klient->getNachrichtEncrypted( accPasswort, len[ 1 ] );
+                    char byte = appS->zDB()->suchBestaetigung( accName, accPasswort );
+                    if( !byte )
+                        klient->sendeEncrypted( "\0", 1 );
+                    else if( byte == -1 )
+                        klient->sendeEncrypted( "\0", 1 );
+                    else if( byte > 0 )
+                    {
+                        klient->sendeEncrypted( &byte, 1 );
+                        char befehl = 0;
+                        while( 1 )
+                        {
+                            klient->getNachrichtEncrypted( &befehl, 1 );
+                            if( !befehl )
+                            {
+                                if( byte == 1 )
+                                    appS->zDB()->neuAccountAbbruch( accName );
+                                break;
+                            }
+                            if( befehl == -1 )
+                                break;
+                            if( befehl == -2 )
+                            {
+                                if( byte == 1 )
+                                    appS->zDB()->sendeErstellEMail( accName, appS->zIni() );
+                            }
+                            if( befehl > 0 )
+                            {
+                                char *key = new char[ befehl + 1 ];
+                                key[ (int)befehl ] = 0;
+                                klient->getNachrichtEncrypted( key, befehl );
+                                if( byte == 1 )
+                                {
+                                    if( !appS->zDB()->aktiviereAccount( accName, key ) )
+                                        klient->sendeEncrypted( "\0", 1 );
+                                    else
+                                    {
+                                        klient->sendeEncrypted( "\1", 1 );
+                                        delete[]key;
+                                        break;
+                                    }
+                                }
+                                delete[]key;
+                            }
+                        }
+                    }
+                    delete[]accName;
+                    delete[]accPasswort;
+                }
+                break;
+            case 22: // Trennen
+                klient->sendeEncrypted( "\1", 1 );
+                br = 1;
+                break;
+            case 23: // Mark Balls finish
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    int level = 0;
+                    klient->getNachrichtEncrypted( (char*)&level, 4 );
+                    int sek = 0;
+                    klient->getNachrichtEncrypted( (char*)&sek, 4 );
+                    if( accountId )
+                        appS->zDB()->markballsFinish( level, sek, accountId, 0, 0, 0, 0 );
+                    else
+                    {
+                        char l = 0;
+                        klient->getNachrichtEncrypted( &l, 1 );
+                        char *device = new char[ l + 1 ];
+                        device[ (int)l ] = 0;
+                        klient->getNachrichtEncrypted( device, l );
+                        appS->zDB()->markballsFinish( level, sek, accountId, device, 0, 0, 0 );
+                        delete[] device;
+                    }
+                    klient->sendeEncrypted( "\1", 1 );
+                    break;
+                }
+            case 24: // Get Mark Balls Score
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    Array< int > *level = new Array< int >();
+                    Array< int > *score = new Array< int >();
+                    RCArray< Text > *name = new RCArray< Text >();
+                    int anz = appS->zDB()->getMarkballsScore( level, score, name, 0 );
+                    klient->sendeEncrypted( (char*)&anz, 4 );
+                    for( int i = 0; i < anz; i++ )
+                    {
+                        int l = level->get( i );
+                        klient->sendeEncrypted( (char*)&l, 4 );
+                        int s = score->get( i );
+                        klient->sendeEncrypted( (char*)&s, 4 );
+                        char nl = (char)name->z( i )->getLength();
+                        klient->sendeEncrypted( &nl, 1 );
+                        if( nl )
+                            klient->sendeEncrypted( name->z( i )->getText(), nl );
+                    }
+                    level->release();
+                    score->release();
+                    name->release();
+                    break;
+                }
+            case 25: // Login Mark Balls
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    char l = 0;
+                    klient->getNachrichtEncrypted( &l, 1 );
+                    char *name = new char[ l + 1 ];
+                    name[ (int)l ] = 0;
+                    if( l )
+                        klient->getNachrichtEncrypted( name, l );
+                    klient->getNachrichtEncrypted( &l, 1 );
+                    char *passwort = new char[ l + 1 ];
+                    passwort[ (int)l ] = 0;
+                    if( l )
+                        klient->getNachrichtEncrypted( passwort, l );
+                    klient->getNachrichtEncrypted( &l, 1 );
+                    char *device = new char[ l + 1 ];
+                    device[ (int)l ] = 0;
+                    if( l )
+                        klient->getNachrichtEncrypted( device, l );
+                    accountId = appS->zDB()->login( name, passwort );
+                    delete[] name;
+                    delete[] passwort;
+                    if( accountId > 0 )
+                    {
+                        appS->zDB()->deviceAccount( device, accountId );
+                        klient->sendeEncrypted( "\1", 1 );
+                    }
+                    else
+                        klient->sende( "\0", 1 );
+                    delete[] device;
+                    break;
+                }
+            case 26: // Mark Balls finish NEW
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    int level = 0;
+                    klient->getNachrichtEncrypted( (char*)&level, 4 );
+                    int sek = 0;
+                    klient->getNachrichtEncrypted( (char*)&sek, 4 );
+                    int diff = 0;
+                    klient->getNachrichtEncrypted( (char*)&diff, 4 );
+                    int gId = 0;
+                    klient->getNachrichtEncrypted( (char*)&gId, 4 );
+                    if( accountId )
+                    {
+                        int kupfer = 0;
+                        klient->getNachrichtEncrypted( (char*)&kupfer, 4 );
+                        appS->zDB()->markballsFinish( level, sek, accountId, 0, diff, kupfer, gId );
+                    }
+                    else
+                    {
+                        char l = 0;
+                        klient->getNachrichtEncrypted( &l, 1 );
+                        char *device = new char[ l + 1 ];
+                        device[ (int)l ] = 0;
+                        klient->getNachrichtEncrypted( device, l );
+                        appS->zDB()->markballsFinish( level, sek, accountId, device, diff, 0, gId );
+                        delete[] device;
+                    }
+                    klient->sendeEncrypted( "\1", 1 );
+                    break;
+                }
+            case 27: // Get Mark Balls Score NEW
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    int diff = 0;
+                    klient->getNachrichtEncrypted( (char*)&diff, 4 );
+                    Array< int > *level = new Array< int >();
+                    Array< int > *score = new Array< int >();
+                    int anz = appS->zDB()->getMarkballsScore( level, score, diff );
+                    klient->sendeEncrypted( (char*)&anz, 4 );
+                    for( int i = 0; i < anz; i++ )
+                    {
+                        int l = level->get( i );
+                        klient->sendeEncrypted( (char*)&l, 4 );
+                        int s = score->get( i );
+                        klient->sendeEncrypted( (char*)&s, 4 );
+                    }
+                    level->release();
+                    score->release();
+                    break;
+                }
+            case 28: // Get gegenstand Liste
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    Array< int > *gId = new Array< int >();
+                    Array< int > *diff = new Array< int >();
+                    int anz = 0;
+                    if( accountId )
+                        anz = appS->zDB()->getGegenstaende( accountId, 0, gId, diff );
+                    else
+                    {
+                        char l = 0;
+                        klient->getNachrichtEncrypted( &l, 1 );
+                        char *device = new char[ l + 1 ];
+                        device[ (int)l ] = 0;
+                        klient->getNachrichtEncrypted( device, l );
+                        anz = appS->zDB()->getGegenstaende( 0, device, gId, diff );
+                        delete[] device;
+                    }
+                    klient->sendeEncrypted( (char*)&anz, 4 );
+                    for( int i = 0; i < anz; i++ )
+                    {
+                        int g = gId->get( i );
+                        klient->sendeEncrypted( (char*)&g, 4 );
+                        int d = diff->get( i );
+                        klient->sendeEncrypted( (char*)&d, 4 );
+                    }
+                    gId->release();
+                    diff->release();
+                    break;
+                }
+            case 29: // Get Kupfer
+                if( 1 )
+                {
+                    if( !accountId )
+                        klient->sendeEncrypted( "\0", 1 );
+                    else
+                    {
+                        klient->sendeEncrypted( "\1", 1 );
+                        int ret = appS->zDB()->getKupfer( accountId );
+                        klient->sendeEncrypted( (char*)&ret, 4 );
+                    }
+                    break;
+                }
+            case 30: // Get Markballs Fortschritt
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    Array< int > *fortschritt = new Array< int >();
+                    int anz = 0;
+                    if( accountId )
+                        anz = appS->zDB()->getMarkballsFortschritt( accountId, 0, fortschritt );
+                    else
+                    {
+                        char l = 0;
+                        klient->getNachrichtEncrypted( &l, 1 );
+                        char *device = new char[ l + 1 ];
+                        device[ (int)l ] = 0;
+                        klient->getNachrichtEncrypted( device, l );
+                        anz = appS->zDB()->getMarkballsFortschritt( 0, device, fortschritt );
+                        delete[] device;
+                    }
+                    klient->sendeEncrypted( (char*)&anz, 4 );
+                    for( int i = 0; i < anz; i++ )
+                    {
+                        int f = fortschritt->get( i );
+                        klient->sendeEncrypted( (char*)&f, 4 );
+                    }
+                    fortschritt->release();
+                    break;
+                }
+            case 31: // Global Login
+            {
+                klient->sendeEncrypted( "\1", 1 );
+                char l = 0;
+                klient->getNachrichtEncrypted( &l, 1 );
+                char *name = new char[ l + 1 ];
+                name[ (int)l ] = 0;
+                if( l )
+                    klient->getNachrichtEncrypted( name, l );
+                klient->getNachrichtEncrypted( &l, 1 );
+                char *passwort = new char[ l + 1 ];
+                passwort[ (int)l ] = 0;
+                if( l )
+                    klient->getNachrichtEncrypted( passwort, l );
+                klient->getNachrichtEncrypted( &l, 1 );
+                char *device = new char[ l + 1 ];
+                device[ (int)l ] = 0;
+                if( l )
+                    klient->getNachrichtEncrypted( device, l );
+                accountId = appS->zDB()->login( name, passwort );
+                delete[] name;
+                delete[] passwort;
+                if( accountId > 0 )
+                    klient->sendeEncrypted( "\1", 1 );
+                else
+                    klient->sende( "\0", 1 );
+                delete[] device;
+                break;
+            }
+            case 32: // Curvesnake finish Game
+            {
+                klient->sendeEncrypted( "\1", 1 );
+                int score = 0;
+                klient->getNachrichtEncrypted( (char*)&score, 4 );
+                int map = 0;
+                klient->getNachrichtEncrypted( (char*)&map, 4 );
+                if( accountId )
+                {
+                    int kupfer = 0;
+                    klient->getNachrichtEncrypted( (char*)&kupfer, 4 );
+                    klient->getNachrichtEncrypted( (char*)&kupfer, 4 );
+                    appS->zDB()->curvesnakeFinish( score, accountId, 0, map, kupfer );
+                }
+                else
+                {
+                    char l = 0;
+                    klient->getNachrichtEncrypted( &l, 1 );
+                    char *device = new char[ l + 1 ];
+                    device[ (int)l ] = 0;
+                    klient->getNachrichtEncrypted( device, l );
+                    appS->zDB()->curvesnakeFinish( score, accountId, device, map, 0 );
+                    delete[] device;
+                }
+                klient->sendeEncrypted( "\1", 1 );
+                break;
+            }
+            case 33: // Curvesnake best score
+            {
+                klient->sendeEncrypted( "\1", 1 );
+                Array< int > *map = new Array< int >();
+                Array< int > *score = new Array< int >();
+                int anz = appS->zDB()->getCurvesnakeScore( map, score );
+                klient->sendeEncrypted( (char*)&anz, 4 );
+                for( int i = 0; i < anz; i++ )
+                {
+                    int l = map->get( i );
+                    klient->sendeEncrypted( (char*)&l, 4 );
+                    int s = score->get( i );
+                    klient->sendeEncrypted( (char*)&s, 4 );
+                }
+                map->release();
+                score->release();
+                break;
+            }
+            case 34: // Curvesnake get Map List
+            {
+                klient->sendeEncrypted( "\1", 1 );
+                Array< int > *map = new Array< int >();
+                int anz = appS->zDB()->getCurvesnakeMapList( map, accountId );
+                klient->sendeEncrypted( (char*)&anz, 4 );
+                for( int i = 0; i < anz; i++ )
+                {
+                    int l = map->get( i );
+                    klient->sendeEncrypted( (char*)&l, 4 );
+                }
+                map->release();
+                break;
+            }
+            case 35: // Add Kupfer
+            {
+                if( accountId )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    int kupfer = 0;
+                    klient->getNachrichtEncrypted( (char*)&kupfer, 4 );
+                    appS->zDB()->addKupfer( accountId, kupfer );
+                }
+                else
+                    klient->sendeEncrypted( "\0", 1 );
+                break;
+            }
+            case 36: // getFreeAds
+            {
+                if( accountId )
+                {
+                    if( appS->zDB()->getFreeAds( accountId ) )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                        klient->sendeEncrypted( "\0", 1 );
+                }
+                else
+                    klient->sendeEncrypted( "\0", 1 );
+                break;
+            }
+			case 37: // keppAlive
+			{
+				klient->sendeEncrypted( "\1", 1 );
+				break;
+			}
+            default:
+                klient->sendeEncrypted( "\0", 1 );
+                br = true;
+                break;
+            }
+            if( br )
+                break;
+            appS->addEmpfangen( klient->getDownloadBytes( 1 ) );
+            appS->addGesendet( klient->getUploadBytes( 1 ) );
+        }
+    }
+    appS->addEmpfangen( klient->getDownloadBytes( 1 ) );
+    appS->addGesendet( klient->getUploadBytes( 1 ) );
+    delete this;
+}
+
+void AppSKlient::timeout()
+{
+	klient->trenne();
+}
+
+void AppSKlient::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient
+{
+    klient->sendeEncrypted( "\3", 1 );
+    char len = (char)textLength( nachricht );
+    klient->sendeEncrypted( &len, 1 );
+    klient->sendeEncrypted( nachricht, len );
+}
+
+
+// Inhalt der AppSKTimeOut Klasse aus AppServer.h
+// Konstruktor
+AppSKTimeOut::AppSKTimeOut( AppSKlient *zK )
+{
+    zKlient = zK;
+    zm = new ZeitMesser();
+    zm->messungStart();
+    st = 0;
+    start();
+}
+
+// Destruktor
+AppSKTimeOut::~AppSKTimeOut()
+{
+    zm->release();
+}
+
+// nicht constant
+void AppSKTimeOut::thread()
+{
+    while( !st )
+    {
+        zm->messungEnde();
+        if( zm->getSekunden() > 10 )
+            zKlient->timeout();
+        for( int i = 0; i < 300 && !st; i++ )
+            Sleep( 100 );
+    }
+}
+
+void AppSKTimeOut::stop()
+{
+    st = 1;
+}
+
+void AppSKTimeOut::addConnect()
+{
+    zm->messungStart();
+}

+ 111 - 0
AppServer/AppServer.h

@@ -0,0 +1,111 @@
+#ifndef AppServer_H
+#define AppServer_H
+
+#include <Server.h>
+#include <Thread.h>
+#include <InitDatei.h>
+#include <Zeit.h>
+#include "Datenbank.h"
+
+using namespace Framework;
+using namespace Network;
+
+class AppSKTimeOut;
+
+class AppServer : public Thread
+{
+private:
+    Server *server;
+    Server *aServer;
+    InitDatei *dat;
+    AppSDatenbank *db;
+    CRITICAL_SECTION cs;
+    int empfangen;
+    int gesendet;
+    int clients;
+    bool end;
+    int ref;
+
+public:
+    // Konstruktor 
+    AppServer( InitDatei *zDat );
+    // Destruktor 
+    virtual ~AppServer();
+    // nicht constant 
+    void runn();
+    void thread();
+    void close();
+    bool serverStarten();
+    void serverBeenden();
+    void addGesendet( int bytes );
+    void addEmpfangen( int bytes );
+    void clientTrennung();
+    // constant 
+    InitDatei *zIni() const;
+    Server *zServer() const;
+    AppSDatenbank *zDB() const;
+    int getClients() const;
+    bool hatClients() const;
+    // Reference Counting
+    AppServer *getThis();
+    AppServer *release();
+};
+
+class AppSAKlient : public Thread
+{
+private:
+    SKlient *klient;
+    Text *name;
+    Text *passwort;
+    int adminId;
+    AppServer *appS;
+
+public:
+    // Konstruktor 
+    AppSAKlient( SKlient *klient, AppServer *appS );
+    // Destruktor 
+    virtual ~AppSAKlient();
+    // nicht constant 
+    void thread();
+    void errorZuKlient( const char *nachricht ) const; // sendet eine Fehlernachricht zum AKlient
+};
+
+class AppSKlient : public Thread
+{
+private:
+    SKlient *klient;
+    AppServer *appS;
+    int accountId;
+    AppSKTimeOut *tmo;
+
+public:
+    // Konstruktor 
+    AppSKlient( SKlient *klient, AppServer *appS );
+    // Destruktor 
+    virtual ~AppSKlient();
+    // nicht constant 
+    void thread() override;
+    void timeout();
+    void errorZuKlient( const char *nachricht ) const; // sendet eine Fehlernachricht zum Klient
+};
+
+class AppSKTimeOut : public Thread
+{
+private:
+    __int64 lastConnect;
+    AppSKlient *zKlient;
+    ZeitMesser *zm;
+    bool st;
+
+public:
+    // Konstruktor
+    AppSKTimeOut( AppSKlient *zK );
+    // Destruktor
+   virtual  ~AppSKTimeOut();
+    // nicht constant
+    void thread() override;
+    void stop();
+    void addConnect();
+};
+
+#endif

+ 166 - 0
AppServer/AppServer.vcxproj

@@ -0,0 +1,166 @@
+<?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>{429CDC3D-BBD5-4216-BECC-947F6C73640D}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>AppServer</RootNamespace>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <IncludePath>..\..\..\Allgemein\Framework;..\..\..\Allgemein\Network\Network;..\..\..\Allgemein\sql\sql;$(IncludePath)</IncludePath>
+    <LibraryPath>..\..\..\Allgemein\Framework\x64\Debug;..\..\..\Allgemein\Network\x64\Debug;..\..\..\Allgemein\sql\x64\Debug;$(LibraryPath)</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>..\..\..\Allgemein\Framework;..\..\..\Allgemein\Network\Network;..\..\..\Allgemein\sql\sql;$(IncludePath)</IncludePath>
+    <LibraryPath>..\..\..\Allgemein\Framework\Release;..\..\..\Allgemein\Network\Release;..\..\..\Allgemein\sql\Release;$(LibraryPath)</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>..\..\..\Allgemein\Framework;..\..\..\Allgemein\Network\Network;..\..\..\Allgemein\sql\sql;$(IncludePath)</IncludePath>
+    <LibraryPath>..\..\..\Allgemein\Framework\x64\Release;..\..\..\Allgemein\Network\x64\Release;..\..\..\Allgemein\sql\x64\Release;$(LibraryPath)</LibraryPath>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>Framework.lib;Network.lib;sql.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>Framework.lib;Network.lib;sql.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>Framework.lib;Network.lib;sql.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>Framework.lib;Network.lib;sql.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="AppServer.h" />
+    <ClInclude Include="Datenbank.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="AppServer.cpp" />
+    <ClCompile Include="Datenbank.cpp" />
+    <ClCompile Include="main.cpp" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 36 - 0
AppServer/AppServer.vcxproj.filters

@@ -0,0 +1,36 @@
+<?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="Datenbank.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="AppServer.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="Datenbank.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="AppServer.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="main.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>

+ 1185 - 0
AppServer/Datenbank.cpp

@@ -0,0 +1,1185 @@
+#include "Datenbank.h"
+#include <iostream>
+#include <Datei.h>
+
+#ifndef WIN32
+#include <spawn.h>
+#endif
+
+// Inhalt der AppSDatenbank Klasse aus Datenbank.h
+// Konstruktor
+AppSDatenbank::AppSDatenbank( InitDatei *zDat )
+{
+    datenbank = new Datenbank( zDat->zWert( "DBBenutzer" )->getText(), zDat->zWert( "DBPasswort" )->getText(),
+                               zDat->zWert( "DBName" )->getText(), zDat->zWert( "DBIP" )->getText(),
+                               (unsigned short)TextZuInt( zDat->zWert( "DBPort" )->getText(), 10 ) );
+    if( !datenbank->istOk() )
+    {
+        std::cout << "AppS: Es konnte keine Verbindung zur Datenbank hergestellt werden:\n";
+        Text *txt = datenbank->getLetzterFehler();
+        std::cout << txt->getText() << "\nDas Programm wird beendet.";
+        txt->release();
+        exit( 1 );
+    }
+    InitializeCriticalSection( &ths );
+    ref = 1;
+    Text befehl = "SELECT port, admin_port FROM server WHERE id = ";
+    befehl += zDat->zWert( "ServerId" )->getText();
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    if( res.zeilenAnzahl == 1 )
+    {
+        zDat->addWert( "AppSPort", res.values[ 0 ] );
+        zDat->addWert( "AppSAPort", res.values[ 1 ] );
+    }
+    res.destroy();
+}
+
+// Detruktor
+AppSDatenbank::~AppSDatenbank()
+{
+    datenbank->release();
+    DeleteCriticalSection( &ths );
+}
+
+// nicht constant
+void AppSDatenbank::lock()
+{
+    EnterCriticalSection( &ths );
+}
+
+void AppSDatenbank::unlock()
+{
+    LeaveCriticalSection( &ths );
+}
+
+int AppSDatenbank::istAdministrator( const char *name, const char *passwort )
+{
+    Text *befehl = new Text( "SELECT id FROM benutzer WHERE name = '" );
+    Text n( name );
+    n.ersetzen( "'", "''" );
+    befehl->append( (char*)n );
+    befehl->append( "' AND passwort = md5('" );
+    Text p( passwort );
+    p.ersetzen( "'", "''" );
+    befehl->append( (char*)p );
+    befehl->append( "')" );
+    lock();
+    datenbank->befehl( befehl->getText() );
+    Result res = datenbank->getResult();
+    unlock();
+    befehl->release();
+    int ret = 0;
+    if( res.zeilenAnzahl > 0 )
+        ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+    res.destroy();
+    return ret;
+}
+
+bool AppSDatenbank::adminHatRecht( int id, int recht )
+{
+    Text *befehl = new Text( "SELECT * FROM benutzer_rechte WHERE benutzer_id = " );
+    befehl->append( id );
+    befehl->append( " AND rechte_id = " );
+    befehl->append( recht );
+    lock();
+    datenbank->befehl( befehl->getText() );
+    int ret = datenbank->getZeilenAnzahl();
+    unlock();
+    befehl->release();
+    return ret != 0;
+}
+
+Text *AppSDatenbank::getKey()
+{
+    lock();
+    datenbank->befehl( "SELECT get_next_schluessel()" );
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+        return 0;
+    Text *ret = new Text( res.values[ 0 ].getText() );
+    res.destroy();
+    return ret;
+}
+
+int AppSDatenbank::login( char *name, char *passwort )
+{
+    Text befehl = "SELECT id FROM account WHERE name = '";
+    befehl += name;
+    befehl += "' AND passwort = '";
+    befehl += passwort;
+    befehl += "'";
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+        return 0;
+    int ret = res.values[ 0 ];
+    res.destroy();
+    return ret;
+}
+
+bool AppSDatenbank::istNeu( int account )
+{
+    Text befehl = "SELECT * from app_5_minigames_score WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    int zeilen = datenbank->getZeilenAnzahl();
+    unlock();
+    return zeilen == 0;
+}
+
+int AppSDatenbank::getWeltBloeckeScore( int anz, Array< int > *score, RCArray< Text > *namen )
+{
+    Text befehl = "SELECT a.bloecke, b.ruf_name FROM app_5_minigames_score a, account b WHERE b.id = a.account_id ORDER BY a.bloecke DESC LIMIT ";
+    befehl += anz;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    int ret = res.zeilenAnzahl;
+    for( int i = 0; i < ret; i++ )
+    {
+        score->set( res.values[ i * 2 ], i );
+        namen->set( new Text( res.values[ i * 2 + 1 ].getText() ), i );
+    }
+    res.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getWeltMauerScore( int anz, Array< int > *score, RCArray< Text > *namen )
+{
+    Text befehl = "SELECT a.mauer, b.ruf_name FROM app_5_minigames_score a, account b WHERE b.id = a.account_id ORDER BY a.mauer DESC LIMIT ";
+    befehl += anz;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    int ret = res.zeilenAnzahl;
+    for( int i = 0; i < ret; i++ )
+    {
+        score->set( res.values[ i * 2 ], i );
+        namen->set( new Text( res.values[ i * 2 + 1 ].getText() ), i );
+    }
+    res.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getWeltFarbenScore( int anz, Array< int > *score, RCArray< Text > *namen )
+{
+    Text befehl = "SELECT a.farben, b.ruf_name FROM app_5_minigames_score a, account b WHERE b.id = a.account_id ORDER BY a.farben DESC LIMIT ";
+    befehl += anz;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    int ret = res.zeilenAnzahl;
+    for( int i = 0; i < ret; i++ )
+    {
+        score->set( res.values[ i * 2 ], i );
+        namen->set( new Text( res.values[ i * 2 + 1 ].getText() ), i );
+    }
+    res.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getWeltFangenScore( int anz, Array< int > *score, RCArray< Text > *namen )
+{
+    Text befehl = "SELECT a.fangen, b.ruf_name FROM app_5_minigames_score a, account b WHERE b.id = a.account_id ORDER BY a.fangen DESC LIMIT ";
+    befehl += anz;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    int ret = res.zeilenAnzahl;
+    for( int i = 0; i < ret; i++ )
+    {
+        score->set( res.values[ i * 2 ], i );
+        namen->set( new Text( res.values[ i * 2 + 1 ].getText() ), i );
+    }
+    res.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getWeltRennenScore( int anz, Array< int > *score, RCArray< Text > *namen )
+{
+    Text befehl = "SELECT a.rennen, b.ruf_name FROM app_5_minigames_score a, account b WHERE b.id = a.account_id ORDER BY a.rennen DESC LIMIT ";
+    befehl += anz;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    int ret = res.zeilenAnzahl;
+    for( int i = 0; i < ret; i++ )
+    {
+        score->set( res.values[ i * 2 ], i );
+        namen->set( new Text( res.values[ i * 2 + 1 ].getText() ), i );
+    }
+    res.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getWeltGesamtScore( int anz, Array< int > *score, RCArray< Text > *namen )
+{
+    Text befehl = "SELECT a.gesamt, b.ruf_name FROM app_5_minigames_score a, account b WHERE b.id = a.account_id ORDER BY a.gesamt DESC LIMIT ";
+    befehl += anz;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    int ret = res.zeilenAnzahl;
+    for( int i = 0; i < ret; i++ )
+    {
+        score->set( res.values[ i * 2 ], i );
+        namen->set( new Text( res.values[ i * 2 + 1 ].getText() ), i );
+    }
+    res.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getBloeckeScore( int account )
+{
+    Text befehl = "SELECT bloecke FROM app_5_minigames_score WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+        return 0;
+    int ret = res.values[ 0 ];
+    res.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getMauerScore( int account )
+{
+    Text befehl = "SELECT mauer FROM app_5_minigames_score WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+        return 0;
+    int ret = res.values[ 0 ];
+    res.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getMauerZeit( int account, int level )
+{
+    Text befehl = "SELECT sekunden FROM app_5_minigames_mauer_score WHERE account_id = ";
+    befehl += account;
+    befehl += " AND level = ";
+    befehl += level;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+        return 0;
+    int ret = res.values[ 0 ];
+    res.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getFarbenScore( int account )
+{
+    Text befehl = "SELECT farben FROM app_5_minigames_score WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+        return 0;
+    int ret = res.values[ 0 ];
+    res.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getFangenScore( int account )
+{
+    Text befehl = "SELECT fangen FROM app_5_minigames_score WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+        return 0;
+    int ret = res.values[ 0 ];
+    res.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getRennenScore( int account )
+{
+    Text befehl = "SELECT rennen FROM app_5_minigames_score WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+        return 0;
+    int ret = res.values[ 0 ];
+    res.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getGesamtScore( int account )
+{
+    Text befehl = "SELECT gesamt FROM app_5_minigames_score WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+        return 0;
+    int ret = res.values[ 0 ];
+    res.destroy();
+    return ret;
+}
+
+void AppSDatenbank::setBloeckeScore( int account, int score )
+{
+    if( score < getBloeckeScore( account ) )
+        return;
+    Text befehl = "UPDATE app_5_minigames_score SET bloecke = ";
+    befehl += score;
+    befehl += " WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    int z = datenbank->getZeilenAnzahl();
+    unlock();
+    if( !z )
+    {
+        befehl = "INSERT INTO app_5_minigames_score( bloecke, account_id ) VALUES( ";
+        befehl += score;
+        befehl += ", ";
+        befehl += account;
+        befehl += " )";
+        lock();
+        datenbank->befehl( befehl );
+        unlock();
+    }
+    calkGesamtScore( account );
+}
+
+void AppSDatenbank::setFarbenScore( int account, int score )
+{
+    if( score < getFarbenScore( account ) )
+        return;
+    Text befehl = "UPDATE app_5_minigames_score SET farben = ";
+    befehl += score;
+    befehl += " WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    int z = datenbank->getZeilenAnzahl();
+    unlock();
+    if( !z )
+    {
+        befehl = "INSERT INTO app_5_minigames_score( farben, account_id ) VALUES( ";
+        befehl += score;
+        befehl += ", ";
+        befehl += account;
+        befehl += " )";
+        lock();
+        datenbank->befehl( befehl );
+        unlock();
+    }
+    calkGesamtScore( account );
+}
+
+void AppSDatenbank::setFangenScore( int account, int score )
+{
+    if( score < getFangenScore( account ) )
+        return;
+    Text befehl = "UPDATE app_5_minigames_score SET fangen = ";
+    befehl += score;
+    befehl += " WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    int z = datenbank->getZeilenAnzahl();
+    unlock();
+    if( !z )
+    {
+        befehl = "INSERT INTO app_5_minigames_score( fangen, account_id ) VALUES( ";
+        befehl += score;
+        befehl += ", ";
+        befehl += account;
+        befehl += " )";
+        lock();
+        datenbank->befehl( befehl );
+        unlock();
+    }
+    calkGesamtScore( account );
+}
+
+void AppSDatenbank::setRennenScore( int account, int score )
+{
+    if( score < getRennenScore( account ) )
+        return;
+    Text befehl = "UPDATE app_5_minigames_score SET rennen = ";
+    befehl += score;
+    befehl += " WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    int z = datenbank->getZeilenAnzahl();
+    unlock();
+    if( !z )
+    {
+        befehl = "INSERT INTO app_5_minigames_score( rennen, account_id ) VALUES( ";
+        befehl += score;
+        befehl += ", ";
+        befehl += account;
+        befehl += " )";
+        lock();
+        datenbank->befehl( befehl );
+        unlock();
+    }
+    calkGesamtScore( account );
+}
+
+void AppSDatenbank::setMauerZeit( int account, int level, int zeit )
+{
+    if( zeit > getMauerZeit( account, level ) && getMauerZeit( account, level ) != 0 )
+        return;
+    if( zeit > 600 )
+        zeit = 600;
+    Text befehl = "UPDATE app_5_minigames_mauer_score SET sekunden = ";
+    befehl += zeit;
+    befehl += " WHERE account_id = ";
+    befehl += account;
+    befehl += " AND level = ";
+    befehl += level;
+    lock();
+    datenbank->befehl( befehl );
+    int z = datenbank->getZeilenAnzahl();
+    unlock();
+    if( !z )
+    {
+        befehl = "INSERT INTO app_5_minigames_mauer_score( account_id, level, sekunden ) VALUES( ";
+        befehl += account;
+        befehl += ", ";
+        befehl += level;
+        befehl += ", ";
+        befehl += zeit;
+        befehl += " )";
+        lock();
+        datenbank->befehl( befehl );
+        unlock();
+    }
+    calkMauerScore( account );
+}
+
+void AppSDatenbank::calkMauerScore( int account )
+{
+    Text befehl = "SELECT count( sekunden ), sum( sekunden ) FROM app_5_minigames_mauer_score WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    if( (int)res.values[ 0 ] == 0 )
+        return;
+    int score = (int)res.values[ 0 ] * 600 - (int)res.values[ 1 ];
+    res.destroy();
+    befehl = "UPDATE app_5_minigames_score SET mauer = ";
+    befehl += score;
+    befehl += " WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    int z = datenbank->getZeilenAnzahl();
+    unlock();
+    if( !z )
+    {
+        befehl = "INSERT INTO app_5_minigames_score( mauer, account_id ) VALUES( ";
+        befehl += score;
+        befehl += ", ";
+        befehl += account;
+        befehl += " )";
+        lock();
+        datenbank->befehl( befehl );
+        unlock();
+    }
+    calkGesamtScore( account );
+}
+
+void AppSDatenbank::calkGesamtScore( int account )
+{
+    Text befehl = "SELECT bloecke, mauer, farben, fangen, rennen FROM app_5_minigames_score WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+        return;
+    int gesamt = ( (int)res.values[ 0 ] + (int)res.values[ 1 ] + (int)res.values[ 2 ] + (int)res.values[ 3 ] + (int)res.values[ 4 ] ) / 5;
+    res.destroy();
+    befehl = "UPDATE app_5_minigames_score SET gesamt = ";
+    befehl += gesamt;
+    befehl += " WHERE account_id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    unlock();
+}
+
+int AppSDatenbank::pruefNeuAccount( const char *name, const char *eMail )
+{
+    Text *befehl = new Text( "SELECT account_neu_alt_check( '" );
+    Text n( name );
+    n.ersetzen( "'", "''" );
+    befehl->append( (char*)n );
+    befehl->append( "', '" );
+    Text m( eMail );
+    m.ersetzen( "'", "''" );
+    befehl->append( (char*)m );
+    befehl->append( "' )" );
+    lock();
+    datenbank->befehl( befehl->getText() );
+    Result res = datenbank->getResult();
+    unlock();
+    if( res.values[ 0 ].istGleich( "t" ) )
+    {
+        befehl->release();
+        res.destroy();
+        return 0;
+    }
+    else
+    {
+        res.destroy();
+        befehl->setText( "SELECT account.id FROM account, account_neu WHERE account.name = '" );
+        befehl->append( (char*)n );
+        befehl->append( "' OR account_neu.name = '" );
+        befehl->append( (char*)n );
+        befehl->append( "'" );
+        lock();
+        datenbank->befehl( befehl->getText() );
+        res = datenbank->getResult();
+        unlock();
+        if( res.zeilenAnzahl > 0 )
+        {
+            befehl->release();
+            res.destroy();
+            return 1;
+        }
+        else
+        {
+            res.destroy();
+            befehl->release();
+            return 2;
+        }
+    }
+}
+
+bool AppSDatenbank::neuAccount( const char *name, const char *pass, const char *geheim, const char *eMail, const char *gebDatum, InitDatei *zIni )
+{
+    Text *befehl = new Text( "INSERT INTO account_neu( name, passwort, geheimnis, e_mail, geb_datum ) VALUES ( '" );
+    Text n( name );
+    n.ersetzen( "'", "''" );
+    befehl->append( (char*)n );
+    befehl->append( "', '" );
+    Text p( pass );
+    p.ersetzen( "'", "''" );
+    befehl->append( (char*)p );
+    befehl->append( "', '" );
+    Text g( geheim );
+    g.ersetzen( "'", "''" );
+    befehl->append( (char*)g );
+    befehl->append( "', '" );
+    Text m( eMail );
+    m.ersetzen( "'", "''" );
+    befehl->append( (char*)m );
+    befehl->append( "', '" );
+    Text d( gebDatum );
+    d.ersetzen( "'", "''" );
+    befehl->append( (char*)d );
+    befehl->append( "' )" );
+    lock();
+    if( datenbank->befehl( befehl->getText() ) )
+    {
+        unlock();
+        befehl->setText( "SELECT schluessel FROM account_neu WHERE name = '" );
+        befehl->append( (char*)n );
+        befehl->append( "'" );
+        lock();
+        datenbank->befehl( befehl->getText() );
+        Result res = datenbank->getResult();
+        unlock();
+        Datei md;
+        if( res.zeilenAnzahl )
+        {
+            md.setDatei( res.values[ 0 ].getText() );
+            if( md.open( Datei::Style::schreiben ) )
+            {
+                Text txt = eMail;
+                txt += "\naccount activation\n Account Details:\n";
+                txt += "\r\nname: ";
+                txt += name;
+                txt += "\r\npassword: ";
+                txt += pass;
+                txt += "\r\nsecret: ";
+                txt += geheim;
+                txt += "\r\ndate of birth: ";
+                txt += gebDatum;
+                txt += "\r\nactivation key: ";
+                txt += res.values[ 0 ].getText();
+                md.schreibe( txt, txt.getLength() );
+                md.close();
+                // e_mail senden
+#ifdef WIN32
+                PROCESS_INFORMATION prozessinfo1;
+                STARTUPINFO startinfo1;
+                startinfo1.cb = sizeof( STARTUPINFOW );
+                ZeroMemory( &startinfo1, sizeof( STARTUPINFOW ) );
+                Text cmdl = zIni->zWert( "Java" )->getText();
+                cmdl += " Mailer ";
+                cmdl += res.values[ 0 ].getText();
+                if( CreateProcess( 0, cmdl, 0, 0, 0, 0, 0, 0, &startinfo1, &prozessinfo1 ) == 1 )
+                    CloseHandle( prozessinfo1.hThread );
+#else
+                pid_t pid;
+                char *pargs[] = { zIni->zWert( "Java" )->getText(), ( char* )"Mailer", res.values[ 0 ].getText(), (char*)0 };
+                posix_spawn( &pid, zIni->zWert( "Java" )->getText(), 0, 0, pargs, 0 );
+#endif
+            }
+        }
+        res.destroy();
+        befehl->release();
+        return 1;
+    }
+    unlock();
+    befehl->release();
+    return 0;
+}
+
+void AppSDatenbank::neuAccountAbbruch( const char *name )
+{
+    Text *befehl = new Text( "DELETE FROM account_neu WHERE name = '" );
+    Text n( name );
+    n.ersetzen( "'", "''" );
+    befehl->append( (char*)n );
+    befehl->append( "'" );
+    lock();
+    datenbank->befehl( befehl->getText() );
+    unlock();
+    befehl->release();
+}
+
+bool AppSDatenbank::aktiviereAccount( const char *name, const char *key )
+{
+    Text *befehl = new Text( "SELECT account_aktivieren( '" );
+    Text n( name );
+    n.ersetzen( "'", "''" );
+    befehl->append( (char*)n );
+    befehl->append( "', '" );
+    Text s( key );
+    s.ersetzen( "'", "''" );
+    befehl->append( (char*)s );
+    befehl->append( "' )" );
+    lock();
+    if( datenbank->befehl( befehl->getText() ) )
+    {
+        befehl->release();
+        Result res = datenbank->getResult();
+        unlock();
+        if( res.values[ 0 ].istGleich( "f" ) )
+        {
+            res.destroy();
+            return 0;
+        }
+        return 1;
+    }
+    unlock();
+    befehl->release();
+    return 0;
+}
+
+char AppSDatenbank::suchBestaetigung( const char *name, const char *pass )
+{
+    Text *befehl = new Text( "select such_account_bestaetigung( '" );
+    Text n( name );
+    n.ersetzen( "'", "''" );
+    befehl->append( (char*)n );
+    befehl->append( "', '" );
+    Text p( pass );
+    p.ersetzen( "'", "''" );
+    befehl->append( (char*)p );
+    befehl->append( "' )" );
+    lock();
+    datenbank->befehl( befehl->getText() );
+    Result res = datenbank->getResult();
+    unlock();
+    befehl->release();
+    char ret = (char)TextZuInt( res.values[ 0 ].getText(), 10 );
+    res.destroy();
+    return ret;
+}
+
+void AppSDatenbank::sendeErstellEMail( const char *name, InitDatei *zIni )
+{
+    Text *befehl = new Text( "SELECT passwort, geheimnis, e_mail, geb_datum, schluessel FROM account_neu WHERE name = '" );
+    Text n( name );
+    n.ersetzen( "'", "''" );
+    befehl->append( (char*)n );
+    befehl->append( "'" );
+    lock();
+    datenbank->befehl( befehl->getText() );
+    Result res = datenbank->getResult();
+    unlock();
+    befehl->release();
+    Datei md;
+    if( res.zeilenAnzahl )
+    {
+        md.setDatei( res.values[ 4 ].getText() );
+        if( md.open( Datei::Style::schreiben ) )
+        {
+            Text txt = res.values[ 2 ].getText();
+            txt += "\naccount activation\n Account Details:\n";
+            txt += "\r\nname: ";
+            txt += name;
+            txt += "\r\npassword: ";
+            txt += res.values[ 0 ].getText();
+            txt += "\r\nsecret: ";
+            txt += res.values[ 1 ].getText();
+            txt += "\r\ndate of birth: ";
+            txt += res.values[ 3 ].getText();
+            txt += "\r\nactivation key: ";
+            txt += res.values[ 4 ].getText();
+            md.schreibe( txt, txt.getLength() );
+            md.close();
+            // e_mail senden
+#ifdef WIN32
+            PROCESS_INFORMATION prozessinfo1;
+            STARTUPINFO startinfo1;
+            startinfo1.cb = sizeof( STARTUPINFOW );
+            ZeroMemory( &startinfo1, sizeof( STARTUPINFOW ) );
+            Text cmdl = zIni->zWert( "Java" )->getText();
+            cmdl += " Mailer ";
+            cmdl += res.values[ 4 ].getText();
+            if( CreateProcess( 0, cmdl, 0, 0, 0, 0, 0, 0, &startinfo1, &prozessinfo1 ) == 1 )
+                CloseHandle( prozessinfo1.hThread );
+#else
+            pid_t pid;
+            char *pargs[] = { zIni->zWert( "Java" )->getText(), ( char* )"Mailer", res.values[ 4 ].getText(), (char*)0 };
+            posix_spawn( &pid, zIni->zWert( "Java" )->getText(), 0, 0, pargs, 0 );
+#endif
+        }
+    }
+    res.destroy();
+}
+
+void AppSDatenbank::markballsFinish( int level, int sek, int account, char *device, int diff, int kupfer, int gId )
+{
+    if( !device && kupfer > 0 )
+    {
+        Text befehl = "UPDATE account SET kupfer = kupfer + ";
+        befehl += kupfer;
+        befehl += " WHERE id = ";
+        befehl += account;
+        lock();
+        datenbank->befehl( befehl );
+        unlock();
+    }
+    if( gId > 0 )
+    {
+        Text befehl = "SELECT markballs_gegenstand_id FROM markballs_gegenstand_account WHERE markballs_gegenstand_id = ";
+        befehl += gId;
+        befehl += " AND diff = ";
+        befehl += diff;
+        if( !device )
+        {
+            befehl += " AND account_id = ";
+            befehl += account;
+        }
+        else
+        {
+            befehl += " AND device = '";
+            befehl += device;
+            befehl += "'";
+        }
+        lock();
+        datenbank->befehl( befehl );
+        int rows = datenbank->getZeilenAnzahl();
+        unlock();
+        if( !rows )
+        {
+            befehl = "INSERT INTO markballs_gegenstand_account( account_id, device, markballs_gegenstand_id, diff ) VALUES( ";
+            if( !device )
+            {
+                befehl += account;
+                befehl += ", NULL, ";
+            }
+            else
+            {
+                befehl += "NULL, '";
+                befehl += device;
+                befehl += "', ";
+            }
+            befehl += gId;
+            befehl += ", ";
+            befehl += diff;
+            befehl += " )";
+            lock();
+            datenbank->befehl( befehl );
+            unlock();
+        }
+    }
+    Text befehl = "SELECT * FROM markballs WHERE level = ";
+    befehl += level;
+    befehl += " AND diff = ";
+    befehl += diff;
+    lock();
+    datenbank->befehl( befehl );
+    int rows = datenbank->getZeilenAnzahl();
+    unlock();
+    if( !rows )
+    {
+        befehl = "INSERT INTO markballs( level, diff ) VALUES( ";
+        befehl += level;
+        befehl += ", ";
+        befehl += diff;
+        befehl += " )";
+        lock();
+        datenbank->befehl( befehl );
+        unlock();
+    }
+    Text spalte = "verloren";
+    if( sek > 0 && sek <= 10 )
+        spalte = "s_1_10";
+    else if( sek > 10 && sek <= 20 )
+        spalte = "s_11_20";
+    else if( sek > 20 && sek <= 30 )
+        spalte = "s_21_30";
+    else if( sek > 30 && sek <= 40 )
+        spalte = "s_31_40";
+    else if( sek > 40 && sek <= 50 )
+        spalte = "s_41_50";
+    else if( sek > 50 && sek <= 60 )
+        spalte = "s_51_60";
+    else if( sek > 60 )
+        spalte = "more";
+    befehl = "UPDATE markballs SET ";
+    befehl += spalte.getText();
+    befehl += " = ";
+    befehl += spalte.getText();
+    befehl += " + 1, account_id = ";
+    if( account )
+        befehl += account;
+    else
+        befehl += "null";
+    befehl += ", device = ";
+    if( !device )
+        befehl += "null";
+    else
+    {
+        befehl += "'";
+        befehl += device;
+        befehl += "'";
+    }
+    befehl += ", best = ";
+    befehl += sek;
+    befehl += " WHERE level = ";
+    befehl += level;
+    befehl += " AND diff = ";
+    befehl += diff;
+    lock();
+    datenbank->befehl( befehl );
+    unlock();
+}
+
+int AppSDatenbank::getMarkballsScore( Array< int > *level, Array< int > *score, RCArray< Text > *name, int diff )
+{
+    Text befehl = "SELECT a.level, a.best, b.ruf_name from markballs a left join account b ON a.account_id = b.id WHERE a.diff = ";
+    befehl += diff;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    int ret = res.zeilenAnzahl;
+    for( int i = 0; i < ret; i++ )
+    {
+        level->set( res.values[ i * 3 ], i );
+        score->set( res.values[ i * 3 + 1 ], i );
+        name->set( new Text( res.values[ i * 3 + 2 ].getText() ), i );
+    }
+    res.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getMarkballsScore( Array< int > *level, Array< int > *score, int diff )
+{
+    Text befehl = "SELECT level, best from markballs WHERE diff = ";
+    befehl += diff;
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    int ret = res.zeilenAnzahl;
+    for( int i = 0; i < ret; i++ )
+    {
+        level->set( res.values[ i * 2 ], i );
+        score->set( res.values[ i * 2 + 1 ], i );
+    }
+    res.destroy();
+    return ret;
+}
+
+void AppSDatenbank::deviceAccount( char *device, int account )
+{
+    Text befehl = "UPDATE markballs SET account_id = ";
+    befehl += account;
+    befehl += ", device = null WHERE account_id IS NULL AND device = '";
+    befehl += device;
+    befehl += "'";
+    lock();
+    datenbank->befehl( befehl );
+    unlock();
+    befehl = "SELECT app_device_to_account( '";
+    befehl += device;
+    befehl += "', ";
+    befehl += account;
+    befehl += " )";
+    lock();
+    datenbank->befehl( befehl );
+    unlock();
+    befehl = "UPDATE markballs_fortschritt SET account_id = ";
+    befehl += account;
+    befehl += ", device = null WHERE account_id IS NULL AND device = '";
+    befehl += device;
+    befehl += "'";
+    lock();
+    datenbank->befehl( befehl );
+    unlock();
+    befehl = "UPDATE markballs_gegenstand_account SET account_id = ";
+    befehl += account;
+    befehl += ", device = null WHERE account_id IS NULL AND device = '";
+    befehl += device;
+    befehl += "'";
+    lock();
+    datenbank->befehl( befehl );
+    unlock();
+}
+
+int AppSDatenbank::getGegenstaende( int accountId, char *device, Array< int > *gId, Array< int > *diff )
+{
+    Text befehl = "SELECT markballs_gegenstand_id, diff FROM markballs_gegenstand_account WHERE ";
+    if( !device )
+    {
+        befehl += " account_id = ";
+        befehl += accountId;
+    }
+    else
+    {
+        befehl += " device = '";
+        befehl += device;
+        befehl += "'";
+    }
+    lock();
+    datenbank->befehl( befehl );
+    Result r = datenbank->getResult();
+    unlock();
+    if( !r.zeilenAnzahl )
+    {
+        r.destroy();
+        return 0;
+    }
+    for( int i = 0; i < r.zeilenAnzahl; i++ )
+    {
+        gId->add( (int)r.values[ i * 2 ] );
+        diff->add( (int)r.values[ i * 2 + 1 ] );
+    }
+    int ret = r.zeilenAnzahl;
+    r.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getKupfer( int accountId )
+{
+    Text befehl = "SELECT kupfer FROM account WHERE id = ";
+    befehl += accountId;
+    lock();
+    datenbank->befehl( befehl );
+    Result r = datenbank->getResult();
+    unlock();
+    int ret = r.zeilenAnzahl ? (int)r.values[ 0 ] : 0;
+    r.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getMarkballsFortschritt( int accountId, char *device, Array< int > *f )
+{
+    Text befehl = "SELECT level, diff FROM markballs_fortschritt WHERE ";
+    if( !device )
+    {
+        befehl += " account_id = ";
+        befehl += accountId;
+    }
+    else
+    {
+        befehl += " device = '";
+        befehl += device;
+        befehl += "'";
+    }
+    befehl += " ORDER BY diff";
+    lock();
+    datenbank->befehl( befehl );
+    Result r = datenbank->getResult();
+    unlock();
+    int anz = 0;
+    int lastDiff = 0;
+    for( int i = 0; i < r.zeilenAnzahl; i++, anz++ )
+    {
+        int l = (int)r.values[ i * 2 ];
+        int d = (int)r.values[ i * 2 + 1 ];
+        for( int j = lastDiff + 1; j < d; j++, anz++ )
+            f->add( 0 );
+        f->add( l );
+        lastDiff = d;
+    }
+    r.destroy();
+    return anz;
+}
+
+void AppSDatenbank::curvesnakeFinish( int score, int accId, char *device, int map, int kupfer )
+{
+    Text befehl = "SELECT id FROM curvesnake WHERE map = ";
+    befehl += map;
+    lock();
+    datenbank->befehl( befehl );
+    int anz = datenbank->getZeilenAnzahl();
+    unlock();
+    if( !anz )
+    {
+        befehl = "INSERT INTO curvesnake( map, score ) VALUES( ";
+        befehl += map;
+        befehl += ", 0 )";
+        lock();
+        datenbank->befehl( befehl );
+        unlock();
+    }
+    befehl = "UPDATE curvesnake SET score = ";
+    befehl += score;
+    if( device )
+    {
+        befehl += ", device = '";
+        befehl += device;
+        befehl += "'";
+    }
+    else
+    {
+        befehl += ", account_id = ";
+        befehl += accId;
+    }
+    befehl += " WHERE map = ";
+    befehl += map;
+    lock();
+    datenbank->befehl( befehl );
+    unlock();
+    if( !device && kupfer )
+    {
+        befehl = "UPDATE account SET kupfer = kupfer + ";
+        befehl += kupfer;
+        befehl += " WHERE id = ";
+        befehl += accId;
+        lock();
+        datenbank->befehl( befehl );
+        unlock();
+    }
+}
+
+int AppSDatenbank::getCurvesnakeScore( Array< int > *map, Array< int > *score )
+{
+    lock();
+    datenbank->befehl( "SELECT map, score from curvesnake ORDER BY map" );
+    Result r = datenbank->getResult();
+    unlock();
+    for( int i = 0; i < r.zeilenAnzahl; i++ )
+    {
+        map->add( r.values[ i * 2 ] );
+        score->add( r.values[ i * 2 + 1 ] );
+    }
+    int ret = r.zeilenAnzahl;
+    r.destroy();
+    return ret;
+}
+
+int AppSDatenbank::getCurvesnakeMapList( Array< int > *map, int account )
+{
+    Text befehl = "SELECT id from curvesnake_map WHERE preis = 0 ";
+    if( account )
+    {
+        befehl += "UNION SELECT map_id FROM curvesnake_map_account WHERE account_id = ";
+        befehl += account;
+    }
+    lock();
+    datenbank->befehl( befehl );
+    Result r = datenbank->getResult();
+    unlock();
+    for( int i = 0; i < r.zeilenAnzahl; i++ )
+        map->add( r.values[ i ] );
+    int ret = r.zeilenAnzahl;
+    r.destroy();
+    return ret;
+}
+
+void AppSDatenbank::addKupfer( int account, int kupfer )
+{
+    Text befehl = "UPDATE account SET kupfer = kupfer + ";
+    befehl += kupfer;
+    befehl += " WHERE id = ";
+    befehl += account;
+    lock();
+    datenbank->befehl( befehl );
+    unlock();
+}
+
+bool AppSDatenbank::getFreeAds( int account )
+{
+    Text befehl = "SELECT get_account_free_ad( ";
+    befehl += account;
+    befehl += " )";
+    lock();
+    datenbank->befehl( befehl );
+    Result r = datenbank->getResult();
+    unlock();
+    if( r.zeilenAnzahl < 1 )
+    {
+        r.destroy();
+        return 0;
+    }
+    bool ret = r.values[ 0 ].istGleich( "t" );
+    r.destroy();
+    return ret;
+}
+
+// Reference Counting
+AppSDatenbank *AppSDatenbank::getThis()
+{
+    ref++;
+    return this;
+}
+
+AppSDatenbank *AppSDatenbank::release()
+{
+    ref--;
+    if( !ref )
+        delete this;
+    return 0;
+}

+ 80 - 0
AppServer/Datenbank.h

@@ -0,0 +1,80 @@
+#ifndef Datenbank_H
+#define Datenbank_H
+
+#include <sql.h>
+#include <Text.h>
+#include <InitDatei.h>
+
+using namespace Framework;
+using namespace sql;
+
+namespace Admin_Recht
+{
+    const int AppSStarten = 62;
+    const int AppSBeenden = 63;
+}
+
+class AppSDatenbank
+{
+private:
+    Datenbank *datenbank;
+    CRITICAL_SECTION ths;
+    int ref;
+
+public:
+    // Konstruktor
+    AppSDatenbank( InitDatei *zDat );
+    // Detruktor
+    ~AppSDatenbank();
+    // nicht constant
+    void lock();
+    void unlock();
+    int istAdministrator( const char *name, const char *passwort );
+    bool adminHatRecht( int id, int recht );
+    Text *getKey();
+    int login( char *name, char *passwort );
+    bool istNeu( int account );
+    int getWeltBloeckeScore( int anz, Array< int > *score, RCArray< Text > *namen );
+    int getWeltMauerScore( int anz, Array< int > *score, RCArray< Text > *namen );
+    int getWeltFarbenScore( int anz, Array< int > *score, RCArray< Text > *namen );
+    int getWeltFangenScore( int anz, Array< int > *score, RCArray< Text > *namen );
+    int getWeltRennenScore( int anz, Array< int > *score, RCArray< Text > *namen );
+    int getWeltGesamtScore( int anz, Array< int > *score, RCArray< Text > *namen );
+    int getBloeckeScore( int account );
+    int getMauerScore( int account );
+    int getMauerZeit( int account, int level );
+    int getFarbenScore( int account );
+    int getFangenScore( int account );
+    int getRennenScore( int account );
+    int getGesamtScore( int account );
+    void setBloeckeScore( int account, int score );
+    void setFarbenScore( int account, int score );
+    void setFangenScore( int account, int score );
+    void setRennenScore( int account, int score );
+    void setMauerZeit( int account, int level, int zeit );
+    void calkMauerScore( int account );
+    void calkGesamtScore( int account );
+    int pruefNeuAccount( const char *name, const char *eMail );
+    bool neuAccount( const char *name, const char *pass, const char *geheim, const char *eMail, const char *gebDatum, InitDatei *zIni );
+    void neuAccountAbbruch( const char *name );
+    bool aktiviereAccount( const char *name, const char *key );
+    char suchBestaetigung( const char *name, const char *pass );
+    void sendeErstellEMail( const char *name, InitDatei *zIni );
+    void markballsFinish( int level, int sek, int account, char *device, int diff, int kupfer, int gId );
+    int getMarkballsScore( Array< int > *level, Array< int > *score, RCArray< Text > *name, int diff );
+    int getMarkballsScore( Array< int > *level, Array< int > *score, int diff );
+    void deviceAccount( char *device, int account );
+    int getGegenstaende( int accountId, char *device, Array< int > *gId, Array< int > *diff );
+    int getKupfer( int accountId );
+    int getMarkballsFortschritt( int accountId, char *device, Array< int > *f );
+    void curvesnakeFinish( int score, int accId, char *device, int map, int kupfer );
+    int getCurvesnakeScore( Array< int > *map, Array< int > *score );
+    int getCurvesnakeMapList( Array< int > *map, int account );
+    void addKupfer( int account, int kupfer );
+    bool getFreeAds( int account );
+    // Reference Counting
+    AppSDatenbank *getThis();
+    AppSDatenbank *release();
+};
+
+#endif

+ 58 - 0
AppServer/main.cpp

@@ -0,0 +1,58 @@
+#include "AppServer.h"
+#include <iostream>
+#include <fstream>
+#include <Zeit.h>
+#include <Datei.h>
+#include <Text.h>
+#include <Globals.h>
+
+int main()
+{
+	Framework::initFramework();
+	chdir( "/test/app" );
+	Zeit *z = getZeit();
+	Text *pfad = new Text( "../log/app/" );
+	pfad->append( z->getZeit( "y-m-d h-i-s.log" ) );
+	z->release();
+	DateiPfadErstellen( pfad->getThis() );
+	std::ofstream file;
+	file.open( pfad->getText() );
+	std::streambuf* sbuf = std::cout.rdbuf();
+	std::cout.rdbuf( file.rdbuf() );
+	pfad->release();
+
+	std::cout << "AppS: Startet...\n";
+	std::cout << "AppS: Lese init Datei ../data/apsInit.ini ...\n";
+
+	InitDatei *dat = new InitDatei( "../data/apsInit.ini" );
+	if( !dat->laden() )
+	{
+		std::cout << "AppS: error: Datei konnte nicht gelesen werden. Das Programm wird geschlossen.\n";
+		dat->release();
+		exit( 1 );
+	}
+	const char *wichtig[] = { "ServerId", "DBBenutzer", "DBPasswort", "DBName", "DBIP", "DBPort", "DataPfad", "Java", "Mailer", "Aktive" };
+	for( const char *w : wichtig )
+	{
+		if( !dat->wertExistiert( w ) )
+		{
+			std::cout << "AppS: error: Der Wert '" << w << "' wurde nicht gefunden. Das Programm wird geschlossen.\n";
+			dat->release();
+			exit( 1 );
+		}
+	}
+
+	AppServer *appServer = new AppServer( dat );
+
+	std::cout << "AppS: Der Admin Server läuft. Startforgang beendet.\n";
+	appServer->runn();
+
+	appServer->ende();
+	appServer->release();
+	dat->release();
+	std::cout << "AppS: Der Server ist heruntergefahren.\n";
+	file.close();
+	std::cout.rdbuf( sbuf );
+	Framework::releaseFramework();
+	return 0;
+}

+ 2 - 0
build.bat

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