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