]> git.stg.codes - stg.git/blob - libs/srvconf/servconf.cpp
Fix XML-RPC module compilation on C++17-only compilers.
[stg.git] / libs / srvconf / servconf.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
19  *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
20  */
21
22 #include "stg/servconf.h"
23
24 #include "netunit.h"
25
26 #include "parsers/simple.h"
27 #include "parsers/get_container.h"
28
29 #include "parsers/server_info.h"
30
31 #include "parsers/get_admin.h"
32 #include "parsers/chg_admin.h"
33
34 #include "parsers/get_tariff.h"
35 #include "parsers/chg_tariff.h"
36
37 #include "parsers/auth_by.h"
38 #include "parsers/get_user.h"
39 #include "parsers/chg_user.h"
40
41 #include "parsers/get_service.h"
42 #include "parsers/chg_service.h"
43
44 #include "parsers/get_corp.h"
45 #include "parsers/chg_corp.h"
46
47 #include "parsers/base.h"
48
49 #include "stg/common.h"
50
51 #include <cstdio>
52 #include <cstring>
53 #include <clocale>
54
55 #include <expat.h>
56 #include <langinfo.h>
57
58 using namespace STG;
59
60 class ServConf::Impl
61 {
62     public:
63         Impl(const std::string& server, uint16_t port,
64              const std::string& login, const std::string& password);
65         Impl(const std::string& server, uint16_t port,
66              const std::string& localAddress, uint16_t localPort,
67              const std::string& login, const std::string& password);
68         ~Impl() { XML_ParserFree(parser); }
69
70         const std::string& GetStrError() const;
71         static void Start(void* data, const char* el, const char** attr);
72         static void End(void* data, const char* el);
73
74         int RawXML(const std::string& request, RawXML::Callback f, void* data);
75
76         template <class P, typename C>
77         int Exec(const std::string& request, C callback, void* data)
78         {
79             return ExecImpl(request, P(callback, data, encoding));
80         }
81
82         template <class P, typename C>
83         int Exec(const std::string& tag, const std::string& request, C callback, void* data)
84         {
85             return ExecImpl(request, P(tag, callback, data, encoding));
86         }
87
88         const std::string& Encoding() const { return encoding; }
89
90     private:
91         NetTransact nt;
92
93         std::string encoding;
94         std::string errorMsg;
95         XML_Parser parser;
96
97         static bool ParserRecv(const std::string& chunk, bool last, void* data);
98         static bool SimpleRecv(const std::string& chunk, bool last, void* data);
99         int ExecImpl(const std::string& request, Parser&& cp);
100 };
101
102 bool ServConf::Impl::ParserRecv(const std::string& chunk, bool last, void* data)
103 {
104     auto sc = static_cast<ServConf::Impl*>(data);
105
106     if (XML_Parse(sc->parser, chunk.c_str(), chunk.length(), last) == XML_STATUS_ERROR)
107     {
108         strprintf(&sc->errorMsg, "XML parse error at line %d, %d: %s. Is last: %d",
109                   static_cast<int>(XML_GetCurrentLineNumber(sc->parser)),
110                   static_cast<int>(XML_GetCurrentColumnNumber(sc->parser)),
111                   XML_ErrorString(XML_GetErrorCode(sc->parser)), static_cast<int>(last));
112         return false;
113     }
114
115     return true;
116 }
117
118 bool ServConf::Impl::SimpleRecv(const std::string& chunk, bool /*last*/, void* data)
119 {
120     *static_cast<std::string*>(data) += chunk;
121     return true;
122 }
123
124 ServConf::ServConf(const std::string& server, uint16_t port,
125                    const std::string& login, const std::string& password)
126     : pImpl(new Impl(server, port, login, password))
127 {
128 }
129
130 ServConf::ServConf(const std::string& server, uint16_t port,
131                    const std::string& localAddress, uint16_t localPort,
132                    const std::string& login, const std::string& password)
133     : pImpl(new Impl(server, port, localAddress, localPort, login, password))
134 {
135 }
136
137 ServConf::~ServConf()
138 {
139     delete pImpl;
140 }
141
142 int ServConf::ServerInfo(ServerInfo::Callback f, void* data)
143 {
144     return pImpl->Exec<ServerInfo::Parser>("<GetServerInfo/>", f, data);
145 }
146
147 int ServConf::RawXML(const std::string& request, RawXML::Callback f, void* data)
148 {
149     return pImpl->RawXML(request, f, data);
150 }
151
152 // -- Admins --
153
154 int ServConf::GetAdmins(GetContainer::Callback<GetAdmin::Info>::Type f, void* data)
155 {
156     return pImpl->Exec<GetContainer::Parser<GetAdmin::Parser> >("admins", "<GetAdmins/>", f, data);
157 }
158
159 int ServConf::GetAdmin(const std::string& login, GetAdmin::Callback f, void* data)
160 {
161     return pImpl->Exec<GetAdmin::Parser>("<GetAdmin login=\"" + login + "\"/>", f, data);
162 }
163
164 int ServConf::ChgAdmin(const AdminConfOpt& conf, Simple::Callback f, void* data)
165 {
166     return pImpl->Exec<Simple::Parser>("ChgAdmin", "<ChgAdmin" + ChgAdmin::serialize(conf, pImpl->Encoding()) + "/>", f, data);
167 }
168
169 int ServConf::AddAdmin(const std::string& login,
170                        const AdminConfOpt& conf,
171                        Simple::Callback f, void* data)
172 {
173     auto res = pImpl->Exec<Simple::Parser>("AddAdmin", "<AddAdmin login=\"" + login + "\"/>", f, data);
174     if (res != st_ok)
175         return res;
176     return pImpl->Exec<Simple::Parser>("ChgAdmin", "<ChgAdmin" + ChgAdmin::serialize(conf, pImpl->Encoding()) + "/>", f, data);
177 }
178
179 int ServConf::DelAdmin(const std::string& login, Simple::Callback f, void* data)
180 {
181     return pImpl->Exec<Simple::Parser>("DelAdmin", "<DelAdmin login=\"" + login + "\"/>", f, data);
182 }
183
184 // -- Tariffs --
185
186 int ServConf::GetTariffs(GetContainer::Callback<GetTariff::Info>::Type f, void* data)
187 {
188     return pImpl->Exec<GetContainer::Parser<GetTariff::Parser> >("tariffs", "<GetTariffs/>", f, data);
189 }
190
191 int ServConf::GetTariff(const std::string& name, GetTariff::Callback f, void* data)
192 {
193     return pImpl->Exec<GetTariff::Parser>("<GetTariff name=\"" + name + "\"/>", f, data);
194 }
195
196 int ServConf::ChgTariff(const TariffDataOpt& tariffData, Simple::Callback f, void* data)
197 {
198     return pImpl->Exec<Simple::Parser>("SetTariff", "<SetTariff name=\"" + tariffData.tariffConf.name.value() + "\">" + ChgTariff::serialize(tariffData, pImpl->Encoding()) + "</SetTariff>", f, data);
199 }
200
201 int ServConf::AddTariff(const std::string& name,
202                         const TariffDataOpt& tariffData,
203                         Simple::Callback f, void* data)
204 {
205     auto res = pImpl->Exec<Simple::Parser>("AddTariff", "<AddTariff name=\"" + name + "\"/>", f, data);
206     if (res != st_ok)
207         return res;
208     return pImpl->Exec<Simple::Parser>("SetTariff", "<SetTariff name=\"" + name + "\">" + ChgTariff::serialize(tariffData, pImpl->Encoding()) + "</SetTariff>", f, data);
209 }
210
211 int ServConf::DelTariff(const std::string& name, Simple::Callback f, void* data)
212 {
213     return pImpl->Exec<Simple::Parser>("DelTariff", "<DelTariff name=\"" + name + "\"/>", f, data);
214 }
215
216 // -- Users --
217
218 int ServConf::GetUsers(GetContainer::Callback<GetUser::Info>::Type f, void* data)
219 {
220     return pImpl->Exec<GetContainer::Parser<GetUser::Parser> >("users", "<GetUsers/>", f, data);
221 }
222
223 int ServConf::GetUser(const std::string& login, GetUser::Callback f, void* data)
224 {
225     return pImpl->Exec<GetUser::Parser>("<GetUser login=\"" + login + "\"/>", f, data);
226 }
227
228 int ServConf::ChgUser(const std::string& login,
229                       const UserConfOpt& conf,
230                       const UserStatOpt& stat,
231                       Simple::Callback f, void* data)
232 {
233     return pImpl->Exec<ChgUser::Parser>("<SetUser><Login value=\"" + login + "\"/>" + ChgUser::serialize(conf, stat, pImpl->Encoding()) + "</SetUser>", f, data);
234 }
235
236 int ServConf::DelUser(const std::string& login, Simple::Callback f, void* data)
237 {
238     return pImpl->Exec<Simple::Parser>("DelUser", "<DelUser login=\"" + login + "\"/>", f, data);
239 }
240
241 int ServConf::AddUser(const std::string& login,
242                       const UserConfOpt& conf,
243                       const UserStatOpt& stat,
244                       Simple::Callback f, void* data)
245 {
246     auto res = pImpl->Exec<Simple::Parser>("AddUser", "<AddUser><Login value=\"" + login + "\"/></AddUser>", f, data);
247     if (res != st_ok)
248         return res;
249     return pImpl->Exec<ChgUser::Parser>("<SetUser><Login value=\"" + login + "\"/>" + ChgUser::serialize(conf, stat, pImpl->Encoding()) + "</SetUser>", f, data);
250 }
251
252 int ServConf::AuthBy(const std::string& login, AuthBy::Callback f, void* data)
253 {
254     return pImpl->Exec<AuthBy::Parser>("<GetUserAuthBy login=\"" + login + "\"/>", f, data);
255 }
256
257 int ServConf::SendMessage(const std::string& login, const std::string& text, Simple::Callback f, void* data)
258 {
259     return pImpl->Exec<Simple::Parser>("SendMessageResult", "<Message login=\"" + login + "\" msgver=\"1\" msgtype=\"1\" repeat=\"0\" repeatperiod=\"0\" showtime=\"0\" text=\"" + Encode12str(text) + "\"/>", f, data);
260 }
261
262 int ServConf::CheckUser(const std::string& login, const std::string& password, Simple::Callback f, void* data)
263 {
264     return pImpl->Exec<Simple::Parser>("CheckUser", "<CheckUser login=\"" + login + "\" password=\"" + password + "\"/>", f, data);
265 }
266
267 // -- Services --
268
269 int ServConf::GetServices(GetContainer::Callback<GetService::Info>::Type f, void* data)
270 {
271     return pImpl->Exec<GetContainer::Parser<GetService::Parser> >("services", "<GetServices/>", f, data);
272 }
273
274 int ServConf::GetService(const std::string& name, GetService::Callback f, void* data)
275 {
276     return pImpl->Exec<GetService::Parser>("<GetService name=\"" + name + "\"/>", f, data);
277 }
278
279 int ServConf::ChgService(const ServiceConfOpt& conf, Simple::Callback f, void* data)
280 {
281     return pImpl->Exec<Simple::Parser>("SetService", "<SetService " + ChgService::serialize(conf, pImpl->Encoding()) + "/>", f, data);
282 }
283
284 int ServConf::AddService(const std::string& name,
285                          const ServiceConfOpt& conf,
286                          Simple::Callback f, void* data)
287 {
288     auto res = pImpl->Exec<Simple::Parser>("AddService", "<AddService name=\"" + name + "\"/>", f, data);
289     if (res != st_ok)
290         return res;
291     return pImpl->Exec<Simple::Parser>("SetService", "<SetService " + ChgService::serialize(conf, pImpl->Encoding()) + "/>", f, data);
292 }
293
294 int ServConf::DelService(const std::string& name, Simple::Callback f, void* data)
295 {
296     return pImpl->Exec<Simple::Parser>("DelService", "<DelService name=\"" + name + "\"/>", f, data);
297 }
298
299 // -- Corporations --
300
301 int ServConf::GetCorporations(GetContainer::Callback<GetCorp::Info>::Type f, void* data)
302 {
303     return pImpl->Exec<GetContainer::Parser<GetCorp::Parser> >("corporations", "<GetCorporations/>", f, data);
304 }
305
306 int ServConf::GetCorp(const std::string& name, GetCorp::Callback f, void* data)
307 {
308     return pImpl->Exec<GetCorp::Parser>("<GetCorp name=\"" + name + "\"/>", f, data);
309 }
310
311 int ServConf::ChgCorp(const CorpConfOpt & conf, Simple::Callback f, void* data)
312 {
313     return pImpl->Exec<Simple::Parser>("SetCorp", "<SetCorp name=\"" + conf.name.value() + "\">" + ChgCorp::serialize(conf, pImpl->Encoding()) + "</SetCorp>", f, data);
314 }
315
316 int ServConf::AddCorp(const std::string& name,
317                       const CorpConfOpt& conf,
318                       Simple::Callback f, void* data)
319 {
320     auto res = pImpl->Exec<Simple::Parser>("AddCorp", "<AddCorp name=\"" + name + "\"/>", f, data);
321     if (res != st_ok)
322         return res;
323     return pImpl->Exec<Simple::Parser>("SetCorp", "<SetCorp name=\"" + name + "\">" + ChgCorp::serialize(conf, pImpl->Encoding()) + "</SetCorp>", f, data);
324 }
325
326 int ServConf::DelCorp(const std::string& name, Simple::Callback f, void* data)
327 {
328     return pImpl->Exec<Simple::Parser>("DelCorp", "<DelCorp name=\"" + name + "\"/>", f, data);
329 }
330
331 const std::string& ServConf::GetStrError() const
332 {
333     return pImpl->GetStrError();
334 }
335
336 //-----------------------------------------------------------------------------
337 ServConf::Impl::Impl(const std::string& server, uint16_t port,
338                      const std::string& login, const std::string& password)
339     : nt(server, port, login, password)
340 {
341     setlocale(LC_ALL, "");
342     setlocale(LC_NUMERIC, "C");
343     encoding = nl_langinfo(CODESET);
344     parser = XML_ParserCreate(NULL);
345 }
346 //-----------------------------------------------------------------------------
347 ServConf::Impl::Impl(const std::string& server, uint16_t port,
348                      const std::string& localAddress, uint16_t localPort,
349                      const std::string& login, const std::string& password)
350     : nt(server, port, localAddress, localPort, login, password)
351 {
352     setlocale(LC_ALL, "");
353     setlocale(LC_NUMERIC, "C");
354     encoding = nl_langinfo(CODESET);
355     parser = XML_ParserCreate(NULL);
356 }
357 //-----------------------------------------------------------------------------
358 void ServConf::Impl::Start(void* data, const char* el, const char** attr)
359 {
360     static_cast<Parser*>(data)->ParseStart(el, attr);
361 }
362 //-----------------------------------------------------------------------------
363 void ServConf::Impl::End(void* data, const char* el)
364 {
365     static_cast<Parser*>(data)->ParseEnd(el);
366 }
367 //-----------------------------------------------------------------------------
368 const std::string & ServConf::Impl::GetStrError() const
369 {
370     return errorMsg;
371 }
372 //-----------------------------------------------------------------------------
373 int ServConf::Impl::ExecImpl(const std::string& request, Parser&& cp)
374 {
375     XML_ParserReset(parser, NULL);
376     XML_SetElementHandler(parser, Start, End);
377     XML_SetUserData(parser, &cp);
378
379     int ret = 0;
380     if ((ret = nt.Connect()) != st_ok)
381     {
382         errorMsg = nt.GetError();
383         cp.Failure(errorMsg);
384         return ret;
385     }
386     if ((ret = nt.Transact(request, ParserRecv, this)) != st_ok)
387     {
388         errorMsg = nt.GetError();
389         cp.Failure(errorMsg);
390         return ret;
391     }
392
393     nt.Disconnect();
394     return st_ok;
395 }
396
397 int ServConf::Impl::RawXML(const std::string& request, RawXML::Callback callback, void* data)
398 {
399     int ret = 0;
400     if ((ret = nt.Connect()) != st_ok)
401         {
402         errorMsg = nt.GetError();
403         callback(false, errorMsg, "", data);
404         return ret;
405         }
406     std::string response;
407     if ((ret = nt.Transact(request, SimpleRecv, &response)) != st_ok)
408         {
409         errorMsg = nt.GetError();
410         callback(false, errorMsg, "", data);
411         return ret;
412         }
413
414     nt.Disconnect();
415     callback(true, "", response, data);
416     return st_ok;
417 }