]> git.mxchange.org Git - flightgear.git/blobdiff - src/Network/httpd.cxx
Update to the Mini FDM network protocal (mostly renaming class and file names)
[flightgear.git] / src / Network / httpd.cxx
index f2c237fff2060f7d83a0a45d56f88361b24e3588..162bf45ec6ec92816ce0b45f78d8f774205fba58 100644 (file)
@@ -1,10 +1,13 @@
-// httpd.hxx -- FGFS http property manager interface / external script
+// httpd.cxx -- FGFS http property manager interface / external script
 //              and control class
 //
 // Written by Curtis Olson, started June 2001.
 //
 // Copyright (C) 2001  Curtis L. Olson - curt@flightgear.org
 //
+// Jpeg Image Support added August 2001
+//  by Norman Vine - nhv@cape.com
+//
 // This program is free software; you can redistribute it and/or
 // modify it under the terms of the GNU General Public License as
 // published by the Free Software Foundation; either version 2 of the
 
 #include <simgear/compiler.h>
 
-#include <simgear/debug/logstream.hxx>
-#include <simgear/io/iochannel.hxx>
-#include <simgear/math/sg_types.hxx>
-#include <simgear/misc/props.hxx>
-
 #include <stdlib.h>            // atoi() atof()
 
 #include STL_STRING
 #include STL_STRSTREAM
 
+#include <simgear/debug/logstream.hxx>
+#include <simgear/io/iochannel.hxx>
+#include <simgear/math/sg_types.hxx>
+#include <simgear/misc/commands.hxx>
+#include <simgear/misc/props.hxx>
+
 #include <Main/fg_props.hxx>
 #include <Main/globals.hxx>
 
 #include "httpd.hxx"
 
 SG_USING_STD(string);
-#if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
 SG_USING_STD(cout);
 SG_USING_STD(istrstream);
