Expose FlightHistory as a http service
usage: GET http://localhost:8080/flighthistory/track.json retrieves track as JSON data { flightHistory: [ { latitude: (number), longitude: (number), altitude: (number) } ] } GET http://localhost:8080/flighthistory/track.kml retrieves track as KML path optional request parameter: LineColor=(hex encoded rgba color) LineWidth=(line width in pixel) PolyColor=(hex encoded rgba color) interval=(number of seconds to auto-refresh)
This commit is contained in:
parent
68c9adb489
commit
cc6178a9f3
7 changed files with 444 additions and 78 deletions
|
@ -5,12 +5,14 @@ set(SOURCES
|
||||||
ScreenshotUriHandler.cxx
|
ScreenshotUriHandler.cxx
|
||||||
PropertyUriHandler.cxx
|
PropertyUriHandler.cxx
|
||||||
JsonUriHandler.cxx
|
JsonUriHandler.cxx
|
||||||
|
FlightHistoryUriHandler.cxx
|
||||||
PkgUriHandler.cxx
|
PkgUriHandler.cxx
|
||||||
RunUriHandler.cxx
|
RunUriHandler.cxx
|
||||||
NavdbUriHandler.cxx
|
NavdbUriHandler.cxx
|
||||||
PropertyChangeWebsocket.cxx
|
PropertyChangeWebsocket.cxx
|
||||||
PropertyChangeObserver.cxx
|
PropertyChangeObserver.cxx
|
||||||
jsonprops.cxx
|
jsonprops.cxx
|
||||||
|
SimpleDOM.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
|
@ -19,6 +21,7 @@ set(HEADERS
|
||||||
ScreenshotUriHandler.hxx
|
ScreenshotUriHandler.hxx
|
||||||
PropertyUriHandler.hxx
|
PropertyUriHandler.hxx
|
||||||
JsonUriHandler.hxx
|
JsonUriHandler.hxx
|
||||||
|
FlightHistoryUriHandler.hxx
|
||||||
PkgUriHandler.hxx
|
PkgUriHandler.hxx
|
||||||
RunUriHandler.hxx
|
RunUriHandler.hxx
|
||||||
NavdbUriHandler.hxx
|
NavdbUriHandler.hxx
|
||||||
|
@ -27,6 +30,7 @@ set(HEADERS
|
||||||
PropertyChangeWebsocket.hxx
|
PropertyChangeWebsocket.hxx
|
||||||
PropertyChangeObserver.hxx
|
PropertyChangeObserver.hxx
|
||||||
jsonprops.hxx
|
jsonprops.hxx
|
||||||
|
SimpleDOM.hxx
|
||||||
)
|
)
|
||||||
|
|
||||||
flightgear_component(Http "${SOURCES}" "${HEADERS}")
|
flightgear_component(Http "${SOURCES}" "${HEADERS}")
|
||||||
|
|
275
src/Network/http/FlightHistoryUriHandler.cxx
Normal file
275
src/Network/http/FlightHistoryUriHandler.cxx
Normal file
|
@ -0,0 +1,275 @@
|
||||||
|
// FlightHistoryUriHandler.cxx -- FlightHistory service
|
||||||
|
//
|
||||||
|
// Written by Torsten Dreyer, started February 2015.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 Torsten Dreyer
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
#include "FlightHistoryUriHandler.hxx"
|
||||||
|
#include "SimpleDOM.hxx"
|
||||||
|
#include <3rdparty/cjson/cJSON.h>
|
||||||
|
|
||||||
|
#include <Aircraft/FlightHistory.hxx>
|
||||||
|
#include <Main/fg_props.hxx>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::stringstream;
|
||||||
|
|
||||||
|
namespace flightgear {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
static cJSON * GeodToJson(const SGGeod & geod) {
|
||||||
|
cJSON * json = cJSON_CreateObject();
|
||||||
|
|
||||||
|
cJSON_AddItemToObject(json, "latitude",
|
||||||
|
cJSON_CreateNumber(geod.getLatitudeDeg()));
|
||||||
|
cJSON_AddItemToObject(json, "longitude",
|
||||||
|
cJSON_CreateNumber(geod.getLongitudeDeg()));
|
||||||
|
cJSON_AddItemToObject(json, "altitude",
|
||||||
|
cJSON_CreateNumber(geod.getElevationFt()));
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string FlightHistoryToJson(const SGGeodVec & history) {
|
||||||
|
cJSON * json = cJSON_CreateObject();
|
||||||
|
|
||||||
|
cJSON * jsonArray = cJSON_CreateArray();
|
||||||
|
for (SGGeodVec::const_iterator it = history.begin(); it != history.end();
|
||||||
|
++it) {
|
||||||
|
cJSON_AddItemToArray(jsonArray, GeodToJson(*it));
|
||||||
|
}
|
||||||
|
cJSON_AddItemToObject(json, "flightHistory", jsonArray);
|
||||||
|
|
||||||
|
char * jsonString = cJSON_PrintUnformatted(json);
|
||||||
|
string reply(jsonString);
|
||||||
|
free(jsonString);
|
||||||
|
cJSON_Delete(json);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string AutoUpdateResponse(const HTTPRequest & request,
|
||||||
|
const string & base, const string & interval) {
|
||||||
|
|
||||||
|
string url = "http://";
|
||||||
|
url.append(request.HeaderVariables.get("Host")).append(base);
|
||||||
|
|
||||||
|
std::string reply("<?xml version='1.0' encoding='UTF-8'?>");
|
||||||
|
DOMNode * kml = new DOMNode("kml");
|
||||||
|
kml->setAttribute("xmlns", "http://www.opengis.net/kml/2.2");
|
||||||
|
|
||||||
|
DOMNode * document = kml->addChild(new DOMNode("Document"));
|
||||||
|
|
||||||
|
DOMNode * networkLink = document->addChild(new DOMNode("NetworkLink"));
|
||||||
|
DOMNode * link = networkLink->addChild(new DOMNode("Link"));
|
||||||
|
link->addChild(new DOMNode("href"))->addChild(new DOMTextElement(url));
|
||||||
|
link->addChild(new DOMNode("refreshMode"))->addChild(
|
||||||
|
new DOMTextElement("onInterval"));
|
||||||
|
link->addChild(new DOMNode("refreshInterval"))->addChild(
|
||||||
|
new DOMTextElement(interval.empty() ? "10" : interval));
|
||||||
|
|
||||||
|
reply.append(kml->render());
|
||||||
|
delete kml;
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string FlightHistoryToKml(const SGGeodVec & history,
|
||||||
|
const HTTPRequest & request) {
|
||||||
|
string interval = request.RequestVariables.get("interval");
|
||||||
|
if (false == interval.empty()) {
|
||||||
|
return AutoUpdateResponse(request, "/flighthistory/track.kml", interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string reply("<?xml version='1.0' encoding='UTF-8'?>");
|
||||||
|
DOMNode * kml = new DOMNode("kml");
|
||||||
|
kml->setAttribute("xmlns", "http://www.opengis.net/kml/2.2");
|
||||||
|
|
||||||
|
DOMNode * document = kml->addChild(new DOMNode("Document"));
|
||||||
|
|
||||||
|
document->addChild(new DOMNode("name"))->addChild(
|
||||||
|
new DOMTextElement("FlightGear"));
|
||||||
|
document->addChild(new DOMNode("description"))->addChild(
|
||||||
|
new DOMTextElement("FlightGear Flight History"));
|
||||||
|
|
||||||
|
DOMNode * style = document->addChild(new DOMNode("Style"))->setAttribute(
|
||||||
|
"id", "flight-history");
|
||||||
|
DOMNode * lineStyle = style->addChild(new DOMNode("LineStyle"));
|
||||||
|
|
||||||
|
string lineColor = request.RequestVariables.get("LineColor");
|
||||||
|
string lineWidth = request.RequestVariables.get("LineWidth");
|
||||||
|
string polyColor = request.RequestVariables.get("PolyColor");
|
||||||
|
|
||||||
|
lineStyle->addChild(new DOMNode("color"))->addChild(
|
||||||
|
new DOMTextElement(lineColor.empty() ? "427ebfff" : lineColor));
|
||||||
|
lineStyle->addChild(new DOMNode("width"))->addChild(
|
||||||
|
new DOMTextElement(lineWidth.empty() ? "4" : lineWidth));
|
||||||
|
|
||||||
|
lineStyle = style->addChild(new DOMNode("PolyStyle"));
|
||||||
|
lineStyle->addChild(new DOMNode("color"))->addChild(
|
||||||
|
new DOMTextElement(polyColor.empty() ? "fbfc4600" : polyColor));
|
||||||
|
|
||||||
|
DOMNode * placemark = document->addChild(new DOMNode("Placemark"));
|
||||||
|
placemark->addChild(new DOMNode("name"))->addChild(
|
||||||
|
new DOMTextElement("Flight Path"));
|
||||||
|
placemark->addChild(new DOMNode("styleUrl"))->addChild(
|
||||||
|
new DOMTextElement("#flight-history"));
|
||||||
|
|
||||||
|
DOMNode * linestring = placemark->addChild(new DOMNode("LineString"));
|
||||||
|
linestring->addChild(new DOMNode("extrude"))->addChild(
|
||||||
|
new DOMTextElement("1"));
|
||||||
|
linestring->addChild(new DOMNode("tessalate"))->addChild(
|
||||||
|
new DOMTextElement("1"));
|
||||||
|
linestring->addChild(new DOMNode("altitudeMode"))->addChild(
|
||||||
|
new DOMTextElement("absolute"));
|
||||||
|
|
||||||
|
stringstream ss;
|
||||||
|
|
||||||
|
for (SGGeodVec::const_iterator it = history.begin(); it != history.end();
|
||||||
|
++it) {
|
||||||
|
ss << (*it).getLongitudeDeg() << "," << (*it).getLatitudeDeg() << ","
|
||||||
|
<< it->getElevationM() << " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
linestring->addChild(new DOMNode("coordinates"))->addChild(
|
||||||
|
new DOMTextElement(ss.str()));
|
||||||
|
|
||||||
|
reply.append(kml->render());
|
||||||
|
delete kml;
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool GetJsonDouble(cJSON * json, const char * item, double & out) {
|
||||||
|
cJSON * cj = cJSON_GetObjectItem(json, item);
|
||||||
|
if (NULL == cj)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (cj->type != cJSON_Number)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
out = cj->valuedouble;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool GetJsonBool(cJSON * json, const char * item, bool & out) {
|
||||||
|
cJSON * cj = cJSON_GetObjectItem(json, item);
|
||||||
|
if (NULL == cj)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (cj->type == cJSON_True) {
|
||||||
|
out = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (cj->type == cJSON_False) {
|
||||||
|
out = true;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FlightHistoryUriHandler::handleRequest(const HTTPRequest & request,
|
||||||
|
HTTPResponse & response, Connection * connection) {
|
||||||
|
response.Header["Access-Control-Allow-Origin"] = "*";
|
||||||
|
response.Header["Access-Control-Allow-Methods"] = "OPTIONS, GET, POST";
|
||||||
|
response.Header["Access-Control-Allow-Headers"] =
|
||||||
|
"Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token";
|
||||||
|
|
||||||
|
if (request.Method == "OPTIONS") {
|
||||||
|
return true; // OPTIONS only needs the headers
|
||||||
|
}
|
||||||
|
|
||||||
|
FGFlightHistory* history =
|
||||||
|
static_cast<FGFlightHistory*>(globals->get_subsystem("history"));
|
||||||
|
|
||||||
|
double minEdgeLengthM = 50;
|
||||||
|
string requestPath = request.Uri.substr(getUri().length());
|
||||||
|
|
||||||
|
if (request.Method == "GET") {
|
||||||
|
} else if (request.Method == "POST") {
|
||||||
|
/*
|
||||||
|
* {
|
||||||
|
* sampleIntervalSec: (number),
|
||||||
|
* maxMemoryUseBytes: (number),
|
||||||
|
* clearOnTakeoff: (bool),
|
||||||
|
* enabled: (bool),
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
cJSON * json = cJSON_Parse(request.Content.c_str());
|
||||||
|
if ( NULL != json) {
|
||||||
|
double d = .0;
|
||||||
|
bool b = false;
|
||||||
|
bool doReinit = false;
|
||||||
|
if (GetJsonDouble(json, "sampleIntervalSec", d)) {
|
||||||
|
fgSetDouble("/sim/history/sample-interval-sec", d);
|
||||||
|
doReinit = true;
|
||||||
|
}
|
||||||
|
if (GetJsonDouble(json, "maxMemoryUseBytes", d)) {
|
||||||
|
fgSetDouble("/sim/history/max-memory-use-bytes", d);
|
||||||
|
doReinit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetJsonBool(json, "clearOnTakeoff", b)) {
|
||||||
|
fgSetBool("/sim/history/clear-on-takeoff", b);
|
||||||
|
doReinit = true;
|
||||||
|
}
|
||||||
|
if (GetJsonBool(json, "enabled", b)) {
|
||||||
|
fgSetBool("/sim/history/enabled", b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doReinit) {
|
||||||
|
history->reinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON_Delete(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Content = "{}";
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
SG_LOG(SG_NETWORK, SG_INFO,
|
||||||
|
"PkgUriHandler: invalid request method '" << request.Method << "'");
|
||||||
|
response.Header["Allow"] = "OPTIONS, GET, POST";
|
||||||
|
response.StatusCode = 405;
|
||||||
|
response.Content = "{}";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestPath == "track.kml") {
|
||||||
|
response.Header["Content-Type"] =
|
||||||
|
"application/vnd.google-earth.kml+xml; charset=UTF-8";
|
||||||
|
|
||||||
|
response.Content = FlightHistoryToKml(
|
||||||
|
history->pathForHistory(minEdgeLengthM), request);
|
||||||
|
|
||||||
|
} else if (requestPath == "track.json") {
|
||||||
|
response.Header["Content-Type"] = "application/json; charset=UTF-8";
|
||||||
|
response.Content = FlightHistoryToJson(
|
||||||
|
history->pathForHistory(minEdgeLengthM));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
response.StatusCode = 404;
|
||||||
|
response.Content = "{}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace http
|
||||||
|
} // namespace flightgear
|
||||||
|
|
40
src/Network/http/FlightHistoryUriHandler.hxx
Normal file
40
src/Network/http/FlightHistoryUriHandler.hxx
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// FlightHistoryUriHandler.hxx -- FlightHistory service
|
||||||
|
//
|
||||||
|
// Written by Torsten Dreyer, started February 2015.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 Torsten Dreyer
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
#ifndef __FG_FLIGHTHISTORY_URI_HANDLER_HXX
|
||||||
|
#define __FG_FLIGHTHISTORY_URI_HANDLER_HXX
|
||||||
|
|
||||||
|
#include "urihandler.hxx"
|
||||||
|
#include <simgear/props/props.hxx>
|
||||||
|
|
||||||
|
namespace flightgear {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
class FlightHistoryUriHandler : public URIHandler {
|
||||||
|
public:
|
||||||
|
FlightHistoryUriHandler( const char * uri = "/flighthistory/" ) : URIHandler( uri ) {}
|
||||||
|
virtual bool handleRequest( const HTTPRequest & request, HTTPResponse & response, Connection * connection );
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace http
|
||||||
|
} // namespace flightgear
|
||||||
|
|
||||||
|
#endif //#define __FG_FLIGHTHISTORY_URI_HANDLER_HXX
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "PropertyUriHandler.hxx"
|
#include "PropertyUriHandler.hxx"
|
||||||
|
#include "SimpleDOM.hxx"
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
#include <simgear/misc/strutils.hxx>
|
#include <simgear/misc/strutils.hxx>
|
||||||
|
@ -63,84 +64,6 @@ static inline std::string htmlSpecialChars( const std::string & s )
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DOMElement {
|
|
||||||
public:
|
|
||||||
virtual ~DOMElement() {}
|
|
||||||
virtual std::string render() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DOMTextElement : public DOMElement {
|
|
||||||
public:
|
|
||||||
DOMTextElement( const string & text ) : _text(text) {}
|
|
||||||
virtual std::string render() const { return _text; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
string _text;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class DOMNode : public DOMElement {
|
|
||||||
public:
|
|
||||||
DOMNode( const string & name ) : _name(name) {}
|
|
||||||
virtual ~DOMNode();
|
|
||||||
|
|
||||||
virtual std::string render() const;
|
|
||||||
virtual DOMNode * addChild( DOMElement * child );
|
|
||||||
virtual DOMNode * setAttribute( const string & name, const string & value );
|
|
||||||
protected:
|
|
||||||
string _name;
|
|
||||||
typedef vector<const DOMElement*> Children_t;
|
|
||||||
typedef map<string,string> Attributes_t;
|
|
||||||
Children_t _children;
|
|
||||||
Attributes_t _attributes;
|
|
||||||
};
|
|
||||||
|
|
||||||
DOMNode::~DOMNode()
|
|
||||||
{
|
|
||||||
for( Children_t::const_iterator it = _children.begin(); it != _children.end(); ++it )
|
|
||||||
delete *it;
|
|
||||||
}
|
|
||||||
|
|
||||||
string DOMNode::render() const
|
|
||||||
{
|
|
||||||
string reply;
|
|
||||||
reply.append( "<" ).append( _name );
|
|
||||||
for( Attributes_t::const_iterator it = _attributes.begin(); it != _attributes.end(); ++it ) {
|
|
||||||
reply.append( " " );
|
|
||||||
reply.append( it->first );
|
|
||||||
reply.append( "=\"" );
|
|
||||||
reply.append( it->second );
|
|
||||||
reply.append( "\"" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( _children.empty() ) {
|
|
||||||
reply.append( " />\r" );
|
|
||||||
return reply;
|
|
||||||
} else {
|
|
||||||
reply.append( ">" );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( Children_t::const_iterator it = _children.begin(); it != _children.end(); ++it ) {
|
|
||||||
reply.append( (*it)->render() );
|
|
||||||
}
|
|
||||||
|
|
||||||
reply.append( "</" ).append( _name ).append( ">\r" );
|
|
||||||
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
DOMNode * DOMNode::addChild( DOMElement * child )
|
|
||||||
{
|
|
||||||
_children.push_back( child );
|
|
||||||
return dynamic_cast<DOMNode*>(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
DOMNode * DOMNode::setAttribute( const string & name, const string & value )
|
|
||||||
{
|
|
||||||
_attributes[name] = value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
class SortedChilds : public simgear::PropertyList {
|
class SortedChilds : public simgear::PropertyList {
|
||||||
public:
|
public:
|
||||||
SortedChilds( SGPropertyNode_ptr node ) {
|
SortedChilds( SGPropertyNode_ptr node ) {
|
||||||
|
|
54
src/Network/http/SimpleDOM.cxx
Normal file
54
src/Network/http/SimpleDOM.cxx
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#include "SimpleDOM.hxx"
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
namespace flightgear {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
DOMNode::~DOMNode()
|
||||||
|
{
|
||||||
|
for( Children_t::const_iterator it = _children.begin(); it != _children.end(); ++it )
|
||||||
|
delete *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
string DOMNode::render() const
|
||||||
|
{
|
||||||
|
string reply;
|
||||||
|
reply.append( "<" ).append( _name );
|
||||||
|
for( Attributes_t::const_iterator it = _attributes.begin(); it != _attributes.end(); ++it ) {
|
||||||
|
reply.append( " " );
|
||||||
|
reply.append( it->first );
|
||||||
|
reply.append( "=\"" );
|
||||||
|
reply.append( it->second );
|
||||||
|
reply.append( "\"" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _children.empty() ) {
|
||||||
|
reply.append( " />\r" );
|
||||||
|
return reply;
|
||||||
|
} else {
|
||||||
|
reply.append( ">" );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( Children_t::const_iterator it = _children.begin(); it != _children.end(); ++it ) {
|
||||||
|
reply.append( (*it)->render() );
|
||||||
|
}
|
||||||
|
|
||||||
|
reply.append( "</" ).append( _name ).append( ">\r" );
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMNode * DOMNode::addChild( DOMElement * child )
|
||||||
|
{
|
||||||
|
_children.push_back( child );
|
||||||
|
return dynamic_cast<DOMNode*>(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMNode * DOMNode::setAttribute( const string & name, const string & value )
|
||||||
|
{
|
||||||
|
_attributes[name] = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
64
src/Network/http/SimpleDOM.hxx
Normal file
64
src/Network/http/SimpleDOM.hxx
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// SimpleDOM.hxx -- poor man's DOM
|
||||||
|
//
|
||||||
|
// Written by Torsten Dreyer
|
||||||
|
//
|
||||||
|
// Copyright (C) 2014 Torsten Dreyer
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
#ifndef __FG_SIMPLE_DOM_HXX
|
||||||
|
#define __FG_SIMPLE_DOM_HXX
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace flightgear {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
class DOMElement {
|
||||||
|
public:
|
||||||
|
virtual ~DOMElement() {}
|
||||||
|
virtual std::string render() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DOMTextElement : public DOMElement {
|
||||||
|
public:
|
||||||
|
DOMTextElement( const std::string & text ) : _text(text) {}
|
||||||
|
virtual std::string render() const { return _text; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string _text;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DOMNode : public DOMElement {
|
||||||
|
public:
|
||||||
|
DOMNode( const std::string & name ) : _name(name) {}
|
||||||
|
virtual ~DOMNode();
|
||||||
|
|
||||||
|
virtual std::string render() const;
|
||||||
|
virtual DOMNode * addChild( DOMElement * child );
|
||||||
|
virtual DOMNode * setAttribute( const std::string & name, const std::string & value );
|
||||||
|
protected:
|
||||||
|
std::string _name;
|
||||||
|
typedef std::vector<const DOMElement*> Children_t;
|
||||||
|
typedef std::map<std::string,std::string> Attributes_t;
|
||||||
|
Children_t _children;
|
||||||
|
Attributes_t _attributes;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // __FG_SIMPLE_DOM_HXX
|
|
@ -24,6 +24,7 @@
|
||||||
#include "ScreenshotUriHandler.hxx"
|
#include "ScreenshotUriHandler.hxx"
|
||||||
#include "PropertyUriHandler.hxx"
|
#include "PropertyUriHandler.hxx"
|
||||||
#include "JsonUriHandler.hxx"
|
#include "JsonUriHandler.hxx"
|
||||||
|
#include "FlightHistoryUriHandler.hxx"
|
||||||
#include "PkgUriHandler.hxx"
|
#include "PkgUriHandler.hxx"
|
||||||
#include "RunUriHandler.hxx"
|
#include "RunUriHandler.hxx"
|
||||||
#include "NavdbUriHandler.hxx"
|
#include "NavdbUriHandler.hxx"
|
||||||
|
@ -459,6 +460,11 @@ void MongooseHttpd::init()
|
||||||
}
|
}
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
|
if ((uri = n->getStringValue("flighthistory"))[0] != 0) {
|
||||||
|
SG_LOG(SG_NETWORK, SG_INFO, "httpd: adding flighthistory uri handler at " << uri);
|
||||||
|
_uriHandler.push_back(new flightgear::http::FlightHistoryUriHandler(uri));
|
||||||
|
}
|
||||||
|
|
||||||
if ((uri = n->getStringValue("run"))[0] != 0) {
|
if ((uri = n->getStringValue("run"))[0] != 0) {
|
||||||
SG_LOG(SG_NETWORK, SG_INFO, "httpd: adding run uri handler at " << uri);
|
SG_LOG(SG_NETWORK, SG_INFO, "httpd: adding run uri handler at " << uri);
|
||||||
_uriHandler.push_back(new flightgear::http::RunUriHandler(uri));
|
_uriHandler.push_back(new flightgear::http::RunUriHandler(uri));
|
||||||
|
|
Loading…
Add table
Reference in a new issue