webui - "cgi" handler and multiple fixes (#700)

* initial commit of webconfig

* update example config with webconfig and fix format of file
update debian postinst script for install example config

* fix compiling
add new web server command "serverinfo" to use in webapp to retrieve json port

* change web default port to 8099

* add cgi engine to webserver

* fix include
This commit is contained in:
redPanther
2016-06-14 20:14:06 +02:00
committed by brindosch
parent eb64e7e528
commit 4a841710dd
12 changed files with 193 additions and 67 deletions

View File

@@ -114,6 +114,7 @@ void Effect::run()
{
std::cerr << "EFFECTENGINE ERROR: Unable to open script file " << _script << std::endl;
}
fclose(file);
// Clean up the thread state
Py_EndInterpreter(_interpreterThreadState);

View File

@@ -615,7 +615,7 @@ MessageForwarder * Hyperion::getForwarder()
return _messageForwarder;
}
Hyperion::Hyperion(const Json::Value &jsonConfig) :
Hyperion::Hyperion(const Json::Value &jsonConfig, const std::string configFile) :
_ledString(createLedString(jsonConfig["leds"], createColorOrder(jsonConfig["device"]))),
_muxer(_ledString.leds().size()),
_raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"])),
@@ -625,6 +625,8 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) :
_device(LedDeviceFactory::construct(jsonConfig["device"])),
_effectEngine(nullptr),
_messageForwarder(createMessageForwarder(jsonConfig["forwarder"])),
_jsonConfig(jsonConfig),
_configFile(configFile),
_timer()
{
if (!_raw2ledAdjustment->verifyAdjustments())

View File

@@ -46,7 +46,7 @@ Logger::Logger ( std::string name, LogLevel minLevel ):
_syslogEnabled(true),
_loggerId(loggerId++)
{
#ifdef __linux__
#ifdef __GLIBC__
_appname = std::string(program_invocation_short_name);
#else
_appname = std::string(getprogname());

View File

@@ -10,6 +10,7 @@ set(WebConfig_QT_HEADERS
${CURRENT_SOURCE_DIR}/QtHttpReply.h
${CURRENT_SOURCE_DIR}/QtHttpRequest.h
${CURRENT_SOURCE_DIR}/QtHttpServer.h
${CURRENT_SOURCE_DIR}/CgiHandler.h
${CURRENT_SOURCE_DIR}/StaticFileServing.h
${CURRENT_HEADER_DIR}/WebConfig.h
)
@@ -23,6 +24,7 @@ set(WebConfig_SOURCES
${CURRENT_SOURCE_DIR}/QtHttpReply.cpp
${CURRENT_SOURCE_DIR}/QtHttpRequest.cpp
${CURRENT_SOURCE_DIR}/QtHttpServer.cpp
${CURRENT_SOURCE_DIR}/CgiHandler.cpp
${CURRENT_SOURCE_DIR}/StaticFileServing.cpp
${CURRENT_SOURCE_DIR}/WebConfig.cpp
)

View File

@@ -0,0 +1,69 @@
#include <QStringBuilder>
#include <QUrlQuery>
#include <QFile>
#include <QByteArray>
#include "CgiHandler.h"
CgiHandler::CgiHandler (Hyperion * hyperion, QObject * parent)
: QObject(parent)
, _hyperion(hyperion)
, _hyperionConfig(_hyperion->getJsonConfig())
{
}
CgiHandler::~CgiHandler()
{
}
void CgiHandler::exec(const QStringList & args, QtHttpReply * reply)
{
try
{
cmd_cfg_jsonserver(args,reply);
cmd_cfg_hyperion(args,reply);
throw 1;
}
catch(int e)
{
if (e != 0)
throw 1;
}
}
void CgiHandler::cmd_cfg_jsonserver(const QStringList & args, QtHttpReply * reply)
{
if ( args.at(0) == "cfg_jsonserver" )
{
quint16 jsonPort = 19444;
if (_hyperionConfig.isMember("jsonServer"))
{
const Json::Value & jsonConfig = _hyperionConfig["jsonServer"];
jsonPort = jsonConfig.get("port", jsonPort).asUInt();
}
// send result as reply
reply->addHeader ("Content-Type", "text/plain" );
reply->appendRawData (QByteArrayLiteral(":") % QString::number(jsonPort).toUtf8() );
throw 0;
}
}
void CgiHandler::cmd_cfg_hyperion(const QStringList & args, QtHttpReply * reply)
{
if ( args.at(0) == "cfg_hyperion" )
{
QFile file ( _hyperion->getConfigFileName().c_str() );
if (file.exists ())
{
if (file.open (QFile::ReadOnly)) {
QByteArray data = file.readAll ();
reply->addHeader ("Content-Type", "text/plain");
reply->appendRawData (data);
file.close ();
}
}
throw 0;
}
}

View File

@@ -0,0 +1,34 @@
#ifndef CGIHANDLER_H
#define CGIHANDLER_H
#include <QObject>
#include <QString>
#include <QStringList>
#include <utils/jsonschema/JsonFactory.h>
#include <hyperion/Hyperion.h>
#include "QtHttpReply.h"
class CgiHandler : public QObject {
Q_OBJECT
public:
CgiHandler (Hyperion * hyperion, QObject * parent = NULL);
virtual ~CgiHandler (void);
void exec(const QStringList & args, QtHttpReply * reply);
// cgi commands
void cmd_cfg_jsonserver(const QStringList & args, QtHttpReply * reply);
void cmd_cfg_hyperion (const QStringList & args, QtHttpReply * reply);
private:
Hyperion* _hyperion;
QtHttpReply * _reply;
const Json::Value &_hyperionConfig;
};
#endif // CGIHANDLER_H

View File

@@ -8,12 +8,13 @@
#include <QPair>
#include <QFile>
StaticFileServing::StaticFileServing (QString baseUrl, quint16 port, quint16 jsonPort, QObject * parent)
: QObject (parent)
, m_baseUrl (baseUrl)
, _jsonPort (jsonPort)
StaticFileServing::StaticFileServing (Hyperion *hyperion, QString baseUrl, quint16 port, QObject * parent)
: QObject (parent)
, _hyperion(hyperion)
, _baseUrl (baseUrl)
, _cgi(hyperion, this)
{
m_mimeDb = new QMimeDatabase;
_mimeDb = new QMimeDatabase;
_server = new QtHttpServer (this);
_server->setServerName (QStringLiteral ("Qt Static HTTP File Server"));
@@ -57,23 +58,31 @@ void StaticFileServing::onRequestNeedsReply (QtHttpRequest * request, QtHttpRepl
if (command == QStringLiteral ("GET"))
{
QString path = request->getUrl ().path ();
QStringList uri_parts = path.split('/', QString::SkipEmptyParts);
// special uri handling for server commands
if ( path == "/serverinfo" )
if ( ! uri_parts.empty() && uri_parts.at(0) == "cgi" )
{
reply->addHeader ("Content-Type", "text/plain" );
reply->appendRawData (QByteArrayLiteral(":") % QString::number(_jsonPort).toUtf8() );
uri_parts.removeAt(0);
try
{
_cgi.exec(uri_parts, reply);
}
catch(...)
{
printErrorToReply (reply, "cgi script failed (" % path % ")");
}
return;
}
// get static files
if ( path == "/" || path.isEmpty() || ! QFile::exists(m_baseUrl % "/" % path) )
if ( path == "/" || path.isEmpty() || ! QFile::exists(_baseUrl % "/" % path) )
path = "index.html";
QFile file (m_baseUrl % "/" % path);
QFile file (_baseUrl % "/" % path);
if (file.exists ())
{
QMimeType mime = m_mimeDb->mimeTypeForFile (file.fileName ());
QMimeType mime = _mimeDb->mimeTypeForFile (file.fileName ());
if (file.open (QFile::ReadOnly)) {
QByteArray data = file.readAll ();
reply->addHeader ("Content-Type", mime.name ().toLocal8Bit ());
@@ -82,7 +91,7 @@ void StaticFileServing::onRequestNeedsReply (QtHttpRequest * request, QtHttpRepl
}
else
{
printErrorToReply (reply, "Requested file " % m_baseUrl % "/" % path % " couldn't be open for reading !");
printErrorToReply (reply, "Requested file " % path % " couldn't be open for reading !");
}
}
else

View File

@@ -8,12 +8,15 @@
#include "QtHttpRequest.h"
#include "QtHttpReply.h"
#include "QtHttpHeader.h"
#include "CgiHandler.h"
#include <hyperion/Hyperion.h>
class StaticFileServing : public QObject {
Q_OBJECT
public:
explicit StaticFileServing (QString baseUrl, quint16 port, quint16 jsonPort, QObject * parent = NULL);
explicit StaticFileServing (Hyperion *hyperion, QString baseUrl, quint16 port, QObject * parent = NULL);
virtual ~StaticFileServing (void);
public slots:
@@ -23,10 +26,11 @@ public slots:
void onRequestNeedsReply (QtHttpRequest * request, QtHttpReply * reply);
private:
QString m_baseUrl;
QtHttpServer * _server;
QMimeDatabase * m_mimeDb;
quint16 _jsonPort;
Hyperion * _hyperion;
QString _baseUrl;
QtHttpServer * _server;
QMimeDatabase * _mimeDb;
CgiHandler _cgi;
};
#endif // STATICFILESERVING_H

View File

@@ -1,23 +1,16 @@
#include "webconfig/webconfig.h"
#include "webconfig/WebConfig.h"
#include "StaticFileServing.h"
WebConfig::WebConfig(std::string baseUrl, quint16 port, quint16 jsonPort, QObject * parent) :
_parent(parent),
_baseUrl(QString::fromStdString(baseUrl)),
_port(port),
_jsonPort(jsonPort),
_server(nullptr)
{
}
WebConfig::WebConfig(const Json::Value &config, QObject * parent) :
_parent(parent),
_port(WEBCONFIG_DEFAULT_PORT),
_server(nullptr)
WebConfig::WebConfig(Hyperion *hyperion, QObject * parent)
: QObject(parent)
, _hyperion(hyperion)
, _port(WEBCONFIG_DEFAULT_PORT)
, _server(nullptr)
{
const Json::Value &config = hyperion->getJsonConfig();
_baseUrl = QString::fromStdString(WEBCONFIG_DEFAULT_PATH);
_jsonPort = 19444;
bool webconfigEnable = true;
if (config.isMember("webConfig"))
@@ -28,13 +21,6 @@ WebConfig::WebConfig(const Json::Value &config, QObject * parent) :
_baseUrl = QString::fromStdString( webconfigConfig.get("document_root", WEBCONFIG_DEFAULT_PATH).asString() );
}
if (config.isMember("jsonServer"))
{
const Json::Value & jsonConfig = config["jsonServer"];
_jsonPort = jsonConfig.get("port", 19444).asUInt();
}
if ( webconfigEnable )
start();
}
@@ -49,7 +35,7 @@ WebConfig::~WebConfig()
void WebConfig::start()
{
if ( _server == nullptr )
_server = new StaticFileServing (_baseUrl, _port, _jsonPort, this);
_server = new StaticFileServing (_hyperion, _baseUrl, _port, this);
}
void WebConfig::stop()