#include "MIDIPlayer.h" #include #include #include #include #include #include #include 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(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(const std::vector& filelist, const std::string& selected) { std::string result{"ok"}; for (const auto& i: filelist) { result += "" + i + ""; } result += ""; result += "" + selected + ""; return result + ""; } } // namespace int main(int argc, char* argv[]) { try { MIDIPlayer player; std::string ok_data{"okOK"}; std::string error_data{"errorGeneral Error"}; 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); try { if (method == "POST") { FCGX_PutS("Content-Type: text/xml\r\n\r\n", request.out); PostData data{request}; std::string command {getCommand(request)}; if (command == "start") { player.start(); FCGX_PutS(ok_data.c_str(), request.out); } else if (command == "stop") { player.stop(); FCGX_PutS(ok_data.c_str(), request.out); } else if (command == "getlist") { FCGX_PutS(to_xml(player.get_filelist(), player.get_file()).c_str(), request.out); } else if (command == "setfile") { std::string filename = data.getXMLElement("data.value"); player.set_file(filename); 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("Content-Type: text/xml\r\n\r\n", request.out); FCGX_PutS(("error"s + ex.what() + "").c_str(), request.out); } } } catch (const std::exception& ex) { std::cerr << "Error: " << ex.what() << std::endl; } return 0; }