-#endif
 
 
 bool FGHttpd::open() {
@@ -58,8 +60,8 @@ bool FGHttpd::open() {
     }
 
     server = new HttpdServer( port );
-
-    set_hz( 5 );                // default to processing requests @ 5Hz
+    
+    set_hz( 15 );                // default to processing requests @ 15Hz
     set_enabled( true );
 
     return true;
@@ -82,6 +84,9 @@ bool FGHttpd::close() {
 
 // Handle http GET requests
 void HttpdChannel::foundTerminator (void) {
+    
+    closeWhenDone ();
+
     const string s = buffer.getData();
 
     if ( s.find( "GET " ) == 0 ) {
@@ -91,7 +96,7 @@ void HttpdChannel::foundTerminator (void) {
         string request;
         string tmp;
 
-        unsigned int pos = rest.find( " " );
+        string::size_type pos = rest.find( " " );
         if ( pos != string::npos ) {
             request = rest.substr( 0, pos );
         } else {
@@ -105,6 +110,7 @@ void HttpdChannel::foundTerminator (void) {
             string args = request.substr( pos + 1 );
             request = request.substr( 0, pos );
             printf("'%s' '%s'\n", request.c_str(), args.c_str());
+            request = urlDecode(request);
 
             // parse args looking for "value="
             bool done = false;
@@ -120,19 +126,38 @@ void HttpdChannel::foundTerminator (void) {
                 }
 
                 printf("  arg = %s\n", arg.c_str() );
-                unsigned int apos = arg.find("=");
+                string::size_type apos = arg.find("=");
                 if ( apos != string::npos ) {
                     string a = arg.substr( 0, apos );
                     string b = arg.substr( apos + 1 );
                     printf("    a = %s  b = %s\n", a.c_str(), b.c_str() );
-                    if ( a == "value" ) {
-                        fgSetString( request, b );
-                    } 
+                    if ( request == "/run.cgi" ) {
+                        // execute a command
+                        if ( a == "value" ) {
+                            SGPropertyNode args;
+                            if ( !globals->get_commands()
+                                 ->execute(urlDecode(b).c_str(), &args) )
+                            {
+                                SG_LOG( SG_GENERAL, SG_ALERT,
+                                        "Command " << urlDecode(b)
+                                        << " failed.");
+                            }
+
+                        }
+                    } else {
+                        if ( a == "value" ) {
+                            // update a property value
+                            fgSetString( request.c_str(),
+                                         urlDecode(b).c_str() );
+                        }
+                    }
                 }
             }
-        }
+        } else {
+            request = urlDecode(request);
+       }
 
-        node = globals->get_props()->getNode(request);
+        node = globals->get_props()->getNode(request.c_str());
 
         string response = "";
         response += "<HTML LANG=\"en\">";
@@ -141,7 +166,7 @@ void HttpdChannel::foundTerminator (void) {
         response += "<HEAD>";
         response += getTerminator();
 
-        response += "<TITLE>HUD - ";
+        response += "<TITLE>FlightGear - ";
         response += request;
         response += "</TITLE>";
         response += getTerminator();
@@ -152,7 +177,15 @@ void HttpdChannel::foundTerminator (void) {
         response += "<BODY>";
         response += getTerminator();
 
-        if ( node->nChildren() > 0 ) {
+        if (node == NULL) {
+            response += "<H3>Non-existent node requested!</H3>";
+            response += getTerminator();
+
+            response += "<B>";
+            response += request.c_str();
+            response += "</B> does not exist.";
+            response += getTerminator();
+       } else if ( node->nChildren() > 0 ) {
             // request is a path with children
             response += "<H3>Contents of \"";
             response += request;
@@ -161,29 +194,29 @@ void HttpdChannel::foundTerminator (void) {
 
             for (int i = 0; i < node->nChildren(); i++) {
                 SGPropertyNode *child = node->getChild(i);
-                string name = child->getName();
+                string name = child->getDisplayName(true);
                 string line = "";
                 if ( child->nChildren() > 0 ) {
                     line += "<B><A HREF=\"";
                     line += request;
-                    if ( request.substr(request.length() - 1, 1) != "/" ) {
+                    if ( request.substr(request.length() - 1, 1) != (string)"/" ) {
                         line += "/";
                     }
-                    line += name;
+                    line += urlEncode(name);
                     line += "\">";
                     line += name;
                     line += "</A></B>";
                     line += "/<BR>";
                 } else {
-                    string value = node->getStringValue ( name, "" );
+                    string value = node->getStringValue ( name.c_str(), "" );
                     line += "<B>";
                     line += name;
                     line += "</B> <A HREF=\"";
                     line += request;
-                    if ( request.substr(request.length() - 1, 1) != "/" ) {
+                    if ( request.substr(request.length() - 1, 1) != (string)"/" ) {
                         line += "/";
                     }
-                    line += name;
+                    line += urlEncode(name);
                     line += "\">(";
                     line += value;
                     line += ")</A><BR>";
@@ -196,17 +229,16 @@ void HttpdChannel::foundTerminator (void) {
             string value = node->getStringValue();
             
             response += "<form method=\"GET\" action=\"";
-            response += request;
+            response += urlEncode(request);
             response += "\">";
             response += "<B>";
             response += request;
             response += "</B> = ";
-            response += "<input type=text name=value size=\"5\" value=\"";
+            response += "<input type=text name=value size=\"15\" value=\"";
             response += value;
             response += "\" maxlength=2047>";
             response += "<input type=submit value=\"update\" name=\"submit\">";
-            response += "<FORM>";
-            response += "<BR>";
+            response += "</FORM>";
         }
         response += "</BODY>";
         response += getTerminator();
@@ -235,3 +267,45 @@ void HttpdChannel::foundTerminator (void) {
 
     buffer.remove();
 }
+
+
+// encode everything but "a-zA-Z0-9_.-/" (see RFC2396)
+string HttpdChannel::urlEncode(string s) {
+    string r = "";
+    
+    for ( int i = 0; i < (int)s.length(); i++ ) {
+        if ( isalnum(s[i]) || s[i] == '_' || s[i] == '.'
+                || s[i] == '-' || s[i] == '/' ) {
+            r += s[i];
+        } else {
+            char buf[16];
+            sprintf(buf, "%%%02X", (unsigned char)s[i]);
+            r += buf;
+        }
+    }
+    return r;
+}
+
+
+string HttpdChannel::urlDecode(string s) {
+    string r = "";
+    int max = s.length();
+    int a, b;
+
+    for ( int i = 0; i < max; i++ ) {
+        if ( s[i] == '+' ) {
+            r += ' ';
+        } else if ( s[i] == '%' && i + 2 < max
+                && isxdigit(s[i + 1])
+                && isxdigit(s[i + 2]) ) {
+            i++;
+            a = isdigit(s[i]) ? s[i] - '0' : toupper(s[i]) - 'A' + 10;
+            i++;
+            b = isdigit(s[i]) ? s[i] - '0' : toupper(s[i]) - 'A' + 10;
+            r += (char)(a * 16 + b);
+        } else {
+            r += s[i];
+        }
+    }
+    return r;
+}