]> git.stg.codes - stg.git/blob - projects/sgconf/main.cpp
9ae82cc560d81d2ba6d524e429a644385d354a01
[stg.git] / projects / sgconf / main.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 "request.h"
23 #include "common_sg.h"
24 #include "sg_error_codes.h"
25
26 #include "xml.h"
27 #include "options.h"
28 #include "actions.h"
29 #include "config.h"
30
31 #include "stg/user_conf.h"
32 #include "stg/user_stat.h"
33 #include "stg/common.h"
34
35 #include <cerrno>
36 #include <clocale>
37 #include <cstdio>
38 #include <cstdlib>
39 #include <cstring>
40 #include <string>
41 #include <sstream>
42
43 #include <unistd.h>
44 #include <getopt.h>
45 #include <iconv.h>
46 #include <langinfo.h>
47
48 namespace
49 {
50
51 template <typename T>
52 struct ARRAY_TYPE
53 {
54 typedef typename T::value_type type;
55 };
56
57 template <typename T>
58 struct ARRAY_TYPE<T[]>
59 {
60 typedef T type;
61 };
62
63 template <typename T, size_t N>
64 struct ARRAY_TYPE<T[N]>
65 {
66 typedef T type;
67 };
68
69 template <typename T>
70 struct nullary_function
71 {
72 typedef T result_type;
73 };
74
75 template <typename F>
76 class binder0 : public nullary_function<typename F::result_type>
77 {
78     public:
79         binder0(const F & func, const typename F::argument_type & arg)
80             : m_func(func), m_arg(arg) {}
81         typename F::result_type operator()() const { return m_func(m_arg); }
82     private:
83         F m_func;
84         typename F::argument_type m_arg;
85 };
86
87 template <typename F>
88 inline
89 binder0<F> bind0(const F & func, const typename F::argument_type & arg)
90 {
91 return binder0<F>(func, arg);
92 }
93
94 template <typename C, typename A, typename R>
95 class METHOD1_ADAPTER : public std::unary_function<A, R>
96 {
97     public:
98         METHOD1_ADAPTER(R (C::* func)(A), C & obj) : m_func(func), m_obj(obj) {}
99         R operator()(A arg) { return (m_obj.*m_func)(arg); }
100     private:
101         R (C::* m_func)(A);
102         C & m_obj;
103 };
104
105 template <typename C, typename A, typename R>
106 class CONST_METHOD1_ADAPTER : public std::unary_function<A, R>
107 {
108     public:
109         CONST_METHOD1_ADAPTER(R (C::* func)(A) const, C & obj) : m_func(func), m_obj(obj) {}
110         R operator()(A arg) const { return (m_obj.*m_func)(arg); }
111     private:
112         R (C::* m_func)(A) const;
113         C & m_obj;
114 };
115
116 template <typename C, typename A, typename R>
117 METHOD1_ADAPTER<C, A, R> Method1Adapt(R (C::* func)(A), C & obj)
118 {
119 return METHOD1_ADAPTER<C, A, R>(func, obj);
120 }
121
122 template <typename C, typename A, typename R>
123 CONST_METHOD1_ADAPTER<C, A, R> Method1Adapt(R (C::* func)(A) const, C & obj)
124 {
125 return CONST_METHOD1_ADAPTER<C, A, R>(func, obj);
126 }
127
128 template <typename T>
129 bool SetArrayItem(T & array, const char * index, const typename ARRAY_TYPE<T>::type & value)
130 {
131 size_t pos = 0;
132 if (str2x(index, pos))
133     return false;
134 array[pos] = value;
135 return true;
136 }
137
138 void RawXMLCallback(bool result, const std::string & reason, const std::string & response, void * /*data*/)
139 {
140 if (!result)
141     {
142     std::cerr << "Failed to get raw XML response. Reason: '" << reason << "'." << std::endl;
143     return;
144     }
145 SGCONF::PrintXML(response);
146 }
147
148 void Usage();
149 void UsageAll();
150 void UsageImpl(bool full);
151 void UsageConnection();
152 void UsageAdmins(bool full);
153 void UsageTariffs(bool full);
154 void UsageUsers(bool full);
155 void UsageServices(bool full);
156 void UsageCorporations(bool full);
157
158 void Version();
159
160 void ReadUserConfigFile(SGCONF::OPTION_BLOCK & block)
161 {
162 std::vector<std::string> paths;
163 const char * configHome = getenv("XDG_CONFIG_HOME");
164 if (configHome == NULL)
165     {
166     const char * home = getenv("HOME");
167     if (home == NULL)
168         return;
169     paths.push_back(std::string(home) + "/.config/sgconf/sgconf.conf");
170     paths.push_back(std::string(home) + "/.sgconf/sgconf.conf");
171     }
172 else
173     paths.push_back(std::string(configHome) + "/sgconf/sgconf.conf");
174 for (std::vector<std::string>::const_iterator it = paths.begin(); it != paths.end(); ++it)
175     if (access(it->c_str(), R_OK) == 0)
176         {
177         block.ParseFile(*it);
178         return;
179         }
180 }
181
182 } // namespace anonymous
183
184 namespace SGCONF
185 {
186
187 class CONFIG_ACTION : public ACTION
188 {
189     public:
190         CONFIG_ACTION(SGCONF::CONFIG & config,
191                       const std::string & paramDescription)
192             : m_config(config),
193               m_description(paramDescription)
194         {}
195
196         virtual ACTION * Clone() const { return new CONFIG_ACTION(*this); }
197
198         virtual std::string ParamDescription() const { return m_description; }
199         virtual std::string DefaultDescription() const { return ""; }
200         virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
201         virtual PARSER_STATE Parse(int argc, char ** argv);
202
203     private:
204         SGCONF::CONFIG & m_config;
205         std::string m_description;
206         OPTION_BLOCK m_suboptions;
207
208         void ParseCredentials(const std::string & credentials);
209         void ParseHostAndPort(const std::string & hostAndPort);
210 };
211
212 class COMMAND_FUNCTOR
213 {
214     public:
215         virtual ~COMMAND_FUNCTOR() {}
216         virtual bool operator()(const SGCONF::CONFIG & config,
217                                 const std::string & arg,
218                                 const std::map<std::string, std::string> & options) = 0;
219         virtual COMMAND_FUNCTOR * Clone() = 0;
220 };
221
222 class COMMAND
223 {
224     public:
225         COMMAND(COMMAND_FUNCTOR * funPtr,
226                 const std::string & arg,
227                 const std::map<std::string, std::string> & options)
228             : m_funPtr(funPtr->Clone()),
229               m_arg(arg),
230               m_options(options)
231         {}
232         COMMAND(const COMMAND & rhs)
233             : m_funPtr(rhs.m_funPtr->Clone()),
234               m_arg(rhs.m_arg),
235               m_options(rhs.m_options)
236         {}
237         ~COMMAND()
238         {
239             delete m_funPtr;
240         }
241         bool Execute(const SGCONF::CONFIG & config) const
242         {
243             return (*m_funPtr)(config, m_arg, m_options);
244         }
245
246     private:
247         COMMAND_FUNCTOR * m_funPtr;
248         std::string m_arg;
249         std::map<std::string, std::string> m_options;
250 };
251
252 class COMMANDS
253 {
254     public:
255         void Add(COMMAND_FUNCTOR * funPtr,
256                  const std::string & arg,
257                  const std::map<std::string, std::string> & options) { m_commands.push_back(COMMAND(funPtr, arg, options)); }
258         bool Execute(const SGCONF::CONFIG & config) const
259         {
260             std::list<COMMAND>::const_iterator it(m_commands.begin());
261             bool res = true;
262             while (it != m_commands.end() && res)
263             {
264                 res = res && it->Execute(config);
265                 ++it;
266             }
267             return res;
268         }
269     private:
270         std::list<COMMAND> m_commands;
271 };
272
273 class COMMAND_ACTION : public ACTION
274 {
275     public:
276         COMMAND_ACTION(COMMANDS & commands,
277                        const std::string & paramDescription,
278                        bool needArgument,
279                        const OPTION_BLOCK& suboptions,
280                        COMMAND_FUNCTOR* funPtr)
281             : m_commands(commands),
282               m_description(paramDescription),
283               m_argument(needArgument ? "1" : ""), // Hack
284               m_suboptions(suboptions),
285               m_funPtr(funPtr)
286         {}
287         COMMAND_ACTION(COMMANDS & commands,
288                        const std::string & paramDescription,
289                        bool needArgument,
290                        COMMAND_FUNCTOR* funPtr)
291             : m_commands(commands),
292               m_description(paramDescription),
293               m_argument(needArgument ? "1" : ""), // Hack
294               m_funPtr(funPtr)
295         {}
296         COMMAND_ACTION(const COMMAND_ACTION& rhs)
297             : m_commands(rhs.m_commands),
298               m_description(rhs.m_description),
299               m_argument(rhs.m_argument),
300               m_suboptions(rhs.m_suboptions),
301               m_params(rhs.m_params),
302               m_funPtr(rhs.m_funPtr->Clone())
303         {
304         }
305
306         ~COMMAND_ACTION()
307         {
308             delete m_funPtr;
309         }
310
311         virtual ACTION * Clone() const { return new COMMAND_ACTION(*this); }
312
313         virtual std::string ParamDescription() const { return m_description; }
314         virtual std::string DefaultDescription() const { return ""; }
315         virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
316         virtual PARSER_STATE Parse(int argc, char ** argv)
317         {
318         PARSER_STATE state(false, argc, argv);
319         if (!m_argument.empty())
320             {
321             if (argc == 0 ||
322                 argv == NULL ||
323                 *argv == NULL)
324                 throw ERROR("Missing argument.");
325             m_argument = *argv;
326             --state.argc;
327             ++state.argv;
328             }
329         m_suboptions.Parse(state.argc, state.argv);
330         m_commands.Add(m_funPtr, m_argument, m_params);
331         return state;
332         }
333
334     private:
335         COMMANDS & m_commands;
336         std::string m_description;
337         std::string m_argument;
338         OPTION_BLOCK m_suboptions;
339         std::map<std::string, std::string> m_params;
340         COMMAND_FUNCTOR* m_funPtr;
341 };
342
343 PARSER_STATE CONFIG_ACTION::Parse(int argc, char ** argv)
344 {
345 if (argc == 0 ||
346     argv == NULL ||
347     *argv == NULL)
348     throw ERROR("Missing argument.");
349 char * pos = strchr(*argv, '@');
350 if (pos != NULL)
351     {
352     ParseCredentials(std::string(*argv, pos));
353     ParseHostAndPort(std::string(pos + 1));
354     }
355 else
356     {
357     ParseHostAndPort(std::string(*argv));
358     }
359 return PARSER_STATE(false, --argc, ++argv);
360 }
361
362 void CONFIG_ACTION::ParseCredentials(const std::string & credentials)
363 {
364 std::string::size_type pos = credentials.find_first_of(':');
365 if (pos != std::string::npos)
366     {
367     m_config.userName = credentials.substr(0, pos);
368     m_config.userPass = credentials.substr(pos + 1);
369     }
370 else
371     {
372     m_config.userName = credentials;
373     }
374 }
375
376 void CONFIG_ACTION::ParseHostAndPort(const std::string & hostAndPort)
377 {
378 std::string::size_type pos = hostAndPort.find_first_of(':');
379 if (pos != std::string::npos)
380     {
381     m_config.server = hostAndPort.substr(0, pos);
382     uint16_t port = 0;
383     if (str2x(hostAndPort.substr(pos + 1), port))
384         throw ERROR("Invalid port value: '" + hostAndPort.substr(pos + 1) + "'");
385     m_config.port = port;
386     }
387 else
388     {
389     m_config.server = hostAndPort;
390     }
391 }
392
393 inline
394 CONFIG_ACTION * MakeParamAction(SGCONF::CONFIG & config,
395                                 const std::string & paramDescription)
396 {
397 return new CONFIG_ACTION(config, paramDescription);
398 }
399
400 inline
401 ACTION * MakeCommandAction(COMMANDS & commands,
402                            const std::string & paramDescription,
403                            bool needArgument,
404                            COMMAND_FUNCTOR * funPtr)
405 {
406 return new COMMAND_ACTION(commands, paramDescription, needArgument, funPtr);
407 }
408
409 class RAW_XML_FUNCTOR : public COMMAND_FUNCTOR
410 {
411     public:
412         virtual bool operator()(const SGCONF::CONFIG & config,
413                                 const std::string & arg,
414                                 const std::map<std::string, std::string> & /*options*/)
415         {
416             STG::SERVCONF proto(config.server.data(),
417                                 config.port.data(),
418                                 config.userName.data(),
419                                 config.userPass.data());
420             return proto.RawXML(arg, RawXMLCallback, NULL) == STG::st_ok;
421         }
422         virtual COMMAND_FUNCTOR * Clone() { return new RAW_XML_FUNCTOR(*this); }
423 };
424
425 } // namespace SGCONF
426
427 time_t stgTime;
428
429 struct option long_options_get[] = {
430 {"server",      1, 0, 's'},  //Server
431 {"port",        1, 0, 'p'},  //Port
432 {"admin",       1, 0, 'a'},  //Admin
433 {"admin_pass",  1, 0, 'w'},  //passWord
434 {"user",        1, 0, 'u'},  //User
435 {"addcash",     0, 0, 'c'},  //Add Cash
436 //{"setcash",     0, 0, 'v'},  //Set Cash
437 {"credit",      0, 0, 'r'},  //cRedit
438 {"tariff",      0, 0, 't'},  //Tariff
439 {"message",     0, 0, 'm'},  //message
440 {"password",    0, 0, 'o'},  //password
441 {"down",        0, 0, 'd'},  //down
442 {"passive",     0, 0, 'i'},  //passive
443 {"disable-stat",0, 0, 'S'},  //disable detail stat
444 {"always-online",0, 0, 'O'}, //always online
445 {"session-upload",   1, 0, 500},  //SU0
446 {"session-download", 1, 0, 501},  //SD0
447 {"month-upload",     1, 0, 502},  //MU0
448 {"month-download",   1, 0, 503},  //MD0
449
450 {"user-data",   1, 0, 700},  //UserData0
451
452 {"prepaid",     0, 0, 'e'},  //prepaid traff
453 {"create",      0, 0, 'n'},  //create
454 {"delete",      0, 0, 'l'},  //delete
455
456 {"note",        0, 0, 'N'},  //Note
457 {"name",        0, 0, 'A'},  //nAme
458 {"address",     0, 0, 'D'},  //aDdress
459 {"email",       0, 0, 'L'},  //emaiL
460 {"phone",       0, 0, 'P'},  //phone
461 {"group",       0, 0, 'G'},  //Group
462 {"ip",          0, 0, 'I'},  //IP-address of user
463 {"authorized-by",0, 0, 800}, //always online
464
465 {0, 0, 0, 0}};
466
467 struct option long_options_set[] = {
468 {"server",      1, 0, 's'},  //Server
469 {"port",        1, 0, 'p'},  //Port
470 {"admin",       1, 0, 'a'},  //Admin
471 {"admin_pass",  1, 0, 'w'},  //passWord
472 {"user",        1, 0, 'u'},  //User
473 {"addcash",     1, 0, 'c'},  //Add Cash
474 {"setcash",     1, 0, 'v'},  //Set Cash
475 {"credit",      1, 0, 'r'},  //cRedit
476 {"tariff",      1, 0, 't'},  //Tariff
477 {"message",     1, 0, 'm'},  //message
478 {"password",    1, 0, 'o'},  //password
479 {"down",        1, 0, 'd'},  //down
480 {"passive",     1, 0, 'i'},  //passive
481 {"disable-stat",1, 0, 'S'},  //disable detail stat
482 {"always-online",1, 0, 'O'},  //always online
483 {"session-upload",   1, 0, 500},  //U0
484 {"session-download", 1, 0, 501},  //U1
485 {"month-upload",     1, 0, 502},  //U2
486 {"month-download",   1, 0, 503},  //U3
487
488 {"user-data",        1, 0, 700},  //UserData
489
490 {"prepaid",     1, 0, 'e'},  //prepaid traff
491 {"create",      1, 0, 'n'},  //create
492 {"delete",      1, 0, 'l'},  //delete
493
494 {"note",        1, 0, 'N'},  //Note
495 {"name",        1, 0, 'A'},  //nAme
496 {"address",     1, 0, 'D'},  //aDdress
497 {"email",       1, 0, 'L'},  //emaiL
498 {"phone",       1, 0, 'P'},  //phone
499 {"group",       1, 0, 'G'},  //Group
500 {"ip",          0, 0, 'I'},  //IP-address of user
501
502 {0, 0, 0, 0}};
503
504 //-----------------------------------------------------------------------------
505 CASH_INFO ParseCash(const char * str)
506 {
507 //-c 123.45:log message
508 std::string cashString;
509 std::string message;
510 const char * pos = strchr(str, ':');
511 if (pos != NULL)
512     {
513     cashString.append(str, pos);
514     message.append(pos + 1);
515     }
516 else
517     cashString = str;
518
519 double cash = 0;
520 if (strtodouble2(cashString, cash) != 0)
521     {
522     printf("Incorrect cash value %s\n", str);
523     exit(PARAMETER_PARSING_ERR_CODE);
524     }
525
526 return CASH_INFO(cash, message);
527 }
528 //-----------------------------------------------------------------------------
529 double ParseCredit(const char * c)
530 {
531 double credit;
532 if (strtodouble2(c, credit) != 0)
533     {
534     printf("Incorrect credit value %s\n", c);
535     exit(PARAMETER_PARSING_ERR_CODE);
536     }
537
538 return credit;
539 }
540 //-----------------------------------------------------------------------------
541 double ParsePrepaidTraffic(const char * c)
542 {
543 double credit;
544 if (strtodouble2(c, credit) != 0)
545     {
546     printf("Incorrect prepaid traffic value %s\n", c);
547     exit(PARAMETER_PARSING_ERR_CODE);
548     }
549
550 return credit;
551 }
552 //-----------------------------------------------------------------------------
553 int64_t ParseTraff(const char * c)
554 {
555 int64_t traff;
556 if (str2x(c, traff) != 0)
557     {
558     printf("Incorrect credit value %s\n", c);
559     exit(PARAMETER_PARSING_ERR_CODE);
560     }
561
562 return traff;
563 }
564 //-----------------------------------------------------------------------------
565 bool ParseDownPassive(const char * dp)
566 {
567 if (!(dp[1] == 0 && (dp[0] == '1' || dp[0] == '0')))
568     {
569     printf("Incorrect value %s\n", dp);
570     exit(PARAMETER_PARSING_ERR_CODE);
571     }
572
573 return dp[0] - '0';
574 }
575 //-----------------------------------------------------------------------------
576 void ParseTariff(const char * str, RESETABLE<std::string> & tariffName, RESETABLE<std::string> & nextTariff)
577 {
578 const char * pos = strchr(str, ':');
579 if (pos != NULL)
580     {
581     std::string tariff(str, pos);
582     if (strcmp(pos + 1, "now") == 0)
583         tariffName = tariff;
584     else if (strcmp(pos + 1, "delayed") == 0)
585         nextTariff = tariff;
586     else
587         {
588         printf("Incorrect tariff value '%s'. Should be '<tariff>', '<tariff>:now' or '<tariff>:delayed'.\n", str);
589         exit(PARAMETER_PARSING_ERR_CODE);
590         }
591     }
592 else
593     tariffName = str;
594 }
595 //-----------------------------------------------------------------------------
596 time_t ParseCreditExpire(const char * str)
597 {
598 struct tm brokenTime;
599
600 brokenTime.tm_wday = 0;
601 brokenTime.tm_yday = 0;
602 brokenTime.tm_isdst = 0;
603 brokenTime.tm_hour = 0;
604 brokenTime.tm_min = 0;
605 brokenTime.tm_sec = 0;
606
607 stg_strptime(str, "%Y-%m-%d", &brokenTime);
608
609 return stg_timegm(&brokenTime);
610 }
611 //-----------------------------------------------------------------------------
612 void ParseAnyString(const char * c, string * msg, const char * enc)
613 {
614 iconv_t cd;
615 char * ob = new char[strlen(c) + 1];
616 char * ib = new char[strlen(c) + 1];
617
618 strcpy(ib, c);
619
620 char * outbuf = ob;
621 char * inbuf = ib;
622
623 setlocale(LC_ALL, "");
624
625 char charsetF[255];
626 strncpy(charsetF, nl_langinfo(CODESET), 255);
627
628 const char * charsetT = enc;
629
630 size_t nconv = 1;
631
632 size_t insize = strlen(ib);
633 size_t outsize = strlen(ib);
634
635 insize = strlen(c);
636
637 cd = iconv_open(charsetT, charsetF);
638 if (cd == (iconv_t) -1)
639     {
640     if (errno == EINVAL)
641         {
642         printf("Warning: iconv from %s to %s failed\n", charsetF, charsetT);
643         *msg = c;
644         return;
645         }
646     else
647         printf("error iconv_open\n");
648
649     exit(ICONV_ERR_CODE);
650     }
651
652 #if defined(FREE_BSD) || defined(FREE_BSD5)
653 nconv = iconv (cd, (const char**)&inbuf, &insize, &outbuf, &outsize);
654 #else
655 nconv = iconv (cd, &inbuf, &insize, &outbuf, &outsize);
656 #endif
657 //printf("nconv=%d outsize=%d\n", nconv, outsize);
658 if (nconv == (size_t) -1)
659     {
660     if (errno != EINVAL)
661         {
662         printf("iconv error\n");
663         exit(ICONV_ERR_CODE);
664         }
665     }
666
667 *outbuf = L'\0';
668
669 iconv_close(cd);
670 *msg = ob;
671
672 delete[] ob;
673 delete[] ib;
674 }
675 //-----------------------------------------------------------------------------
676 void CreateRequestSet(REQUEST * req, char * r)
677 {
678 const int strLen = 10024;
679 char str[strLen];
680 memset(str, 0, strLen);
681
682 r[0] = 0;
683
684 if (!req->usrMsg.empty())
685     {
686     string msg;
687     Encode12str(msg, req->usrMsg.data());
688     sprintf(str, "<Message login=\"%s\" msgver=\"1\" msgtype=\"1\" repeat=\"0\" repeatperiod=\"0\" showtime=\"0\" text=\"%s\"/>", req->login.const_data().c_str(), msg.c_str());
689     //sprintf(str, "<message login=\"%s\" priority=\"0\" text=\"%s\"/>\n", req->login, msg);
690     strcat(r, str);
691     return;
692     }
693
694 if (req->deleteUser)
695     {
696     sprintf(str, "<DelUser login=\"%s\"/>", req->login.const_data().c_str());
697     strcat(r, str);
698     //printf("%s\n", r);
699     return;
700     }
701
702 if (req->createUser)
703     {
704     sprintf(str, "<AddUser> <login value=\"%s\"/> </AddUser>", req->login.const_data().c_str());
705     strcat(r, str);
706     //printf("%s\n", r);
707     return;
708     }
709
710 strcat(r, "<SetUser>\n");
711 sprintf(str, "<login value=\"%s\"/>\n", req->login.const_data().c_str());
712 strcat(r, str);
713 if (!req->credit.empty())
714     {
715     sprintf(str, "<credit value=\"%f\"/>\n", req->credit.const_data());
716     strcat(r, str);
717     }
718
719 if (!req->creditExpire.empty())
720     {
721     sprintf(str, "<creditExpire value=\"%ld\"/>\n", req->creditExpire.const_data());
722     strcat(r, str);
723     }
724
725 if (!req->prepaidTraff.empty())
726     {
727     sprintf(str, "<FreeMb value=\"%f\"/>\n", req->prepaidTraff.const_data());
728     strcat(r, str);
729     }
730
731 if (!req->cash.empty())
732     {
733     string msg;
734     Encode12str(msg, req->message);
735     sprintf(str, "<cash add=\"%f\" msg=\"%s\"/>\n", req->cash.const_data(), msg.c_str());
736     strcat(r, str);
737     }
738
739 if (!req->setCash.empty())
740     {
741     string msg;
742     Encode12str(msg, req->message);
743     sprintf(str, "<cash set=\"%f\" msg=\"%s\"/>\n", req->setCash.const_data(), msg.c_str());
744     strcat(r, str);
745     }
746
747 if (!req->usrPasswd.empty())
748     {
749     sprintf(str, "<password value=\"%s\" />\n", req->usrPasswd.const_data().c_str());
750     strcat(r, str);
751     }
752
753 if (!req->down.empty())
754     {
755     sprintf(str, "<down value=\"%d\" />\n", req->down.const_data());
756     strcat(r, str);
757     }
758
759 if (!req->passive.empty())
760     {
761     sprintf(str, "<passive value=\"%d\" />\n", req->passive.const_data());
762     strcat(r, str);
763     }
764
765 if (!req->disableDetailStat.empty())
766     {
767     sprintf(str, "<disableDetailStat value=\"%d\" />\n", req->disableDetailStat.const_data());
768     strcat(r, str);
769     }
770
771 if (!req->alwaysOnline.empty())
772     {
773     sprintf(str, "<aonline value=\"%d\" />\n", req->alwaysOnline.const_data());
774     strcat(r, str);
775     }
776
777 // IP-address of user
778 if (!req->ips.empty())
779     {
780     sprintf(str, "<ip value=\"%s\" />\n", req->ips.const_data().c_str());
781     strcat(r, str);
782     }
783
784 int uPresent = false;
785 int dPresent = false;
786 for (int i = 0; i < DIR_NUM; i++)
787     {
788     if (!req->monthUpload[i].empty())
789         {
790         if (!uPresent && !dPresent)
791             {
792             sprintf(str, "<traff ");
793             strcat(r, str);
794             uPresent = true;
795             }
796
797         stringstream ss;
798         ss << req->monthUpload[i].const_data();
799         //sprintf(str, "MU%d=\"%lld\" ", i, req->u[i].const_data());
800         sprintf(str, "MU%d=\"%s\" ", i, ss.str().c_str());
801         strcat(r, str);
802         }
803     if (!req->monthDownload[i].empty())
804         {
805         if (!uPresent && !dPresent)
806             {
807             sprintf(str, "<traff ");
808             strcat(r, str);
809             dPresent = true;
810             }
811
812         stringstream ss;
813         ss << req->monthDownload[i].const_data();
814         sprintf(str, "MD%d=\"%s\" ", i, ss.str().c_str());
815         strcat(r, str);
816         }
817     if (!req->sessionUpload[i].empty())
818         {
819         if (!uPresent && !dPresent)
820             {
821             sprintf(str, "<traff ");
822             strcat(r, str);
823             uPresent = true;
824             }
825
826         stringstream ss;
827         ss << req->sessionUpload[i].const_data();
828         //sprintf(str, "MU%d=\"%lld\" ", i, req->u[i].const_data());
829         sprintf(str, "MU%d=\"%s\" ", i, ss.str().c_str());
830         strcat(r, str);
831         }
832     if (!req->sessionDownload[i].empty())
833         {
834         if (!uPresent && !dPresent)
835             {
836             sprintf(str, "<traff ");
837             strcat(r, str);
838             dPresent = true;
839             }
840
841         stringstream ss;
842         ss << req->sessionDownload[i].const_data();
843         sprintf(str, "MD%d=\"%s\" ", i, ss.str().c_str());
844         strcat(r, str);
845         }
846     }
847 if (uPresent || dPresent)
848     {
849     strcat(r, "/>");
850     }
851
852 //printf("%s\n", r);
853
854 if (!req->tariff.empty())
855     {
856     switch (req->chgTariff)
857         {
858         case TARIFF_NOW:
859             sprintf(str, "<tariff now=\"%s\"/>\n", req->tariff.const_data().c_str());
860             strcat(r, str);
861             break;
862         case TARIFF_REC:
863             sprintf(str, "<tariff recalc=\"%s\"/>\n", req->tariff.const_data().c_str());
864             strcat(r, str);
865             break;
866         case TARIFF_DEL:
867             sprintf(str, "<tariff delayed=\"%s\"/>\n", req->tariff.const_data().c_str());
868             strcat(r, str);
869             break;
870         }
871
872     }
873
874 if (!req->note.empty())
875     {
876     string note;
877     Encode12str(note, req->note.data());
878     sprintf(str, "<note value=\"%s\"/>", note.c_str());
879     strcat(r, str);
880     }
881
882 if (!req->name.empty())
883     {
884     string name;
885     Encode12str(name, req->name.data());
886     sprintf(str, "<name value=\"%s\"/>", name.c_str());
887     strcat(r, str);
888     }
889
890 if (!req->address.empty())
891     {
892     string address;
893     Encode12str(address, req->address.data());
894     sprintf(str, "<address value=\"%s\"/>", address.c_str());
895     strcat(r, str);
896     }
897
898 if (!req->email.empty())
899     {
900     string email;
901     Encode12str(email, req->email.data());
902     sprintf(str, "<email value=\"%s\"/>", email.c_str());
903     strcat(r, str);
904     }
905
906 if (!req->phone.empty())
907     {
908     string phone;
909     Encode12str(phone, req->phone.data());
910     sprintf(str, "<phone value=\"%s\"/>", phone.c_str());
911     strcat(r, str);
912     }
913
914 if (!req->group.empty())
915     {
916     string group;
917     Encode12str(group, req->group.data());
918     sprintf(str, "<group value=\"%s\"/>", group.c_str());
919     strcat(r, str);
920     }
921
922 for (int i = 0; i < USERDATA_NUM; i++)
923     {
924     if (!req->userData[i].empty())
925         {
926         string ud;
927         Encode12str(ud, req->userData[i].data());
928         sprintf(str, "<userdata%d value=\"%s\"/>", i, ud.c_str());
929         strcat(r, str);
930         }
931     }
932
933 strcat(r, "</SetUser>\n");
934 }
935 //-----------------------------------------------------------------------------
936 int CheckParameters(REQUEST * req)
937 {
938 bool su = false;
939 bool sd = false;
940 bool mu = false;
941 bool md = false;
942 bool ud = false;
943 bool a = !req->admLogin.empty()
944     && !req->admPasswd.empty()
945     && !req->server.empty()
946     && !req->port.empty()
947     && !req->login.empty();
948
949 bool b = !req->cash.empty()
950     || !req->setCash.empty()
951     || !req->credit.empty()
952     || !req->prepaidTraff.empty()
953     || !req->tariff.empty()
954     || !req->usrMsg.empty()
955     || !req->usrPasswd.empty()
956
957     || !req->note.empty()
958     || !req->name.empty()
959     || !req->address.empty()
960     || !req->email.empty()
961     || !req->phone.empty()
962     || !req->group.empty()
963     || !req->ips.empty() // IP-address of user
964
965     || !req->createUser
966     || !req->deleteUser;
967
968
969 for (int i = 0; i < DIR_NUM; i++)
970     {
971     if (req->sessionUpload[i].empty())
972         {
973         su = true;
974         break;
975         }
976     }
977
978 for (int i = 0; i < DIR_NUM; i++)
979     {
980     if (req->sessionDownload[i].empty())
981         {
982         sd = true;
983         break;
984         }
985     }
986
987 for (int i = 0; i < DIR_NUM; i++)
988     {
989     if (req->monthUpload[i].empty())
990         {
991         mu = true;
992         break;
993         }
994     }
995
996 for (int i = 0; i < DIR_NUM; i++)
997     {
998     if (req->monthDownload[i].empty())
999         {
1000         md = true;
1001         break;
1002         }
1003     }
1004
1005 for (int i = 0; i < DIR_NUM; i++)
1006     {
1007     if (req->userData[i].empty())
1008         {
1009         ud = true;
1010         break;
1011         }
1012     }
1013
1014
1015 //printf("a=%d, b=%d, u=%d, d=%d ud=%d\n", a, b, u, d, ud);
1016 return a && (b || su || sd || mu || md || ud);
1017 }
1018 //-----------------------------------------------------------------------------
1019 int CheckParametersGet(REQUEST * req)
1020 {
1021 return CheckParameters(req);
1022 }
1023 //-----------------------------------------------------------------------------
1024 int CheckParametersSet(REQUEST * req)
1025 {
1026 return CheckParameters(req);
1027 }
1028 //-----------------------------------------------------------------------------
1029 bool mainGet(int argc, char **argv)
1030 {
1031 int c;
1032 REQUEST req;
1033 RESETABLE<string>   t1;
1034 int missedOptionArg = false;
1035
1036 const char * short_options_get = "s:p:a:w:u:crtmodieNADLPGISOE";
1037 int option_index = -1;
1038
1039 while (1)
1040     {
1041     option_index = -1;
1042     c = getopt_long(argc, argv, short_options_get, long_options_get, &option_index);
1043     if (c == -1)
1044         break;
1045
1046     switch (c)
1047         {
1048         case 's': //server
1049             req.server = optarg;
1050             break;
1051
1052         case 'p': //port
1053             req.port = ParseServerPort(optarg);
1054             //req.portReq = 1;
1055             break;
1056
1057         case 'a': //admin
1058             req.admLogin = ParseAdminLogin(optarg);
1059             break;
1060
1061         case 'w': //admin password
1062             req.admPasswd = ParsePassword(optarg);
1063             break;
1064
1065         case 'o': //change user password
1066             req.usrPasswd = " ";
1067             break;
1068
1069         case 'u': //user
1070             req.login = ParseUser(optarg);
1071             break;
1072
1073         case 'c': //get cash
1074             req.cash = 1;
1075             break;
1076
1077         case 'r': //credit
1078             req.credit = 1;
1079             break;
1080
1081         case 'E': //credit expire
1082             req.creditExpire = 1;
1083             break;
1084
1085         case 'd': //down
1086             req.down = 1;
1087             break;
1088
1089         case 'i': //passive
1090             req.passive = 1;
1091             break;
1092
1093         case 't': //tariff
1094             req.tariff = " ";
1095             break;
1096
1097         case 'e': //Prepaid Traffic
1098             req.prepaidTraff = 1;
1099             break;
1100
1101         case 'N': //Note
1102             req.note = " ";
1103             break;
1104
1105         case 'A': //nAme
1106             req.name = " ";
1107             break;
1108
1109         case 'D': //aDdress
1110             req.address =" ";
1111             break;
1112
1113         case 'L': //emaiL
1114             req.email = " ";
1115             break;
1116
1117         case 'P': //phone
1118             req.phone = " ";
1119             break;
1120
1121         case 'G': //Group
1122             req.group = " ";
1123             break;
1124
1125         case 'I': //IP-address of user
1126             req.ips = " ";
1127             break;
1128
1129         case 'S': //Detail stat status
1130             req.disableDetailStat = " ";
1131             break;
1132
1133         case 'O': //Always online status
1134             req.alwaysOnline = " ";
1135             break;
1136
1137         case 500: //U
1138             SetArrayItem(req.sessionUpload, optarg, 1);
1139             //req.sessionUpload[optarg] = 1;
1140             break;
1141         case 501:
1142             SetArrayItem(req.sessionDownload, optarg, 1);
1143             //req.sessionDownload[optarg] = 1;
1144             break;
1145         case 502:
1146             SetArrayItem(req.monthUpload, optarg, 1);
1147             //req.monthUpload[optarg] = 1;
1148             break;
1149         case 503:
1150             SetArrayItem(req.monthDownload, optarg, 1);
1151             //req.monthDownload[optarg] = 1;
1152             break;
1153
1154         case 700: //UserData
1155             SetArrayItem(req.userData, optarg, std::string(" "));
1156             //req.userData[optarg] = " ";
1157             break;
1158
1159         case 800:
1160             req.authBy = true;
1161             break;
1162
1163         case '?':
1164         case ':':
1165             missedOptionArg = true;
1166             break;
1167
1168         default:
1169             printf ("?? getopt returned character code 0%o ??\n", c);
1170         }
1171     }
1172
1173 if (optind < argc)
1174     {
1175     printf ("non-option ARGV-elements: ");
1176     while (optind < argc)
1177         printf ("%s ", argv[optind++]);
1178     UsageInfo();
1179     exit(PARAMETER_PARSING_ERR_CODE);
1180     }
1181
1182 if (missedOptionArg || !CheckParametersGet(&req))
1183     {
1184     //printf("Parameter needed\n");
1185     UsageInfo();
1186     exit(PARAMETER_PARSING_ERR_CODE);
1187     }
1188
1189 if (req.authBy)
1190     return ProcessAuthBy(req.server.data(), req.port.data(), req.admLogin.data(), req.admPasswd.data(), req.login.data());
1191 else
1192     return ProcessGetUser(req.server.data(), req.port.data(), req.admLogin.data(), req.admPasswd.data(), req.login.data(), req);
1193 }
1194 //-----------------------------------------------------------------------------
1195 bool mainSet(int argc, char **argv)
1196 {
1197 string str;
1198
1199 int c;
1200 bool isMessage = false;
1201 REQUEST req;
1202
1203 RESETABLE<string>   t1;
1204
1205 const char * short_options_set = "s:p:a:w:u:c:r:t:m:o:d:i:e:v:nlN:A:D:L:P:G:I:S:O:E:";
1206
1207 int missedOptionArg = false;
1208
1209 USER_CONF_RES conf;
1210 USER_STAT_RES stat;
1211 while (1)
1212     {
1213     int option_index = -1;
1214
1215     c = getopt_long(argc, argv, short_options_set, long_options_set, &option_index);
1216
1217     if (c == -1)
1218         break;
1219
1220     switch (c)
1221         {
1222         case 's': //server
1223             req.server = optarg;
1224             break;
1225
1226         case 'p': //port
1227             req.port = ParseServerPort(optarg);
1228             //req.portReq = 1;
1229             break;
1230
1231         case 'a': //admin
1232             req.admLogin = ParseAdminLogin(optarg);
1233             break;
1234
1235         case 'w': //admin password
1236             req.admPasswd = ParsePassword(optarg);
1237             break;
1238
1239         case 'o': //change user password
1240             conf.password = ParsePassword(optarg);
1241             break;
1242
1243         case 'u': //user
1244             req.login = ParseUser(optarg);
1245             break;
1246
1247         case 'c': //add cash
1248             stat.cashAdd = ParseCash(optarg);
1249             break;
1250
1251         case 'v': //set cash
1252             stat.cashSet = ParseCash(optarg);
1253             break;
1254
1255         case 'r': //credit
1256             conf.credit = ParseCredit(optarg);
1257             break;
1258
1259         case 'E': //credit expire
1260             conf.creditExpire = ParseCreditExpire(optarg);
1261             break;
1262
1263         case 'd': //down
1264             conf.disabled = ParseDownPassive(optarg);
1265             break;
1266
1267         case 'i': //passive
1268             conf.passive = ParseDownPassive(optarg);
1269             break;
1270
1271         case 't': //tariff
1272             ParseTariff(optarg, conf.tariffName, conf.nextTariff);
1273             break;
1274
1275         case 'm': //message
1276             ParseAnyString(optarg, &str);
1277             req.usrMsg = str;
1278             isMessage = true;
1279             break;
1280
1281         case 'e': //Prepaid Traffic
1282             stat.freeMb = ParsePrepaidTraffic(optarg);
1283             break;
1284
1285         case 'n': //Create User
1286             req.createUser = true;
1287             break;
1288
1289         case 'l': //Delete User
1290             req.deleteUser = true;
1291             break;
1292
1293         case 'N': //Note
1294             ParseAnyString(optarg, &str, "koi8-ru");
1295             conf.note = str;
1296             break;
1297
1298         case 'A': //nAme
1299             ParseAnyString(optarg, &str, "koi8-ru");
1300             conf.realName = str;
1301             break;
1302
1303         case 'D': //aDdress
1304             ParseAnyString(optarg, &str, "koi8-ru");
1305             conf.address = str;
1306             break;
1307
1308         case 'L': //emaiL
1309             ParseAnyString(optarg, &str, "koi8-ru");
1310             conf.email = str;
1311             break;
1312
1313         case 'P': //phone
1314             ParseAnyString(optarg, &str);
1315             conf.phone = str;
1316             break;
1317
1318         case 'G': //Group
1319             ParseAnyString(optarg, &str, "koi8-ru");
1320             conf.group = str;
1321             break;
1322
1323         case 'I': //IP-address of user
1324             ParseAnyString(optarg, &str);
1325             conf.ips = StrToIPS(str);
1326             break;
1327
1328         case 'S':
1329             conf.disabledDetailStat = ParseDownPassive(optarg);
1330             break;
1331
1332         case 'O':
1333             conf.alwaysOnline = ParseDownPassive(optarg);
1334             break;
1335
1336         case 500: //U
1337             SetArrayItem(stat.sessionUp, optarg, ParseTraff(argv[optind++]));
1338             break;
1339         case 501:
1340             SetArrayItem(stat.sessionDown, optarg, ParseTraff(argv[optind++]));
1341             break;
1342         case 502:
1343             SetArrayItem(stat.monthUp, optarg, ParseTraff(argv[optind++]));
1344             break;
1345         case 503:
1346             SetArrayItem(stat.monthDown, optarg, ParseTraff(argv[optind++]));
1347             break;
1348
1349         case 700: //UserData
1350             ParseAnyString(argv[optind++], &str);
1351             SetArrayItem(conf.userdata, optarg, str);
1352             break;
1353
1354         case '?':
1355             missedOptionArg = true;
1356             break;
1357
1358         case ':':
1359             missedOptionArg = true;
1360             break;
1361
1362         default:
1363             printf("?? getopt returned character code 0%o ??\n", c);
1364         }
1365     }
1366
1367 if (optind < argc)
1368     {
1369     printf ("non-option ARGV-elements: ");
1370     while (optind < argc)
1371         printf ("%s ", argv[optind++]);
1372     UsageConf();
1373     exit(PARAMETER_PARSING_ERR_CODE);
1374     }
1375
1376 if (missedOptionArg || !CheckParametersSet(&req))
1377     {
1378     //printf("Parameter needed\n");
1379     UsageConf();
1380     exit(PARAMETER_PARSING_ERR_CODE);
1381     }
1382
1383 const int rLen = 20000;
1384 char rstr[rLen];
1385 memset(rstr, 0, rLen);
1386
1387 if (isMessage)
1388     return ProcessSendMessage(req.server.data(), req.port.data(), req.admLogin.data(), req.admPasswd.data(), req.login.data(), req.usrMsg.data());
1389
1390 return ProcessSetUser(req.server.data(), req.port.data(), req.admLogin.data(), req.admPasswd.data(), req.login.data(), conf, stat);
1391 }
1392 //-----------------------------------------------------------------------------
1393 int main(int argc, char **argv)
1394 {
1395 SGCONF::CONFIG config;
1396 SGCONF::COMMANDS commands;
1397
1398 SGCONF::OPTION_BLOCKS blocks;
1399 blocks.Add("General options")
1400       .Add("c", "config", SGCONF::MakeParamAction(config.configFile, std::string("~/.config/stg/sgconf.conf"), "<config file>"), "override default config file")
1401       .Add("h", "help", SGCONF::MakeFunc0Action(bind0(Method1Adapt(&SGCONF::OPTION_BLOCKS::Help, blocks), 0)), "\t\tshow this help and exit")
1402       .Add("help-all", SGCONF::MakeFunc0Action(UsageAll), "\t\tshow full help and exit")
1403       .Add("v", "version", SGCONF::MakeFunc0Action(Version), "\t\tshow version information and exit");
1404 SGCONF::OPTION_BLOCK & block = blocks.Add("Connection options")
1405       .Add("s", "server", SGCONF::MakeParamAction(config.server, std::string("localhost"), "<address>"), "\t\thost to connect")
1406       .Add("p", "port", SGCONF::MakeParamAction(config.port, uint16_t(5555), "<port>"), "\t\tport to connect")
1407       .Add("u", "username", SGCONF::MakeParamAction(config.userName, std::string("admin"), "<username>"), "\tadministrative login")
1408       .Add("w", "userpass", SGCONF::MakeParamAction(config.userPass, "<password>"), "\tpassword for the administrative login")
1409       .Add("a", "address", SGCONF::MakeParamAction(config, "<connection string>"), "connection params as a single string in format: <login>:<password>@<host>:<port>");
1410 blocks.Add("Raw XML")
1411       .Add("r", "raw", SGCONF::MakeCommandAction(commands, "<xml>", true, new SGCONF::RAW_XML_FUNCTOR()), "\t\tmake raw XML request");
1412 /*blocks.Add("Admins management options")
1413       .Add("get-admins", SGCONF::MakeConfAction())
1414       .Add("get-admin", SGCONF::MakeConfAction())
1415       .Add("add-admin", SGCONF::MakeConfAction())
1416       .Add("del-admin", SGCONF::MakeConfAction())
1417       .Add("chg-admin", SGCONF::MakeConfAction());*/
1418
1419
1420 SGCONF::PARSER_STATE state(false, argc, argv);
1421
1422 try
1423 {
1424 state = blocks.Parse(--argc, ++argv); // Skipping self name
1425 }
1426 catch (const SGCONF::OPTION::ERROR& ex)
1427 {
1428 std::cerr << ex.what() << "\n";
1429 return -1;
1430 }
1431
1432 if (state.stop)
1433     return 0;
1434
1435 if (state.argc > 0)
1436     {
1437     std::cerr << "Unknown option: '" << *state.argv << "'\n";
1438     return -1;
1439     }
1440
1441 try
1442 {
1443 SGCONF::CONFIG configOverride(config);
1444
1445 if (config.configFile.empty())
1446     {
1447     const char * mainConfigFile = "/etc/sgconf/sgconf.conf";
1448     if (access(mainConfigFile, R_OK) == 0)
1449         block.ParseFile(mainConfigFile);
1450     ReadUserConfigFile(block);
1451     }
1452 else
1453     {
1454     block.ParseFile(config.configFile.data());
1455     }
1456
1457 config = configOverride;
1458 }
1459 catch (const std::exception& ex)
1460 {
1461 std::cerr << ex.what() << "\n";
1462 return -1;
1463 }
1464
1465 std::cerr << "Config: " << config.Serialize() << std::endl;
1466 return commands.Execute(config) ? 0 : -1;
1467
1468 /*return 0;
1469
1470 if (argc < 2)
1471     {
1472     Usage();
1473     return 1;
1474     }
1475
1476 if (argc <= 2)
1477     {
1478     UsageConf();
1479     exit(PARAMETER_PARSING_ERR_CODE);
1480     }
1481
1482 if (strcmp(argv[1], "get") == 0)
1483     {
1484     //printf("get\n");
1485     return mainGet(argc - 1, argv + 1);
1486     }
1487 else if (strcmp(argv[1], "set") == 0)
1488     {
1489     //printf("set\n");
1490     if (mainSet(argc - 1, argv + 1) )
1491         return 0;
1492     return -1;
1493     }
1494 else
1495     {
1496     UsageConf();
1497     exit(PARAMETER_PARSING_ERR_CODE);
1498     }
1499 return UNKNOWN_ERR_CODE;*/
1500 }
1501 //-----------------------------------------------------------------------------
1502
1503 namespace
1504 {
1505
1506 void Usage()
1507 {
1508 UsageImpl(false);
1509 }
1510
1511 void UsageAll()
1512 {
1513 UsageImpl(true);
1514 }
1515
1516 void UsageImpl(bool full)
1517 {
1518 std::cout << "sgconf is the Stargazer management utility.\n\n"
1519           << "Usage:\n"
1520           << "\tsgconf [options]\n\n"
1521           << "General options:\n"
1522           << "\t-c, --config <config file>\t\toverride default config file (default: \"~/.config/stg/sgconf.conf\")\n"
1523           << "\t-h, --help\t\t\t\tshow this help and exit\n"
1524           << "\t--help-all\t\t\t\tshow full help and exit\n"
1525           << "\t-v, --version\t\t\t\tshow version information and exit\n\n";
1526 UsageConnection();
1527 UsageAdmins(full);
1528 UsageTariffs(full);
1529 UsageUsers(full);
1530 UsageServices(full);
1531 UsageCorporations(full);
1532 }
1533 //-----------------------------------------------------------------------------
1534 void UsageConnection()
1535 {
1536 std::cout << "Connection options:\n"
1537           << "\t-s, --server <address>\t\t\thost to connect (ip or domain name, default: \"localhost\")\n"
1538           << "\t-p, --port <port>\t\t\tport to connect (default: \"5555\")\n"
1539           << "\t-u, --username <username>\t\tadministrative login (default: \"admin\")\n"
1540           << "\t-w, --userpass <password>\t\tpassword for administrative login\n"
1541           << "\t-a, --address <connection string>\tconnection params as a single string in format: <login>:<password>@<host>:<port>\n\n";
1542 }
1543 //-----------------------------------------------------------------------------
1544 void UsageAdmins(bool full)
1545 {
1546 std::cout << "Admins management options:\n"
1547           << "\t--get-admins\t\t\t\tget a list of admins (subsequent options will define what to show)\n";
1548 if (full)
1549     std::cout << "\t\t--login\t\t\t\tshow admin's login\n"
1550               << "\t\t--priv\t\t\t\tshow admin's priviledges\n\n";
1551 std::cout << "\t--get-admin\t\t\t\tget the information about admin\n";
1552 if (full)
1553     std::cout << "\t\t--login <login>\t\t\tlogin of the admin to show\n"
1554               << "\t\t--priv\t\t\t\tshow admin's priviledges\n\n";
1555 std::cout << "\t--add-admin\t\t\t\tadd a new admin\n";
1556 if (full)
1557     std::cout << "\t\t--login <login>\t\t\tlogin of the admin to add\n"
1558               << "\t\t--password <password>\t\tpassword of the admin to add\n"
1559               << "\t\t--priv <priv number>\t\tpriviledges of the admin to add\n\n";
1560 std::cout << "\t--del-admin\t\t\t\tdelete an existing admin\n";
1561 if (full)
1562     std::cout << "\t\t--login <login>\t\t\tlogin of the admin to delete\n\n";
1563 std::cout << "\t--chg-admin\t\t\t\tchange an existing admin\n";
1564 if (full)
1565     std::cout << "\t\t--login <login>\t\t\tlogin of the admin to change\n"
1566               << "\t\t--priv <priv number>\t\tnew priviledges\n\n";
1567 }
1568 //-----------------------------------------------------------------------------
1569 void UsageTariffs(bool full)
1570 {
1571 std::cout << "Tariffs management options:\n"
1572           << "\t--get-tariffs\t\t\t\tget a list of tariffs (subsequent options will define what to show)\n";
1573 if (full)
1574     std::cout << "\t\t--name\t\t\t\tshow tariff's name\n"
1575               << "\t\t--fee\t\t\t\tshow tariff's fee\n"
1576               << "\t\t--free\t\t\t\tshow tariff's prepaid traffic in terms of cost\n"
1577               << "\t\t--passive-cost\t\t\tshow tariff's cost of \"freeze\"\n"
1578               << "\t\t--traff-type\t\t\tshow what type of traffix will be accounted by the tariff\n"
1579               << "\t\t--dirs\t\t\t\tshow tarification rules for directions\n\n";
1580 std::cout << "\t--get-tariff\t\t\t\tget the information about tariff\n";
1581 if (full)
1582     std::cout << "\t\t--name <name>\t\t\tname of the tariff to show\n"
1583               << "\t\t--fee\t\t\t\tshow tariff's fee\n"
1584               << "\t\t--free\t\t\t\tshow tariff's prepaid traffic in terms of cost\n"
1585               << "\t\t--passive-cost\t\t\tshow tariff's cost of \"freeze\"\n"
1586               << "\t\t--traff-type\t\t\tshow what type of traffix will be accounted by the tariff\n"
1587               << "\t\t--dirs\t\t\t\tshow tarification rules for directions\n\n";
1588 std::cout << "\t--add-tariff\t\t\t\tadd a new tariff\n";
1589 if (full)
1590     std::cout << "\t\t--name <name>\t\t\tname of the tariff to add\n"
1591               << "\t\t--fee <fee>\t\t\tstariff's fee\n"
1592               << "\t\t--free <free>\t\t\ttariff's prepaid traffic in terms of cost\n"
1593               << "\t\t--passive-cost <cost>\t\ttariff's cost of \"freeze\"\n"
1594               << "\t\t--traff-type <type>\t\twhat type of traffi will be accounted by the tariff\n"
1595               << "\t\t--times <times>\t\t\tslash-separated list of \"day\" time-spans (in form \"hh:mm-hh:mm\") for each direction\n"
1596               << "\t\t--prices-day-a <prices>\t\tslash-separated list of prices for \"day\" traffic before threshold for each direction\n"
1597               << "\t\t--prices-night-a <prices>\tslash-separated list of prices for \"night\" traffic before threshold for each direction\n"
1598               << "\t\t--prices-day-b <prices>\t\tslash-separated list of prices for \"day\" traffic after threshold for each direction\n"
1599               << "\t\t--prices-night-b <prices>\tslash-separated list of prices for \"night\" traffic after threshold for each direction\n"
1600               << "\t\t--single-prices <yes|no>\tslash-separated list of \"single price\" flags for each direction\n"
1601               << "\t\t--no-discounts <yes|no>\t\tslash-separated list of \"no discount\" flags for each direction\n"
1602               << "\t\t--thresholds <thresholds>\tslash-separated list of thresholds (in Mb) for each direction\n\n";
1603 std::cout << "\t--del-tariff\t\t\t\tdelete an existing tariff\n";
1604 if (full)
1605     std::cout << "\t\t--name <name>\t\t\tname of the tariff to delete\n\n";
1606 std::cout << "\t--chg-tariff\t\t\t\tchange an existing tariff\n";
1607 if (full)
1608     std::cout << "\t\t--name <name>\t\t\tname of the tariff to change\n"
1609               << "\t\t--fee <fee>\t\t\tstariff's fee\n"
1610               << "\t\t--free <free>\t\t\ttariff's prepaid traffic in terms of cost\n"
1611               << "\t\t--passive-cost <cost>\t\ttariff's cost of \"freeze\"\n"
1612               << "\t\t--traff-type <type>\t\twhat type of traffix will be accounted by the tariff\n"
1613               << "\t\t--dir <N>\t\t\tnumber of direction data to change\n"
1614               << "\t\t\t--time <time>\t\t\"day\" time-span (in form \"hh:mm-hh:mm\")\n"
1615               << "\t\t\t--price-day-a <price>\tprice for \"day\" traffic before threshold\n"
1616               << "\t\t\t--price-night-a <price>\tprice for \"night\" traffic before threshold\n"
1617               << "\t\t\t--price-day-b <price>\tprice for \"day\" traffic after threshold\n"
1618               << "\t\t\t--price-night-b <price>\tprice for \"night\" traffic after threshold\n"
1619               << "\t\t\t--single-price <yes|no>\t\"single price\" flag\n"
1620               << "\t\t\t--no-discount <yes|no>\t\"no discount\" flag\n"
1621               << "\t\t\t--threshold <threshold>\tthreshold (in Mb)\n\n";
1622 }
1623 //-----------------------------------------------------------------------------
1624 void UsageUsers(bool full)
1625 {
1626 std::cout << "Users management options:\n"
1627           << "\t--get-users\t\t\t\tget a list of users (subsequent options will define what to show)\n";
1628 if (full)
1629     std::cout << "\n\n";
1630 std::cout << "\t--get-user\t\t\t\tget the information about user\n";
1631 if (full)
1632     std::cout << "\n\n";
1633 std::cout << "\t--add-user\t\t\t\tadd a new user\n";
1634 if (full)
1635     std::cout << "\n\n";
1636 std::cout << "\t--del-user\t\t\t\tdelete an existing user\n";
1637 if (full)
1638     std::cout << "\n\n";
1639 std::cout << "\t--chg-user\t\t\t\tchange an existing user\n";
1640 if (full)
1641     std::cout << "\n\n";
1642 std::cout << "\t--check-user\t\t\t\tcheck credentials is valid\n";
1643 if (full)
1644     std::cout << "\n\n";
1645 std::cout << "\t--send-message\t\t\t\tsend a message to a user\n";
1646 if (full)
1647     std::cout << "\n\n";
1648 }
1649 //-----------------------------------------------------------------------------
1650 void UsageServices(bool full)
1651 {
1652 std::cout << "Services management options:\n"
1653           << "\t--get-services\t\t\t\tget a list of services (subsequent options will define what to show)\n";
1654 if (full)
1655     std::cout << "\t\t--name\t\t\t\tshow service's name\n"
1656               << "\t\t--comment\t\t\tshow a comment to the service\n"
1657               << "\t\t--cost\t\t\t\tshow service's cost\n"
1658               << "\t\t--pay-day\t\t\tshow service's pay day\n\n";
1659 std::cout << "\t--get-service\t\t\t\tget the information about service\n";
1660 if (full)
1661     std::cout << "\t\t--name <name>\t\t\tname of the service to show\n"
1662               << "\t\t--comment\t\t\tshow a comment to the service\n"
1663               << "\t\t--cost\t\t\t\tshow service's cost\n"
1664               << "\t\t--pay-day\t\t\tshow service's pay day\n\n";
1665 std::cout << "\t--add-service\t\t\t\tadd a new service\n";
1666 if (full)
1667     std::cout << "\t\t--name <name>\t\t\tname of the service to add\n"
1668               << "\t\t--comment <comment>\t\ta comment to the service\n"
1669               << "\t\t--cost <cost>\t\t\tservice's cost\n"
1670               << "\t\t--pay-day <day>\t\t\tservice's pay day\n\n";
1671 std::cout << "\t--del-service\t\t\t\tdelete an existing service\n";
1672 if (full)
1673     std::cout << "\t\t--name <name>\t\t\tname of the service to delete\n\n";
1674 std::cout << "\t--chg-service\t\t\t\tchange an existing service\n";
1675 if (full)
1676     std::cout << "\t\t--name <name>\t\t\tname of the service to change\n"
1677               << "\t\t--comment <comment>\t\ta comment to the service\n"
1678               << "\t\t--cost <cost>\t\t\tservice's cost\n"
1679               << "\t\t--pay-day <day>\t\t\tservice's pay day\n\n";
1680 }
1681 //-----------------------------------------------------------------------------
1682 void UsageCorporations(bool full)
1683 {
1684 std::cout << "Corporations management options:\n"
1685           << "\t--get-corporations\t\t\tget a list of corporations (subsequent options will define what to show)\n";
1686 if (full)
1687     std::cout << "\t\t--name\t\t\t\tshow corporation's name\n"
1688               << "\t\t--cash\t\t\t\tshow corporation's cash\n\n";
1689 std::cout << "\t--get-corp\t\t\t\tget the information about corporation\n";
1690 if (full)
1691     std::cout << "\t\t--name <name>\t\t\tname of the corporation to show\n"
1692               << "\t\t--cash\t\t\t\tshow corporation's cash\n\n";
1693 std::cout << "\t--add-corp\t\t\t\tadd a new corporation\n";
1694 if (full)
1695     std::cout << "\t\t--name <name>\t\t\tname of the corporation to add\n"
1696               << "\t\t--cash <cash>\t\t\tinitial corporation's cash (default: \"0\")\n\n";
1697 std::cout << "\t--del-corp\t\t\t\tdelete an existing corporation\n";
1698 if (full)
1699     std::cout << "\t\t--name <name>\t\t\tname of the corporation to delete\n\n";
1700 std::cout << "\t--chg-corp\t\t\t\tchange an existing corporation\n";
1701 if (full)
1702     std::cout << "\t\t--name <name>\t\t\tname of the corporation to change\n"
1703               << "\t\t--add-cash <amount>[:<message>]\tadd cash to the corporation's account and optional comment message\n"
1704               << "\t\t--set-cash <cash>[:<message>]\tnew corporation's cash and optional comment message\n\n";
1705 }
1706
1707 void Version()
1708 {
1709 std::cout << "sgconf, version: 2.0.0-alpha.\n";
1710 }
1711
1712 } // namespace anonymous