]> git.stg.codes - stg.git/blobdiff - sgconf/xml.cpp
Port to CMake, get rid of os_int.h.
[stg.git] / sgconf / xml.cpp
diff --git a/sgconf/xml.cpp b/sgconf/xml.cpp
new file mode 100644 (file)
index 0000000..abf2ccc
--- /dev/null
@@ -0,0 +1,105 @@
+#include "xml.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+
+#include "stg/servconf.h"
+
+#include <iostream>
+#include <string>
+#include <map>
+
+#include <expat.h>
+
+namespace
+{
+
+struct ParserState
+{
+size_t level;
+};
+
+std::string Indent(size_t level)
+{
+return std::string(level * 4, ' ');
+}
+
+std::string PrintAttr(const char ** attr)
+{
+std::string res;
+if (attr == NULL)
+    return res;
+while (*attr)
+    {
+    if (*(attr + 1) == NULL)
+        return res;
+    res += std::string(" ") + *attr + "=\"" + *(attr + 1) + "\"";
+    ++attr; ++attr;
+    }
+return res;
+}
+
+void Start(void * data, const char * el, const char ** attr)
+{
+ParserState * state = static_cast<ParserState *>(data);
+if (el != NULL)
+    std::cout << Indent(state->level) << "<" << el << PrintAttr(attr) << ">\n";
+++state->level;
+}
+
+void End(void * data, const char * el)
+{
+ParserState * state = static_cast<ParserState *>(data);
+--state->level;
+if (el != NULL)
+    std::cout << Indent(state->level) << "</" << el << ">\n";
+}
+
+void PrintXML(const std::string& xml)
+{
+ParserState state = { 0 };
+
+XML_Parser parser = XML_ParserCreate(NULL);
+XML_ParserReset(parser, NULL);
+XML_SetElementHandler(parser, Start, End);
+XML_SetUserData(parser, &state);
+
+if (XML_Parse(parser, xml.c_str(), xml.length(), true) == XML_STATUS_ERROR)
+    std::cerr << "XML parse error at line " << XML_GetCurrentLineNumber(parser)
+              << ": '" << XML_ErrorString(XML_GetErrorCode(parser)) << "'"
+              << std::endl;
+
+XML_ParserFree(parser);
+}
+
+void RawXMLCallback(bool result, const std::string & reason, const std::string & response, void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Failed to get raw XML response. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+PrintXML(response);
+}
+
+bool RawXMLFunction(const SGCONF::CONFIG & config,
+                    const std::string & arg,
+                    const std::map<std::string, std::string> & /*options*/)
+{
+STG::SERVCONF proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.RawXML(arg, RawXMLCallback, NULL) == STG::st_ok;
+}
+
+}
+
+void SGCONF::AppendXMLOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+blocks.Add("Raw XML")
+      .Add("r", "raw", SGCONF::MakeAPIAction(commands, "<xml>", RawXMLFunction), "\tmake raw XML request");
+}