#include "PatchServer.h" #include #include #include // Inhalt der PatchServer Klasse aus PatchServer.h // Konstruktor PatchServer::PatchServer(InitDatei* zIni) : Thread() { Network::Start(100); std::cout << "PS: Verbindung mit Datenbank wird hergestellt...\n"; db = new PSDatenbank(zIni); klients = new RCArray< PSKlient >(); empfangen = 0; gesendet = 0; fehler = new Text(); ini = dynamic_cast(zIni->getThis()); id = (int)*zIni->zWert("ServerId"); Text* dgInitPfad = new Text(ini->zWert("SystemPfad")->getText()); dgInitPfad->append("/datei_gruppe.ini"); InitDatei* dgInit = new InitDatei(dgInitPfad); dgInit->laden(); for (int i = 0; i < dgInit->getWertAnzahl(); i++) db->setDateiGruppe(id, TextZuInt(dgInit->zName(i)->getText(), 10), (int)TextZuInt(dgInit->zWert(i)->getText(), 10)); dgInit->release(); server = new Server(); aServer = new SSLServer(); aServer->setPrivateKeyPassword(zIni->zWert("SSLPasswort")->getText()); aServer->setCertificateFile(zIni->zWert("SSLCert")->getText()); aServer->setPrivateKeyFile(zIni->zWert("SSLKey")->getText()); std::cout << "PS: Starten des Admin Servers...\n"; if (!aServer->verbinde((unsigned short)TextZuInt(ini->zWert("AdminServerPort")->getText(), 10), 10)) { std::cout << "PS: Der Admin Server konnte nicht gestartet werden. Das Programm wird beendet.\n"; exit(1); } db->setServerStatus(id, 2); end = 0; nichtPausiert = 0; InitializeCriticalSection(&cs); updateAnzahl = 0; updateGruppe = new Array< int >(); if (zIni->zWert("Aktiv")->istGleich("TRUE")) { serverStarten(); serverFortsetzen(); } } // Destruktor PatchServer::~PatchServer() { fehler->release(); server->trenne(); server->release(); aServer->trenne(); aServer->release(); if (klients) klients->release(); ini->release(); db->release(); updateGruppe->release(); DeleteCriticalSection(&cs); } // nicht constant void PatchServer::runn() { while (!end && aServer->isConnected()) { SSLSKlient* klient; klient = aServer->getKlient(); if (end && klient) { klient->trenne(); klient = (SSLSKlient*)klient->release(); Sleep(1000); return; } if (!klient) continue; PSAKlient* clHandle = new PSAKlient(klient, dynamic_cast(getThis()), dynamic_cast(ini->getThis())); clHandle->start(); } } void PatchServer::thread() { while (server->isConnected()) { SKlient* klient; klient = server->getKlient(); if (!klient) continue; Framework::getThreadRegister()->cleanUpClosedThreads(); PSKlient* clHandle = new PSKlient(klient, dynamic_cast(getThis()), dynamic_cast(ini->getThis())); EnterCriticalSection(&cs); klients->add(clHandle); LeaveCriticalSection(&cs); clHandle->start(); } } void PatchServer::close() { db->setServerStatus(id, 1); server->trenne(); #ifdef WIN32 warteAufThread(1000); #endif EnterCriticalSection(&cs); for (int i = 0; i < klients->getEintragAnzahl(); i++) klients->z(i)->absturz(); klients = (RCArray*) klients->release(); LeaveCriticalSection(&cs); ende(); run = 0; end = 1; Klient* klient = new Klient(); klient->verbinde(aServer->getPort(), "127.0.0.1"); Sleep(500); aServer->trenne(); klient->release(); } bool PatchServer::serverStarten() { if (nichtPausiert) { fehler->setText("Der Server konnte nicht gestartet werden: Der Server läuft bereits."); return 0; } if (server) server->release(); server = new Server(); if (server->verbinde((unsigned short)TextZuInt(ini->zWert("ServerPort")->getText(), 10), 10)) { nichtPausiert = 1; start(); return 1; } else { serverBeenden(); fehler->setText("Der Server konnte nicht gestartet werden: Eventuell ist der Port in benutzung."); return 0; } } bool PatchServer::serverPause() { if (!nichtPausiert) { fehler->setText("Der Server konnte nicht pausiert werden: Der Server läuft nicht."); return 0; } if (!db->setServerStatus(id, 2)) { fehler->setText("Der Server konnte nicht pausiert werden: "); fehler->append(db->getLetzterFehler()); return 0; } return 1; } bool PatchServer::serverFortsetzen() { if (!nichtPausiert) { fehler->setText("Der Server konnte nicht fortgesetzt werden: Der Server läuft nicht."); return 0; } if (!db->setServerStatus(id, 3)) { fehler->setText("Der Server konnte nicht fortgesetzt werden: "); fehler->append(db->getLetzterFehler()); return 0; } return 1; } bool PatchServer::serverBeenden() { if (!nichtPausiert) { fehler->setText("Der Server konnte nicht beendet werden: Der Server läuft nicht."); return 0; } if (db->serverIstNichtPausiert(id)) { fehler->setText("Der Server konnte nicht beendet werden: Der Server muss erst pausiert werden."); return 0; } nichtPausiert = 0; ende(); if (server) server->trenne(); return 1; } bool PatchServer::setMaxKlients(int mc) { if (!db->setMaxClients(id, mc)) { fehler->setText("Die maximale Anzahl der Clients konnte nicht gesetzt werden:\n"); fehler->append(db->getLetzterFehler()); return 0; } ini->setWert("MaxClients", Text() += mc); return 1; } bool PatchServer::absturzKlient(int klientId) { bool gefunden = 0; EnterCriticalSection(&cs); for (int i = 0; i < klients->getEintragAnzahl(); i++) { if (klients->z(i)->getKlientNummer() == klientId) { klients->z(i)->absturz(); klients->remove(i); gefunden = 1; break; } } LeaveCriticalSection(&cs); return gefunden; } bool PatchServer::removeKlient(PSKlient* zKlient) { bool gefunden = 0; EnterCriticalSection(&cs); for (int i = 0; i < klients->getEintragAnzahl(); i++) { if (klients->z(i) == zKlient) { klients->remove(i); gefunden = 1; break; } } LeaveCriticalSection(&cs); return gefunden; } void PatchServer::addGesendet(int bytes) { gesendet += bytes; } void PatchServer::addEmpfangen(int bytes) { empfangen += bytes; } bool PatchServer::beginnUpdate(int gruppe) { bool update = 0; for (int i = 0; i < updateAnzahl; i++) { if (updateGruppe->get(i) == gruppe) { update = 1; break; } } if (update || proveVersion(gruppe)) return 0; if (!db->supportedDateiGruppe(id, gruppe)) { db->setDateiGruppe(id, gruppe, 0); } if (!db->setDateiGruppe(id, gruppe, true)) return 0; Text* gruppeN = db->getDateiGruppeName(gruppe); if (!gruppeN) return 0; Result systemT = db->getSystemListe(); for (int i = 0; i < systemT.zeilenAnzahl; i++) { Text* pfad = new Text(ini->zWert("SystemPfad")->getText()); pfad->append("/"); pfad->append(gruppeN->getText()); pfad->append("/"); pfad->append(systemT.values[i * 2 + 1].getText()); pfad->append("/version.ini"); InitDatei* vIni = new InitDatei(pfad->getText()); vIni->laden(); pfad->remove(pfad->getLength() - 11, pfad->getLength()); Result dateiT = db->getDeletedFiles(TextZuInt(systemT.values[i * 2].getText(), 10), gruppe); for (int j = 0; j < dateiT.zeilenAnzahl; j++) { if (vIni->wertExistiert(dateiT.values[j].getText())) { Text* pf = new Text(pfad->getText()); pf->append(dateiT.values[j].getText()); DateiRemove(pf); vIni->removeWert(dateiT.values[j].getText()); } } dateiT.destroy(); DateiPfadErstellen(vIni->getPfad()); vIni->speichern(); vIni->release(); pfad->release(); } gruppeN->release(); systemT.destroy(); return 1; } void PatchServer::endUpdate(int gruppe) { Text* dgInitPfad = new Text(ini->zWert("SystemPfad")->getText()); dgInitPfad->append("/datei_gruppe.ini"); InitDatei* dgInit = new InitDatei(dgInitPfad); dgInit->laden(); Text* gT = new Text(); gT->append(gruppe); Text* vT = new Text(); vT->append(db->getDateiGruppeVersion(gruppe)); if (!dgInit->wertExistiert(gT->getText())) dgInit->addWert(gT->getText(), vT->getText()); else dgInit->setWert(gT->getText(), vT->getText()); gT->release(); vT->release(); dgInit->speichern(); dgInit->release(); db->dateiGruppeUpdateFertig(id, gruppe); for (int i = 0; i < updateAnzahl; i++) { if (updateGruppe->get(i) == gruppe) { updateAnzahl--; updateGruppe->remove(i); break; } } } void PatchServer::updateAbbruch(int gruppe) { db->setDateiGruppe(id, gruppe, (bool)0); for (int i = 0; i < updateAnzahl; i++) { if (updateGruppe->get(i) == gruppe) { updateAnzahl--; updateGruppe->remove(i); break; } } } // constant bool PatchServer::istAn() const { return db->serverIstNichtPausiert(id); } Server* PatchServer::zServer() const { return server; } PSDatenbank* PatchServer::zDB() const { return db; } bool PatchServer::hatClients() const { return klients->hat(0); } int PatchServer::getId() const { return id; } const char* PatchServer::getLetzterFehler() const { return fehler->getText(); } bool PatchServer::proveVersion(int gruppe) const { Result systemT = db->getSystemListe(); for (int i = 0; i < systemT.zeilenAnzahl; i++) { int system = TextZuInt(systemT.values[i * 2].getText(), 10); Result dateiT = db->getDateiListeOhneOrdner(system, gruppe); Text* gruppeN = db->getDateiGruppeName(gruppe); if (!gruppeN) continue; Text* pfad = new Text(ini->zWert("SystemPfad")->getText()); pfad->append("/"); pfad->append(gruppeN); pfad->append("/"); pfad->append(systemT.values[i * 2 + 1].getText()); pfad->append("/version.ini"); InitDatei* vIni = new InitDatei(pfad); vIni->laden(); int dAnz = vIni->getWertAnzahl(); if (dAnz != dateiT.zeilenAnzahl) // nicht aktuell { systemT.destroy(); dateiT.destroy(); vIni->release(); return 0; } for (int j = 0; j < dAnz; j++) { if (!vIni->wertExistiert(dateiT.values[j * 2].getText())) // nicht aktuell { systemT.destroy(); dateiT.destroy(); vIni->release(); return 0; } if (!vIni->zWert(dateiT.values[j * 2].getText())->istGleich(dateiT.values[j * 2 + 1].getText())) // nicht aktuell { systemT.destroy(); dateiT.destroy(); vIni->release(); return 0; } } dateiT.destroy(); dateiT = db->getDeletedFiles(system, gruppe); for (int j = 0; j < dateiT.zeilenAnzahl; j++) { if (vIni->wertExistiert(dateiT.values[j].getText())) // nicht aktuell { systemT.destroy(); dateiT.destroy(); vIni->release(); return 0; } } dateiT.destroy(); vIni->release(); } systemT.destroy(); return 1; } bool PatchServer::proveVersion() const { Result gruppeT = db->getGruppeIds(); for (int g = 0; g < gruppeT.zeilenAnzahl; g++) { int gruppe = TextZuInt(gruppeT.values[g].getText(), 10); Result systemT = db->getSystemListe(); for (int i = 0; i < systemT.zeilenAnzahl; i++) { int system = TextZuInt(systemT.values[i * 2].getText(), 10); Result dateiT = db->getDateiListeOhneOrdner(system, gruppe); Text* gruppeN = db->getDateiGruppeName(gruppe); if (!gruppeN) continue; Text* pfad = new Text(ini->zWert("SystemPfad")->getText()); pfad->append("/"); pfad->append(gruppeN); pfad->append("/"); pfad->append(systemT.values[i * 2 + 1].getText()); pfad->append("/version.ini"); InitDatei* vIni = new InitDatei(pfad); vIni->laden(); int dAnz = vIni->getWertAnzahl(); if (dAnz != dateiT.zeilenAnzahl) // nicht aktuell { gruppeT.destroy(); systemT.destroy(); dateiT.destroy(); vIni->release(); return 0; } for (int j = 0; j < dAnz; j++) { if (!vIni->wertExistiert(dateiT.values[j * 2].getText())) // nicht aktuell { gruppeT.destroy(); systemT.destroy(); dateiT.destroy(); vIni->release(); return 0; } if (!vIni->zWert(dateiT.values[j * 2].getText())->istGleich(dateiT.values[j * 2 + 1].getText())) // nicht aktuell { gruppeT.destroy(); systemT.destroy(); dateiT.destroy(); vIni->release(); return 0; } } dateiT.destroy(); dateiT = db->getDeletedFiles(system, gruppe); for (int j = 0; j < dateiT.zeilenAnzahl; j++) { if (vIni->wertExistiert(dateiT.values[j].getText())) // nicht aktuell { gruppeT.destroy(); systemT.destroy(); dateiT.destroy(); vIni->release(); return 0; } Text tmp = vIni->zPfad()->getText(); tmp.remove("version.ini"); tmp += dateiT.values[j].getText(); if (DateiExistiert(tmp)) // nicht aktuell { gruppeT.destroy(); systemT.destroy(); dateiT.destroy(); vIni->release(); return 0; } } dateiT.destroy(); vIni->release(); } systemT.destroy(); } gruppeT.destroy(); return 1; } // Inhalt der PSAKlient Klasse aus PatchServer.h // Konstruktor PSAKlient::PSAKlient(SSLSKlient* klient, PatchServer* ps, InitDatei* ini) : Thread() { this->klient = klient; name = new Text(""); passwort = new Text(""); adminId = 0; updateGruppe = 0; gruppeN = 0; this->ps = ps; this->ini = ini; } // Destruktor PSAKlient::~PSAKlient() { klient->trenne(); klient->release(); ps->release(); name->release(); passwort->release(); ini->release(); if (gruppeN) gruppeN->release(); } // nicht constant void PSAKlient::thread() { while (1) { char c = 0; if (!klient->getNachricht(&c, 1)) break; else { bool br = 0; switch (c) { case 1: // Login if (1) { klient->sende("\1", 1); unsigned char len = 0; klient->getNachricht((char*)&len, 1); char* n = new char[len + 1]; n[(int)len] = 0; if (len) klient->getNachricht(n, len); unsigned char pLen = 0; klient->getNachricht((char*)&pLen, 1); char* p = new char[pLen + 1]; p[(int)pLen] = 0; if (pLen) klient->getNachricht(p, pLen); int adminId = ps->zDB()->istAdministrator(n, p); if (adminId) { klient->sende("\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->sende("\1", 1); break; case 3: // Trennen br = 1; klient->sende("\1", 1); break; case 4: // Server starten if (!adminId) errorZuKlient("Du musst dich einloggen."); else { if (ps->zDB()->adminHatRecht(adminId, Admin_Recht::PSStarten)) { if (!ps->serverStarten()) { Text* err = new Text(); err->append(ps->getLetzterFehler()); errorZuKlient(err->getText()); err->release(); } else klient->sende("\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 (ps->zDB()->adminHatRecht(adminId, Admin_Recht::PSBeenden)) { if (ps->serverBeenden()) klient->sende("\1", 1); else { Text* err = new Text(); err->append(ps->getLetzterFehler()); errorZuKlient(err->getText()); err->release(); } } else errorZuKlient("Du bist nicht berechtigt den Server zu beenden."); } break; case 6: // Programm Schließen if (!adminId) errorZuKlient("Du musst dich einloggen."); else { bool ok = 0; if (ps->isRunning()) { if (ps->zDB()->adminHatRecht(adminId, Admin_Recht::PSBeenden)) { if (ps->serverBeenden()) ok = 1; else { Text* err = new Text(); err->append(ps->getLetzterFehler()); errorZuKlient(err->getText()); err->release(); } } else errorZuKlient("Du bist nicht berechtigt den Server zu beenden."); } else ok = 1; if (ok && ps->hatClients()) { errorZuKlient("Es sind noch Klients Online. Bitte versuche es später erneut."); break; } if (ok) { klient->sende("\1", 1); std::cout << "PS: Der Server wird von Benutzer " << adminId << " heruntergefahren.\n"; ps->close(); br = 1; } } break; case 7: // Progtamm abstürzen if (!adminId) errorZuKlient("Du musst dich einloggen."); else { bool ok = 0; if (ps->isRunning()) { if (ps->zDB()->adminHatRecht(adminId, Admin_Recht::PSBeenden)) { ps->serverBeenden(); ok = 1; } else errorZuKlient("Du bist nicht berechtigt den Server zu beenden."); } else ok = 1; if (ok) { klient->sende("\1", 1); std::cout << "PS: Der Server wurde von Benutzer " << adminId << " terminiert.\n"; ps->close(); br = 1; } } break; case 8: // Status Frage if (1) { char status = 0; if (ps->isRunning()) { status = 1; if (ps->istAn()) status = 2; } if (!ps->proveVersion()) status = 3; klient->sende("\1", 1); klient->sende(&status, 1); } break; case 9: // Server pausieren if (!adminId) errorZuKlient("Du musst dich einloggen."); else { klient->sende("\1", 1); char pause = 0; klient->getNachricht(&pause, 1); if (ps->zDB()->adminHatRecht(adminId, Admin_Recht::PSPausieren)) { bool ok = 0; if (pause) ok = ps->serverPause(); else ok = ps->serverFortsetzen(); if (ok) klient->sende("\1", 1); else { Text* err = new Text(); err->append(ps->getLetzterFehler()); errorZuKlient(err->getText()); err->release(); } } else { if (pause) errorZuKlient("Du bist nicht berechtigt den Server zu pausieren."); else errorZuKlient("Du bist nicht berechtigt den Server fortzusetzen."); } } break; case 0xA: // maximale Anzahl der Clients setzen if (!adminId) errorZuKlient("Du musst dich einloggen."); else { klient->sende("\1", 1); int maxC = 0; klient->getNachricht((char*)&maxC, 4); if (ps->zDB()->adminHatRecht(adminId, Admin_Recht::PSMCChange)) { if (ps->setMaxKlients(maxC)) klient->sende("\1", 1); else { Text* err = new Text(); err->append(ps->getLetzterFehler()); errorZuKlient(err->getText()); err->release(); } } else errorZuKlient("Du bist nicht berechtigt die maximale Anzahl der Clients zu verändern."); } break; case 0xB: // frage nach geänderten Dateien if (!adminId) { errorZuKlient("Du musst dich einloggen."); break; } if (updateGruppe) { klient->sende("\1", 1); Result systemT = ps->zDB()->getSystemListe(); for (int i = 0; i < systemT.zeilenAnzahl; i++) { int len = systemT.values[i * 2 + 1].getLength(); klient->sende((char*)&len, 4); klient->sende(systemT.values[i * 2 + 1].getText(), len); Result dateiT = ps->zDB()->getDateiListeOhneOrdner(TextZuInt(systemT.values[i * 2].getText(), 10), updateGruppe); Text* pfad = new Text(ini->zWert("SystemPfad")->getText()); pfad->append("/"); pfad->append(gruppeN->getText()); pfad->append("/"); pfad->append(systemT.values[i * 2 + 1].getText()); pfad->append("/version.ini"); InitDatei* vIni = new InitDatei(pfad); vIni->laden(); for (int j = 0; j < dateiT.zeilenAnzahl; j++) { bool veraltet = 0; if (!vIni->wertExistiert(dateiT.values[j * 2].getText())) veraltet = 1; if (!veraltet && !vIni->zWert(dateiT.values[j * 2].getText())->istGleich(dateiT.values[j * 2 + 1].getText())) veraltet = 1; if (veraltet) { int len = dateiT.values[j * 2].getLength(); klient->sende((char*)&len, 4); klient->sende(dateiT.values[j * 2].getText(), len); } } klient->sende("\0\0\0\0", 4); dateiT.destroy(); vIni->release(); } klient->sende("\0\0\0\0", 4); systemT.destroy(); } else errorZuKlient("Du musst zunächst den Aktualisierungsvorgang starten."); break; case 0xC: // Update Beendet if (!adminId) errorZuKlient("Du musst dich einloggen."); else { if (!updateGruppe) { errorZuKlient("Du musst zunächst den Aktualisierungsvorgang starten."); break; } ps->endUpdate(updateGruppe); updateGruppe = 0; if (gruppeN) gruppeN = (Text*)gruppeN->release(); std::cout << "PS: Update erfolgreich abgeschlossen.\n"; klient->sende("\1", 1); } break; case 0xD: // Update Vorgang starten if (!adminId) errorZuKlient("Du musst dich einloggen."); else { if (updateGruppe) { errorZuKlient("Du musst die Aktualisierung erst beenden."); break; } klient->sende("\1", 1); int dg = 0; klient->getNachricht((char*)&dg, 4); gruppeN = ps->zDB()->getDateiGruppeName(dg); if (!gruppeN) { updateGruppe = 0; errorZuKlient("Die Dateigruppe existiert nicht."); break; } if (!ps->proveVersion()) { if (ps->zDB()->adminHatRecht(adminId, Admin_Recht::KSGCUpdate)) { if (ps->beginnUpdate(dg)) { klient->sende("\1", 1); std::cout << "PS: Die Dateigruppe " << dg << " wird von Benutzer " << adminId << " geupdatet.\n"; updateGruppe = dg; } else errorZuKlient("Es läuft bereits eine andere Aktualisierung."); } else errorZuKlient("Die Version ist bereits aktuel."); } else errorZuKlient("Dir fehlt die Berechtigung für diesen Vorgang."); } break; case 0xE: // Datei übertragen if (!adminId) errorZuKlient("Du musst dich einloggen."); else { if (!updateGruppe) { errorZuKlient("Du musst zunächst den Aktualisierungsvorgang starten."); break; } klient->sende("\1", 1); int system = 0; klient->getNachricht((char*)&system, 4); int version = 0; klient->getNachricht((char*)&version, 4); Text* sName = ps->zDB()->getSystemName(system); unsigned short len = 0; klient->getNachricht((char*)&len, 2); char* pfad = new char[len + 1]; pfad[len] = 0; if (len) klient->getNachricht(pfad, len); if (!len || !sName) { errorZuKlient("Die Datei konnte nicht angelegt werden."); delete[] pfad; if (sName) sName->release(); break; } Text* pf = new Text(ini->zWert("SystemPfad")->getText()); pf->append("/"); pf->append(gruppeN->getText()); pf->append("/"); pf->append(sName->getText()); sName->release(); pf->append("/version.ini"); InitDatei* vIni = new InitDatei(pf->getText()); vIni->laden(); pf->remove(pf->getLength() - 11, pf->getLength()); pf->append(pfad); Datei* d = new Datei(); d->setDatei(pf); d->erstellen(); if (d->open(Datei::Style::schreiben)) { klient->sende("\1", 1); klient->getNachricht((char*)&len, 2); while (len) { char* buff = new char[len]; klient->getNachricht(buff, len); d->schreibe(buff, len); delete[] buff; klient->getNachricht((char*)&len, 2); ps->addEmpfangen(klient->getDownloadBytes(1)); ps->addGesendet(klient->getUploadBytes(1)); } klient->sende("\1", 1); Text* vT = new Text(); vT->append(version); if (!vIni->wertExistiert(pfad)) vIni->addWert(pfad, vT->getText()); else vIni->setWert(pfad, vT->getText()); vIni->speichern(); vT->release(); } else errorZuKlient("Die Datei konnte nicht zum schreiben geöffnet werden."); d->close(); d->release(); vIni->release(); delete[] pfad; } break; case 0xF: // klient absturtz if (!adminId) errorZuKlient("Du musst dich einloggen."); else { klient->sende("\1", 1); int klientId = 0; klient->getNachricht((char*)&klientId, 4); if (klientId && ps->absturzKlient(klientId)) klient->sende("\1", 1); else klient->sende("\0", 1); } break; case 0x10: // SMP Frage nach Datei Gruppen Status if (!adminId) errorZuKlient("Du musst dich einloggen."); else { if (!ps->zDB()->adminHatRecht(adminId, Admin_Recht::KSGCUpdate)) errorZuKlient("Du hast kein Recht diese Operation durchzuführen."); else { Array< FileGroupInfo* > list; if (ps->zDB()->getFileGroupInfoList(ps->getId(), &list)) { klient->sende("\1", 1); int anz = list.getEintragAnzahl(); klient->sende((char*)&anz, 4); for (int i = 0; i < anz; i++) { FileGroupInfo* info = list.get(i); klient->sende((char*)&info->id, 4); unsigned char len = (unsigned char)info->name.getLength(); klient->sende((char*)&len, 1); klient->sende(info->name, len); len = (unsigned char)info->status.getLength(); klient->sende((char*)&len, 1); klient->sende(info->status, len); unsigned short l = (unsigned short)info->pfad.getLength(); klient->sende((char*)&l, 2); klient->sende(info->pfad, l); klient->sende((char*)&info->version, 4); delete info; } } else errorZuKlient("Fehler beim abrufen der Datei Gruppen Informationen."); } } break; case 0x11: // SMP Get System List if (!adminId) errorZuKlient("Du musst dich einloggen."); else { if (!ps->zDB()->adminHatRecht(adminId, Admin_Recht::KSGCUpdate)) errorZuKlient("Du hast kein Recht diese Operation durchzuführen."); else { klient->sende("\1", 1); Result res = ps->zDB()->getSystemListe(); klient->sende((char*)&res.zeilenAnzahl, 4); for (int i = 0; i < res.zeilenAnzahl; i++) { int id = (int)res.values[i * 2]; klient->sende((char*)&id, 4); unsigned char len = (unsigned char)res.values[i * 2 + 1].getLength(); klient->sende((char*)&len, 1); klient->sende(res.values[i * 2 + 1], len); } res.destroy(); } } break; case 0x12: // SMP Get File List if (!adminId) errorZuKlient("Du musst dich einloggen."); else { if (!ps->zDB()->adminHatRecht(adminId, Admin_Recht::KSGCUpdate)) errorZuKlient("Du hast kein Recht diese Operation durchzuführen."); else { klient->sende("\1", 1); int system, group; klient->getNachricht((char*)&system, 4); klient->getNachricht((char*)&group, 4); Result res = ps->zDB()->getDateiListeSMP(system, group); klient->sende((char*)&res.zeilenAnzahl, 4); for (int i = 0; i < res.zeilenAnzahl; i++) { int id = (int)res.values[i * 4]; klient->sende((char*)&id, 4); unsigned short len = (unsigned short)res.values[i * 4 + 1].getLength(); klient->sende((char*)&len, 2); klient->sende(res.values[i * 4 + 1], len); int version = (int)res.values[i * 4 + 2]; klient->sende((char*)&version, 4); unsigned char l = (unsigned char)res.values[i * 4 + 3].getLength(); klient->sende((char*)&l, 1); klient->sende(res.values[i * 4 + 3], l); } res.destroy(); } } break; case 0x13: // Get File Version if (!adminId) errorZuKlient("Du musst dich einloggen."); else { if (!ps->zDB()->adminHatRecht(adminId, Admin_Recht::KSGCUpdate)) errorZuKlient("Du hast kein Recht diese Operation durchzuführen."); else { klient->sende("\1", 1); int group, system; unsigned short len; klient->getNachricht((char*)&len, 2); char* path = new char[len + 1]; klient->getNachricht(path, len); path[len] = 0; klient->getNachricht((char*)&group, 4); klient->getNachricht((char*)&system, 4); int version = ps->zDB()->getDateiVersion(path, system, group); delete[] path; klient->sende((char*)&version, 4); } } break; case 0x14: // Update File if (!adminId) errorZuKlient("Du musst dich einloggen."); else { if (!ps->zDB()->adminHatRecht(adminId, Admin_Recht::KSGCUpdate)) errorZuKlient("Du hast kein Recht diese Operation durchzuführen."); else { klient->sende("\1", 1); unsigned short len; klient->getNachricht((char*)&len, 2); char* path = new char[len + 1]; klient->getNachricht(path, len); path[len] = 0; char status = 0; // 0: delete, 1: update, 2: new klient->getNachricht(&status, 1); unsigned char l; klient->getNachricht((char*)&l, 1); char* time = 0; if (l > 0) { time = new char[l + 1]; klient->getNachricht(time, l); time[l] = 0; } int system, gruppe; klient->getNachricht((char*)&system, 4); klient->getNachricht((char*)&gruppe, 4); if (ps->zDB()->updateDatei(path, status, time, system, gruppe)) klient->sende("\1", 1); else errorZuKlient("Fehler beim updaten der Datei."); } } break; case 0x15: // Update Gruppe if (!adminId) errorZuKlient("Du musst dich einloggen."); else { if (!ps->zDB()->adminHatRecht(adminId, Admin_Recht::KSGCUpdate)) errorZuKlient("Du hast kein Recht diese Operation durchzuführen."); else { klient->sende("\1", 1); int gruppe; klient->getNachricht((char*)&gruppe, 4); if (ps->zDB()->dateiGruppeUpdate(gruppe)) klient->sende("\1", 1); else errorZuKlient("Fehler beim updaten der Gruppe."); } } break; default: errorZuKlient("Unbekannte Nachricht!"); break; } if (br) break; ps->addEmpfangen(klient->getDownloadBytes(1)); ps->addGesendet(klient->getUploadBytes(1)); } } ps->addEmpfangen(klient->getDownloadBytes(1)); ps->addGesendet(klient->getUploadBytes(1)); if (updateGruppe) ps->updateAbbruch(updateGruppe); delete this; } void PSAKlient::errorZuKlient(const char* nachricht) const // sendet eine Fehlernachricht zum Klient { klient->sende("\3", 1); char len = (char)textLength(nachricht); klient->sende(&len, 1); klient->sende(nachricht, len); } // Inhalt der PSKlient aus PatchServer.h // Konstruktor PSKlient::PSKlient(SKlient* klient, PatchServer* ps, InitDatei* ini) : Thread() { this->klient = klient; unsigned char key[20] = { 102, 139, 140, 143, 52, 52, 194, 167, 97, 106, 23, 72, 170, 121, 213, 178, 28, 28, 124, 185 }; klient->setSendeKey((char*)key, 20); klient->setEmpfangKey((char*)key, 20); klientNummer = 0; system = 0; this->ps = ps; this->ini = ini; encrypted = 0; } // Destruktor PSKlient::~PSKlient() { ps->release(); klient->release(); ini->release(); } // nicht constant void PSKlient::absturz() { ende(); klient->trenne(); ps->zDB()->unregisterKlient(klientNummer, ps->getId()); } void PSKlient::thread() { int hack = 0; while (1) { char c = 0; if ((!encrypted && !klient->getNachricht(&c, 1)) || (encrypted && !klient->getNachrichtEncrypted(&c, 1))) break; else { bool br = 0; switch (c) { case 0: encrypted = 1; break; case 1: // Klient identifikation if (encrypted) { klient->getNachrichtEncrypted((char*)&klientNummer, 4); klient->getNachrichtEncrypted((char*)&system, 1); } else { klient->getNachricht((char*)&klientNummer, 4); klient->getNachricht((char*)&system, 1); } if (!ps->zDB()->proveKlient(klientNummer, ps->getId())) { klientNummer = 0; errorZuKlient("Du bist nicht für diesen Server eingetragen"); } else { if (encrypted) { Text* key = ps->zDB()->getKlientKey(klientNummer); if (!key) errorZuKlient("Es konnte kein Key ermittelt werden."); else { klient->sendeEncrypted("\1", 1); klient->setEmpfangKey(*key, key->getLength()); klient->setSendeKey(*key, key->getLength()); key->release(); } } else klient->sende("\1", 1); } break; case 2: // Erhaltung Server message if (1) { char befehl = 0; if (encrypted) klient->getNachrichtEncrypted(&befehl, 1); else klient->getNachricht(&befehl, 1); switch (befehl) { case 2: // Klient absturz if (1) { int klientId = 0; if (encrypted) { klient->getNachrichtEncrypted((char*)&klientId, 4); if (klientId && ps->absturzKlient(klientId)) klient->sendeEncrypted("\1", 1); else klient->sendeEncrypted("\0", 1); } else { klient->getNachricht((char*)&klientId, 4); if (klientId && ps->absturzKlient(klientId)) klient->sende("\1", 1); else klient->sende("\0", 1); } } break; default: errorZuKlient("Befehl nicht bekannt!"); break; } } break; case 3: // Verbindungsende br = 1; if (encrypted) klient->sendeEncrypted("\1", 1); else klient->sende("\1", 1); break; case 4: // unregister Klient if (klientNummer) { ps->zDB()->unregisterKlient(klientNummer, ps->getId()); if (encrypted) klient->sendeEncrypted("\1", 1); else klient->sende("\1", 1); } else errorZuKlient("Du bist nicht Identifiziert."); break; case 5: // update anfrage ****Altes Update System if (klientNummer) { // Keine Verkeyung bei den alten Clients klient->sende("\1", 1); char version[4]; klient->getNachricht(version, 4); //int v = ( ( version[ 3 ] << 24 ) & 0xFF000000 ) | ( ( version[ 2 ] << 16 ) & 0x00FF0000 ) | ( ( version[ 1 ] << 8 ) & 0x0000FF00 ) | ( version[ 0 ] & 0x000000FF ); //Result änderungen = ps->zDB()->getGeänderteDateien( v, (int)X64 + 1 ); char byte = 0; // ********neu beginn********* klient->sende("\2", 1); Text* pfad = new Text("start.exe"); byte = (char)pfad->getLength(); klient->sende(&byte, 1); klient->sende(pfad->getText(), byte); klient->sende("\2", 1); pfad->setText("framework.dll"); byte = (char)pfad->getLength(); klient->sende(&byte, 1); klient->sende(pfad->getText(), byte); klient->sende("\2", 1); pfad->setText("network.dll"); byte = (char)pfad->getLength(); klient->sende(&byte, 1); klient->sende(pfad->getText(), byte); klient->sende("\2", 1); pfad->setText("data/patch/bin/patcher.exe"); byte = (char)pfad->getLength(); klient->sende(&byte, 1); klient->sende(pfad->getText(), byte); klient->sende("\2", 1); pfad->setText("data/patch/bin/übernehmen.exe"); byte = (char)pfad->getLength(); klient->sende(&byte, 1); klient->sende(pfad->getText(), byte); klient->sende("\2", 1); pfad->setText("data/start/icon.exe"); byte = (char)pfad->getLength(); klient->sende(&byte, 1); klient->sende(pfad->getText(), byte); klient->sende("\2", 1); pfad->setText("data/optionen.ini"); byte = (char)pfad->getLength(); klient->sende(&byte, 1); klient->sende(pfad->getText(), byte); pfad->release(); klient->sende("\4", 1); // ********neu ende******** //for( int i = 0; i < änderungen.zeilenAnzahl; i++ ) //{ // if( änderungen.values[ i * 2 + 1 ].istGleich( "t" ) ) // byte = 1; // else // byte = 2; // klient->sende( &byte, 1 ); // byte = änderungen.values[ i * 2 ].getLength(); // klient->sende( &byte, 1 ); // klient->sende( änderungen.values[ i * 2 ].getText(), byte ); //} //änderungen.destroy(); //Result remove = ps->zDB()->getGelöschteDateien( v, (int)X64 + 1 ); //for( int i = 0; i < remove.zeilenAnzahl; i++ ) //{ // klient->sende( "\3", 1 ); // byte = remove.values[ i * 2 ].getLength(); // klient->sende( &byte, 1 ); // klient->sende( remove.values[ i * 2 ].getText(), byte ); //} //klient->sende( "\4", 1 ); //remove.destroy(); } else errorZuKlient("Du bist nicht Identifiziert."); break; case 6: // Frage nach Datei ****Altes Update System if (1) { // Keine Verkeyung bei den alten Clients if (!klientNummer) { errorZuKlient("Du bist nicht Identifiziert."); break; } klient->sende("\1", 1); unsigned char byte = 0; klient->getNachricht((char*)&byte, 1); Text* pfad = new Text(""); pfad->fillText(' ', byte); klient->getNachricht((char*)pfad->getText(), byte); __int64 pos = 0; klient->getNachricht((char*)&pos, 8); if (system) pfad->insert(0, "../versions/x64/live/"); else pfad->insert(0, "../versions/x32/live/"); pfad->ersetzen("ü", "ue"); Datei* datei = new Datei(); datei->setDatei(pfad); datei->open(Datei::Style::lesen); if (pos) datei->setLPosition(pos, 0); __int64 length = datei->getSize(); length -= pos; char* bytes = new char[2048]; unsigned short byteLen = 0; while (1) { if (!length) { klient->sende("\0\0", 2); break; } byteLen = 2048; if (length < 2048) byteLen = (unsigned short)length; klient->sende((char*)&byteLen, 2); datei->lese(bytes, byteLen); klient->sende(bytes, byteLen); length -= byteLen; char ret = 0; if (byteLen != 2048) break; klient->getNachricht((char*)&ret, 1); ps->addEmpfangen(klient->getDownloadBytes(1)); ps->addGesendet(klient->getUploadBytes(1)); if (ret == 1) continue; if (!ret) break; if (ret == 2) { pos = 0; klient->getNachricht((char*)&pos, 8); if (pos > length) pos = length; datei->setLPosition(pos, 0); length = datei->getSize(); length -= pos; } } delete[]bytes; datei->close(); datei->release(); } break; case 7: // Frage nach neuster Version ****Altes Update System if (1) { // Keine Verkeyung bei den alten Clients if (!klientNummer) { errorZuKlient("Du bist nicht Identifiziert."); break; } klient->sende("\1", 1); int version = 30; klient->sende((char*)&version, 4); } break; case 8: // Frage nach Dateigröße ****Altes Update System if (1) { // Keine Verkeyung bei den alten Clients if (!klientNummer) { errorZuKlient("Du bist nicht Identifiziert."); break; } klient->sende("\1", 1); char byte = 0; klient->getNachricht(&byte, 1); Text* pfad = new Text(""); pfad->fillText(' ', byte); klient->getNachricht((char*)pfad->getText(), byte); if (system) pfad->insert(0, "../versions/x64/live/"); else pfad->insert(0, "../versions/x32/live/"); pfad->ersetzen("ü", "ue"); Datei* datei = new Datei(); datei->setDatei(pfad); __int64 size = datei->getSize(); datei->release(); klient->sende((char*)&size, 8); } break; case 9: // Frage nach Dateiliste ****Neues Update System if (1) { if (!klientNummer) { errorZuKlient("Du bist nicht Identifiziert."); break; } if (encrypted) klient->sendeEncrypted("\1", 1); else klient->sende("\1", 1); int updateGruppe = 0; if (encrypted) klient->getNachrichtEncrypted((char*)&updateGruppe, 4); else klient->getNachricht((char*)&updateGruppe, 4); Result dateien = ps->zDB()->getDateiListeOhneOrdner(system, updateGruppe); if (!dateien.zeilenAnzahl) { dateien.destroy(); errorZuKlient("Dein System wird nicht unterstützt."); break; } Result deleted = ps->zDB()->getDeletedFiles(system, updateGruppe); if (encrypted) klient->sendeEncrypted("\1", 1); else klient->sende("\1", 1); for (int i = 0; i < dateien.zeilenAnzahl; i++) { int len = dateien.values[i * 2].getLength(); if (!len) break; if (encrypted) { klient->sendeEncrypted((char*)&len, 4); klient->sendeEncrypted(dateien.values[i * 2].getText(), len); int version = TextZuInt(dateien.values[i * 2 + 1].getText(), 10); klient->sendeEncrypted((char*)&version, 4); } else { klient->sende((char*)&len, 4); klient->sende(dateien.values[i * 2].getText(), len); int version = TextZuInt(dateien.values[i * 2 + 1].getText(), 10); klient->sende((char*)&version, 4); } } if (encrypted) klient->sendeEncrypted("\0\0\0\0", 4); else klient->sende("\0\0\0\0", 4); for (int i = 0; i < deleted.zeilenAnzahl; i++) { int len = deleted.values[i].getLength(); if (!len) break; if (encrypted) { klient->sendeEncrypted((char*)&len, 4); klient->sendeEncrypted(deleted.values[i].getText(), len); } else { klient->sende((char*)&len, 4); klient->sende(deleted.values[i].getText(), len); } } if (encrypted) klient->sendeEncrypted("\0\0\0\0", 4); else klient->sende("\0\0\0\0", 4); deleted.destroy(); dateien.destroy(); } break; case 10: // Frage nach Dateigröße ****Neues Update System if (1) { if (!klientNummer) { errorZuKlient("Du bist nicht Identifiziert."); break; } if (encrypted) klient->sendeEncrypted("\1", 1); else klient->sende("\1", 1); int updateGruppe = 0; if (encrypted) klient->getNachrichtEncrypted((char*)&updateGruppe, 4); else klient->getNachricht((char*)&updateGruppe, 4); if (!ps->zDB()->supportedDateiGruppe(ps->getId(), updateGruppe)) { int s = ps->zDB()->getDateiGruppePatchServer(klientNummer, updateGruppe); int port = 0; Text* ip = new Text(); bool ok = ps->zDB()->getPatchServerPortIp(s, &port, ip); if (!s || !ok) errorZuKlient("Es ist momentan nicht möglich diese Datei herunterzuladen."); else { if (encrypted) { klient->sendeEncrypted("\2", 1); klient->sendeEncrypted((char*)&port, 4); int len = ip->getLength(); klient->sendeEncrypted((char*)&len, 4); klient->sendeEncrypted((char*)ip->getText(), len); } else { klient->sende("\2", 1); klient->sende((char*)&port, 4); int len = ip->getLength(); klient->sende((char*)&len, 4); klient->sende((char*)ip->getText(), len); } } ip->release(); break; } Text* gruppeN = ps->zDB()->getDateiGruppeName(updateGruppe); if (!gruppeN) { errorZuKlient("Dein System wird nicht unterstützt."); break; } Text* pfad = new Text(ini->zWert("SystemPfad")->getText()); pfad->append("/"); pfad->append(gruppeN); pfad->append("/"); Text* tmp = ps->zDB()->getSystemName(system); if (!tmp) { errorZuKlient("Dein System wird nicht unterstützt."); pfad->release(); break; } pfad->append(tmp); pfad->append("/"); if (encrypted) klient->sendeEncrypted("\1", 1); else klient->sende("\1", 1); int len = 0; if (encrypted) klient->getNachrichtEncrypted((char*)&len, 4); else klient->getNachricht((char*)&len, 4); char* pf = new char[len + 1]; pf[len] = 0; if (encrypted) klient->getNachrichtEncrypted(pf, len); else klient->getNachricht(pf, len); pfad->append(pf); delete[] pf; Datei* datei = new Datei(); datei->setDatei(pfad); __int64 size = datei->getSize(); datei->release(); if (encrypted) klient->sendeEncrypted((char*)&size, 8); else klient->sende((char*)&size, 8); } break; case 11: // Frage nach Datei ****Neues Update System if (1) { if (!klientNummer) { errorZuKlient("Du bist nicht Identifiziert."); break; } if (encrypted) klient->sendeEncrypted("\1", 1); else klient->sende("\1", 1); int updateGruppe = 0; if (encrypted) klient->getNachrichtEncrypted((char*)&updateGruppe, 4); else klient->getNachricht((char*)&updateGruppe, 4); if (!ps->zDB()->supportedDateiGruppe(ps->getId(), updateGruppe)) { int s = ps->zDB()->getDateiGruppePatchServer(klientNummer, updateGruppe); int port = 0; Text* ip = new Text(); bool ok = ps->zDB()->getPatchServerPortIp(s, &port, ip); if (!s || !ok) errorZuKlient("Es ist momentan nicht möglich diese Datei herunterzuladen."); else { if (encrypted) { klient->sendeEncrypted("\2", 1); klient->sendeEncrypted((char*)&port, 4); int len = ip->getLength(); klient->sendeEncrypted((char*)&len, 4); klient->sendeEncrypted((char*)ip->getText(), len); } else { klient->sende("\2", 1); klient->sende((char*)&port, 4); int len = ip->getLength(); klient->sende((char*)&len, 4); klient->sende((char*)ip->getText(), len); } } ip->release(); break; } Text* gruppeN = ps->zDB()->getDateiGruppeName(updateGruppe); if (!gruppeN) { errorZuKlient("Dein System wird nicht unterstützt."); break; } Text* pfad = new Text(ini->zWert("SystemPfad")->getText()); pfad->append("/"); pfad->append(gruppeN); pfad->append("/"); Text* tmp = ps->zDB()->getSystemName(system); if (!tmp) { errorZuKlient("Dein System wird nicht unterstützt."); pfad->release(); break; } pfad->append(tmp); pfad->append("/"); if (encrypted) klient->sendeEncrypted("\1", 1); else klient->sende("\1", 1); int len = 0; if (encrypted) klient->getNachrichtEncrypted((char*)&len, 4); else klient->getNachricht((char*)&len, 4); char* pf = new char[len + 1]; pf[len] = 0; if (encrypted) klient->getNachrichtEncrypted(pf, len); else klient->getNachricht(pf, len); pfad->append(pf); delete[] pf; __int64 pos = 0; if (encrypted) klient->getNachrichtEncrypted((char*)&pos, 8); else klient->getNachricht((char*)&pos, 8); Datei* datei = new Datei(); datei->setDatei(pfad); datei->open(Datei::Style::lesen); if (pos) datei->setLPosition(pos, 0); __int64 length = datei->getSize(); length -= pos; char* bytes = new char[2048]; unsigned short byteLen = 0; while (1) { if (!length) { klient->sende("\0\0", 2); break; } byteLen = 2048; if (length < 2048) byteLen = (unsigned short)length; if (!klient->sende((char*)&byteLen, 2)) break; datei->lese(bytes, byteLen); if (!klient->sende(bytes, byteLen)) break; length -= byteLen; if (byteLen != 2048) break; ps->addEmpfangen(klient->getDownloadBytes(1)); ps->addGesendet(klient->getUploadBytes(1)); } char ret = 0; if (encrypted) klient->getNachrichtEncrypted(&ret, 1); else klient->getNachricht(&ret, 1); delete[] bytes; datei->close(); datei->release(); } break; case 12: // Frage nach Datei Gruppen Liste ****Neues Update System if (1) { if (!klientNummer) { errorZuKlient("Du bist nicht Identifiziert."); break; } if (encrypted) klient->sendeEncrypted("\1", 1); else klient->sende("\1", 1); Result dgl = ps->zDB()->getDateiGruppeListe(); for (int i = 0; i < dgl.zeilenAnzahl; i++) { if (encrypted) { int id = TextZuInt(dgl.values[i * 3].getText(), 10); klient->sendeEncrypted((char*)&id, 4); int len = dgl.values[i * 3 + 1].getLength(); klient->sendeEncrypted((char*)&len, 4); if (len) klient->sendeEncrypted(dgl.values[i * 3 + 1].getText(), len); int vs = TextZuInt(dgl.values[i * 3 + 2].getText(), 10); klient->sendeEncrypted((char*)&vs, 4); } else { int id = TextZuInt(dgl.values[i * 3].getText(), 10); klient->sende((char*)&id, 4); int len = dgl.values[i * 3 + 1].getLength(); klient->sende((char*)&len, 4); if (len) klient->sende(dgl.values[i * 3 + 1].getText(), len); int vs = TextZuInt(dgl.values[i * 3 + 2].getText(), 10); klient->sende((char*)&vs, 4); } } if (encrypted) klient->sendeEncrypted("\0\0\0\0", 4); else klient->sende("\0\0\0\0", 4); dgl.destroy(); char ret = 0; if (encrypted) klient->getNachrichtEncrypted(&ret, 1); else klient->getNachricht(&ret, 1); } break; default: hack++; if (!errorZuKlient("Unbekannte Nachricht!")) br = 1; break; } if (br || hack >= 10) break; } ps->addEmpfangen(klient->getDownloadBytes(1)); ps->addGesendet(klient->getUploadBytes(1)); } ps->addEmpfangen(klient->getDownloadBytes(1)); ps->addGesendet(klient->getUploadBytes(1)); ps->removeKlient(this); // delete this } // constant bool PSKlient::errorZuKlient(const char* nachricht) const // sendet eine Fehlernachricht zum Klient { if (encrypted) { if (!klient->sendeEncrypted("\3", 1)) return 0; char len = (char)textLength(nachricht); if (!klient->sendeEncrypted(&len, 1)) return 0; if (!klient->sendeEncrypted(nachricht, len)) return 0; } else { if (!klient->sende("\3", 1)) return 0; char len = (char)textLength(nachricht); if (!klient->sende(&len, 1)) return 0; if (!klient->sende(nachricht, len)) return 0; } return 1; } int PSKlient::getKlientNummer() const // gibt die KlientId zurück { return klientNummer; }