// Copyright 2000 - 2010 HTS-Software Unternehmensberatung // Alexander Schucha // // This file is part of Athena-Web. // // Athena-Web is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Athena-Web is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with Athena-Web. If not, see . //****************************************************************************** //* Formatierung: * //* ============= * //* Kurze Beschreibung vor jeder Funktion: * //* // * //* // * //* // * //* * //* Zwischen Funktionen sind immer zwei Leerzeilen. * //* * //* Funktionsbeschreibung: * //* ====================== * //* Das Login Programm wird über die Apache CGI-Schnittstelle aufgerufen und * //* steuert die Authentifizierung eines Users. Es werden folgende aktivitäten * //* von diesem Programm erledigt. * //* * //* Prüfen des Passworts gegen die System Passwortdatei (gepl. LDAP) * //* Speichern der Login Zeit in der Session-Tabelle der Datenbank * //* Erzeugen der Session-ID bei der ersten Anmeldung * //* Prüfen der Session-ID und des Logintimouts beim ausführen von * //* Funktionen * //* * //* Offene Punkte: * //* ============== * //* Es ist eine bessere Fehlerbehandlung nötig (Exeptions usw.). * //* * //* Neuentwicklung 15.06.2000 * //* Einführung einer Session-ID die als gültig und ungültig 03.01.2001 * //* Markiert wird. * //* * //* Neue Strukturierung des Programms: 07.11.2007 * //* - längere Session-IDs * //* - Datenübertragung zu den Nutzerprozessen über Domainsockets * //* * //* Neue Strukturierung und Verwendung der STL 2010 * //* Es wurden einige alte Funktionen entfernt weil diese nicht * //* mehr in dieser Form sinnvoll waren. * //* * //****************************************************************************** #include #include #include #include #include #include #include #include // usleep, setuid, setgid #include // Meldungen ins syslog schreibe #include // nullptr ??? // Linux #include // Shadow Passwörter lesen. #include // User Einträge lesen. #include // Passwort verschlüsseln crypt (). #include #include #include #include // Eigene #include "../../../Athena-Api/Log/Log.hpp" #include "../../../Athena-Api/Log/LogStdout.hpp" #include "../../../Athena-Api/Log/LogSyslog.hpp" #include "../../../Athena-Api/Log/LogFile.hpp" #include "../../../Athena-Api/Log/LogNoLog.hpp" #include "../../../Athena-Api/HtsCgi/HtsCgi.hpp" #include "../../../Athena-Api/HtsCgi/HtsCgi.cpp" #include "../../../Athena-Api/HtsConf/HtsConf.hpp" #include "../../../Athena-Api/HtsConf/HtsConf.cpp" #include "../../../Athena-Api/HtsSession/HtsSession.hpp" #include "../../../Athena-Api/HtsSession/HtsSession.cpp" #include "../../../Athena-Api/HtsStartProg/HtsStartProg.hpp" #include "../../../Athena-Api/HtsStartProg/HtsStartProg.cpp" #include "../../../Athena-Api/HtsSaveDb/HtsSaveDb.hpp" #include "../../../Athena-Api/HtsSaveDb/HtsSaveDb.cpp" #include "HtsCgiLogin.hpp" int main (int argC, char *argV[]) { // Globale Einstellungen zum Message loging. boolDebugInfo = true; //***** //* Eine Instanz der Log-Klasse erzeugen. //* Je nach erzeugter Instanz wird an verschiedene Ziele (Stdout, File, Syslog, NoLog) gelogt. //* // Logging für das gewünschte Log-Ziel aktivieren. Hts::Log* pLog; //pLog = Hts::LogStdout::getInstance (); //pLog = Hts::LogFile::getInstance (); pLog = Hts::LogSyslog::getInstance (); //pLog = Hts::LogNoLog::getInstance (); // LogStatus gibt an welche Loglevel ausgegeben werden. Als Standard ist "Info" ein guter Wert. // Hier sollten Meldungen ausgegeben werden die den User auf Probleme Hinweisen und Lösungen vorschlagen. pLog->setLogStatus ("Info Error"); // Für die Entwicklung alle Ausgaben einschalten. //pLog->setLogStatus ("on"); //* //***** //Hts::Log* pLogStdout = Hts::LogStdout::getInstance (); //pLogStdout->setLogLevel ("Info"); // //Hts::Log* pLogSyslog = Hts::LogSyslog::getInstance (); //pLogSyslog->setLogLevel ("Info"); // Startmeldung für das Programm HtsCgiLogin, damit man im Syslog leichter sieht wo die Meldungen anfangen. syslog (LOG_INFO, "***** Programm gestartet *****"); //***** (1) //* Von der CGI-Schnittstelle die relevanten Parameter lesen. //* Wurde die SessionId nicht als CGI-Variable gefunden wird noch versucht diese aus einem Cookie zu setzen. //* Ist die SessionId weder als CGI-Variable noch als Cookie vorhanden wird weiter unten eine neue vergeben. //* HtsCgi *pCgi = new HtsCgi (); std::string strCgiSessionId = pCgi->findFirst ("SessionId"); if (strCgiSessionId == "") { strCgiSessionId = pCgi->getCookie ("HtsSessionId"); // Für die folgende Programmierung die SessionId in einer CGI-Variable ablegen. // Damit ist der Zugriff im weiteren Verlauf unabhängig ob Cookie oder CGI-Variable // zur Übergabe benutzt werden. pCgi->Set ("SessionId", strCgiSessionId); } //syslog (LOG_INFO, "HTTPS : '%s'", pCgi->findFirst ("HTTPS").c_str ()); //syslog (LOG_INFO, "HTTP_HOST : '%s'", pCgi->findFirst ("HTTP_HOST").c_str ()); //syslog (LOG_INFO, "HTTP_REFERER : '%s'", pCgi->findFirst ("HTTP_REFERER").c_str ()); // //syslog (LOG_INFO, "PATH : '%s'", pCgi->findFirst ("PATH").c_str ()); //syslog (LOG_INFO, "SERVER_NAME : '%s'", pCgi->findFirst ("SERVER_NAME").c_str ()); // //syslog (LOG_INFO, "DOCUMENT_ROOT: '%s'", pCgi->findFirst ("DOCUMENT_ROOT").c_str ()); //syslog (LOG_INFO, "REQUEST_URI : '%s'", pCgi->findFirst ("REQUEST_URI").c_str ()); std::string strCgiSubsystem = pCgi->findFirst ("Subsystem"); std::string strCgiModul = pCgi->findFirst ("Modul"); std::string strCgiFunktion = pCgi->findFirst ("Funktion"); std::string strCgiUserId = pCgi->findFirst ("UserId"); std::string strCgiPasswd = pCgi->findFirst ("Passwd"); //* //***** //***** (1.1) //* Lese die Datenbank connect Daten aus der Konfigurationsdatei. std::string strConfigFile = ""; std::string strSectionName = "Datenbank_1"; std::string strVariablenName = ""; std::string strServerAdresse = ""; std::string strDatenbankName = ""; std::string strDbUserId = ""; std::string strDbPasswd = ""; try { strConfigFile = "HtsCgiLogin.conf"; HtsConf *pConfig = new HtsConf (strConfigFile, "r"); strVariablenName = "ServerAdresse"; pConfig->FindFirst (strSectionName, strVariablenName); strServerAdresse = pConfig->GetValue (); strVariablenName = "DatenbankName"; pConfig->FindFirst (strSectionName, strVariablenName); strDatenbankName = pConfig->GetValue (); strVariablenName = "UserId"; pConfig->FindFirst (strSectionName, strVariablenName); strDbUserId = pConfig->GetValue (); strVariablenName = "Passwd"; pConfig->FindFirst (strSectionName, strVariablenName); strDbPasswd = pConfig->GetValue (); } catch (...) { syslog (LOG_INFO, "HtsCgiLogin->main: Lesen der Datenbank konfiguration, unbekannte Exception. ('%s', '%s').", strSectionName.c_str (), strVariablenName.c_str ()); exit (1); } //* //***** //***** (2) //* Lese die Parameter zum Subsystem aus der Datenbank. //* Wurde keins übergeben lese die des als Standardsubsystem markierten. //* // Erzeuge das benötigte Datenbankobjekt. pConfigDb = new HtsSaveDb (strServerAdresse, strDatenbankName, strDbUserId, strDbPasswd); std::string strSql = ""; std::string strSubsystem = ""; std::string strSubsystemArt = ""; std::string strSubsystemDefault = ""; std::string strProgramm = ""; std::string strAuthArt = ""; std::string strUserId = ""; std::string strHttpLocation = ""; try { if (strCgiSubsystem == "") strSql = "select * from SubsystemConfig where SubsystemDefault = '1';"; else strSql = "select * from SubsystemConfig where Subsystem = '" + pConfigDb->StringToSql (strCgiSubsystem) + "';"; if (boolDebugInfo) syslog (LOG_INFO, "%s", strSql.c_str ()); pConfigDb->ExecSql (strSql); strSubsystem = pConfigDb->Get ("Subsystem"); strSubsystemArt = pConfigDb->Get ("SubsystemArt"); strSubsystemDefault = pConfigDb->Get ("SubsystemDefault"); strProgramm = pConfigDb->Get ("Programm"); strAuthArt = pConfigDb->Get ("AuthArt"); strUserId = pConfigDb->Get ("UserId"); strHttpLocation = pConfigDb->Get ("HttpLocation"); } catch (HtsSaveDb::TableEmpty) { syslog (LOG_INFO, "Tabelle: SubsystemConfig ist leer: '%s'", strSql.c_str ()); exit (1); } catch (HtsSaveDb::NoResult) { syslog (LOG_INFO, "Tabelle: SubsystemConfig nix gefunden: '%s'", strSql.c_str ()); exit (1); } catch (...) { syslog (LOG_INFO, "Tabelle: SubsystemConfig unbekannte Exception: '%s'", strSql.c_str ()); exit (1); } //* //***** //***** (3) //* Prüfe welche Daten per CGI oder Cookie übergeben wurden und entscheide was getan werden muss. //* AuthArt = "keine" Darf den User nur aus der Datenbank benutzen (anders ists ein Sicherheitsproblem). //* AuthArt = "passwd" Wurde keine User-ID übergeben wird die Loginseite gesendet. //* std::string strLoginUser = ""; if ((strAuthArt == "passwd") && (strCgiSubsystem == "") && (strCgiModul == "") && (strCgiFunktion == "")) { // Sende das Loginformular zum Client. std::string strDateiname = "login" + strSubsystem + ".html"; std::ifstream loginForm (strDateiname.c_str ()); if (!loginForm) { std::string strMessage = "HtsCgiLogin (3) -> open Loginformular: '" + strDateiname + "' fehlgeschlagen."; pLog->setLogLevel ("Info"); pLog->sendMessage ("content-type: text/html\n\n" + strMessage); pLog->setLogLevel ("Info"); pLog->sendMessage (strMessage); exit (1); } std::string strLoginform = ""; while (!loginForm.eof ()) { std::getline (loginForm, strLoginform); std::cout << strLoginform << std::endl; } loginForm.close (); exit (1); } else if (((strAuthArt == "passwd") && (strCgiUserId != "")) || ((strAuthArt == "passwd") && (strCgiUserId == ""))) { strLoginUser = strCgiUserId; // User-ID vom Client strCgiUserId = ""; // Löschen damit es weiter unten nicht versehentlich benutzt werden kann. } else if ((strAuthArt == "keine") && (strUserId != "")) { strLoginUser = strUserId; // User-ID aus der Subsystem-Config-Datenbank strUserId = ""; // Löschen damit es weiter unten nicht versehentlich benutzt werden kann. } else { std::string strMessage = "HtsCgiLogin (3) -> AuthArt: '" + strAuthArt + "' und Quelle der User-ID ungültig."; pLog->setLogLevel ("Info"); pLog->sendMessage ("content-type: text/html\n\n" + strMessage); pLog->setLogLevel ("Info"); pLog->sendMessage (strMessage); exit (1); } if (strLoginUser == "root") { std::string strMessage = "HtsCgiLogin (3) -> Login als '" + strLoginUser + "' nicht erlaubt."; pLog->setLogLevel ("Info"); pLog->sendMessage ("content-type: text/html\n\n" + strMessage); pLog->setLogLevel ("Info"); pLog->sendMessage (strMessage); exit (1); } //* //***** //***** (4) //* Prüfe ob eine Session-ID per CGI-Schnittstelle oder Cookie übergeben wurde. //* Wenn NEIN: erzeuge eine neue. //* Wenn JA : prüfe ob diese in der Datenbank eingetragen ist. //* HtsSession *pSession = NULL; int boolNeueSessionId = false; if (strCgiSessionId == "") { // Testmeldung if (boolDebugInfo) syslog (LOG_INFO, "HtsCgiLogin (4) -> Neue Session-ID erzeugt, Subsystem: '%s'", strSubsystem.c_str ()); // Neue SessionId generieren pSession = new HtsSession (pConfigDb); strCgiSessionId = pSession->getSessionId (); // Für die weitere Verarbeitung speichern das die SessionId neu ist. boolNeueSessionId = true; // Speichert die neue Session-ID in der Datenbank. pSession->setSessionDaten (strCgiSessionId, strSubsystem, "0", strLoginUser); // Aktuelle Zeit + ca. 1 Jahr ermitteln. time_t DateTime; struct tm *LocalDateTime; DateTime = time (NULL); DateTime = DateTime + (364 * 24 * 60 * 60); LocalDateTime = localtime (&DateTime); // Das Cookielaufzeit Ende in einen String konvertieren. char *pszTime = new char [40]; strftime (pszTime, 40, "%a, %d-%m-%Y %H:%M:%S GMT", LocalDateTime); std::string strTime = pszTime; // Setze den HTTP-Header für das Session Cookie. std::cout << "Set-Cookie: HtsSessionId=" << strCgiSessionId << "; expires=" << strTime << "; version = 1" << std::endl; } else { // Testmeldung if (boolDebugInfo) syslog (LOG_INFO, "HtsCgiLogin (4) -> Vorhandene Session-ID, SessionId: '%s' Subsystem: '%s'", strCgiSessionId.c_str (), strSubsystem.c_str ()); // Lese die Daten zur aktuellen Session aus der Datenbank. pSession = new HtsSession (pConfigDb, strCgiSessionId); // Prüfe ob die von CGI oder Cookie gelesene SessionId gültig ist. Also in der Datenbank vorhanden. if (!pSession->checkSessionId (strSubsystem)) { syslog (LOG_INFO, "HtsCgiLogin (4) -> Cracker am Werk: gefälschte SessionId (beende das Programm). SessionId, Subsystem: '%s', '%s'", strCgiSessionId.c_str (), strSubsystem.c_str ()); exit (1); } } //* //***** //***** (5) //* Nach der aus der Tabelle "SubsystemConfig" gelesenen AuthArt die Authentifizerung durchführen. if (boolDebugInfo) syslog (LOG_INFO, "HtsCgiLogin (5) -> Nach der aus der Tabelle \"SubsystemConfig\" gelesenen AuthArt die Authentifizerung durchführen."); if (strAuthArt == "keine") // Für User aus der HtsCgiLogin konfigurations Datenbank wird das Passwort nicht geprüft. { // HTTP-Weiterleitung zur Anwendungs-URL zum Client senden. // *** In die Tabelle "SubsystemConfig" eine Anwendungslokation einbauen *** if (strCgiSubsystem == "") { syslog (LOG_INFO, "HtsCgiLogin (5) -> Login: kein Login erforderlich"); syslog (LOG_INFO, "strHttpLocation: '%s'", strHttpLocation.c_str ()); std::cout << "Location: " << strHttpLocation << "?Subsystem=" << strSubsystem << "&Modul=" << "Start" << "&Funktion=" << "Anzeigen" << std::endl; std::cout << "content-type: text/html\n\n"; exit (1); } } else if (strAuthArt == "LDAP") { syslog (LOG_INFO, "LDAP Authentifizierung ist noch nicht implementiert."); exit (1); } else if (strAuthArt == "OpenId") { syslog (LOG_INFO, "OpenId Authentifizierung ist noch nicht implementiert."); exit (1); } else if (strAuthArt == "passwd") // Vom Loginformular gesendeter User/Passwort werden gegen /etc/passwd geprüft. { // Bei einer neuen Session-ID sind zum prüfen des Logins noch keine Daten in der Datenbank. // Diese Prüfung muß dann Programm intern erfolgen. if (boolNeueSessionId) { // Neue Session anlegen und User-ID und Passwort prüfen. if (!pSession->checkSystemPasswd (strLoginUser, strCgiPasswd)) { std::string strMessage = "HtsCgiLogin (5) -> checkSystemPasswd: '" + strLoginUser + "' User-ID oder Passwort falsch."; pLog->setLogLevel ("Info"); pLog->sendMessage ("content-type: text/html\n\n" + strMessage); pLog->setLogLevel ("Info"); pLog->sendMessage (strMessage); exit (1); } } else { // Feststellen ob der vorher erfolgte Login noch gültig ist. if (!pSession->checkSystemLogin (strLoginUser, strSubsystem)) { if (boolDebugInfo) syslog (LOG_INFO, "HtsCgiLogin (5) -> Logintimeout abgelaufen"); if (!pSession->checkSystemPasswd (strLoginUser, strCgiPasswd)) { // ****************************************************** // Hier sollte dann ein erneuter Login ermöglicht werden. // ****************************************************** std::string strMessage = "HtsCgiLogin (5) -> checkSystemPasswd: '" + strLoginUser + "' User-ID oder Passwort falsch."; pLog->setLogLevel ("Info"); pLog->sendMessage ("content-type: text/html\n\n" + strMessage); pLog->setLogLevel ("Info"); pLog->sendMessage (strMessage); exit (1); } } } // Setze den Loginzeitpunkt in der Datenbank. if (boolDebugInfo) syslog (LOG_INFO, "HtsCgiLogin (5) -> Login OK setze die Loginzeit in der Tabelle »SessionInfo« neu."); pSession->setLoginZeit (strCgiSessionId, strSubsystem); // Wurde ein Login ausgeführt leite den Client zu Anwendung weiter. // So werden auch die Logindaten nicht mehr als Parameter mitgeführt. if (strCgiFunktion == "Login") { // HTTP-Weiterleitung zur Anwendungs-URL zum Client senden. // *** In die Tabelle "SubsystemConfig" eine Anwendungslokation einbauen *** syslog (LOG_INFO, "HtsCgiLogin (5) -> Login: OK, zur neuen Location weiterleiten."); std::cout << "Location: " << strHttpLocation << "?Subsystem=" << strSubsystem << "&Modul=" << strCgiModul << "&Funktion=" << "Anzeigen" << "&UserId=" << strLoginUser << std::endl; std::cout << "content-type: text/html\n\n"; exit (1); } } else { syslog (LOG_INFO, "HtsCgiLogin, AuthArt aus der Datenbank unbekannt."); exit (1); } //* //***** //***** (6) //* Wurde eine neue Session-ID erzeugt dann muß auch das Subsystem neu gestartet werden. //* Ist es eine in der Datenbank vorhandene kombination aus Session-ID und Subsystem wird //* geprüft ob der Prozess noch läuft. Wenn er das tut werden die Daten von der CGI-Schnittstelle //* an diesen Prozess gesendet. Läuft der Prozess nicht mehr wird er wie bei einer neuen //* Session-ID wieder neu gestartet. //* std::string strProzessId = ""; if (boolNeueSessionId) { // Das Subsystem neu starten. if (strSubsystemArt == "Daemon") { if (boolDebugInfo) syslog (LOG_INFO, "Subsystem: '%s' als Daemon starten.", strProgramm.c_str ()); HtsStartProg Subsystem (strLoginUser); strProzessId = Subsystem.StartDaemon (strProgramm, ""); // Aktuallisiere die neue Prozess-ID in der Datenbank. pSession->updateSessionDaten (strCgiSessionId, strSubsystem, strProzessId, strLoginUser); } } else { // Lese die Prozess-ID zur aktuellen Session-ID, Subsystem kombination. strProzessId = pSession->getProzessId (strSubsystem); // Prüfe ob das Subsystem zu dieser Session-ID noch läuft. if (!pSession->checkSubsystemProzess (strProzessId)) { // Das Subsystem neu starten. if (strSubsystemArt == "Daemon") { if (boolDebugInfo) syslog (LOG_INFO, "Subsystem: '%s' als Daemon starten.", strProgramm.c_str ()); HtsStartProg Subsystem (strLoginUser); strProzessId = Subsystem.StartDaemon (strProgramm, ""); // Aktuallisiere die Prozess-ID in der Datenbank. pSession->updateSessionDaten (strCgiSessionId, strSubsystem, strProzessId, strLoginUser); } } } //* //***** //***** (7) //* Komunikation mit dem Subsystem durchführen. //* Sende die neue Seite über die Standardausgabe zum Apache Webserver. //* //std::cout << "content-type: text/html\n\n"; int iSocket = 0; try { //***** //* Socket erzeugen. std::string strSocketName = "Socketfiles/"; strSocketName = strSocketName + strProzessId; iSocket = 0; struct sockaddr_un address; if ((iSocket = socket (PF_LOCAL, SOCK_STREAM, 0)) > 0) syslog (LOG_INFO, "HtsCgiLogin->main: Socket wurde angelegt."); address.sun_family = AF_LOCAL; strcpy (address.sun_path, strSocketName.c_str ()); //* Verbindung herstellen. int iVersuche = 1; for (; iVersuche < 100; iVersuche++) { if (connect (iSocket, (struct sockaddr *) &address, sizeof (address)) == 0) { syslog (LOG_INFO, "Verbindung (connect) mit dem Subsystem hergestellt. iVersuche: '%d'", iVersuche); break; } else sleep (1); } syslog (LOG_INFO, "Verbindung (connect), iVersuche: '%d'", iVersuche); //* //***** //***** //* Lese die Bereitschaftsmeldung des Subsystems std::string strReady = ""; int iSize = 0; char szBuffer[1024]; for (iVersuche = 1; iVersuche < 100; iVersuche++) { iSize = recv (iSocket, &szBuffer, sizeof (szBuffer) - 1, 0); if (iSize > 0) szBuffer[iSize] = '\0'; if (iSize == -1) { strReady = ""; sleep (1); } else { strReady = szBuffer; break; } } syslog (LOG_INFO, "Ready lesen (recv) strReady: '%s', iSize: '%d', iVersuche: '%d'", strReady.c_str (), iSize, iVersuche); //* //***** // Prüfe ob das Subsystem ein Ready gesendet hat. if (strReady == "Ready\n") { //***** //* Sende die CGI-Daten zum Subsystem. //* // Wichtige Informationen für das zum Subsystem gehörende Programm an die CGI-Daten anhängen. pCgi->Set ("Subsystem", strSubsystem); pCgi->Set ("HttpLocation", strHttpLocation); // Den Header mit der länge der zu sendenden Daten vorne einfügen. std::ostringstream iToString; iToString << pCgi->getCgiStream().size(); std::string strCgiDaten = "content-length: "; strCgiDaten = strCgiDaten + iToString.str () + "\n\n"; strCgiDaten = strCgiDaten + pCgi->getCgiStream () + "\n"; syslog (LOG_INFO, "CGI-Daten: %s", strCgiDaten.c_str()); send (iSocket, strCgiDaten.c_str () + '\0', strCgiDaten.size (), 0); //* //***** //***** //* Lese die neue Seite vom Subsystem. std::string strNeueSeite = ""; int iSize = 0; int iLength = 0; int iContentLength = 0; int boolHeaderLesen = true; for (;;) { iSize = recv (iSocket, &szBuffer, sizeof (szBuffer) - 1, 0); if (iSize == 0) // Der Returnwert 0 zeigt an das das Subsystem die Verbindung beendet hat. { if (iContentLength == iLength) break; else { syslog (LOG_INFO, "HtsCgiLogin->main: nicht alle Daten des Subsystems gelesen, erwartet: '%d', gelesen: '%d'.", iContentLength, iLength); exit (1); } } else if (iSize > 0) // Ein Returnwert > 0 zeigt an das Daten aus dem Socket gelesen wurden. { // Die gelesenen Date zu einem String zusammenbauen. szBuffer[iSize] = '\0'; strNeueSeite = strNeueSeite + szBuffer; iLength = iLength + iSize; // Prüfe ob alle Header gelesen wurden. if (boolHeaderLesen) { int iPos = strNeueSeite.find ("\n\n", 0); if (iPos != std::string::npos) { // Den content-length Header suchen und den Wert ausschneiden und einen int daraus machen. std::string strHeaderName = "content-length:"; int iPosA = strNeueSeite.find (strHeaderName, 0); int iPosB = strNeueSeite.find ("\n", iPosA); iPosA = iPosA + strHeaderName.size (); std::string strContentLength = strNeueSeite.substr (iPosA, iPosB - iPosA); std::stringstream StringToInt (strContentLength); StringToInt >> iContentLength; // Zum Prüfen der Content länge die Header länge von den gelesenen Daten abziehen. iLength = iLength - (iPos + 3); // Header aus den gelesenen Daten entfernen. // +2 um die zwei Newline der Trennung Header/Content mit zu entfernen. strNeueSeite.erase (0, iPos + 2); // Setze den Merker das die Header verarbeitet wurden. boolHeaderLesen = false; } } } else if (iSize == -1) // Der Returnwert -1 zeigt an das ein Fehler aufgetretten ist. { syslog (LOG_INFO, "HtsCgiLogin->main: Fehler beim lesen der neuen Seite."); exit (1); } } syslog (LOG_INFO, "strNeueSeite: '%s'", strNeueSeite.c_str ()); //* //***** // Sende die neue Seite zum Client. std::cout << strNeueSeite; } else { syslog (LOG_INFO, "Bereitschaftmeldung vom Subsystem nicht empfangen (Ready)."); exit (1); } } catch (std::exception &e) { syslog (LOG_INFO, "Fehler beim Daten lesen vom Subsystem: '%s'", e.what ()); exit (1); } catch (...) { syslog (LOG_INFO, "Fehler beim Daten lesen vom Subsystem: 'unbekannte Exception'"); exit (1); } close (iSocket); syslog (LOG_INFO, "Programm beendet"); //* //***** return 0; }