Probleme mit cgi



  • Bin dabei ein kleines cgi zu schreiben, leider liefert es keine Ergebnisse zurück.
    cgi.cpp

    #include <iostream>
    #include <string>
    #include <fstream>
    #include "include/libhtml++.h"
    
    using namespace std;
    
    bool cgi::anfrage()
    {
        query = string(); // Gespeicherten Wert zurücksetzen
    
        char *request = getenv("REQUEST_METHOD");
        char *env = getenv("QUERY_STRING");
    
        if( request == 0)
        { 
            return false; // Änderung des Rückgabewerts
        }
    
        if (request == "GET")
        {
            if (env != 0)
            {
                query = env;
                return true;   // Rückgabewert geändert
            }
            else
            {
                return false; // Rückgabewert geändert
            }
        }
        else
            return false;
    }
    
    bool cgi::output(const string& formname)
    {
    if (anfrage())
    {
    
    if ( query.find(formname, start))
    {
    start += 1;
    end = query.find("&", start);
    if (end == 0)
    {
    end = query.size();
    }
    else
    {
    end -= 1;
    }
    query = query.substr(start,end);
    return true;
    }
    
    else
    {
    return false;
    }
    
    }
    
    else
    return false;
    
    };
    

    libhtml++.h

    #include <iostream>
    #include <string>
    #include <sstream>
    
    using namespace std;
    
    class cgi
    {
    private:
    
    int start;
    int end;
    
    public:
    string query;
    bool anfrage();
    bool output(const string& formname);
    };
    
    class htmlformsubmit
    {
    private:
    void inputsubmit( string submitname);
    public:
    htmlformsubmit(string submitname)
    {
    inputsubmit(submitname);
    };
    
    };
    
    class htmlformselect
    {
    private:
    void formselectdisplay(string formselectname, string formselectinput, string methodform);
    public:
    htmlformselect(string formselectname, string formselectinput, string methodform)
    {
    formselectdisplay (formselectname, formselectinput, methodform);
    };
    
    };
    

    nutzung der funktion:

    void libcss::libcssout()
    {
    cgi css;
    string cssstyle;
    
    if (css.output("cssstyle"))
    {
    cssstyle = css.query;
    }
    else
    {
    cssstyle = "default";
    }
    
    cout << "<link rel=\"stylesheet\" type=\"text/css\" href=\"" << folder << "/" << cssstyle << "/"<< "main.css" << "\">" << endl;
    
    }
    

    leider bekomme ich keine ausgabe

    source ftp://tuxist.de/tuxist/tuxcms.tar.gz



  • Kennst du den Unterschied zwischen std::string und char*? Mir scheint, du kennst ihn nicht.

    ...
    bool cgi::anfrage()
    {
        query = string(); // Gespeicherten Wert zurücksetzen
    
        char *request = getenv("REQUEST_METHOD");
        char *env = getenv("QUERY_STRING");
    
        if( request == 0)
        { 
            return false; // Änderung des Rückgabewerts
        }
    
        if (request == "GET")
    

    Du vergleichst hier zwei Zeiger. Diese Bedinung wird nur dann wahr, wenn request auf die Adresse des statischen Zeichenkettenliterals "GET" zeigt, was selten der Fall sein dürfte. Was du machen könntest, wäre

    if(request == std::string("GET"))
    

    das ruft dann den passenden operator== auf, der die beiden Strings nach Inhalt vergleicht, nicht ihre Speicheradressen. 🙂

    Gruß,

    Roker



  • Roker schrieb:

    if(request == std::string("GET"))
    

    Entweder das oder

    if (strcmp(request, "GET"))
    


  • Falsch,

    if (strcmp(request, "GET") == 0)
    


  • darthdespotism schrieb:

    Roker schrieb:

    if(request == std::string("GET"))
    

    Entweder das oder

    if (strcmp(request, "GET"))
    

    Naja, ich dachte, wir machen hier C++, nicht C. Ich finde das C++-Beispiel mit std::string wesentlich intuitiver als deines. Außerdem ist dein Code falsch, wie Th hier schon gemerkt hat. Das scheint meine Meinung zu bestärken, dass man die C-Funktionen nicht nutzen sollte, wenn es sich - wie in diesem Falle - vermeiden lässt.

    Gruß,
    Roker



  • Unter Performancegesichtspunkten wäre es sicher sinnvoll, die temporäre String-Kopie (und die damit einhergehende Fragmentierung des Heaps) zu vermeiden, aber das ist Mikrooptimierung. Eine gute Lösung wäre, die eingehenden Daten direkt als std::string(s) zu verwalten, dann braucht man das Literal garnicht umwandeln 😉

    (Komisch, ich habe eine natürliche Abneigung, Literale nur temporär umzuwandeln, aber das Ergebnis von getenv würde ich nach NULL-Prüfung bedenkenlos in einen string kopieren)



  • Also ich persönlich finde auch die String-Konvertierung von Literalen nicht so schön, da die String-Klasse die Zeichenkette (char 😉 kopiert. (Für die zumeist kleinen Literal-Strings zwar egal, aber schöner wäre es wenn die String-Klasse intern copy-on-write verwenden würde - ich weiß nicht, ob der Standard dies zuläßt, aber die gängigen Implementierungen verwenden es nicht).

    P.S: Die Rückgabewerte von 'getenv' würde ich als 'const char *' deklarieren...



  • Th schrieb:

    schöner wäre es wenn die String-Klasse intern copy-on-write verwenden würde - ich weiß nicht, ob der Standard dies zuläßt, aber die gängigen Implementierungen verwenden es nicht).

    Es ist zugelassen (es wird sogar AFAIR explizit auf diese mögliche Implementierung hingewiesen) und soweit ich weiß gab es sogar eine Zeit, in der mehrere Implementierungen das so gehandhabt haben (Stroustrup geht in TC++PL auch explizit darauf ein).

    Inzwischen wird es nicht mehr gemacht, weil die copy-on-write-Methode zu falschen Semantiken führen kann:

    string a = "Hallo";
    string::iterator i = a.begin();
    string b  = a; // Verzögerte Kopie
    *i = 'x';
    cout << b << endl; // Erwartet: "Hallo", tatsächliche Ausgabe: "xallo"
    

    Ich finde das zwar ein vertretbares Trade-off aber die meisten Bibliotheks-Hersteller scheinen anderer Meinung zu sein (und haben wahrscheinlich recht).



  • danke Rocker erst einaml hat geholfen 😉

    hätte noch eine Frage 🙄
    Wieso ghet das nicht:

    {
    if (query.find(formname, start))
    {
    	start += 1;
    end = query.find("&", start); 
    
    	if (end != string::npos)
    		end -= 1;
    	if (end == string::npos)
    		end = query.length();
    
    size = end -= start;
    queryout = query.substr(start, size);
    
    	return true;
    
    }
    

    wenn den int wert von ende minus start rechne müsste ich die substring länge ja haben welche ich für substring benötige.

    bekomme aber immer nur :

    terminate called after throwing an instance of 'std::out_of_range'
      what():  basic_string::substr
    


  • so habe alles so hinbekommen wie ich wollte danke nochmal.

    bool cgi::output(const string& formname)
    {
    
    if (anfrage())
    {
    f_start = query.find(formname);
    if ( f_start != string::npos)
    {
    v_start = query.find("=", f_start);
    v_start += 1;
    end = query.find("&", v_start); 
    
    	if (end != string::npos)
    		end -= 1;
    	if (end == string::npos)
    		end = query.length();
    size = end - v_start;
    queryout = query.substr(v_start, size);
    
    	return true;
    }
    else
    {
    return false;
    }
    
    }
    
    else
    return false;
    
    };
    

Anmelden zum Antworten