group(),
credit(),
nextTariff(),
- userdata(USERDATA_NUM, RESETABLE<std::string>()),
+ userdata(USERDATA_NUM),
creditExpire(),
ips()
{
group = uc.group;
credit = uc.credit;
nextTariff = uc.nextTariff;
- for (int i = 0; i < USERDATA_NUM; i++)
- {
- userdata[i] = uc.userdata[i];
- }
+ for (size_t i = 0; i < USERDATA_NUM; i++) userdata[i] = uc.userdata[i];
creditExpire = uc.creditExpire;
ips = uc.ips;
return *this;
#include <ctime>
#include <map>
+#include <utility>
+#include <string>
#include "os_int.h"
#include "resetable.h"
//-----------------------------------------------------------------------------
typedef std::map<IP_DIR_PAIR, STAT_NODE> TRAFF_STAT;
//-----------------------------------------------------------------------------
+typedef std::pair<double, std::string> CASH_INFO;
+//-----------------------------------------------------------------------------
struct USER_STAT_RES
{
USER_STAT_RES()
}
RESETABLE<double> cash;
+ RESETABLE<CASH_INFO> cashAdd;
+ RESETABLE<CASH_INFO> cashSet;
RESETABLE<double> freeMb;
RESETABLE<double> lastCashAdd;
RESETABLE<time_t> lastCashAddTime;
class DIR_TRAFF_RES
{
public:
+ typedef RESETABLE<uint64_t> value_type;
typedef RESETABLE<uint64_t> ValueType;
typedef std::vector<ValueType> ContainerType;
typedef ContainerType::size_type IndexType;
}
const ValueType & operator[](IndexType idx) const { return traff[idx]; }
ValueType & operator[](IndexType idx) { return traff[idx]; }
+ IndexType size() const { return traff.size(); }
DIR_TRAFF GetData() const
{
DIR_TRAFF res;
int port,
const std::string & login,
const std::string & password,
- const std::string & str)
+ const std::string & user,
+ const USER_CONF_RES & conf,
+ const USER_STAT_RES & stat)
{
SERVCONF sc(server, port, login, password);
ResultData data;
-int res = sc.ChgUser(str.c_str(), ResultCallback, &data);
+int res = sc.ChgUser(user, conf, stat, ResultCallback, &data);
if (res == st_ok && data.result)
{
#include <string>
+struct USER_CONF_RES;
+struct USER_STAT_RES;
+
void UsageConf();
void UsageInfo();
int port,
const std::string & admLogin,
const std::string & admPasswd,
- const std::string & str);
+ const std::string & user,
+ const USER_CONF_RES & conf,
+ const USER_STAT_RES & stat);
bool ProcessSendMessage(const std::string & server, uint16_t port,
const std::string & login, const std::string & password,
$Date: 2010/03/25 14:37:43 $
*/
-#include <unistd.h>
-#include <getopt.h>
-#include <iconv.h>
-#include <langinfo.h>
+#include "request.h"
+#include "common_sg.h"
+#include "sg_error_codes.h"
+
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+#include "stg/common.h"
#include <cerrno>
#include <clocale>
#include <string>
#include <sstream>
-#include "stg/common.h"
-#include "request.h"
-#include "common_sg.h"
-#include "sg_error_codes.h"
+#include <unistd.h>
+#include <getopt.h>
+#include <iconv.h>
+#include <langinfo.h>
namespace
{
template <typename T>
-struct ARRAY_TYPE;
+struct ARRAY_TYPE
+{
+typedef typename T::value_type type;
+};
template <typename T>
struct ARRAY_TYPE<T[]>
{0, 0, 0, 0}};
//-----------------------------------------------------------------------------
-double ParseCash(const char * c, string * message)
+CASH_INFO ParseCash(const char * str)
{
//-c 123.45:log message
-double cash;
-char * msg;
-char * str;
-str = new char[strlen(c) + 1];
-
-strncpy(str, c, strlen(c));
-str[strlen(c)] = 0;
-
-msg = strchr(str, ':');
-
-if (msg)
+std::string cashString;
+std::string message;
+const char * pos = strchr(str, ':');
+if (pos != NULL)
{
- *message = msg + 1;
- str[msg - str] = 0;
+ cashString.append(str, pos);
+ message.append(pos + 1);
}
else
- *message = "";
+ cashString = str;
-if (strtodouble2(str, cash) != 0)
+double cash = 0;
+if (strtodouble2(cashString, cash) != 0)
{
- printf("Incorrect cash value %s\n", c);
+ printf("Incorrect cash value %s\n", str);
exit(PARAMETER_PARSING_ERR_CODE);
}
-delete[] str;
-return cash;
+return CASH_INFO(cash, message);
}
//-----------------------------------------------------------------------------
double ParseCredit(const char * c)
return dp[0] - '0';
}
//-----------------------------------------------------------------------------
-string ParseTariff(const char * t, int &chgType)
+void ParseTariff(const char * str, RESETABLE<std::string> & tariffName, RESETABLE<std::string> & nextTariff)
{
-int l = strlen(t);
-char * s;
-s = new char[l];
-char * s1, * s2;
-string ss;
-
-strcpy(s, t);
-
-s1 = strtok(s, ":");
-
-if (strlen(s1) >= TARIFF_NAME_LEN)
+const char * pos = strchr(str, ':');
+if (pos != NULL)
{
- printf("Tariff name too big %s\n", s1);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-//*tariff = s;
-
-if (CheckLogin(s1))
- {
- printf("Incorrect tariff value %s\n", t);
- exit(PARAMETER_PARSING_ERR_CODE);
- }
-
-s2 = strtok(NULL, ":");
-
-chgType = -1;
-
-if (s2 == NULL)
- {
- chgType = TARIFF_NOW;
- ss = s;
- delete[] s;
- return ss;
- }
-
-
-if (strcmp(s2, "now") == 0)
- chgType = TARIFF_NOW;
-
-if (strcmp(s2, "delayed") == 0)
- chgType = TARIFF_DEL;
-
-if (strcmp(s2, "recalc") == 0)
- chgType = TARIFF_REC;
-
-if (chgType < 0)
- {
- printf("Incorrect tariff value %s\n", t);
- exit(PARAMETER_PARSING_ERR_CODE);
+ std::string tariff(str, pos);
+ if (strcmp(pos + 1, "now") == 0)
+ tariffName = tariff;
+ else if (strcmp(pos + 1, "delayed") == 0)
+ nextTariff = tariff;
+ else
+ {
+ printf("Incorrect tariff value '%s'. Should be '<tariff>', '<tariff>:now' or '<tariff>:delayed'.\n", str);
+ exit(PARAMETER_PARSING_ERR_CODE);
+ }
}
-
-ss = s;
-delete[] s;
-return ss;
+else
+ tariffName = str;
}
//-----------------------------------------------------------------------------
time_t ParseCreditExpire(const char * str)
int missedOptionArg = false;
+USER_CONF_RES conf;
+USER_STAT_RES stat;
while (1)
{
int option_index = -1;
break;
case 'o': //change user password
- req.usrPasswd = ParsePassword(optarg);
+ conf.password = ParsePassword(optarg);
break;
case 'u': //user
break;
case 'c': //add cash
- req.cash = ParseCash(optarg, &req.message);
+ stat.cashAdd = ParseCash(optarg);
break;
case 'v': //set cash
- req.setCash = ParseCash(optarg, &req.message);
+ stat.cashSet = ParseCash(optarg);
break;
case 'r': //credit
- req.credit = ParseCredit(optarg);
+ conf.credit = ParseCredit(optarg);
break;
case 'E': //credit expire
- req.creditExpire = ParseCreditExpire(optarg);
+ conf.creditExpire = ParseCreditExpire(optarg);
break;
case 'd': //down
- req.down = ParseDownPassive(optarg);
+ conf.disabled = ParseDownPassive(optarg);
break;
case 'i': //passive
- req.passive = ParseDownPassive(optarg);
+ conf.passive = ParseDownPassive(optarg);
break;
case 't': //tariff
- req.tariff = ParseTariff(optarg, req.chgTariff);
+ ParseTariff(optarg, conf.tariffName, conf.nextTariff);
break;
case 'm': //message
break;
case 'e': //Prepaid Traffic
- req.prepaidTraff = ParsePrepaidTraffic(optarg);
+ stat.freeMb = ParsePrepaidTraffic(optarg);
break;
case 'n': //Create User
case 'N': //Note
ParseAnyString(optarg, &str, "koi8-ru");
- req.note = str;
+ conf.note = str;
break;
case 'A': //nAme
ParseAnyString(optarg, &str, "koi8-ru");
- req.name = str;
+ conf.realName = str;
break;
case 'D': //aDdress
ParseAnyString(optarg, &str, "koi8-ru");
- req.address = str;
+ conf.address = str;
break;
case 'L': //emaiL
ParseAnyString(optarg, &str, "koi8-ru");
- req.email = str;
- //printf("EMAIL=%s\n", optarg);
+ conf.email = str;
break;
case 'P': //phone
ParseAnyString(optarg, &str);
- req.phone = str;
+ conf.phone = str;
break;
case 'G': //Group
ParseAnyString(optarg, &str, "koi8-ru");
- req.group = str;
+ conf.group = str;
break;
case 'I': //IP-address of user
ParseAnyString(optarg, &str);
- req.ips = str;
+ conf.ips = StrToIPS(str);
break;
case 'S':
- req.disableDetailStat = ParseDownPassive(optarg);
+ conf.disabledDetailStat = ParseDownPassive(optarg);
break;
case 'O':
- req.alwaysOnline = ParseDownPassive(optarg);
+ conf.alwaysOnline = ParseDownPassive(optarg);
break;
case 500: //U
- SetArrayItem(req.sessionUpload, optarg, ParseTraff(argv[optind++]));
- //req.sessionUpload[optarg] = ParseTraff(argv[optind++]);
+ SetArrayItem(stat.sessionUp, optarg, ParseTraff(argv[optind++]));
break;
case 501:
- SetArrayItem(req.sessionDownload, optarg, ParseTraff(argv[optind++]));
- //req.sessionDownload[optarg] = ParseTraff(argv[optind++]);
+ SetArrayItem(stat.sessionDown, optarg, ParseTraff(argv[optind++]));
break;
case 502:
- SetArrayItem(req.monthUpload, optarg, ParseTraff(argv[optind++]));
- //req.monthUpload[optarg] = ParseTraff(argv[optind++]);
+ SetArrayItem(stat.monthUp, optarg, ParseTraff(argv[optind++]));
break;
case 503:
- SetArrayItem(req.monthDownload, optarg, ParseTraff(argv[optind++]));
- //req.monthDownload[optarg] = ParseTraff(argv[optind++]);
+ SetArrayItem(stat.monthDown, optarg, ParseTraff(argv[optind++]));
break;
case 700: //UserData
ParseAnyString(argv[optind++], &str);
- SetArrayItem(req.userData, optarg, str);
- //req.userData[optarg] = str;
+ SetArrayItem(conf.userdata, optarg, str);
break;
case '?':
char rstr[rLen];
memset(rstr, 0, rLen);
-CreateRequestSet(&req, rstr);
if (isMessage)
return ProcessSendMessage(req.server.data(), req.port.data(), req.admLogin.data(), req.admPasswd.data(), req.login.data(), req.usrMsg.data());
-return ProcessSetUser(req.server.data(), req.port.data(), req.admLogin.data(), req.admPasswd.data(), rstr);
+return ProcessSetUser(req.server.data(), req.port.data(), req.admLogin.data(), req.admPasswd.data(), req.login.data(), conf, stat);
}
//-----------------------------------------------------------------------------
int main(int argc, char **argv)
const char * LogDate(time_t t);
int ParesTimeStat(const char * str);
int IsTimeStat(struct tm * t, int statTime);
-/*bool IsDigit(char c);
-bool IsAlpha(char c);*/
-int strtodouble2(const char * s, double &a);
+int strtodouble2(const char * str, double & value);
+inline int strtodouble2(const std::string & str, double & value) { return strtodouble2(str.c_str(), value); }
int printfd(const char * __file__, const char * fmt, ...);
void Encode12(char * dst, const char * src, size_t srcLen);
void Decode21(char * dst, const char * src);
int DaysInMonth(unsigned year, unsigned mon);
int DaysInCurrentMonth();
int Min8(int a);
-//char * inet_ntostr(unsigned long);
std::string inet_ntostring(uint32_t);
uint32_t inet_strington(const std::string & value);
int strprintf(std::string * str, const char * fmt, ...);
#include <string>
+struct USER_CONF_RES;
+struct USER_STAT_RES;
+
namespace STG
{
int GetAdmins(GET_ADMINS::CALLBACK f, void * data);
int GetAdmin(const std::string & login, GET_ADMIN::CALLBACK f, void * data);
int ChgAdmin(const ADMIN_CONF_RES & conf, SIMPLE::CALLBACK f, void * data);
- int AddAdmin(const std::string & login, const ADMIN_CONF & conf, SIMPLE::CALLBACK f, void * data);
+ int AddAdmin(const std::string & login,
+ const ADMIN_CONF_RES & conf,
+ SIMPLE::CALLBACK f, void * data);
int DelAdmin(const std::string & login, SIMPLE::CALLBACK f, void * data);
int GetUsers(GET_USERS::CALLBACK f, void * data);
int GetUser(const std::string & login, GET_USER::CALLBACK f, void * data);
- int ChgUser(const std::string & request, SIMPLE::CALLBACK f, void * data);
+ int ChgUser(const std::string & login,
+ const USER_CONF_RES & conf,
+ const USER_STAT_RES & stat,
+ SIMPLE::CALLBACK f, void * data);
int DelUser(const std::string & login, SIMPLE::CALLBACK f, void * data);
int AddUser(const std::string & login, SIMPLE::CALLBACK f, void * data);
int AuthBy(const std::string & login, AUTH_BY::CALLBACK f, void * data);
if (!conf.password.empty())
params += " password=\"" + conf.password.data() + "\"";
if (!conf.priv.empty())
- params += " priv=\"" + x2str(conf.priv.data().ToInt()) + "\"";
+ params += " priv=\"" + unsigned2str(conf.priv.data().ToInt()) + "\"";
return params;
}
#include "chg_user.h"
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+
+#include <sstream>
+
#include <strings.h>
using namespace STG;
+namespace
+{
+
+template <typename T>
+void appendResetable(std::ostream & stream, const std::string & name, const T & value)
+{
+if (!value.empty())
+ stream << "<" << name << " value=\"" << value.data() << "\"/>";
+}
+
+template <typename T>
+void appendResetable(std::ostream & stream, const std::string & name, size_t suffix, const T & value)
+{
+if (!value.empty())
+ stream << "<" << name << suffix << " value=\"" << value.data() << "\"/>";
+}
+
+} // namespace anonymous
+
CHG_USER::PARSER::PARSER(SIMPLE::CALLBACK f, void * d)
: callback(f),
data(d),
else
callback(false, "Invalid response.", data);
}
+
+std::string CHG_USER::Serialize(const USER_CONF_RES & conf, const USER_STAT_RES & stat)
+{
+std::ostringstream stream;
+
+// Conf
+
+appendResetable(stream, "credit", conf.credit);
+appendResetable(stream, "creditExpire", conf.creditExpire);
+appendResetable(stream, "password", conf.password);
+appendResetable(stream, "down", conf.disabled); // TODO: down -> disabled
+appendResetable(stream, "passive", conf.passive);
+appendResetable(stream, "disableDetailStat", conf.disabledDetailStat); // TODO: disable -> disabled
+appendResetable(stream, "aonline", conf.alwaysOnline); // TODO: aonline -> alwaysOnline
+appendResetable(stream, "ip", conf.ips); // TODO: ip -> ips
+
+if (!conf.nextTariff.empty())
+ stream << "<tariff delayed=\"" << conf.nextTariff.data() << "\"/>";
+else if (!conf.tariffName.empty())
+ stream << "<tariff now=\"" << conf.nextTariff.data() << "\"/>";
+
+appendResetable(stream, "note", conf.note);
+appendResetable(stream, "name", conf.realName); // TODO: name -> realName
+appendResetable(stream, "address", conf.address);
+appendResetable(stream, "email", conf.email);
+appendResetable(stream, "phone", conf.phone);
+appendResetable(stream, "group", conf.group);
+
+for (size_t i = 0; i < conf.userdata.size(); ++i)
+ appendResetable(stream, "userdata", i, conf.userdata[i]);
+
+// Stat
+
+if (!stat.cashAdd.empty())
+ stream << "<cash add=\"" << stat.cashAdd.data().first << "\" msg=\"" << stat.cashAdd.data().second << "\"/>";
+else if (!stat.cashSet.empty())
+ stream << "<cash set=\"" << stat.cashAdd.data().first << "\" msg=\"" << stat.cashAdd.data().second << "\"/>";
+
+appendResetable(stream, "freeMb", stat.freeMb);
+
+std::ostringstream traff;
+for (size_t i = 0; i < stat.sessionUp.size(); ++i)
+ if (!stat.sessionUp[i].empty())
+ traff << " SU" << i << "=\"" << stat.sessionUp[i].data() << "\"";
+for (size_t i = 0; i < stat.sessionDown.size(); ++i)
+ if (!stat.sessionDown[i].empty())
+ traff << " SD" << i << "=\"" << stat.sessionDown[i].data() << "\"";
+for (size_t i = 0; i < stat.monthUp.size(); ++i)
+ if (!stat.monthUp[i].empty())
+ traff << " MU" << i << "=\"" << stat.monthUp[i].data() << "\"";
+for (size_t i = 0; i < stat.monthDown.size(); ++i)
+ if (!stat.monthDown[i].empty())
+ traff << " MD" << i << "=\"" << stat.monthDown[i].data() << "\"";
+
+std::string traffData = traff.str();
+if (!traffData.empty())
+ stream << "<traff" << traffData << "/>";
+
+return stream.str();
+}
#include "stg/servconf_types.h"
+struct USER_CONF_RES;
+struct USER_STAT_RES;
+
namespace STG
{
namespace CHG_USER
void ParseAnswer(const char * el, const char ** attr);
};
+std::string Serialize(const USER_CONF_RES & conf, const USER_STAT_RES & stat);
+
} // namespace CHG_USER
} // namespace STG
void GET_ADMIN::PARSER::ParseAdmin(const char * el, const char ** attr)
{
if (strcasecmp(el, "admin") == 0)
+ {
if (attr && attr[0] && attr[1])
{
if (strcasecmp(attr[1], "error") == 0)
}
else
parsingAnswer = true;
+ }
}
//-----------------------------------------------------------------------------
void GET_ADMIN::PARSER::ParseAdminParams(const char * el, const char ** attr)
std::map<std::string, long long *> props;
for (size_t i = 0; i < DIR_NUM; ++i)
{
- props.insert(std::pair<std::string, long long *>("su" + x2str(i), &value.su[i]));
- props.insert(std::pair<std::string, long long *>("sd" + x2str(i), &value.sd[i]));
- props.insert(std::pair<std::string, long long *>("mu" + x2str(i), &value.mu[i]));
- props.insert(std::pair<std::string, long long *>("md" + x2str(i), &value.md[i]));
+ props.insert(std::pair<std::string, long long *>("su" + unsigned2str(i), &value.su[i]));
+ props.insert(std::pair<std::string, long long *>("sd" + unsigned2str(i), &value.sd[i]));
+ props.insert(std::pair<std::string, long long *>("mu" + unsigned2str(i), &value.mu[i]));
+ props.insert(std::pair<std::string, long long *>("md" + unsigned2str(i), &value.md[i]));
}
size_t pos = 0;
while (attr[pos])
AddParser(propertyParsers, "traff", info.stat);
for (size_t i = 0; i < USERDATA_NUM; ++i)
- AddParser(propertyParsers, "userData" + x2str(i), info.userData[i], GetEncodedValue);
+ AddParser(propertyParsers, "userData" + unsigned2str(i), info.userData[i], GetEncodedValue);
}
//-----------------------------------------------------------------------------
GET_USER::PARSER::~PARSER()
void GET_USER::PARSER::ParseUser(const char * el, const char ** attr)
{
if (strcasecmp(el, "user") == 0)
+ {
if (attr && attr[0] && attr[1])
{
if (strcasecmp(attr[1], "error") == 0)
}
else
parsingAnswer = true;
+ }
}
//-----------------------------------------------------------------------------
void GET_USER::PARSER::ParseUserParams(const char * el, const char ** attr)
AddParser(propertyParsers, "tariff_num", info.tariffNum);
for (size_t i = 0; i < DIR_NUM; i++)
- AddParser(propertyParsers, "dir_name_" + x2str(i), info.dirName[i], GetEncodedValue);
+ AddParser(propertyParsers, "dir_name_" + unsigned2str(i), info.dirName[i], GetEncodedValue);
}
//-----------------------------------------------------------------------------
int SERVER_INFO::PARSER::ParseStart(const char *el, const char **attr)
{
depth++;
if (depth == 1)
+ {
if (strcasecmp(el, "ServerInfo") == 0)
parsingAnswer = true;
+ }
else
+ {
if (depth == 2 && parsingAnswer)
if (!TryParse(propertyParsers, ToLower(el), attr))
error = "Invalid parameter.";
+ }
return 0;
}
//-----------------------------------------------------------------------------
return pImpl->Exec<SIMPLE::PARSER>("ChgAdmin", "<ChgAdmin" + CHG_ADMIN::Serialize(conf) + "/>", f, data);
}
-int SERVCONF::AddAdmin(const std::string & login, const ADMIN_CONF & conf, SIMPLE::CALLBACK f, void * data)
+int SERVCONF::AddAdmin(const std::string & login,
+ const ADMIN_CONF_RES & conf,
+ SIMPLE::CALLBACK f, void * data)
{
int res = pImpl->Exec<SIMPLE::PARSER>("AddAdmin", "<AddAdmin login=\"" + login + "\"/>", f, data);
if (res != st_ok)
return pImpl->Exec<GET_USER::PARSER>("<GetUser login=\"" + login + "\"/>", f, data);
}
-int SERVCONF::ChgUser(const std::string & request, SIMPLE::CALLBACK f, void * data)
+int SERVCONF::ChgUser(const std::string & login,
+ const USER_CONF_RES & conf,
+ const USER_STAT_RES & stat,
+ SIMPLE::CALLBACK f, void * data)
{
-return pImpl->Exec<CHG_USER::PARSER>(request, f, data);
+return pImpl->Exec<CHG_USER::PARSER>("<SetUser><Login value=\"" + login + "\"/>" + CHG_USER::Serialize(conf, stat) + "</SetUser>", f, data);
}
int SERVCONF::DelUser(const std::string & login, SIMPLE::CALLBACK f, void * data)