]> git.stg.codes - stg.git/blob - projects/sgconf/main.cpp
[NY Flight] Improvements in parser dispatching.
[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  */
20
21  /*
22  $Author: faust $
23  $Revision: 1.25 $
24  $Date: 2010/03/25 14:37:43 $
25  */
26
27 #include <unistd.h>
28 #include <getopt.h>
29 #include <iconv.h>
30 #include <langinfo.h>
31
32 #include <cerrno>
33 #include <clocale>
34 #include <cstdio>
35 #include <cstring>
36 #include <string>
37 #include <list>
38 #include <sstream>
39
40 #include "stg/common.h"
41 #include "stg/netunit.h"
42 #include "request.h"
43 #include "common_sg.h"
44 #include "sg_error_codes.h"
45
46 namespace
47 {
48
49 template <typename T>
50 struct ARRAY_TYPE;
51
52 template <typename T>
53 struct ARRAY_TYPE<T[]>
54 {
55 typedef T type;
56 };
57
58 template <typename T, size_t N>
59 struct ARRAY_TYPE<T[N]>
60 {
61 typedef T type;
62 };
63
64 template <typename T>
65 bool SetArrayItem(T & array, const char * index, const typename ARRAY_TYPE<T>::type & value)
66 {
67 size_t pos = 0;
68 if (str2x(index, pos))
69     return false;
70 array[pos] = value;
71 return true;
72 }
73
74 } // namespace anonymous
75
76 time_t stgTime;
77
78 int ParseReplyGet(void * data, list<string> * ans);
79 //int ParseReplySet(void * data, list<string> * ans);
80
81 struct option long_options_get[] = {
82 {"server",      1, 0, 's'},  //Server
83 {"port",        1, 0, 'p'},  //Port
84 {"admin",       1, 0, 'a'},  //Admin
85 {"admin_pass",  1, 0, 'w'},  //passWord
86 {"user",        1, 0, 'u'},  //User
87 {"addcash",     0, 0, 'c'},  //Add Cash
88 //{"setcash",     0, 0, 'v'},  //Set Cash
89 {"credit",      0, 0, 'r'},  //cRedit
90 {"tariff",      0, 0, 't'},  //Tariff
91 {"message",     0, 0, 'm'},  //message
92 {"password",    0, 0, 'o'},  //password
93 {"down",        0, 0, 'd'},  //down
94 {"passive",     0, 0, 'i'},  //passive
95 {"disable-stat",0, 0, 'S'},  //disable detail stat
96 {"always-online",0, 0, 'O'}, //always online
97 {"session-upload",   1, 0, 500},  //SU0
98 {"session-download", 1, 0, 501},  //SD0
99 {"month-upload",     1, 0, 502},  //MU0
100 {"month-download",   1, 0, 503},  //MD0
101
102 {"user-data",   1, 0, 700},  //UserData0
103
104 {"prepaid",     0, 0, 'e'},  //prepaid traff
105 {"create",      0, 0, 'n'},  //create
106 {"delete",      0, 0, 'l'},  //delete
107
108 {"note",        0, 0, 'N'},  //Note
109 {"name",        0, 0, 'A'},  //nAme
110 {"address",     0, 0, 'D'},  //aDdress
111 {"email",       0, 0, 'L'},  //emaiL
112 {"phone",       0, 0, 'P'},  //phone
113 {"group",       0, 0, 'G'},  //Group
114 {"ip",          0, 0, 'I'},  //IP-address of user
115 {"authorized-by",0, 0, 800}, //always online
116
117 {0, 0, 0, 0}};
118
119 struct option long_options_set[] = {
120 {"server",      1, 0, 's'},  //Server
121 {"port",        1, 0, 'p'},  //Port
122 {"admin",       1, 0, 'a'},  //Admin
123 {"admin_pass",  1, 0, 'w'},  //passWord
124 {"user",        1, 0, 'u'},  //User
125 {"addcash",     1, 0, 'c'},  //Add Cash
126 {"setcash",     1, 0, 'v'},  //Set Cash
127 {"credit",      1, 0, 'r'},  //cRedit
128 {"tariff",      1, 0, 't'},  //Tariff
129 {"message",     1, 0, 'm'},  //message
130 {"password",    1, 0, 'o'},  //password
131 {"down",        1, 0, 'd'},  //down
132 {"passive",     1, 0, 'i'},  //passive
133 {"disable-stat",1, 0, 'S'},  //disable detail stat
134 {"always-online",1, 0, 'O'},  //always online
135 {"session-upload",   1, 0, 500},  //U0
136 {"session-download", 1, 0, 501},  //U1
137 {"month-upload",     1, 0, 502},  //U2
138 {"month-download",   1, 0, 503},  //U3
139
140 {"user-data",        1, 0, 700},  //UserData
141
142 {"prepaid",     1, 0, 'e'},  //prepaid traff
143 {"create",      1, 0, 'n'},  //create
144 {"delete",      1, 0, 'l'},  //delete
145
146 {"note",        1, 0, 'N'},  //Note
147 {"name",        1, 0, 'A'},  //nAme
148 {"address",     1, 0, 'D'},  //aDdress
149 {"email",       1, 0, 'L'},  //emaiL
150 {"phone",       1, 0, 'P'},  //phone
151 {"group",       1, 0, 'G'},  //Group
152 {"ip",          0, 0, 'I'},  //IP-address of user
153
154 {0, 0, 0, 0}};
155
156 //-----------------------------------------------------------------------------
157 double ParseCash(const char * c, string * message)
158 {
159 //-c 123.45:log message
160 double cash;
161 char * msg;
162 char * str;
163 str = new char[strlen(c) + 1];
164
165 strncpy(str, c, strlen(c));
166 str[strlen(c)] = 0;
167
168 msg = strchr(str, ':');
169
170 if (msg)
171     {
172     *message =  msg + 1;
173     str[msg - str] = 0;
174     }
175 else
176     *message = "";
177
178 if (strtodouble2(str, cash) != 0)
179     {
180     printf("Incorrect cash value %s\n", c);
181     exit(PARAMETER_PARSING_ERR_CODE);
182     }
183
184 delete[] str;
185 return cash;
186 }
187 //-----------------------------------------------------------------------------
188 double ParseCredit(const char * c)
189 {
190 double credit;
191 if (strtodouble2(c, credit) != 0)
192     {
193     printf("Incorrect credit value %s\n", c);
194     exit(PARAMETER_PARSING_ERR_CODE);
195     }
196
197 return credit;
198 }
199 //-----------------------------------------------------------------------------
200 double ParsePrepaidTraffic(const char * c)
201 {
202 double credit;
203 if (strtodouble2(c, credit) != 0)
204     {
205     printf("Incorrect prepaid traffic value %s\n", c);
206     exit(PARAMETER_PARSING_ERR_CODE);
207     }
208
209 return credit;
210 }
211 //-----------------------------------------------------------------------------
212 int64_t ParseTraff(const char * c)
213 {
214 int64_t traff;
215 if (str2x(c, traff) != 0)
216     {
217     printf("Incorrect credit value %s\n", c);
218     exit(PARAMETER_PARSING_ERR_CODE);
219     }
220
221 return traff;
222 }
223 //-----------------------------------------------------------------------------
224 bool ParseDownPassive(const char * dp)
225 {
226 if (!(dp[1] == 0 && (dp[0] == '1' || dp[0] == '0')))
227     {
228     printf("Incorrect value %s\n", dp);
229     exit(PARAMETER_PARSING_ERR_CODE);
230     }
231
232 return dp[0] - '0';
233 }
234 //-----------------------------------------------------------------------------
235 string ParseTariff(const char * t, int &chgType)
236 {
237 int l = strlen(t);
238 char * s;
239 s = new char[l];
240 char * s1, * s2;
241 string ss;
242
243 strcpy(s, t);
244
245 s1 = strtok(s, ":");
246
247 if (strlen(s1) >= TARIFF_NAME_LEN)
248     {
249     printf("Tariff name too big %s\n", s1);
250     exit(PARAMETER_PARSING_ERR_CODE);
251     }
252
253 //*tariff = s;
254
255 if (CheckLogin(s1))
256     {
257     printf("Incorrect tariff value %s\n", t);
258     exit(PARAMETER_PARSING_ERR_CODE);
259     }
260
261 s2 = strtok(NULL, ":");
262
263 chgType = -1;
264
265 if (s2 == NULL)
266     {
267     chgType = TARIFF_NOW;
268     ss = s;
269     delete[] s;
270     return ss;
271     }
272
273
274 if (strcmp(s2, "now") == 0)
275     chgType = TARIFF_NOW;
276
277 if (strcmp(s2, "delayed") == 0)
278     chgType = TARIFF_DEL;
279
280 if (strcmp(s2, "recalc") == 0)
281     chgType = TARIFF_REC;
282
283 if (chgType < 0)
284     {
285     printf("Incorrect tariff value %s\n", t);
286     exit(PARAMETER_PARSING_ERR_CODE);
287     }
288
289 ss = s;
290 delete[] s;
291 return ss;
292 }
293 //-----------------------------------------------------------------------------
294 time_t ParseCreditExpire(const char * str)
295 {
296 struct tm brokenTime;
297
298 brokenTime.tm_wday = 0;
299 brokenTime.tm_yday = 0;
300 brokenTime.tm_isdst = 0;
301 brokenTime.tm_hour = 0;
302 brokenTime.tm_min = 0;
303 brokenTime.tm_sec = 0;
304
305 stg_strptime(str, "%Y-%m-%d", &brokenTime);
306
307 return stg_timegm(&brokenTime);
308 }
309 //-----------------------------------------------------------------------------
310 void ParseAnyString(const char * c, string * msg, const char * enc)
311 {
312 iconv_t cd;
313 char * ob = new char[strlen(c) + 1];
314 char * ib = new char[strlen(c) + 1];
315
316 strcpy(ib, c);
317
318 char * outbuf = ob;
319 char * inbuf = ib;
320
321 setlocale(LC_ALL, "");
322
323 char charsetF[255];
324 strncpy(charsetF, nl_langinfo(CODESET), 255);
325
326 const char * charsetT = enc;
327
328 size_t nconv = 1;
329
330 size_t insize = strlen(ib);
331 size_t outsize = strlen(ib);
332
333 insize = strlen(c);
334
335 cd = iconv_open(charsetT, charsetF);
336 if (cd == (iconv_t) -1)
337     {
338     if (errno == EINVAL)
339         {
340         printf("Warning: iconv from %s to %s failed\n", charsetF, charsetT);
341         *msg = c;
342         return;
343         }
344     else
345         printf("error iconv_open\n");
346
347     exit(ICONV_ERR_CODE);
348     }
349
350 #if defined(FREE_BSD) || defined(FREE_BSD5)
351 nconv = iconv (cd, (const char**)&inbuf, &insize, &outbuf, &outsize);
352 #else
353 nconv = iconv (cd, &inbuf, &insize, &outbuf, &outsize);
354 #endif
355 //printf("nconv=%d outsize=%d\n", nconv, outsize);
356 if (nconv == (size_t) -1)
357     {
358     if (errno != EINVAL)
359         {
360         printf("iconv error\n");
361         exit(ICONV_ERR_CODE);
362         }
363     }
364
365 *outbuf = L'\0';
366
367 iconv_close(cd);
368 *msg = ob;
369
370 delete[] ob;
371 delete[] ib;
372 }
373 //-----------------------------------------------------------------------------
374 void CreateRequestSet(REQUEST * req, char * r)
375 {
376 const int strLen = 10024;
377 char str[strLen];
378 memset(str, 0, strLen);
379
380 r[0] = 0;
381
382 if (!req->usrMsg.res_empty())
383     {
384     string msg;
385     Encode12str(msg, req->usrMsg);
386     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());
387     //sprintf(str, "<message login=\"%s\" priority=\"0\" text=\"%s\"/>\n", req->login, msg);
388     strcat(r, str);
389     return;
390     }
391
392 if (req->deleteUser)
393     {
394     sprintf(str, "<DelUser login=\"%s\"/>", req->login.const_data().c_str());
395     strcat(r, str);
396     //printf("%s\n", r);
397     return;
398     }
399
400 if (req->createUser)
401     {
402     sprintf(str, "<AddUser> <login value=\"%s\"/> </AddUser>", req->login.const_data().c_str());
403     strcat(r, str);
404     //printf("%s\n", r);
405     return;
406     }
407
408 strcat(r, "<SetUser>\n");
409 sprintf(str, "<login value=\"%s\"/>\n", req->login.const_data().c_str());
410 strcat(r, str);
411 if (!req->credit.res_empty())
412     {
413     sprintf(str, "<credit value=\"%f\"/>\n", req->credit.const_data());
414     strcat(r, str);
415     }
416
417 if (!req->creditExpire.res_empty())
418     {
419     sprintf(str, "<creditExpire value=\"%ld\"/>\n", req->creditExpire.const_data());
420     strcat(r, str);
421     }
422
423 if (!req->prepaidTraff.res_empty())
424     {
425     sprintf(str, "<FreeMb value=\"%f\"/>\n", req->prepaidTraff.const_data());
426     strcat(r, str);
427     }
428
429 if (!req->cash.res_empty())
430     {
431     string msg;
432     Encode12str(msg, req->message);
433     sprintf(str, "<cash add=\"%f\" msg=\"%s\"/>\n", req->cash.const_data(), msg.c_str());
434     strcat(r, str);
435     }
436
437 if (!req->setCash.res_empty())
438     {
439     string msg;
440     Encode12str(msg, req->message);
441     sprintf(str, "<cash set=\"%f\" msg=\"%s\"/>\n", req->setCash.const_data(), msg.c_str());
442     strcat(r, str);
443     }
444
445 if (!req->usrPasswd.res_empty())
446     {
447     sprintf(str, "<password value=\"%s\" />\n", req->usrPasswd.const_data().c_str());
448     strcat(r, str);
449     }
450
451 if (!req->down.res_empty())
452     {
453     sprintf(str, "<down value=\"%d\" />\n", req->down.const_data());
454     strcat(r, str);
455     }
456
457 if (!req->passive.res_empty())
458     {
459     sprintf(str, "<passive value=\"%d\" />\n", req->passive.const_data());
460     strcat(r, str);
461     }
462
463 if (!req->disableDetailStat.res_empty())
464     {
465     sprintf(str, "<disableDetailStat value=\"%d\" />\n", req->disableDetailStat.const_data());
466     strcat(r, str);
467     }
468
469 if (!req->alwaysOnline.res_empty())
470     {
471     sprintf(str, "<aonline value=\"%d\" />\n", req->alwaysOnline.const_data());
472     strcat(r, str);
473     }
474
475 // IP-address of user
476 if (!req->ips.res_empty())
477     {
478     sprintf(str, "<ip value=\"%s\" />\n", req->ips.const_data().c_str());
479     strcat(r, str);
480     }
481
482 int uPresent = false;
483 int dPresent = false;
484 for (int i = 0; i < DIR_NUM; i++)
485     {
486     if (!req->monthUpload[i].res_empty())
487         {
488         if (!uPresent && !dPresent)
489             {
490             sprintf(str, "<traff ");
491             strcat(r, str);
492             uPresent = true;
493             }
494
495         stringstream ss;
496         ss << req->monthUpload[i].const_data();
497         //sprintf(str, "MU%d=\"%lld\" ", i, req->u[i].const_data());
498         sprintf(str, "MU%d=\"%s\" ", i, ss.str().c_str());
499         strcat(r, str);
500         }
501     if (!req->monthDownload[i].res_empty())
502         {
503         if (!uPresent && !dPresent)
504             {
505             sprintf(str, "<traff ");
506             strcat(r, str);
507             dPresent = true;
508             }
509
510         stringstream ss;
511         ss << req->monthDownload[i].const_data();
512         sprintf(str, "MD%d=\"%s\" ", i, ss.str().c_str());
513         strcat(r, str);
514         }
515     if (!req->sessionUpload[i].res_empty())
516         {
517         if (!uPresent && !dPresent)
518             {
519             sprintf(str, "<traff ");
520             strcat(r, str);
521             uPresent = true;
522             }
523
524         stringstream ss;
525         ss << req->sessionUpload[i].const_data();
526         //sprintf(str, "MU%d=\"%lld\" ", i, req->u[i].const_data());
527         sprintf(str, "MU%d=\"%s\" ", i, ss.str().c_str());
528         strcat(r, str);
529         }
530     if (!req->sessionDownload[i].res_empty())
531         {
532         if (!uPresent && !dPresent)
533             {
534             sprintf(str, "<traff ");
535             strcat(r, str);
536             dPresent = true;
537             }
538
539         stringstream ss;
540         ss << req->sessionDownload[i].const_data();
541         sprintf(str, "MD%d=\"%s\" ", i, ss.str().c_str());
542         strcat(r, str);
543         }
544     }
545 if (uPresent || dPresent)
546     {
547     strcat(r, "/>");
548     }
549
550 //printf("%s\n", r);
551
552 if (!req->tariff.res_empty())
553     {
554     switch (req->chgTariff)
555         {
556         case TARIFF_NOW:
557             sprintf(str, "<tariff now=\"%s\"/>\n", req->tariff.const_data().c_str());
558             strcat(r, str);
559             break;
560         case TARIFF_REC:
561             sprintf(str, "<tariff recalc=\"%s\"/>\n", req->tariff.const_data().c_str());
562             strcat(r, str);
563             break;
564         case TARIFF_DEL:
565             sprintf(str, "<tariff delayed=\"%s\"/>\n", req->tariff.const_data().c_str());
566             strcat(r, str);
567             break;
568         }
569
570     }
571
572 if (!req->note.res_empty())
573     {
574     string note;
575     Encode12str(note, req->note);
576     sprintf(str, "<note value=\"%s\"/>", note.c_str());
577     strcat(r, str);
578     }
579
580 if (!req->name.res_empty())
581     {
582     string name;
583     Encode12str(name, req->name);
584     sprintf(str, "<name value=\"%s\"/>", name.c_str());
585     strcat(r, str);
586     }
587
588 if (!req->address.res_empty())
589     {
590     string address;
591     Encode12str(address, req->address);
592     sprintf(str, "<address value=\"%s\"/>", address.c_str());
593     strcat(r, str);
594     }
595
596 if (!req->email.res_empty())
597     {
598     string email;
599     Encode12str(email, req->email);
600     sprintf(str, "<email value=\"%s\"/>", email.c_str());
601     strcat(r, str);
602     }
603
604 if (!req->phone.res_empty())
605     {
606     string phone;
607     Encode12str(phone, req->phone);
608     sprintf(str, "<phone value=\"%s\"/>", phone.c_str());
609     strcat(r, str);
610     }
611
612 if (!req->group.res_empty())
613     {
614     string group;
615     Encode12str(group, req->group);
616     sprintf(str, "<group value=\"%s\"/>", group.c_str());
617     strcat(r, str);
618     }
619
620 for (int i = 0; i < USERDATA_NUM; i++)
621     {
622     if (!req->userData[i].res_empty())
623         {
624         string ud;
625         Encode12str(ud, req->userData[i]);
626         sprintf(str, "<userdata%d value=\"%s\"/>", i, ud.c_str());
627         strcat(r, str);
628         }
629     }
630
631 strcat(r, "</SetUser>\n");
632 }
633 //-----------------------------------------------------------------------------
634 int CheckParameters(REQUEST * req)
635 {
636 bool su = false;
637 bool sd = false;
638 bool mu = false;
639 bool md = false;
640 bool ud = false;
641 bool a = !req->admLogin.res_empty()
642     && !req->admPasswd.res_empty()
643     && !req->server.res_empty()
644     && !req->port.res_empty()
645     && !req->login.res_empty();
646
647 bool b = !req->cash.res_empty()
648     || !req->setCash.res_empty()
649     || !req->credit.res_empty()
650     || !req->prepaidTraff.res_empty()
651     || !req->tariff.res_empty()
652     || !req->usrMsg.res_empty()
653     || !req->usrPasswd.res_empty()
654
655     || !req->note.res_empty()
656     || !req->name.res_empty()
657     || !req->address.res_empty()
658     || !req->email.res_empty()
659     || !req->phone.res_empty()
660     || !req->group.res_empty()
661     || !req->ips.res_empty()    // IP-address of user
662
663     || !req->createUser
664     || !req->deleteUser;
665
666
667 for (int i = 0; i < DIR_NUM; i++)
668     {
669     if (req->sessionUpload[i].res_empty())
670         {
671         su = true;
672         break;
673         }
674     }
675
676 for (int i = 0; i < DIR_NUM; i++)
677     {
678     if (req->sessionDownload[i].res_empty())
679         {
680         sd = true;
681         break;
682         }
683     }
684
685 for (int i = 0; i < DIR_NUM; i++)
686     {
687     if (req->monthUpload[i].res_empty())
688         {
689         mu = true;
690         break;
691         }
692     }
693
694 for (int i = 0; i < DIR_NUM; i++)
695     {
696     if (req->monthDownload[i].res_empty())
697         {
698         md = true;
699         break;
700         }
701     }
702
703 for (int i = 0; i < DIR_NUM; i++)
704     {
705     if (req->userData[i].res_empty())
706         {
707         ud = true;
708         break;
709         }
710     }
711
712
713 //printf("a=%d, b=%d, u=%d, d=%d ud=%d\n", a, b, u, d, ud);
714 return a && (b || su || sd || mu || md || ud);
715 }
716 //-----------------------------------------------------------------------------
717 int CheckParametersGet(REQUEST * req)
718 {
719 return CheckParameters(req);
720 }
721 //-----------------------------------------------------------------------------
722 int CheckParametersSet(REQUEST * req)
723 {
724 return CheckParameters(req);
725 }
726 //-----------------------------------------------------------------------------
727 bool mainGet(int argc, char **argv)
728 {
729 int c;
730 REQUEST req;
731 RESETABLE<string>   t1;
732 int missedOptionArg = false;
733
734 const char * short_options_get = "s:p:a:w:u:crtmodieNADLPGISOE";
735 int option_index = -1;
736
737 while (1)
738     {
739     option_index = -1;
740     c = getopt_long(argc, argv, short_options_get, long_options_get, &option_index);
741     if (c == -1)
742         break;
743
744     switch (c)
745         {
746         case 's': //server
747             req.server = optarg;
748             break;
749
750         case 'p': //port
751             req.port = ParseServerPort(optarg);
752             //req.portReq = 1;
753             break;
754
755         case 'a': //admin
756             req.admLogin = ParseAdminLogin(optarg);
757             break;
758
759         case 'w': //admin password
760             req.admPasswd = ParsePassword(optarg);
761             break;
762
763         case 'o': //change user password
764             req.usrPasswd = " ";
765             break;
766
767         case 'u': //user
768             req.login = ParseUser(optarg);
769             break;
770
771         case 'c': //get cash
772             req.cash = 1;
773             break;
774
775         case 'r': //credit
776             req.credit = 1;
777             break;
778
779         case 'E': //credit expire
780             req.creditExpire = 1;
781             break;
782
783         case 'd': //down
784             req.down = 1;
785             break;
786
787         case 'i': //passive
788             req.passive = 1;
789             break;
790
791         case 't': //tariff
792             req.tariff = " ";
793             break;
794
795         case 'e': //Prepaid Traffic
796             req.prepaidTraff = 1;
797             break;
798
799         case 'N': //Note
800             req.note = " ";
801             break;
802
803         case 'A': //nAme
804             req.name = " ";
805             break;
806
807         case 'D': //aDdress
808             req.address =" ";
809             break;
810
811         case 'L': //emaiL
812             req.email = " ";
813             break;
814
815         case 'P': //phone
816             req.phone = " ";
817             break;
818
819         case 'G': //Group
820             req.group = " ";
821             break;
822
823         case 'I': //IP-address of user
824             req.ips = " ";
825             break;
826
827         case 'S': //Detail stat status
828             req.disableDetailStat = " ";
829             break;
830
831         case 'O': //Always online status
832             req.alwaysOnline = " ";
833             break;
834
835         case 500: //U
836             SetArrayItem(req.sessionUpload, optarg, 1);
837             //req.sessionUpload[optarg] = 1;
838             break;
839         case 501:
840             SetArrayItem(req.sessionDownload, optarg, 1);
841             //req.sessionDownload[optarg] = 1;
842             break;
843         case 502:
844             SetArrayItem(req.monthUpload, optarg, 1);
845             //req.monthUpload[optarg] = 1;
846             break;
847         case 503:
848             SetArrayItem(req.monthDownload, optarg, 1);
849             //req.monthDownload[optarg] = 1;
850             break;
851
852         case 700: //UserData
853             SetArrayItem(req.userData, optarg, std::string(" "));
854             //req.userData[optarg] = " ";
855             break;
856
857         case 800:
858             req.authBy = true;
859             break;
860
861         case '?':
862         case ':':
863             missedOptionArg = true;
864             break;
865
866         default:
867             printf ("?? getopt returned character code 0%o ??\n", c);
868         }
869     }
870
871 if (optind < argc)
872     {
873     printf ("non-option ARGV-elements: ");
874     while (optind < argc)
875         printf ("%s ", argv[optind++]);
876     UsageInfo();
877     exit(PARAMETER_PARSING_ERR_CODE);
878     }
879
880 if (missedOptionArg || !CheckParametersGet(&req))
881     {
882     //printf("Parameter needed\n");
883     UsageInfo();
884     exit(PARAMETER_PARSING_ERR_CODE);
885     }
886
887 if (req.authBy)
888     return ProcessAuthBy(req.server, req.port, req.admLogin, req.admPasswd, req.login);
889 else
890     return ProcessGetUser(req.server, req.port, req.admLogin, req.admPasswd, req.login, req);
891 }
892 //-----------------------------------------------------------------------------
893 bool mainSet(int argc, char **argv)
894 {
895 string str;
896
897 int c;
898 bool isMessage = false;
899 REQUEST req;
900
901 RESETABLE<string>   t1;
902
903 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:";
904
905 int missedOptionArg = false;
906
907 while (1)
908     {
909     int option_index = -1;
910
911     c = getopt_long(argc, argv, short_options_set, long_options_set, &option_index);
912
913     if (c == -1)
914         break;
915
916     switch (c)
917         {
918         case 's': //server
919             req.server = optarg;
920             break;
921
922         case 'p': //port
923             req.port = ParseServerPort(optarg);
924             //req.portReq = 1;
925             break;
926
927         case 'a': //admin
928             req.admLogin = ParseAdminLogin(optarg);
929             break;
930
931         case 'w': //admin password
932             req.admPasswd = ParsePassword(optarg);
933             break;
934
935         case 'o': //change user password
936             req.usrPasswd = ParsePassword(optarg);
937             break;
938
939         case 'u': //user
940             req.login = ParseUser(optarg);
941             break;
942
943         case 'c': //add cash
944             req.cash = ParseCash(optarg, &req.message);
945             break;
946
947         case 'v': //set cash
948             req.setCash = ParseCash(optarg, &req.message);
949             break;
950
951         case 'r': //credit
952             req.credit = ParseCredit(optarg);
953             break;
954
955         case 'E': //credit expire
956             req.creditExpire = ParseCreditExpire(optarg);
957             break;
958
959         case 'd': //down
960             req.down = ParseDownPassive(optarg);
961             break;
962
963         case 'i': //passive
964             req.passive = ParseDownPassive(optarg);
965             break;
966
967         case 't': //tariff
968             req.tariff = ParseTariff(optarg, req.chgTariff);
969             break;
970
971         case 'm': //message
972             ParseAnyString(optarg, &str);
973             req.usrMsg = str;
974             isMessage = true;
975             break;
976
977         case 'e': //Prepaid Traffic
978             req.prepaidTraff = ParsePrepaidTraffic(optarg);
979             break;
980
981         case 'n': //Create User
982             req.createUser = true;
983             break;
984
985         case 'l': //Delete User
986             req.deleteUser = true;
987             break;
988
989         case 'N': //Note
990             ParseAnyString(optarg, &str, "koi8-ru");
991             req.note = str;
992             break;
993
994         case 'A': //nAme
995             ParseAnyString(optarg, &str, "koi8-ru");
996             req.name = str;
997             break;
998
999         case 'D': //aDdress
1000             ParseAnyString(optarg, &str, "koi8-ru");
1001             req.address = str;
1002             break;
1003
1004         case 'L': //emaiL
1005             ParseAnyString(optarg, &str, "koi8-ru");
1006             req.email = str;
1007             //printf("EMAIL=%s\n", optarg);
1008             break;
1009
1010         case 'P': //phone
1011             ParseAnyString(optarg, &str);
1012             req.phone = str;
1013             break;
1014
1015         case 'G': //Group
1016             ParseAnyString(optarg, &str, "koi8-ru");
1017             req.group = str;
1018             break;
1019
1020         case 'I': //IP-address of user
1021             ParseAnyString(optarg, &str);
1022             req.ips = str;
1023             break;
1024
1025         case 'S':
1026             req.disableDetailStat = ParseDownPassive(optarg);
1027             break;
1028
1029         case 'O':
1030             req.alwaysOnline = ParseDownPassive(optarg);
1031             break;
1032
1033         case 500: //U
1034             SetArrayItem(req.sessionUpload, optarg, ParseTraff(argv[optind++]));
1035             //req.sessionUpload[optarg] = ParseTraff(argv[optind++]);
1036             break;
1037         case 501:
1038             SetArrayItem(req.sessionDownload, optarg, ParseTraff(argv[optind++]));
1039             //req.sessionDownload[optarg] = ParseTraff(argv[optind++]);
1040             break;
1041         case 502:
1042             SetArrayItem(req.monthUpload, optarg, ParseTraff(argv[optind++]));
1043             //req.monthUpload[optarg] = ParseTraff(argv[optind++]);
1044             break;
1045         case 503:
1046             SetArrayItem(req.monthDownload, optarg, ParseTraff(argv[optind++]));
1047             //req.monthDownload[optarg] = ParseTraff(argv[optind++]);
1048             break;
1049
1050         case 700: //UserData
1051             ParseAnyString(argv[optind++], &str);
1052             SetArrayItem(req.userData, optarg, str);
1053             //req.userData[optarg] = str;
1054             break;
1055
1056         case '?':
1057             missedOptionArg = true;
1058             break;
1059
1060         case ':':
1061             missedOptionArg = true;
1062             break;
1063
1064         default:
1065             printf("?? getopt returned character code 0%o ??\n", c);
1066         }
1067     }
1068
1069 if (optind < argc)
1070     {
1071     printf ("non-option ARGV-elements: ");
1072     while (optind < argc)
1073         printf ("%s ", argv[optind++]);
1074     UsageConf();
1075     exit(PARAMETER_PARSING_ERR_CODE);
1076     }
1077
1078 if (missedOptionArg || !CheckParametersSet(&req))
1079     {
1080     //printf("Parameter needed\n");
1081     UsageConf();
1082     exit(PARAMETER_PARSING_ERR_CODE);
1083     }
1084
1085 const int rLen = 20000;
1086 char rstr[rLen];
1087 memset(rstr, 0, rLen);
1088
1089 CreateRequestSet(&req, rstr);
1090 if (isMessage)
1091     return ProcessSendMessage(req.server, req.port, req.admLogin, req.admPasswd, rstr);
1092
1093 return ProcessSetUser(req.server, req.port, req.admLogin, req.admPasswd, rstr);
1094 }
1095 //-----------------------------------------------------------------------------
1096 int main(int argc, char **argv)
1097 {
1098 if (argc <= 2)
1099     {
1100     UsageConf();
1101     exit(PARAMETER_PARSING_ERR_CODE);
1102     }
1103
1104 if (strcmp(argv[1], "get") == 0)
1105     {
1106     //printf("get\n");
1107     return mainGet(argc - 1, argv + 1);
1108     }
1109 else if (strcmp(argv[1], "set") == 0)
1110     {
1111     //printf("set\n");
1112     if (mainSet(argc - 1, argv + 1) )
1113         return 0;
1114     return -1;
1115     }
1116 else
1117     {
1118     UsageConf();
1119     exit(PARAMETER_PARSING_ERR_CODE);
1120     }
1121 return UNKNOWN_ERR_CODE;
1122 }
1123 //-----------------------------------------------------------------------------
1124