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.
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.
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
18 * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
24 $Date: 2010/03/25 14:37:43 $
28 #include "common_sg.h"
29 #include "sg_error_codes.h"
31 #include "stg/user_conf.h"
32 #include "stg/user_stat.h"
33 #include "stg/common.h"
54 typedef typename T::value_type type;
58 struct ARRAY_TYPE<T[]>
63 template <typename T, size_t N>
64 struct ARRAY_TYPE<T[N]>
70 bool SetArrayItem(T & array, const char * index, const typename ARRAY_TYPE<T>::type & value)
73 if (str2x(index, pos))
79 } // namespace anonymous
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
104 {"user-data", 1, 0, 700}, //UserData0
106 {"prepaid", 0, 0, 'e'}, //prepaid traff
107 {"create", 0, 0, 'n'}, //create
108 {"delete", 0, 0, 'l'}, //delete
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
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
142 {"user-data", 1, 0, 700}, //UserData
144 {"prepaid", 1, 0, 'e'}, //prepaid traff
145 {"create", 1, 0, 'n'}, //create
146 {"delete", 1, 0, 'l'}, //delete
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
158 //-----------------------------------------------------------------------------
159 CASH_INFO ParseCash(const char * str)
161 //-c 123.45:log message
162 std::string cashString;
164 const char * pos = strchr(str, ':');
167 cashString.append(str, pos);
168 message.append(pos + 1);
174 if (strtodouble2(cashString, cash) != 0)
176 printf("Incorrect cash value %s\n", str);
177 exit(PARAMETER_PARSING_ERR_CODE);
180 return CASH_INFO(cash, message);
182 //-----------------------------------------------------------------------------
183 double ParseCredit(const char * c)
186 if (strtodouble2(c, credit) != 0)
188 printf("Incorrect credit value %s\n", c);
189 exit(PARAMETER_PARSING_ERR_CODE);
194 //-----------------------------------------------------------------------------
195 double ParsePrepaidTraffic(const char * c)
198 if (strtodouble2(c, credit) != 0)
200 printf("Incorrect prepaid traffic value %s\n", c);
201 exit(PARAMETER_PARSING_ERR_CODE);
206 //-----------------------------------------------------------------------------
207 int64_t ParseTraff(const char * c)
210 if (str2x(c, traff) != 0)
212 printf("Incorrect credit value %s\n", c);
213 exit(PARAMETER_PARSING_ERR_CODE);
218 //-----------------------------------------------------------------------------
219 bool ParseDownPassive(const char * dp)
221 if (!(dp[1] == 0 && (dp[0] == '1' || dp[0] == '0')))
223 printf("Incorrect value %s\n", dp);
224 exit(PARAMETER_PARSING_ERR_CODE);
229 //-----------------------------------------------------------------------------
230 void ParseTariff(const char * str, RESETABLE<std::string> & tariffName, RESETABLE<std::string> & nextTariff)
232 const char * pos = strchr(str, ':');
235 std::string tariff(str, pos);
236 if (strcmp(pos + 1, "now") == 0)
238 else if (strcmp(pos + 1, "delayed") == 0)
242 printf("Incorrect tariff value '%s'. Should be '<tariff>', '<tariff>:now' or '<tariff>:delayed'.\n", str);
243 exit(PARAMETER_PARSING_ERR_CODE);
249 //-----------------------------------------------------------------------------
250 time_t ParseCreditExpire(const char * str)
252 struct tm brokenTime;
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;
261 stg_strptime(str, "%Y-%m-%d", &brokenTime);
263 return stg_timegm(&brokenTime);
265 //-----------------------------------------------------------------------------
266 void ParseAnyString(const char * c, string * msg, const char * enc)
269 char * ob = new char[strlen(c) + 1];
270 char * ib = new char[strlen(c) + 1];
277 setlocale(LC_ALL, "");
280 strncpy(charsetF, nl_langinfo(CODESET), 255);
282 const char * charsetT = enc;
286 size_t insize = strlen(ib);
287 size_t outsize = strlen(ib);
291 cd = iconv_open(charsetT, charsetF);
292 if (cd == (iconv_t) -1)
296 printf("Warning: iconv from %s to %s failed\n", charsetF, charsetT);
301 printf("error iconv_open\n");
303 exit(ICONV_ERR_CODE);
306 #if defined(FREE_BSD) || defined(FREE_BSD5)
307 nconv = iconv (cd, (const char**)&inbuf, &insize, &outbuf, &outsize);
309 nconv = iconv (cd, &inbuf, &insize, &outbuf, &outsize);
311 //printf("nconv=%d outsize=%d\n", nconv, outsize);
312 if (nconv == (size_t) -1)
316 printf("iconv error\n");
317 exit(ICONV_ERR_CODE);
329 //-----------------------------------------------------------------------------
330 void CreateRequestSet(REQUEST * req, char * r)
332 const int strLen = 10024;
334 memset(str, 0, strLen);
338 if (!req->usrMsg.empty())
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);
350 sprintf(str, "<DelUser login=\"%s\"/>", req->login.const_data().c_str());
358 sprintf(str, "<AddUser> <login value=\"%s\"/> </AddUser>", req->login.const_data().c_str());
364 strcat(r, "<SetUser>\n");
365 sprintf(str, "<login value=\"%s\"/>\n", req->login.const_data().c_str());
367 if (!req->credit.empty())
369 sprintf(str, "<credit value=\"%f\"/>\n", req->credit.const_data());
373 if (!req->creditExpire.empty())
375 sprintf(str, "<creditExpire value=\"%ld\"/>\n", req->creditExpire.const_data());
379 if (!req->prepaidTraff.empty())
381 sprintf(str, "<FreeMb value=\"%f\"/>\n", req->prepaidTraff.const_data());
385 if (!req->cash.empty())
388 Encode12str(msg, req->message);
389 sprintf(str, "<cash add=\"%f\" msg=\"%s\"/>\n", req->cash.const_data(), msg.c_str());
393 if (!req->setCash.empty())
396 Encode12str(msg, req->message);
397 sprintf(str, "<cash set=\"%f\" msg=\"%s\"/>\n", req->setCash.const_data(), msg.c_str());
401 if (!req->usrPasswd.empty())
403 sprintf(str, "<password value=\"%s\" />\n", req->usrPasswd.const_data().c_str());
407 if (!req->down.empty())
409 sprintf(str, "<down value=\"%d\" />\n", req->down.const_data());
413 if (!req->passive.empty())
415 sprintf(str, "<passive value=\"%d\" />\n", req->passive.const_data());
419 if (!req->disableDetailStat.empty())
421 sprintf(str, "<disableDetailStat value=\"%d\" />\n", req->disableDetailStat.const_data());
425 if (!req->alwaysOnline.empty())
427 sprintf(str, "<aonline value=\"%d\" />\n", req->alwaysOnline.const_data());
431 // IP-address of user
432 if (!req->ips.empty())
434 sprintf(str, "<ip value=\"%s\" />\n", req->ips.const_data().c_str());
438 int uPresent = false;
439 int dPresent = false;
440 for (int i = 0; i < DIR_NUM; i++)
442 if (!req->monthUpload[i].empty())
444 if (!uPresent && !dPresent)
446 sprintf(str, "<traff ");
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());
457 if (!req->monthDownload[i].empty())
459 if (!uPresent && !dPresent)
461 sprintf(str, "<traff ");
467 ss << req->monthDownload[i].const_data();
468 sprintf(str, "MD%d=\"%s\" ", i, ss.str().c_str());
471 if (!req->sessionUpload[i].empty())
473 if (!uPresent && !dPresent)
475 sprintf(str, "<traff ");
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());
486 if (!req->sessionDownload[i].empty())
488 if (!uPresent && !dPresent)
490 sprintf(str, "<traff ");
496 ss << req->sessionDownload[i].const_data();
497 sprintf(str, "MD%d=\"%s\" ", i, ss.str().c_str());
501 if (uPresent || dPresent)
508 if (!req->tariff.empty())
510 switch (req->chgTariff)
513 sprintf(str, "<tariff now=\"%s\"/>\n", req->tariff.const_data().c_str());
517 sprintf(str, "<tariff recalc=\"%s\"/>\n", req->tariff.const_data().c_str());
521 sprintf(str, "<tariff delayed=\"%s\"/>\n", req->tariff.const_data().c_str());
528 if (!req->note.empty())
531 Encode12str(note, req->note.data());
532 sprintf(str, "<note value=\"%s\"/>", note.c_str());
536 if (!req->name.empty())
539 Encode12str(name, req->name.data());
540 sprintf(str, "<name value=\"%s\"/>", name.c_str());
544 if (!req->address.empty())
547 Encode12str(address, req->address.data());
548 sprintf(str, "<address value=\"%s\"/>", address.c_str());
552 if (!req->email.empty())
555 Encode12str(email, req->email.data());
556 sprintf(str, "<email value=\"%s\"/>", email.c_str());
560 if (!req->phone.empty())
563 Encode12str(phone, req->phone.data());
564 sprintf(str, "<phone value=\"%s\"/>", phone.c_str());
568 if (!req->group.empty())
571 Encode12str(group, req->group.data());
572 sprintf(str, "<group value=\"%s\"/>", group.c_str());
576 for (int i = 0; i < USERDATA_NUM; i++)
578 if (!req->userData[i].empty())
581 Encode12str(ud, req->userData[i].data());
582 sprintf(str, "<userdata%d value=\"%s\"/>", i, ud.c_str());
587 strcat(r, "</SetUser>\n");
589 //-----------------------------------------------------------------------------
590 int CheckParameters(REQUEST * req)
597 bool a = !req->admLogin.empty()
598 && !req->admPasswd.empty()
599 && !req->server.empty()
600 && !req->port.empty()
601 && !req->login.empty();
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()
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
623 for (int i = 0; i < DIR_NUM; i++)
625 if (req->sessionUpload[i].empty())
632 for (int i = 0; i < DIR_NUM; i++)
634 if (req->sessionDownload[i].empty())
641 for (int i = 0; i < DIR_NUM; i++)
643 if (req->monthUpload[i].empty())
650 for (int i = 0; i < DIR_NUM; i++)
652 if (req->monthDownload[i].empty())
659 for (int i = 0; i < DIR_NUM; i++)
661 if (req->userData[i].empty())
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);
672 //-----------------------------------------------------------------------------
673 int CheckParametersGet(REQUEST * req)
675 return CheckParameters(req);
677 //-----------------------------------------------------------------------------
678 int CheckParametersSet(REQUEST * req)
680 return CheckParameters(req);
682 //-----------------------------------------------------------------------------
683 bool mainGet(int argc, char **argv)
687 RESETABLE<string> t1;
688 int missedOptionArg = false;
690 const char * short_options_get = "s:p:a:w:u:crtmodieNADLPGISOE";
691 int option_index = -1;
696 c = getopt_long(argc, argv, short_options_get, long_options_get, &option_index);
707 req.port = ParseServerPort(optarg);
712 req.admLogin = ParseAdminLogin(optarg);
715 case 'w': //admin password
716 req.admPasswd = ParsePassword(optarg);
719 case 'o': //change user password
724 req.login = ParseUser(optarg);
735 case 'E': //credit expire
736 req.creditExpire = 1;
751 case 'e': //Prepaid Traffic
752 req.prepaidTraff = 1;
779 case 'I': //IP-address of user
783 case 'S': //Detail stat status
784 req.disableDetailStat = " ";
787 case 'O': //Always online status
788 req.alwaysOnline = " ";
792 SetArrayItem(req.sessionUpload, optarg, 1);
793 //req.sessionUpload[optarg] = 1;
796 SetArrayItem(req.sessionDownload, optarg, 1);
797 //req.sessionDownload[optarg] = 1;
800 SetArrayItem(req.monthUpload, optarg, 1);
801 //req.monthUpload[optarg] = 1;
804 SetArrayItem(req.monthDownload, optarg, 1);
805 //req.monthDownload[optarg] = 1;
809 SetArrayItem(req.userData, optarg, std::string(" "));
810 //req.userData[optarg] = " ";
819 missedOptionArg = true;
823 printf ("?? getopt returned character code 0%o ??\n", c);
829 printf ("non-option ARGV-elements: ");
830 while (optind < argc)
831 printf ("%s ", argv[optind++]);
833 exit(PARAMETER_PARSING_ERR_CODE);
836 if (missedOptionArg || !CheckParametersGet(&req))
838 //printf("Parameter needed\n");
840 exit(PARAMETER_PARSING_ERR_CODE);
844 return ProcessAuthBy(req.server.data(), req.port.data(), req.admLogin.data(), req.admPasswd.data(), req.login.data());
846 return ProcessGetUser(req.server.data(), req.port.data(), req.admLogin.data(), req.admPasswd.data(), req.login.data(), req);
848 //-----------------------------------------------------------------------------
849 bool mainSet(int argc, char **argv)
854 bool isMessage = false;
857 RESETABLE<string> t1;
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:";
861 int missedOptionArg = false;
867 int option_index = -1;
869 c = getopt_long(argc, argv, short_options_set, long_options_set, &option_index);
881 req.port = ParseServerPort(optarg);
886 req.admLogin = ParseAdminLogin(optarg);
889 case 'w': //admin password
890 req.admPasswd = ParsePassword(optarg);
893 case 'o': //change user password
894 conf.password = ParsePassword(optarg);
898 req.login = ParseUser(optarg);
902 stat.cashAdd = ParseCash(optarg);
906 stat.cashSet = ParseCash(optarg);
910 conf.credit = ParseCredit(optarg);
913 case 'E': //credit expire
914 conf.creditExpire = ParseCreditExpire(optarg);
918 conf.disabled = ParseDownPassive(optarg);
922 conf.passive = ParseDownPassive(optarg);
926 ParseTariff(optarg, conf.tariffName, conf.nextTariff);
930 ParseAnyString(optarg, &str);
935 case 'e': //Prepaid Traffic
936 stat.freeMb = ParsePrepaidTraffic(optarg);
939 case 'n': //Create User
940 req.createUser = true;
943 case 'l': //Delete User
944 req.deleteUser = true;
948 ParseAnyString(optarg, &str, "koi8-ru");
953 ParseAnyString(optarg, &str, "koi8-ru");
958 ParseAnyString(optarg, &str, "koi8-ru");
963 ParseAnyString(optarg, &str, "koi8-ru");
968 ParseAnyString(optarg, &str);
973 ParseAnyString(optarg, &str, "koi8-ru");
977 case 'I': //IP-address of user
978 ParseAnyString(optarg, &str);
979 conf.ips = StrToIPS(str);
983 conf.disabledDetailStat = ParseDownPassive(optarg);
987 conf.alwaysOnline = ParseDownPassive(optarg);
991 SetArrayItem(stat.sessionUp, optarg, ParseTraff(argv[optind++]));
994 SetArrayItem(stat.sessionDown, optarg, ParseTraff(argv[optind++]));
997 SetArrayItem(stat.monthUp, optarg, ParseTraff(argv[optind++]));
1000 SetArrayItem(stat.monthDown, optarg, ParseTraff(argv[optind++]));
1003 case 700: //UserData
1004 ParseAnyString(argv[optind++], &str);
1005 SetArrayItem(conf.userdata, optarg, str);
1009 missedOptionArg = true;
1013 missedOptionArg = true;
1017 printf("?? getopt returned character code 0%o ??\n", c);
1023 printf ("non-option ARGV-elements: ");
1024 while (optind < argc)
1025 printf ("%s ", argv[optind++]);
1027 exit(PARAMETER_PARSING_ERR_CODE);
1030 if (missedOptionArg || !CheckParametersSet(&req))
1032 //printf("Parameter needed\n");
1034 exit(PARAMETER_PARSING_ERR_CODE);
1037 const int rLen = 20000;
1039 memset(rstr, 0, rLen);
1042 return ProcessSendMessage(req.server.data(), req.port.data(), req.admLogin.data(), req.admPasswd.data(), req.login.data(), req.usrMsg.data());
1044 return ProcessSetUser(req.server.data(), req.port.data(), req.admLogin.data(), req.admPasswd.data(), req.login.data(), conf, stat);
1046 //-----------------------------------------------------------------------------
1047 int main(int argc, char **argv)
1052 exit(PARAMETER_PARSING_ERR_CODE);
1055 if (strcmp(argv[1], "get") == 0)
1058 return mainGet(argc - 1, argv + 1);
1060 else if (strcmp(argv[1], "set") == 0)
1063 if (mainSet(argc - 1, argv + 1) )
1070 exit(PARAMETER_PARSING_ERR_CODE);
1072 return UNKNOWN_ERR_CODE;
1074 //-----------------------------------------------------------------------------