]> git.stg.codes - stg.git/blob - projects/sgconf/xml.cpp
Merge branch 'stg-2.409-radius'
[stg.git] / projects / sgconf / xml.cpp
1 #include "xml.h"
2
3 #include "api_action.h"
4 #include "options.h"
5 #include "config.h"
6
7 #include "stg/servconf.h"
8
9 #include <iostream>
10 #include <string>
11 #include <map>
12
13 #include <expat.h>
14
15 namespace
16 {
17
18 struct ParserState
19 {
20 size_t level;
21 };
22
23 std::string Indent(size_t level)
24 {
25 return std::string(level * 4, ' ');
26 }
27
28 std::string PrintAttr(const char ** attr)
29 {
30 std::string res;
31 if (attr == NULL)
32     return res;
33 while (*attr)
34     {
35     if (*(attr + 1) == NULL)
36         return res;
37     res += std::string(" ") + *attr + "=\"" + *(attr + 1) + "\"";
38     ++attr; ++attr;
39     }
40 return res;
41 }
42
43 void Start(void * data, const char * el, const char ** attr)
44 {
45 ParserState * state = static_cast<ParserState *>(data);
46 if (el != NULL)
47     std::cout << Indent(state->level) << "<" << el << PrintAttr(attr) << ">\n";
48 ++state->level;
49 }
50
51 void End(void * data, const char * el)
52 {
53 ParserState * state = static_cast<ParserState *>(data);
54 --state->level;
55 if (el != NULL)
56     std::cout << Indent(state->level) << "</" << el << ">\n";
57 }
58
59 void PrintXML(const std::string& xml)
60 {
61 ParserState state = { 0 };
62
63 XML_Parser parser = XML_ParserCreate(NULL);
64 XML_ParserReset(parser, NULL);
65 XML_SetElementHandler(parser, Start, End);
66 XML_SetUserData(parser, &state);
67
68 if (XML_Parse(parser, xml.c_str(), xml.length(), true) == XML_STATUS_ERROR)
69     std::cerr << "XML parse error at line " << XML_GetCurrentLineNumber(parser)
70               << ": '" << XML_ErrorString(XML_GetErrorCode(parser)) << "'"
71               << std::endl;
72
73 XML_ParserFree(parser);
74 }
75
76 void RawXMLCallback(bool result, const std::string & reason, const std::string & response, void * /*data*/)
77 {
78 if (!result)
79     {
80     std::cerr << "Failed to get raw XML response. Reason: '" << reason << "'." << std::endl;
81     return;
82     }
83 PrintXML(response);
84 }
85
86 bool RawXMLFunction(const SGCONF::CONFIG & config,
87                     const std::string & arg,
88                     const std::map<std::string, std::string> & /*options*/)
89 {
90 STG::SERVCONF proto(config.server.data(),
91                     config.port.data(),
92                     config.localAddress.data(),
93                     config.localPort.data(),
94                     config.userName.data(),
95                     config.userPass.data());
96 return proto.RawXML(arg, RawXMLCallback, NULL) == STG::st_ok;
97 }
98
99 }
100
101 void SGCONF::AppendXMLOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
102 {
103 blocks.Add("Raw XML")
104       .Add("r", "raw", SGCONF::MakeAPIAction(commands, "<xml>", RawXMLFunction), "\tmake raw XML request");
105 }