1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#include "config.h"
#include <stdexcept>
#include <string>
#include <iostream>
#include <fcgiapp.h>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <fmt/format.h>
namespace pt = boost::property_tree;
using namespace std::string_literals;
namespace {
class PostData
{
public:
PostData(FCGX_Request& request) {
std::string result;
std::string contentLengthString(FCGX_GetParam("CONTENT_LENGTH", request.envp));
int contentLength = std::stoul(contentLengthString);
result.resize(contentLength);
unsigned int status = FCGX_GetStr(result.data(), result.size(), request.in);
if (status != result.size()) {
throw std::runtime_error(fmt::format("Read error: {}/{}", status, result.size()));
}
m_data = result;
}
std::string getData()
{
return m_data;
}
// path: xml path, e.g. data.value
std::string getXMLElement(const std::string& path)
{
pt::ptree tree{};
std::istringstream iss{m_data};
pt::read_xml(iss, tree, pt::xml_parser::trim_whitespace);
return tree.get<std::string>(path);
}
private:
std::string m_data;
};
std::string getCommand(FCGX_Request& request)
{
std::string query = FCGX_GetParam("QUERY_STRING", request.envp);
size_t pos = query.find("command=");
if (pos != query.npos) {
return query.substr(pos + 8);
} else {
return {};
}
}
std::string to_xml()
{
std::string result{"<data><status>ok</status><ui>"};
result += "ui1</ui>";
return result + "</data>";
}
} // namespace
int main(int argc, char* argv[]) {
try {
Config config{argc, argv};
std::string ok_data{"<data><status>ok</status><message>OK</message></data>"};
std::string error_data{"<data><status>error</status><message>General Error</message></data>"};
int result = FCGX_Init();
if (result != 0) {
return 1; // error on init
}
FCGX_Request request;
if (FCGX_InitRequest(&request, 0, 0) != 0) {
return 1; // error on init
}
while (FCGX_Accept_r(&request) == 0) {
std::string method = FCGX_GetParam("REQUEST_METHOD", request.envp);
FCGX_PutS("Content-Type: text/xml\r\n\r\n", request.out);
try {
if (method == "POST") {
PostData data{request};
std::string command {getCommand(request)};
if (command == "start") {
FCGX_PutS(ok_data.c_str(), request.out);
} else if (command == "stop") {
FCGX_PutS(ok_data.c_str(), request.out);
} else if (command == "getui") {
FCGX_PutS(to_xml().c_str(), request.out);
} else if (command == "setfile") {
std::string filename = data.getXMLElement("data.value");
FCGX_PutS(ok_data.c_str(), request.out);
} else {
FCGX_PutS(error_data.c_str(), request.out);
}
} else {
throw std::runtime_error(fmt::format("Bad request method: POST expected, got {}", method).c_str());
}
} catch (const std::exception& ex) {
FCGX_PutS(("<data><status>error</status><message>Error: "s + ex.what() + "</message></data>").c_str(), request.out);
}
}
} catch (const std::exception& ex) {
std::cerr << "Error: " << ex.what() << std::endl;
}
return 0;
}
|